0 引言
來鵝廠實習了一段時間,因為沒有什麼特别緊急的需求(hahahahaha),是以主要花在了學習和搗鼓一些小工具上。有一個小需求是要實作滑鼠拖動球體的轉動,然後發現我不再能隻用歐拉角來糊弄過去了。然後又發現,網上大部分資料的采用的歐拉角順規都是xyz,然後我基于D3D11的辣雞架構用了zxy,公式不太能直接套用,于是摸了兩三天魚,整理了一下幾種三維旋轉表示(歐拉角,四元數,旋轉矩陣,軸角)與他們之間的互相轉換的資料,并且加入了自己的一些推導,
給出這些轉換公式的推導思路和細節,這樣子如果各位想使用其他歐拉角順規和定義的時候,自己動手算一算就好了。
至于這幾種三維旋轉的表示形式随手百度Google都可以看到很多科普文的,這裡着重說一下
他們之間的轉換的細節吧(不少公式和推導,預警一波,如果有錯誤請指出~)
圖:下文介紹的幾種轉換路徑
1 歐拉角(Euler Angle)與旋轉矩陣(Rotation Matrix)
1.1 歐拉角 ----> 旋轉矩陣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
Euler angles - Wikipediaen.wikipedia.org
[4]Rotation Matrix
Rotation matrix - Wikipediaen.wikipedia.org
可以知道,歐拉角構造旋轉矩陣就直接把三個Elemental Rotation Matrix乘在一起就好了(LaTeX扣得真累orz):
其中:
上面的歐拉角--->矩陣的結果與維基百科Euler Angles[3]
給出的結果一緻,那應該穩了:
圖:其實可以不用自己推的,維基百科把12種順規乘出來的矩陣都寫出來了
.
1.2 旋轉矩陣----> 歐拉角參考一篇NASA的關于姿态描述的技術報告[1]的Appendix-A6和[5],我們可以用
旋轉矩陣元素的相乘、相除、反三角函數等操作去“湊”出歐拉角。[5]給出了從XYZ順規提取歐拉角的方法、步驟、思路,[1]則給出了全部12種順規的歐拉角提取公式,但是沒有給一些細節注意事項。是以總結一下,根據[1]、[5]、[7]《Real Time Rendering 3rd Edition》4.2.2和自己的推導,從ZXY順規旋轉矩陣提取歐拉角的公式是([1]原文下标似乎有點小問題):
- Y axis yaw angle:
- X axis pitch angle:
- Z axis roll angle:
.
注意到一點,注意到矩陣的每一個元素都是pitch angle
的函數…是以當
即
的時候,這時候其他的歐拉角提取表達式就涼涼了(分子分母都是0, arctan和atan2都沒有意義了)….其實pitch angle
恰好就是Gimbal Lock的位置。在Gimbal Lock的時候,旋轉矩陣會退化為:
.
那麼要進一步處理萬向節死鎖的corner case就需要分兩種情況:
- ,此時
其中要給
或者
其中一個歐拉角指派,另外一個就按等式計算出來。
.
- ,此時
同樣的,要給
或者
其中一個歐拉角指派,另外一個就按等式計算出來。
.
從旋轉矩陣提取歐拉角的公式跟歐拉角順規的選取有關,因為旋轉矩陣的元素會略有不同,但是思路都是一樣的,就是
根據旋轉矩陣的解析表達式+反三角函數湊出來23333。
2 四元數(Quaternion)與旋轉矩陣
2.1 四元數---->旋轉矩陣衆所周知的是,歐拉旋轉是有萬向節死鎖(Gimbal Lock)的問題的。幸好我們有四元數(Quaternion)這種數學工具可以避免這個情況。一般來說,我們都會用機關四元數
來表示旋轉,其中
。那麼給定一個機關四元數,可以構造旋轉矩陣(column major)[1][4][8][14][15]:
這個四元數構造的大概思路就是把
四元數的旋轉操作寫成矩陣形式(注:給定一個用于旋轉的機關四元數
和被旋轉的三維向量
,那麼要直接用四元數旋轉這個向量,則我們首先要構造一個純四元數
,設旋轉後的向量為
,旋轉後的向量構造的純四元數為
,那麼
)。因為是用四元數來構造矩陣的,是以這個矩陣構造公式就沒有歐拉角順規的說法了。
.
2.2 旋轉矩陣---->四元數那第一步肯定是判斷3x3矩陣是一個正交矩陣啦(滿足
)。那麼如果這個矩陣已經是一個合法的旋轉矩陣了,要從旋轉矩陣裡提取四元數,也是可以像提取歐拉角那樣,
用參數化過的矩陣的表達式湊出來。參考[8]《Real Time Rendering 3rd edition》Chapter4的思路,我們觀察一下用四元數分量進行參數化的矩陣
,然後經過一頓操作,我們發現:
于是我們再湊出個實分量
,就可以把四元數四個分量都用矩陣元素表示出來了。于是我們又機智地發現了一個等式:
其中
是矩陣
的迹(trace),也就是矩陣對角元素的和。因為這裡用的是3x3矩陣,跟其他資料裡面的表示有一點不同。是以我們可以把四元數的四個分量都用矩陣元素湊出來了:
有一點《Real Time Rendering》提到的,
絕對值比較小的時候,可能會出現數值不穩定的情況,那麼想要數值穩定的話就得用一種不用除法的方式來湊,在這不展開了,可以看一下RTR 2333。
3 歐拉角與四元數
3.1 歐拉角---->四元數首先提一下四元數的乘積:
參考維基百科[2]的思路,歐拉角構造四元數,跟歐拉角構造旋轉矩陣一樣,就是
把三個基礎旋轉Elemental Rotation組合在一起。Conversion between quaternions and Euler anglesen.wikipedia.org
那麼用于旋轉的四元數
的表達式是:
這個我自己推導的結果跟[1]NASA Technical Report的Appendix A給出的結果對比過了
https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770019231.pdfntrs.nasa.gov
([1]中四元數記号是
),看起來沒什麼問題。
.
3.2 四元數---->歐拉角本來我以為,從四元數提取歐拉角的思路可以跟旋轉矩陣提取歐拉角類似,也是用四元數的元素運算和反三角函數湊出公式來。後來我發現這簡直就是一個極其硬核的任務,展開之後每一項都是六次多項式,畫面有一丢暴力且少兒不宜,直接強行湊的話畫風大概是這樣:
這個結果跟歐拉角參數化的旋轉矩陣的
的表達式是吻合的。但這還隻是最好湊的那一個,惹不起惹不起。是以舒服的思路還是
四元數-->旋轉矩陣-->歐拉角,想一步到位的話,把四元數分量參數化的旋轉矩陣、歐拉角參數化的旋轉矩陣結合在一起,參考下旋轉矩陣轉歐拉角的方法,替換下元素就完事了。這裡就不把公式展開了,因為四元數直接轉歐拉角 跟 旋轉矩陣轉歐拉角一樣,依舊是要處理gimbal lock的corner case,還是那麼麻煩,是以這裡先鴿了23333
4 軸-角(Axis-Angle)
4.1 軸角---->四元數軸-角(Axis-Angle)顧名思義就是繞某條機關軸旋轉一定角度,從這個意義上看,它構造四元數是非常舒服的,畢竟直覺的幾何意義有一點點類似,繞機關軸
旋轉
的四元數是:
.
4.2 軸角---->旋轉矩陣Axis Angle轉Rotation Matrix可以從[9]羅德裡格斯旋轉公式Rodrigues Rotation Formula開始推導。
https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formulaen.wikipedia.org
Rodrigues' rotation formula
Rodrigues' rotation formulaen.wikipedia.org
設
是我們要旋轉的機關向量,旋轉軸為
,
繞
旋轉角度
,那麼旋轉後的向量為:
這個公式的推導思路是這樣子的,我們先對向量
進行正交分解,分解成投影到旋轉軸
的分量和垂直于
的分量:
其中:
圖:魔性p圖,假設k和v都在螢幕這個平面上吧
于是繞
旋轉向量
其實就是把上面
正交投影後的向量分别旋轉之後再加起來。那麼很明顯的,投影到旋轉軸上的部分
都跟旋轉軸共享了,那麼自然旋轉之後的結果就沒有變化了,于是我們隻需要旋轉和旋轉軸垂直的部分
。那麼這個
旋轉後的表達式就是:
然後我們不按wikipedia裡面坑爹的、不考慮下文的變形,自己推一波:
這裡我們把旋轉後向量的表達式
變形得隻剩下叉積(cross product),去掉點積(dot product)了,這樣子我們才可以把這個繞軸旋轉的表達式寫成矩陣形式。怎麼寫呢?首先叉積可以寫成矩陣形式:
Cross product - Wikipediaen.wikipedia.org
于是羅德裡格斯旋轉公式的變換就可以寫成矩陣形式:
展開之後就是:
罷工罷工!!LaTeX敲到我頭皮發麻了!!
(不那麼标準的)引用
[1]Henderson, D.M.. Euler angles, quaternions, and transformation matrices for space shuttle analysis[C]//NASA, Jun 09, 1977.
[2] https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Euler_Angles_to_Quaternion_Conversion
[3] https://en.wikipedia.org/wiki/Euler_angles
[4] https://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://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
[10] https://en.wikipedia.org/wiki/Cross_product#Conversion_to_matrix_multiplication
[11] http://mathworld.wolfram.com/RodriguesRotationFormula.html
[12] https://zh.wikipedia.org/wiki/%E5%9B%9B%E5%85%83%E6%95%B8
[13] https://blog.csdn.net/silangquan/article/details/39008903
[14] Quaternion and Rotations, http://run.usc.edu/cs520-s12/quaternions/quaternions-cs520.pdf
[15] https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation