2013-02-24 37 views
4

我將角軸表示轉換爲歐拉角。我決定檢查並確保從轉換中得到的歐拉角度會回到原來的軸角度。我打印出這些值,但它們不匹配!我已閱讀http://forum.onlineconversion.com/showthread.php?t=5408http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles以及本網站上的類似轉換問題。將四元數轉換爲歐拉角和返回的不正確

在下面的代碼中,我從角度'angle'和軸(rx,ry,rz)開始,然後將其轉換爲四元數(q0,q1,q2,q3)。我將四元數轉換成歐拉角(滾動,俯仰,偏航)。然後檢查它,我將(滾動,俯仰,偏航)轉換回軸角爲cAngle和(cRx,cRy,cRz)。然後我做一些邊界檢查(滾動,俯仰,偏航)以保持-pi和pi之間的數字,然後將它們打印出來。應該是cAngle =角度和(cRx,cRy,cRz)=(rx,ry,rz),但這些都是錯誤的。

我相信旋轉的順序是Z * Y * X。我的數學有什麼問題嗎?我打算最終在pitch爲0或PI爲http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/時添加特殊情況,但現在我認爲問題是分開的。

 //input is angle 'angle' and axis '(rx,ry,rz)' 

     //convert rx,ry,rz, angle, into roll, pitch, yaw 
     double q0 = Math.Cos(angle/2); 
     double q1 = Math.Sin(angle/2) *Math.Cos(rx); 
     double q2 = Math.Sin(angle/2) * Math.Cos(ry); 
     double q3 = Math.Sin(angle/2) * Math.Cos(rz); 
     double roll = Math.Atan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (q1 * q1 + q2 * q2)); 
     double pitch = Math.Asin(2 * (q0 * q2 - q3 * q1)); 
     double yaw = Math.Atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3)); 

     //convert back to angle axis 
     double cAngle = 2 * Math.Cos(Math.Cos(roll/2) * Math.Cos(pitch/2) * Math.Cos(yaw/2) + Math.Sin(roll/2) * Math.Sin(pitch/2) * Math.Sin(yaw/2)); 
     double cRx = Math.Acos((Math.Sin(roll/2) * Math.Cos(pitch/2) * Math.Cos(yaw/2) - Math.Cos(roll/2) * Math.Sin(pitch/2) * Math.Sin(yaw/2))/Math.Sin(cAngle/2)); 
     double cRy = Math.Acos((Math.Cos(roll/2) * Math.Sin(pitch/2) * Math.Cos(yaw/2) + Math.Sin(roll/2) * Math.Cos(pitch/2) * Math.Sin(yaw/2))/Math.Sin(cAngle/2)); 
     double cRz = Math.Acos((Math.Cos(roll/2) * Math.Cos(pitch/2) * Math.Sin(yaw/2) - Math.Sin(roll/2) * Math.Sin(pitch/2) * Math.Cos(yaw/2))/Math.Sin(cAngle/2)); 

     //stay within +/- PI of 0 to keep the number small 
     if (roll > 3.1416) roll = -Math.PI + (roll - Math.PI); 
     if (roll < -3.1416) roll = Math.PI + (roll - (-1) * Math.PI); 
     if (pitch > 3.1416) pitch = -Math.PI + (pitch - Math.PI); 
     if (pitch < -3.1416) pitch = Math.PI + (pitch - (-1) * 3.1416F); 
     if (yaw > 3.1416) yaw = -Math.PI + (yaw - Math.PI); 
     if (yaw < -3.1416) yaw = Math.PI + (yaw - (-1) * Math.PI); 

     Console.WriteLine("original angle, axis " + angle + ": " + rx + ", " + ry + ", " + rz); 
     Console.WriteLine("converted angle, axis " + cAngle + ": " + cRx + ", " + cRy + ", " + cRz); 
     Console.WriteLine("quats " + q0 + ", " + q1 + ", " + q2 + ", " + q3); 
     Console.WriteLine("roll,pitch,yaw: " + roll + ", " + pitch + ", " + yaw); 
+1

+1。我終於知道四元數是什麼。更多信息在一分鐘內比谷歌天。希望你得到你的答案。 – Kaliber64 2013-02-24 00:55:43

回答

4

我沒有(我不會)檢查你的代碼。 即使您的代碼正確,但您的測試失敗的原因至少有兩個。

也就是說,即使您的轉換正確,您也可以獲得其他表示,而不是您開始使用的表示。無論你是從歐拉角還是四元數開始都沒有關係。


如果你想測試你的代碼,我建議檢查單位的基礎矢量的正交旋轉。例如,適當旋轉[1, 0, 0]以90度得到[0, 1, 0]。檢查你是否真的得到了預期的[0, 1, 0]等 如果你得到了所有3個基本向量的旋轉,那麼你的代碼很可能是正確的。

此測試的優點是明確,如果你搞砸了某些東西(例如公式中的符號),這個測試可以幫助你找到你的錯誤。


我不會使用歐拉角作爲they screw up the stability of your application。他們也是not very handy

+0

非常感謝您提供完整的解釋。我想我現在會避免使用歐拉角度,我不想使用它們作爲中介組成旋轉矩陣。如果我將四元數直接轉換爲旋轉矩陣並返回(如http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/teche52.html),我是否也會遇到同樣的問題,或者會我能夠正確地測試基向量以外的值嗎?另外,如果用這種方法遮掩俯仰角,是否可以寫一個特殊情況來避免萬向節鎖定? – AAB 2013-02-24 18:53:59

+1

只要您來回轉換,您將遇到同樣的問題:四元數具有雙重封面屬性。如果你測試我建議的方式,那麼你**不會有**這個問題。你不必測試單位基礎矢量,這只是一個建議。你可以測試任何你喜歡的矢量,只要你可以計算出預期的結果(你可以很容易地計算出你的單位矢量的那個,這就是爲什麼我建議他們)。旋轉矩陣和四元數都不受萬向節鎖的影響。所以如果你擺脫了歐拉角,你也可以擺脫萬向節鎖問題。 – Ali 2013-02-24 19:01:32

+0

好吧,我現在看到。非常感謝。我會確保我更理解雙封面。感謝您的測試建議。 – AAB 2013-02-24 19:06:50

相關問題