VINS-Mono笔记01_VINS-Mono的编译运行
本笔记记录在Ubuntu18.04下基于Ruroc数据集编译运行VINS-Mono项目的过程.
编译VINS-Mono
安装ROS
关于ROS安装的教程很多,随便找一篇照着做就行.为提升速度,可以将软件源换成国内源.
安装OpenCV,Eigen3和Ceres
OpenCV和Eigen3可以用apt
命令安装:
sudo apt -y install libopencv-dev # 安装OpenCV
sudo apt -y install libeigen3-dev # 安装Eigen3
Ceres不在apt仓库内,因此需要通过源码安装.主要步骤就是cmake
,再make && make install
,在网上随便搜一篇教程照着做就行.
创建ROS工作空间
所有ROS程序都必须放置在某个ROS工作空间(workspace)下,我们在家目录下创建一个名为catkin_ws
的ROS工作空间(ROS工作的空间名字可以随便取,一般约定俗成以_ws
结尾).
mkdir -p ~/catkin_ws/src # 递归创建工作空间及其下的src目录
cd ~/catkin_ws/src # 移动到工作空间下的src目录
catkin_init_workspace # 初始化工作空间
可以看到,在~/catkin_ws/src
路径下创建了一个CMakeLists.txt
文件.
一个典型的ROS工作空间目录结构如下:
catkin_ws/ # 工作空间
├── src/ # src目录放置源码
│ ├── CMakeLists.txt # 顶层CMakeLists.txt
│ ├── package_1/ # ROS包1
│ ├── package_2/ # ROS包2
│ └── package_n/ # ROS包n
├── build/ # build目录放置编译结果
├── devel/ # devel目录放置开发相关文件
│ └── setup.bash # 运行该脚本才能让该工作空间下的包被ROS发现
└── install/ # install目录放置安装相关文件
src
目录下存放的是我们写的源码,build
、devel
和install
目录都是ROS在编译过程中为我们生成的,不需要我们创建或修改.
导入ROS包
ROS程序是以ROS包(package)的形式组织的,一系列相关的程序(节点,node)被组织成一个ROS包,放置在工作空间的src
路径下.
VINS-Mono程序实际上包含了6个包: feature_tracker
, vins_estimator
, ar_demo
, benchmark_publisher
, camera_model
, pose_graph
.我们将整个VINS-Mono项目的代码放在catkin_ws/src
下,得到的目录结构如下:
catkin_ws/ # 工作空间
└── src # src目录放置源码
└── VINS-Mono
├── feature_tracker # ROS包feature_tracker,用于前段光流
├── pose_graph # ROS包pose_graph,用于位姿图优化
├── vins_estimator # ROS包vins_estimator,用于预积分
├── ar_demo # ROS包ar_demo,用于展示AR的demo
├── benchmark_publisher # ROS包benchmark_publisher,用于发布groun truth
├── camera_model # ROS包camera_model,用于提供相机模型
└── config # 配置文件目录,非ROS包
值得注意的是,与上文中ROS工作空间目录示意图略有不同的是,我们的ROS包并非放置在ROS工作空间
src
目录的直接下层,而是间隔了一层VINS-Mono
目录,这也是允许的.
ROS包的标志是其直接路径下package.xml
文件,该文件记载了该ROS包的信息,例如feature_tracker
包的package.xml
内容如下:
<?xml version="1.0"?>
<package>
<name>feature_tracker</name>
<version>0.0.0</version>
<description>The feature_tracker package</description>
<maintainer email="[email protected]">dvorak</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>camera_model</build_depend>
<build_depend>message_generation</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>camera_model</run_depend>
<run_depend>message_runtime</run_depend>
</package>
编译
在工作空间~/catkin_ws
下使用catkin_make
命令即可编译ROS包.
catkin_make # 编译当前工作空间下的所有ROS包
编译完成后,可以看到工作空间下多出了build
和devel
目录,目录结构如下:
catkin_ws/ # 工作空间
├── src
│ └── VINS-Mono
│ ├── feature_tracker
│ ├── pose_graph
│ ├── vins_estimator
│ ├── ar_demo
│ ├── benchmark_publisher
│ ├── camera_model
│ └── config
├── build/
└── devel/
└── setup.bash
其中devel
目录下有setup.bash
脚本,运行该脚本才能让工作空间下的包被ROS发现.因此每次运行VINS-Mono程序之前,都要先运行该setup.bash
脚本:
source ~/catkin_ws/devel/setup.bash
每次启动命令行都执行一遍上面命令比较麻烦,因此一般将上调命令加入到
~/bashrc
脚本的最后一行.~/bashrc
在每次启动命令行时自动执行,因此我们添加source ~/catkin_ws/devel/setup.bash
命令也被执行,从而使VINS-Mono的包被ROS发现.
运行VINS-Mono
运行ROS节点
ROS中,程序被称为ROS节点(node),不准确地说,一个包含main
函数的完整程序就是一个ROS节点.VINS-Mono程序包含很多ROS节点.
在运行ROS节点之前,应先启动一个命令行窗口,执行roscore
命令启动一个ROS核心,才能执行其他的ROS命令.
roscore # 启动一个ROS核心
运行ROS节点的命令格式如下:
rosrun ROS包名 ROS节点名 [参数1:=值1 参数2:=值2]
例如想要运行feature_tracker
包中的feature_tracker
节点,需要执行以下命令:
roscore&rosrun feature_tracker feature_tracker _config_file:=~/learning_ros_ws/src/VINS-Mono/config/euroc/euroc_config.yaml _vins_path:=~/learning_ros_ws/src/VINS-Mono
运行launch文件
一个完整的应用通常包含很多个ROS节点,一次使用rosrun
命令启动这些节点并配置参数较为麻烦,因此将一系列节点和运行参数写进launch
文件中,通过roslaunch
命令一次启动多个节点.
launch
文件一般放在ROS包下的launch
目录,例如使用VINS-Mono运行Euroc数据集对应的luanch
文件是euroc.launch
,位于vins_estimator
包下,其完整路径为~/catkin_ws/src/VINS-Mono/vins_estimator/launch/euroc.launch
.
launch
文件是以xml形式组织的,例如euroc.launch
文件内容如下:
<launch>
<!-- 全局参数config_path和vins_path -->
<arg name="config_path" default="$(find feature_tracker)/../config/euroc/euroc_config.yaml"/>
<arg name="vins_path" default="$(find feature_tracker)/../config/../"/>
<!-- feature_tracker包下的feature_tracker节点 -->
<node name="feature_tracker" pkg="feature_tracker" type="feature_tracker" output="log">
<param name="config_file" type="string" value="$(arg config_path)"/>
<param name="vins_folder" type="string" value="$(arg vins_path)"/>
</node>
<!-- vins_estimator包下的vins_estimator节点 -->
<node name="vins_estimator" pkg="vins_estimator" type="vins_estimator" output="screen">
<param name="config_file" type="string" value="$(arg config_path)"/>
<param name="vins_folder" type="string" value="$(arg vins_path)"/>
</node>
<!-- pose_graph包下的pose_graph节点 -->
<node name="pose_graph" pkg="pose_graph" type="pose_graph" output="screen">
<param name="config_file" type="string" value="$(arg config_path)"/>
<param name="visualization_shift_x" type="int" value="0"/>
<param name="visualization_shift_y" type="int" value="0"/>
<param name="skip_cnt" type="int" value="0"/>
<param name="skip_dis" type="double" value="0"/>
</node>
</launch>
运行roslaunch
文件的命令格式如下:
rosrun ROS包名 launch文件名
ROS会自动在第一次运行launch
文件的窗口调用roscore
(可以理解为每个launch
文件都有一个缺省的roscore
节点),因此只需要一个命令行窗口就可以运行所有相关的ROS节点.
例如,想要运行euroc.launch
,命令如下
roslaunch vins_estimator euroc.launch # 运行vins_estimator包下的euroc.launch文件
执行上述命令后,命令行窗口内输出一系列调试信息,说明运行成功.
想实时查看VINS-Mono运行过程中的状态,还需要运行vins_estimator
下的vins_rviz.launch
,命令如下:
roslaunch vins_estimator vins_rviz.launch # 运行vins_estimator包下的vins_rviz.launch文件
执行上述命令后,出现一个可视化窗口,说明运行成功.
准备数据
本次实验使用Euroc MAV数据集,需要下载bag
格式的数据集,放置在任意路径下,例如本次下载其中的MH_01_easy.bag
数据集,放置在~/Dataset/MH_01_easy.bag
路径下.
ROS bag是ROS支持的一种数据集格式,文件后缀名为.bag
,一个ROS bag中可以包含多组不同格式不同来源的数据,使用rosbag
命令对其进行操作.
rosbag play
命令用来播放ROS bag,也就是将ROS bag中的数据信息发送给ROS系统,从而发送给需要对应数据的ROS节点,rosbag play
的命令格式如下:
rosbag play bag路径
例如要播放本次实验下载的MH_01_easy.bag
,命令如下:
rosbag play ~/Dataset/MH_01_easy.bag # 播放对应路径下的MH_01_easy.bag数据集
在播放ROS bag数据集前应先运行上节提到的两个
launch
文件.
执行上述命令后,VINS-Mono开始运行,可视化界面显示实时信息,说明运行成功.
查看节点间的关系
ROS话题(ROS topic)是ROS中信息传递的最基本方式,节点之间通过发布和订阅一系列话题实现通信,上节的rosbag play
命令本质上是启动了一个/play
节点,发布对应的ROS话题.
使用rqt_graph
命令可以看到当前ROS系统中所有节点和话题,结果如下:
rqt_graph
下图中椭圆表示节点,方块表示话题.可以看到,/play
节点发布了/cam0
和/imu0
两个话题,分别对应相机和IMU数据,VINS-Mono的各节点订阅对应的话题,且VINS-Mono的节点间也是以话题的形式进行通信的.