LOAM论文介绍与A-LOAM代码简介

一、前言

LOAM[1]是Ji Zhang于2014年提出的使用激光雷达完成定位与三维建图的算法,即Lidar Odometry and Mapping。之后许多激光SLAM算法借鉴了LOAM中的一些思想,可以说学习LOAM对学习3D激光SLAM很有帮助。本文对LOAM算法,以及简化版的开源代码A-LOAM进行简单介绍。

二、LOAM算法

2.1 系统整体架构

LOAM主要包含两个模块,一个是Lidar Odometry,即使用激光雷达做里程计计算两次扫描之间的位姿变换;另一个是Lidar Mapping,利用多次扫描的结果构建地图,细化位姿轨迹。由于Mapping部分计算量较大,所以计算频率较低(1Hz),由Mapping校准细化Odometry过程中计算出来的轨迹。

2.2 Lidar Odometry部分

Lidar Odometry是通过Lidar的两次扫描匹配,计算这两次扫描之间Lidar的位姿变换,从而用作里程计Odometry。既然提到了两次扫描的匹配,自然而然想到了经典的ICP算法。然而LOAM并没有采用全部的激光点进行匹配,而是筛选出了两类特征点,分别是角点和平面点。

所谓角点,是当前激光扫描线束上曲率较大的点;而平面点,即曲率较小的点。在匹配时,首先提取当前扫描中的角点和平面点,对于角点,可以认为是物理世界中直线元素的采样,所以计算到上一次扫描中对应直线的距离;而对于平面点,认为是物理世界平面元素的采样,所以计算到上一次扫描中对应平面的距离。通过不断优化,使距离最小,从而得到最优的位姿变换参数。

2.2.1 角点到直线距离的计算

计算角点到对应直线距离时,需要确定对应直线的方程,才能够计算距离。作者认为,可以有如下假设:角点是雷达某个线束与物理世界两个平面夹角相交时的采样,那么这个线束相邻的雷达扫描线束也会与这个平面夹角相交,所以这个平面夹角的直线可以用前后两次扫描的角点进行标识。

图:两种特征点提取示意

具体而言,当获得当前某一个角点时,首先根据假设的运动参数(上一次运动参数作为这一次优化的初始),计算这个角点在上一次扫描时的坐标,之后查找上一次扫描中最近邻的角点,并在相邻的雷达扫描线束中搜索最近的角点,从而得到了直线方程,便能够计算点到之间距离。

2.2.2 平面点到平面距离的计算

计算平面点到对应平面距离时,也需要首先拿到平面的方程,即平面上一点与平面的法向量。与角点对应直线搜索方式类似,首先找上一次扫描中最近邻的平面点,之后在同一个扫描线数和不同的线束上各提取一个平面点,这样共得到了3个不共线的平面点,唯一确定了平面,从而计算平面点到平面的距离。

2.2.3 一些其他细节

a) 在角点和平面点的选择上,为了使分布更加均匀,通常将激光雷达一圈的扫描均匀分成几个部分,分别在每个部分中提取曲率最大(角点)和最小(平面点)的几个点。

b) 在激光雷达的一次扫描过程中,由于运动,采集到的点云会有运动畸变,所以在LOAM中点云会通过预估的运动参数去畸变进行对齐

c) 雷达扫描到的一些数据点是不稳定的,作者认为有两种不稳定数据点,如下图所示。一种是采集面与扫描面基本平行,另一种是被遮挡。在获得一次激光雷达扫描的点云后,这两种不稳定点会被首先去除。

图:两种不稳定点示意

2.3 Lidar Mapping部分

Mapping部分的意义是,通过与多次扫描构成的地图进行匹配,得到Lidar Odometry中利用两帧之间计算位姿产生的漂移,从而对轨迹进行细化。如下图所示:

图中,分别表示前k次扫描的轨迹(蓝色曲线)和地图(黑色直线),而最新的轨迹为。将k+1次雷达扫描到通过Odometry得到的映射到地图坐标系中,得到了未经校准的地图,可以看出存在一定的误差,并没有与原有地图对齐。此时通过一次Lidar Mapping,可以消掉这部分的误差,从而校准位姿参数。

