ORB-SLAM2评估全流程:TUM/KITTI/EuRoC数据集与evo实操指南
在SLAM圈子里最尴尬的场景不是算法跑挂而是算法跑通了你却说不清它到底跑得怎么样。我刚接触ORBSLAM时好不容易把ORB-SLAM2编译通过看着实时建图窗口觉得自己已经入门。但真到汇报实验、或者想跟别人对比算法效果时才发现手头只有一段视频连一条能证明精度的曲线都拿不出来。后来我把TUM、KITTI、EuRoC三套数据集各跑了一遍又花了两天时间研究evo工具才算把“数据集-算法-评估”这条链路走通。在这个领域会跑算法只是第一步会选数据集、会用评估工具给出可信指标才是一个SLAM实验结果能否说服别人的分水岭。这篇文章不打算重复官方README里已经写清楚的内容而是把三套主流数据集的选择逻辑、下载与预处理要点、ORBSLAM适配方式以及evo从安装到生成精度报告的核心用法按我实际操作的顺序串起来。适合刚编译完ORB-SLAM2、准备跑第一次正式实验的读者也适合需要给论文补对比表格的研究生参考。1. ORBSLAM三件套TUM、KITTI、EuRoC各自解决什么问题1.1 为什么不能随便拿一组数据就开跑很多新手容易犯一个错误手里有什么数据就喂什么数据结果SLAM前端跑飞了还以为是代码没编译对。SLAM算法和普通深度学习算法不一样它需要的是连续图像序列 精确传感器参数 位姿真值ground truth三样东西。没有真值你只能看到轨迹形状对不对无法量化误差没有内参ORBSLAM甚至没法初始化。另外ORBSLAM有单目、双目、RGB-D三种主要模式每种模式对数据的要求都不一样。单目只需要一个摄像头图像流但轨迹存在尺度不确定性双目需要左右目时间戳严格同步RGB-D需要彩色图和深度图的像素对齐。如果你拿一个目标检测数据集比如COCO去跑SLAM那完全错位因为单张图片之间没有时间连续性和相机运动关系。所以在SLAM领域大家默认去用几套公开基准数据集。它们的好处是提供了统一的真值格式、统一的评估指标、统一的传感器参数这样不同论文之间的结果才能直接对比。对ORBSLAM来说最常用的就是下面三套TUM RGB-D、KITTI Odometry、EuRoC MAV。1.2 TUM RGB-D单目和RGB-D入门的首选TUM RGB-D数据集由慕尼黑工业大学计算机视觉组发布是RGB-D SLAM领域引用率最高的数据集之一。它用微软Kinect v1相机采集提供640x480的彩色图、深度图以及由运动捕捉系统Vicon或者高精度运动跟踪设备得到的相机轨迹真值。TUM数据集的ground truth格式非常经典直接影响了后来很多SLAM工具的轨迹格式。每个csv/txt文件每一行是这样的timestamp tx ty tz qx qy qz qw也就是时间戳 平移向量xyz 四元数xyzw。注意四元数顺序是x、y、z、w不是w开头这个我后面踩坑部分会专门再说。ORB-SLAM2输出的KeyFrameTrajectory.txt就是这个格式因此TUM数据集可以直接和ORB-SLAM2输出无缝对接。常用的序列包括序列特点适合测试什么freiburg1_desk桌面场景纹理丰富运动速度中等RGB-D/SLAM入门的默认选择freiburg1_room房间场景运动范围大有快速转动跟踪鲁棒性freiburg2_xyz纯平移运动几乎无旋转精度标定和建图质量freiburg3_long_office_household办公室长廊纹理适中长轨迹漂移测试另外TUM数据集还提供了associate.py脚本用来对齐彩色图和深度图的时间戳。这一点对ORB-SLAM2的rgbd_tum示例尤其重要后面我会详细讲。1.3 KITTI Odometry自动驾驶场景下的双目/单目基准KITTI是自动驾驶领域绕不开的数据集由卡尔斯鲁厄理工学院KIT和丰田工业大学芝加哥分校TTIC联合发布。对SLAM来说我们常用的是其中的Odometry基准包含从城市道路、乡村、高速公路采集的双目灰度图像序列分辨率约1241x376频率10Hz。Odometry基准中00~10共11个序列提供了公开的ground truth。真值以3x4变换矩阵形式存储每行12个数代表每一帧左目相机在世界坐标系通常以第一帧为原点的位姿矩阵r11 r12 r13 t1 r21 r22 r23 t2 r31 r32 r33 t3这和TUM的四元数表示形式完全不同但在数学上等价。KITTI的ground truth是用高精度GPS/IMU组合导航系统生成的在开阔道路上精度很高。KITTI更适合测试双目SLAM在真实驾驶场景下的表现因为图像序列长、运动速度快、光照变化明显比TUM的室内桌面场景要苛刻得多。ORB-SLAM2的stereo_kitti示例就是专门为KITTI写的跑通它基本意味着你已经掌握了双目SLAM的基本流程。1.4 EuRoC MAV视觉惯性SLAM的标准测试场EuRoC MAV数据集由苏黎世联邦理工ETH Zurich自治系统实验室发布是无人机视觉惯性SLAM最常用的测试集。它包含双目图像752x48020Hz、IMU数据200Hz和由激光跟踪仪或Vicon系统给出的位姿真值。EuRoC最大的特点是运动剧烈、纹理变化大比如快速旋转、剧烈抖动、飞行器悬停等场景。这对于纯视觉SLAM来说很难但对视觉惯性SLAM来说是绝佳的测试场。ORB-SLAM3的视觉惯性模式主要就是用EuRoC来做评估的。EuRoC的地面真值格式也是8列时间戳 位置xyz 四元数wxyz或xyzw具体见各序列的state_groundtruth_estimate0/data.csv文件。但需要注意它默认表示的是IMU机体坐标系下的轨迹而视觉SLAM输出的通常是相机坐标系下的轨迹评估前需要考虑外参转换。这个细节非常容易踩坑后面我会专门展开。2. 数据集下载与首跑前的格式处理2.1 三套数据集的下载结构这几套数据集官网下载都比较直接但如果你在校园网或者国内网络环境下下载速度不稳定是常有的事。我的建议是优先用官方链接必要时借助学术资源平台或者校内镜像下载后一定对比文件大小或者说校验码避免下到残缺文件。TUM RGB-D数据集某个序列比如freiburg1_desk解压后核心目录结构是这样的rgbd_dataset_freiburg1_desk/ ├── rgb/ ├── depth/ ├── rgb.txt ├── depth.txt ├── groundtruth.txt └── accelerometer.txtKITTI Odometry下载后建议按序列组织目录KITTI/ ├── poses/ │ ├── 00.txt │ ├── 01.txt │ └── ... └── sequences/ ├── 00/ │ ├── image_0/ │ ├── image_1/ │ ├── calib.txt │ └── times.txt ├── 01/ └── ...EuRoC数据集下载后以ASL格式组织MH_01到MH_05和V1、V2系列各为一个包解压后大致结构MH_01_easy/ └── mav0/ ├── cam0/ ├── cam1/ ├── imu0/ └── state_groundtruth_estimate0/每个子目录下都有data.csv和data.csv配套的传感器标定文件。EuRoC的官方下载页面容易因为并发高而超时可以用脚本批量下载断点续传工具在这里很实用。2.2 TUM的时间戳关联脚本TUM数据集的RGB图像和深度图像分别用rgb.txt和depth.txt记录时间戳。ORB-SLAM2的rgbd_tum示例要求传入一个关联文件每一行是“彩色图时间戳 深度图时间戳 彩色图路径 深度图路径”。官方提供了associate.py脚本在数据集根目录执行python associate.py rgb.txt depth.txt associations.txt脚本会基于时间戳最近邻匹配默认容差是0.02秒。如果你想增大容差可以加参数python associate.py --max_difference 0.05 rgb.txt depth.txt associations.txt容差越大匹配到的帧越多但深度图和彩色图内容差异也可能越大可能影响精度。在我实际跑下来0.02秒的默认值在大多数TUM序列上够用如果匹配对数太少再适当放宽。这里有个经验之谈ORB-SLAM2仓库里自带了Examples/RGB-D/associations/目录里面已经有fr1、fr2、fr3常用序列的关联文件。如果你是刚入门直接用现成的关联文件最省事不需要自己重新生成。2.3 KITTI与EuRoC的格式处理KITTI序列没有传统意义上的时间戳文件但提供了times.txt里面记录每帧图像的相对时间。ORB-SLAM2的stereo_kitti示例在运行时会从Examples/Stereo/目录下读取对应序列的时间戳文件比如00.txt每行一个浮点数代表该帧时间。严格来说这只是给帧打了个时间标签并不会影响位姿估计本身但会影响输出轨迹文件的时间列。EuRoC的数据则自带data.csv每一行有表头格式大致为timestamp, p_RS_R_x [m], p_RS_R_y [m], p_RS_R_z [m], q_RS_w [], q_RS_x [], q_RS_y [], q_RS_z []这里四元数又是wxyz顺序和TUM不同。使用evo或者ORB-SLAM3读取时工具会自动解析但你自己写脚本处理时一定要看清表头否则位姿大概率是错的。2.4 ORBSLAM的配置文件适配ORB-SLAM2的Examples目录下按传感器模式分好了配置文件传感器模式配置文件RGB-DTUMExamples/RGB-D/TUM1.yaml、TUM2.yaml、TUM3.yaml双目KITTIExamples/Stereo/KITTI00-02.yaml、KITTI03.yaml等双目EuRoCExamples/Stereo/EuRoC.yaml单目TUMExamples/Monocular/TUM1.yaml、TUM2.yaml、TUM3.yaml这些yaml文件里包含相机内参、畸变系数、ORB特征数量、尺度金字塔参数等。使用对应数据集时直接选对应配置文件一般都能跑但要注意如果你用的是自己标定的相机必须把Camera.fx、Camera.fy、Camera.cx、Camera.cy以及畸变参数替换掉否则ORB-SLAM初始化会非常不稳定甚至一直处于“寻找初始化”状态。还有一个容易被忽略的点KITTI的双目图像是灰度图EuRoC的双目图像也是灰度图但KITTI和EuRoC的基线距离、焦距差异很大所以它们的yaml文件不能互相混用。很多人跑完TUM再跑KITTI不换配置文件结果双目深度估计一直有问题就是这个原因。3. evo为什么能成为轨迹评估事实标准3.1 APE和RPE两个指标管的事不一样在ORBSLAM这类视觉SLAM算法出来后怎么评估一条轨迹的好坏社区里慢慢形成了两个核心指标APE绝对位姿误差和RPE相对位姿误差。APE衡量的是估计轨迹和真值轨迹在全局上的偏差。它对每一对时间戳对齐后的位姿求差计算平移部分的RMSE、均值、中位数等统计量。它直观反映“整条轨迹离真值有多远”是论文里最常放的数字。RPE则衡量局部漂移。它给定一个时间间隔delta比较“经过delta帧后估计轨迹的位姿变化”与“真值轨迹的位姿变化”有多接近。它更关注短时间内的相对运动一致性对局部漂移更敏感。指标全称观察视角典型用途APEAbsolute Pose Error全局一致性对比不同算法整条轨迹的精度RPERelative Pose Error局部平滑性评估前端跟踪的局部漂移在evo里对应两条命令evo_ape和evo_rpe。后面实操部分我给你具体命令。3.2 轨迹对齐直接比较姿态前必须做的数学处理很多人第一次用evo时会困惑为什么我直接用evo_ape跑出来的误差特别大甚至几十米这通常是因为没有做轨迹对齐。ORBSLAM估计的轨迹所在的坐标系和数据集真值轨迹所在的坐标系并不是同一个。哪怕算法再准两个轨迹之间也差了一个刚体变换旋转平移单目还差一个尺度。如果不做对齐直接逐帧比较误差当然大得离谱。evo内部使用Umeyama算法做轨迹对齐常用两种模式对齐方式对应参数适用场景SE(3)对齐-a双目、RGB-D只求旋转平移Sim(3)对齐-a -s单目同时估计尺度因子我的习惯是双目或RGB-D结果只用-a单目结果一定用-a -s这样得出的APE才有参考意义。如果你在论文里看到有人单目跑完不做尺度对齐就报误差那基本可以判断实验设计有问题。3.3 evo安装与常用命令总览evo是德国研究者Michael Grupp开发的开源Python工具安装非常简单pip install evo --upgrade --no-binary evo为什么要加--no-binary evo因为evo的某些绘图依赖在二进制分发上踩过坑源码安装更稳。如果你在安装过程中遇到numpy或者matplotlib版本冲突建议新建一个conda环境用Python 3.8或3.9安装。evo常用的命令有五个evo_traj读取并可视化一条或多条轨迹evo_ape计算绝对位姿误差evo_rpe计算相对位姿误差evo_res比较多个evo生成的评估结果文件zipevo_config修改evo全局配置它支持TUM、KITTI、EuRoC以及ROS bag这几种格式基本覆盖了SLAM领域绝大多数数据集。这也是它成为事实标准的重要原因——你不需要为每个数据集写一套评估脚本。4. 完整实操ORB-SLAM2跑TUM并用evo生成评估结果4.1 先用rgbd_tum把关键帧轨迹导出来我们以TUM的freiburg1_desk序列为例完整走一遍流程。假设你的ORB-SLAM2已经编译成功数据集已经解压到某个目录。运行rgbd_tum示例的命令格式是./Examples/RGB-D/rgbd_tum \ Vocabulary/ORBvoc.txt \ Examples/RGB-D/TUM1.yaml \ /data/datasets/rgbd_dataset_freiburg1_desk \ Examples/RGB-D/associations/fr1_desk.txt程序跑完后会在当前目录生成两个关键文件CameraTrajectory.txt和KeyFrameTrajectory.txt。这里有一个新手常犯的错误默认只对着CameraTrajectory看轨迹动画忽略KeyFrameTrajectory。实际上在做评估时优先用KeyFrameTrajectory.txt。原因是关键帧轨迹经过了局部优化和回环优化更稳定、更接近ORBSLAM的“最优估计”CameraTrajectory包含了每一帧的位姿数量多但噪声也大更适合看实时跟踪质量不太适合做整体精度评估。4.2 evo_ape评估绝对位姿误差进入输出目录把TUM自带的真值轨迹复制或软链过来然后执行evo_ape tum groundtruth.txt KeyFrameTrajectory.txt -a --plot --plot_mode xyz参数说明参数作用tum指定轨迹格式为TUMgroundtruth.txt参考轨迹KeyFrameTrajectory.txt待评估轨迹-a做SE(3)对齐--plot生成误差曲线图--plot_mode xyz按三维坐标模式绘图终端会输出一段统计结果类似这样APE w.r.t. translation part (m) max 0.5432 mean 0.2311 median 0.2011 min 0.0456 rmse 0.2678 sse 45.2345真正写论文时大家一般看RMSE或者Mean。RMSE对异常值比较敏感Mean更稳定建议两个都给出。如果你跟别人的结果做对比一定要确认对方用的统计指标是同一个否则数字没可比性。如果你想保存评估结果用于多组实验对比加一个参数evo_ape tum groundtruth.txt KeyFrameTrajectory.txt -a --save_results fr1_desk_orb2.zip4.3 evo_rpe补一个局部漂移指标只报APE在有些审稿人眼里是不够的还需要RPE。对于TUM这类室内序列默认的相邻帧间隔delta1可以反映跟踪是否平滑evo_rpe tum groundtruth.txt KeyFrameTrajectory.txt -a --plot --plot_mode xyz如果你想观察跨越多帧的漂移比如每10帧的相对误差evo_rpe tum groundtruth.txt KeyFrameTrajectory.txt -a -d 10 --plot这里-d就是delta单位是帧数。当delta增大时RPE衡量的是更长一段时间的相对运动误差能体现系统是否有累积漂移。实际实验里我一般会同时跑-d 1和-d 10两组这样既能看到帧间抖动也能看到长时间漂移。4.4 多组实验对比evo_traj与evo_res如果你用ORB-SLAM2、ORB-SLAM3或者其他算法各跑了一遍同一序列想对比谁的轨迹更准可以用evo_traj先可视化evo_traj tum KeyFrameTrajectory_orb2.txt KeyFrameTrajectory_orb3.txt \ --ref groundtruth.txt -a --plot --plot_mode xz这个命令会一并显示真值、多个估计轨迹并自动对齐一眼就能看出谁的轨迹跟真值更贴合。如果想定量对比就需要把每个算法跑出来的APE结果保存成zip再用evo_res汇总evo_ape tum groundtruth.txt KeyFrameTrajectory_orb2.txt -a --save_results orb2.zip evo_ape tum groundtruth.txt KeyFrameTrajectory_orb3.txt -a --save_results orb3.zip evo_res orb2.zip orb3.zip --plotevo_res会输出一个对比表格列出每条轨迹的RMSE、Mean、Median、Max等指标还会生成误差分布小提琴图。这个功能在润色论文对比表格时非常省力我基本每次实验对比都会用。5. 踩坑实录时间戳、尺度、坐标系的三个大坑5.1 时间戳不对齐评估结果全无意义evo在做评估时首先会做时间戳匹配。如果两个轨迹的时间戳没对齐它会报出类似Found N matches的信息也可能报错Error: no matching timestamps found。最常见的错误来源是TUM数据集使用真实传感器时间戳而ORB-SLAM2输出的关键帧时间戳来自你输入的关联文件。如果你自己写了associate文件但容差设置太大匹配到了时间戳相差很远的深度图导致ORB-SLAM2跟踪的帧序列和ground truth的时间对不上最后评估结果就会非常混乱。另一个常见情况是你跑的是KITTI序列ORB-SLAM2输出的时间戳来自虚拟的00.txt而KITTI真值根本没有时间戳。此时用evo_ape kitti格式评估最稳妥它会按行号一一对应不依赖时间戳匹配。如果你非要把KITTI输出转换成TUM格式再和TUM格式的ground truth对齐反而容易因为时间基准不一致而出错。所以我的建议是数据集是什么格式就用evo对应的格式评估不要盲目转换。5.2 单目尺度SfM的七自由度不确定性单目SLAM估计出来的轨迹在相似变换Sim(3)意义下和真值只差一个尺度因子。也就是说轨迹形状能对但漂移估计出来的位移可能是真值的0.8倍或者1.3倍。如果你用双目或者RGB-D的评估方式直接加-a会发现APE大得离谱。正确做法是单目轨迹一定要加-sevo_ape tum groundtruth.txt KeyFrameTrajectory_mono.txt -a -s --plot加了-s之后evo会估算一个最优尺度并校正轨迹再计算误差。校正后的尺度越接近1说明单目估计的绝对尺度越准。对ORB-SLAM单目来说这个值通常在0.9到1.1之间如果偏差很大说明跟踪或三角化有明显问题。还有一个容易被忽视的点单目ORB-SLAM的全局尺度在回环后可能发生跳变。如果你发现评估结果前后两段轨迹尺度不一致建议把轨迹按回环事件分成多段分别评估排查问题出在哪一段。5.3 坐标系与四元数顺序这是我自己踩过最狠的一个坑。TUM格式的四元数顺序是xyzwEuRoC的data.csv表头里明确写的是qw qx qy qz而很多工具内部默认又是wxyz。如果格式解析错轨迹可能看起来整体形状是对的但姿态误差大得离谱而且完全没规律。再一个坑是坐标系定义。TUM的ground truth记录的是相机位姿ORB-SLAM2输出也是相机位姿可以直接比。但EuRoC的state_groundtruth_estimate0默认是IMU机体位姿如果你跑的是纯视觉ORB-SLAM2输出的是相机位姿两者之间差了一个相机到IMU的外参变换。在evo里直接比平移部分可能勉强能看姿态部分一定对不上。解决方式有两种一是用ORB-SLAM3的视觉惯性模式它会输出IMU坐标系轨迹二是用evo或自己的脚本把相机轨迹通过外参矩阵变换到IMU坐标系后再比较。无论哪种都要注意外参方向别搞反。5.4 还有几个容易忽略的小问题EVO绘图乱码和字体问题。在部分Linux服务器上matplotlib中文字体缺失会导致图例乱码解决办法是设置evo_config set plot_fontfamily serif或者安装中文字体。如果你只是发论文英文标注反而更省事。另外evo的--save_results保存的是zip文件旧版本可能只支持存成zip新版本可以存成目录。如果你要把结果提交给自动化脚本处理注意版本差异。我实际遇到过一次用evo 1.12生成的zip在evo 1.19里读取时警告格式不兼容所以建议团队内部统一evo版本。还有一个小技巧运行evo_config set可以调整默认绘图风格比如evo_config set plot_seaborn_style whitegrid plot_fontfamily serif这样后续所有evo绘图统一走白网格背景和衬线字体论文里插图风格更一致。比每次在命令行加参数省事很多。说实话SLAM的评估工作看起来只是“跑几条命令”但真正决定实验可信度的恰恰是这些细节。数据集选错了指标算出来也没人信对齐没做对数字再好看也是自欺欺人。我自己在整理第一个完整的ORBSLAM对比实验时有将近三分之一的时间花在数据格式和时间戳处理上真正调算法的时间反而没那么长。所以如果你刚开始跑这套流程遇到诡异的大误差先别怀疑算法回头检查一下数据格式、时间戳对齐和坐标系变换多半能发现真正的问题。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →