重磅乾貨,第一時間送達
![]()
D3D和OpenGL不同,用的坐標系是Y軸豎直向上的左手系,所以歐拉角的順規是跟廣大blog、OpenGL不一樣的,那麼博客上、甚至維基百科[2]上的各種基於右手系xyz順規(分別對應roll, pitch,yaw)的看起來就不太能隨隨便便直接用了。
首先歐拉角旋轉序列(Euler Angle Rotational Sequence)一共有12種順規,6種繞三條軸的旋轉(也叫Tait-Bryan Angle,XYZ,XZY,YXZ,YZX,ZXY,ZYX),另外6種只繞兩條軸的旋轉(也叫Proper Euler Angle,XYX,YXY,XZX,ZXZ,YZY,ZYZ)。如果相鄰兩次旋轉是繞同一條軸,例如XXY,那麼其實可以坍縮成XY。那麼只繞一條軸旋轉就根本不夠自由度就不需要說了。也就是說,一共有12種基礎旋轉的組合順序,它們可以旋轉出三維的所有旋轉狀態。所以一共是12種旋轉順規(可以表示所有旋轉的集合),DirectXMath庫採用的是ZXY順規,分別對應著Z-Roll,X-Pitch,Y-Yaw。
![]()
圖:歐拉旋轉與Yaw-Pitch-Roll的直觀意義(網圖魔改)
注意:那麼下文我們都採用ZXY順規來推導公式!採用列主向量(column major)!(但是注意DirectXMath API生成的矩陣其實是行主向量(row major)的)
參考一下維基百科的[3]Euler Angle、[4]Rotation Matrix
可以知道,歐拉角構造旋轉矩陣就直接把三個Elemental Rotation Matrix乘在一起就好了(LaTeX扣得真累orz):上面的歐拉角--->矩陣的結果與維基百科Euler Angles[3] 給出的結果一致,那應該穩了:
![]()
圖:其實可以不用自己推的,維基百科把12種順規乘出來的矩陣都寫出來了參考一篇NASA的關於姿態描述的技術報告[1]的Appendix-A6和[5],我們可以用旋轉矩陣元素的相乘、相除、反三角函數等操作去「湊」出歐拉角。[5]給出了從XYZ順規提取歐拉角的方法、步驟、思路,[1]則給出了全部12種順規的歐拉角提取公式,但是沒有給一些細節注意事項。所以總結一下,根據[1]、[5]、[7]《Real Time Rendering 3rd Edition》4.2.2和自己的推導,從ZXY順規旋轉矩陣提取歐拉角的公式是([1]原文下標似乎有點小問題):注意到一點,注意到矩陣的每一個元素都是pitch angle 的函數…所以當 即 的時候,這時候其他的歐拉角提取表達式就涼涼了(分子分母都是0, arctan和atan2都沒有意義了)….其實pitch angle 恰好就是Gimbal Lock的位置。在Gimbal Lock的時候,旋轉矩陣會退化為:那麼要進一步處理萬向節死鎖的corner case就需要分兩種情況: ,此時 其中要給或者 其中一個歐拉角賦值,另外一個就按等式計算出來。 ,此時 同樣的,要給或者 其中一個歐拉角賦值,另外一個就按等式計算出來。從旋轉矩陣提取歐拉角的公式跟歐拉角順規的選取有關,因為旋轉矩陣的元素會略有不同,但是思路都是一樣的,就是根據旋轉矩陣的解析表達式+反三角函數湊出來。眾所周知的是,歐拉旋轉是有萬向節死鎖(Gimbal Lock)的問題的。幸好我們有四元數(Quaternion)這種數學工具可以避免這個情況。一般來說,我們都會用單位四元數 來表示旋轉,其中 。那麼給定一個單位四元數,可以構造旋轉矩陣(column major)[1][4][8][14][15]:這個四元數構造的大概思路就是把四元數的旋轉操作寫成矩陣形式(註:給定一個用於旋轉的單位四元數 和被旋轉的三維向量 ,那麼要直接用四元數旋轉這個向量,則我們首先要構造一個純四元數 ,設旋轉後的向量為 ,旋轉後的向量構造的純四元數為 ,那麼 )。因為是用四元數來構造矩陣的,所以這個矩陣構造公式就沒有歐拉角順規的說法了。那第一步肯定是判斷3x3矩陣是一個正交矩陣啦(滿足 )。那麼如果這個矩陣已經是一個合法的旋轉矩陣了,要從旋轉矩陣裡提取四元數,也是可以像提取歐拉角那樣,用參數化過的矩陣的表達式湊出來。參考[8]《Real Time Rendering 3rd edition》Chapter4的思路,我們觀察一下用四元數分量進行參數化的矩陣 ,然後經過一頓操作,我們發現:於是我們再湊出個實分量 ,就可以把四元數四個分量都用矩陣元素表示出來了。於是我們又機智地發現了一個等式:其中 是矩陣 的跡(trace),也就是矩陣對角元素的和。因為這裡用的是3x3矩陣,跟其他資料裡面的表示有一點不同。所以我們可以把四元數的四個分量都用矩陣元素湊出來了:有一點《Real Time Rendering》提到的, 絕對值比較小的時候,可能會出現數值不穩定的情況,那麼想要數值穩定的話就得用一種不用除法的方式來湊,在這不展開了,可以看一下RTR。參考維基百科[2]的思路,歐拉角構造四元數,跟歐拉角構造旋轉矩陣一樣,就是把三個基礎旋轉Elemental Rotation組合在一起。那麼用於旋轉的四元數 的表達式是:這個我自己推導的結果跟[1]NASA Technical Report的Appendix A給出的結果對比過了,([1]中四元數記號是 ),看起來沒什麼問題。本來我以為,從四元數提取歐拉角的思路可以跟旋轉矩陣提取歐拉角類似,也是用四元數的元素運算和反三角函數湊出公式來。後來我發現這簡直就是一個極其硬核的任務,展開之後每一項都是六次多項式,畫面有一丟暴力且少兒不宜,直接強行湊的話畫風大概是這樣:這個結果跟歐拉角參數化的旋轉矩陣的 的表達式是吻合的。但這還只是最好湊的那一個,惹不起惹不起。所以舒服的思路還是四元數-->旋轉矩陣-->歐拉角,想一步到位的話,把四元數分量參數化的旋轉矩陣、歐拉角參數化的旋轉矩陣結合在一起,參考下旋轉矩陣轉歐拉角的方法,替換下元素就完事了。這裡就不把公式展開了,因為四元數直接轉歐拉角 跟 旋轉矩陣轉歐拉角一樣,依舊是要處理gimbal lock的corner case,還是那麼麻煩,所以這裡先鴿了軸-角(Axis-Angle)顧名思義就是繞某條單位軸旋轉一定角度,從這個意義上看,它構造四元數是非常舒服的,畢竟直觀的幾何意義有一點點類似,繞單位軸 旋轉 的四元數是:Axis Angle轉Rotation Matrix可以從[9]羅德裡格斯旋轉公式Rodrigues Rotation Formula開始推導。設 是我們要旋轉的單位向量,旋轉軸為 , 繞 旋轉角度 ,那麼旋轉後的向量為:這個公式的推導思路是這樣子的,我們先對向量 進行正交分解,分解成投影到旋轉軸 的分量和垂直於 的分量:
![]()
於是繞 旋轉向量 其實就是把上面正交投影后的向量分別旋轉之後再加起來。那麼很明顯的,投影到旋轉軸上的部分 都跟旋轉軸共享了,那麼自然旋轉之後的結果就沒有變化了,於是我們只需要旋轉和旋轉軸垂直的部分 。那麼這個旋轉後的表達式就是:然後我們不按wikipedia裡面坑爹的、不考慮下文的變形,自己推一波:這裡我們把旋轉後向量的表達式變形得只剩下叉積(cross product),去掉點積(dot product)了,這樣子我們才可以把這個繞軸旋轉的表達式寫成矩陣形式。怎麼寫呢?首先叉積可以寫成矩陣形式:[1]Henderson, D.M.. Euler angles, quaternions, and transformation matrices for space shuttle analysis[C]//NASA, Jun 09, 1977.[2] https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles%23Euler_Angles_to_Quaternion_Conversion[3] https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Euler_angles[4] https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Rotation_matrix[5] Slabaugh G G. Computing Euler angles from a rotation matrix[J]. 1999.[6] Mike Day, Converting a Rotation Matrix to a Quaternion. https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf[7] Tomas K.M. , Eric H., Naty H.. Real Time Rendering 3rd Edition , p68-p69, 2008.[8] Tomas K.M. , Eric H., Naty H.. Real Time Rendering 3rd Edition , p76-p77, 2008.[9] https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Rodrigues%2527_rotation_formula[10] https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Cross_product%23Conversion_to_matrix_multiplication[11] https://link.zhihu.com/?target=http%3A//mathworld.wolfram.com/RodriguesRotationFormula.html[12] https://link.zhihu.com/?target=https%3A//zh.wikipedia.org/wiki/%25E5%259B%259B%25E5%2585%2583%25E6%2595%25B8[13] https://link.zhihu.com/?target=https%3A//blog.csdn.net/silangquan/article/details/39008903[14] Quaternion and Rotations, https://link.zhihu.com/?target=http%3A//run.usc.edu/cs520-s12/quaternions/quaternions-cs520.pdf[15] https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
本文轉自知乎:雞哥
原文網址:https://zhuanlan.zhihu.com/p/45404840