目前网上有很多分析文章,但是都只是一些比较基础的原理分析,而且很多量,虽然有推倒,但是往往没有讲清楚这些量是什么,为什么要有这些量,这些量是从哪来的,也没有刷通整个代码,或者太简练了,对新手不友好。这一次我计划从原理/代码一步步刷通整个VINS,并且说清楚代码中遇到的每一个数据结构对应的作用是什么。vins系列可以说是vio或者是SLAM传感器融合的必读经典巨作,希望你能从我的分享中有所收获。
github官方上开源了VINS-mono,VINS-Fusion和VINS-mobile,还有另一个VINS-course是贺一家基于VINS-MONO的手写后端版(不用ceres/ROS)的代码,这个代码对VINS的理解,尤其是后端的理解非常有帮助。
后续有时间的话,我会写一下vins-fusion的全流程解析。实际上,mono和fusion的区别不是很大,如果mono彻底明白了,fusion(的主流程也)很好理解的。
官方链接:vins-mono, vins-fusion, vins-mobile
我的github请点击此处,对vins-mono进行了一些小的修改,修改的地方请见此处的介绍。另外,我根据vins-mono开发了一个双目vio系统,感谢沈老师课题组的开源。
原创内容,转载请先与我联系并注明出处,谢谢!
【SLAM】VINS-MONO解析——综述
【SLAM】VINS-MONO解析——feature_tracker
【SLAM】VINS-MONO解析——IMU预积分
【SLAM】VINS-MONO解析——vins_estimator
【SLAM】VINS-MONO解析——初始化(理论部分)
【SLAM】VINS-MONO解析——初始化(代码部分)
【SLAM】VINS-MONO解析——后端优化(理论部分)
【SLAM】VINS-MONO解析——后端优化(代码部分)
【SLAM】VINS-MONO解析——sliding window
【SLAM】VINS-MONO解析——回环检测
【SLAM】VINS-Fusion解析——流程
【SLAM】VINS-MONO解析——对vins-mono的修改使流程逻辑更清晰
【SLAM】VINS-MONO解析——基于vins-mono的slam系统开发
【SLAM】面试常见问题
原论文:
在正常运行过程中,初始化只进行一次。前端负责不断地提取特征点发给后端;后端负责IMU数据采集,预积分和优化/滑窗等操作。前端和后端在运行过程中不断地循环。
这个系统包括以下几个过程:特征提取与发布;IMU提取与预积分;初始化;滑窗与优化;回环检测。
代码主要包括3个node:feature_tracker,vins_estimator,pose_graph,其中feature_tracker仅负责特征点提取和发布,pose_graph关键帧的选择/位姿图建立/回环检测,而vins_estimator的内容最多了,包含了初始化,滑窗,优化等后端内容和IMU预积分等前端内容,并且在这个结点里分出了2个线程。
一般来讲,一个标准的SLAM系统是前后端分离的,如下图所示,
而VINS系统,他的前端仅包括光流计算;初始化等工作都放在vins_estimator里面了。
我的理解它之所以这么做,是因为IMU的数据获取如果放在前端,预积分完了之后还需要advertise到ROS系统里,让后端接收,与其这样,还不如让后端直接接收IMU数据就在后端处理了,减少通信过程。
启动VINS系统时,首先source一下bash文件,roscore,然后就是启动lauch文件了,它们包括:
roslaunch vins_estimator euroc.launch
roslaunch vins_estimator vins_rviz.launch
rosbag play YOUR_PATH_TO_DATASET/MH_01_easy.bag
首先看一下euroc.launch文件的内容,它在source/vins_estimator/launch目录下。
2.1.1 launch文件内的局部变量配置
<arg name="config_path" default = "$(find feature_tracker)/../config/euroc/euroc_config.yaml" />
<arg name="vins_path" default = "$(find feature_tracker)/../config/../" />
这里定义了两个path,而这两个path在代码中大量出现,第一个是config_path,即配置文件的路径。后面内容的意思是要想找到config_path的路径,首先先找到find feature_tracker所在路径,然后返回上一层目录,再找到config/euroc文件夹下的euroc_config.yaml配置文件,里面定义了ROS topic,相机参数,特征提取的极限值,IMU参数。
然后就是vins_path,基本上所有的程序都是基于这个路径,它是feature_tracker的上一层。
2.2.2 node结点的定义
就以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_pose多了4个变量的定义:
<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" />
visualization_shift_x和visualization_shift_y表示在进行位姿图优化后,对得到的位姿在x坐标和y坐标的偏移量(一般都设为0);
skip_cnt在pose_graph_node的process()中,表示每隔skip_cnt个图像帧才进行一次处理;
skip_dis也在pose_graph_node的process()中,目的是将距上一帧的时间间隔超过SKIP_DIS的图像创建为位姿图中的关键帧。
打开rviz进行可视化。
<launch>
<node name="rvizvisualisation" pkg="rviz" type="rviz" output="log" args="-d $(find vins_estimator)/../config/vins_rviz_config.rviz" />
</launch>
看到了一个非常好的文章,https://blog.csdn.net/Hanghang_/article/details/104535370,虽然目前阅读量不高,但是写的真好,我就不再重复写了,这里附上链接。
《VINS-Mono: A Robust and Versatile Monocular Visual-Inertial State Estimator》 秦神
《从零开始手写VIO》贺神,高神,崔神;
《VINS论文推导及代码解析》崔神;
《主流VIO技术综述及VINS解析》崔神;
《因子图的理论基础》董靖博士;
《SLAM十四讲》高神;
https://blog.csdn.net/qq_41839222/article/details/85793998 Manii;
《古月 · ROS入门21讲》古月神