网上有很多ORB-SLAM的编译安装教程,我觉得大同小异,差不多都是按照GitHub源码中的README翻译过来的。当然,按照README一步步来做肯定是没有问题的,但是我觉得略微有些繁琐,所以我更喜欢按照自己的方式来。
ORB-SLAM1是依赖于ROS运行的,因为它的主程序中引用了ROS的头文件,必须通过订阅话题来实现图像的输入。其实程序本身相对比较独立,除了订阅一个sensor_msgs::Image类型的话题、发布一个sensor_msgs::Image类型的话题和一个visualization_msgs::Marker类型的话题,里面其他的任何算法跟ROS就没啥关系了。
ORB-SLAM2是不完全依赖ROS的,它有两个编译选项,对应两个脚本文件build.sh和build_ros.sh。编译前者你只能跑一些数据集,当然有能力的改改源码也是可以跑自己的设备的;编译后者则可以利用ROS很方便地接入自己的设备。ORB-SLAM2支持Monocular、Stereo、RGB-D相机,代码结构更加复杂,但条理依然很清晰。
ORB-SLAM官方主页:http://webdiis.unizar.es/~raulmur/orbslam/
ORB-SLAM1源码地址:https://github.com/raulmur/ORB_SLAM
ORB-SLAM2源码地址:https://github.com/raulmur/ORB_SLAM2
编译ORB-SLAM之前需要安装一些必要的依赖库,按照源码中的README操作即可。下面开始在ROS上编译ORB-SLAM1和ORB-SLAM2,步骤与官方教程不一样,在我这里没有问题,但不能保证都适用,注意我的编译环境为Ubuntu16.04(ROS-kinetic):
$ mkdir -p ~/SLAM/src
$ cd ~/SLAM/src
$ catkin_init_workspace
$ cd ..
$ catkin_make
$ echo "source ~/SLAM/devel/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
$ cd ~/SLAM/src
$ git clone https://github.com/raulmur/ORB_SLAM.git ORB_SLAM1
$ git clone https://github.com/raulmur/ORB_SLAM2.git ORB_SLAM2
虽然我们前面按照README安装了ORB-SLAM所有的依赖库,但编译过程中难免还是会遇到各种各样的问题,接下来根据我在编译过程中遇到过的问题列出以下修改意见:
(1)在ORB_SLAM1文件夹下有个manifest.xml文件,将里面的
这一行删掉或注释掉。
(2)打开ORB_SLAM1/src文件夹下的ORBextractor.cc文件,添加两个头文件:
#include
#include
修改以上两条的原因是ROS-kinetic版本自带OpenCV3 。
(3)打开ORB_SLAM1/Thirdparty/g2o/g2o/solvers文件夹下的linear_solver_eigen.h文件,找到typedef Eigen::PermutationMatrix
,将其改为typedef Eigen::PermutationMatrix
,原因是Ubuntu16.04安装的Eigen库与源码自带的g2o库产生了一些不兼容的问题。
(4)打开ORB_SLAM1文件夹下的CMakeLists.txt,在target_link_libraries()
中添加两个库文件:
/usr/lib/x86_64-linux-gnu/libboost_system.so
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so
(5)打开ORB_SLAM2/Examples/ROS/ORB_SLAM2文件夹下的CMakeLists.txt,在set(LIBS ...)
中同样添加上述的两个库文件。
修改以上两条的原因是编译过程中可能会遇到cmake找不到libboost_system.so和libboost_filesystem.so的情况,也许你不会遇到。当然,上面两个库的路径要根据自己的实际情况进行适当修改,可以通过$ locate libboost_system.so
来进行定位。
(1)编译ORB-SLAM1
$ cd ~/SLAM/src/ORB_SLAM1/Thirdparty/DBoW2/
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ make
$ cd ~/SLAM/src/ORB_SLAM1/Thirdparty/g2o/
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ make
$ cd ~/SLAM/src/ORB_SLAM1/
$ mkdir build
$ cd build
$ cmake .. -DROS_BUILD_TYPE=Release
$ make
(2)编译ORB-SLAM2
$ cd ~/SLAM/src/ORB_SLAM2/
$ chmod +x build.sh
$ ./build.sh
$ chmod +x build_ros.sh
$ ./build_ros.sh
编译ROS选项的时候均不需要设置ROS_PACKAGE_PATH,因为源码就在ROS的工作空间里。不出意外的话,编译可顺利通过!
第一步:当然是先运行$ roscore
啦!
第二步:解压ORBvoc.txt
$ roscd ORB_SLAM1
$ cd Data/
$ tar zxvf ORBvoc.txt.tar.gz
第三步:运行ORB_SLAM节点
$ roscd ORB_SLAM1
$ rosrun ORB_SLAM ORB_SLAM Data/ORBvoc.txt Data/Settings.yaml
这一步一定要在ORB_SLAM的包路径下执行,因为源码main.cc中有这么两句:
// Load Settings and Check
string strSettingsFile = ros::package::getPath("ORB_SLAM")+"/"+argv[2];
// Load ORB Vocabulary
string strVocFile = ros::package::getPath("ORB_SLAM")+"/"+argv[1];
在这一步之前你可能还需要干一件事,那就是修改Data文件夹下的Settings.yaml文件,因为里面有一些相机的内参等重要的参数设置。如果你要使用的相机内参跟它里面原来的参数不一致,是一定要改的!如果你的相机还没有标定,那么方法有很多,可以参考这篇博客:ROS 教程之 vision: 摄像头标定camera calibration,教你如何利用ROS标定相机。
现在你可以查看一下ROS的节点和话题情况,打开一个新的终端,按照下图中的命令依次运行:
显然,ORB_SLAM节点发布了两个话题/ORB_SLAM/Frame和/ORB_SLAM/Map,同时订阅一个话题/camera/image_raw。另外它还发布了一个 tf 变换,在这里暂时用不到,忽略掉。
第四步:运行RViz,订阅ORB_SLAM节点发布的两个话题
$ roscd ORB_SLAM1
$ rosrun rviz rviz -d Data/rviz.rviz
源码里这个rviz的默认配置文件中没有订阅/ORB_SLAM/Frame话题,我们打开rviz后可以手动添加上,然后保存配置,下次再打开就不用手动添加了。
第五步:启动相机节点,发布/camera/image_raw话题
如果还没有安装的话,运行命令:
$ sudo apt-get install ros-kinetic-usb-cam
然后随便找个地方新建一个launch文件用来启动usb_cam_node节点,不妨就在ORB_SLAM1文件夹下吧!新建一个文件,叫“usb_cam_node.launch”,然后粘贴以下代码:
"usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
<param name="video_device" value="/dev/video1" />
<param name="image_width" value="640" />
<param name="image_height" value="480" />
<param name="pixel_format" value="yuyv" />
<param name="camera_frame_id" value="usb_cam" />
<param name="io_method" value="mmap" />
from="/usb_cam/image_raw" to="/camera/image_raw" />
保存文件,然后运行命令:
$ roscd ORB_SLAM1
$ roslaunch usb_cam_node.launch
如何编写ROS相机节点,请参考我的这篇博客:用OpenCV编写一个ROS节点发布图像话题。按照上面的步骤编译成功后,新建一个my_nodes.launch文件,粘贴以下代码运行即可:
<launch>
<node name="cam_node" pkg="my_nodes" type="cam_node" output="screen" >
<param name="video_device" value="1" />
<param name="frame_rate" value="30" />
<remap from="/cam_node/image_raw" to="/camera/image_raw" />
node>
launch>
OK!当我们的相机节点一开始运行,ORB_SLAM节点就会订阅到/camera/image_raw这个话题,整个SLAM系统就有条不紊地运作起来啦!运行效果应该是这样的:
有了上面ORB-SLAM1的铺垫,现在跑SLAM2简直是信手拈来,打开三个终端,分别运行以下命令:
$ roscore
$ rosrun ORB_SLAM2 Mono ~/SLAM/src/ORB_SLAM2/Vocabulary/ORBvoc.txt ~/SLAM/src/ORB_SLAM2/Examples/ROS/ORB_SLAM2/Logitech.yaml
$ roslaunch my_nodes my_nodes.launch
这里的Logitech.yaml是我的配置文件。或者更方便的,我们可以写一个launch文件来启动这两个节点(ORB-SLAM1的也可以这样做),代码如下:
<launch>
<node pkg="ORB_SLAM2" type="Mono" name="Mono" output="screen"
args="/home/lbx/SLAM/src/ORB_SLAM2/Vocabulary/ORBvoc.txt
/home/lbx/SLAM/src/ORB_SLAM2/Examples/ROS/ORB_SLAM2/Logitech.yaml" />
<include file="$(find my_nodes)/launch/my_nodes.launch" >
include>
launch>
之前没怎么玩过Kinect,研究了一通,才知道还有一代与二代之分。
一代版本(Kinect V1)长这样:
二代版本(Kinect V2)长这样:
博主使用的是Kinect V1,这个在网上的资料不是特别多,推荐参考这两篇博客:Ubuntu14.04下 ROS indigo使用kinect 亲测好用,ORB-SLAM2 with Kinect V1。在此基础上,下面我要简单介绍一下Kinect V1的标定过程,因为这两篇博客中都没有提到(参考openni_launch/ Tutorials)。
在标定相机内参之前你应该事先准备一个棋盘格,比如我用的是一个11x8x0.03的棋盘格。现在开始标定RGB摄像头,运行以下命令:
$ roslaunch openni_launch openni.launch
$ rosrun camera_calibration cameracalibrator.py image:=/camera/rgb/image_raw camera:=/camera/rgb --size 11x8 --square 0.03
标定的时候要尽量保证它的四个指标都能变绿,这样标定出来的参数会更准确一点。等四个进度条都变绿了,点击“CALIBRATE”开始计算,完了以后点击“COMMIT”,标定参数就自动保存到默认路径了。通常在~/.ros/camera_info/文件夹下,你可以cd到这个文件夹看一下,里面有一个“rgb”开头的.yaml文件,是它没错了。
点击完“COMMIT”你会发现,那个标定节点已经自动退出了,紧接着我们在这个终端运行下条命令,开始标定红外摄像头:
$ rosrun camera_calibration cameracalibrator.py image:=/camera/ir/image_raw camera:=/camera/ir --size 11x8 --square 0.03
注意:标定红外摄像头时一定要遮住Kinect的红外发射器,不然图像会出现散斑!其余操作同上。
这个有点麻烦,改天再写,先把参考网址撂这儿:http://wiki.ros.org/openni_launch/Tutorials/ExtrinsicCalibration。
标定完Kinect相机后,复制一份ORB_SLAM2/Examples/RGB-D文件夹下的TUM1.yaml,重命名为kinect1.yaml,将里面的相机参数改为刚才标定的RGB相机的参数。然后在ORB_SLAM2/文件夹下新建一个kinect_orbslam2.launch文件,复制粘贴以下代码:
<launch>
<node pkg="ORB_SLAM2" type="RGBD" name="ORB_SLAM2" output="screen"
args="/home/lbx/SLAM/src/ORB_SLAM2/Vocabulary/ORBvoc.txt
/home/lbx/SLAM/src/ORB_SLAM2/Examples/RGB-D/kinect1.yaml" />
<include file="$(find openni_launch)/launch/openni.launch">
<arg name="depth_registration" value="true" />
<arg name="rgb_processing" value="false" />
<arg name="ir_processing" value="false" />
<arg name="depth_processing" value="false" />
<arg name="depth_registered_processing" value="false" />
<arg name="disparity_processing" value="false" />
<arg name="disparity_registered_processing" value="false" />
<arg name="hw_registered_processing" value="false" />
<arg name="sw_registered_processing" value="false" />
include>
launch>
运行kinect_orbslam2.launch,应该会出现下图所示的效果:
Kinect带着线走不远,但是感觉效果还是不错的,不需要初始化。
实验室有个ZED相机,本来想试试Stereo,无奈电脑不行,等有条件了再补。好了,先写到这儿吧! 此致 敬礼
[1] http://wiki.ros.org/openni_launch
[2] https://www.cnblogs.com/zengcv/p/6021512.html
[3] https://blog.csdn.net/wubaobao1993/article/details/53142795