一点Cartographer的调参心得:传感器篇 - 哔哩哔哩
Cartographer 的参数调整对建图和定位都有很大的影响,怎么调参在网上相关的资料也很多,官方也有文档介绍,不过我觉得都不够实用,因为大多都没有介绍调整这个参数需要出于什么而考虑,调整后又会产生什么影响。
最近无聊就写写文章记录一下我在工作中根据实际场景调参的过程,同时也帮助一下有需要的小伙伴们。
参数文件分别散落在 cartographer 和 cartographer_ros 两个项目里,小伙伴们可以自己搜索一下源码找到对应的位置。
Cartographer 接收的传感器数据主要就三种:激光雷达、IMU 和里程计。Cartographer 是以激光雷达是作为主导的传感器,另外两个都只是辅助。
实际使用中,最好三种传感器一起上,IMU 和里程计少了任意一个建图效果都会不咋地,这是由于 Cartographer 对多传感器融合的实现太过简单粗暴导致的。
这三种传感器的数据在前端和后端中都有着不同的作用,我只用过carto的2d slam,所以我也就只介绍2d的情况:
前端部分
激光雷达
点云直接用于生成 Submap,第一帧点云初始化第一幅 Submap,后续点云就和当前生成中的 Submap 进行 scan-to-map 的匹配,用于估算每一帧点云的位移。
匹配的位移也会用于下一帧点云匹配前的位姿推算,carto 会根据两次匹配位姿的距离和时间差估算角速度和线速度,用于计算下一帧点云可能的位置,新来的点云就直接在预估位置附近做匹配。
IMU
参与下一个时间点的位姿估算,当给 carto 输入 IMU 数据后,点云匹配前将会用IMU的角速度和匹配位姿的线速度来估算下一帧点云可能的位置。
里程计
也是参与下一个时间点的位姿估算,当提供里程计数据后,不再使用匹配位姿来估算线速度,而是直接用里程计的线速度和IMU的角速度来估算下一帧点云可能的位置。
后端部分
激光雷达
激光雷达在后端的作用主要是两个,一个是 scan-to-map 匹配做回环检测,一个是前端产生的匹配位姿之间的相对位姿作为约束参与后端的全局优化,优化的目的是为了尽可能消除累计误差。
IMU
2d slam 时 IMU 数据在后端没有任何戏份。
里程计
使用俩帧里程计数据的相对位姿作为约束参与后端优化,里程计数据短时间内必须要足够准确,不然得到的相对位姿误差大,会导致全局优化出来的地图效果更差。
下面就介绍一下这几个传感器的比较常用的参数配置和调整方式:
激光雷达
用于配置运动畸变矫正的 num_subdivisions_per_laser_scan 和 num_accumulated_range_data,num_subdivisions_per_laser_scan 用于指定将一帧点云切成 N 份,然后均匀估算每一份的时间戳,num_accumulated_range_data 又会将 N 份点云合并成 1 份,参数默认值都是 10。合并的过程中会根据每一份点云的时间戳估算它应该在的位置和角度。运动畸变矫正是非常依赖里程计和IMU的,里程计估算线速度,IMU 估算角速度,如果没有接入这两个传感器,或者其中一个的精度非常差,最好是把畸变矫正给关了,把两个参数设置成 1,不然矫正后会比不矫正的偏差还大。关闭运动畸变的话需要在建图时移动速度尽可能慢,让雷达扫描不会产生太大的畸变,从而减少累计误差提高建图质量。
TRAJECTORY_BUILDER_2D.min_range 和 TRAJECTORY_BUILDER_2D.max_range,用于限制点云的有效距离,最小距离一般是用来过滤掉雷达周围的遮挡物的,最大距离的配置就比较依赖实际环境的面积,max_range 这个配置不是越大越好的,大了会增加计算量,也会因为测量距离较远时噪声变大和点间距稀疏带来更多的累计误差,影响建图质量。可以在目标工作场景下录个包,反复测试观察不影响 scan-to-map 匹配的最小距离作为参数值,可以通过观察雷达移动后 carto 匹配的点云位置有没有做出相应的移动来判断。
voxel_filter_size 体素滤波的大小设置,体素滤波是用来降低点云密度的,限制两个点之间的最小距离,把值调大了可以降低计算量,但建图质量也会被降低,一般是设置成 0.025 或者 0.05,也就是两点之间间隔 2.5cm 或者是 5cm。
rangefinder_sampling_ratio 点云数据输入频率限制 ,一般维持在 12hz 左右的输入就好了,如果雷达的输出频率比较高,例如 30hz,那就可以将这个参数设置为 0.33,仅保留 33% 的输入,降低计算量,如果机器内存和算力充足,越大越好,这个自己根据实际情况调整。
里程计
use_odometry 打开里程计数据输入 ,这个没啥好说的,看前面介绍的数据作用就行了。
IMU
TRAJECTORY_BUILDER_2D.use_imu_date 打开 IMU 数据输入,也是没啥好说的😀。
最后再说点题外话,根据这些传感器的作用和参数配置方式,我们可以反推出 carto 对传感器的要求,例如 IMU 数据只使用了角速度来估计旋转运动,那我们可以选择对旋转有着高精度测量的任意惯性器件,线速度的测量精度可以不在意。里程计也是,只需要关注线速度的测量精度,这里的里程计不一定只能是轮式里程计,也可以是视觉 SLAM 框架输出的位姿作为里程计信息输入到 cartographer 里,或者是别的啥都行,只要是数据的格式和表现形式跟轮式里程计一样就可以了。