Question

J'essaie de convertir une rotation 3D décrite en terme d'angles d'Euler en une matrice puis inversement, en utilisant .NET/C#.Mes conventions sont :

  • système pour gauchers (x à droite, y en haut, z en avant)
  • ordre des rotations :se diriger autour de y, tanguer autour de x, s'incliner autour de z
  • les rotations sont positives en utilisant la règle de la main gauche (pouce pointant vers + l'infini)

Mon essai est le suivant :

Euler à la matrice (J'ai supprimé la partie de traduction x, y, z pour des raisons de simplification)

Matrix3D matrix = new Matrix3D() {
    M11 =   cosH * cosB - sinH * sinP * sinB,
    M12 = - sinB * cosP,
    M13 =   sinH * cosB + cosH * sinP * sinB,
    M21 =   cosH * sinB + sinH * sinP * cosB,
    M22 =   cosB * cosP,
    M23 =   sinB * sinH - cosH * sinP * cosB,
    M31 = - sinH * cosP,
    M32 = - sinP,
    M33 =   cosH * cosP,
};

Matrice vers Euler

const double RD_TO_DEG = 180 / Math.PI;            
double h, p, b; // angles in degrees

// extract pitch
double sinP = -matrix.M23;            
if (sinP >= 1) {
    p = 90; }       // pole
else if (sinP <= -1) {
    p = -90; } // pole
else {
    p = Math.Asin(sinP) * RD_TO_DEG; }             

// extract heading and bank
if (sinP < -0.9999 || sinP > 0.9999) { // account for small angle errors
    h = Math.Atan2(-matrix.M31, matrix.M11) * RD_TO_DEG;
    b = 0; }
else {
    h = Math.Atan2(matrix.M13, matrix.M33) * RD_TO_DEG;
    b = Math.Atan2(matrix.M21, matrix.M22) * RD_TO_DEG; }

Cela doit être faux.Si je prends 3 angles, je les convertis en matrice et je reconvertis la matrice en angles, le résultat est différent des valeurs initiales.

J'ai parcouru plusieurs sites avec des formules différentes, à commencer par euclideanspace.com, mais je suis maintenant complètement perdu et je ne trouve pas les bons calculs.J'apprécie un peu d'aide.Y a-t-il un mathématicien à bord ?

Était-ce utile?

La solution

Tout d'abord, si:

sinP = -matrix.M32

EDIT: Solution complète suit

Ma dérivation:

Rx(P)=| 1      0       0 |
      | 0  cos P  -sin P |
      | 0  sin P   cos P |

Ry(H)=|  cos H  0  sin H |
      |      0  1      0 |
      | -sin H  0  cos H |

Rz(B)=| cos B  -sin B  0 |
      | sin B   cos B  0 |
      |     0       0  1 |

Multiplié avec votre commande:

R = Ry(H)*Rx(P)*Rz(B)
  = | cos H*cos B+sin H*sin P*sin B  cos B*sin H*sin P-sin B*cos H  cos P*sin H |
    |                   cos P*sin B                    cos B*cos P       -sin P |
    | sin B*cos H*sin P-sin H*cos B  sin H*sin B+cos B*cos H*sin P  cos P*cos H |

Ce qui donne inverse dérivations:

tan

B = M12 / M22

sin P = -m32

H = tan M31 / M33

Autres conseils

Votre idée est fausse :"Ça doit être faux.Si je prends 3 angles, je les convertis en matrice et je reconvertis la matrice en angles, le résultat est différent des valeurs initiales. " Cela aurait été beau, mais ce n'est pas nécessairement vrai.En général, plus d'un triplet d'angles d'Euler (convention fixe) conduit à la même orientation dans l'espace.Cela ne signifie pas pour autant qu’il n’y a pas d’erreur dans votre calcul.De Wikipédia :"Par exemple, supposons que nous utilisions la convention zyz ci-dessus ;alors nous avons les paires équivalentes suivantes :(90 °, 45 °, −105 °) ≡ (−270 °, −315 °, 255 °) Multiples de 360 ​​° (72 °, 0 °, 0 °) ≡ (40 °, 0 °, 32 °) Alignement (45 °, 60 °, −30 °) ≡ (−135 °, −60 °, 150 °) Flip bistable "

Il y a un grand nombre de combinaisons de ces fonctions que les changements de réponse en fonction de vos conventions. Je suis généralement en utilisant DirectX et les mêmes conventions que l'unité. De plus mon arrière-plan est flightsims, l'espace et des cartes, de sorte lacet puis plantez puis correspond à un style rouleau lat / long aussi.

Être clair sur les conventions ou ayant Compose désorienté / fonctions peuvent conduire se décomposent à des bugs très bizarres. Il convient également compte tenu du fait que plusieurs ensembles d'angles euler peuvent produire la même orientation.

Conventions (comme ci-dessus):

  • angles d'Euler: X = Pitch, Yaw Y = Z = Rouleau
  • ordre Euler: Rotation appliquée, puis lacet tangage puis rouler
  • Axes: + X Droite, Y + haut, + Z Forward
  • : conventions Matrices DirectX (en utilisant SimpleMath.h de MS DirectXTK )

Pour convertir à la version OpenGL, jetez un oeil à ce .

J'ai pris réponse de Mike Tunnicliffe et converti en code C ++ et ajouté à ma bibliothèque. J'espère que d'autres personnes de gagner du temps en l'utilisant.

A noter que la fonction de composition efface la quatrième colonne et le composant de traduction à l'identité, et la fonction de décomposer assume l'élément de rotation 3x3 contient rotation pure (c.-à-pas à l'échelle, etc.).

Tout d'abord le code pour générer une matrice de Eulers:

//====================================================================================================
// MatrixFromYawPitchRoll
//
// Create matrix based on provided yaw (heading), pitch and roll (bank).
//
// Assumptions:
//  Euler:   X = Pitch, Y = Yaw, Z = Roll
//  Applied: Yaw then pitch then roll
//  Axes:    X = Right, Y = Up, Z = Forward
//  DirectX: Matrices are row major (http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html)
//
// Code is based on Mike Tunnicliffe's answer to this question:
//   https://stackoverflow.com/questions/1996957/conversion-euler-to-matrix-and-matrix-to-euler
inline void MatrixFromYawPitchRoll(
    const DirectX::SimpleMath::Vector3& euler,
    DirectX::SimpleMath::Matrix&        mat)
{
    float cosY = cosf(euler.y);     // Yaw
    float sinY = sinf(euler.y);

    float cosP = cosf(euler.x);     // Pitch
    float sinP = sinf(euler.x);

    float cosR = cosf(euler.z);     // Roll
    float sinR = sinf(euler.z);

    mat = DirectX::SimpleMath::Matrix::Identity;
    mat._11 = cosY * cosR + sinY * sinP * sinR;
    mat._21 = cosR * sinY * sinP - sinR * cosY;
    mat._31 = cosP * sinY;

    mat._12 = cosP * sinR;
    mat._22 = cosR * cosP;
    mat._32 = -sinP;

    mat._13 = sinR * cosY * sinP - sinY * cosR;
    mat._23 = sinY * sinR + cosR * cosY * sinP;
    mat._33 = cosP * cosY;
}

Alors code pour récupérer les angles d'Euler de la matrice:

//====================================================================================================
// MatrixDecomposeYawPitchRoll
//
// Extract the rotation contained in the provided matrix as yaw (heading), pitch and roll (bank) in
// radiuans.
//
// Assumptions:
//  Euler:   X = Pitch, Y = Yaw, Z = Roll
//  Applied: Yaw then pitch then roll
//  Axes:    X = Right, Y = Up, Z = Forward
//  DirectX: Matrices are row major (http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html)
//
// Code is based on Mike Tunnicliffe's answer to this question:
//   https://stackoverflow.com/questions/1996957/conversion-euler-to-matrix-and-matrix-to-euler
inline void MatrixDecomposeYawPitchRoll(
    const DirectX::SimpleMath::Matrix&  mat,
    DirectX::SimpleMath::Vector3&       euler)
{
    euler.x = asinf(-mat._32);                  // Pitch
    if (cosf(euler.x) > 0.0001)                 // Not at poles
    {
        euler.y = atan2f(mat._31, mat._33);     // Yaw
        euler.z = atan2f(mat._12, mat._22);     // Roll
    }
    else
    {
        euler.y = 0.0f;                         // Yaw
        euler.z = atan2f(-mat._21, mat._11);    // Roll
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top