2013-01-21 59 views
1

我正在嘗試使用Irrlicht作爲圖形引擎和物理ODE在C++中編寫3D模擬。然後我使用函數將ODE四元數轉換爲Irrlicht euler角。爲了做到這一點,我使用這個代碼。將四元數轉換爲歐拉角。 Y角度範圍的問題

void QuaternionToEuler(const dQuaternion quaternion, vector3df &euler) 
{ 
    dReal w,x,y,z; 

    w = quaternion[0]; 
    x = quaternion[1]; 
    y = quaternion[2]; 
    z = quaternion[3]; 

    double sqw = w*w;  
    double sqx = x*x;  
    double sqy = y*y;  
    double sqz = z*z; 

    euler.Z = (irr::f32) (atan2(2.0 * (x*y + z*w),(sqx - sqy - sqz + sqw)) * (180.0f/irr::core::PI)); 
    euler.X = (irr::f32) (atan2(2.0 * (y*z + x*w),(-sqx - sqy + sqz + sqw)) * (180.0f/irr::core::PI));   
    euler.Y = (irr::f32) (asin(-2.0 * (x*z - y*w)) * (180.0f/irr::core::PI)); 

} 

它工作正常繪製我的東西在正確的位置和旋轉,但問題來與「ASIN」指令。它只返回0..90 - 0 ..- 90範圍內的值,我需要從0到360度範圍內。至少我需要得到一個旋轉的0..360的範圍內,當我打電話節點 - > getRotation()。Ÿ

任何一個可以幫我這個好嗎?

+2

在'[0°,360°]','sin'取的每個值的兩倍,因此存在用於'asin'(反正弦函數)沒有合理的方式爲0°和360°之間返回值。 – us2012

回答

6

歐拉角(任何類型)有一個奇點。在你使用的那些特定的歐拉角(看起來像泰特 - 布賴恩角或其一些變化)的情況下,奇點在正負90度的節距(Y)上。這是歐拉角的固有限制,也是它們在任何嚴肅背景下都很少使用的主要原因之一(除了飛機動力學因爲所有飛機的速度矢量(可能不是水平的)都有非常有限的俯仰能力,所以他們很少來到這個奇點附近)。

這也意味着,你的計算實際上只是兩個等價的解決方案之一。對於一個給定的四元數,歐拉角有兩種解決方案,代表相同的旋轉,一個在奇點的一邊,另一個與第一個相反。由於這兩種解決方案都是相同的,所以您只需從最容易的一面選擇一個,即音調在-90到90度之間。

此外,你的代碼需要處理,以避免得到NaN的接近奇點。換句話說,您必須檢查您是否接近(具有小容差)奇點(音高-90和90度),如果是,則使用替代公式(它只能計算一個最接近的角度旋轉)。

如果有什麼方法可以讓你避免使用歐拉角乾脆,我強烈建議你這樣做,幾乎轉任表示最好歐拉角。 Irrlicht本身使用矩陣,並且還支持通過axis-angle representation設置/獲取旋轉,這比使用更好(並且更容易從四元數獲得,並且沒有奇點)。

1

想想地球的地球。其上的每個點只能在緯度(範圍[-90, 90])和經度(範圍[-180, 180])之間定義。因此,可以使用這些角度來指定球體上的每個點。現在球體上的點指定了一個矢量,球體上的所有點指定了所有可能的矢量。因此,就像this article中指出的那樣,您使用的公式會生成所有可能的方向。

希望這會有所幫助。