Frage

Ist es ein bestehender Algorithmus zur Umwandlung einer quaternion-Darstellung der rotation um eine Euler-Winkel Darstellung?Die Reihenfolge für die Euler-Darstellung ist bekannt und kann in jeder der sechs Permutationen (alsoxyz, xzy, yxz, yzx, zxy, zyx).Ich habe gesehen, algorithmen, die für einen festgelegten Reihenfolge (in der Regel die NASA überschrift, bank, roll-übereinkommen), nicht aber für beliebige Drehung um.

Darüber hinaus, da es mehrere Euler-Winkel-Darstellungen eine einzige Orientierung, dieses Ergebnis wird eindeutig sein.Dies akzeptabel ist (da die Ausrichtung ist immer noch gültig, es können nur nicht derjenige sein, der Benutzer wird erwartet, um zu sehen), aber es wäre noch besser, wenn es einen Algorithmus, nahm rotation Grenzen (d.h.die Anzahl der Freiheitsgrade und die Grenzen für jeden Grad der Freiheit) in Rechnung und lieferte die 'vernünftigste' Euler Darstellung dieser Einschränkungen.

Ich habe ein Gefühl, das dieses problem (oder etwas ähnliches) kann es in der IK oder rigid body dynamics-Domänen.


Gelöst: Ich habe gerade realisiert, dass es vielleicht nicht klar, dass ich dieses problem gelöst, indem Sie die folgenden Ken Shoemake algorithmen von Grafiken Edelsteine.Ich habe Antwort auf meine eigene Frage, aber es fällt mir es kann nicht sein, klar, dass habe ich so.Siehe die Antwort unten für weitere Details.


Nur um zu klären - ich weiß, wie zu konvertieren von einer quaternion zu der sogenannten 'Tait-Bryan'Repräsentation - was ich war, ruft die 'NASA' convention.Dies ist eine Drehung um (vorausgesetzt, die Konvention, die 'Z' - Achse aufwärts) zxy.Ich brauche einen Algorithmus für alle rotation Bestellungen.

Möglicherweise die Lösung ist, dann nehmen Sie die zxy, um conversion-und leiten daraus fünf anderen Umbauten für die andere Drehrichtung Bestellungen.Ich denke, ich hatte gehofft, es war eine 'übergeordnete' - Lösung.In jedem Fall bin ich überrascht, dass ich nicht in der Lage zu finden, bestehende Lösungen gibt.

Darüber hinaus, und dies ist vielleicht ein separates überhaupt nicht in Frage, eine Umwandlung (unter der Annahme einer bekannten Reihenfolge natürlich) zu wählen eine Euler Darstellung, aber es gibt in der Tat viele.Zum Beispiel wird bei einer rotation um von yxz, die beiden Darstellungen (0,0,180) und (180,180,0) äquivalent sind (und würde die Ausbeute der gleichen Quaternionen).Gibt es eine Möglichkeit zu beschränken, die Lösung mit Grenzen, die auf den Grad der Freiheit?Wie Sie im IK und rigid body dynamics?d.h.im obigen Beispiel gäbe es nur einen Freiheitsgrad um die Z-Achse dann die zweite Darstellung, die ignoriert werden können.


Ich habe aufgespürt einem Papier, das könnte ein Algorithmus in diese pdf-Datei aber ich muss gestehen, ich finde die Logik und die Mathematik ein wenig schwer zu Folgen.Sicherlich gibt es andere Lösungen gibt?- Beliebige Drehung um wirklich so selten?Sicherlich jeder gängigen 3D-Paket, das ermöglicht Skelett-animation zusammen mit quaternion-interpolation (D. H.Maya, Max, Blender, etc) müssen gelöst haben genau dieses problem?

War es hilfreich?

Lösung

Dies sieht aus wie ein klassischer Fall, bei alten technology zu übersehen - ich habe es geschafft, zu Graben, eine Kopie von Graphics Gems IV aus der garage, und es sieht aus wie Ken Shoemake hat nicht nur einen Algorithmus für die Umwandlung von Euler Winkeln, die von beliebig Reihenfolge, sondern auch Antworten die meisten meiner anderen Fragen zu dem Thema.Hurra für Bücher.Wenn ich nur könnte Stimmen HerrnShoemake Antwort und belohnen Sie ihn mit Ruf-Punkte.

