从欧拉ZXZ旋转转换到固定轴XYZ旋转

我有的问题是,我需要从XYZ固定轴旋转转换到欧拉旋转大约Z,然后X',然后Z''。

这里是相关的矩阵:

X:

Y:

Z:

组合,如Rz(psi)Ry(R)Rx(theta)= Rxyz(theta,phi,psi); 他们给:

Rxyz: Rxyz

和我想要的欧拉角具体惯例的旋转矩阵; 这是:

欧拉: 欧拉

所以我最初的计划是比较矩阵元素,并提取我想要的角度; 我想出了这个(最终的实际当前代码):

码

但在几种情况下这不起作用。 Cos(theta)Cos(phi)== 1; 此后Cos(β)= 1,因此Sinβ= 0。其中Sin(β)是代码中的s2。 这只有在Cos(theta)和cos(phi)= +/- 1时才会发生。

所以我马上就可以排除可能的情况;

当theta或phi = 0,180,360,540,...时,则Cos(θ)和Cos(φ)是+/- 1;

所以我只需要为这些情况做不同的处理;

我结束了这段代码:

public static double[] ZXZtoEuler(double θ, double φ, double ψ){

    θ *= Math.PI/180.0;
    φ *= Math.PI/180.0;
    ψ *= Math.PI/180.0;

    double α = -1;
    double β = -1;
    double γ = -1;

    double c2 = Math.cos(θ) * Math.cos(φ);

    β = Math.acos(r(c2));

    if(eq(c2,1) || eq(c2,-1)){
        if(eq(Math.cos(θ),1)){
            if(eq(Math.cos(φ),1)){
                α = 0.0;
                γ = ψ;
            }else if(eq(Math.cos(φ),-1)){
                α = 0.0;
                γ = Math.PI - ψ;
            }
        }else if(eq(Math.cos(θ),-1)){
            if(eq(Math.cos(φ),1)){
                α = 0.0;
                γ = -ψ;
            }else if(eq(Math.cos(φ),-1)){
                α = 0.0;
                γ = ψ + Math.PI;
            }
        }
    }else{

        //original way

        double s2 = Math.sin(β);

        double c3 = ( Math.sin(θ) * Math.cos(φ) )/ s2;
        double s1 = ( Math.sin(θ) * Math.sin(ψ) + Math.cos(θ) * Math.sin(φ) * Math.cos(ψ) )/s2;

        γ = Math.acos(r(c3));
        α = Math.asin(r(s1));

    }

    α *= 180/Math.PI;
    β *= 180/Math.PI;
    γ *= 180/Math.PI;

    return new double[] {r(α), r(β), r(γ)};
}

r和eq只是两个简单的函数;

public static double r(double a){
    double prec = 1000000000.0;
    return Math.round(a*prec)/prec;
}

static double thresh = 1E-4;
public static boolean eq(double a, double b){
    return (Math.abs(a-b) < thresh);
}

eq只是比较测试的数字,而r是为了防止浮点错误将数字推到Math.acos / Math.asin范围之外,并给出NaN结果;

(即每隔一段时间我最终会得到Math.acos(1.000000000000000004))。

其中考虑了围绕x和y旋转的4个案例,其中c2 == 1。

但现在是问题发生的地方;

上面所做的一切都对我有意义,但它并没有给出正确的角度。

这里是一些输出,在每一对中,第一个是theta phi psi角度,并且每一对中的第二个是相应的alpha beta伽玛线。 忽略四舍五入错误,它似乎正在得到一些关闭的角度

[0.0, 0.0, 0.0] - correct!
[0.0, 0.0, 0.0]

[0.0, 0.0, 45.0] - correct!
[0.0, 0.0, 45.0]

[0.0, 0.0, 90.0] - correct!
[0.0, 0.0, 90.0]

[0.0, 0.0, 135.0] - correct!
[0.0, 0.0, 135.0]

[0.0, 0.0, 180.0] - correct
[0.0, 0.0, 180.0]

[0.0, 0.0, 225.0] - correct
[0.0, 0.0, 225.0]

[0.0, 0.0, 270.0] - correct
[0.0, 0.0, 270.0]

[0.0, 0.0, 315.0] - correct
[0.0, 0.0, 315.0]

[0.0, 45.0, 0.0] - incorrect: should be [90, 45, -90]
[90.0, 44.999982, 90.0]

[0.0, 45.0, 45.0]
[45.000018, 44.999982, 90.0]

[0.0, 45.0, 90.0]
[0.0, 44.999982, 90.0]

[0.0, 45.0, 135.0]
[-45.000018, 44.999982, 90.0]

[0.0, 45.0, 180.0]
[-90.0, 44.999982, 90.0]

[0.0, 45.0, 225.0]
[-45.000018, 44.999982, 90.0]

[0.0, 45.0, 270.0]
[0.0, 44.999982, 90.0]

[0.0, 45.0, 315.0]
[45.000018, 44.999982, 90.0]

[0.0, 90.0, 0.0]
[90.0, 90.0, 90.0]

[0.0, 90.0, 45.0]
[45.000018, 90.0, 90.0]

[0.0, 90.0, 90.0]
[0.0, 90.0, 90.0]

[0.0, 90.0, 135.0]
[-45.000018, 90.0, 90.0]

[0.0, 90.0, 180.0]
[-90.0, 90.0, 90.0]

[0.0, 90.0, 225.0]
[-45.000018, 90.0, 90.0]

我认为这是Math.acos和Math.asin工作方式的原因,任何人都可以想出解决方案吗?

编辑:math.asin和math.acos分别返回-pi / 2和pi / 2以及0和pi之间的值。 这并不含糊,所以我不认为问题在这里。 看起来我可能在某个地方有数学错误,但我在推理中看不到一个洞。

编辑2:对于任何人来说,如何不知道欧拉旋转是如何工作的,就像这样:

欧拉角度Gif

也就是说,围绕Z旋转,围绕新的X轴(X'),然后围绕新的Z“轴旋转。


我还没有完全想到这一点,但我注意到一件事:你使用arccos / arcsin函数,就好像cos / sin是双射的,只是反过来。 但是,在采用arccos时,应考虑弧函数的一般解。 例如,当cos y = x ,则有两个(很好,无限多)解:

  • y = arccos x + 2kPI ,其中k element Z
  • y = 2PI - arccos x + 2kPI ,k如上所述
  • k=-1 ,最后一个方程减小到

  • y = -arccos x
  • 所以y = +- arccos xy = +- arccos x 。 这基本上归结为cos轴对称于x=0的事实。 一个类似的论点适用于arcsin ,导致y = PI - asin x (在sin y = x的一般解中k=0

    这立即适用于您的代码。 声明γ = Math.acos(r(c3)); 不知何故必须考虑到这个标志。 我与这一个斗争,必须有一个标准来梳理“不正确”的解决方案。

    链接地址: http://www.djcxy.com/p/85003.html

    上一篇: Converting from a Euler ZXZ rotation, to fixed axis XYZ rotations

    下一篇: Interpolate x, y, z coordinates on a sphere using points from two spin vectors?