对点云匹配算法ICP、PL-ICP、NICP和IMLS-ICP的理解

点云匹配算法是为了匹配两帧点云数据,从而得到传感器(激光雷达或摄像头)前后的位姿差,即里程数据。匹配算法已经从最初的ICP方法发展出了多种改进的算法。他们分别从配准点的寻找,误差方程等等方面进行了优化。下面分别介绍:

ICP

ICP的基本思想是:
给定两个点云集合

X = { x 1 , x 2 , ⋯   , x N x } X=\left\{x_{1}, x_{2}, \cdots, x_{N_{x}}\right\} X={x1,x2,,xNx}

P = { p 1 , p 2 , ⋯   , p N p } P=\left\{p_{1}, p_{2}, \cdots, p_{N_{p}}\right\} P={p1,p2,,pNp}

其中 x i x_{i} xi p i p_{i} pi表示点云坐标, N x N_{x} Nx N p N_{p} Np表示点云的数量。
求解旋转矩阵R和平移向量t使得下式结果最小。

E ( R , t ) = 1 N p ∑ i = 1 N p ∥ x i − R p i − t ∥ 2 E(R, t)=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-R p_{i}-t\right\|^{2} E(R,t)=Np1i=1NpxiRpit2

在实际工程中不可能知道两个点云的点是如何配对的。只能通过迭代求解的方法一步步缩小误差,最终得到使误差方程最小的旋转矩阵R和平移矩阵t。

算法流程:
1)寻找对应点
通常使用编码盘的里程计数据得到位姿差,即当前机器人在上次机器人坐标系中的位姿。将此R和t作为ICP算法的first guess,帮助算法寻找点云对应点。这里需注意,如果激光传感器没有安装在机器人坐标系中心,则存在里程计得到的位姿到激光传感器位姿的坐标转换关系。如下图中 l l l所示:
在这里插入图片描述
2)根据对应点计算R和t。
这一步就是根据找好的对应点构建误差方程。普通的ICP 是使用点到点的距离作为误差的。误差方程如下:

E ( R , t ) = 1 N p ∑ i = 1 N p ∥ x i − R p i − t ∥ 2 E(R, t)=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-R p_{i}-t\right\|^{2} E(R,t)=Np1i=1NpxiRpit2

然后求解出R和t。具体的求解推导如下:

E ( R , t ) = 1 N p ∑ i = 1 N p ∥ x i − R p i − t ∥ 2 E ( R , t ) = 1 N p ∑ i = 1 N p ∥ x i − R p i − t − u x + R u p + u x − R u p ∥ 2 = 1 N p ∑ i = 1 N p ∥ x i − u x − R ( p i − u p ) + ( u x − R u p − t ) ∥ 2 = 1 N p ∑ i = 1 N p ∥ x i − u x − R ( p i − u p ) ∥ 2 + ∥ u x − R u p − t ∥ 2 + 2 ( x i − u x − R ( p i − u p ) ) T ( u x − R u p − t ) = 1 N p ∑ i = 1 N p ∥ x i − u x − R ( p i − u p ) ∥ 2 + ∥ u x − R u p − t ∥ 2 \begin{aligned} E(R, t) &=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-R p_{i}-t\right\|^{2} \\ E(R, t) &=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-R p_{i}-t-u_{x}+R u_{p}+u_{x}-R u_{p}\right\|^{2} \\=& \frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-u_{x}-R\left(p_{i}-u_{p}\right)+\left(u_{x}-R u_{p}-t\right)\right\|^{2} \\=& \frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-u_{x}-R\left(p_{i}-u_{p}\right)\right\|^{2}+\left\|u_{x}-R u_{p}-t\right\|^{2} \\ &+2\left(x_{i}-u_{x}-R\left(p_{i}-u_{p}\right)\right)^{T}\left(u_{x}-R u_{p}-t\right) \\&=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-u_{x}-R\left(p_{i}-u_{p}\right)\right\|^{2}+\left\|u_{x}-R u_{p}-t\right\|^{2} \end{aligned} E(R,t)E(R,t)===Np1i=1NpxiRpit2=Np1i=1NpxiRpitux+Rup+uxRup2Np1i=1NpxiuxR(piup)+(uxRupt)2Np1i=1NpxiuxR(piup)2+uxRupt2+2(xiuxR(piup))T(uxRupt)=Np1i=1NpxiuxR(piup)2+uxRupt2