Ich denke, eine Empfehlung, dass jeder arbeiten mit Euler-Winkel, sollten Sie sich eine Kopie der Grafik Gems IV, aus Ihrer örtlichen Bibliothek und Lesen Sie den Abschnitt ab Seite 222 zu tun haben.Es hat auf die klarste und prägnanteste Erklärung für das problem, das ich gelesen habe, noch nicht.


Hier ist ein nützlicher link, den ich gefunden habe, da - http://www.cgafaq.info/wiki/Euler_angles_from_matrix - Das folgt demselben system wie Shoemake;die 24 verschiedenen Permutationen der Reihenfolge codiert sind, als vier separate Parameter - innere Achse, Parität, Wiederholung und Rahmen - die dann ermöglicht die Reduktion der Algorithmus von 24 Fällen 2.Könnte nützlich sein wiki im Allgemeinen - ich hatte nicht über ihn kommen, vor.

An old link scheint kaputt zu sein hier ist eine weitere Kopie von "Computing die Euler Winkeln von rotation matrix ".

Andere Tipps

In einem rechtshändigen kartesischen Koordinatensystem mit Z-Achse nach oben zeigt, dies zu tun:

struct Quaternion
{
    double w, x, y, z;
};

void GetEulerAngles(Quaternion q, double& yaw, double& pitch, double& roll)
{
    const double w2 = q.w*q.w;
    const double x2 = q.x*q.x;
    const double y2 = q.y*q.y;
    const double z2 = q.z*q.z;
    const double unitLength = w2 + x2 + y2 + z2;    // Normalised == 1, otherwise correction divisor.
    const double abcd = q.w*q.x + q.y*q.z;
    const double eps = 1e-7;    // TODO: pick from your math lib instead of hardcoding.
    const double pi = 3.14159265358979323846;   // TODO: pick from your math lib instead of hardcoding.
    if (abcd > (0.5-eps)*unitLength)
    {
        yaw = 2 * atan2(q.y, q.w);
        pitch = pi;
        roll = 0;
    }
    else if (abcd < (-0.5+eps)*unitLength)
    {
        yaw = -2 * ::atan2(q.y, q.w);
        pitch = -pi;
        roll = 0;
    }
    else
    {
        const double adbc = q.w*q.z - q.x*q.y;
        const double acbd = q.w*q.y - q.x*q.z;
        yaw = ::atan2(2*adbc, 1 - 2*(z2+x2));
        pitch = ::asin(2*abcd/unitLength);
        roll = ::atan2(2*acbd, 1 - 2*(y2+x2));
    }
}

Ich habe auf der Suche für einige Tage auf eine ähnliche Lösung, und ich schließlich rannte über diese website, die einen Algorithmus für die Umwandlung von Quaternionen zu beliebigen Euler und Tait-Bryan-Rotationen!

Hier der link: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/

Und hier ist der code:

///////////////////////////////
// Quaternion to Euler
///////////////////////////////
enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};

void twoaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r11, r12 );
  res[1] = acos ( r21 );
  res[2] = atan2( r31, r32 );
}

void threeaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r31, r32 );
  res[1] = asin ( r21 );
  res[2] = atan2( r11, r12 );
}

