萬向節鎖 Gimbal Lock 的理解

2022-03-16 12:57:31 字數 3150 閱讀 1364

目錄我直接丟擲結論:

gimbal lock 產生的原因不是尤拉角也不是旋轉順序,而是我們的思維方式和程式的執行邏輯沒有對應,也就是說是我們的觀念導致這個情況的發生。

首先我們看一下尤拉角的定義:

用一句話說,尤拉角就是物體繞座標系三個座標軸(x,y,z軸)的旋轉角度。

在這裡,座標系可以是世界座標系,也可以是物體座標系,旋轉順序也是任意的,可以是xyz,xzy,yxz,zxy,yzx,zyx中的任何一種,甚至可以是xyx,xyy,xzz,zxz等等等等。。。。。。所以說尤拉角多種多樣。尤拉角可分為兩種情況:

1,靜態:即繞世界座標系三個軸的旋轉,由於物體旋轉過程中座標軸保持靜止,所以稱為靜態。

2,動態:即繞物體座標系三個軸的旋轉,由於物體旋轉過程中座標軸隨著物體做相同的轉動,所以稱為動態。

是指物體的兩個旋轉軸指向同乙個方向。實際上,當兩個旋轉軸平行時,我們就說萬向節鎖現象發生了,換句話說,繞乙個軸旋轉可能會覆蓋住另乙個軸的旋轉,從而失去一維自由度

通常說來,萬向節鎖發生在使用eular angles(尤拉角)的旋轉操作中,原因是eular angles按照一定的順序依次獨立地繞軸旋轉。讓我們想象乙個具體的旋轉場景,首先物體先繞轉x軸旋轉,然後再繞y軸,最後繞z軸選擇,從而完成乙個旋轉操作(飄飄白雲譯註:實際是想繞某乙個軸旋轉,然而eular angle將這個旋轉分成三個獨立的步驟進行),當你繞y軸旋轉90度之後萬向節鎖的問題就出現了,因為x軸已經被求值了,它不再隨同其他兩個軸旋轉,這樣x軸與z軸就指向同乙個方向(它們相當於同乙個軸了)。

看得懂嗎?我是看不太懂~

我們先來考慮一下,旋轉到底是怎麼個旋轉法。

靜態的情況很好理解,怎麼旋轉都不會有問題,萬向節的問題是不會出現在靜態的旋轉過程中的。但是你想像一下動態的旋轉,動態的旋轉,這裡會有兩個座標系,看清楚了,兩個座標系!

世界座標系

物體座標系

那麼這兩者是什麼關係呢?

一開始,這兩個座標系是重合的,但是旋轉開始以後,世界座標系不會變化,物體座標系隨著旋轉就發生變化了。

親愛的讀者,你們先想想,這兩個座標系的關係,你們覺得物體旋轉是繞著那個座標系旋轉的?

你會說:

你剛剛不是說了嘛!是繞著物體的座標系旋轉的!

對,沒有錯,那麼在物體旋轉的時候,物體的座標系是不是一直在變化呢?是的!那麼我們在給他旋轉的引數的時候考慮到這個問題了嗎?沒有!

就是說我給他的旋轉的引數是基於一種假設:每一次旋轉都是以物體的座標係為參考來進行的。就是說我是希望它每一次旋轉前,都能夠將旋轉引數在物體座標系上進行計算。很簡單,一架飛機,作為機長,每次旋轉以後他跟著飛機旋轉了,後面的旋轉操作自然是基於新的物體座標系來的。

但是實際上,程式解析我給的資料的時候,只是簡單地將三個軸的旋轉乙個個的相乘,也就是說,總的來說還是在最開始的那個座標系(也就是一直不動的世界座標系)下面計算的。而且需要注意的是:每一次進行計算的順序是確定不變的!這也是為什麼有人會說萬向節問題是因為旋轉順序導致的樂。

看一下在opengl 實現旋轉的**:

void configrotatetrans(glfloat radx, glfloat rady, glfloat radz) ;

glfloat ytrans[4][4] = ;

glfloat ztrans[4][4] = ;

glfloat tempmatrix[4][4] = ;

