news 2026/9/15 15:55:31

ORB-SLAM3 Euroc数据集测试实战:编译、运行与精度评估

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ORB-SLAM3 Euroc数据集测试实战:编译、运行与精度评估

第一次把ORB-SLAM3跑在Euroc的MH01序列上,我看着屏幕上不断刷新的地图点和轨迹线,第一反应是“终于跑通了”,第二反应是“这轨迹怎么和真值差了这么多”。后来仔细一查,问题居然出在一个非常不起眼的地方——我给单目模式传的yaml文件里,Camera.fps写的是20,但数据集实际发布频率是20Hz没错,可时间戳文件里第一帧不是从0开始的,导致评估对齐时整体偏移。类似这样的细节,在Euroc数据集的测试过程中比比皆是。

如果你正准备用Euroc数据集检验ORB-SLAM3,或者想复现论文里那几条漂亮的精度曲线,这篇分享能帮你少走不少弯路。我会从数据集选型、编译安装、四种传感器模式的运行命令、评估工具一直聊到那些不写进文档的坑,最后再给几个批量测试的小习惯。内容都以我自己的实际操作经验为准,命令和参数都是实测可跑的。

1. 你测试Euroc前需要先搞懂的三件事

1.1 Euroc数据集到底长什么样

Euroc数据集是苏黎世联邦理工发布的微型无人机MAV数据集,在视觉SLAM圈子里几乎是“标准试卷”。它由一架四旋翼搭载双目相机和IMU采集,场景分为Machine Hall(MH系列)和Vicon Room(V系列)两类。MH序列在机器大厅里运行,纹理丰富、光照稳定,属于入门难度;V系列在动捕房间里,有更多快速旋转和近距离遮挡,难度更高。

数据集的目录结构很固定,每个序列解压后都是这样的:

MH01/ └── mav0/ ├── cam0/ │ ├── data/ │ │ ├── 1403715282262142976.png │ │ └── ... │ └── data.csv ├── cam1/ │ ├── data/ │ └── data.csv ├── imu0/ │ ├── data.csv └── state_groundtruth_estimate0/ └── data.csv

整个路径里最关键的三样东西:cam0/datacam1/data是左右目灰度图,imu0/data.csv是200Hz的IMU测量,state_groundtruth_estimate0/data.csv是动捕系统给的米制真值轨迹,用于评估。ORB-SLAM3的命令行参数几乎就是在告诉你“我需要哪个路径、哪份时间戳、哪份真值”。

很多新手在这里犯的第一个错:把数据集根目录当成了mav0。注意ORB-SLAM3的Euroc示例程序里,传入的dataset_path是指包含mav0的上一级目录,比如~/Datasets/EuRoC/MH01,而后面跟的mav0/cam0/data是相对路径。这个路径搞错,程序会直接崩,后面我会细说。

1.2 和TUM、KITTI对比,Euroc的独特价值

做SLAM测试的人绕不开TUM、KITTI和Euroc这三板斧。TUM RGB-D主要在室内用Kinect采集,偏向单目/RGB-D和手持运动,真值由运动捕捉系统提供,精度高但场景范围小;KITTI是室外车载场景,双目加激光雷达,地面真值来自高精度GPS/IMU组合,适合自动驾驶环境,但视觉纹理变化很大,动态物体也多。

Euroc的特点是它天生为视觉惯性SLAM设计。它同时提供了高频IMU数据和双目图像,时间戳也做了硬件同步,这正好是ORB-SLAM3最擅长的赛道——视觉惯性融合和IMU初始化。换句话说,如果你想验证ORB-SLAM3单目+IMU或双目+IMU的效果,Euroc是最合适的公开数据集。它也提供纯双目序列,MH01-MH05可以用连续序列模拟“长时间运行”,V系列考验快速运动下的鲁棒性。

1.3 测试前先定好“口径”:单目、双目、要不要IMU

这个决定会影响你后面所有命令和评估方式。单目模式下,ORB-SLAM3输出轨迹没有真实尺度,单位是“任意单位”,需要用Sim(3)相似变换对齐到真值才能算精度;双目和IMU模式输出的是米制轨迹,可以直接和真值做SE(3)对齐。

