2012-06-19 2 views
11

테스트 quaternion에 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 개의 오일러 각도 포함). 이 개념에서 객체 쿼터니온 (object quaternion)에 대해 작업하고 사용자에 대한 오일러 각도를 저장합니다. 쿼터니언이있는 오일러 각을 사용하여 회전을 지정하는 것이 훨씬 간단하다고 말하면 아마 나에게 동의 할 것입니다 ... (내가 읽으려고합니다. – user1466739

+0

예, 동의합니다. 사용자와 통신 할 때 오일러 각이 유용 할 수 있습니다. – Ali

+0

오케이. 네가 나에게 말했던 책을 읽었고 이제는 모든 것을 이해했다. 고맙습니다. – user1466739

11

이 페이지를 살펴보십시오. 3D 변환을 처리하기 위해 필요한 모든 것이 있습니다 (심지어 일부 코드 샘플!). 당신은 오일러 각에 사원 수의 필요 결국,하지만 당신은 임의의 회전 순서를해야하는 경우 All rotation conversions

7

Euler Angles to Quaternion

Quaternion to Euler Angles

, 나는 변환 코드가있는 사이트를 건너 왔어요. 때로는 트릭은 올바른 순환 순서를 찾는 것입니다. (Btw, XYX와 같은 문자가 두 번있는 주문은 적절한 오일러 각이지만 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>

관련 문제