迭代最近点算法

计算科学 优化 迭代法 svd 3d 最近点
2021-12-22 05:03:37

我目前正在研究迭代最近点算法(在 C++ 中,请参见此处)。

我了解 ICP 算法的基本前提。您有两个点云(一个目标和一个参考),并且您希望将参考注册到目标中。您可以通过以下方式执行此操作:

  • 关联点对(kd 树或类似的东西)
  • 找到最佳旋转和平移,使变换点和目标之间的距离的 RMSE 最小化(在我的例子中,我使用带有奇异值分解的 Kabsch 算法)。
  • 接下来,使用先前计算的旋转和平移更新参考点,并使用新的参考点和目标点再次迭代。
  • 这样做直到满足停止条件。

我的问题是如何正确跟踪旋转和平移。目前我通过计算到目前为止的总旋转(以度为单位)并添加新的旋转(以度为单位)来更新旋转。为了跟踪总平移,我采用最后一次平移(即到目前为止的总平移),将其乘以新计算的旋转,然后添加新计算的旋转。换一种说法:

(假设当前的外观是循环 i,newRotation 和 newTranslation 刚刚使用 Kabsch 方法计算,toMatrix()将角度以度为单位toDegrees()转换为旋转矩阵,将旋转矩阵转换为以度为单位的角度)。

rotation(i) = toMatrix(toDegrees(rotation(i-1)) + toDegrees(newRotation))

translation(i) = (newRotation * translation(i-1)) + newTranslation. 

这种方法似乎从根本上是错误的,因为我的误差(均方根误差)随着每次迭代而增加。

我用来测试的数据非常匹配,实际上我事先知道映射,所以算法应该很快收敛。我已经验证了我的最近点匹配工作,所以我认为“总”旋转和平移的计算是问题所在。这是实现这个的正确方法还是我做错了什么?

1个回答

使用角度存储旋转是一个非常糟糕的主意。它们是模棱两可的,并不总是一致的定义。

将姿势矩阵存储为旋转和平移的增强矩阵:在该约定中,点通过以下操作进行转换:P=[R|t]xR3

x=Px

P是一个矩阵,而是一个 3D 坐标的列向量。4x3x

现在让表示在迭代/时间的位姿,而是当前更新的位姿(来自 Kabash、Horn、Point-to-Plane 等的解决方案)。这次它们是矩阵,组装如下:PttPδ4x4

P=[Rt01]

那么你的新姿势是:

Pt+1=PδPt

这样,您可以在最小化过程中跟踪矩阵,而无需分别跟踪如果您的案例是 2D 的,您仍然可以做同样的事情,只是使用尺寸减小的矩阵。Rt

您可以在此处查看使用此约定的示例