另外,ORB-SLAM3的官方Demo里分了四个可执行文件:

  • mono_euroc:纯单目,只读左目
  • stereo_euroc:纯双目,读左右目
  • mono_inertial_euroc:单目+IMU
  • stereo_inertial_euroc:双目+IMU

四种模式的命令参数和结果差异都不同。我建议初学者先跑stereo_inertial_euroc,因为它最能体现ORB-SLAM3的完整能力,而且不容易因为尺度问题让人困惑。想理解纯视觉极限的再跑单目,想对比IMU增益的再跑双目的两种模式。别一上来就全跑一遍,先跑通一种模式,再延展。

2. 编译ORB-SLAM3时我亲历的依赖地狱

2.1 依赖版本组合:OpenCV、Eigen、Pangolin到底怎么配

ORB-SLAM3的官方README里只简单列了Pangolin、OpenCV、Eigen三个依赖,但实际编译时版本细节非常多。我先后在Ubuntu 18.04和20.04上编译过,踩过不少版本组合的坑。

先说我目前在Ubuntu 20.04上稳定可用的组合:

依赖版本备注
Pangolin0.6老版本稳定,和ORB-SLAM3的接口匹配
OpenCV3.4.x 或 4.2.0注意4.x以上需要C++11兼容
Eigen33.3.7直接用apt安装即可
g2o / DBoW2 / Sophus仓库自带Thirdparty无需手动装

Pangolin是最容易出问题的一个。如果你用的是0.8甚至更新的版本,可能会出现pango_view_handler命名空间变化、gl::前缀要求等编译错误。我自己实测,直接用0.6版本可以避免大部分接口不兼容问题。当然,新版Pangolin配合最新ORB-SLAM3主分支有时也能过,但没有必要在测试数据集阶段给自己提高难度。

OpenCV版本方面,apt直接装的libopencv-dev在Ubuntu 20.04是4.2,编译ORB-SLAM3没问题。但如果你是在Python环境里顺手装了opencv-python,不要混用。ORB-SLAM3用的是C++版本的OpenCV,务必通过pkg-config opencv4确认系统库已经正确安装。

2.2 build.sh背后的编译逻辑与常见错误处理

ORB-SLAM3根目录下有一个build.sh,它会顺序进入Thirdparty/DBoW2Thirdparty/g2oThirdparty/SophusExamples等目录,依次执行cmake和make。理论上你只需要:

cd ORB_SLAM3 chmod +x build.sh ./build.sh

但实际执行中很容易在某个子模块卡住。我的经验是,不要直接全量跑,最好先单独编译每个Thirdparty,确认没问题后再编译主目录。你可以这样操作:

cd Thirdparty/DBoW2 mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j4

每个子模块都成功后,再回到根目录执行./build.sh。这样即使出错,也能明确知道是哪一环。全量脚本最大的问题是它把错误信息淹没在一大片日志里,很难定位。

还有一个常见坑:ORB-SLAM3要求C++11或更高,但某些编译器默认可能不是。如果你在编译g2o时出现“#error This file requires compiler and library support for the ISO C++ 2011 standard”,就在cmake时加上-DCMAKE_CXX_FLAGS="-std=c++11"。不要在调用make时临时加,那样没用。

2.3 跑通前先用自带的小样本或示例验证安装

编译完成后,先别急着下载完整Euroc数据集。你可以先看一眼Examples目录下的可执行文件是否都生成了:

ls -lh Examples/Monocular/mono_euroc ls -lh Examples/Stereo-Inertial/stereo_inertial_euroc

如果能看到可执行文件,说明主程序编译成功。但“编译成功”不等于“能跑”,因为还要依赖数据集和yaml文件。ORB-SLAM3仓库自带了Examples/Monocular/EuRoC.yamlExamples/Stereo/EuRoC.yamlExamples/Monocular-Inertial/EuRoC.yaml等参数文件,所以配置这块不用自己写。

