ORB-SLAM3的CMake与ROS编译以及测试

Sep 30,2020   7198 words   26 min

Tags: SLAM

萨拉戈萨大学在今年7月推出了全新的ORB-SLAM3,当时我也第一时间进行了跟进,在之前在IMAV的比赛例会中也进行了分享,但是没有在博客中进行总结过。所以这篇博客的主要目的就是从实用的角度,记录如何成功运行ORB-SLAM3。由于整个ORB-SLAM3有常规版本和ROS版本,所以这里也主要分这两个部分进行介绍。其实,ORB-SLAM3的Github主页部分已经说的比较详细了,照着编译基本不会出现上面问题。而且源码中也给出了build.shbuild_ros.sh的两个脚本用于自动编译,其实已经非常方便了。不过,本着学习、记录的态度,还是自己再写一下。另外也记录一下一些可能发生的错误。

1.ORB-SLAM3的CMake编译

(1)依赖环境配置

可以直接参考ORB-SLAM3的Github主页,主要包括Pangolin、OpenCV、Eigen3、DBoW2和G2O。其中后两个在ORB-SLAM3的源码中自带了,所以实际只需要安装前三个就行。关于如何安装,可以参考之前的配置SLAM环境的博客,这里就假定已经安装好依赖环境了。

(2)代码下载

这个就不用多说了,直接去ORB-SLAM3的Github主页上下载代码即可,所有文件加一起大约有800MB左右。当然如果你网速很好,直接clone也可以。

(3)第三方库编译

主要是ORB-SLAM3自带的DBoW2和G2O。首先是DBoW2,在ORB_SLAM3源码根目录下打开终端,依次输入如下命令。

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

简单解释其实就是非常常规的CMake步骤,切换到DBoW2目录下,新建build文件夹,cmake配置,make编译。编译好后如下图所示。 然后编译G2O,同理,我们可以在源码根目录ORB_SLAM3下打开终端,输入如下命令。

cd Thirdparty/g2o
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j

和上面一样,这里就不再赘述了。如果之前是通过apt的方式安装的Eigen,可能出现的错误是提示找不到Eigen3这个库,如下。 简单来说这是因为他要求的EIgen3必须要是3.1.0的版本,而你的电脑上没有对应版本(比他高也不行)。解决办法也非常简单,你可以修改g2o文件夹下的CMakeLists.txt,如下,将其中的3.1.0删掉保存,再重新cmake即可。 最后make生成,生成结果如下。

(4)源码编译

上面的步骤已经把相关依赖解决了,这一步就是最后也是最重要的一步了,就是编译ORB-SLAM3的源码。虽然ORB-SLAM3源码很复杂,但其实还是标准的CMake流程,所以不用担心。还是在源码根目录ORB_SLAM3下打开终端,输入如下命令。

mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j

同样的,你有可能会遇到如下的报错。 不用担心,仔细看下会发现和上面的问题是一样的,他指定了Eigen3的版本为3.1.0。解决方法也是一样,我们在ORB-SLAM3源码根目录下的CMakeLists.txt中将Eigen的版本删掉并保存即可。再次重新CMake就不会有错了,然后就是make。接下来就是等待,在我的电脑上大约用了一分半。 另外需要注意的是,ORB-SLAM3编译对于内存的使用相对较大,推荐16GB及以上。当然也可以在8GB内存上编译,不过编译的时候记得尽可能多腾出点空间,把用不到的程序关掉。否则编译内存不够的话,会直接卡死。编译好的输出如下所示。 至此,ORB-SLAM3的CMake编译就完成了。我们可以在Examples文件夹下看到很多生成的可执行文件。 同时在源码根目录的lib文件夹下看到一个.so库文件。

2.ORB-SLAM3的运行

这里我们以ORB-SLAM3运行双目-IMU配置,EuRoC MH—04-difficult为例。

(1)解压字典

