日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

万向节锁的理解

發布時間:2024/3/12 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 万向节锁的理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載: https://www.cnblogs.com/psklf/p/5656938.html


結論

  • 我直接拋出結論:
    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軸就指向同一個方向(它們相當于同一個軸了)。

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

我的理解

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

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

1.世界坐標系
2.物體坐標系
那么這兩者是什么關系呢?

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

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

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

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

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

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

看一下在OpenGL 實現旋轉的代碼:

void configRotateTrans(GLfloat radX, GLfloat radY, GLfloat radZ) {GLfloat xTrans[4][4] = {0};GLfloat yTrans[4][4] = {0};GLfloat zTrans[4][4] = {0};GLfloat tempMatrix[4][4] = {0};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 * zTransmultiMatrix(xTrans, yTrans, tempMatrix);multiMatrix(tempMatrix, zTrans, rotateTrans);

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

現在我們明確了兩點:

1.物體的旋轉是以世界坐標系為參考的。
2.物體旋轉的順序是確定的,和用戶輸入的旋轉的順序無關。

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

操作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,這并不是什么缺陷,陷阱,而是我們的思維方式是錯誤的,所以導致這個問題的出現。

總結

以上是生活随笔為你收集整理的万向节锁的理解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。