我建议第一次运行就用mono_euroc跑MH01序列的很小一段来验证,因为单目程序启动快,依赖少。后面第3节会给出具体命令。如果你能坚持到可视化窗口出现并稳定跟踪几秒,就算基本通了。

3. 四行命令跑完全部传感器模式,但每行都不简单

3.1 单目模式命令与参数逐项解析

单目Euroc示例的命令格式如下:

./Examples/Monocular/mono_euroc \ ../Vocabulary/ORBvoc.txt \ ./Examples/Monocular/EuRoC.yaml \ ~/Datasets/EuRoC/MH01 \ mav0/cam0/data \ ./Examples/Monocular/EuRoC_TimeStamps/MH01.txt \ dataset-MH01_mono.txt

我逐个说参数的含义。第一个是词袋文件ORBvoc.txt,路径不能错;第二个是相机内参和IMU参数文件;第三个是数据集根目录,这里我用的是绝对路径,推荐你也在测试时用绝对路径,避免相对路径带来的环境依赖;第四个是相对dataset_path的左目图像目录,所以是mav0/cam0/data;第五个是时间戳文件,ORB-SLAM3仓库里已经为每个Euroc序列准备好了单独的txt;最后一个是你想保存的轨迹文件名。

运行后,终端会输出当前处理的图像索引、特征点数量、跟踪状态等。如果你只看到图像编号在涨,但地图点数量一直是0,多半是yaml里的内参和数据集不匹配,或者图像加载路径不对。

单目命令输出的轨迹文件格式是每行timestamp tx ty tz qx qy qz qw,这正好是TUM格式。后面评估时可以直接用。

3.2 双目模式:为什么直接给scale没问题

双目命令在单目基础上增加了一个右目路径参数:

./Examples/Stereo/stereo_euroc \ ../Vocabulary/ORBvoc.txt \ ./Examples/Stereo/EuRoC.yaml \ ~/Datasets/EuRoC/MH01 \ mav0/cam0/data \ mav0/cam1/data \ ./Examples/Stereo/EuRoC_TimeStamps/MH01.txt \ dataset-MH01_stereo.txt

双目模式的关键在于左右目时间戳必须严格对应。ORB-SLAM3内部会通过时间戳文件同步左右目图像,如果时间戳文件有问题,会出现右目图像加载失败或特征匹配数量骤降。

另外,双目模式下EuRoC.yaml里的Camera.fpsCamera.bf(双目基线乘焦距)这些参数不能乱改。Euroc数据集的基线是固定的,yaml里已经配好,改了会直接导致深度估计错误。我在刚开始测试时,为了让某个序列跑得更好,去调整了Camera.bf,结果轨迹明显歪掉,后来重置回去才恢复。

3.3 单目+IMU与双目+IMU:IMU初始化带来的效果差异

单目+IMU命令:

./Examples/Monocular-Inertial/mono_inertial_euroc \ ../Vocabulary/ORBvoc.txt \ ./Examples/Monocular-Inertial/EuRoC.yaml \ ~/Datasets/EuRoC/MH01 \ mav0/cam0/data \ mav0/imu0/data.csv \ ./Examples/Monocular-Inertial/EuRoC_TimeStamps/MH01.txt \ dataset-MH01_monoi.txt

IMU模式的输入多了一项mav0/imu0/data.csv。这里要注意,data.csv是Euroc官方给的IMU数据文件,列包括时间戳、陀螺仪和加速度计读数。ORB-SLAM3会读取这个文件,并通过时间戳与图像帧对齐。

单目+IMU最大的看点是IMU初始化。ORB-SLAM3在启动时会尝试用视觉轨迹和IMU测量联合估计初始重力方向、速度、尺度,这个过程通常需要几秒钟的激励运动。如果你跑的序列太短或者运动太平缓,初始化可能失败,程序会一直卡在IMU initializing的状态。MH01序列运动幅度刚好,是比较安全的测试选择。

双目+IMU命令:

./Examples/Stereo-Inertial/stereo_inertial_euroc \ ../Vocabulary/ORBvoc.txt \ ./Examples/Stereo-Inertial/EuRoC.yaml \ ~/Datasets/EuRoC/MH01 \ mav0/cam0/data \ mav0/cam1/data \ mav0/imu0/data.csv \ ./Examples/Stereo-Inertial/EuRoC_TimeStamps/MH01.txt \ dataset-MH01_stereoi.txt

