歐拉角和四元數(shù)
筆記主要摘自下列博文和回答中
如何通俗地解釋歐拉角景东?之后為何要引入四元數(shù)斤吐? - 知乎
【Unity編程】四元數(shù)(Quaternion)與歐拉角 - Andrew的游戲世界 - CSDN博客
【Unity編程】歐拉角與萬向節(jié)死鎖(圖文版) - Andrew的游戲世界 - CSDN博客
歐拉角
歐拉角:由三個角度組成和措,在特定坐標系下用于描述剛體的orientation。orientation可以理解為形態(tài)蜕煌,用來唯一地確定定點轉(zhuǎn)動明體位置的三個一組獨立角參量派阱,它不是一個方向或向量,如圖1的向量斜纪,無論怎么旋轉(zhuǎn)它都是不會改變的贫母,因為它沒有orientation。
而在圖2中當你旋轉(zhuǎn)物體時盒刚,它的orientation就會發(fā)生改變颁独。描述一個向量用兩個維度就可以(忽略長度信息),而描述orientation至少需要三個角度,即歐拉角贮聂,總結(jié)起來耻警,歐拉角就是用來表示三維坐標系中方向和方向變換的。
下面這個圖解釋了如何通過歐拉角進行旋轉(zhuǎn)
圖中有兩組坐標荡含,一組是xyz装处,它是全局坐標保持不懂,而XYZ則是局部坐標,跟著物體一起旋轉(zhuǎn)槽惫。旋轉(zhuǎn)步驟為:1.繞著全局z軸轉(zhuǎn)了角各薇;2.繞著自己的X軸轉(zhuǎn)了
角林螃;3.繞這自己的Z軸轉(zhuǎn)了
角。下面的圖4更加清晰地展示了旋轉(zhuǎn)的過程 (
對應(yīng)
,
?對應(yīng)
,
?對應(yīng)
)
我們把上面的旋轉(zhuǎn)順序記為zXZ(習慣稱為zxz順規(guī))亡笑,加上對應(yīng)的角度就構(gòu)成了一個完整的歐拉角,表示為? zXZ—(,
,
)
萬向節(jié)
維基百科中關(guān)于平衡環(huán)架的一段描述
平衡環(huán)架(英語:Gimbal)為一具有樞紐的裝置,使得一物體能以單一軸旋轉(zhuǎn)谷羞。由彼此垂直的樞紐軸所組成的一組三只平衡環(huán)架,則可使架在最內(nèi)的環(huán)架的物體維持旋轉(zhuǎn)軸不變知残,而應(yīng)用在船上的陀螺儀、羅盤、飲料杯架等用途上溉委,而不受船體因波浪上下震動藻三、船身轉(zhuǎn)向的影響逗概。
它的樣子如圖5所示
其組成如下圖所示
萬向節(jié)與歐拉角的工作方式類似秘噪,三層嵌套的圓環(huán),它們互相交叉,帶來了三個方向自由度的旋轉(zhuǎn)晋渺。如圖6所示,沿著機身右方軸(Unity中的+X)進行旋轉(zhuǎn)恋捆,稱為pitch鸠信,中文叫俯仰。 沿著機頭上方軸(Unity中的+Y)進行旋轉(zhuǎn),稱為Yaw占业,中文叫偏航念恍。 沿著機頭前方軸(Unity中的+Z)進行旋轉(zhuǎn)该默,稱為Roll栓袖,中文叫桶滾。
萬向節(jié)死鎖
了解了上面一些東西后塔橡,我們來了解萬向節(jié)死鎖產(chǎn)生和問題癞谒,為了解釋清楚問題翎卓,這里有一個簡單的陀螺儀示意圖。
把三個Gimbal環(huán)用不同的顏色做了標記畜号,底部三個軸向缴阎,RGB分別對應(yīng)XYZ。 假設(shè)現(xiàn)在這個陀螺儀被放在一艘船上简软,船頭的方向沿著+Z軸蛮拔,也就是右前方述暂。通過博文中的演示可知道當船體分別發(fā)生俯仰,偏航和桶滾時建炫,平衡環(huán)架中的轉(zhuǎn)子和平衡軸都能通過自身的調(diào)節(jié)保持平衡的狀態(tài)畦韭,而使移動只發(fā)生在陀螺儀內(nèi)部的相對移動。
這樣看似在任何搖晃下這個簡陋的陀螺儀都能通過自身的調(diào)整使其保持穩(wěn)定的平衡肛跌,但是在我們假設(shè)船體發(fā)生了事故艺配,船首揚起了90°(即俯仰旋轉(zhuǎn)),此時陀螺儀會呈現(xiàn)圖9這種狀態(tài)(紅色圓環(huán)俯仰轉(zhuǎn)動90°成豎直狀態(tài))
此時衍慎,船體再次發(fā)生轉(zhuǎn)動转唉,沿著當前世界坐標的+Z軸(藍色軸,應(yīng)該正指向船底)進行轉(zhuǎn)動會發(fā)生什么情況呢稳捆,如圖10所示
這中現(xiàn)象為什么會出現(xiàn)呢赠法?
之前陀螺儀之所以能通過自身調(diào)節(jié),保持平衡乔夯,是因為存在可以相對旋轉(zhuǎn)的連接頭砖织。在這種情況下,已經(jīng)不存在可以相對旋轉(zhuǎn)的連接頭了驯嘱。那么連接頭呢镶苞?去了哪里?顯然鞠评,它還是在那里茂蚓,只不過是,連接頭可以旋轉(zhuǎn)的相對方向不是現(xiàn)在需要的按著+Z軸方向剃幌。從上圖中聋涨,我們清楚地看到:
紅色連接頭:可以給予一個相對俯仰的自由度。
綠色連接頭:可以給予一個相對偏航的自由度负乡。
藍色連接頭:可以給予一個相對偏航的自由度牍白。
三個連接頭提供的自由度只對應(yīng)了俯仰和偏航兩個自由度,桶滾自由度丟失了抖棘。這就是陀螺儀上的“萬向節(jié)死鎖”問題茂腥。
而萬向節(jié)的死鎖也是歐拉角在應(yīng)用時的一大缺點,為解決這個問題切省,可以引入四元數(shù)來對旋轉(zhuǎn)變換進行描述最岗。
四元數(shù)
歐拉旋轉(zhuǎn)定理
由下圖可以看出,當長度為1時朝捆,矢量落在長度為1的圓形上般渡,此時實數(shù)軸上的a = cos(φ),虛數(shù)軸上的b = sin(φ),其中φ為旋轉(zhuǎn)角度驯用。此時的表示形式為?e = cos(φ) + sin(φ)i
當圓上的一個矢量進行了連續(xù)的旋轉(zhuǎn)時時脸秽,假設(shè)先旋轉(zhuǎn)φ,再旋轉(zhuǎn)θ蝴乔,則結(jié)果應(yīng)該是兩個旋轉(zhuǎn)的角的和的復(fù)數(shù)形式记餐,即 e = cos(φ+θ)+sin(φ+θ)i。假設(shè):e1= cos(φ) + sin(φ)i (表示旋轉(zhuǎn)了φ角度)薇正,e2= cos(θ) + sin(θ)i (表示旋轉(zhuǎn)了θ角度)剥扣,根據(jù)公式演算可得e和e1、e2的關(guān)系為 e = e1*e2铝穷,也就是說,連續(xù)的旋轉(zhuǎn)(例如這里旋轉(zhuǎn)φ再旋轉(zhuǎn)θ)佳魔,可以使用兩個復(fù)數(shù)的乘積進行表示曙聂,這就是歐拉定理和復(fù)數(shù)結(jié)合的作用,它能夠方便的表示出二維矢量的旋轉(zhuǎn)變化鞠鲜。
四元數(shù)定義
四元數(shù)的定義一般是 q=w+xi+yj+zk宁脊,其中 w,x,y,z是實數(shù)。同時贤姆,有:
i*i=-1榆苞; j*j=-1;k*k=-1霞捡,四元數(shù)也可以表示為: q=[w,v]
其中v = (x,y,z)是矢量坐漏,w是標量,雖然v是矢量碧信,但不能簡單的理解為3維空間的矢量赊琳,它是4維空間中的的矢量,這點比較抽象砰碴,不做深究躏筏。
通俗的講,一個四元數(shù)描述了一個旋轉(zhuǎn)軸和一個旋轉(zhuǎn)角度呈枉。當然也可以隨意指定一個角度一個旋轉(zhuǎn)軸來構(gòu)造一個四元數(shù)趁尼。這個角度是相對于單位四元數(shù)而言的,也可以說是相對于物體的初始方向而言的猖辫。
有多種方式可表示旋轉(zhuǎn)酥泞,如 axis/angle、歐拉角(Euler angles)住册、矩陣(matrix)婶博、四元組等。 相對于其它方法,四元數(shù)有其本身的優(yōu)點:
1.四元數(shù)不會有歐拉角存在的萬向節(jié)死鎖問題
2.四元數(shù)由4個數(shù)組成凡人,旋轉(zhuǎn)矩陣需要9個數(shù)
3.兩個四元數(shù)之間更容易插值
4.四元數(shù)名党、矩陣在多次運算后會積攢誤差,需要分別對其做規(guī)范化(normalize)和正交化(orthogonalize)挠轴,對四元數(shù)規(guī)范化更容易
與旋轉(zhuǎn)矩陣類似传睹,兩個四元組相乘可表示兩次旋轉(zhuǎn)
四元數(shù)——對旋轉(zhuǎn)角表示方法
這里主要參考了【Unity技巧】四元數(shù)(Quaternion)和旋轉(zhuǎn) - candycat - CSDN博客的文章做了一個我本人學(xué)習的總結(jié)。
我們下面使用q = ((x, y, z)岸晦,w) = (v, w)欧啤,其中v是向量,w是實數(shù)启上,這樣的式子來表示一個四元數(shù)邢隧。我們可以使用一個四元數(shù)q=((x,y,z)sinθ2,cosθ2)?來執(zhí)行一個旋轉(zhuǎn)。具體來說冈在,如果我們想要把空間的一個點P繞著單位向量軸u = (x, y, z)表示的旋轉(zhuǎn)軸旋轉(zhuǎn)θ角度倒慧,我們首先把點P擴展到四元數(shù)空間,即四元數(shù)p = (P, 0)包券。那么纫谅,旋轉(zhuǎn)后新的點對應(yīng)的四元數(shù)(計算得的四元數(shù)的實部為0,虛部系數(shù)就是新的坐標)為: p′=qpq?1
其中溅固,q=(cosθ2, (x,y,z)sinθ2)?付秕,q?1=q?N(q),由于u是單位向量侍郭,因此N(q)=1询吴,即q?1=q*。
右邊表達式包含了四元數(shù)乘法励幼。相關(guān)的定義如下:(其中v汰寓,v1,v2為向量)
四元數(shù)乘法:q1q2=(v1×v2+w1v2+w2v1,w1w2?v1?v2)?
共軛四元數(shù):q*=(?v,w)
四元數(shù)的模:N(q) = √(x^2 + y^2 + z^2 +w^2)苹粟,即四元數(shù)到原點的距離
四元數(shù)的逆:q^-1=q?N(q)
關(guān)于四元數(shù)各種性質(zhì)的分析可參考下面這個鏈接中的內(nèi)容
【Unity編程】四元數(shù)(Quaternion)與歐拉角 - Andrew的游戲世界 - CSDN博客
由于我所需要的是結(jié)果和能夠使用結(jié)果有滑,所以不列出證明,其主要思想是構(gòu)建了一個輔助向量k嵌削,它是將p繞旋轉(zhuǎn)軸旋轉(zhuǎn)θ/2得到的毛好。證明過程嘗試證明wk?=kv?,以此證明w與v苛秕、k在同一平面內(nèi)肌访,且與v夾角為θ。
舉一個例子艇劫,把點P(1, 0, 1)繞旋轉(zhuǎn)軸u = (0, 1, 0)旋轉(zhuǎn)90°吼驶,求旋轉(zhuǎn)后的頂點坐標。首先將P擴充到四元數(shù),即p = (P, 0)蟹演。而q = (u*sin45°, cos45°)风钻。求p′=qpq?1的值。最后的結(jié)果p` = ((1, 0, -1), 0)酒请,即旋轉(zhuǎn)后的頂點位置是(1, 0, -1)骡技。
如果想要得到復(fù)合旋轉(zhuǎn),只需類似復(fù)合矩陣那樣左乘新的四元數(shù)羞反,再進行運算即可布朦。
我們來總結(jié)下四元數(shù)旋轉(zhuǎn)的幾個需要注意的地方:
1.用于旋轉(zhuǎn)的四元數(shù),每個分量的范圍都在(-1昼窗,1)是趴;
2.每一次旋轉(zhuǎn)實際上需要兩個四元數(shù)的參與,即q和q*澄惊;
3.所有用于旋轉(zhuǎn)的四元數(shù)都是單位四元數(shù)右遭,即它們的模是1;
Unity中的四元數(shù)使用
實際上缤削,在Unity里即便不知道上述公式和變換也絲毫不妨礙我們使用四元數(shù),但是有一點要提醒你吹榴,除非你對四元數(shù)非常了解亭敢,那么不要直接對它們進行賦值。在Unity里找到對應(yīng)的函數(shù)來進行四元數(shù)變換图筹,那么可以使用這兩個函數(shù):Quaternion.Euler和Quaternion.eulerAngles帅刀。它們基本可以滿足絕大多數(shù)的四元數(shù)旋轉(zhuǎn)變換。
四元數(shù)和歐拉角的轉(zhuǎn)換
給定一個歐拉旋轉(zhuǎn)(X, Y, Z)(即分別繞x軸远剩、y軸和z軸旋轉(zhuǎn)X扣溺、Y、Z度)瓜晤,則對應(yīng)的四元數(shù)為:
x = sin(Y/2)sin(Z/2)cos(X/2)+cos(Y/2)cos(Z/2)sin(X/2)
y = sin(Y/2)cos(Z/2)cos(X/2)+cos(Y/2)sin(Z/2)sin(X/2)
z = cos(Y/2)sin(Z/2)cos(X/2)-sin(Y/2)cos(Z/2)sin(X/2)
w = cos(Y/2)cos(Z/2)cos(X/2)-sin(Y/2)sin(Z/2)sin(X/2)
四元數(shù) q = ((x, y, z), w)锥余。
使用四元數(shù)解決萬向節(jié)鎖
一般情況下對于給定的按照一定順規(guī)的歐拉角,將其轉(zhuǎn)換成為四元數(shù)再轉(zhuǎn)換為旋轉(zhuǎn)矩陣進行計算痢掠,即每一個歐拉角都生成一個新的四元數(shù)和新的旋轉(zhuǎn)矩陣驱犹,在使用歐拉角時這樣做是沒有問題的,但是在使用四元數(shù)的時候就會出現(xiàn)問題足画,因為每次輸入的繞軸旋轉(zhuǎn)有多個軸和多個角度雄驹,對于多次旋轉(zhuǎn)繞多軸沒有考慮坐標系的變化,解決辦法是分別計算用戶每一次輸入的旋轉(zhuǎn)變換矩陣淹辞,將每一次的單獨的旋轉(zhuǎn)變換矩陣點乘原來的旋轉(zhuǎn)變換矩陣医舆,得到最新的變換矩陣。后續(xù)的每一次變換都在這個矩陣的基礎(chǔ)上不斷的乘,也就是說每一次都是在原來的基礎(chǔ)上再加一點點變化蔬将。
并且用四元數(shù)生成旋轉(zhuǎn)矩陣相乘爷速,運算的順序?qū)Y(jié)果不會有影響。