YZX旋转矩阵的欧拉角问题

时间:2011-06-28 09:55:27

标签: math 3d rotation euler-angles

我已经陷入困境,让我的旋转角度超出我的旋转矩阵。

我的约定是:

  • 左撇子(x右,后仰,右上)
  • YZX
  • 左手角度旋转

我的旋转矩阵是从欧拉角(如我的代码)构建的:

    var xRotationMatrix = $M([
        [1,  0,   0, 0], 
        [0, cx, -sx, 0], 
        [0, sx,  cx, 0], 
        [0,  0,   0, 1]
    ]);

    var yRotationMatrix = $M([
        [ cy, 0, sy, 0], 
        [  0, 1,  0, 0], 
        [-sy, 0, cy, 0], 
        [  0, 0,  0, 1]
    ]);
    var zRotationMatrix = $M([
        [cz, -sz, 0, 0], 
        [sz,  cz, 0, 0], 
        [ 0,   0, 1, 0], 
        [ 0,   0, 0, 1]
    ]);

这导致最终的旋转矩阵为:

R(YZX) = | cy.cz, -cy.sz.cx + sy.sx,  cy.sz.sx + sy.cx, 0|
         |    sz,             cz.cx,            -cz.sx, 0|
         |-sy.cz,  sy.sz.cx + cy.sx, -sy.sz.sx + cy.cx, 0|
         |     0,                 0,                 0, 1|

我正在使用以下代码从此矩阵计算我的欧拉角:

this.anglesFromMatrix = function(m) {
    var y = 0, x = 0, z = 0;

    if (m.e(2, 1) > 0.999) {
        y = Math.atan2(m.e(1, 3), m.e(3, 3));
        z = Math.PI / 2;
        x = 0;
    } else if (m.e(2, 1) < -0.999) {
        y = Math.atan2(m.e(1, 3), m.e(3, 3));
        z = -Math.PI / 2;
        x = 0;
    } else {
        y = Math.atan2(-m.e(3, 1), -m.e(1, 1));
        x = Math.atan2(-m.e(2, 3), m.e(2, 2));
        z = Math.asin(m.e(2, 1));
    }
    return {theta: this.deg(x), phi: this.deg(y), psi: this.deg(z)};
};

我已经向后退几次数学,但我看不出有什么问题。任何帮助都会非常感激。

3 个答案:

答案 0 :(得分:2)

您的矩阵和欧拉角不一致。看起来你应该使用

y = Math.atan2(-m.e(3, 1), m.e(1, 1));

而不是

y = Math.atan2(-m.e(3, 1), -m.e(1, 1));

一般情况(else分支)。

我说“看起来像”因为 - 这是什么语言?我假设你有这种语言的索引正确。你确定atan2吗? atan2没有单一的约定。在某些编程语言中,正弦项是第一个参数,在其他语言中,余弦项是第一个参数。

答案 1 :(得分:1)

anglesFromMatrix函数的最后一个也是最重要的分支有一个小符号错误,但在其他方面正常工作。使用

y = Math.atan2(-m.e(3, 1), m.e(1, 1))

因为只有m.e(3, 1)m.e(1, 1) = cy.cz的{​​{1}}应该被倒置。我没有检查其他分支是否有错误。

请注意,由于m.e(3, 1) = -sy.cz有两个解,因此用于构造矩阵sz = m.e(2, 1)的角度(x, y, z)可能与{{1}返回的角度m不同}}。相反,我们可以测试从(rx, ry, rz)构造的矩阵anglesFromMatrix(m)确实等于rm

答案 2 :(得分:0)

我广泛地研究了这个问题,为给定的矩阵提出了正确的角度。数学中的问题来自于无法确定SIN的精确值,因为-SIN(x)= SIN(-x),这将影响矩阵的其他值。我提出的解决方案在八种可能的解决方案中提出了两种同样有效的解决方案。我使用标准Z.是的X矩阵形式但它应适用于任何矩阵。从以下三个角度开始:X = atan(m32,m33):Y = -asin(m31):Z = atan(m21,m11):然后创建角度X&#39; = -sign(X)* PI + X:Y&#39; =符号(Y)* PI-Y:Z = -sign(Z)* pi + Z.使用这些角度创建八组角度组:XYZ:X&#39; YZ:XYZ&#39; :X&#39; YZ&#39; :X&#39; Y&#39; Z&#39; :XY&#39; Z&#39; :X&#39; Y&#39; Z:XY&#39; Z. 使用这些集创建八个相应的矩阵。然后对未知矩阵和每个矩阵之间的差值求和。这是未知的每个元素减去测试矩阵的相同元素的总和。在这样做之后,两个和将为零,并且那些矩阵将表示与原始矩阵的解角。这适用于所有可能的角度组合,包括0&#39; s。随着0的引入,八个测试矩阵中的更多矩阵变得有效。在0,0,0它们都成为同一性矩阵! 希望这有帮助,它对我的​​应用程序非常有效。 布鲁斯 的 更新 在上述解决方案中发现Y = -90或90度的问题后。我想出了这个似乎在所有值上重现矩阵的解决方案!     X = if(或(m31 = 1,m31 = -1),0,atan(m33 + 1e-24,m32))     Y = -asin(m31)     Z = if(或(m31 = 1,m31 = -1), - atan2(m22,m12),atan2(m11 + 1e-24,m21)) 我走了很长的路要找到这个解决方案,但它很有启发性:o) 希望这可以帮助! 布鲁斯