其中

u x = 1 N p ∑ i = 1 N p x i u p = 1 N p ∑ i = 1 N p p i u_{x}=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}} x_{i} \quad u_{p}=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}} p_{i} ux=Np1i=1Npxiup=Np1i=1Nppi

( x i − u x − R ( p i − u p ) ) \left(x_{i}-u_{x}-R\left(p_{i}-u_{p}\right)\right) (xiuxR(piup))项累加 N p N_{p} Np次后会等于0。

最终得到的等式中只有 ∥ x i − u x − R ( p i − u p ) ∥ 2 \left\|x_{i}-u_{x}-R\left(p_{i}-u_{p}\right)\right\|^{2} xiuxR(piup)2项与 R R R有关。

可以先令 ∥ u x − R u p − t ∥ 2 \left\|u_{x}-R u_{p}-t\right\|^{2} uxRupt2等于0,则只需保证 ∥ x i − u x − R ( p i − u p ) ∥ 2 \left\|x_{i}-u_{x}-R\left(p_{i}- u_{p}\right)\right\|^{2} xiuxR(piup)2项最小即可。求出 R R R后带入 ∥ u x − R u p − t ∥ 2 = 0 \left\|u_{x}-R u_{p}-t\right\|^{2}=0 uxRupt2=0求解出t。所以误差方程可以简化成下式:

min ⁡ E ( R , t ) = 1 N p ∑ i = 1 N p ∥ x i − u x − R ( p i − u p ) ∥ 2 \min E(R, t)=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}-u_{x}-R\left(p_{i}-u_{p}\right)\right\|^{2} minE(R,t)=Np1i=1NpxiuxR(piup)2

= 1 N p ∑ i = 1 N p ∥ x i ′ − R p i ′ ∥ 2 = 1 N p ∑ i = 1 N p x i T x i ′ + p i T R T R p i ′ − 2 x i T R p i ′ =\frac{1}{N_{p}} \sum_{i=1}^{N_{p}}\left\|x_{i}^{\prime}-R p_{i}^{\prime}\right\|^{2}=\frac{1}{N_{p}} \sum_{i=1}^{N_{p}} x_{i}^{T} x_{i}^{\prime}+p_{i}^{T} R^{T} R p_{i}^{\prime}-2 x_{i}^{T} R p_{i}^{\prime} =Np1i=1NpxiRpi2=Np1i=1NpxiTxi+piTRTRpi2xiTRpi

= ∑ i = 1 N p − 2 x i ′ T R p i ′ =\sum_{i=1}^{N_{p}}-2 x_{i}^{\prime T} R p_{i}^{\prime} =i=1Np2xiTRpi

因为 x i T x i ′ x_{i}^{T} x_{i}^{\prime} xiTxi项与 R R R矩阵没有关系,所以可以不考虑。由于 R R R为正交矩阵,则 R T R = I R^TR=I RTR=I,进而 p i T R T R p i ′ = p i T p i ′ p_{i}^{T} R^{T} R p_{i}^{\prime}=p_{i}^{T} p_{i}^{\prime} piTRTRpi=piTpi。可以看到该项与 R R R也没有什么关系,同样不考虑它。最后就只剩下一项与 R R R相关了。

要求最小即最大化下面的式子:

max ⁡ ∑ i = 1 N p x i ′ T R p i ′ = ∑ i = 1 N p Trace ⁡ ( R x i ′ p i T ) = Trace ⁡ ( R H ) \max \sum_{i=1}^{N_{p}} x_{i}^{\prime T}{{R} p_{i}^{\prime}}=\sum_{i=1}^{N_{p}} \operatorname{Trace}\left(R x_{i}^{\prime} p_{i}^{T}\right)=\operatorname{Trace}(R H) maxi=1NpxiTRpi=i=1NpTrace(RxipiT)=Trace(RH)

其中 H = ∑ i = 1 N p x i ′ p i ′ T H=\sum_{i=1}^{N_{p}} x_{i}^{\prime} p_{i}^{\prime T} H=i=1NpxipiT

