3D激光SLAM:ALOAM:异常点剔除机制代码解析

举报
月照银海似蛟龙 发表于 2022/07/29 09:28:21 2022/07/29
【摘要】 在LOAM的论文中,作者提到了要剔除两种异常点. - 平行点 - 遮挡点 但是在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中 异常点剔除 功能的 代码 分析

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。