激光SLAM:ICP升级版本NICP(Normal ICP)原理+法向量即曲率计算代码

@[TOC](激光SLAM:ICP升级版本NICP(Normal ICP)原理+法向量即曲率计算代码)

NICP(Normal ICP)匹配方法

传统ICP的缺点:
由于ICP算法在点云的匹配关系上,是计算同一坐标系下的两帧点云上的点的距离最小作为比配点,这样的计算得到匹配关系,经常是错误的,会出现将不同位置(不同物体或者不同物体部分的扫描点)点进行匹配的情况,从而陷入局部最优。

NICP基本思想:
替换原始ICP方法中的对应点匹配(point correspondences)方法;
误差项除了考虑对应点的欧氏距离之外,同时还考虑对应点法向量的角度差。
充分利用实际曲面的特征来对错误的点匹配进行滤除,主要的特征为法向量和曲率;

在这里插入图片描述
上图中绿色和蓝色为两次扫描,紫色线表示匹配的点,可以看出,右上角部分虽然蓝色和绿色的点在距离上重合,但是由于法向量不同,并不会建立匹配关系.

NICP点匹配规则:

  • 如果没有well define的法向量,则拒绝。
  • 两点间的距离大于阈值,则拒绝。
  • 两点的曲率之差距大于阈值,则拒绝。
  • 两点的法向量角度之差大于阈值,则拒绝。

法向量和曲率计算

该方法需要计算点云中点的法向量和曲率
计算方法如下
数学模型:

找到点pi周围半径R球形空间内的所有点Vi,然后去中心化,并构造协方差矩阵,公式如下:
在这里插入图片描述

曲率的计算方法:
在这里插入图片描述
法向量的计算方法:
最小特征值对应的特征向量

上面是二维的,对于三维的则曲率计算如下:
在这里插入图片描述
法向量依旧是最小特征值对应的特征向量
参考链接

也可以用pcl的方法求得

目标函数

传统ICP的向量是点的坐标,而NICP将其进行了扩充,即坐标+法向量.
在这里插入图片描述

那么变换参数T(R,t)对这个扩充向量的变换则变为:
在这里插入图片描述
即对点进行旋转+平移,对法向量旋转.

目标函数则是点的距离和法向量角度误差
在这里插入图片描述
目标函数的定义为:
在这里插入图片描述

二维点云计算法向量方法 Code

通过 Eigen 的方法基于数学模型计算
完整代码

Eigen::Vector2d ComputeNormal(std::vector<Eigen::Vector2d> &nearPoints)
{
    Eigen::Vector2d normal;
    
    //根据周围的激光点计算法向量,参考ppt中NICP计算法向量的方法
    Eigen::Vector2d average;//周围点的几何中心
    average.setZero();//至0
    for(auto v : nearPoints)//遍历每个点
    {
        average += v / nearPoints.size();//求其周围点的几何中心
    }

    Eigen::Matrix2d covariance;//协方差矩阵
    covariance.setZero();//至0
    for(auto v : nearPoints)//遍历每个点
    {
        covariance += (v - average) * (v - average).transpose() / nearPoints.size();//求协方差矩阵
    }

    Eigen::EigenSolver<Eigen::Matrix2d> eigen_solver(covariance);//转化为对角线矩阵
    Eigen::Vector2d eigenValues = eigen_solver.pseudoEigenvalueMatrix().diagonal();
    Eigen::Matrix2d eigenVectors = eigen_solver.pseudoEigenvectors();
    normal = eigenValues(0) < eigenValues(1) ? eigenVectors.col(0) : eigenVectors.col(1);//计算法向量
    

    return normal;
}

代码解释

Eigen::Vector2d ComputeNormal(std::vector<Eigen::Vector2d> &nearPoints)

函数名称:ComputeNormal
函数功能:计算二维点云某点法向量
函数参数: nearPoints 某个点周围的所有激光点
函数返回: 该点法向量

+++++++++++++++++++++++++++++++++++++++++++++++++++++

    Eigen::Vector2d normal;//声明要计算的法向量
    
    Eigen::Vector2d average;//声明周围点的几何中心
    average.setZero();//至0

    for(auto v : nearPoints)//遍历每个点
    {
        average += v / nearPoints.size();//求其周围点的几何中心
    }

声明要计算的法向量
求其周围点的几何中心
+++++++++++++++++++++++++++++++++++++++++++++++++++++

    Eigen::Matrix2d covariance;//声明协方差矩阵
    covariance.setZero();//至0

    for(auto v : nearPoints)//遍历每个点
    {
        covariance += (v - average) * (v - average).transpose() / nearPoints.size();//求协方差矩阵
    }

求协方差矩阵
就是这个公式
在这里插入图片描述
+++++++++++++++++++++++++++++++++++++++++++++++++++++

    Eigen::EigenSolver<Eigen::Matrix2d> eigen_solver(covariance);//转化为对角线矩阵
    Eigen::Vector2d eigenValues = eigen_solver.pseudoEigenvalueMatrix().diagonal();//提取特征值
    Eigen::Matrix2d eigenVectors = eigen_solver.pseudoEigenvectors();//提取特征向量构成的矩阵

将协方差矩阵转为对角线矩阵
提取特征值和特征向量
+++++++++++++++++++++++++++++++++++++++++++++++++++++

	normal = eigenValues(0) < eigenValues(1) ? eigenVectors.col(0) : eigenVectors.col(1);//计算法向量 : 最小特征值对应的特征向量
	
	return normal;//返回法向量

通过特征值和特征向量,计算该点法向量
最小特征值对应的特征向量

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
ORB-SLAM2是一种基于二维图像的实时单目视觉SLAM系统,可以在没有先验地图的情况下,从单个摄像头的输入中实时定位和建立环境模型。为了更好地理解ORB-SLAM2的原理代码实现,我们需要逐行分析其核心算。 ORB-SLAM2的主要原理是通过特征提取,特征匹配和位姿估计来实现定位和建图。在代码中,我们可以看到一些关键的数据结构和函数调用,这些都是实现这些原理的关键。 首先,ORB-SLAM2使用FAST特征检测器在图像中检测关键点。这些关键点代表图像中的有趣区域。然后,使用ORB描述符对关键点进行描述。ORB描述符使用二进制位串来表示关键点周围的特征。 然后,ORB-SLAM2使用词袋(Bag-of-Words)模型来进行特征匹配。它首先通过建立一个词典来表示所有关键点的描述符。然后,使用词袋模型来计算图像之间的相似度,从而找到匹配的关键点。 接下来,ORB-SLAM2使用RANSAC算来估计两个图像之间的相对位姿。RANSAC算通过迭代随机采样的方式来筛选出最佳的匹配关系,从而得到相对位姿估计。 最后,ORB-SLAM2使用优化算(如g2o)来进行位姿图优化,从而更精确地估计相机的位姿。通过优化,ORB-SLAM2能够减少位置漂移,并在动态环境下更好地跟踪相机的位置。 总的来说,ORB-SLAM2通过特征提取、特征匹配和位姿估计实现实时单目视觉SLAM。核心代码实现了特征检测、描述符提取、特征匹配、RANSAC算和图优化等关键步骤。了解这些原理代码实现,可以帮助我们更好地理解ORB-SLAM2系统背后的工作原理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月照银海似蛟龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值