SLAM——拆解LIO-SAM(一)
本文为拆解LIO-SAM代码的第一部分。
Image Projection
LIO-SAM的lidar odometry部分与LeGO-LOAM是类似的。在LeGO-LOAM中,会把点云投影到range image上,进行ground提取,我们先来看一下这部分的内容。
range image的行数取决于雷达的线数,而列数取决于雷达的水平分辨率,在lio-sam中为1800。Image Projection是一个预处理的过程。下面是点云投影的代码:
1 | void projectPointCloud() |
可以看到,在投影过程中可能会出现多个点投影到一个pixel上的情况,这时候我们直接忽略后来的点。在投影过程中,还会对点云进行去扰动,也就是下面要说的内容。
Get Undistorted Points
在之前的介绍中了解到了,由于雷达的测距原理,当雷达运动时,雷达的点是会有扰动的。在A-LOAM中,去除distortion使用的是球面线性差值(旋转)以及(平移)线性差值,假设在扫描一圈过程中雷达的运动是匀速的。但是实际上往往并非如此,有了IMU数据,我们可以使用IMU的状态来直接估计各个时刻的相机的transforamtion,从而直接进行去扰动(在计算机中)。
1 | PointType deskewPoint(PointType *point, double relTime) |
具体的做法是,点云中的每个点,记录的是捕获到该点的时间到捕获第一个点的时间间隔,因此根据该点的时间戳来找到IMU的状态。由于IMU的时间戳与点的时间戳不会严格一样,因此我们可能遇到两种情况:
- 点的时间戳在两个IMU状态之间,则用这两个IMU的状态进行插值;
- 点的时间戳是大于最新的IMU状态的时间戳,则直接用离得最近的IMU状态。
具体实现如下:
1 | void findRotation(double pointTime, float *rotXCur, float *rotYCur, float *rotZCur) |
点云提取
接下来的操作是提取出可用的点,存储range image,并且根据所属的SCAN来进行划分。可以看到这里的startRingIndex与endRingIndex与A-LOAM中一致,都忽略了两端的部分点:
1 | void cloudExtraction() |
最后就是将整理后的点(论文中称为segmented points)发布出去了。