我目前正在研究迭代最近点算法(在 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.
这种方法似乎从根本上是错误的,因为我的误差(均方根误差)随着每次迭代而增加。
我用来测试的数据非常匹配,实际上我事先知道映射,所以算法应该很快收敛。我已经验证了我的最近点匹配工作,所以我认为“总”旋转和平移的计算是问题所在。这是实现这个的正确方法还是我做错了什么?