it-swarm.com.de

Wie kann man Euler-Winkel in einen Richtungsvektor konvertieren?

Ich habe Neigungs-, Roll- und Gierwinkel. Wie würde ich diese in einen Richtungsvektor konvertieren?

Es wäre besonders cool, wenn Sie mir eine Quaternion- und/oder Matrixdarstellung davon zeigen können! 

41
Polaris878

Leider gibt es unterschiedliche Konventionen bei der Definition dieser Dinge (und Wank, Nick und Gier sind nicht ganz die Euler-Winkel). Sie müssen also vorsichtig sein.

Wenn wir pitch = 0 als horizontal (z = 0) und yaw gegen den Uhrzeigersinn von der x-Achse definieren, wird der Richtungsvektor sein

 x = cos (Gieren) * cos (Tonhöhe) 
 y = sin (Gieren) * cos (Tonhöhe) 
 z = sin (Tonhöhe) 

Beachten Sie, dass ich keine Rolle verwendet habe. Dies ist der Richtungseinheitsvektor, er gibt keine Einstellung an. Es ist leicht genug, eine Rotationsmatrix zu schreiben, die Dinge in den Rahmen des fliegenden Objekts trägt (wenn Sie beispielsweise wissen möchten, wohin die linke Flügelspitze zeigt), aber es ist wirklich eine gute Idee, zuerst die Konventionen festzulegen. Können Sie uns mehr über das Problem erzählen?

EDIT: (Ich hatte vor zweieinhalb Jahren die Absicht, auf diese Frage zurückzukommen.)

Wenn wir für die Vollrotationsmatrix die obige Konvention verwenden und der Vektor zuerst gieren, dann neigen und dann rollen soll, um die endgültigen Koordinaten im Weltkoordinatenrahmen zu erhalten, müssen wir die Rotationsmatrizen in umgekehrter Reihenfolge anwenden.

Erste Rolle:

| 1    0          0      |
| 0 cos(roll) -sin(roll) |
| 0 sin(roll)  cos(roll) |

dann pech:

| cos(pitch) 0 -sin(pitch) |
|     0      1      0      |
| sin(pitch) 0  cos(pitch) |

dann gähnen:

| cos(yaw) -sin(yaw) 0 |
| sin(yaw)  cos(yaw) 0 |
|    0         0     1 |

Kombinieren Sie sie und die Gesamtrotationsmatrix lautet:

| cos(yaw)cos(pitch) -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll) -cos(yaw)sin(pitch)cos(roll)+sin(yaw)sin(roll)|
| sin(yaw)cos(pitch) -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll) -sin(yaw)sin(pitch)cos(roll)-cos(yaw)sin(roll)|
| sin(pitch)          cos(pitch)sin(roll)                            cos(pitch)sin(roll)|

Für einen Einheitsvektor, der an der x-Achse beginnt, lauten die endgültigen Koordinaten:

x = cos(yaw)cos(pitch)
y = sin(yaw)cos(pitch)
z = sin(pitch)

Und für den Einheitsvektor, der an der y-Achse (der linken Flügelspitze) beginnt, lauten die endgültigen Koordinaten:

x = -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll)
y = -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll)
z =  cos(pitch)sin(roll)
65
Beta

Es gibt sechs verschiedene Möglichkeiten, drei Euler-Winkel in eine Matrix zu konvertieren, abhängig von der Reihenfolge, in der sie angewendet werden:

typedef float Matrix[3][3];
struct EulerAngle { float X,Y,Z; };

// Euler Order enum.
enum EEulerOrder
{
    ORDER_XYZ,
    ORDER_YZX,
    ORDER_ZXY,
    ORDER_ZYX,
    ORDER_YXZ,
    ORDER_XZY
};


