3

我一直无法将欧拉角从旋转矩阵中取出。

我的约定是:

  • 左撇子(x 右,z 后,y 上)
  • 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)};
};

我已经前后计算了几次,但我看不出有什么问题。任何帮助将不胜感激。

4

3 回答 3

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 没有单一的约定。在某些编程语言中,正弦项是第一个参数,而在其他编程语言中,余弦项是第一个参数。

于 2011-06-28T11:55:24.043 回答
1

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

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

因为只有和m.e(3, 1)应该倒置。我还没有检查其他分支是否有错误。m.e(1, 1) = cy.czm.e(3, 1) = -sy.cz

请注意,由于sz = m.e(2, 1)有两种解决方案,(x, y, z)用于构造矩阵的角度m可能(rx, ry, rz)anglesFromMatrix(m). 相反,我们可以测试rm构造自的矩阵(rx, ry, rz)确实等于m

于 2011-06-28T12:49:20.750 回答
0

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

于 2014-09-09T12:28:50.573 回答