今天要解析的代码是lins,对应论文《LINS: A Lidar-Inertial State Estimator for Robust and Efficient Navigation》,来自港科大刘明组,注释过的代码和论文链接附在文章最后。LINS这个名字与VINS相似,可以理解为Lidar-Inertial System的缩写。
lins也衍生自loam,算是在lego-loam基础上的改进版本,主要的改进在于:
查看cmake文件可以看到,代码主要分为4个功能模块:image_projection_node,lins_fusion_node,lidar_mapping_node,transform_fusion_node,其中第1、3模块基本上完全是从loam、lego-loam照搬过来的,我在之前SC-Lego-LOAM解析的文章中也详细分析过,本文就不再赘述,第4个模块并未起到实际作用。需要额外说明的是,由于第1、3模块基本直接从lego-loam搬过来的,坐标系的定义方式与lins本身是不同的,所以在调用1、3模块相关代码前和后都会对坐标系进行一次变换,这只是习惯问题,本文不做细致分析。剩下的篇幅,重点来分析下lins_fusion_node,即利用Iterative ESKF对lidar和imu数据进行紧耦合,实现一个鲁棒的激光里程计。
需要特别解释的是,论文中的状态都是相对位姿和误差,假设frame m和frame n是相邻两帧激光位姿,中间会夹杂40帧IMU数据(论文中雷达10Hz,IMU400Hz),即frame m+1, frame m+2, …, frame n-2, frame n-1, 当frame m+1等到来时都会累积相对于frame m的位姿,这也是本文中的“状态”和“状态误差”中的“状态”,当frame n到来会进行IEKF的更新,然后重新开始一个周期来进行IEKF的预测和更新。
接下来先上一个图,这是我总结的一个大概的思维导图(真没想到逼乎可以直接粘上来这个。。。)
lins_fusion_node思维导图
LinsFusion lins的回调函数接受激光角/面点,IMU等所需的消息并push到buffer里,它有一个重要的成员变量estimator真正的负责状态估计。IMU的回调函数imuCallback会触发状态估计performStateEstimation,最终调用estimator的一系列成员函数完成状态估计。执行performStateEstimation函数时存在几种不同的状态:
对于状态1:会依次调用processFirstPointCloud->processPCL->processFirstScan对estimator的预积分器preintegration和滤波器filter_进行创建和简单的初始化,也会将当前scan作为将来的target进行匹配;
对于状态2:会依次调用processPointClouds->processImu->processPCL->processSecondScan。其中processImu会通过estimator的preintegration_进行中值积分,计算出来一个第2帧和第3帧激光之间的相对位姿估计,然后processSecondScan会以preintegration_积分的结果为初值,以点云匹配的形式计算出第2帧和第3帧激光之间的相对位姿估计,然后对filter进行初始化,需要注意的是,滤波器中主要保存了两种信息:(1)相对位姿,两帧激光雷达数据中会存在40个IMU消息(论文中激光10Hz,IMU400Hz),每当IMU到来都会以前一个激光帧时刻的位姿为坐标系累积相对位姿;(2)相对位姿误差协方差。因此,滤波器的状态是相对位姿误差,需要至少存在两帧激光雷达数据才能真正完成初始化。余下的一些操作包括估计实话的roll和pitch,初始化全局位姿globalState_。
状态3才是正常的一般数据处理处理流程,lins的processPointClouds会对一组scan和IMU(40个左右)进行处理,分别通过调用estimator的processImu和processPCL->processScan来完成。
接下来正常情况下维持在状态3,循环执行filter_.predict和performIESKF进行卡尔曼滤波的预测和更新步骤。
到这里文章的主体部分已经结束了,比较简洁,只是对代码核心部分的结构和数据流走向进行了梳理,激光点云特征提取和建图都是在其他论文和代码里多次出现过的,本专栏其他文章也有过解析不再赘述。这篇文章是对自己学习的总结,也给想简单了解的读者提供一个引导,感兴趣的读者可以对照论文和代码再深入理解。文章写的比较仓促,代码也是分几次看完的,写注释的时候可能理解不够,如有错误和歧义的话,也欢迎大家留言指出讨论。
2022.6.5更新
周末又重新读了lins中状态估计部分lins_fusion_node代码,主要想对卡尔曼滤波器有更多的思考和理解,这里记录几点想法。
想當兵,卻因為下蹲不全過不瞭兵檢,明明身體很壯腳踝扭傷恢復得挺好,但就是蹲不下來深蹲推舉,腳後跟卻總是離地下蹲不全,...
具有濕組織粘附性的粘附性水凝膠已被廣泛用於傷口輔料、止血劑、可穿戴電子、藥物投遞系統和組織工程領域,由於其具有附著力...