NDT点云配准算法原理及PCL实现

前言

NDT算法因其具有较强的鲁棒性而被广泛的应用,下面这些项目中的点云配准算法采用的都是NDT:
Autoware
hdl_graph_slam
hdl_localization
可见该配准方法的重要性,下面我将对这个算法进行分析.

算法流程

在这里插入图片描述
依据上述伪码流程可以看出,该算法主要的思路就是将目标点云刻画成多个概率分布,然后通过位姿变换关系将待配准点云转换到目标点云坐标系下,计算转换后待配准点云的总概率,并将此概率的负值作为目标函数,通过高斯牛顿迭代法优化该目标函数以求获得负的最小概率值(即最大概率值).高斯牛顿迭代公式见第23行,由梯度向量、海森矩阵和待求的位姿增量组成,因此最后整个NDT算法可以简单的归为求解梯度向量、求解海森矩阵和求解位姿增量三个主要过程.下面主要分析较复杂的梯度向量和海森矩阵的求解.

目标函数(对应伪码中的 s c o r e score score)

总概率计算如下:
在这里插入图片描述
为了能使用高斯牛顿迭代法,需要将目标函数转换成求最小值,而我们的目标是要求取公式(6.5)的最大值,因此可通过下式进行转换,将求取公式(6.5)的最大值转换成求取公式(6.6)的最小值:
在这里插入图片描述
假设每个栅格内点的分布呈正态分布,按公式(6.6)对一个正态分布的PDF求取-log值会出现下图红线所示的没有最大边界问题,该问题会使得噪声对优化结果产生很大影响(如果噪声很大,-log值会非常大,导致优化算法主要的目标是去优化噪声了,结果将会被严重影响)
在这里插入图片描述
为了抑制噪声影响,提出了如下正态分布与均匀分布结合的概率分布模型,可以实现图中绿线所示的有边界的效果:
在这里插入图片描述
其中常数 c 1 , c 2 c_{1}, c_{2} c1,c2 可以通过要求 p ˉ ( x ⃗ ) \bar{p}(\vec{x}) pˉ(x ) 的概率质量在一个单元格跨越的空间内等于1来确定。公式(6.7)没有简单的一阶、二阶微分.但通过观察上图发现公式(6.7)可以被下式近似:
在这里插入图片描述
式中的 d 1 , d 2 , d 3 d_{1}, d_{2}, d_{3} d1,d2,d3 可通过令 x = 0 , x = σ , x = ∞ x=0,x=\sigma, x=\infty x=0,x=σ,x=建立方程求解,结果为:
在这里插入图片描述
该式具有简单的微分方程.基于高斯近似后的概率分布函数如下:
在这里插入图片描述
于是最终的目标函数由(6.6)转换成了下式:
在这里插入图片描述
注意:
虽然目标函数已确定,但目标函数中的协方差矩阵 Σ \Sigma Σ 的确定需要采取一些策略.因为目标函数中需要求取协方差矩阵的逆 Σ − 1 \Sigma ^{-1} Σ1 ,如果栅格中的点是共面或共线的,协方差矩阵是奇异的,无法求取逆矩阵,因此由三维空间中三个及以下的点来求取协方差矩阵必然是奇异的.为了解决该问题,NDT算法中的PDF计算要求至少需要5个点,并且当 Σ \Sigma Σ 几乎为奇异值时,就对该协方差进行调整,调整的策略为: 如果 Σ \Sigma Σ 最大的特征值 λ 3 \lambda_{3} λ3 λ 1 , λ 2 \lambda_{1}, \lambda_{2} λ1,λ2 大100倍时,令 λ 1 = λ 2 = λ 3 / 100 \lambda_{1} = \lambda_{2} = \lambda_{3}/100 λ1=λ2=λ3/100 ,然后再令 Σ = V ∧ ′ V \Sigma = \mathbf{V}\boldsymbol{\wedge}^{'}\mathbf{V} Σ=VV,其中 V \mathbf{V} V 包含了 Σ \Sigma Σ 的特征向量, ∧ ′ \wedge^{'} 的计算如下:
在这里插入图片描述
至此确定了NDT算法的目标函数.

梯度向量的求解