双目+IMU是四种模式里精度上限最高的,因为双目直接给了尺度,IMU又提供了帧间的约束和重力方向。测试时你会发现它比纯双目的跟踪更稳,快速转动时不容易丢,这就是IMU预积分的作用。

3.4 运行输出文件内容:时间戳和轨迹格式

上面每个命令最后的dataset-*.txt是轨迹输出路径。ORB-SLAM3会在每处理完一帧后追加一行,格式为:

timestamp tx ty tz qx qy qz qw

其中四元数顺序是x, y, z, w。这个格式可以直接被evo识别为TUM格式。但这里有个细节:Euroc的ground truth中四元数顺序是w, x, y, z,就用原始数据时要注意转换。用evo读取euroc格式的话,它会自动处理,如果你自己写脚本比对,就必须先统一四元数顺序。

4. 在Euroc上评估精度:别只会看漂移曲线

4.1 官方评估脚本还是evo?我的选择

ORB-SLAM3仓库里有一个evaluation目录,里面包含evaluate_ate_scale.pyevaluate_rpe.py等脚本,用于复现论文中的ATE和RPE。这些脚本需要Python2或Python3,还依赖numpymatplotlib。如果你只是偶尔跑几个序列,用官方脚本足够,但每次都要处理时间戳关联、参数对齐,脚本的输入输出格式也比较“实验室化”。

我更推荐用evo。它是一个专门评估SLAM轨迹的工具,支持TUM、KITTI、Euroc等格式,一行命令就能算ATE/RPE,还能出图。安装很简单:

pip install evo --upgrade --no-binary evo

--no-binary evo是为了避免预编译包在某些环境下的兼容问题。我的实际使用体验是,evo在Python 3.8上非常稳定,对比结果清晰,而且能自动处理尺度对齐和SE(3)对齐。

4.2 具体评估命令与对齐方式

用evo评估Euroc测试结果,我通常分两步。第一步把ORB-SLAM3保存的轨迹文件转换成可评估的格式,实际上不用转换,直接用TUM格式读取即可。第二步用真值文件评估。

Euroc序列的真值文件是mav0/state_groundtruth_estimate0/data.csv,格式是:

timestamp, p_RS_R_x, p_RS_R_y, p_RS_R_z, q_RS_w, q_RS_x, q_RS_y, q_RS_z, ...

用evo读取:

evo_ape euroc \ ~/Datasets/EuRoC/MH01/mav0/state_groundtruth_estimate0/data.csv \ dataset-MH01_mono.txt \ -a \ -s \ --plot

参数-a表示进行SE(3)/Sim(3)对齐(取决于是否加-s)。-s表示同时估计尺度,针对单目轨迹必须加;对于双目或IMU模式,因为尺度已经是米制,可以不加-s,但如果轨迹和真值之间存在微小尺度差,加了也无妨,作为参考。

如果想看相对位姿误差RPE,用:

evo_rpe euroc \ ~/Datasets/EuRoC/MH01/mav0/state_groundtruth_estimate0/data.csv \ dataset-MH01_mono.txt \ -a \ -s \ --plot

注意,无论是eval脚本还是evo,最关键的是时间戳关联。ORB-SLAM3保存的轨迹时间戳来自图像时间戳,而真值时间戳覆盖整个采集过程,两者的起点不一定完全一致。evo会自动做时间戳匹配,但如果你看到“matching failed”之类的提示,就要检查轨迹文件最后有没有写完整,或者时间戳文件是否有缺失。

4.3 一组典型的Euroc测试结果解读

以我自己在MH01上的实测为例,大致范围是这样的(机器配置不同会有波动,仅供参考):

模式ATE(米)备注
单目0.15~0.35尺度对齐后,受初始化影响大
双目0.03~0.08尺度准确,长走廊容易漂
单目+IMU0.02~0.05IMU初始化成功后很稳
双目+IMU0.01~0.04四种模式中表现最好

