2012-06-19 16 views
11

Uso lib glm (http://glm.g-truc.net/) per quaternioni di test ma ho un problema; quando converto l'angolo di Eulero in quaternione, quindi immediatamente quaternione in angoli di Eulero, il mio risultato è totalmente diverso dai miei angoli iniziali di Eulero. È normale? Potrebbe essere perché le rotazioni non sono comuni?Angolo di Eulero a Quaternion quindi Quaternione a angolo di Eulero

prova Codice:

#include <glm\quaternion.hpp> 
#include <math.h> 

#define PI M_PI 
#define RADTODEG(x) ((x) * 180.0/PI) 
#define DEGTORAD(x) ((x) * PI/180.0) 

int   main(void) 
{ 
    float RotX = 90.f; 
    float RotY = 180.f; 
    float RotZ = -270.f; 

    if (RotX || RotY || RotZ) 
    { 
     std::cout << "Init: x= " << RotX << ", y= " << RotY << ", z= " << RotZ << "\n"; 
     glm::quat key_quat(glm::detail::tvec3<float>(DEGTORAD(RotX), 
                DEGTORAD(RotY), 
                DEGTORAD(RotZ))); 
     glm::detail::tvec3<float> v = glm::eulerAngles(key_quat); 

     /* // the result is even worse with this code here 
     RotX = RADTODEG(v.x); 
     RotY = RADTODEG(v.y); 
     RotZ = RADTODEG(v.z); 
     */ 

     RotX = v.x; 
     RotY = v.y; 
     RotZ = v.z; 

     std::cout << "Final: x= " << RotX << ", y= " << RotY << ", z= " << RotZ << "\n"; 
    } 
    return (0); 
} 

Risultato:

Init: x= 90, y= 180, z= -270 
Final: x= -90, y= -3.41509e-006, z= -90 

grazie in anticipo o/

risposta

16

Sì, è normale. There are 2 ways per rappresentare la stessa rotazione con gli angoli di Eulero.

Personalmente non mi piacciono gli angoli di Eulero, they mess up the stability of your app. li eviterei. Inoltre, sono not very handy entrambi.

+1

grazie a questa utile risposta. efficacemente, nel mio motore, uso quaternion per ruotare i miei oggetti. Quindi, gli utenti possono utilizzare fonction; SetRotation e GetRotation (con 3 angoli di Eulero). In questa funzione, opero su quaternion di oggetti e salvo euler-angles per l'utente. probabilmente sarai d'accordo con me se dico che è molto più semplice specificare le sue rotazioni con gli angoli di Eulero che con i quaternioni ... (Ho intenzione di leggere/guardare tutto ciò che colleghi. Tornerò) – user1466739

+0

Sì, sono d'accordo, gli angoli di Eulero possono essere utili quando si comunica con l'utente. – Ali

+0

Ok. Ho letto il libro che mi hai detto e ora ho capito tutto. Grazie mille. – user1466739

7

Se si finisce per dover quaternione di angoli di Eulero, ma è necessario un ordine di rotazione arbitraria, mi sono imbattuto in un sito con codice di conversione. A volte il trucco è trovare il giusto ordine di rotazione. (A proposito, gli ordini che hanno la stessa lettera due volte, come XYX, sono angoli di Eulero appropriati, ma quelli come XYZ sono angoli di Tait-Bryan).

ecco il link: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/

Ed ecco il codice:

/////////////////////////////// 
// 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; 
    } 
} 
0

Euler -> Quaternion

Estratto dal Three.js.

Ecco un pezzo di codice che funziona per me:

function eulerToQuaternion(eulerXYZ) { 
 
    var c1 = Math.cos(eulerXYZ[0]/2), 
 
    c2 = Math.cos(eulerXYZ[1]/2), 
 
    c3 = Math.cos(eulerXYZ[2]/2), 
 
    s1 = Math.sin(eulerXYZ[0]/2), 
 
    s2 = Math.sin(eulerXYZ[1]/2), 
 
    s3 = Math.sin(eulerXYZ[2]/2), 
 
    x = s1 * c2 * c3 + c1 * s2 * s3, 
 
    y = c1 * s2 * c3 - s1 * c2 * s3, 
 
    z = c1 * c2 * s3 + s1 * s2 * c3, 
 
    w = c1 * c2 * c3 - s1 * s2 * s3; 
 

 
    return [x, y, z, w]; 
 
}; 
 

 
function calculate() { 
 
    var quat = eulerToQuaternion([document.querySelector('#x').value, document.querySelector('#y').value, document.querySelector('#z').value]); 
 

 
    document.querySelector('#result').innerHTML = quat.join(' &nbsp; '); 
 
}
<h3>Euler radians in XYZ order:</h3> 
 
<fieldset> 
 
    <label>X: 
 
    <input id="x" value="1.5" /> 
 
    </label> 
 
    <label>Y: 
 
    <input id="y" value="1" /> 
 
    </label> 
 
    <label>Z: 
 
    <input id="z" value="0" /> 
 
    </label> 
 
    <button onClick="calculate()">To Quaternion</button> 
 
</fieldset> 
 
<h3>X Y Z W result:</h3> 
 
<div id="result"></div>

Problemi correlati