在这里插入图片描述
可得梯度向量:
在这里插入图片描述

海森矩阵的求解

在这里插入图片描述

示例

从上面的分析可知,NDT算法主要的任务是对梯度向量和海森矩阵的求解,而从公式(6.12)和(6.13)可以看出,针对不同场景,主要的差异体现 δ x ⃗ k ′ δ p i \frac{\delta\vec{\mathbf{x}}_{k}^{'}}{\delta\mathbf{p}_{i}} δpiδx k δ 2 x ⃗ k ′ δ p i δ p j \frac{\delta^{2}\vec{\mathbf{x}}_{k}^{'}}{\delta\mathbf{p}_{i}\delta\mathbf{p}_{j}} δpiδpjδ2x k.下面以2D场景为例对这两项进行解算.
假设位姿变换参数为 p ⃗ = ( t x , t y , ϕ ) \vec{\mathbf{p}}=(t_{x},t_{y},\phi) p =(tx,ty,ϕ),待转换的点为 x ⃗ = ( x 1 , x 2 ) \vec{\mathbf{x}} = (x_{1}, x_{2}) x =(x1,x2),则转换位姿变换方程如下:
在这里插入图片描述
δ x ⃗ k ′ δ p i \frac{\delta\vec{\mathbf{x}}_{k}^{'}}{\delta\mathbf{p}_{i}} δpiδx k结果为:
在这里插入图片描述
δ 2 x ⃗ k ′ δ p i δ p j \frac{\delta^{2}\vec{\mathbf{x}}_{k}^{'}}{\delta\mathbf{p}_{i}\delta\mathbf{p}_{j}} δpiδpjδ2x k的结果为:
在这里插入图片描述
对于3D场景的示例可查看论文,与二维场景相比,只对三维位姿的求导存在差异.

PCL实现(直接链接PCL库)

2D场景实现
3D场景实现
测试直接看官方demo吧,很简单.

NDT改进版本

ndt_omp

改进1: 引入cpu多线程支持OpenMP
改进2: 搜索速度提升,提升策略如下
在这里插入图片描述

参考论文

The Three-Dimensional Normal-Distributions Transform — an Efficient Representation for Registration, Surface Analysis, and Loop Detection

  • 11
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
点云ICP配准是一种常用的点云配准方法,可以将两组点云进行精确的对齐。在PCL中,ICP配准算法可以通过pcl::IterativeClosestPoint类实现。 以下是一个简单的点云ICP配准示例: ```c++ #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/registration/icp.h> int main(int argc, char** argv) { // 加载原始点云和目标点云 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in (new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out (new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile<pcl::PointXYZ> ("input_cloud.pcd", *cloud_in); pcl::io::loadPCDFile<pcl::PointXYZ> ("target_cloud.pcd", *cloud_out); // 创建ICP对象 pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; icp.setInputSource(cloud_in); icp.setInputTarget(cloud_out); // 设置ICP参数 icp.setMaxCorrespondenceDistance(0.05); icp.setMaximumIterations(50); icp.setTransformationEpsilon(1e-8); icp.setEuclideanFitnessEpsilon(1); // 执行ICP配准 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_aligned (new pcl::PointCloud<pcl::PointXYZ>); icp.align(*cloud_aligned); // 输出配准结果 std::cout << "ICP has converged:" << icp.hasConverged() << " score: " << icp.getFitnessScore() << std::endl; std::cout << icp.getFinalTransformation() << std::endl; // 保存配准后的点云 pcl::io::savePCDFile<pcl::PointXYZ>("output_cloud.pcd", *cloud_aligned); return 0; } ``` 在代码中,我们首先加载了原始点云和目标点云,然后创建了一个pcl::IterativeClosestPoint对象,并将原始点云和目标点云设置为输入源和目标。 接着,我们设置了ICP的参数,例如最大对应距离、最大迭代次数、变换阈值等等。 最后,我们调用icp.align()函数执行ICP配准,将配准后的点云保存到硬盘中。 需要注意的是,ICP算法只能对初始姿态比较接近的两组点云进行配准。如果两组点云初始姿态差距较大,需要使用其他方法(例如全局配准)进行预处理,以便ICP算法可以更快地收敛到最优解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值