Matrix EulerAnglesToMatrix(const EulerAngle &inEulerAngle,EEulerOrder EulerOrder)
{
    // Convert Euler Angles passed in a vector of Radians
    // into a rotation matrix.  The individual Euler Angles are
    // processed in the order requested.
    Matrix Mx;

    const FLOAT    Sx    = sinf(inEulerAngle.X);
    const FLOAT    Sy    = sinf(inEulerAngle.Y);
    const FLOAT    Sz    = sinf(inEulerAngle.Z);
    const FLOAT    Cx    = cosf(inEulerAngle.X);
    const FLOAT    Cy    = cosf(inEulerAngle.Y);
    const FLOAT    Cz    = cosf(inEulerAngle.Z);

    switch(EulerOrder)
    {
    case ORDER_XYZ:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=-Cy*Sz;
        Mx.M[0][2]=Sy;
        Mx.M[1][0]=Cz*Sx*Sy+Cx*Sz;
        Mx.M[1][1]=Cx*Cz-Sx*Sy*Sz;
        Mx.M[1][2]=-Cy*Sx;
        Mx.M[2][0]=-Cx*Cz*Sy+Sx*Sz;
        Mx.M[2][1]=Cz*Sx+Cx*Sy*Sz;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_YZX:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=Sx*Sy-Cx*Cy*Sz;
        Mx.M[0][2]=Cx*Sy+Cy*Sx*Sz;
        Mx.M[1][0]=Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Cz*Sx;
        Mx.M[2][0]=-Cz*Sy;
        Mx.M[2][1]=Cy*Sx+Cx*Sy*Sz;
        Mx.M[2][2]=Cx*Cy-Sx*Sy*Sz;
        break;

    case ORDER_ZXY:
        Mx.M[0][0]=Cy*Cz-Sx*Sy*Sz;
        Mx.M[0][1]=-Cx*Sz;
        Mx.M[0][2]=Cz*Sy+Cy*Sx*Sz;
        Mx.M[1][0]=Cz*Sx*Sy+Cy*Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Cy*Cz*Sx+Sy*Sz;
        Mx.M[2][0]=-Cx*Sy;
        Mx.M[2][1]=Sx;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_ZYX:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=Cz*Sx*Sy-Cx*Sz;
        Mx.M[0][2]=Cx*Cz*Sy+Sx*Sz;
        Mx.M[1][0]=Cy*Sz;
        Mx.M[1][1]=Cx*Cz+Sx*Sy*Sz;
        Mx.M[1][2]=-Cz*Sx+Cx*Sy*Sz;
        Mx.M[2][0]=-Sy;
        Mx.M[2][1]=Cy*Sx;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_YXZ:
        Mx.M[0][0]=Cy*Cz+Sx*Sy*Sz;
        Mx.M[0][1]=Cz*Sx*Sy-Cy*Sz;
        Mx.M[0][2]=Cx*Sy;
        Mx.M[1][0]=Cx*Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Sx;
        Mx.M[2][0]=-Cz*Sy+Cy*Sx*Sz;
        Mx.M[2][1]=Cy*Cz*Sx+Sy*Sz;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_XZY:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=-Sz;
        Mx.M[0][2]=Cz*Sy;
        Mx.M[1][0]=Sx*Sy+Cx*Cy*Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Cy*Sx+Cx*Sy*Sz;
        Mx.M[2][0]=-Cx*Sy+Cy*Sx*Sz;
        Mx.M[2][1]=Cz*Sx;
        Mx.M[2][2]=Cx*Cy+Sx*Sy*Sz;
        break;
    }
    return(Mx);
}

FWIW, einige CPUs können Sin & Cos gleichzeitig berechnen (z. B. fsincos auf x86). Wenn Sie dies tun, können Sie es mit drei Aufrufen anstelle von 6 etwas schneller machen, um die anfänglichen sin & cos-Werte zu berechnen.

Update: Es gibt 12 Möglichkeiten, je nachdem, ob Sie Rechts- oder Linkshänderergebnisse erzielen möchten - Sie können die "Händigkeit" ändern, indem Sie die Winkel negieren.

19
Adisak

Beta hat meinen Tag gerettet. Ich verwende jedoch ein etwas anderes Bezugskoordinatensystem und meine Definition der Tonhöhe ist aufwärts (mit dem Kopf zustimmend), wobei eine positive Tonhöhe eine negative y-Komponente ergibt. Mein Referenzvektor ist der OpenGl-Stil (entlang der -z-Achse), so dass der resultierende Einheitsvektor bei yaw = 0, pitch = 0 gleich (0, 0, -1) ist. Wenn jemand auf diesen Beitrag stößt und Schwierigkeiten beim Übersetzen hat Betas Formeln für dieses bestimmte System sind die Gleichungen, die ich verwende:

vDir->X = sin(yaw);
vDir->Y = -(sin(pitch)*cos(yaw));
vDir->Z = -(cos(pitch)*cos(yaw));

Beachten Sie den Vorzeichenwechsel und den Gierwechsel <->. Hoffe, das wird jemandem etwas Zeit sparen.

8
pauluss86

Sie müssen Ihre Definitionen hier genau definieren - insbesondere, welchen Vektor Sie wollen? Wenn es sich um die Richtung handelt, in die ein Flugzeug zeigt, hat die Rolle keinen Einfluss auf die Rolle, und Sie verwenden lediglich sphärische Koordinaten (wahrscheinlich mit Achsen/Winkeln).

Wenn Sie dagegen einen bestimmten Vektor mit diesen Winkeln transformieren möchten, suchen Sie nach einer Rotationsmatrix. Der Wiki-Artikel auf Rotationsmatrizen enthält eine Formel für eine Yaw-Pitch-Roll-Rotation, basierend auf den Xyz-Rotationsmatrizen. Ich werde nicht versuchen, es hier einzugeben, angesichts der griechischen Buchstaben und Matrizen.

1
Cascabel

Wenn jemand bei der Suche nach einer Implementierung in FreeCAD stolpert.

import FreeCAD, FreeCADGui
from FreeCAD import Vector
from math import sin, cos, pi

cr = FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation().toEuler()
crx = cr[2] # Roll
cry = cr[1] # Pitch
crz = cr[0] # Yaw

crx = crx * pi / 180.0
cry = cry * pi / 180.0
crz = crz * pi / 180.0

x = sin(crz)
y = -(sin(crx) * cos(crz))
z = cos(crx) * cos(cry)

view = Vector(x, y, z)
0
nvd