ELBE
電話:021-58780503 微信:18017854633 郵箱:sales_fullyear@126.com 地址:上海市浦東新區(qū)城南路168弄3號峰匯商務(wù)廣場B座911室
由上,我們可以發(fā)現(xiàn),一個三維旋轉(zhuǎn)可以用一個旋轉(zhuǎn)平面、一個不動點、一個旋轉(zhuǎn)方向、一個旋轉(zhuǎn)角來定義,如果稱旋轉(zhuǎn)前的點為“原始點”,則旋轉(zhuǎn)可定義為:在旋轉(zhuǎn)平面上,以不動點為圓心,以不動點到原始點的距離為半徑做一個圓,在該圓上以原始點為起點往旋轉(zhuǎn)方向畫一道弧,該弧對應(yīng)的角度大小等于旋轉(zhuǎn)角,則該弧的中點為旋轉(zhuǎn)后的點。
旋轉(zhuǎn)的代數(shù)表示我們已經(jīng)知道一個旋轉(zhuǎn)在幾何上可以用一個旋轉(zhuǎn)平面、一個不動點、一個旋轉(zhuǎn)方向、一個旋轉(zhuǎn)角來定義,但是計算機(jī)要表示旋轉(zhuǎn)的話,需要更加代數(shù)化的表示,最好就是向量、矩陣這類數(shù)的排列。我們一個個來看:
旋轉(zhuǎn)平面也只是一個普通的平面而已,而任何一個平面都能用平面上的一點和垂直于該平面的法向量來定義。我們知道原始點和不動點必定在旋轉(zhuǎn)平面上,所以要表示一個旋轉(zhuǎn)平面用一個向量就夠了。不動點,就是對應(yīng)的坐標(biāo)數(shù)值構(gòu)成的一個向量而已。旋轉(zhuǎn)方向,我們可以定義與上文中提到的旋轉(zhuǎn)平面的法向量滿足右手螺旋法則的方向為旋轉(zhuǎn)方向。右手螺旋法則就是說,舉起右手,把大拇指立起來,讓大拇指朝向法向量方向,最后把剩下四指收進(jìn)掌心,則此時四指的方向就是旋轉(zhuǎn)方向。旋轉(zhuǎn)角,就只是一個實數(shù)來表示大小而已。綜上,一個旋轉(zhuǎn)要用代數(shù)來表示的話需要四樣?xùn)|西:一個表示旋轉(zhuǎn)平面法線方向的向量,一個表示不動點的向量,一種由旋轉(zhuǎn)平面法向量得出旋轉(zhuǎn)方向的規(guī)定,一個表示旋轉(zhuǎn)角度的實數(shù)。
假如我們規(guī)定不動點是原點,并使用右手螺旋法則來求旋轉(zhuǎn)方向,且稱旋轉(zhuǎn)平面法向量為“旋轉(zhuǎn)軸”,那么一個旋轉(zhuǎn)就只有兩樣?xùn)|西:旋轉(zhuǎn)軸、旋轉(zhuǎn)角——一個向量、一個實數(shù)。之后我們說“旋轉(zhuǎn)”的時候都是指這樣一個只由旋轉(zhuǎn)軸、旋轉(zhuǎn)角表示的旋轉(zhuǎn)。
旋轉(zhuǎn)的運算上文中最后指出一個旋轉(zhuǎn)可以只由旋轉(zhuǎn)軸和旋轉(zhuǎn)角來表示,這樣它確實很容易被計算機(jī)存儲,但我們的最終目標(biāo)是快速地計算出旋轉(zhuǎn)后的點的坐標(biāo)。所以不止是存儲,我們還需要一套方便的運算方法。
注:一般來說,旋轉(zhuǎn)的運算有兩類方法,矩陣運算與四元數(shù)運算。這里只提及矩陣運算的思想,因為四元數(shù)的話,必須講解數(shù)學(xué),比較麻煩,而且使用恰當(dāng)時,四元數(shù)也不會帶來萬向節(jié)死鎖問題。
計算機(jī)中計算旋轉(zhuǎn),是通過疊加的方式來實現(xiàn)的。首先,應(yīng)該很容易明白,如果先做一個旋轉(zhuǎn),再做另一個旋轉(zhuǎn),那么實際上這兩個旋轉(zhuǎn)疊加的效果相當(dāng)于做了一個等效的旋轉(zhuǎn),也就是兩個旋轉(zhuǎn)疊加以后還是一個旋轉(zhuǎn)。這是因為根據(jù)旋轉(zhuǎn)的定義,兩次旋轉(zhuǎn)都不會改變點到不動點的距離。具體來說,如果原始點是x,第一次旋轉(zhuǎn)后變成了x1,第二次旋轉(zhuǎn)后是x2,那么x, x1, x2到不動點的距離是相等的,所以我們可以把x到x2的這一整個過程看作是一個單獨的旋轉(zhuǎn)。
其次,還應(yīng)該能比較容易地接受一個結(jié)論:繞任意旋轉(zhuǎn)軸的旋轉(zhuǎn)都可以由三個分別繞x,y,z軸的旋轉(zhuǎn)疊加得到。也就是,若C是一個任意旋轉(zhuǎn),則總是存在繞x軸的旋轉(zhuǎn)X,繞y軸的旋轉(zhuǎn)Y,繞z軸的旋轉(zhuǎn)Z,使得C(p)=Z(Y(X(p)))。關(guān)于這一結(jié)論,此處不作展開。通過應(yīng)用這一結(jié)論,計算機(jī)內(nèi)部可以用三個旋轉(zhuǎn)的疊加來表示任意旋轉(zhuǎn)。而繞x, y, z軸的旋轉(zhuǎn)后的點都是比較容易得到的。
以繞z軸的旋轉(zhuǎn)角為θ的旋轉(zhuǎn)為例,若旋轉(zhuǎn)前的點的坐標(biāo)為
,旋轉(zhuǎn)后的坐標(biāo)為
,則有
,若用矩陣、向量的形式來寫的話,就是
。關(guān)于x, y軸的旋轉(zhuǎn)也都可以如此用矩陣運算來表示。
而矩陣之間可以用乘法進(jìn)行運算得到一個新矩陣,所以如果繞z,y,x軸的旋轉(zhuǎn)矩陣分別為Z,Y,X,那么它們的乘積ZYX也是一個旋轉(zhuǎn)矩陣。
萬向節(jié)死鎖由上文可知,我們總是可以用三個分別表示繞x,y,z軸旋轉(zhuǎn)的矩陣的乘積來表示任意一個旋轉(zhuǎn)運算。這看起來似乎沒有問題,事實上,絕大多數(shù)情況也確實沒有任何問題。
這里要稍微偏離一下話題,考慮一下自己的手臂。觀察手臂的構(gòu)造,我們可以發(fā)現(xiàn)它大致為:肩膀-肩關(guān)節(jié)-上臂-肘關(guān)節(jié)-小臂-腕關(guān)節(jié)-手。也就是我們用三個關(guān)節(jié)連接了四塊部件,這三個關(guān)節(jié)為我們的手臂提供了靈活性,因為我們的骨頭可以在關(guān)節(jié)處旋轉(zhuǎn)。如果沒有關(guān)節(jié)的話,手臂就會是筆直筆直的,沒法彎曲了。來做一個不符合實際的假設(shè),假設(shè)肩關(guān)節(jié)只能沿z軸旋轉(zhuǎn)(把你的上臂上下抬動),肘關(guān)節(jié)只能繞y軸旋轉(zhuǎn)(縮起小臂到胸前這類的),腕關(guān)節(jié)只能繞x軸旋轉(zhuǎn)(讓你的拳頭像撥浪鼓一樣轉(zhuǎn)來轉(zhuǎn)去),然后把手?jǐn)傞_,考慮手心的面向與手指的朝向。如果我們的關(guān)節(jié)能360度旋轉(zhuǎn)的話,那這就和上面提到的三個沿坐標(biāo)軸的旋轉(zhuǎn)的疊加是一樣的。轉(zhuǎn)動肩關(guān)節(jié)時,顯然我們的掌心也會跟著轉(zhuǎn)動,改變面向,這說明肘關(guān)節(jié)的轉(zhuǎn)動作用到了手的轉(zhuǎn)動這邊。顯然,肘關(guān)節(jié)、腕關(guān)節(jié)的轉(zhuǎn)動也會作用到手上,也就是說三個關(guān)節(jié)的轉(zhuǎn)動疊加到了手上面。另一方面,因為上面提到任意旋轉(zhuǎn)都能由三個沿坐標(biāo)軸的旋轉(zhuǎn)的疊加得到,所以我們的手心和手指能朝向任何方向。這看起來沒有問題。
但是此時考慮一種情況,如圖中所示(模型使用 ** gic poser web),抬平上臂,把小臂抬平到胸前。然后嘗試腕關(guān)節(jié)的旋轉(zhuǎn)和肩關(guān)節(jié)的旋轉(zhuǎn),我們會發(fā)現(xiàn),這兩個不同的關(guān)節(jié)的旋轉(zhuǎn),會使得手心朝向的轉(zhuǎn)變是相同的——都是沿z軸,也就是肩關(guān)節(jié)繞著旋轉(zhuǎn)的那個軸,而手指的朝向則是固定不變的。換句話說,我們本應(yīng)是分別沿x軸、z軸這兩個方向的旋轉(zhuǎn),現(xiàn)在變成了沿相同方向的旋轉(zhuǎn)了。
為什么會這樣呢?注意到三個關(guān)節(jié)并不是獨立的:肩關(guān)節(jié)的旋轉(zhuǎn)會帶動肘關(guān)節(jié)和腕關(guān)節(jié)的移動,肘關(guān)節(jié)的旋轉(zhuǎn)也會帶動腕關(guān)節(jié)的移動。正如同這三個關(guān)節(jié)都會作用到位處手臂末端的手一樣,上面的關(guān)節(jié)也會作用到下面的關(guān)節(jié)。旋轉(zhuǎn)肩關(guān)節(jié)時會同時帶動肘關(guān)節(jié)和腕關(guān)節(jié),所以對之后肘關(guān)節(jié)與腕關(guān)節(jié)的旋轉(zhuǎn)產(chǎn)生的影響是相同的。但是肘關(guān)節(jié)只會帶動腕關(guān)節(jié),不會帶動肩關(guān)節(jié)。上文中,抬平小臂到胸前的行為就轉(zhuǎn)動了肘關(guān)節(jié),從而影響到了腕關(guān)節(jié),但是沒有對肩關(guān)節(jié)產(chǎn)生影響,結(jié)果導(dǎo)致腕關(guān)節(jié)旋轉(zhuǎn)的效果變成與肩關(guān)節(jié)旋轉(zhuǎn)一樣的效果了。
回到原來的問題,在計算機(jī)中用三個矩陣表示任意旋轉(zhuǎn)是否也會有同樣的問題呢?注意到上述問題之所以會產(chǎn)生是因為中間的關(guān)節(jié)會影響到最下面的關(guān)節(jié),而不會影響到最上面的關(guān)節(jié)。再看看矩陣表示的旋轉(zhuǎn),我們用ZYX這一矩陣乘積來表示任意旋轉(zhuǎn),也就是p'=ZYXp,我們將Z,Y,X,ZYX這四個矩陣都給寫出來看看:
若我們?nèi)?/p>
,則乘積變?yōu)?/p>
,注意到無論我們怎樣修改θ、φ,都不會改變z’的值,z’始終等于-x。也就是說,當(dāng)我們沿y軸旋轉(zhuǎn)90°時,此時X,Z這兩個旋轉(zhuǎn)矩陣都是在進(jìn)行繞z軸的旋轉(zhuǎn)。這與之前手臂的情況是相同的。因為矩陣的相乘作用到p點也是有順序的,我們先左乘X,再左乘Y,那么在乘Y時,實際上也影響到了已經(jīng)乘進(jìn)去的X。而在乘Z的時候,會對X和Y產(chǎn)生相同的影響。所以這里的p就相當(dāng)于我們的手心與手指的朝向,X相當(dāng)于腕關(guān)節(jié),Y相當(dāng)于肘關(guān)節(jié),Z相當(dāng)于肩關(guān)節(jié)。Y會對X產(chǎn)生影響,但影響不到Z,使得X變成與Z沿著相同軸旋轉(zhuǎn)的矩陣。
結(jié)語本文講了講旋轉(zhuǎn)的定義、計算機(jī)中旋轉(zhuǎn)的運算方式,然后重點講解了隨之而來的萬向節(jié)死鎖問題。在這里順帶提一下萬向節(jié)這東西,原版的萬向節(jié)中之所以會有萬向節(jié)死鎖問題,也是因為三個環(huán)并不完全獨立,中間的環(huán)會帶動最里面的環(huán),但不會影響到最外面的環(huán)。萬向節(jié)死鎖問題是個不可避免的問題,只要使用不相互獨立的三次旋轉(zhuǎn)來表示任意旋轉(zhuǎn),都會帶來這一問題。但是萬向節(jié)死鎖并不可怕,它僅僅只會在中間的旋轉(zhuǎn)取極端值的情況下出現(xiàn),若我們只是想表示一個旋轉(zhuǎn),那萬向節(jié)死鎖不會帶來任何問題,畢竟我們總是能找到沿坐標(biāo)軸的三個旋轉(zhuǎn)來表示任意旋轉(zhuǎn)。萬向節(jié)死鎖只會在需要旋轉(zhuǎn)不斷疊加的情況下才會導(dǎo)致問題,例如飛機(jī)控制、旋轉(zhuǎn)插值。所以在那方面的應(yīng)用中,本文沒有提及的四元數(shù)被廣泛引用。
萬向節(jié)死鎖到底是什么,它又為何產(chǎn)生這問題實在是困擾了我相當(dāng)久,僅以此 ** 個記錄,若有不正之處,歡迎指出。