Loam算法详解(配合开源代码aloam)

简介: Loam算法详解(配合开源代码aloam)

LOAM算法是激光slam中一个经典的开源框架,结合qin tong 博士的开源代码a-loam,对其原理及代码实现简要介绍如下:

LOAM算法的总体框架如下图所示:

除了左侧的硬件采集数据之外,LOAM算法本身主要包括图中标记的-四个部分。该算法的关键想法是把实时定位与测图这一同时寻找优化大量变量的复杂问题进行区分,通过两个算法来进行解决。首先,使用一个高频、低精度的里程计来估计LiDAR的位姿,并以此结果去除实验过程中产生的运动畸变(假设为匀速运动)。另外,使用一个低频、高精度的里程计算法来改善LiDAR位姿的精度,并输出全局坐标系下的地图。

1 LiDAR硬件

LiDAR硬件在采集过程中不断发布点云数据(10 HZ),以符号image.png表示在第K帧接收到的点云数据。

L是局部激光坐标系,坐标原点在Lidar的几何中心,以符号 image.png表示在第K帧中的i点在局部坐标系下的坐标。

W是全局坐标系,坐标原点在Lidar的起始位置,以符号 image.png表示在第 K帧中的 i点在全局坐标系下的坐标。

2 Point Cloud Registration

这一部分中从LiDAR硬件中接收原始点云数据,接着进行预处理(去除噪声点、无效点)并按照扫描线号进行区分,存储在一个vector中。随后,对点云数据进行处理,发布sharp、less_sharp、flat、less_flat四种类型的特征点,如下图中所示:

分别介绍LiDAR点云预处理与特征点提取两部分内

2.1 LiDAR点云预处理

传感器获得的数据可能在一些点的坐标中为NaN(不是数)值, 一个NaNs表明测量传感器距离到该点的距离值是有问题的,可能是因为传感器太近或太远,或者因为表面反射。那么当存在无效点云的NaNs值作为算法的输入的时候,可能会引起很多问题,使用PCL自带的函数进行去除。

随后,去除原始数据中距离很近的点,即相邻点间小于仪器测量的分辨率,这里设置MINIMUM_RANGE为0.1 m。

进行上述处理后,计算每个点的scanID并存储在对应的laserCloudScans变量中。

此外,还计算了当前点在一帧数据中的相对时间(时间比例),存放在intensity中(后续修正运动畸变时使用)。

2.2 提取特征点

在文章中描述了通过公式(1)来描述局部表面的平滑程度,其中S表示选取的一个周围点集,image.png表示当前点,image.png 表示近邻点。

若c值较大,则代表当前点与周围点的差距较大,曲率较高,代表为一个边缘点(也就是代码中的sharp点)。

若c值较小,则代表当前点与周围点的差距较小,曲率较低,代表为一个平面点(也就是代码中的flat点)。

通过如下代码计算公式(1),当前点的前后5个点组成点云集合S。

在选择特征点的过程中,我们还想让其均匀分布,所以文章中计划把每个扫描分为4个部分(代码中分为了6个部分),同时每个子集区域中选取2个sharp点和4个flat点。

此外,为了避免选中不稳定的特征点,作者还讨论了下图中的两种情况要进行避免。1)左图(a)中的B点在一个几乎与激光束平行的表面上。2)右图(b)中的A点在被遮挡区域的边缘。

3 Lidar odometry

3.1 寻找特征点对应关系

假设一个扫描k的开始时间戳为 t k  ,在第 k帧扫描结束接收到的点云为 P k(左侧第一条蓝线),其被投影到image.png 时间戳,用 image.png表示(即中间的绿线),同时在下一个扫描k+1中获取的数据为 (图中的橙线)。

(注意:由于假设为匀速运动,所以上图中可以用直线来表示每一帧扫描的点云数据。)

现在,假设我们有了和 P(k+1)两个点云数据集,基于此来寻找两个点云数据之间的对应关系。

首先,对P(k+1) 采用2.2节中提取特征点的方法找到两个特征点集,边缘点 E ( k + 1 )和平面点 H(k+1)。其次,对进行kd-tree索引,并在 中找到每个边缘点对应的边缘线(两个点,左图(a))与每个平面点对应的面片(三个点,右图(b))。

利用向量叉乘,获取点 i到直线ij的距离,以及点 i到平面ljm的距离。计算公式分别为:

前述假设LiDAR在一个扫描中角速度和线速度均为匀速运动,所以能够对计算出的位姿进行线性插值。假设image.pngimage.png两帧点云数据之间的位姿变换(6-DoF),给定一个点i , image.png,其获取的时间戳为image.png之间的变换为image.png并可以通过下式进行计算。

在每一次迭代过程中均把 P ( k + 1 )中的点i投影到该帧数据的起始点 t ( k + 1 ),然后再与 P k 中的点进行匹配。

假设 image.png为投影之前的i点坐标, image.png 为投影到起始点 t ( k + 1 )之后的i点坐标,则两者之间存在如下关系。

综合考虑前述的公式2与公式3,得到以下公式9与公式10:

综合公式9与公式10,得到:

式11中每一行均为一个特征点及对应的边缘线或平面面片,对公式11中的非线性函数进行优化,不断迭代使得d dd最小。

