2011-06-28 9 views
3

Je me suis retrouvé coincé à faire sortir mes angles d'Euler de ma matrice de rotation.Problème avec les angles d'Euler de la matrice de rotation YZX

Mes conventions sont les suivantes:

  • gaucher (x droite, z arrière, y up)
  • YZX
  • rotation angle gaucher

Ma matrice de rotation est constitué des angles d'Euler comme (de mon code):

var xRotationMatrix = $M([ 
     [1, 0, 0, 0], 
     [0, cx, -sx, 0], 
     [0, sx, cx, 0], 
     [0, 0, 0, 1] 
    ]); 

    var yRotationMatrix = $M([ 
     [ cy, 0, sy, 0], 
     [ 0, 1, 0, 0], 
     [-sy, 0, cy, 0], 
     [ 0, 0, 0, 1] 
    ]); 
    var zRotationMatrix = $M([ 
     [cz, -sz, 0, 0], 
     [sz, cz, 0, 0], 
     [ 0, 0, 1, 0], 
     [ 0, 0, 0, 1] 
    ]); 

Quels sont les résultats dans une matrice de rotation finale:

R(YZX) = | cy.cz, -cy.sz.cx + sy.sx, cy.sz.sx + sy.cx, 0| 
     | sz,    cz.cx,   -cz.sx, 0| 
     |-sy.cz, sy.sz.cx + cy.sx, -sy.sz.sx + cy.cx, 0| 
     |  0,     0,     0, 1| 

Je calculer mes angles euler retour de cette matrice en utilisant ce code:

this.anglesFromMatrix = function(m) { 
    var y = 0, x = 0, z = 0; 

    if (m.e(2, 1) > 0.999) { 
     y = Math.atan2(m.e(1, 3), m.e(3, 3)); 
     z = Math.PI/2; 
     x = 0; 
    } else if (m.e(2, 1) < -0.999) { 
     y = Math.atan2(m.e(1, 3), m.e(3, 3)); 
     z = -Math.PI/2; 
     x = 0; 
    } else { 
     y = Math.atan2(-m.e(3, 1), -m.e(1, 1)); 
     x = Math.atan2(-m.e(2, 3), m.e(2, 2)); 
     z = Math.asin(m.e(2, 1)); 
    } 
    return {theta: this.deg(x), phi: this.deg(y), psi: this.deg(z)}; 
}; 

Je l'ai fait les mathématiques avant et en arrière quelques fois, mais je ne peux pas voir ce qui ne va pas. Toute aide serait grandement appréciée.

+0

S'il vous plaît poser votre question sur http://math.stackexchange.com/ –

+3

Je l'aurais fait, mais il y a beaucoup plus de matériel sur la rotation 3D sur stackoverflow. Et math.stackexchange prétend être le site "pour les personnes qui étudient les mathématiques ou dans les professions liées aux mathématiques". Cela m'exclut. –

+3

@ Scorpi0: Ceci est une question appropriée ici. @Brendon: Votre code semble correct. J'essaierais les cas triviaux: faites pivoter +90 deg autour de l'axe X et vérifiez le résultat. Puis autour de l'axe Y et ainsi de suite. Une seule rotation à la fois, et toujours à partir de l'état d'origine, pas de rotations consécutives. – Ali

Répondre

2

Vos angles de matrice et d'euler ne sont pas cohérents. Il semble que vous devriez utiliser

y = Math.atan2(-m.e(3, 1), m.e(1, 1)); 

au lieu de

y = Math.atan2(-m.e(3, 1), -m.e(1, 1)); 

