2012-03-19 33 views
5

El problema que tengo, es que necesito convertir rotaciones de eje fijo XYZ, rotaciones de Euler sobre Z, luego X ', luego Z' '.Convirtiendo desde una rotación de Euler ZXZ a rotaciones de eje fijo XYZ

Aquí son las matrices relevantes:

X: X

Y: Y

Z: Z

combinada, como Rz (psi) Ry (phi) Rx (theta) = Rxyz (theta, phi, psi); que os den

Rxyz: Rxyz

Y la matriz de rotación para la convención específica de los ángulos de Euler que quiero; es la siguiente:

Euler: Euler

Así que mi plan inicial, fue comparar elementos de la matriz, y extraer los ángulos que yo quería de esa manera; Se me ocurrió esto (código actual real al final):

Code

Pero esto no funciona en varias circunstancias. El ser más obvio cuando Cos (theta) Cos (phi) == 1; desde entonces Cos (beta) = 1, y entonces Sin [beta] = 0. Donde Sin (beta) es s2 en el código. Esto ocurre solo cuando Cos (theta) y cos (phi) = +/- 1.

Así que de inmediato puedo descartar las posibles situaciones;

Cuando theta o phi = 0, 180, 360, 540, ..., entonces Cos (theta) y Cos (phi) son +/- 1;

así que solo tengo que hacerlo de manera diferente para estos casos;

y terminé con este código:

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

donde R y eq son sólo dos funciones simples;

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 es sólo para comparar los números para las pruebas, y r es para evitar errores puntuales que empujan los números fuera del rango de Math.acos/Math.asin y me dan resultados NaN flotante;

(es decir, de vez en cuando que terminaría siendo con Math.acos (1,000000000000000004) o algo así.)

que tiene en cuenta los 4 casos de tener rotaciones alrededor de x e y que dejan c2 == 1 .

Pero ahora es donde ocurre el problema;

Todo lo que he hecho anteriormente, tiene sentido para mí, pero no da los ángulos correctos;

Aquí hay alguna salida, en cada par, los primeros son los ángulos theta phi psi, y el segundo de cada par son las líneas alfa gamma correspondientes.Haciendo caso omiso de los errores de redondeo, que parece ser cada vez algunos de los ángulos fuera en alrededor de

[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] 

creo que es debido a la forma Math.acos y Math.asin trabajo, ¿Puede alguien pensar en una solución?

EDITAR: math.asin y math.acos devuelven valores entre -pi/2 y pi/2 y 0 y pi respectivamente. Esto no es ambiguo, así que no creo que el problema esté aquí. Parece como si pudiera tener las matemáticas mal en alguna parte, pero no puedo ver un agujero en mi razonamiento ...

Edit2: Para nadie cómo no saben cómo funcionan las rotaciones de Euler, es como esto:

Euler Angles Gif

es decir, girar alrededor de Z, a continuación, alrededor del nuevo eje X (X'), entonces alrededor de la nueva Z '' eje.

+0

Los ángulos de Euler tienen ambigüedades a los 90 - Creo que 0/45/0 es equivalente a 90/45/-90 si entiendo tus ejes correctamente. –

+0

los ángulos de Euler giran alrededor de Z, luego X ', luego Z' ', entonces 0/45/0 es 45 sobre el eje X, mientras que 90/45/90 gira los ejes para que el eje X' sea el mismo que el eje Y 90/45/-90 es una rotación de 45 aproximadamente Y. – will

Respuesta

1

No me he dado cuenta completamente de esto, pero una cosa sí noté: Usas las funciones arccos/arcsin como si cos/sin fuera bijectivo, simplemente tomando su inverso. Sin embargo, al tomar los arcos, considere el general solutions para las funciones de arco. Por ejemplo, cuando cos y = x, a continuación, hay dos (así, infinitamente muchos) soluciones:

  • y = arccos x + 2kPI, donde k element Z
  • y = 2PI - arccos x + 2kPI, k como anteriormente

Con k=-1, la última ecuación se reduce a

  • y = -arccos x

En total, y = +- arccos x. Esto se reduce esencialmente al hecho de que cos es axialmente simétrica a x=0. Un argumento análogo se aplica a arcsin, lo que lleva a y = PI - asin x (con k=0 en la solución general de sin y = x)

Este immediatelly se aplica a su código. La declaración γ = Math.acos(r(c3)); de alguna manera debe tomar el signo en cuenta. Lucho con este, debe haber un criterio para resolver la solución "incorrecta".

+0

Me di cuenta de esto también, la molestia de eliminar las respuestas incorrectas cada vez que se usaba acos/asin parecía desalentador - imaginaba que necesitaba ejecutar un pequeño conjunto de pruebas en el 4 respuestas posibles que causarían las ambigüedades +/-, y luego seleccionando la respuesta que funcionó. Ejecutar un banco de pruebas siempre arruinaría la pulcritud de la solución, algo de lo que no era muy fanático. – will

+0

Hice la pregunta aquí también, http://math.stackexchange.com/questions/122162/convert-from-fixed-axis-xyz-rotations-to-euler-zxz-rotations y simplemente decidí usar el ZXZ rotaciones en lugar de Z''X'Z de euler. Sin embargo, aún no es ideal. – will

+0

Así que finalmente hice algunas lecturas sobre toda esta maldad. Descubrí cómo hacerlo y respondió [aquí] (http://math.stackexchange.com/a/637534/27211). – will

Cuestiones relacionadas