Algorithm 旋转矩阵的特征重正交化
在乘以大量旋转矩阵后,由于舍入问题(非正交化),最终结果可能不再是有效的旋转矩阵 重新正交化的一种方法是遵循以下步骤:Algorithm 旋转矩阵的特征重正交化,algorithm,math,rotation,eigen,rotational-matrices,Algorithm,Math,Rotation,Eigen,Rotational Matrices,在乘以大量旋转矩阵后,由于舍入问题(非正交化),最终结果可能不再是有效的旋转矩阵 重新正交化的一种方法是遵循以下步骤: 将旋转矩阵转换为轴角度表示形式() 将轴角度转换回旋转矩阵() 图书馆里有没有什么东西通过隐藏所有细节来做同样的事情?还是有更好的食谱 由于特殊的奇点情况,此过程必须小心处理,因此如果Eigen提供了一个更好的工具,这将是非常好的。我不使用Eigen,也没有费心查找API,但这里有一个简单、计算廉价且稳定的过程来重新正交旋转矩阵。此正交化过程取自 威廉·普莱梅兰尼和保罗·比扎德
由于特殊的奇点情况,此过程必须小心处理,因此如果Eigen提供了一个更好的工具,这将是非常好的。我不使用Eigen,也没有费心查找API,但这里有一个简单、计算廉价且稳定的过程来重新正交旋转矩阵。此正交化过程取自 威廉·普莱梅兰尼和保罗·比扎德;方程19-21 设
x
、y
和z
为(稍微混乱的)旋转矩阵的行向量。设error=dot(x,y)
其中dot()
是点积。如果矩阵是正交的,x
和y
的点积,即误差
为零
错误
平均分布在x
和y
上:x_-ort=x-(错误/2)*y
和y_-ort=y-(错误/2)*x
。第三行z_-ort=cross(x_-ort,y_-ort)
,根据定义,它与x_-ort
和y_-ort
正交
现在,您仍然需要规范化x_-ort
、y_-ort
和z_-ort
,因为这些向量应该是单位向量
x_new = 0.5*(3-dot(x_ort,x_ort))*x_ort
y_new = 0.5*(3-dot(y_ort,y_ort))*y_ort
z_new = 0.5*(3-dot(z_ort,z_ort))*z_ort
就这些,我们都做了
使用Eigen提供的API应该很容易实现这一点。你可以很容易地想出其他的拼音程序,但我不认为这会在实践中产生明显的不同。我在我的运动跟踪应用程序中使用了上述程序,它工作得非常好;它既稳定又快速。您可以使用QR分解系统地重新正交化,用Q因子替换原始矩阵。在库例程中,如有必要,您必须通过对Q中的相应列求反来检查和更正R的对角线项是否为正(如果原始矩阵接近正交,则接近1) 最接近给定矩阵的旋转矩阵Q由极分解或QP分解获得,其中p是半正定对称矩阵。QP分解可以迭代计算,也可以使用SVD计算。如果后者具有因子分解USV',则Q=UV.同时:
#include <Eigen/Geometry>
Eigen::Matrix3d mmm;
Eigen::Matrix3d rrr;
rrr << 0.882966, -0.321461, 0.342102,
0.431433, 0.842929, -0.321461,
-0.185031, 0.431433, 0.882966;
// replace this with any rotation matrix
mmm = rrr;
Eigen::AngleAxisd aa(rrr); // RotationMatrix to AxisAngle
rrr = aa.toRotationMatrix(); // AxisAngle to RotationMatrix
std::cout << mmm << std::endl << std::endl;
std::cout << rrr << std::endl << std::endl;
std::cout << rrr-mmm << std::endl << std::endl;
#包括
本征::矩阵3d-mmm;
本征::矩阵3D rrr;
rrr应该非常稳健。引用参考文献:
设M=U∑V为M的奇异值分解,则R=UV
对于矩阵,∑中的奇异值应该非常接近1。矩阵R保证为,这是旋转矩阵的定义性质。如果在计算原始旋转矩阵时没有任何舍入错误,那么R将与M完全相同,在数值精度范围内。另一种方法是使用特征::四元数来表示旋转。这更容易规范化,而且rotation*rotation
产品通常更快。如果你有很多旋转*向量的乘积(使用相同的矩阵),你应该将四元数局部转换成3x3矩阵。“感谢迄今为止的答案!”在Stackoverflow,我们不说谢谢,而是向上投票和/或接受答案。“一个人怎么能确定他处理了所有的奇点呢?”我猜它假设rrr
实际上是一个旋转矩阵。如果它不是(这就是你的问题所在,你的旋转矩阵被弄乱了),那么它很可能是做错了什么。这种方法似乎更像是一种特殊的破解,而不是一种解决方案。实际上不需要计算角度,只需将轴旋转矩阵相乘即可,而无需担心象限和奇点。这是使用Givens旋转方法进行的QR分解。如果您想改进A=QR分解,请检查R的非对角部分是否小,并使用Q*(I+(R-R')/2)作为更好的近似值。如果(R-I)稍大,则使用更好的近似值I+(R-R')/2+(R-R')^2/8或精确值来计算(R-R')/2的矩阵指数。(R'=R的转置,首先从矩阵中识别k,然后应用公式。)If肯定会给出比我的答案中的过程更好的结果,但代价是计算成本明显更高。是的,应该做最简单的事情。这个问题没有给出一个维度,所以它可能是3D的,就像你的答案一样,或者是其他的东西。[[Easy in 3D也是使用Givens旋转的QR分解(恰好使用旋转矩阵的Euler角表示)。编辑:我看到问题中提到了这一点,所以是3D。]]无论如何,至少我对你的答案投了赞成票。:)(虽然OP在我看来应该已经这样做了。)Hi Lutzl,在Eigen:rotation.householderQr().householderQ()中进行QR分解并获得Q矩阵很容易。不过,我不太熟悉户主的方法。这够好吗?另外,请您在回答中详细说明“检查并更正”和“否定相应列”作为额外步骤?任何参考资料或代码示例都会很好!通过将QR分解应用于单位矩阵I
进行测试。结果可能是[Q,R]=[-I,-I]
。这是因为Householder反射被选择为最稳定的,即避免被零或接近零分割。应该注意的是,这里的标准化过程使用泰勒展开来近似向量大小。如果高精度