【SLAM】在 ubuntu 18.04 arm 中以ROS环境编译与运行ORB_SLAM3

在ubuntu18.04arm中于ROS环境编译与运行ORB_SLAM3,并以TUM和EuRoC数据集测试了ROS下单目、双目和RGB-D运行。

1. 引言

在之前的博客中,已经介绍了基于虚拟机docker环境以及云端的AutoDL环境运行ORB_SLAM3的步骤。

在实际场景中,SLAM通常是需要在机器人平台上运行的,ROS就是一个比较常见的机器人开发平台,在ROS环境中运行,可以方便我们的SLAM系统与其他机器人功能模块(比如导航和路径规划)进行通信,而且在ros node模式下运行的SLAM更适合多机通讯环境,比如实现多机器人协同建图、机器人和PC交互等等功能。

ORB_SLAM3在本地运行的基础上,提供了在ROS中运行的机制,本文简述了如何在ubuntu 18.04 arm环境中安装ROS环境、编译ORB_SLAM3 ROS版本,以及用现有的数据集模拟摄像头信号输入来使用ORB_SLAM3的全流程。

本文示例环境:ubuntu 22.04 arm虚拟机下启动的ubuntu18.04 docker容器。

2. 安装ROS环境

参考【Linux】在ubuntu18.04arm中安装ROS环境一文进行安装,主要基于ROS官网的教程。

3. 编译ROS环境的ORB_SLAM3

本文撰写时UZ-SLAMLab/ORB_SLAM3的最新提交为2022年2月10日的4452a3c4ab75b1cde34e5505a36ec3f9edcdc4c4,后文的教程基于此提交点。

3.1. 编译命令

3.1.1. 先编译普通版本

本文不赘述安装ORB_SLAM3依赖项的步骤,您可以参考【SLAM】于ubuntu18.04上纯CPU运行GCNv2_SLAM的记录(ARM64/AMD64) | 慕雪的寒舍 一文中的依赖项安装步骤。参考博客里面的步骤安装opencv、eigen3、Pangolin6.0就可以了,不需要安装libtorch。

其中需要注意的是,如果你需要编译ROS的ORB_SLAM3,opencv不能安装3.4.5版本,必须安装3.2.0版本!好消息是,如果你是跟随者本站或者ROS官网的教程安装的ROS,那么opencv 3.2.0版本已经和ROS一起安装在你的系统里面了。

安装完毕依赖后,先以普通模式编译ORB_SLAM3,因为ROS版本依赖于普通版本才能进行编译,这一点必须要注意。

bash 复制代码
git clone https://github.com/UZ-SLAMLab/ORB_SLAM3.git ORB_SLAM3

cd ORB_SLAM3
chmod +x build.sh
./build.sh
3.1.2. 修改build_ros.sh脚本

编译完毕普通版本后,才可以执行build_ros.sh脚本。但是先别急,cat这个脚本,看看里面写了啥

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3# cat build_ros.sh 
echo "Building ROS nodes"

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

其中第一个命令就有问题了,最新版本的ORB_SLAM3源码里面,Examples路径下已经没有ROS目录了,这个目录现在是Examples_old/ROS/ORB_SLAM3

如果你没有注意这个问题就开始执行build_ros.sh脚本,问题就会出现,因为Examples/ROS/ORB_SLAM3目录当前不存在,该脚本实际上是直接在项目根目录下创建了build目录然后cmake开始编译的,编译的完全不是ROS版本。

这个脚本里面还有另外一个坑,那就是make -j后面没有写任何数字。这会导致make无休止地使用系统资源,直到把你的整个系统内存和swap都吃光光。根据我找到的博客,ORB_SLAM3的编译最多能吃掉16GB内存,完全是个洪水猛兽。

最开始我没有注意这个脚本,以为它没有任何问题,就直接执行了,最终在编译时遇到了如下错误。

复制代码
c++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-7/README.Bugs> for instructions.

这个错误就是因为系统没有资源了。开另外一个终端,再启动编译,你可以轻易地观察到编译是怎么把整个系统内存给吃光光的,最终物理内存和swap都没了,操作系统自然会kill掉编译进程,从而导致了上述报错。

如果你直接搜索"ORB_SLAM3编译失败"等字样,可能会搜到相关教程让你加大swap文件,这是一个可选项,但还不够可选,因为在我的测试中,即便再给出2GB的swap文件,编译依旧会因为内存不足而失败。下面给出新增swap文件的命令。

