2012-03-19 1 views
5

Проблема, которую я имею, заключается в том, что мне нужно преобразовать из вращения неподвижной оси XYZ, к вращениям Эйлера вокруг Z, затем X ', затем Z' '.Преобразование из вращения Euler ZXZ, вращения неподвижной оси XYZ

Вот соответствующие матрицы:

X: X

Y: Y

Z: Z

Совмещенный, а Rz (фунтов на квадратный дюйм) Ry (фи) Rx (тета) = Rxyz (theta, phi, psi); они дают:

Rxyz: Rxyz

и матрица вращения для конкретной конвенции углов Эйлера я хочу; это:

Эйлер: Euler

Так что мой первоначальный план был для сравнения матричных элементов, и извлекать углы я хотел таким образом; Я пришел с этим (фактическим текущим кодом в конце):

Code

Но это не работает в нескольких случаях. Наиболее очевидное существо, когда Cos (theta) Cos (phi) == 1; с тех пор Cos (beta) = 1, и поэтому Sin [beta] = 0. Если Sin (бета) является s2 в коде. Это происходит только тогда, когда Cos (theta) и cos (phi) = +/- 1.

Так что я сразу могу исключить возможные ситуации;

Когда тета или phi = 0, 180, 360, 540, ..., затем Cos (тета) и Cos (phi) равны +/- 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(γ)}; 
} 

Где г и эк лишь две простые функции;

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); 
} 

эк просто сравнить цифры для испытаний, а г предотвратить с плавающей запятой ошибки маневрового числа вне диапазона Math.acos/Math.asin и давая мне результаты NaN;

(т.е. каждый сейчас и потом я бы в конечном итоге с Math.acos (1.000000000000000004) или что-то.)

который учитывает 4 случая наличия вращения вокруг х и у, которые оставляют с2 == 1 ,

Но теперь возникает проблема;

Все, что я сделал выше, имеет смысл для меня, но оно не дает правильных углов;

Вот несколько выходных данных в каждой паре, первые - тета phi psi, а вторая из каждой пары - соответствующие альфа-бета-гамма-линии.Не обращая внимания на ошибки округления, это, кажется, получить некоторые из углов от примерно

[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 работа, Может кто-нибудь придумать решение?

EDIT: math.asin и math.acos возвращают значения между -pi/2 и pi/2 и 0 и pi соответственно. Это не двусмысленно, поэтому я не думаю, что проблема здесь. Похоже, что я, возможно, математика неправильно где-то, но я не могу видеть дыру в моем рассуждении ...

EDIT2: Для тех, кто, как не знает, как работать Эйлер вращение, это так:

Euler Angles Gif

то есть, вращается вокруг Z, а затем вокруг новых Х осей (Х»), а затем вокруг нового Z '' оси.

+0

У углов Эйлера есть двусмысленности в 90-е годы - я думаю, 0/45/0 эквивалентен 90/45/-90, если я правильно понимаю ваши оси. –

+0

углы Эйлера вращаются вокруг Z, тогда X ', затем Z' ', поэтому 0/45/0 составляет 45 относительно оси X, а 90/45/-90 вращает оси так, что ось X' такая же, как ось Y. 90/45/-90 - это поворот 45 по сравнению с Y. – will

ответ

1

Я не совсем понял это, но одно, что я заметил: вы используете функции arccos/arcsin, как если бы cos/sin были биективными, просто принимая их обратные. Однако, беря arccos, рассмотрите general solutions для функций дуги. Например, когда cos y = x, то есть два (ну, бесконечно много) решений:

  • y = arccos x + 2kPI, где k element Z
  • y = 2PI - arccos x + 2kPI, к, как указано выше

С k=-1, последнее уравнение сводится к

  • y = -arccos x

Итак, всего y = +- arccos x. Это, по существу, сводится к тому, что cos аксиально симметрично x=0. Аналогичное рассуждение относится и к arcsin, что приводит к y = PI - asin xk=0 в общем решении sin y = x)

Это мгновенное относится к коду. Заявление γ = Math.acos(r(c3)); должно каким-то образом учитывать этот знак. Я борюсь с этим, должны быть критерии для определения «неправильного» решения.

+0

Я тоже заметил это, из-за того, что каждый раз, когда acos/asin был использован, были неприятны ответы на неверные ответы. Мне казалось, что вам нужно запустить небольшой набор тестов на 4 возможных ответа на +/- могут возникнуть неоднозначности, а затем выбор ответа, который сработал. Запуск тестового набора каждый раз заставлял бы испортить аккуратность решения, которое я не был слишком большим поклонником. – will

+0

Я тоже задал этот вопрос, http://math.stackexchange.com/questions/122162/convert-from-fixed-axis-xyz-rotations-to-euler-zxz-rotations и просто решил использовать ZXZ вместо Z''X'Z эйлера. Тем не менее, это не идеальный вариант. – will

+0

Итак, я наконец-то кое-что прочитал обо всем этом гадости. Выяснили, как это сделать и ответили [здесь] (http://math.stackexchange.com/a/637534/27211). – will

 Смежные вопросы

  • Нет связанных вопросов^_^