void quaternion2Euler(const Quaternion& q, double res[], RotSeq rotSeq)
{
    switch(rotSeq){
    case zyx:
      threeaxisrot( 2*(q.x*q.y + q.w*q.z),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    -2*(q.x*q.z - q.w*q.y),
                     2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                     res);
      break;

    case zyz:
      twoaxisrot( 2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.z + q.w*q.y),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.z - q.w*q.y),
                  res);
      break;

    case zxy:
      threeaxisrot( -2*(q.x*q.y - q.w*q.z),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      2*(q.y*q.z + q.w*q.x),
                     -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                      res);
      break;

    case zxz:
      twoaxisrot( 2*(q.x*q.z + q.w*q.y),
                  -2*(q.y*q.z - q.w*q.x),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.x*q.z - q.w*q.y),
                   2*(q.y*q.z + q.w*q.x),
                   res);
      break;

    case yxz:
      threeaxisrot( 2*(q.x*q.z + q.w*q.y),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    -2*(q.y*q.z - q.w*q.x),
                     2*(q.x*q.y + q.w*q.z),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                     res);
      break;

    case yxy:
      twoaxisrot( 2*(q.x*q.y - q.w*q.z),
                   2*(q.y*q.z + q.w*q.x),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.x*q.y + q.w*q.z),
                  -2*(q.y*q.z - q.w*q.x),
                  res);
      break;

    case yzx:
      threeaxisrot( -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                      2*(q.x*q.y + q.w*q.z),
                     -2*(q.y*q.z - q.w*q.x),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      res);
      break;

    case yzy:
      twoaxisrot( 2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.y - q.w*q.z),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.y + q.w*q.z),
                   res);
      break;

    case xyz:
      threeaxisrot( -2*(q.y*q.z - q.w*q.x),
                    q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    2*(q.x*q.z + q.w*q.y),
                   -2*(q.x*q.y - q.w*q.z),
                    q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    res);
      break;

    case xyx:
      twoaxisrot( 2*(q.x*q.y + q.w*q.z),
                  -2*(q.x*q.z - q.w*q.y),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.y - q.w*q.z),
                   2*(q.x*q.z + q.w*q.y),
                   res);
      break;

    case xzy:
      threeaxisrot( 2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                    -2*(q.x*q.y - q.w*q.z),
                     2*(q.x*q.z + q.w*q.y),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                     res);
      break;

    case xzx:
      twoaxisrot( 2*(q.x*q.z - q.w*q.y),
                   2*(q.x*q.y + q.w*q.z),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.z + q.w*q.y),
                  -2*(q.x*q.y - q.w*q.z),
                  res);
      break;
    default:
      std::cout << "Unknown rotation sequence" << std::endl;
      break;
   }
}

Ich habe meinen Beitrag mit dem Titel "Quaternion to Euler-Winkel Umrechnung für Beliebige Rotation Mit Geometrischen Methoden" auf meiner website an noelhughes.net.Ich habe auch algorithmen für die Umwandlung von jedem Satz von Euler-Winkeln eine quaternion und quaternion to/from direction cosine matrix, die ich nach diesem Wochenende.Diese werden auch auf Martin Bäcker-website, aber ein wenig schwer zu finden.Google my name, Noel Hughes und Quaternionen und Sie sollten ihn zu finden.

Ich löse es so:

Schritt 1:Stellen Sie sicher, dass die Konvention für die Euler-Drehung, die Sie wollen, sagen, zyx.

Schritt 2:Die Berechnung der analytischen drehmatrix für die Drehung.Zum Beispiel, wenn Sie möchten R(zyx),

**R***zyx* = **R***x*( phi ) * **R***y*( theta ) * **R***z*( psi ), wo die Elemente zu

R11 =  cos(theta)*cos(psi)
R12 = -cos(theta)*sin(psi)
R13 =  sin(theta)
R21 =  sin(psi)*cos(phi) + sin(theta)*cos(psi)*sin(phi)
R22 =  cos(psi)*cos(phi) - sin(theta)*sin(psi)*sin(phi)
R23 = -cos(theta)*sin(phi)
R31 =  sin(psi)*sin(phi) - sin(theta)*cos(psi)*cos(phi)
R32 =  cos(psi)sin(phi) + sin(theta)*sin(psi)*cos(phi)
R33 =  cos(theta)*cos(phi) 

Schritt 3:Durch die Inspektion können Sie finden, die sin oder tan für die drei Winkel mit den Elementen vor.In diesem Beispiel

tan(phi) = -R23/R33

sin(theta) = -R13

tan(psi) = -R12/R11

Schritt 4:Berechnen Sie die rotationsmatrix aus Ihrer Quaternionen (siehe wikipedia), für Elemente, die Sie brauchen, berechnen Sie die Winkel, wie in 3) beschrieben vor.

Andere Konventionen kann berechnet werden mit der gleichen Prozedur.

Hier ist ein Papier, das ich schrieb über die Umwandlung einer quaternion to Euler angles.

Link 1

Ich habe auch eine Reihe von Dokumenten an dieser Stelle diskutieren verschiedene Aspekte der Quaternionen, Euler-Winkel und rotation matrices (DCM).

Link 2

Für diejenigen, die stolpern, der diese Seite beim Googeln habe ich vor kurzem gefunden Ableitungen für diese Umrechnungen für alle 12 intrinsische Tait-Bryan (1-2-3, 3-2-1, etc.) und die Richtige Euler (1-2-1, 3-1-3, etc.) rotation Sequenzen in den beiden folgenden Referenzen:

Dank frodo2975 für den zweiten link.

Wikipedia zeigt, wie Sie die Teile verwenden, die von der Quaternionen und berechnen Sie die euler-Winkel.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top