bash 复制代码
# 安装
apt install util-linux
# 分配2G
sudo fallocate -l 2G /swapfile
# 给予权限
sudo chmod 600 /swapfile
# 激活权限(执行了之后swap就生效了)
sudo mkswap /swapfile
sudo swapon /swapfile
# 不需要的时候,使用如下命令删除swap文件
swapoff -v /swapfile
rm /swapfile

实际上,在物理内存大于8GB的环境中不需要这么麻烦,前文提到了脚本里面make没有写线程数,解决办法就是修正这个脚本,首先是修正目录,其次是将make后面加上-j4来限制make使用的资源,这样就能绕过内存不足导致的编译错误了。修改后的脚本如下:

bash 复制代码
echo "Building ROS nodes"

cd Examples_old/ROS/ORB_SLAM3
mkdir build
cd build
cmake .. -DROS_BUILD_TYPE=Release
make -j4

如果你的环境物理内存低于8GB,可以考虑在加大swap文件的同时进一步减少make使用的线程数,比如make -j2

3.1.3. 编译ROS版本

修正了build_ros.sh脚本之后,就可以开始编译ROS版本了。

bash 复制代码
chmod +x build_ros.sh
./build_ros.sh

再次提醒,ROS版本的编译依赖于普通版本,需要先编译普通版本!

3.2. 编译期间遇到的各种问题

部分问题参考:记录配置ubuntu18.04下运行ORBSLAM3的ros接口的过程及执行单目imu模式遇到的问题

3.2.1. cmake错误ROS_PACKAGE_PATH

遇到的第一个错误应该是环境变量有关,编译ros版本的时候,需要将源码路径加入到环境变量中,才可以正常编译。

复制代码
CMake Error at /opt/ros/melodic/share/ros/core/rosbuild/private.cmake:99 (message):
  [rosbuild] rospack found package "ORB_SLAM3" at "", but the current
  directory is "/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3".  You should
  double-check your ROS_PACKAGE_PATH to ensure that packages are found in the
  correct precedence order.
Call Stack (most recent call first):
  /opt/ros/melodic/share/ros/core/rosbuild/public.cmake:177 (_rosbuild_check_package_location)
  CMakeLists.txt:4 (rosbuild_init)

在ORB_SLAM3项目根目录下执行如下命令即可

bash 复制代码
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:$PWD/Examples_old/ROS/ORB_SLAM3

修正之后即可正常开始编译

3.2.2. 头文件se3.hpp找不到

编译到30%的时候,会提示<sophus/se3.hpp>头文件找不到

复制代码
[ 30%] Building CXX object CMakeFiles/Mono_Inertial.dir/src/ros_mono_inertial.cc.o
In file included from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/Frame.h:30:0,
                 from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/KeyFrame.h:28,
                 from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/MapPoint.h:23,
                 from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/FrameDrawer.h:24,
                 from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/Viewer.h:23,
                 from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/Tracking.h:26,
                 from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/System.h:31,
                 from /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/ros_mono_inertial.cc:34:
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/../../../include/ImuTypes.h:29:10: fatal error: sophus/se3.hpp: No such file or directory
 #include <sophus/se3.hpp>
          ^~~~~~~~~~~~~~~~****

这个第三方库sophus已经在Thirdparty文件夹里面自带了,刚刚我们编译普通版本的时候,其实也已经编译好了这个第三方库了。要做的就是进它的目录make install安装一下。

bash 复制代码
cd Thirdparty/Sophus/build/
make install

