3D激光SLAM:ALOAM:异常点剔除机制代码解析
前言
在LOAM的论文中,作者提到了要剔除两种异常点.
- 平行点
- 遮挡点
但是在ALOAM的代码中并未写相关的功能.
如果想把论文中两种异常点的剔除机制加进去,可以参考下面的代码.
之前把一些其它的异常点剔除的方法总结了,可以参考这个地方
- 去除掉非常近的点
- 去除掉非常远的点
- 去除NaN的点
- 反射率处理
- 去除入射角较小的点 (实际就是平行点)
LOAM中的异常点
再回顾下LOAM中定义的两类异常点
平行点:
平行点指的就是 图中的B点
就是激光的射线几乎和物体的平面平行了
剔除这种点的原因有两个:
1 激光的数据会不准,射线被拉长
2 这种点被视为特征点后会非常不稳定,下一帧可能就没了,无法做配对了
例如图片中的lidar向左移一点,那么B点就消失了,形成对比的就是A点,极短时间内不会消失
遮挡点:
遮挡点就是 图中的A点
lidar一条sacn上,相邻的两个或几个点的距离偏差很大,被视为遮挡点
剔除这种点的原因是:
这种点被视为特征点后会非常不稳定,下一帧可能就没了,无法做配对了
例如图片中的lidar向右移一点,那么A点就消失了,形成对比的就是B点,极短时间内不会消失
此时最后把A点的左边几个点,都剔除掉
Code
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//获取点云中点的个数
int cloudSize = extractedCloud->points.size();
获取点云中点的个数
// 循环处理每个点,判断是否是遮挡点还是平行点
for (int i = 5; i < cloudSize - 6; ++i)
{
循环处理每个点,判断是否是遮挡点还是平行点
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/* occluded points 遮挡点的判断 */
float depth1 = cloudInfo.pointRange[i];//当前点距离
float depth2 = cloudInfo.pointRange[i+1];//下一个点的距离
首先是判断 遮挡点
depth就是点的距离 = sqrt(xx+yy+z*z)
// 列索引间的距离
int columnDiff = std::abs(int(cloudInfo.pointColInd[i+1] - cloudInfo.pointColInd[i]));
计算点的 一条scan上的 索引偏差
因为前面可能要去掉一些点,比如NAN点,如果索引偏差很大,那么就可以不进行遮挡点的判断了
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 相邻两点如果列索引太小,则这个点周围的点不进行特征提取
if (columnDiff < 10){
// 如果相邻两点距离大于0.3,选出6个点
if (depth1 - depth2 > 0.3){
//如果i点在后面,那么i点也不能要,并且i-1至i-5不要
cloudNeighborPicked[i - 5] = 1;
cloudNeighborPicked[i - 4] = 1;
cloudNeighborPicked[i - 3] = 1;
cloudNeighborPicked[i - 2] = 1;
cloudNeighborPicked[i - 1] = 1;
cloudNeighborPicked[i] = 1;
}else if (depth2 - depth1 > 0.3){
//如果i在前面,那么i+1是被遮挡的点,那么i+1至i+6不要
cloudNeighborPicked[i + 1] = 1;
cloudNeighborPicked[i + 2] = 1;
cloudNeighborPicked[i + 3] = 1;
cloudNeighborPicked[i + 4] = 1;
cloudNeighborPicked[i + 5] = 1;
cloudNeighborPicked[i + 6] = 1;
}
}
如果点的索引偏差不大的话,那么进行判断是否是遮挡点
偏差大不进行判断的原因就是比如下图
如图上的情况,因为去了NAN点,那么i和i+1点距离偏差过大,也不是遮挡点,要排除此种情况
如果相邻两点距离大于0.3,选出6个点
这时候要分两种情况
一个是i点的距离大,即i为被遮挡点,那么i点也不能要,并且i-1至i-5不要,因为i-1至i-5也不稳定
另外一种情况是i在前面,那么i+1是被遮挡的点,那么i+1至i+6不要
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/* parallel beam 平行点的判断 */
// 平行线的情况,根据左右两点与该点的深度差,确定该点是否会被选择为特征点
float diff1 = std::abs(float(cloudInfo.pointRange[i-1] - cloudInfo.pointRange[i]));
float diff2 = std::abs(float(cloudInfo.pointRange[i+1] - cloudInfo.pointRange[i]));
if (diff1 > 0.02 * cloudInfo.pointRange[i] && diff2 > 0.02 * cloudInfo.pointRange[i])
cloudNeighborPicked[i] = 1;
}
这个是平行点的判断
平行线的情况,根据左右两点与该点的深度差,确定该点是否会被选择为特征点
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
整体代码
// 标记遮挡点与平行点,不进行特征提取
void markOccludedPoints()
{
//获取点云中点的个数
int cloudSize = extractedCloud->points.size();
// 循环处理每个点,判断是否是遮挡点还是平行点
for (int i = 5; i < cloudSize - 6; ++i)
{
/* occluded points 遮挡点的判断 */
float depth1 = cloudInfo.pointRange[i];//当前点距离
float depth2 = cloudInfo.pointRange[i+1];//下一个点的距离
// 列索引间的距离
int columnDiff = std::abs(int(cloudInfo.pointColInd[i+1] - cloudInfo.pointColInd[i]));
// 相邻两点如果列索引太小,则这个点周围的点不进行特征提取
if (columnDiff < 10){
// 如果相邻两点距离大于0.3,选出6个点
if (depth1 - depth2 > 0.3){
//如果i点在后面,那么i点也不能要,并且i-1至i-5不要
cloudNeighborPicked[i - 5] = 1;
cloudNeighborPicked[i - 4] = 1;
cloudNeighborPicked[i - 3] = 1;
cloudNeighborPicked[i - 2] = 1;
cloudNeighborPicked[i - 1] = 1;
cloudNeighborPicked[i] = 1;
}else if (depth2 - depth1 > 0.3){
//如果i在前面,那么i+1是被遮挡的点,那么i+1至i+6不要
cloudNeighborPicked[i + 1] = 1;
cloudNeighborPicked[i + 2] = 1;
cloudNeighborPicked[i + 3] = 1;
cloudNeighborPicked[i + 4] = 1;
cloudNeighborPicked[i + 5] = 1;
cloudNeighborPicked[i + 6] = 1;
}
}
/* parallel beam 平行点的判断 */
// 平行线的情况,根据左右两点与该点的深度差,确定该点是否会被选择为特征点
float diff1 = std::abs(float(cloudInfo.pointRange[i-1] - cloudInfo.pointRange[i]));
float diff2 = std::abs(float(cloudInfo.pointRange[i+1] - cloudInfo.pointRange[i]));
if (diff1 > 0.02 * cloudInfo.pointRange[i] && diff2 > 0.02 * cloudInfo.pointRange[i])
cloudNeighborPicked[i] = 1;
}
}
以上是ALOAM中 异常点剔除 功能的 代码 分析
- 点赞
- 收藏
- 关注作者
评论(0)