利用定理,假设矩阵A为正定对称矩阵,则对于任意的正交矩阵B,都有

Trace ⁡ ( A ) ≥ Trace ⁡ ( B A ) \operatorname{Trace}(A) \geq \operatorname{Trace}(B A) Trace(A)Trace(BA)

H H H进行SVD分解 H = U Λ V T H=U \Lambda V^{T} H=UΛVT

X = V U T X=V U^{T} X=VUT,则 X X X为正交矩阵。

X H = V U T U Λ V T = V Λ V T X H=V U^{T} U \Lambda V^{T}=V \Lambda V^{T} XH=VUTUΛVT=VΛVT得到正定对称矩阵。

则:

Tr ⁡ ace ⁡ ( X H ) ≥ Tr ⁡ ace ⁡ ( B X H ) \operatorname{Tr} \operatorname{ace}(X H) \geq \operatorname{Tr} \operatorname{ace}(B X H) Trace(XH)Trace(BXH)

B是任意的正交矩阵,X也是一个正交矩阵,因此BX可以取遍所有的正交矩阵。所以BX也包括了需要求解的旋转矩阵T,因此

Trace ⁡ ( R H ) ≤ Trace ⁡ ( X H ) \operatorname{Trace}(R H) \leq \operatorname{Trace}(X H) Trace(RH)Trace(XH)

当R=X时,等式成立。因此:

R = X = V U T R=X=V U^{T} R=X=VUT

t = u x − R u p \mathrm{t}=u_{x}-R u_{p} t=uxRup

3)将计算得到的R和t用于下一次迭代计算,直到误差值小于设定的阈值。

这里指出ICP的一个明显缺陷:
两帧激光点云数据中的点不可能表示的是空间中相同的位置。所以用点到点的距离作为误差方程势必会引入随机误差。

参考论文:Least-Squares Fitting of Two 3-D Point Sets

PL-ICP

PL-ICP相对于PP-ICP最大的区别是其改进了误差方程。PP-ICP是点对点的距离作为误差而PL-ICP是采用点到其最近两个点连线的距离。下图展示了误差方程的差异。
在这里插入图片描述
从上方的(a)中可以看出,激光点是对实际环境中曲面的离散采样。最好的误差尺度是激光点到实际曲面的距离。而PL-ICP采用分段线性的方法对实际曲面进行近似,用激光点到最近两点连线的距离来模拟实际激光点到曲面的距离。可以看出PL-ICP的误差方程更贴近实际情况。

算法流程:
先贴一张论文里的算法步骤
在这里插入图片描述
1)给定一个初始的转换矩阵 q 0 q_{0} q0,将当前激光帧的数据转换到参考帧坐标系下。初始的转换矩阵 q 0 q_{0} q0一般通过里程计来获得。后面迭代计算所需的 q k q_{k} qk由上一次算法迭代计算得到。
2)为当前激光帧中的每一个点,找到其最近的两个点j1和j2。
3)去除误差过大的点。
4)构建最小化误差方程。
5)求解出位姿转换矩阵 q k + 1 \boldsymbol{q}_{k+1} qk+1。然后将其用于下次迭代计算。