安装以后就解决这个问题了。

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3# cd Thirdparty/Sophus/build/
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3/Thirdparty/Sophus/build# make install
[  8%] Built target test_sim2
[ 16%] Built target test_se2
[ 25%] Built target test_so3
[ 33%] Built target test_rxso2
[ 41%] Built target test_so2
[ 50%] Built target test_se3
[ 58%] Built target test_geometry
[ 66%] Built target test_rxso3
[ 75%] Built target test_sim3
[ 83%] Built target test_velocities
[ 91%] Built target test_common
[100%] Built target HelloSO3
Install the project...
-- Install configuration: "Release"
-- Installing: /usr/local/share/sophus/cmake/SophusTargets.cmake
-- Installing: /usr/local/share/sophus/cmake/SophusConfig.cmake
-- Installing: /usr/local/share/sophus/cmake/SophusConfigVersion.cmake
-- Installing: /usr/local/include/sophus/average.hpp
-- Installing: /usr/local/include/sophus/common.hpp
-- Installing: /usr/local/include/sophus/geometry.hpp
-- Installing: /usr/local/include/sophus/interpolate.hpp
-- Installing: /usr/local/include/sophus/interpolate_details.hpp
-- Installing: /usr/local/include/sophus/num_diff.hpp
-- Installing: /usr/local/include/sophus/rotation_matrix.hpp
-- Installing: /usr/local/include/sophus/rxso2.hpp
-- Installing: /usr/local/include/sophus/rxso3.hpp
-- Installing: /usr/local/include/sophus/se2.hpp
-- Installing: /usr/local/include/sophus/se3.hpp
-- Installing: /usr/local/include/sophus/sim2.hpp
-- Installing: /usr/local/include/sophus/sim3.hpp
-- Installing: /usr/local/include/sophus/sim_details.hpp
-- Installing: /usr/local/include/sophus/so2.hpp
-- Installing: /usr/local/include/sophus/so3.hpp
-- Installing: /usr/local/include/sophus/types.hpp
-- Installing: /usr/local/include/sophus/velocities.hpp
-- Installing: /usr/local/include/sophus/formatstring.hpp
3.2.3. OpenCV 版本不匹配

前文提到过,OpenCV必须安装 3.2.0 版本,是因为cv_bridge默认会指向ROS自带的3.2.0版本,而不是我们自己安装的其他版本,最终编译或者运行的时候就会导致链接错误或者coredump错误。

复制代码
/usr/bin/ld: warning: libopencv_core.so.3.2, needed by /opt/ros/melodic/lib/libcv_bridge.so, may conflict with libopencv_core.so.3.4

如果你已经安装了其他版本的opencv,需要删掉它们。从源码安装的话,直接进入opencv源码的build目录执行make uninstall就可以卸载掉自己安装的opencv。

删掉了之后就会发现系统里面只剩下和ros一起安装的3.2.0版本opencv了,应该是下载ros环境的时候自动安装的。

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3# pkg-config --modversion opencv
3.2.0

随后我们需要修改CMakeLists文件,让编译的时候使用opencv 3.2.0版本。首先是根目录下的CMakeLists,修改如下部分的版本号为3.2即可

cmake 复制代码
# ORB_SLAM3/CMakeLists.txt
find_package(OpenCV 3.2)
   if(NOT OpenCV_FOUND)
      message(FATAL_ERROR "OpenCV > 3.2 not found.")
   endif()

然后是Examples_old/ROS/ORB_SLAM3里面的CMakeLists文件,修改如下部分为3.2.0版本

cmake 复制代码
# ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/CMakeLists.txt
find_package(OpenCV 3.2.0 QUIET) # 修改为3.2.0
if(NOT OpenCV_FOUND)
   find_package(OpenCV 2.4.3 QUIET)
   if(NOT OpenCV_FOUND)
      message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
   endif()
endif()

接下来就要删除所有编译缓存,重新编译一遍。

