lego-loam 代码阅读记录 ------ 特征提取与关联部分:
本文对 lego-loam代码的特征提取部分进行总结,目的是方便用python复现lego-loam的特征提取以及配准过程。
最后对提取特征点的整个过程中用到的阈值进行了整理。每个函数的详细内容见:链接
1. imageProjection.cpp:
首先说明 labelMat 的定义:
- size: (64,1800) 记录了点的聚类情况:
- -1: 地面点
- 0: 初始值
- 1,2,3,…: 有效聚类点
- 999999: 无效聚类点.
各个函数说明:
projectPointCloud():
三维点云的柱面投影
groundRemoval()
标记地面点以及空点,并记录到 groundMat = 1(初始值为0)
cloudSegmentation()
这一步进行点云的分割。
- 首先在 labelComponents() 函数中对非地面点进行平面点集聚类,结果记录在 labelMat = 1,2,3,…
- 去除无效聚类点(无效点经过降采样后加入到outliers),将 有效聚类点、降采样后的地面点 加入到变量 segmentedCloud 中。
- 标记该点是否为地面点,记录range、以及Col index用于后面去除遮挡点。
- 最后,得到的分割点云以及点云的信息被传入featureAssociation类中进行处理
2. featureAssociation.cpp
各个函数说明:
calculateSmoothness():
- 计算前5个点与后5个点范围内的曲率,并维护一个平滑度数组cloudSmoothness[], 以及cloudCurvature[]
- 初始化 cloudNeighborPicked[] = 0 以及 cloudLabel[] = 0
markOccludedPoints():
- 水平距离小于10的、但是距离较远(>0.3)的那些点,将远的点以及附近5个点,标记 cloudNeighborPicked = 1
- 选择左右点之间距离变化较大的点,标记 cloudNeighborPicked = 1
extractFeatures():
该函数实现了将四种特征提取到对应的四个特征点集合。
- 在没有标记的(cloudNeighborPicked ==0)非地面点中按照 平滑度 提取出 20个cornerPointsLessSharp以及2个 cornerPointsSharp ,cornerPointsLessSharp中的点标记为cloudlabel = 1,cornerPointsSharp中的点标记为cloudlabel = 2。并将提取的20个点以及该点开始 前后5个点范围内与该点列坐标的差值小于10的点 均标记为已处理。
- 在没有标记的(cloudNeighborPicked ==0)地面点中将 平滑度 小于阈值的点标记cloudLabel = -1, 并提取出4个最平滑的surfPointsFlat。 surfPointsLessFlatScan 集合包括所有cloudLabel<=0的点(平滑度小于阈值的地面点,以及不是cornerless的非地面点)。并将提取的4个点以及该4点开始 前后5个点范围内与该点列坐标的差值小于10的点 均标记为已处理(cloudNeighborPicked =1),最后将 surfPointsLessFlatScan 降采样得到surfPointsLessFlat点集。
注意 : surfless包含了地面点以及非地面点,surf只包含地面点。
LeGO-Loam提取特征时的阈值参数总结(不全):
- ImageProjection::groundRemoval():abs(angle - sensorMountAngle) <= 10则认为是地面点
- ImageProjection::labelComponents():
- if (angle > segmentTheta) 则认为是同一平面
- 可用聚类阈值: 30
- 竖直方向可用聚类: 3
- FeatureAssociation::markOccludedPoints():
- if (columnDiff < 10) // 水平距离小于10的、但是距离较远(>0.3)的那些点,将远的点以及附近5个点标记为1
- if (diff1 > 0.02 * segInfo.segmentedCloudRange[i] && diff2 > 0.02 * segInfo.segmentedCloudRange[i]): 瑕点阈值: 0.02
- FeatureAssociation::extractFeatures():
- 提取cornerLess: cloudCurvature[ind] > edgeThreshold; edgeThreshold = 0.1,
- 每个子图各2个corner点,20个cornerLess点
- 对于符合阈值条件的点的前后各5个点, 如果columnDiff < 10 则标记为已处理
- 提取surf: surfThreshold = 0.1
- 每个子图各4个surf,
- 对于符合阈值条件的点的前后各5个点, 如果columnDiff < 10 则标记为已处理
- FeatureAssociation::calculateTransformationSurf() {
- if (deltaR < 0.1 && deltaT < 0.1) 用于判断迭代优化是否收敛。