总结PL-ICP与ICP的主要区别:
1)误差函数的形式不同,ICP对点对点的距离作为误差,PL-ICP为点到线的距离作为误差;
PL-ICP的误差形式更符合实际情况。
2)收敛速度不同,ICP为一阶收敛,PL-ICP为二阶收敛。
∥ q k − q ∞ ∥ < c ∥ q k − 1 − q ∞ ∥ ∥ q k − q ∞ ∥ 2 < c ∥ q k − 1 − q ∞ ∥ 2 \left\|\boldsymbol{q}_{k}-\boldsymbol{q}_{\infty}\right\|<c\left\|\boldsymbol{q}_{k-1}-\boldsymbol{q}_{\infty}\right\| \quad\left\|\boldsymbol{q}_{k}-\boldsymbol{q}_{\infty}\right\|^{2}<c\left\|\boldsymbol{q}_{k-1}-\boldsymbol{q}_{\infty}\right\|^{2} qkq<cqk1qqkq2<cqk1q2
3)PL-ICP的求解精度高于ICP,特别是在结构化环境中。
4)PL-ICP对初始值更敏感。不单独使用。其容易陷入局部循环,如下图(a)所示。通常用里程计得到一个初始转换矩阵 q 0 q_{0} q0给到PL-ICP算法。
在这里插入图片描述
csm源码包分析:
ros的csm包实现了ICP和PL-ICP算法。源码包和论文下载地址如下:
https://censi.science/software/csm/
csm包的作者给出了一个该功能包的操作说明文件(csm_manual.pdf)。里面详细描述了各项配置参数的含义。
其中sm/app文件夹中的sm0.c sm1.c sm2.c sm3.c 相当于是几个使用示例。
主要的算法实现是在csm/icp文件夹中的几个文件里。论文中的所有算法步骤完整的体现在了icp_loop.c文件中的icp_loop函数里。
开源代码
参考论文:An ICP variant using a point-to-line metric

NICP

NICP方法与ICP方法的主要流程和思想是一致的。但是它在Trim outlier和误差项里考虑了更多的因素。这也是它效果更好的原因。它充分利用实际曲面的特征来对错误点进行了滤除,主要使用的特征为法向量曲率。在误差项里除了考虑了点到对应点切面的距离,还考虑了对应点法向量的角度差。目前NICP方法开源的代码主要是针对3D点云的,其调用了Eigen库和OpenCV库。源码中显示的部分调用了QT5。既然NICP方法考虑了法向量和曲率,那么就涉及到了如何求解点的法向量和曲率。下面简述论文中的方法:
1)高斯拟合。找到点 p i p_i pi周围半径 R R R范围内的所有点 V i V_i Vi。求解均值和协方差。
μ i s = 1 ∣ V i ∣ ∑ p j ∈ V i p i Σ i s = 1 ∣ V i ∣ ∑ p j ∈ V i ( p i − μ i ) T ( p i − μ i ) \begin{aligned} \mu_{i}^{s} &=\frac{1}{\left|\mathcal{V}_{i}\right|} \sum_{\mathbf{p}_{j} \in \mathcal{V}_{i}} \mathbf{p}_{i} \\ \boldsymbol{\Sigma}_{i}^{s} &=\frac{1}{\left|\mathcal{V}_{i}\right|} \sum_{\mathbf{p}_{j} \in \mathcal{V}_{i}}\left(\mathbf{p}_{i}-\mu_{i}\right)^{T}\left(\mathbf{p}_{i}-\mu_{i}\right) \end{aligned} μisΣis=Vi1pjVipi=Vi1pjVi(piμi)T(piμi)

2)对协方差矩阵进行SVD分解,得到按从小到大顺序的特征值 λ 1 : 3 \lambda_{1: 3} λ1:3
Σ i s = R ( λ 1 0 0 0 λ 2 0 0 0 λ 3 ) R T \mathbf{\Sigma}_{i}^{\mathrm{s}}=\mathbf{R}\left(\begin{array}{ccc}{\lambda_{1}} & {0} & {0} \\ {0} & {\lambda_{2}} & {0} \\ {0} & {0} & {\lambda_{3}}\end{array}\right) \mathbf{R}^{T} Σis=Rλ1000λ2000λ3RT

论文中曲率的定义为:
σ i = λ 1 λ 1 + λ 2 \sigma_{i}=\frac{\lambda_{1}}{\lambda_{1}+\lambda_{2}} σi=λ1+λ2λ1
法向量的定义:最小特征值对应的特征向量。

Trim outlier中的改进:
在这里插入图片描述
1)如果没有well define的法向量,则拒绝。即选择比较结构化的点,如果对应点周围过于杂乱就丢弃该点。
2)两点间的距离大于阈值,则拒绝。
∥ p i c − T ⊕ p j r ∥ > ϵ d \left\|\mathbf{p}_{i}^{\mathrm{c}}-\mathbf{T} \oplus \mathbf{p}_{j}^{\mathrm{r}}\right\|>\epsilon_{d} picTpjr>ϵd
3)两点的曲率之差距大于阈值,则拒绝。
∣ log ⁡ σ i c − log ⁡ σ j r ∣ > ϵ σ \left|\log \sigma_{i}^{\mathrm{c}}-\log \sigma_{j}^{\mathrm{r}}\right|>\epsilon_{\sigma} logσiclogσjr>ϵσ
4)两点的法向量角度之差大于阈值,则拒绝。
n i c ⋅ T ⊕ n j r < ϵ n \mathbf{n}_{i}^{\mathrm{c}} \cdot \mathbf{T} \oplus \mathbf{n}_{j}^{\mathrm{r}}<\epsilon_{n} nicTnjr<ϵn