复制代码
rm -rf Thirdparty/g2o/build/
rm -rf Thirdparty/DBoW2/build/
rm -rf Thirdparty/Sophus/build/
rm -rf Vocabulary/*.bin
rm -rf ./build
rm -rf Examples_old/ROS/ORB_SLAM3/build

注意普通版本也需要重新编译 !因为最开始编译的时候我的普通版本是基于opecv 3.4.5编译的,如果不重新基于opencv 3.2.0编译普通版本,编译ROS的时候就会提示libORB_SLAM3.so需要3.4.5版本的opencv才能正常链接,终究还是版本对不上。

3.2.4. AR代码错误(四处)

修复了opencv版本问题后,接下来就会遇到一堆由于Examples_old/ROS/ORB_SLAM3/src/AR路径下的代码问题导致的错误。如果你不需要使用MonoAR也就是单目AR 功能,可以直接注释掉CMakeLists文件里面71行的如下部分,跳过AR代码的编译。

cmake 复制代码
# ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/CMakeLists.txt
# Node for monocular camera (Augmented Reality Demo)
rosbuild_add_executable(MonoAR
 src/AR/ros_mono_ar.cc
 src/AR/ViewerAR.h
 src/AR/ViewerAR.cc
)

target_link_libraries(MonoAR
 ${LIBS}
)

注释掉之后,应该就可以成功编译其他部分了

复制代码
[rosbuild] Including /opt/ros/melodic/share/roslisp/rosbuild/roslisp.cmake
[rosbuild] Including /opt/ros/melodic/share/roscpp/rosbuild/roscpp.cmake
[rosbuild] Including /opt/ros/melodic/share/rospy/rosbuild/rospy.cmake
Build type: Release
-- Using flag -std=c++11.
-- Configuring done
-- Generating done
-- Build files have been written to: /work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/build
[  0%] Built target rospack_genmsg_libexe
[  0%] Built target rosbuild_precompile
[ 40%] Built target RGBD
[ 40%] Built target Stereo
[ 80%] Built target Mono_Inertial
[ 80%] Built target Stereo_Inertial
[100%] Built target Mono

如果你需要MonoAR,就需要上手改代码了 。参考github.com/UZ-SLAMLab/ORB_SLAM3/issues/442,依次修复问题。

这部分修改很杂,你可以直接根据我的提交记录来修改:Fix compile error of ROS AR, used opencv 3.2.0 for ROS compile. · musnows/ORB_SLAM3@4e1cbdb · GitHub


1)类型Sophus::SE3<float>cv::Mat不匹配

复制代码
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ros_mono_ar.cc: In member function 'void ImageGrabber::GrabImage(const ImageConstPtr&)':
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ros_mono_ar.cc:151:41: error: conversion from 'Sophus::SE3f {aka Sophus::SE3<float>}' to non-scalar type 'cv::Mat' requested
     cv::Mat Tcw = mpSLAM->TrackMonocular(cv_ptr->image,cv_ptr->header.stamp.toSec());
                   ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CMakeFiles/MonoAR.dir/build.make:198: recipe for target 'CMakeFiles/MonoAR.dir/src/AR/ViewerAR.cc.o' failed

修改ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ros_mono_ar.cc的151行,被注释掉的是源代码

cpp 复制代码
    // cv::Mat Tcw = mpSLAM->TrackMonocular(cv_ptr->image,cv_ptr->header.stamp.toSec());
    cv::Mat Tcw;
    Sophus::SE3f Tcw_SE3f = mpSLAM->TrackMonocular(cv_ptr->image,cv_ptr->header.stamp.toSec());
    Eigen::Matrix4f Tcw_Matrix = Tcw_SE3f.matrix();
    cv::eigen2cv(Tcw_Matrix, Tcw);

2)'eigen2cv' is not a member of 'cv' 错误

复制代码
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ros_mono_ar.cc:155:9: error: 'eigen2cv' is not a member of 'cv'
     cv::eigen2cv(Tcw_Matrix, Tcw);
         ^~~~~~~~
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ros_mono_ar.cc:155:9: note: suggested alternative: 'eigen'
     cv::eigen2cv(Tcw_Matrix, Tcw);
         ^~~~~~~~
         eigen

ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ros_mono_ar.ccORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ViewerAR.h顶部添加三个头文件

cpp 复制代码
#include <Eigen/Dense>
#include <opencv2/core/eigen.hpp>
#include <opencv2/opencv.hpp>

3)类型Eigen::Matrix<float, 3, 1>cv::Mat不匹配

复制代码
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ViewerAR.cc: In member function 'void ORB_SLAM3::Plane::Recompute()':
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ViewerAR.cc:530:42: error: conversion from 'Eigen::Vector3f {aka Eigen::Matrix<float, 3, 1>}' to non-scalar type 'cv::Mat' requested
             cv::Mat Xw = pMP->GetWorldPos();
                          ~~~~~~~~~~~~~~~~^~

修改ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ViewerAR.cc:530处代码

cpp 复制代码
// cv::Mat Xw = pMP->GetWorldPos();
cv::Mat Xw;
cv::eigen2cv(pMP->GetWorldPos(), Xw);

4)尾插错误 no matching function for call to 'std::vector<cv::Mat>::push_back(Eigen::Vector3f)'

这个问题也是类型不匹配

复制代码
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ViewerAR.cc: In member function 'ORB_SLAM3::Plane* ORB_SLAM3::ViewerAR::DetectPlane(cv::Mat, const std::vector<ORB_SLAM3::MapPoint*>&, int)':
/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ViewerAR.cc:405:53: error: no matching function for call to 'std::vector<cv::Mat>::push_back(Eigen::Vector3f)'
                 vPoints.push_back(pMP->GetWorldPos());
                                                     ^

修改ORB_SLAM3/Examples_old/ROS/ORB_SLAM3/src/AR/ViewerAR.cc:405的代码

cpp 复制代码
// vPoints.push_back(pMP->GetWorldPos());
cv::Mat WorldPos;
cv::eigen2cv(pMP->GetWorldPos(), WorldPos);
vPoints.push_back(WorldPos);

3.3. 成功编译

修改完毕上述四个问题后,就应该可以编译成功了。

编译完成后会多出很多可执行文件。

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3# ls
Asus.yaml  CMakeLists.txt  Mono  MonoAR  Mono_Inertial  RGBD  Stereo  Stereo_Inertial  build  lib  manifest.xml  src

注意这些可执行文件是不能直接运行的,因为它们是针对ROS设计的文件。

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3# ./Mono
[ERROR] [1739083807.698375008]: [registerPublisher] Failed to contact master at [localhost:11311].  Retrying...
^C
Usage: rosrun ORB_SLAM3 Mono path_to_vocabulary path_to_settings

4. 在ROS下运行项目

参考博客:ORB-SLAM3的CMake与ROS编译以及测试ORB SLAM 2 demo 复现(普通模式 + ROS 模式) - 简书

4.1. 下载TUM和EuRoC数据集

因为是在ROS环境下运行,所以数据集不能用之前下载的tgz格式的了,必须使用ROS专门的bag格式的数据集。

在TUM数据集的下载页面中,往下滑可以看到每个数据集的简单介绍,这里就能下载到bag格式的数据集。

下载完毕后,可以使用rosbag info命令查看数据集中有的topic信息:

  • Topic是一个命名的通信管道,用于在不同的ROS节点之间传递信息;
  • 每个Topic都有一个唯一的名称,节点可以通过这个名称来订阅这个topic的信息;
  • Topic中的数据以message的格式传输,message是ROS中定义好的数据结构,如 sensor_msgs/Imagegeometry_msgs/Pose 等;

举个例子,fr1/desk数据集的Topic信息如下,其中depth就是深度数据,rgb就是普通的彩色录像数据。

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3# rosbag info datasets/TUM/rgbd_dataset_freiburg1_desk.bag
path:         datasets/TUM/rgbd_dataset_freiburg1_desk.bag
version:      2.0
duration:     23.8s
start:        May 10 2011 20:44:09.56 (1305031449.56)
end:          May 10 2011 20:44:33.32 (1305031473.32)
size:         371.7 MB
messages:     19893
compression:  bz2 [1210/1210 chunks; 29.85%]
uncompressed:   1.2 GB @ 52.3 MB/s
compressed:   370.9 MB @ 15.6 MB/s (29.85%)
types:        sensor_msgs/CameraInfo         [c9a58c1b0b154e0e6da7578cb991d214]
              sensor_msgs/Image              [060021388200f6f0f447d0fcd9c64743]
              sensor_msgs/Imu                [6a62c6daae103f4ff57a132d6f95cec2]
              tf/tfMessage                   [94810edda583a504dfda3829e70d7eec]
              visualization_msgs/MarkerArray [f10fe193d6fac1bf68fad5d31da421a7]
topics:       /camera/depth/camera_info     595 msgs    : sensor_msgs/CameraInfo        
              /camera/depth/image           595 msgs    : sensor_msgs/Image             
              /camera/rgb/camera_info       613 msgs    : sensor_msgs/CameraInfo        
              /camera/rgb/image_color       613 msgs    : sensor_msgs/Image             
              /cortex_marker_array         2360 msgs    : visualization_msgs/MarkerArray
              /imu                        11815 msgs    : sensor_msgs/Imu               
              /tf                          3302 msgs    : tf/tfMessage

而给出的EuRoC双目数据集的Topic如下,有两个cam就对应了左侧和右侧的两个相机。

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3/datasets# rosbag info MH_01_easy.bag 
path:        MH_01_easy.bag
version:     2.0
duration:    3:06s (186s)
start:       Jun 25 2014 03:02:59.81 (1403636579.81)
end:         Jun 25 2014 03:06:06.70 (1403636766.70)
size:        2.5 GB
messages:    47283
compression: none [2456/2456 chunks]
types:       geometry_msgs/PointStamped [c63aecb41bfdfd6b7e1fac37c7cbe7bf]
             sensor_msgs/Image          [060021388200f6f0f447d0fcd9c64743]
             sensor_msgs/Imu            [6a62c6daae103f4ff57a132d6f95cec2]
topics:      /cam0/image_raw    3682 msgs    : sensor_msgs/Image         
             /cam1/image_raw    3682 msgs    : sensor_msgs/Image         
             /imu0             36820 msgs    : sensor_msgs/Imu           
             /leica/position    3099 msgs    : geometry_msgs/PointStamped

假设我们使用自己的摄像头的话,也是利用ROS的工具将我们摄像头的数据输入到一个Topic中,这样就可以供系统的其他组件,比如SLAM系统来读取,以此实现在ROS系统上硬件输入和软件的读取。这便是使用ROS模式和普通模式的最大区别,普通模式下我们必须要直接提供程序的数据输入源,才能让程序运行起来;而ROS模式下我们可以先把整个SLAM系统启动起来,再通过我们想要的方式往SLAM系统订阅的Topic里面喂数据即可。

4.2. 单目运行

刚刚我们下载的TUM fr1/desk的数据集,即可以用作RGB-D模式的输入,又可以做单目摄像头的输入,因为深度数据是独立于RGB单目数据的。

刚刚我们直接运行Mono的时候,就打印出了一个Usage

复制代码
root@ubuntu-linux-22-04-02-desktop:/work/ORB_SLAM3/Examples_old/ROS/ORB_SLAM3# ./Mono
[ERROR] [1739083807.698375008]: [registerPublisher] Failed to contact master at [localhost:11311].  Retrying...
^C
Usage: rosrun ORB_SLAM3 Mono path_to_vocabulary path_to_settings

我们要使用的就是这个命令,rosrun代表启动一个节点,ORB_SLAM3是我们当前使用的包名称,也就是CMakeLists里面注册的项目名称,Mono是我们要执行的可执行文件名称。后面的两个参数分别是词袋文件和相机的配置文件。

最终执行的命令如下,需要在两个终端中执行(在项目根目录执行)

bash 复制代码
# 打开终端A
roscore
# 打开终端B
rosrun ORB_SLAM3 Mono Vocabulary/ORBvoc.txt Examples_old/Monocular/TUM1.yaml

执行了之后,就会启动ORB_SLAM3的Map Viewer,此时是黑屏的,因为么有任何数据被送到ORB_SLAM3订阅的Topic中。

再新建一个终端,执行如下命令,将TUM数据集bag文件里面的Topic绑定到ORB_SLAM3订阅的Topic上,这样就能获取到数据了。

bash 复制代码
rosbag play \
	datasets/TUM/rgbd_dataset_freiburg1_desk.bag \
	/camera/rgb/image_color:=/camera/image_raw

其中,最后一个参数/camera/rgb/image_color:=/camera/image_raw指代将bag文件中的/camera/rgb/image_color绑定到/camera/image_raw上,后者就是ORB_SLAM3订阅的相机原始数据的Topic,相当于将bag中已有的图像数据重新喂给了我们的SLAM系统。

因为ROS的Topic机制,这种喂进去的数据集和接一个摄像头得到的实时数据,对于订阅这个Topic的SLAM系统而言是完全一样的!

执行这个命令后,就能在GUI里面看到相机的数据流和SLAM的建图了

4.3. RGB-D运行

RGB-D相机也是使用相同的命令来执行,先在另外一个终端执行roscore,然后执行如下命令

bash 复制代码
rosrun ORB_SLAM3 RGBD Vocabulary/ORBvoc.txt Examples_old/RGB-D/TUM1.yaml

刚启动的时候也是黑屏

再开另外一个终端,开始喂我们的数据集,这里用了两个:=号,分别绑定了原始的RGB相机数据到/camera/rgb/image_raw ,绑定了深度数据到/camera/depth_registered/image_raw

bash 复制代码
rosbag play \
	datasets/TUM/rgbd_dataset_freiburg1_desk.bag \
	/camera/rgb/image_color:=/camera/rgb/image_raw \
	/camera/depth/image:=/camera/depth_registered/image_raw

随后GUI里面也开始显示图像了

等运行结束后,会发现此时SLAM的建图结果是不对的,所有的点都在很小的一块区域中

作为对比,下图为本地虚拟机在普通模式下运行时的RGB-D建图结果,很明显和上图完全不一样。

这是因为Examples_old/RGB-D/TUM1.yaml数据配置有问题。在TUM官网上提到了这两个数据集在ROS和非ROS中是不一样的,实际上这个文件里面也有注释

yaml 复制代码
# Deptmap values factor 
DepthMapFactor: 5000 # 1.0 for ROS_bag

官网说明:cvg.cit.tum.de/data/datasets/rgbd-dataset/file_formats#intrinsic...

Color images and depth maps

We provide the time-stamped color and depth images as a gzipped tar file (TGZ).

  • The color images are stored as 640x480 8-bit RGB images in PNG format.
  • The depth maps are stored as 640x480 16-bit monochrome images in PNG format.
  • The color and depth images are already pre-registered using the OpenNI driver from PrimeSense, i.e., the pixels in the color and depth images correspond already 1:1.
  • The depth images are scaled by a factor of 5000, i.e., a pixel value of 5000 in the depth image corresponds to a distance of 1 meter from the camera, 10000 to 2 meter distance, etc. A pixel value of 0 means missing value/no data.

这里是深度值的校正系数(factor),使用时的计算公式为Z = depth_image[v,u] / factor,在ROS中要把它改成1才可以。

yaml 复制代码
factor = 5000 # for the 16-bit PNG files
factor = 1    # for the 32-bit float images in the ROS bag files

将DepthMapFactor修改为1.0之后的建图就正常一些了

4.4. 双目运行

下载EuRoC对应的rosbag:MH_01_easy.bag,上文已经给出过该数据集对应的Topic了,其中要用到的 Topic 是左右两个摄像头的数据 /cam0/image_raw/cam1/image_raw。ORB_SLAM3 中双目 Stereo 接收的 Topic 分别为 /camera/left/image_raw/camera/right/image_raw,因此在运行时也需要绑定一下 Topic。

复制代码
topics:      /cam0/image_raw    3682 msgs    : sensor_msgs/Image         
             /cam1/image_raw    3682 msgs    : sensor_msgs/Image         
             /imu0             36820 msgs    : sensor_msgs/Imu           
             /leica/position    3099 msgs    : geometry_msgs/PointStamped

双目的rosrun命令最后多了一个bool类型参数do_rectify,含义为是否进行矫正,根据需要选择true或false。

复制代码
Usage: rosrun ORB_SLAM3 Stereo path_to_vocabulary path_to_settings do_rectify

执行如下命令,先启动Stereo双目模式下的SLAM,然后开始播放数据集,同样是使用:=分别绑定左侧和右侧两个摄像头的数据。

bash 复制代码
# 终端a
roscore
# 终端b
rosrun ORB_SLAM3 Stereo Vocabulary/ORBvoc.txt Examples_old/Stereo/EuRoC.yaml true
# 终端c
rosbag play MH_01_easy.bag /cam0/image_raw:=/camera/left/image_raw /cam1/image_raw:=/camera/right/image_raw

也是成功运行起来了

5. The end

本文介绍了如何在ROS环境下编译ORB_SLAM3,并使用TUM和EuRoC数据集测试单目、双目、RGB-D三种模式在ROS下运行的效果。希望对你有帮助!

更新:ORB_SLAM2的ROS运行命令和本文记录的完全一致,只需要把rosrun里面的包名改成ORB_SLAM2就可以了。下图是在ROS模式下运行ORB_SLAM2的RGB-D的截图。

相关推荐
xq5148631 小时前
Linux系统下安装mongodb
linux·mongodb
柒七爱吃麻辣烫1 小时前
在Linux中安装JDK并且搭建Java环境
java·linux·开发语言
孤寂大仙v1 小时前
【Linux笔记】——进程信号的产生
linux·服务器·笔记
深海蜗牛2 小时前
Jenkins linux安装
linux·jenkins
愚戏师2 小时前
Linux复习笔记(三) 网络服务配置(web)
linux·运维·笔记
JANYI20182 小时前
嵌入式MCU和Linux开发哪个好?
linux·单片机·嵌入式硬件
熊大如如3 小时前
Java NIO 文件处理接口
java·linux·nio
晚秋大魔王3 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos
农民小飞侠3 小时前
ubuntu 24.04 error: cannot uninstall blinker 1.7.0, record file not found. hint
linux·运维·ubuntu
某不知名網友3 小时前
Linux 软硬连接详解
linux·运维·服务器