2012-06-19 51 views
11

Tôi đang sử dụng lib glm (http://glm.g-truc.net/) cho quaternion thử nghiệm nhưng tôi đã có một vấn đề; khi tôi chuyển đổi góc euler thành quaternion thì quaternion lập tức thành các góc euler, kết quả của tôi hoàn toàn khác với các góc euler ban đầu của tôi. Điều này có bình thường không? Nó có thể là vì các vòng quay không phải là cộng sản?Góc Euler tới Quaternion sau đó Quaternion thành góc euler

thử nghiệm Mã số:

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

Kết quả:

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

cảm ơn bạn trước o/

Trả lời

16

Vâng, đó là điều bình thường. There are 2 ways để thể hiện cùng một vòng quay với góc Euler.

Cá nhân tôi không thích góc Euler, they mess up the stability of your app. Tôi sẽ tránh chúng. Ngoài ra, chúng cũng là not very handy.

+1

nhờ này hữu ích trả lời. hiệu quả, trong động cơ của tôi, tôi sử dụng quaternion để xoay đối tượng của mình. Vì vậy, người dùng có thể sử dụng fonction; SetRotation và GetRotation (với 3 góc euler). Trong fonction này, tôi hoạt động trên quaternion đối tượng và tôi tiết kiệm góc euler cho người dùng. bạn có thể sẽ đồng ý với tôi nếu tôi nói đơn giản hơn nhiều để chỉ định xoay vòng với góc Euler với quaternions ... (Tôi sẽ đọc/xem tất cả những gì bạn liên kết. Tôi sẽ quay lại) – user1466739

+0

Vâng, tôi đồng ý, góc Euler có thể hữu ích khi giao tiếp với người dùng. – Ali

+0

OK. Tôi đọc cuốn sách bạn nói với tôi và bây giờ tôi đã hiểu mọi thứ. Cảm ơn nhiều. – user1466739

7

Nếu bạn kết thúc cần quaternion để Góc Euler, nhưng bạn cần một trật tự luân chuyển tùy ý, tôi đi qua một trang web với mã chuyển đổi. Đôi khi, mẹo chỉ là tìm đúng thứ tự xoay vòng. (Btw, các đơn đặt hàng có cùng một chữ cái hai lần, giống như XYX, là các góc Euler thích hợp, nhưng các thứ tự như XYZ là các góc Tait-Bryan).

Đây là liên kết: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/

Và đây là đoạn 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; 
    } 
} 
0

Euler -> tec non

Trích từ Three.js.

Dưới đây là một đoạn mã mà làm việc cho tôi:

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>

Các vấn đề liên quan