看结果时不要只看ATE数字,还要看轨迹的误差曲线是否有突变。比如单目模式可能在某个转角的误差突然飙升,这通常说明局部地图退化或跟踪丢失重定位。这种定性的观察能帮你快速定位算法的瓶颈。

5. 实测中高频出现的四个坑与排查思路

5.1 一运行就段错误:先查路径,再查yaml权限

我遇到过好几次,编译一切正常,一运行mono_euroc立刻Segmentation fault。第一次我怀疑是OpenCV库冲突,查了半天,最后发现是数据集路径传错了——我传成了~/Datasets/EuRoC/MH01/mav0,而程序内部拼接图像路径时又加了一次mav0/cam0/data,导致找不到任何图片,读取空向量时越界。

排查这类问题,最快的方式是先确认数据集目录结构:

ls ~/Datasets/EuRoC/MH01/mav0/cam0/data | head

能正常列出png文件,再检查命令行参数。还要注意路径中不要有中文和空格,ORB-SLAM3对这类路径处理得很脆弱。

另一类段错误和yaml文件有关。如果EuRoC.yaml中的Camera.fxCamera.fy被改成了0或异常值,三角化时会除零。建议直接用仓库自带的yaml,不要自己从头写。

5.2 IMU轨迹发散:问题大多出在时间戳或yaml的IMU参数

我在跑V2_02序列时,单目+IMU的轨迹跑着跑着就飞了。排查过程很有意思:单目纯视觉没问题,双目纯视觉没问题,单目+IMU就发散。后来我把IMU数据csv的前几行和图像时间戳做了对比,发现两者起始时间差了几毫秒,但ORB-SLAM3在初始化IMU时对时间偏差很敏感。

这类问题我最终的解决方案是:使用仓库自带的EuRoC_TimeStamps时间戳文件,不要自己从data.csv里裁剪生成。这些时间戳文件是官方预处理过的,和图像、IMU的时间戳可以对齐。另外,检查EuRoC.yaml里的IMU.Frequency是否为200,这个是Euroc IMU的实际频率,填错会让预积分的时间间隔全部错掉。

5.3 Pangolin窗口卡死或无响应:和GPU驱动、显示环境强相关

有几次我在远程服务器上跑,用X11转发显示Pangolin窗口,结果窗口出现不到一秒就卡死,程序也失去响应。这是因为Pangolin的可视化需要OpenGL支持,远程转发的GL性能很差。换到本地带GPU的机器上,一切正常。

如果你必须在无显示环境或远程环境测试,建议关闭可视化。最简单的方式是修改Examples/Monocular/mono_euroc.cc这类示例程序,把创建Viewer的代码注释掉,或者修改System构造时bUseViewer参数为false。当然这会改变源码,只适合自己实验。如果不想改源码,可以用xvfb-run提供一个虚拟显示,但可能影响Pangolin渲染效率。

5.4 别人能复现的结果你复现不了:先检查编译类型和随机性

ORB-SLAM3论文里的数值是在特定机器、特定ROS版本、特定编译优化下得到的,直接复现时差几倍都很正常。我这里想提醒的是,build.sh默认的cmake类型是Release,但如果你自己cmake时用了Debug模式,跟踪速度和精度都会显著下降。用cat CMakeLists.txt就能确认,一定要保证是-DCMAKE_BUILD_TYPE=Release

另外,SLAM算法本身的特征点提取和优化存在线程调度上的随机性,同一个序列跑两遍,ATE也会有细微差异。如果你想写进报告,最好每个配置跑三到五遍,取中位数或平均值,并记录范围。别拿一次运行的结果下结论。

6. 让Euroc测试从跑通到高效的三个小习惯

6.1 写一个shell脚本批量跑完所有序列

手动一条条敲命令太容易漏参数了。我习惯把要跑的序列列表放在一个数组里,用循环批量执行。下面这段脚本可以按需修改,核心是把数据集根目录、时间戳路径、输出文件名做成变量:

#!/bin/bash VOCAB=../Vocabulary/ORBvoc.txt DATASET_ROOT=~/Datasets/EuRoC MODE=stereo_inertial EXE=./Examples/Stereo-Inertial/stereo_inertial_euroc YAML=./Examples/Stereo-Inertial/EuRoC.yaml TS_ROOT=./Examples/Stereo-Inertial/EuRoC_TimeStamps for seq in MH01 MH02 MH03 MH04 MH05; do echo "Running ${seq} ..." $EXE $VOCAB $YAML $DATASET_ROOT/$seq \ mav0/cam0/data mav0/cam1/data mav0/imu0/data.csv \ $TS_ROOT/$seq.txt \ result_${MODE}_${seq}.txt done

注意每个模式的时间戳文件目录不同,比如单目模式在Examples/Monocular/EuRoC_TimeStamps,双目模式在Examples/Stereo/EuRoC_TimeStamps,IMU模式在对应Monocular-InertialStereo-Inertial目录。批量跑之前先单独跑一个序列验证路径无误,再全量执行,否则脚本会带着错误路径跑完所有序列,浪费时间。

6.2 记录硬件与系统状态,避免结果无法追溯

SLAM的测试结果跟CPU频率、内存、是否开启Turbo Boost、显卡都有关系。批量跑之前,我通常先把系统信息保存到文件里:

lscpu > test_env.txt free -h >> test_env.txt nvidia-smi >> test_env.txt 2>/dev/null cat /etc/os-release >> test_env.txt

如果之后想对比不同机器上的数据,这些信息非常有用。更重要的是,测试过程中要留意程序占用的CPU线程数。ORB-SLAM3默认用四线程加载特征点,如果机器只有双核,跑起来会明显变慢,结果也会受影响。

6.3 输出文件统一命名,方便评估脚本批量处理

我给每个结果文件命名时,遵循模式_序列名.txt的规律,比如mono_MH01.txtstereoi_V201.txt。评估时可以直接用shell通配符批量处理,不用每次手动输入文件名。另外,轨迹文件不要存放在ORB-SLAM3源码目录里,单独建一个results文件夹,免得后面重新编译时被清理掉。

还有一个细节:时间戳文件里如果存在重复或乱序的时间戳,ORB-SLAM3可能会卡在等待图像那里。批量跑完一遍后,检查一下输出轨迹的行数是否和序列图像数量大致一致,如果少很多,大概率是中间丢帧或崩溃了,这种结果直接归档容易误导后面的对比。

踩过几次坑之后,我现在跑Euroc测试的顺序固定是:先检查目录结构,再确认yaml参数,跑一个短序列验证,再批量执行,最后统一评估。这套流程看起来很笨,但能最大程度避免“跑了半天结果无效”的尴尬。ORB-SLAM3的工程细节确实多,但只要把Euroc这个标准测试跑顺了,后面换其他数据集、加传感器融合,都会从容很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 15:54:46

VGG19实战:从结构解析到PyTorch实现与调参全指南

前一段时间整理自己深度学习系列的学习笔记,正好写到“深度学习12—VGG19实现”这一篇。VGG19这个模型,现在看起来已经不算最前沿,但它在视觉模型演进里的位置非常特殊:它是“深度”这个概念真正被做到极致的代表作,也…

作者头像 李华
网站建设 2026/9/15 15:54:12

三步用 ipatool 下载 iOS IPA 包:新手完整的上手指南

三步用 ipatool 下载 iOS IPA 包:新手完整的上手指南 【免费下载链接】ipatool Command-line tool that allows you to search for iOS, iPadOS, tvOS, visionOS, and macOS apps on the App Store, and download .ipa or macOS .pkg app packages. 项目地址: htt…

作者头像 李华
网站建设 2026/9/15 15:52:26

KMP跨平台瀑布流实战:基于Compose Multiplatform的LazyVerticalStaggeredGrid

最近在做KMP项目的瀑布流时踩了不少坑,整理成这篇东西,希望能让后来的人少走弯路。先说清楚,这里的KMP是Kotlin Multiplatform的缩写,不是数据结构里那个KMP字符串匹配算法。如果你看到标题第一反应是“求next数组”,那…

作者头像 李华