误差项中的改进:
在这里插入图片描述
1)点到对应点切面的距离作为其中的一个误差项。
2)法向量的夹角作为另一个误差项。考虑该项误差增加了旋转矩阵 R R R的求解精度。

最后得到的误差定义为:

e i j ( T ) = ( p ~ i c − T ⊕ p ~ j r ) \mathbf{e}_{i j}(\mathbf{T})=\left(\tilde{\mathbf{p}}_{i}^{\mathrm{c}}-\mathbf{T} \oplus \tilde{\mathbf{p}}_{j}^{\mathrm{r}}\right) eij(T)=(p~icTp~jr)

其中
T ⊕ p ~ i = ( R p i + t R n i ) T \oplus \widetilde{\mathrm{p}}_{i}=\left(\begin{array}{c}{R p_{i}+t} \\ {R n_{i}}\end{array}\right) Tp i=(Rpi+tRni)
即同时考虑了欧式距离和法向量的夹角。

目标函数的求解:
1)目标函数的定义为:

∑ c e i j ( T ) T Ω ~ i j e i j ( T ) \sum_{c} \mathbf{e}_{i j}(\mathbf{T})^{T} \tilde{\Omega}_{i j} \mathbf{e}_{i j}(\mathbf{T}) ceij(T)TΩ~ijeij(T)

2)非线性最小二乘问题,通过LM方法进行求解。

( H + λ I ) Δ T = b H = ∑ J i J i T J i = ∂ e i j ( T ) ∂ T T ← Δ T ⊕ T \begin{aligned}(\mathbf{H}+\lambda \mathbf{I}) \Delta \mathbf{T} &=\mathbf{b} \\ H &=\sum_{J_{i} J_{i}}^{T} \\ J_{i} &=\frac{\partial e_{i j}(T)}{\partial T} \quad \mathbf{T} \leftarrow \Delta \mathbf{T} \oplus \mathbf{T} \end{aligned} (H+λI)ΔTHJi=b=JiJiT=Teij(T)TΔTT

对NICP的总结:
1)由于在寻找点匹配的过程中,考虑了环境 曲面的法向量和曲率,因此可以提前排除 一些明显是错误的匹配。这样就减少了计算量并且提高了计算结果的精度。
2)在误差定义中,除了考虑欧式距离之外,还考虑了法向量之间的夹角,因此具有更加准确的求解角度。
3)用LM方法进行迭代求解目标误差方程,迭代收敛即可得到两帧激光数据之间的相对位姿。
源码地址
参考网址:http://jacoposerafin.com/nicp/

IMLS-ICP