3.2 Lidar odometry算法总结

Lidar odometry算法如下所示,以上一帧点云image.png,逐渐增长的点云P(k+1),以及上一次迭代计算的位姿参数T(k+1)作为输入(如果是一个扫描的开始则设置为0)。接着,从P

(k+1)中提取边缘点E

(k+1)和平面点 H(k+1),对于每个边缘点/平面点,在上一帧点云Pk中找到其对应的边缘线/面片,建立公式11中的非线性函数,并进行优,若迭代达到收敛则输出,若达到了扫描的终点则输出 image.pngimage.png

4 Lidar Mapping

第3节中的里程计高频、低精度运行,其输出的位姿参数还需要进一步在后续的mapping中进行优化。

Mapping算法在每个扫描结束才运行一次,如在第k+1次扫描结束后,lidar odometry产生了一个没有畸变的点云 和一个位姿变换参数image.png(代表image.png之间的运动)。Mapping算法把点云image.png 配准到全局坐标系 W下,如下图中所示,假设 Qk为前k次扫描积累的数据所形成的点云地图,为lidar在地图中最后一次扫描k到k+1处的变换位姿。随着lidar odometry的输出,Mapping算法不断扩展 image.pngimage.png(即扫描时间image.png范围的全局变换,并把image.png投影到全局坐标系下,得到image.png。接着,通过不断优化 image.pngimage.png匹配到地图Qk中。

特征点提取方法与上述的2.2节相同(数量增加10倍,即为代码中的less_sharp点与less_flat点)。为了找到特征点之间的对应关系且提高运行效率,使用边长为10m的立方体代替全局地图(代码中是10105)。

取立方体中与image.png相交的部分,建立3D kd-tree索引。在 Q k的特征点中选取点集S’,针对边缘点只保留S’中边缘线上的点,针对平面点,只保留S’中面片上的点。然后,计算点集S’的协方差矩阵M,并分解M得到特征值记为V,特征向量E。如果S’分布在一条线段上,那么V中一个特征值就会明显比其他两个大, E中与较大特征值相对应的特征向量代表边缘线的方向。(一大两小,大方向)

如果S’分布在一个平面上,那么V中一个特征值就会明显比其他两个小, E中与较小特征值相对应的特征向量代表平面的朝向。(一小两大,小方向)

边缘线或平面块的位置通过点集S’的几何中心确定。

边缘线或平面块的位置通过点集S’的几何中心确定。

为了计算边缘点/平面点与其对应边缘线/面片之间的距离,在一个边缘线上选取两个点,在面片上选取三个点,分别通过公式2、3进行计算,并转换为公式9、10,组合为公式11中所示的非线性函数,进行优化。

边缘特征:

平面特征:

求解:

最后,image.png匹配到地图 Qk中时,考虑到点云的均匀分布,还对其进行了一个下采样。

目录
相关文章
|
1天前
|
算法 测试技术 开发者
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗;代码审查通过检查源代码发现潜在问题,提高代码质量和团队协作效率。本文介绍了一些实用的技巧和工具,帮助开发者提升开发效率。
6 3
|
13天前
|
存储 缓存 算法
如何通过优化算法和代码结构来提升易语言程序的执行效率?
如何通过优化算法和代码结构来提升易语言程序的执行效率?
|
14天前
|
搜索推荐
插入排序算法的讲解和代码
【10月更文挑战第12天】插入排序是一种基础的排序算法,理解和掌握它对于学习其他排序算法以及数据结构都具有重要意义。你可以通过实际操作和分析,进一步深入了解插入排序的特点和应用场景,以便在实际编程中更好地运用它。
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【自然语言处理】TF-IDF算法在人工智能方面的应用,附带代码
TF-IDF算法在人工智能领域,特别是自然语言处理(NLP)和信息检索中,被广泛用于特征提取和文本表示。以下是一个使用Python的scikit-learn库实现TF-IDF算法的简单示例,并展示如何将其应用于文本数据。
246 65
|
6天前
|
缓存 分布式计算 监控
优化算法和代码需要注意什么
【10月更文挑战第20天】优化算法和代码需要注意什么
13 0
|
27天前
|
算法 Java 测试技术
数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题
文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。
15 0
|
2月前
|
机器学习/深度学习 存储 算法
经典算法代码
这段代码展示了多个经典算法,包括:穷举法解决“百钱买百鸡”问题;递推法计算“猴子吃桃”问题;迭代法求解斐波那契数列及折纸高度超越珠峰的问题。同时,还提供了希尔排序算法实现及披萨票务订购系统和汉诺塔问题的链表存储解决方案。每部分通过具体案例解释了算法的应用场景与实现方法。
30 3
|
3月前
|
算法 数据处理 数据安全/隐私保护
|
3月前
|
机器学习/深度学习 人工智能 算法
【人工智能】传统语音识别算法概述,应用场景,项目实践及案例分析,附带代码示例
传统语音识别算法是将语音信号转化为文本形式的技术,它主要基于模式识别理论和数学统计学方法。以下是传统语音识别算法的基本概述
70 2
|
3月前
|
人工智能 算法 数据可视化
DBSCAN密度聚类算法(理论+图解+python代码)
DBSCAN密度聚类算法(理论+图解+python代码)