图片来源[2]

如上图所示,在Mapping时,LOAM维护了一个以当前位置为中心,具有多个block的子地图,论文中指出这个子地图是10m的立方体。当Lidar采集到的点落入到这个子地图的某些block时,将从这个子地图提取出去对应的block,然后在这些block中像特征点提取那样,提取当前扫描中角点和平面点近邻的对应点,但有不同之处,并不像第2小节那样提取2个近邻角点确定直线或者3个平面点确定平面,而是提取更多的点进行拟合,因为子地图是多次扫描构成的结果。

对于当前扫描的一个角点,提取对应子地图中多个近邻角点,通过奇异值分解求出这些角点的主方向,从而的到直线方程,从而计算点到直线距离;对于平面点,通过寻找最小特征值对应的向量得到拟合平面的法向量,从而计算点到平面距离。再进行优化,得到对齐扫描与子地图的位姿纠正参数,之后将原有的轨迹进行纠正,便得到了细化的轨迹。

2.4 补充说明

LOAM一文中提出,可以通过IMU进行辅助。所谓“辅助”就是在激光雷达两次扫描之间,利用IMU得到较为准确的变化轨迹,从而进行点云畸变的去除,从而不需要靠上次扫描获得的运动参数插值对这次的畸变进行去除,能够提升精度。但IMU的数据并没有参与到优化当中,所以IMU在LOAM算法中只起到了辅助作用,而后续一些其他3D激光雷达算法,例如LINS[3],Lio-mapping[4]和LIO-SAM[5]等,利用IMU进行了紧耦合的优化,取得了更好的效果。

3. A-LOAM代码

LOAM的作者曾经开源了LOAM的代码,但由于某些原因又取消了开源,现在网上也流传着一些当时的片段或者牛人的实现。而A-LOAM是LOAM的一个简化版本,去掉了IMU以及一些其他细节,采用了Eigen,ceres等替代了原有LOAM代码中的手动实现,非常适合学习LOAM思想,也适合新手入门3D激光SLAM。A-LOAM的链接是:https://github.com/HKUST-Aerial-Robotics/A-LOAM

3.1 代码概览

A-LOAM代码通过ROS运行,主要有3个节点,分别是:ascanResigtration, alaserOdometry和alaserMapping,对应特征点提取、里程计计算和mapping细化三部分。整体的结构如下:

截图来源[6]

ascanResigtration:处理Lidar输入的点云,提取并发布角点、平面点以及简单处理后的完整点云;

alaserOdometry:接收特征点,计算位姿参数(轨迹)并发布

alaserMapping:接收Lidar的点云与Odometry计算的轨迹,进行细化,得到精确的轨迹和地图并发布

3.2 代码学习资料

由于代码部分内容较多,不方便展开详细介绍。网上资料较多,给出一些参考资料供大家自行学习。

LOAM中文注释版:https://github.com/cuitaixiang/LOAM_NOTED

LOAM笔记及A-LOAM源码阅读[6]:https://www.cnblogs.com/wellp/p/8877990.html

LOAM代码解析:https://blog.csdn.net/liuyanpeng12333/article/details/82737181

ALOAM试跑及程序注释:https://blog.csdn.net/unlimitedai/article/details/105711240

注意有些注释的是LOAM,有些是A-LOAM,基本上LOAM的注释涵盖了A-LOAM

参考文献

1. J. Zhang and S. Singh, "Visual-lidar odometry and mapping: low-drift, robust, and fast," 2015 IEEE International Conference on Robotics and Automation (ICRA), Seattle, WA, 2015, pp. 2174-2181, doi: 10.1109/ICRA.2015.7139486.

2. https://www.cnblogs.com/wellp/p/8877990.html

3. LINS: A Lidar-Inertial State Estimator for Robust and Efficient Navigation

4. Tightly Coupled 3D Lidar Inertial Odometry and Mapping

5. LIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping

6. https://www.cnblogs.com/wellp/p/8877990.html