IMLS-SLAM是一个仅依赖点云数据的低漂移(low-drift)SLAM算法。其依赖于一个scan-to-model的匹配框架。这里的model可以认为是对点云进行的局部曲面建模。
基本思想:
1)选择具有代表性的激光点来进行匹配,既能减少计算量同时又能减少激光点分布不均匀导致的计算结果出现偏移。
2)点云中隐藏着真实的曲面,最好的做法是能从参考帧点云中把曲面重建出来。
3)曲面重建的越准确,对真实世界描述越准确,匹配的精度就越高。
具体的改进措施:
1)scan egomotion
egomotion的定义如下:
在这里插入图片描述
进行激光数据的运动畸变去除。在雷达扫描一圈的过程中,车子是在运动的。这会造成一帧激光的时间内,每束激光测量时车子实际的位置是不同的。论文里假设两次连续的激光扫描间隔,车子的egomotion是相似的。所以采用上一次的相对位移来计算当前的实际的egomotion。
2)去除动态障碍物
在匹配scan和model之前,我们要去除scan中所有移动物体。我们采用去除所有可能会动的小物体的方法:首先,删去地面点云,聚类,并抛弃所有(bounding box的)长小于14m,宽小于14m,高小于4m的物体。剩下的结构足够我们匹配。最后添上去掉的地面点云。
3)特征点的选取
选取思路:

  • 具有丰富特征的点,即为结构化的点:具有良好的曲率和法向量的定义。

  • 曲率越小的点越好,因为曲率为0代表着直线,代表着最结构化的点,也代表着具有非常好的法向量定义,能够提供足够的约束。

  • 选点的时候需要注意选取的激光点的均衡以保证可观性,因为是平面匹配,不存在角度不可观的情况。只需要考虑X方向和Y方向的可观性。要保证两者的约束基本上是一致的, 才能让结果不出现偏移。

  • 大概率上,随着角度的偏转,观测的点云是不一样的。所以角度一般是可观的。对于二维SLAM,只需保证X方向和Y方向上选取的点云数量接近就可以。而对于三维则需要考虑6个维度(X,Y,Z,roll,pitch,yaw)。

4)曲面重建

  • 已知点云集合 P k P_k Pk中每一个点 p i p_i pi的法向量 n i n_i ni ,则 P k P_k Pk中隐藏的曲面为:
    I P k ( x ) = ∑ p i ∈ P k W i ( x ) ( ( x − p i ) ⋅ n i → ) ∑ p j ∈ P k W j ( x ) W i ( x ) = e − ∥ x − p i ∥ 2 / h 2 \begin{aligned} I^{P_{k}}(x) &=\frac{\sum_{p_{i} \in P_{k}} W_{i}(x)\left(\left(x-p_{i}\right) \cdot \overrightarrow{n_{i}}\right)}{\sum_{p_{j} \in P_{k}} W_{j}(x)} \\ W_{i}(x) &=e^{-\left\|x-p_{i}\right\|^{2} / h^{2}} \end{aligned} IPk(x)Wi(x)=pjPkWj(x)piPkWi(x)((xpi)ni )=expi2/h2

x x x是空间中的一个点, p i pi pi是点云中的一个点。
在这里插入图片描述
上图中的 H e i g h t = ( x − p i ) ⋅ n i Height=(x-p_i)\cdot n_i Height=(xpi)ni,表示点到曲面的距离。
我们认为激光点云是分布在真实曲面的附近,并可以用高斯分布描述。如下图
在这里插入图片描述
所以可以用 W i ( x ) W_i(x) Wi(x)表示点 x x x到点云 p i p_i pi距离的权重。当点 x x x到点云 p i p_i pi距离很远时,权重会接近0。该算法会选取点 x x x附近的一部分点使用上面的公式重建曲面。公式中的 ∑ p j ∈ P k W j ( x ) {\sum_{p_{j} \in P_{k}} W_{j}(x)} pjPkWj(x)为所有这些权重的累加。

公式的实现代码

    double mh2 = m_h * m_h;
    for(int i = 0; i < nearPoints.size(); ++i)
    {
        Eigen::Vector2d delta_p = x - nearPoints[i];
        double weight = std::exp(-delta_p.squaredNorm()/mh2);
        projSum += weight * delta_p.dot(nearNormals[i]);
        weightSum += weight;
    }
    height = projSum / (weightSum + 0.000001);//加一个很小的数避免除0
  • I P k ( x ) = 0 I^{P_{\mathrm{k}}}(x)=0 IPk(x)=0对应的集合表示曲面。
  • 空间中点到曲面的距离,直接代入上述方程即可。