首先,我们需要把源码根目录下的Vocabulary文件夹下的字典文件解压一下,得到一个ORBvoc.txt文件。

(2)数据下载与解压

这里我们使用EuRoC数据集,如下图所示。 对于常规CMake生成的可执行文件,我们使用的是ASL格式的数据。下载完成后解压即可。

(3)对数据集的预处理

但按照ORB-SLAM3双目-IMU启动参数的要求,需要以下参数:

Usage: ./stereo_inertial_euroc path_to_vocabulary path_to_settings path_to_sequence_folder_1 path_to_times_file_1 save_file_name

我们需要字典文件、参数设置文件、影像序列文件夹路径、对应的时间戳文件以及最后一个参数,一些SLAM结果的保存文件名。如果不写就以默认名称CameraTrajectory.txtKeyFrameTrajectory.txt保存。这里可以发现,前三个参数都很容易得到,但直接下载下来的EuRoC数据集里并没有时间戳文件,不要担心,ORB-SLAM3已经贴心地为我们准备好了时间戳文件。 这里EuRoC_IMU里放的是IMU的时间戳,EuRoC_TimeStamps里放的是相机的时间戳。关于这些参数的更详细的说明和使用,直接查看对应Example的源码即可,都非常简单,基本一看就懂了。另外一个非常重要的点是,在代码中,是有mav0这个文件夹的。意思就是,对于下载的MH_04_difficult.zip文件,如果右键,在Ubuntu下直接解压(提取到此处)得到的是一个mav0文件夹,里面是cam0cam1等文件夹。这时一定不要直接把mav0修改成其它名字,而是应该新建一个文件夹,然后将mav0整体放进去,对新建的文件夹改名字。不然程序一启动就会卡住,也不会报错。原因就在于他在代码里是这样写的,如下。 路径被写死了,一旦找不到就会卡住。

(4)程序运行

在有了上面的而关于如何运行,其实在源码根目录下的xxx_examples.sh中都有介绍,如下。 这里我们就以双目-IMU配置为例,按照上面介绍的参数,跑通EuRoC数据。在Examples/Stereo-Inertial下打开终端,并输入如下内容。注意对应文件路径要换成你自己的。

./stereo_inertial_euroc ../../Vocabulary/ORBvoc.txt ./EuRoC.yaml /root/Data/EuRoC/MH_04_difficult ./EuRoC_TimeStamps/MH04.txt mh04_results

程序运行和ORB-SLAM2没什么区别,如下。 而且我们也得到了两个txt文件,一个是每一帧的位姿,一个是关键帧的位姿。

至此,双目-IMU的ORB-SLAM3的运行就完成了。其它配置模式的运行其实都是类似的,会了这一个其它也基本不会有问题了。

3.ORB-SLAM3的ROS编译

如前面提到的ORB-SLAM3也有ROS对应的版本。对应Examples/ROS/ORB_SLAM3文件夹下的内容,包括Mono、MonoAR、RGBD和Stereo。而至于其它的节点,可以照葫芦画瓢地写出来。

(1)ROS环境配置

既然你都看到这里了,我也就假定你的ROS环境已经配置好了。如果还没有配置ROS环境,可以参考之前的这篇ROS笔记进行配置,完成后再回来。

(2)代码编译

整个ROS节点还是用CMake进行编译,在代码中通过调用ROS的API接口实现数据的读写。所以从这个角度来说,其实ROS只是发挥了数据传输的作用,核心的算法还是那些C++文件。既然是CMake,那就按照CMake的标准流程进行,和上面可以说是一模一样的。在源码根目录下打开终端,输入如下命令。

cd Examples/ROS/ORB_SLAM3
mkdir build
cd build
cmake .. -DROS_BUILD_TYPE=Release
make -j