pour le cas général (la branche d'autre).

J'ai dit "ressemble" parce que - quelle langue est-ce? Je suppose que vous avez l'indexation correcte pour cette langue. Êtes-vous sûr d'atan2? Il n'y a pas de convention unique pour atan2. Dans certains langages de programmation, le terme sinus est le premier argument, dans d'autres, le terme cosinus est le premier argument.

+0

Je savais que ça allait descendre à 1 personnage! Tu as fait ma journée. J'ai retravaillé mes calculs tant de fois, mais mes yeux ont tendance à voir ce qu'ils veulent. –

1

La dernière branche la plus importante de la fonction anglesFromMatrix comporte une petite erreur de signe, mais fonctionne autrement correctement. Utilisez

y = Math.atan2(-m.e(3, 1), m.e(1, 1)) 

depuis que m.e(3, 1) de m.e(1, 1) = cy.cz et m.e(3, 1) = -sy.cz doit être inversée. Je n'ai pas vérifié les autres branches pour les erreurs.

Prenez garde que depuis sz = m.e(2, 1) a deux solutions, les angles (x, y, z) utilisés pour construire la matrice m pourraient ne pas être les mêmes que les angles (rx, ry, rz) retournés par anglesFromMatrix(m). Au lieu de cela, nous pouvons tester que la matrice rm construite à partir de (rx, ry, rz) est en effet égale à m.

+0

Merci @antonakos. Je viens de remarquer le problème des deux solutions (et le problème autour des pôles), et il en résulte actuellement une rotation à deux angles très sympa autour de ces points. Mais je pense que je peux programmer autour de cela en conduisant mes rotations avec des matrices et en utilisant juste les angles euler pour enregistrer l'état de repos. Merci pour votre réponse. –

+0

@Brendon: Le comportement autour des pôles est appelé "verrou cardan". Un moyen courant d'éviter ce problème dans les graphiques 3D est Quaternions. – Landei

0

J'ai beaucoup travaillé sur ce problème pour trouver les angles corrects pour une matrice donnée. Le problème dans le calcul vient de l'incapacité de déterminer une valeur précise pour le NAS puisque -SIN (x) = SIN (-x) et cela affectera les autres valeurs de la matrice. La solution que j'ai trouvée aboutit à deux solutions valables sur huit solutions possibles. J'ai utilisé un Z standard. Y. Forme matricielle X mais elle devrait pouvoir s'adapter à n'importe quelle matrice. Commencez par trouver les trois angles à partir de: X = atan (m32, m33): Y = -asin (m31): Z = atan (m21, m11): Ensuite, créez des angles X '= -sign (X) * PI + X: Y '= signe (Y) * PI-Y: Z = -sign (Z) * pi + Z.En utilisant ces angles, créez huit ensembles de groupes d'angles: XYZ: X'YZ: XYZ ': X'YZ': X'Y'Z ': XY'Z': X'Y'Z: XY'Z Utilisez ces paramètres pour créer les huit matrices correspondantes. Faites ensuite la somme de la différence entre la matrice inconnue et chaque matrice. C'est la somme de chaque élément de l'inconnu moins le même élément de la matrice de test. Après cela, deux des sommes seront égales à zéro et ces matrices représenteront les angles de la solution par rapport à la matrice d'origine. Cela fonctionne pour toutes les combinaisons d'angles possibles, y compris les 0. Lorsque les 0 sont introduits, plusieurs des huit matrices de test deviennent valides. A 0,0,0 ils deviennent tous des matrices d'idenity! J'espère que cela aide, cela a très bien fonctionné pour mon application. Après avoir trouvé des problèmes avec Y = -90 ou 90 degrés dans la solution ci-dessus Bruce mise à jour Après avoir trouvé des problèmes avec Y = -90 ou 90 degrés dans la solution ci-dessus. Je suis venu avec cette solution qui semble reproduire la matrice à toutes les valeurs! X = si (ou (m31 = 1, m31 = -1), 0, atan (m33 + 1e-24, m32)) Y = -asine (m31) Z = si (ou (m31 = 1, m31) = -1), - atan2 (m22, m12), atan2 (m11 + 1e-24, m21)) Je suis allé le long chemin pour trouver cette solution, mais c'était très éclairant: o) Espérons que cela aide! Bruce

+0

Note: J'essayais de recréer les angles que j'ai utilisés pour créer la matrice 3D. En utilisant cette solution, l'un des ensembles est toujours les angles originaux utilisés pour créer la matrice. Les deux ensembles de solutions sont exactement la même matrice sans aucun moyen de les distinguer du côté de la solution. –

Questions connexes