在乘以大量旋转矩阵后,由于舍入问题(去正交化),最终结果可能不再是有效的旋转矩阵
重新正交化的一种方法是遵循以下步骤:
答案 0 :(得分:10)
我不使用Eigen,也没有费心去查找API,但这里是一个简单,计算上便宜且稳定的程序来重新正交化旋转矩阵。该正交化过程取自Direction Cosine Matrix IMU: Theory William Premerlani和Paul Bizard;方程19-21。
让x
,y
和z
成为(略微混乱)旋转矩阵的行向量。让error=dot(x,y)
其中dot()
是点积。如果矩阵是正交的,x
和y
的点积,即error
将为零。
error
分布在x
和y
上:x_ort=x-(error/2)*y
和y_ort=y-(error/2)*x
。第三行z_ort=cross(x_ort, y_ort)
,根据定义与x_ort
和y_ort
正交。
现在,您仍然需要对x_ort
,y_ort
和z_ort
进行标准化,因为这些向量应该是单位向量。
x_new = 1/2*(3-dot(x_ort,x_ort))*x_ort
y_new = 1/2*(3-dot(y_ort,y_ort))*y_ort
z_new = 1/2*(3-dot(z_ort,z_ort))*z_ort
就是这样,已经完成了。
使用Eigen提供的API实现它应该很容易。您可以轻松地提出其他正交化程序,但我认为它不会在实践中产生明显的差异。我在我的运动跟踪应用程序中使用了上述程序,并且它工作得非常好;它既稳定又快速。
答案 1 :(得分:1)
与此同时:
#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;
这是一个好消息,因为我可以摆脱我的自定义方法,让人头疼一点(怎么能确定他能处理所有奇点呢?),
但我真的希望你对更好/替代的方式发表意见:)
答案 2 :(得分:1)
Singular Value Decomposition应该非常强大。引用参考文献:
设M =UΣV是M的奇异值分解,则R = UV。
对于矩阵,Σ中的奇异值应非常接近1。矩阵R保证为orthogonal,这是旋转矩阵的定义属性。如果在计算原始旋转矩阵时没有任何舍入误差,则R将与数值精度内的M完全相同。
答案 3 :(得分:0)
另一种方法是使用Eigen::Quaternion
来表示您的轮换。这很容易标准化,并且rotation*rotation
产品通常更快。如果您有很多rotation*vector
产品(具有相同的矩阵),则应将四元数局部转换为3x3矩阵。