在研读了论文及开源代码后,对LOAM的一些理解做一个整理。
文章:Low-drift and real-time lidar odometry and mapping
开源代码:https://github.com/daobilige-su/loam_velodyne
系统概述
LOAM的整体思想就是将复杂的SLAM问题分为:1. 高频的运动估计; 2. 低频的环境建图。
Lidar接收数据,首先进行Point Cloud Registration,Lidar Odometry以10Hz的频率进行运动估计和坐标转换,Lidar Mapping以1Hz的频率构建三维地图,Transform Integration完成位姿的优化。这样并行的结构保证了系统的实时性。
接下来是代码的框架图:
整个算法分为四个模块,相对于其它直接匹配两个点云的算法,LOAM是通过提取特征点进行匹配之后计算坐标变换。具体流程为:ScanRegistration 提取特征点并排除瑕点;LaserOdometry从特征点中估计运动,然后整合数据发送给LaserMapping;LaserMapping输出的laser_cloud_surround为地图;TransformMaintenance订阅LaserOdometry与LaserMapping发布的Odometry消息,对位姿进行融合优化。后面将详细进行说明。
ScanRegistration
这一模块(节点)主要功能是:特征点的提取
一次扫描的点通过曲率值来分类,特征点曲率大于阈值的为边缘点;特征点曲率小于阈值的为平面点。为了使特征点均匀的分布在环境中,将一次扫描划分为4个独立的子区域。每个子区域最多提供2个边缘点和4个平面点。此外,将不稳定的特征点(瑕点)排除。下面将通过代码进行说明。
从主函数开始:
- intintchar
- "scanRegistration"
- /*
- /*
- "/velodyne_points"
- "/imu/data"
- /*
- "/velodyne_cloud_2"
- "/laser_cloud_sharp"
- "/laser_cloud_less_sharp"
- "/laser_cloud_flat"
- "/laser_cloud_less_flat"
- "/imu_trans"
- /**
- return
laserCloudHandler与imuHandler。
・laserHandler
laserCloudHandler是这一模块的重点部分,主要功能是对接收到的点云进行预处理,完成分类。具体分类内容为:一是将点云划入不同线中存储;二是对其进行特征分类。
首先对收到的点云进行处理
- voidconst
- if
- if
- true
- return
- int
- int
- double
- int
- //去除无效值
- int
- //计算点云的起始角度/终止角度
- float
- float
- forint
- float
- int
- intint
- if
- else
- if
- continue
接下来计算每个点的相对方位角计算出相对时间,根据线性插值的方法计算速度及角度,并转换到sweep k的初始imu坐标系下,再划入16线数组中
- float
- if
- if
- elseif
- if
- true
- else
- if
- elseif
- //scanPeriod=0.1,是因为lidar工作周期是10HZ,意味着转一圈是0.1秒;intensity是一个整数+小数,小数不会超过0.1,完成了按照时间排序的需求
- float
- if
- float
- while
- if
- break
- if
- else
- int
- float
- float
- if
- elseif
- else
- if
- else
之后将对所有点进行曲率值的计算并记录每一层曲率数组的起始和终止
- new
- //将所有点存入laserCloud中,点按线序进行排列
- forint
- int
- forint
- float
- float
- float
- ifint
- int(laserCloud->points[i].intensity);//scanCount=scanID
- if
接下来,对提到的两种瑕点进行排除
- forint
- float
- float
- float
- float
- if
- float
- float
- if
- if
- else
- if
- float
- float
- float
- float
- float
- if
- forint
- new
- forint
- int
- int
- forint
- forint
- if
- int
- int
- forint
- int
- if
- if
- elseif
- else
- break
- forint
- float
- float
- float
- if
- break
- forint
- float
- float
- float
- if
- break
- int
- forint
- int
- if
- if
- break
- forint
- float
- float
- float
- if
- break
- forint
- float
- float
- float
- if
- break
- forint
- if
之后再将信息发布出去
・imuHandler
- voidconst
- double
- float
- float
- float
- void
- float
- float
- float
- float
- float
- float
- float
- float
- float
- float
- float
- float
- int
- double
- if
后面涉及的坐标变换即欧拉角的旋转计算,这部分尚不熟悉,需要进一步学习。
・小结
以上数据传输流帮助理解这个模块源代码的功能。