1. 为什么 ORB-SLAM3 的编译和 ROS 接入值得单独拿出来讲
ORB-SLAM3 是目前视觉 SLAM 领域里少数同时支持单目、双目、RGB-D 以及鱼眼相机,并且把视觉惯性紧耦合做得比较完整的开源系统之一。它的定位精度、回环能力和多地图机制在实际项目里确实能打,但它的编译和 ROS 接入过程,几乎是每个新手都要掉一层皮的地方。我自己第一次上手的时候,光是让它在 ROS 里跑起来就折腾了整整两天,中间踩的坑包括 OpenCV 版本冲突、Pangolin 链接失败、ROS 话题对不上、配置文件路径写错等等。
这篇内容就是把我自己反复编译、反复重装、反复调试之后总结出来的完整流程写清楚。核心关键词是ORB-SLAM3 编译和ROS 运行,我会从依赖选型、编译顺序、ROS 节点接入、配置文件解析、常见报错排查这几个角度展开。适合的人群包括:正在做视觉 SLAM 课程项目的研究生、需要把 ORB-SLAM3 集成到机器人平台上的工程师、以及想拿它做二次开发但被环境卡住的开发者。不管你是刚接触 SLAM 的小白,还是已经用过 ORB-SLAM2 想升级到 3 的老手,这篇内容都能让你少走弯路。
需要提前说明的是,ORB-SLAM3 的编译对系统环境非常敏感,尤其是 OpenCV、Eigen、Pangolin、DBoW2、g2o 这几个库的版本和安装路径。很多人编译失败不是因为代码有问题,而是因为环境里存在多个版本的库,链接器找到了错误的那个。所以我会把依赖管理单独拎出来讲,而不是直接甩几条命令就完事。
2. 编译前的环境准备与依赖选型逻辑
2.1 系统与基础工具的选择
我实测下来最稳的组合是 Ubuntu 20.04 + ROS Noetic,这个组合的好处是 ROS 官方源里自带的 OpenCV 是 4.2 版本,和 ORB-SLAM3 的兼容性比较好。如果你用的是 Ubuntu 18.04 + ROS Melodic,OpenCV 是 3.2,也能跑,但部分 C++ 标准需要手动调整。Ubuntu 22.04 + ROS2 的话,ORB-SLAM3 原生并不支持 ROS2,需要额外写桥接层,这个后面会提到。
基础工具方面,编译工具链必须齐全:
sudo apt update sudo apt install -y build-essential cmake git pkg-config sudo apt install -y libglew-dev libboost-all-dev libssl-dev这里解释一下为什么需要这些。build-essential提供 gcc、g++、make,是编译 C++ 项目的基础。cmake是 ORB-SLAM3 的构建系统。pkg-config用来在编译时查找库的路径,很多 CMakeLists 里会调用它。libglew-dev是 Pangolin 依赖的 OpenGL 扩展库,缺了它 Pangolin 编译会报找不到 GLEW。libboost-all-dev和libssl-dev主要是给 ROS 和一些底层通信库用的,虽然 ORB-SLAM3 本身不直接依赖,但 ROS 环境里经常需要。
注意:不要用
apt安装 OpenCV 之后再手动编译一个不同版本的 OpenCV,这是最常见的冲突来源。要么全用系统自带的,要么全用手动编译的,并且确保 CMake 能找到正确的那个。
2.2 OpenCV 版本的处理策略
ORB-SLAM3 官方推荐 OpenCV 3.4 以上,实测 4.2 和 4.5 都能跑。问题在于 ROS Noetic 自带的 OpenCV 是 4.2,如果你再手动装一个 4.5,编译 ORB-SLAM3 时 CMake 可能会找到 4.5,而 ROS 的 cv_bridge 链接的是 4.2,运行时就可能出现符号冲突。
我的建议是:直接用 ROS 自带的 OpenCV,不要额外装。验证方法:
pkg-config --modversion opencv4如果输出 4.2.0 之类的版本号,说明系统里已经有 OpenCV4 了。如果输出的是 3.x,那可能需要手动装一个 4.x。手动编译 OpenCV 的时候,一定要指定安装路径,并且把OpenCV_DIR环境变量设对:
cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D WITH_CUDA=OFF \ -D BUILD_EXAMPLES=OFF ..WITH_CUDA=OFF是因为 ORB-SLAM3 本身不用 CUDA,开了反而增加编译时间和出错概率。安装完之后执行sudo ldconfig刷新动态库缓存,这一步很多人会忘,导致运行时找不到库。
2.3 Eigen、Pangolin、DBoW2、g2o 的安装顺序
这几个库的安装顺序有讲究。Eigen 是头文件库,装在哪里都行,但 Pangolin 依赖 Eigen,DBoW2 和 g2o 是 ORB-SLAM3 自带的第三方库,不需要单独装,但需要确保它们能编译通过。
Eigen 的安装:
sudo apt install -y libeigen3-dev如果系统源里的 Eigen 版本太老(低于 3.3),建议手动装 3.3.7 或 3.4.0。手动装的时候解压后执行:
mkdir build && cd build cmake .. sudo make installPangolin 的安装稍微麻烦一点,因为它依赖 OpenGL 和 GLEW。我推荐用 v0.6 版本,比较稳定:
git clone https://github.com/stevenlovegrove/Pangolin.git cd Pangolin git checkout v0.6 mkdir build && cd build cmake .. make -j4 sudo make install编译 Pangolin 的时候如果报Could NOT find GLEW,说明libglew-dev没装好,回去补装。如果报 OpenGL 相关的错误,检查显卡驱动和libgl1-mesa-dev是否安装。
实操心得:Pangolin 编译时间比较长,
make -j4里的数字根据你机器的 CPU 核心数调整,但不要开太大,否则内存不够会卡死。我一般用-j2保守一点。
DBoW2 和 g2o 在 ORB-SLAM3 的Thirdparty目录里,编译 ORB-SLAM3 时会自动编译它们。但如果你之前编译失败过,建议先手动进到对应目录清理一下:
cd ORB_SLAM3/Thirdparty/DBoW2 rm -rf build mkdir build && cd build cmake .. make -j2g2o 同理。这两个库编译通过之后,再编译主项目会顺利很多。
3. ORB-SLAM3 主项目编译的完整流程与关键细节
3.1 源码获取与目录结构说明
从官方仓库克隆源码之后,你会看到这样的目录结构:
ORB_SLAM3/ ├── Examples/ ├── include/ ├── src/ ├── Thirdparty/ │ ├── DBoW2/ │ ├── g2o/ │ └── Sophus/ ├── Vocabulary/ ├── CMakeLists.txt └── build.shExamples里放的是各种示例程序,包括单目、双目、RGB-D、ROS 等。Vocabulary里是 ORB 词袋文件,这个文件很大,下载的时候要有耐心。Thirdparty里是依赖库。build.sh是官方提供的编译脚本,但我建议不要直接跑它,因为它的编译顺序和错误处理不够灵活。
3.2 编译脚本的逐行解析与手动编译
官方build.sh的内容大致是这样的:
echo "Configuring and building Thirdparty/DBoW2 ..." cd Thirdparty/DBoW2 mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j cd ../../g2o mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j cd ../../../ echo "Configuring and building ORB_SLAM3 ..." mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j这个脚本的问题在于make -j没有指定并行数,在内存小的机器上容易崩。我一般会改成make -j2或者make -j4。另外,如果 DBoW2 或 g2o 编译失败,脚本不会停下来,会继续往下跑,导致主项目编译时找不到库。所以我更推荐手动一步步来。
手动编译的完整流程:
# 编译 DBoW2 cd ORB_SLAM3/Thirdparty/DBoW2 mkdir -p build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j2 # 编译 g2o cd ../../g2o mkdir -p build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j2 # 编译主项目 cd ../../../ mkdir -p build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j2每一步都要确认没有报错再往下走。DBoW2 编译成功后会生成libDBoW2.so,g2o 会生成libg2o.so,主项目会生成libORB_SLAM3.so和各个可执行文件。
3.3 编译过程中的典型报错与解决
报错一:fatal error: Eigen/Core: No such file or directory
这个通常是 Eigen 没装或者路径不对。检查/usr/include/eigen3是否存在,如果存在但编译还是找不到,可能是 CMakeLists 里的 include 路径写的是/usr/local/include/eigen3。解决方法是在 CMakeLists 里加上:
include_directories(/usr/include/eigen3)或者创建一个软链接:
sudo ln -s /usr/include/eigen3/Eigen /usr/include/Eigen报错二:undefined reference to symbol '_ZN5boost6system15system_categoryEv'
这是 Boost 库链接问题。ORB-SLAM3 的某些版本需要显式链接 Boost。在 CMakeLists 里找到target_link_libraries那一行,加上:
${Boost_LIBRARIES}并在前面加上find_package(Boost REQUIRED)。
报错三:Pangolin could not be found
Pangolin 安装之后,CMake 可能找不到它的配置文件。检查/usr/local/lib/cmake/Pangolin是否存在。如果不存在,说明 Pangolin 安装不完整,重新编译安装。如果存在但还是找不到,在 CMakeLists 里手动指定:
set(Pangolin_DIR /usr/local/lib/cmake/Pangolin)报错四:C++ standard version mismatch
ORB-SLAM3 需要 C++11 或更高。如果系统默认的 g++ 版本太老,在 CMakeLists 里加上:
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON)避坑技巧:编译之前先执行
sudo ldconfig,确保所有动态库都能被找到。编译过程中如果某个库报错,先单独进到那个库的目录里编译,确认它能独立编译通过,再回到主项目。
4. ROS 节点接入与运行配置
4.1 ROS 工作空间的搭建与包结构
ORB-SLAM3 的 ROS 示例在Examples/ROS/ORB_SLAM3目录下。要把它接入 ROS,需要把这个目录放到 ROS 工作空间的src里,或者创建一个软链接。我一般是这样做的:
mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src ln -s ~/ORB_SLAM3/Examples/ROS/ORB_SLAM3 . cd ~/catkin_ws catkin_make这里有个关键点:catkin_make之前,需要确保 ORB-SLAM3 的主项目已经编译完成,因为 ROS 节点会链接libORB_SLAM3.so。如果主项目没编译好,catkin_make会报找不到库。
另外,ROS 节点的 CMakeLists 里会引用 ORB-SLAM3 的头文件和库路径。如果路径不对,需要手动修改。找到Examples/ROS/ORB_SLAM3/CMakeLists.txt,检查这几行:
set(ORB_SLAM3_DIR /path/to/ORB_SLAM3) include_directories(${ORB_SLAM3_DIR}/include) link_directories(${ORB_SLAM3_DIR}/lib)把/path/to/ORB_SLAM3改成你的实际路径。
4.2 ROS 话题订阅与消息类型解析
ORB-SLAM3 的 ROS 节点订阅的话题类型取决于你用的是单目、双目还是 RGB-D。以单目为例,它订阅的是sensor_msgs/Image类型的图像话题。双目的话,订阅两个图像话题,或者一个sensor_msgs/Image加一个sensor_msgs/CameraInfo。RGB-D 的话,订阅图像和深度图两个话题。
节点的启动文件在Examples/ROS/ORB_SLAM3/launch目录下。以单目为例,mono.launch的内容大致是:
<launch> <node name="ORB_SLAM3" pkg="ORB_SLAM3" type="Mono" args="/path/to/vocabulary /path/to/config.yaml" output="screen"> <remap from="/camera/image_raw" to="/your_camera/image_raw" /> </node> </launch>这里的args是两个参数:词袋文件路径和配置文件路径。词袋文件在ORB_SLAM3/Vocabulary/ORBvoc.txt,配置文件在ORB_SLAM3/Examples/Monocular/下,比如EuRoC.yaml、TUM1.yaml等。
注意:词袋文件加载比较慢,第一次运行可能要等十几秒,这是正常的。如果一直卡住,检查文件路径是否正确,以及文件是否完整。
4.3 配置文件的参数含义与调优
配置文件是 YAML 格式,里面包含了相机内参、畸变系数、ORB 特征参数、IMU 参数等。以单目为例,关键参数包括:
Camera.fx: 535.4 Camera.fy: 539.2 Camera.cx: 320.1 Camera.cy: 247.6 Camera.k1: 0.0 Camera.k2: 0.0 Camera.p1: 0.0 Camera.p2: 0.0 Camera.width: 640 Camera.height: 480 Camera.fps: 30.0 ORBextractor.nFeatures: 1000 ORBextractor.scaleFactor: 1.2 ORBextractor.nLevels: 8fx、fy、cx、cy是相机内参,必须和你的相机标定结果一致。k1、k2、p1、p2是畸变系数,如果相机畸变很小可以都设成 0。nFeatures是每帧提取的特征点数量,默认 1000,如果相机分辨率高可以适当增加到 1500 或 2000。scaleFactor是金字塔缩放因子,一般 1.2 就行。nLevels是金字塔层数,默认 8。
如果是双目或 RGB-D,还需要配置第二个相机的参数或者深度图的缩放因子。如果是视觉惯性模式,还需要配置 IMU 的噪声参数和频率。
实操心得:配置文件里的参数不要随便改,尤其是内参和畸变系数。如果用的是标准数据集,直接用官方提供的配置文件就行。如果用自己的相机,一定要先做标定,标定不准的话 SLAM 轨迹会飘得厉害。
4.4 运行时的数据流与调试方法
启动 ROS 节点之后,可以用rostopic list查看话题,用rostopic hz /your_camera/image_raw查看图像频率。如果频率太低,SLAM 会跟不上。可以用rqt_image_view查看图像是否正常。
ORB-SLAM3 运行时会发布一些话题,比如/ORB_SLAM3/trajectory发布轨迹,/ORB_SLAM3/pose发布当前位姿。可以用rviz可视化轨迹和特征点。如果轨迹漂移严重,检查相机标定和配置文件参数。如果跟踪丢失频繁,可能是特征点太少或者场景纹理太弱,可以尝试增加nFeatures或者降低scaleFactor。
调试的时候,我一般会先跑官方数据集,确认环境没问题,再换自己的数据。官方数据集可以从网上下载,比如 EuRoC 的 MH01 序列。跑数据集的命令是:
rosrun ORB_SLAM3 Mono /path/to/ORBvoc.txt /path/to/EuRoC.yaml然后用rosbag play播放数据包。如果数据集能跑通,说明环境没问题,再排查自己的数据。
5. 常见问题排查与实战避坑经验
5.1 编译类问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 找不到 Eigen/Core | Eigen 未安装或路径不对 | 安装 libeigen3-dev 或手动指定路径 |
| Pangolin 链接失败 | Pangolin 未安装或版本不兼容 | 重新编译安装 Pangolin v0.6 |
| DBoW2 编译报错 | OpenCV 版本冲突 | 统一 OpenCV 版本,清理后重编 |
| g2o 编译报错 | C++ 标准不匹配 | 设置 CMAKE_CXX_STANDARD 11 |
| 主项目链接失败 | 第三方库未编译成功 | 先单独编译 DBoW2 和 g2o |
| ROS 节点找不到库 | 环境变量未设置 | source devel/setup.bash |
5.2 运行类问题与排查思路
问题一:节点启动后立即退出
检查 launch 文件里的args参数是否正确,尤其是词袋文件和配置文件的路径。如果路径里有空格或特殊字符,要用引号包起来。另外,检查配置文件里的参数是否完整,缺少必要参数会导致初始化失败。
问题二:图像话题收不到数据
用rostopic list确认话题名称是否匹配。如果相机发布的话题是/camera/image_raw,而 launch 文件里 remap 的是/your_camera/image_raw,那肯定收不到。另外,检查相机的驱动是否正常启动,可以用rostopic echo查看是否有数据。
问题三:跟踪丢失频繁
可能的原因包括:图像纹理太弱、相机运动太快、特征点数量太少、配置文件参数不对。解决方法:增加nFeatures,降低scaleFactor,检查相机标定,放慢相机运动速度。如果是视觉惯性模式,检查 IMU 数据是否正常。
问题四:轨迹漂移严重
最常见的原因是相机标定不准。重新标定相机,确保内参和畸变系数准确。另外,检查配置文件里的Camera.fps是否和实际帧率一致。如果用的是卷帘快门相机,ORB-SLAM3 可能处理不好,建议用全局快门相机。
避坑技巧:运行之前先
source ~/catkin_ws/devel/setup.bash,确保 ROS 能找到你的包。如果还是找不到,检查ROS_PACKAGE_PATH环境变量。
5.3 性能优化与二次开发建议
如果要在嵌入式平台上跑 ORB-SLAM3,性能优化是必须的。可以关闭 Pangolin 的可视化,减少 CPU 占用。可以降低nFeatures,减少计算量。可以用-DCMAKE_BUILD_TYPE=Release开启编译优化。如果平台支持 NEON 指令集,可以在 CMakeLists 里加上-mfpu=neon。
二次开发的话,建议先熟悉System.h、Tracking.h、LocalMapping.h、LoopClosing.h这几个核心类。System是入口,负责初始化和管理各个线程。Tracking负责跟踪,LocalMapping负责局部建图,LoopClosing负责回环检测。如果要加新的传感器,比如轮速计,可以在Tracking里加融合逻辑。如果要改地图保存格式,可以在Map和MapPoint里改。
我自己在做二次开发的时候,最大的体会是:不要一上来就改核心代码,先用官方示例跑通,再逐步替换模块。每次只改一个地方,改完就测试,确认没问题再改下一个。这样出问题的时候容易定位。
6. 从编译到运行的完整实操记录
6.1 一次完整的从零搭建过程
假设你有一台刚装好 Ubuntu 20.04 和 ROS Noetic 的机器,从零开始搭建 ORB-SLAM3 的完整流程如下:
第一步,安装基础依赖:
sudo apt update sudo apt install -y build-essential cmake git pkg-config libglew-dev libboost-all-dev libssl-dev libeigen3-dev第二步,编译安装 Pangolin:
git clone https://github.com/stevenlovegrove/Pangolin.git cd Pangolin git checkout v0.6 mkdir build && cd build cmake .. make -j2 sudo make install sudo ldconfig第三步,克隆 ORB-SLAM3 并编译:
git clone https://github.com/UZ-SLAMLab/ORB_SLAM3.git cd ORB_SLAM3 cd Thirdparty/DBoW2 && mkdir build && cd build && cmake .. && make -j2 cd ../../g2o && mkdir build && cd build && cmake .. && make -j2 cd ../../../ mkdir build && cd build && cmake .. && make -j2第四步,搭建 ROS 工作空间:
mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src ln -s ~/ORB_SLAM3/Examples/ROS/ORB_SLAM3 . cd ~/catkin_ws catkin_make第五步,运行测试:
source ~/catkin_ws/devel/setup.bash rosrun ORB_SLAM3 Mono ~/ORB_SLAM3/Vocabulary/ORBvoc.txt ~/ORB_SLAM3/Examples/Monocular/EuRoC.yaml然后播放数据集:
rosbag play MH01.bag如果一切正常,你应该能看到 Pangolin 窗口里显示特征点和轨迹。
6.2 关键参数的计算与选择过程
以相机内参为例,假设你用的是一个 640x480 的 USB 相机,标定之后得到 fx=535.4,fy=539.2,cx=320.1,cy=247.6。这些参数的含义是:fx 和 fy 是焦距在像素单位下的表示,cx 和 cy 是光心在图像中的位置。如果标定不准,SLAM 的尺度估计和轨迹都会有问题。
ORB 特征参数的选择也有讲究。nFeatures默认 1000,如果场景纹理丰富,可以降到 800 减少计算量。如果场景纹理弱,可以增加到 1500 或 2000。scaleFactor默认 1.2,表示每层金字塔的缩放比例。nLevels默认 8,表示金字塔层数。这两个参数影响特征点的尺度和旋转不变性,一般不用改。
IMU 参数的话,如果用的是视觉惯性模式,需要配置IMU.NoiseGyro、IMU.NoiseAcc、IMU.GyroWalk、IMU.AccWalk等。这些参数可以从 IMU 的数据手册里查到,或者通过标定得到。如果参数不对,融合效果会很差。
6.3 运行效果评估与调优记录
跑完数据集之后,可以用evo工具评估轨迹精度。安装evo:
pip install evo --upgrade --no-binary evo然后保存 ORB-SLAM3 的轨迹,和真值对比:
evo_traj tum ORB_SLAM3_trajectory.txt --ref groundtruth.txt -p --plot_mode=xyz如果轨迹误差大,检查相机标定和配置文件。如果轨迹抖动厉害,可能是特征点跟踪不稳定,尝试调整nFeatures和scaleFactor。如果回环检测不生效,检查词袋文件是否加载成功,以及场景是否有足够的重复纹理。
我自己在调优的时候发现,ORB-SLAM3 对光照变化比较敏感。如果场景光照变化大,特征点匹配会变差,导致跟踪丢失。解决方法是在相机前面加一个自动曝光控制,或者用光照不变性更好的特征描述子。另外,如果场景里有大量动态物体,比如行人,也会影响跟踪。可以在Tracking里加动态物体剔除逻辑,但这属于二次开发范畴了。
6.4 后续扩展与实用建议
如果你想把 ORB-SLAM3 用到实际机器人上,有几个方向可以扩展。一是加 IMU 融合,提高鲁棒性。二是加轮速计融合,提高尺度估计精度。三是加语义分割,剔除动态物体。四是加地图保存和加载,支持长期定位。
地图保存的话,ORB-SLAM3 支持SaveMap和LoadMap接口,可以在System里调用。保存的地图文件包括地图点和关键帧,加载之后可以继续建图或者做重定位。这个功能在实际项目里很有用,比如机器人关机再开机之后,可以快速重定位。
最后分享一个小技巧:如果编译的时候报错信息太多,可以用make 2>&1 | tee build.log把日志保存下来,然后慢慢看。错误信息一般从下往上看,第一个报错往往是最关键的。另外,编译之前先git status确认代码没有被意外修改,有时候改了一个小地方会导致编译失败。
这个内容后续还可以这样扩展:把 ORB-SLAM3 和 ROS2 结合,写一个桥接节点,把 ROS2 的图像话题转成 ROS1 的消息格式,再喂给 ORB-SLAM3。或者把 ORB-SLAM3 移植到嵌入式平台,比如 Jetson 系列,做性能优化和裁剪。这些都是实际项目里会遇到的需求,有机会再单独展开讲。