如果不出意外,你可能会遇到下面的错误。 提示说ROS包路径有问题。这是因为你并没有把你当前的ROS代码路径添加到ROS_PACKAGE_PATH环境变量中,导致找不到。解决办法也很简单,gedit ~/.bashrc打开编辑器,然后再末尾添加如下内容(注意对应路径要换成你自己的):

# For ORB-SLAM3
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:/root/Codes/ORB_SLAM3/Examples/ROS/ORB_SLAM3

添加完成后如下所示。 保存文件,最后别忘source ~/.bashrc。然而,当这个问题解决以后,新的问题又出现了,不过仔细看会发现还是前面遇到过两次的Eigen的版本问题。 所以解决起来会容易多了。找到/Examples/ROS/ORB_SLAM3下面的CMakeLists.txt文件,将其中的3.1.0删掉保存即可。再次cmake就应该没问题了,如下所示。 最后,就是make一下,按道理说就大功告成了。然而在我的电脑上遇到了这样的错误。 提示我说GeometricCamera.h头文件找不到。我们可以定位到KeyFrame.h文件中,可以看到,其中32行它是直接#include "GeometricCamera.h",但问题在于,这个文件并不是和KeyFrame.h在同一个目录下,而是在CameraModels/GeometricCamera.h,所以知道这个问题以后,也就很好改了,改成#include "CameraModels/GeometricCamera.h"即可。此外,还需要修改Atlas.hinclude

#include "CameraModels/GeometricCamera.h"
#include "CameraModels/Pinhole.h"
#include "CameraModels/KannalaBrandt8.h"

Tracking.hinclude

#include "CameraModels/GeometricCamera.h"

进一步,解决了这个错误,你可能又会遇到‘MapPoint’ was not declared in this scope的错误,如下。 如果仔细观察会发现,这些错误都发生在MonoAR节点代码里。一个“逃避但可能有用的方法”是不编译这个MonoAR节点。当然如果直面问题也是有解决办法的。打开ViewerAR.h文件,你会发现一个神奇的事情,明明是ORB-SLAM3但是他的命名空间却是ORB-SLAM2,如下。 而这个明显的Bug也正是问题的关键所在。所以改起来也很简单了,搜索ViewerAR.h中所有的ORB_SLAM2,统一改成ORB_SLAM3。此外,不仅仅是ViewerAR.h里有这个问题,ViewerAR.cc(2处)、ros_mono_ar.cc(8处)里都有这个问题。不得不说这显然是写代码的时候粗心导致的,或者是直接把原来的代码拷过来了,只是改了个开头的版权申明,内容完全没修改,才会导致这种低级错误的发生。

当你以为万事大吉,没有问题的时候,惊喜又来了。 定睛一看,你会发现又是ORB_SLAM2命名空间的问题。只不过这次是在ros_mono.cc里,所以要怎么改不用多说了,统一改成ORB_SLAM3就好。另外ros_rgbd.ccros_stereo.cc里都有这个问题,也要改过来。总的来说,你会发现,整个ROS的源代码都有这个问题,不得不说实在是太粗心大意了。看了下Github上的Issue,也有其他人提到了这个问题。

经过了上面这么多的错误,你总以为该结束了吧。然而现实总是很残酷。这会在Link的时候又出错了,如下。 说是对_ZN5boost6system15system_categoryEv这一长串未定义的引用,经验丰富的你十有八九应该想到可能是CMakeLists.txt文件中没有找到包或者配置好。事实也确实是这样。看到错误信息里有libboost_system.so,所以我们可以在CMakeLists.txt文件的中加上它,把下面这部分替换文件中的对应部分。

set(LIBS 
${OpenCV_LIBS} 
${EIGEN3_LIBS}
${Pangolin_LIBRARIES}
${PROJECT_SOURCE_DIR}/../../../Thirdparty/DBoW2/lib/libDBoW2.so
${PROJECT_SOURCE_DIR}/../../../Thirdparty/g2o/lib/libg2o.so
${PROJECT_SOURCE_DIR}/../../../lib/libORB_SLAM3.so
-lboost_system
)