xtrans[3][3] = 1;

xtrans[0][0] = 1;

xtrans[1][1] = cosf(radx);

xtrans[1][2] = -sinf(radx);

xtrans[2][2] = cosf(radx);

xtrans[2][1] = sinf(radx);

ytrans[3][3] = 1;

ytrans[0][0] = cosf(rady);

ytrans[0][2] = sinf(rady);

ytrans[2][2] = cosf(rady);

ytrans[2][0] = -sinf(rady);

ytrans[1][1] = 1;

ztrans[3][3] = 1;

ztrans[2][2] = 1;

ztrans[0][0] = cosf(radz);

ztrans[0][1] = -sinf(radz);

ztrans[1][0] = sinf(radz);

ztrans[1][1] = cosf(radz);

// multiply the 3 matrix

// rotatetrans = xtrans * ytrans * ztrans

multimatrix(xtrans, ytrans, tempmatrix);

multimatrix(tempmatrix, ztrans, rotatetrans);

看懂了嗎,物體最終在哪個位置是簡單粗暴地將繞xyz三個旋轉的矩陣連續相乘得到的,計算的順序是x->y->z,那麼比如使用者先輸入繞y軸轉90度,再輸入繞x軸轉90度。其實程式執行的時候,還是會先將x軸的資料進行計算,再計算y軸的資料。但是如果使用者先輸入繞y軸轉90度,再輸入繞z軸轉90度,程式還是按照x-y-z的順序來,只是正好使用者也是這樣輸入。

現在我們明確了兩點:

物體的旋轉是以世界座標係為參考的。

物體旋轉的順序是確定的,和使用者輸入的旋轉的順序無關。

那麼還是剛剛那兩種情況:

操作a:

使用者第一次輸入: 繞y軸轉90度,第二次輸入:繞x軸轉90度。

實際程式執行:先繞x軸轉90度,再繞y軸轉90度。

操作b:

使用者第一次輸入: 繞y軸轉90度,第二次輸入:繞z軸轉90度。

實際程式執行:先繞y軸轉90度,再繞z軸轉90度。

現在發揮一下想象力,當物體繞y軸轉動90度以後,物體座標系的x軸和世界座標系的z軸是不是變成了同乙個軸?好的,那麼這個時候,使用者無論輸入的是繞x軸轉還是繞z軸轉,最終物體轉動是不是都是繞著這個軸(世界z軸/物體x軸)。上面的操作a和操作b的結果是一樣的!

這就是gimbal lock,這並不是什麼缺陷,陷阱,而是我們的思維方式是錯誤的,所以導致這個問題的出現。

萬向節死鎖 萬向節死鎖 gimbal lock

如下圖一,把灰色箭頭想象成是一架飛機,紅,綠藍三個圈看作是三個外圍控制器,外圈帶動所有裡圈運動,裡圈的運動不影響外圈。1,首先,繞y軸旋轉 旋轉綠圈 來確定前進的方向。這時紅圈與藍圈都跟著旋轉。2,然後,繞x軸旋轉 旋轉紅圈 讓飛機仰視或俯視。這時藍圈跟著一起旋轉,綠圈不動。3,最後,繞z軸旋轉 旋...

萬向節死鎖 Gimbal Lock

第一次繞 x轉 角度 第二次繞y轉 xx角度 完後的z軸可能已經和第一次旋轉的x軸重合 第三次繞z轉 角度 重合了 再繞z轉其實相當於第一步的操作 也就是說著步的操作其實是無用的 圖1 物體的初始朝向 現在開始旋轉物體,先繞物體座標系x軸 xl 旋轉30度 這裡我規定沿著軸向軸的負方向看去,順時針旋...

萬向節死鎖 Gimbal Lock

萬向節死鎖 gimbal lock 在學習計算機動畫課程的時候,書中提到固定角和尤拉角朝向表示法有一定的侷限性,它們無法避免gimbal lock現象。在網路上蒐集了很多有關gimbal lock有用的資料,對我很有幫助,在這裡列出乙個索引,以方便其他有需要的朋友檢視 1.維基百科 首先有必要理解一...