2012-06-19 112 views
11

私はlib四捨五入のためにglm(http://glm.g-truc.net/)を使用していますが、問題があります。オイラー角をクォータニオンに変換した後、すぐにオイラー角に四元数を変換すると、私の結果は最初のオイラー角とはまったく異なります。これは正常ですか?ローテーションがコミュニケートではないためかもしれませんか?オイラー角からクォータニオンへ、次にクォータニオンからオイラー角へ

コードのテスト:

#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); 
} 

結果:

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

はい、それは正常です

答えて

16

/oを事前にお願いします。 There are 2 waysはオイラー角で同じ回転を表します。

私は個人的にオイラー角が好きではない、they mess up the stability of your app.私はそれらを避けるだろう。さらに、彼らはnot very handyです。

+1

感謝。 私のエンジンでは、四元数を使ってオブジェクトを回転させます。 したがって、ユーザーは機能を使用できます。 SetRotationとGetRotation(3オイラーアングル)。この考え方では、私はオブジェクトクォータニオンを操作し、ユーザーのオイラーアングルを節約します。 クォータニオンのオイラー角で回転を指定するほうがはるかに簡単だと言えば、おそらく私に同意するでしょう... (私はあなたがリンクしているすべてを見ています/私は戻ってきます) – user1466739

+0

はい、私は同意します、オイラー角は、ユーザーと通信するときに便利です。 – Ali

+0

あなたが私に言った本を読んで、今私はすべてを理解しました。どうもありがとうございました。 – user1466739

7

あなたはオイラー角に四元さんを必要と終わるが、あなたは、任意の回転順序が必要な場合は、私は、変換コードをサイトに出くわしました。場合によっては、トリックは正しいローテーション順序を見つけるだけです。 (Btw、XYXのような同じ文字を2回持つオーダーは正しいオイラー角ですが、XYZのようなものはTait-Bryan角です)。

はここのリンクです:http://bediyap.com/programming/convert-quaternion-to-euler-rotations/

そして、ここのコードです:

/////////////////////////////// 
// 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

オイラー - Three.jsから抽出>クォータニオン

ここでは私のために動作するコードの一部を以下に示します。この便利な答えに

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>

関連する問題