5)匹配求解

  • 当前帧中一点 x i x_i xi 到曲面的距离为 I P k ( x i ) I^{P_k}(x_i) IPk(xi)

  • 则点 x i x_i xi在曲面上的投影 y i y_i yi为: y i = x i − I P k ( x i ) ⋅ n i \mathrm{y}_{i}=x_{i}-I^{P_{k}}\left(x_{i}\right) \cdot n_{i} yi=xiIPk(xi)ni
    P k P_k Pk中离点 x i x_i xi最近的点的法向量为 n i n_i ni。利用这个公式寻找 x i x_i xi对应的投影点 y i y_i yi

  • x i x_i xi和点 y i y_i yi为对应的匹配点: ∑ ( ( R x i + t − y i ) ⋅ n i ) 2 \sum\left(\left(\mathrm{R} \mathrm{x}_{\mathrm{i}}+\mathrm{t}-\mathrm{y}_{\mathrm{i}}\right) \cdot \mathrm{n}_{\mathrm{i}}\right)^{2} ((Rxi+tyi)ni)2
    这里的法向量 n i n_i ni y i y_i yi点的法向量。该公式描述的是转换后的 x i x_i xi点到投影点 y i y_i yi上的距离(注意是法向量上的距离)。

总结:
IMLS-ICP使用高斯拟合和最小二乘重建出一个隐含的曲面。找到空间点在隐含曲面的投影点。使用点到该曲面上投影点间的距离构建误差方程。

参考网址:
IMLS-SLAM 论文学习
IMLS-SLAM: scan-to-model matching based on 3D data,Jean-Emmanuel Deschaud

相关论文放到我的github里了:
相关论文

ICP方法初始值的设定方法

一个好的初始值可以减少icp迭代的次数,提高效率和效果。初始值的设定可以从下面三个角度来考虑:
1.、假设机器人静止,设置帧间位移为0。
2、假设机器人匀速运动,利用上一时刻机器人的速度和时间,计算当前时刻机器人位移间隔,将此作为初值传入icp
3、利用传感器如里程计、IMU等,计算前后两时刻的初始位移。实际使用时要注意坐标系的转换。因为icp方法实在激光坐标系下进行的。

提升ICP方法精度和速度的一些考虑

精度上:
1)使用其他传感器或方法(如里程计、IMU)提供初值(coarse to fine)。
2)Ransac框架,去除outlier。
效率上:
1)选取合适的采样点。IMLS-ICP的论文里就提到了一些去除误差点的方法。
2)使用合适的数据结构,提高程序的运行效率。

关注公众号《首飞》回复“机器人”获取精心推荐的C/C++,Python,Docker,Qt,ROS1/2,机器人学等机器人行业常用技术资料。

  • 80
    点赞
  • 433
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
NICP(Normal Distributions Transform Iterative Closest Point)算法是一种基于正态分布变换(NDT)的迭代最近点算法ICP)的改进。其主要思想是使用NDT将点云表达为高斯混合模型,从而提高匹配的鲁棒性。 以下是MATLAB实现NICP算法的基本步骤: 1. 读取两个点云P和Q,并将它们转换为NDT表示形式。 2. 初始化变换矩阵T为单位矩阵。 3. 通过计算点云P和变换后的点云Q'之间的最近点对,计算初始误差。 4. 重复以下步骤直到收敛: - 计算点云P和变换后的点云Q'之间的最近点对。 - 基于最近点对计算出变换矩阵T。 - 将点云Q转换为T变换后的点云Q'。 - 计算误差并检查是否收敛。 以下是MATLAB代码示例: ``` % 读取点云 P = pcread('pointcloud1.pcd'); Q = pcread('pointcloud2.pcd'); % 将点云转换为NDT表示形式 ndt_P = pointCloud(P.Location); ndt_Q = pointCloud(Q.Location); % 初始化变换矩阵为单位矩阵 T = eye(4); % 设置迭代次数和误差阈值 max_iter = 100; error_threshold = 0.001; % 迭代计算 for i = 1:max_iter % 计算最近点对 [indices, distances] = findNearestNeighbors(ndt_Q, ndt_P.Location, 1); nearest_P = ndt_P.Location(indices,:); nearest_Q = ndt_Q.Location; % 计算变换矩阵 T = icp_transform(nearest_P, nearest_Q); % 将点云Q转换为T变换后的点云Q' ndt_Q = pctransform(ndt_Q, affine3d(T)); % 计算误差并检查是否收敛 error = sum(distances.^2) / length(distances); if error < error_threshold break; end end % 输出变换矩阵 disp(T); ``` 其中,icp_transform是自定义函数,用于计算变换矩阵。具体实现可以参考ICP算法,这里不再赘述。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

首飞爱玩机器人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值