Eric
Eric

Reputation: 19863

How to convert ZXZ rotation matrix to Euler angles?

I'm using Catia software. When I query the position of an object inside my CAD drawing, the system returns a 3x4 matrix

[Rotations | Translations]

I think that the Rotations are expressed in a ZXZ fashion but for further processing I'd like to convert that rotation matrix to a XYZ notation, is this something doable?

Edit:

My object is positionned at [ 0, 0, 1000 ] the orientation given by Catia is

R = [ 1  0  0 ]  
    [ 0  0  1 ]  
    [ 0 -1  0 ]

When I try to multiply my own point [ 0, 0, 50 ] ( just an offset on the Z axis )

P1 = [ 0  ]
     [ 0  ]
     [ 50 ]

R*P1 = [ 0  ]
       [ 50 ]
       [ 0  ]

This is what lead me to believe that the rotation matrix is not XYZ with right hand notation.

Upvotes: 2

Views: 6417

Answers (4)

John Alexiou
John Alexiou

Reputation: 29244

I just tested this code and it works ok. It goes through all the alternatives for angles and returns the ones closest to 0.

public class Matrix3
{
    double a11,a13,a13,a21,a22,a23,a31,a32,a33;

    public void GetEulerZXZDegree(out double a, out double b, out double c)
    {
        GetEulerZXZ(out a, out b, out c);
        a*=180/Math.PI;
        b*=180/Math.PI;
        c*=180/Math.PI;
    }
    public void GetEulerZXZ(out double a, out double b, out double c)
    {
        // Options
        double[] a_list=new double[] { Math.Atan2(-a13, a23), Math.Atan2(a13, -a23) };
        double[] c_list=new double[] { Math.Atan2(a31, a32), Math.Atan2(-a31, -a32) };
        double[] b_list=new double[] { Math.PI/2-Math.Asin(a33), -Math.PI/2+Math.Asin(a33) };

        int min_a_index=FindMinAbsIndex(a_list);
        int min_b_index=FindMinAbsIndex(b_list);
        int min_c_index=FindMinAbsIndex(c_list);

        a=a_list[min_a_index];
        b=b_list[min_b_index];
        c=c_list[min_c_index];
    }
    public void GetEulerZYXDegree(out double a, out double b, out double c)
    {
        GetEulerZYX(out a, out b, out c);
        a*=180/Math.PI;
        b*=180/Math.PI;
        c*=180/Math.PI;
    }
    public void GetEulerZYX(out double a, out double b, out double c)
    {
        // Options
        double[] a_list=new double[] { Math.Atan2(a21, a11), Math.Atan2(-a21, -a11) };
        double[] c_list=new double[] { Math.Atan2(a32, a33), Math.Atan2(-a32, -a33) };
        double[] b_list=new double[] { -Math.Asin(a31), Math.Asin(a31)-Math.PI };

        int min_a_index=FindMinAbsIndex(a_list);
        int min_b_index=FindMinAbsIndex(b_list);
        int min_c_index=FindMinAbsIndex(c_list);

        a=a_list[min_a_index];
        b=b_list[min_b_index];
        c=c_list[min_c_index];
    }

    // This returns the index of the smallest number
    public static int FindMinAbsIndex(double[] list)
    {
        if(list.Length==0) return -1;
        double x=Math.Abs(list[0]);
        int index=0;
        for(int i=1; i<list.Length; i++)
        {
            if(Math.Abs(list[i])<x)
            {
                index=i;
                x=Math.Abs(list[i]);
            }
        }
        return index;
    }
}

Here is a unit test:

    /// <summary>
    ///A test for GetEulerZXZDegree
    ///</summary>
    [TestMethod()]
    public void GetEulerZXZDegreeTest()
    {
        // Make matrix from three rotations
        // RZ(75)*RX(22)*RZ(-12)
        Matrix3 target = 
            Rotations.RotateZDegrees( 75)*
            Rotations.RotateXDegrees( 22)*
            Rotations.RotateZDegrees(-12);
        //Matrix3 target=new Matrix3(
        //    0.439367031912771, -0.822208517146682, 0.361842183278486,
        //    0.894924870582839, 0.435556129311581, -0.0969553207969503,
        //    -0.0778850902285301, 0.366420540568700, 0.927183854566759);
        double a;
        double aExpected=75;
        double b;
        double bExpected=22;
        double c;
        double cExpected=-12;
        target.GetEulerZXZDegree(out a, out b, out c);
        Assert.AreEqual(aExpected, a, 1e-8);
        Assert.AreEqual(bExpected, b, 1e-8);
        Assert.AreEqual(cExpected, c, 1e-8);
    }

Upvotes: 1

Archie
Archie

Reputation: 2672

You may think of your 3x4 transformation matrix as a set of three unit vectors that define transformed coordinate system axes (first three columns of the matrix) and an origin of that coordinate system (fourth column). For your case the unit vectors are:
X = (1, 0, 0)
Y = (0, 0, -1)
Z = (0, 1, 0)
So in your transformed system, X axis is the same as original one, Y became -Z, and Z became +Y. That is actually a 90 degrees rotation around X axis (when Z turns towards Y).

Upvotes: 0

Pavel Radzivilovsky
Pavel Radzivilovsky

Reputation: 19104

Who gives matrices in ZXZ notation? Are you sure it is the format?

If it's a regular roation matrix, then you should start by taking a unit vector along one of the axes and see where the transformation brings it. It will give you two of the euler angles. To get the third, you need to consider a plane generated by two vectors.

Upvotes: 0

Alexandre C.
Alexandre C.

Reputation: 56956

I'm afraid you'll have to work out the math.

Upvotes: 0

Related Questions