由于我们修改了CMakeLists.txt文件,所以需要重新cmake一下,然后再make。终于,没有再报任何错误了。你的ROS版本ORB-SLAM3终于编译好了。 你会在文件夹下看到这四个可执行文件,也就是ROS节点了。

4.ORB-SLAM3的ROS运行

虽然刚刚编译出来的是可执行文件,但你是无法直接运行的,会报如下错误。 说是找不到ROS Master。这才说明它是一个ROS程序,如果和之前的CMake程序一样直接就运行起来了才是有问题了。如果运行的话,可以先用roscore启动Master。

这里我们以Stereo节点为例,还是选择EuRoC数据集,MH_03_medium,介绍ROS版本的运行。注意由于是ROS,所以数据集的格式是.bag。下载对应的bag文件就可以了。

(1)启动ROS Master

这个其实刚刚说过了,节点启动之前得先要有个Master。所以新打开一个终端,输入roscore启动Master。

(2)回放ROS Bag

由于是ROS,所以我们需要发布数据Topic。简单方便的方式是回放录好的ROS Bag。当然你也可以连接D435i等这种相机,然后修改Stereo节点订阅的Topic。这里我们就暂时不修改他的代码,通过新建一个新的Topic实现。首先我们需要看看Stereo节点订阅了哪些Topic,打开代码文件如下。 可以看到,它订阅了/camera/left/image_rawcamera/right/image_raw两个Topic,分别对应左右影像流。而我们再利用rosbag工具看一下EuRoC数据集中的Topic是什么,如下。 可以看到它里面,左右影像的名称分别是/cam0/image_raw/cam1/image_raw,所以我们需要一个“转发器”,将数据流转发一下。而这个技术在上一篇博客中其实已经提到了,利用ROS中的topic_tools就可以实现。我们分别打开两个终端,然后输入如下命令。

rosrun topic_tools throttle messages /cam0/image_raw 20.0 /camera/left/image_raw
rosrun topic_tools throttle messages /cam1/image_raw 20.0 /camera/right/image_raw

然后新打开终端,输入如下命令(记得改成你自己的路径),开始回放数据包。

rosbag play MH_03_medium.bag
(3)启动Stereo节点

Stereo节点的输入参数如下。

Usage: rosrun ORB_SLAM3 Stereo path_to_vocabulary path_to_settings do_rectify

字典文件路径、参数路径,以及是否进行校正。你可能会有疑问,输入的数据呢?答案是由于是ROS节点,数据是通过订阅Topic进行接收的。所以只要发送Topic,Stereo就会接收数据。这点是和之前CMake的程序最大的不同点之一。

Stereo节点所在的目录下打开终端,然后输入如下内容(路径记得改成你的):

rosrun ORB_SLAM3 Stereo /root/Codes/ORB_SLAM3/Vocabulary/ORBvoc.txt /root/Codes/ORB_SLAM3/Examples/Stereo/EuRoC.yaml true

然后就可以启动节点了,如下。 就运行的效果而言,是和CMake的程序没有区别的。至此,我们就完成了双目ROS版本的ORB-SLAM3的运行。

5.总结

本篇博客主要从CMake普通版本和ROS版本两个方面介绍了ORB-SLAM3的编译和运行。相比于官方的文档,对其中可能遇到的问题进行了记录,并提出了解决方案,有一定参考价值。在之后的博客中会介绍如何运行ROS版的双目-IMU的ORB-SLAM3。正如前面提到的,官方示例中并没有这种配置,也就意味着我们需要参考已有内容自己实现。之后,在实现这个目标之后,会尝试使用真实的D435i传感器跑ORB-SLAM3,显然,利用自己的传感器跑又会遇到许多新的问题。这在之后的博客中再介绍。

本文作者原创,未经许可不得转载,谢谢配合

返回顶部