Как преобразовать матрицу вращения ZXZ в углы Эйлера? - PullRequest
1 голос
/ 23 июня 2010

Я использую программное обеспечение Catia. Когда я запрашиваю положение объекта внутри чертежа САПР, система возвращает матрицу 3х4

[Вращения | Перевод]

Я думаю, что Вращения выражены в виде ZXZ, но для дальнейшей обработки я хотел бы преобразовать эту матрицу вращения в нотацию XYZ, это выполнимо?

Edit:

Мой объект расположен на [0, 0, 1000] ориентация, данная Катейей, составляет

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

Когда я пытаюсь умножить свою точку [0, 0, 50] (просто смещение по оси Z) * ​​1012 *

P1 = [ 0  ]
     [ 0  ]
     [ 50 ]

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

Это то, что привело меня к мысли, что матрица вращения - это не XYZ с правым обозначением.

Ответы [ 4 ]

0 голосов
/ 06 февраля 2013

Я только что проверил этот код, и он работает нормально.Он проходит все альтернативы для углов и возвращает те, которые ближе всего к 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;
    }
}

Вот модульный тест:

    /// <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);
    }
0 голосов
/ 23 июня 2010

Кто дает матрицы в нотации ZXZ?Вы уверены, что это формат?

Если это обычная матрица вращения, то вам следует начать с переноса единичного вектора вдоль одной из осей и посмотреть, куда его приводит преобразование.Это даст вам два угла Эйлера.Чтобы получить третий, вам нужно рассмотреть плоскость, порожденную двумя векторами.

0 голосов
/ 25 июня 2010

Вы можете думать о своей матрице преобразования 3x4 как о наборе трех единичных векторов, которые определяют преобразованные оси системы координат (первые три столбца матрицы) и источник этой системы координат (четвертый столбец). Для вашего случая единичные векторы: <br> X = (1, 0, 0)<br> Y = (0, 0, -1)<br> Z = (0, 1, 0)<br> Таким образом, в вашей преобразованной системе ось X совпадает с исходной, Y стала -Z, а Z стала + Y. На самом деле это поворот на 90 градусов вокруг оси X (когда Z поворачивается к Y).

0 голосов
/ 23 июня 2010

Боюсь, вам придется отработать математику .

...