2015-06-13 43 views
1

我想弄清楚如何反轉RotateAxisAngle以獲得圍繞這些任意軸(或產生相同的淨旋轉的同等旋轉,不一定是相同的)的迴轉。有誰知道該怎麼做?我使用的是MathGeoLib,但是我沒有看到相反的方式,當你所有的是矩陣時,要返回關於軸的角度。逆轉RotateAxisAngle回到角度

這裏的前進方向代碼(RotateAxisAngle是MathGeoLib):

float4x4 matrixRotation = float4x4::RotateAxisAngle(axisX, ToRadian(rotation.x)); 
matrixRotation = matrixRotation * float4x4::RotateAxisAngle(axisY, ToRadian(rotation.y)); 
matrixRotation = matrixRotation * float4x4::RotateAxisAngle(axisZ, ToRadian(rotation.z)); 

現在我想回到程度,這些任意軸,以相同的順序(當然,拉斷Z,然後Y,那麼X),所以如果我再做一次,向前的方向,將產生相同的淨旋轉。

這裏的對應於一組旋轉的樣本/矩陣我張貼以上,如果有幫助,倒車回去吧:

axisX: 
x 0.80878228 float 
y -0.58810818 float 
z 0.00000000 float 
Rot about that axis: 
30.000000 float 

axisY: 
x 0.58811820 float 
y 0.80877501 float 
z 0.00000000 float 
Rot about that axis: 
60.000000 float 

axisZ: 
x 0.00000000 float 
y 0.00000000 float 
z 1.0000000 float 
Rot about that axis: 
40.000000 float 

形成這個矩陣,並存儲到一個文件,並需要檢索有關的旋轉軸以上(不含轉左右任何信息最初使用)

[4][4] 
[0x0] 0.65342271 float 
[0x1] -0.51652151 float 
[0x2] 0.55339342 float 
[0x3] 0.00000000 float 
[0x0] 0.69324547 float 
[0x1] 0.11467478 float 
[0x2] -0.71151978 float 
[0x3] 0.00000000 float 
[0x0] 0.30405501 float 
[0x1] 0.84856069 float 
[0x2] 0.43300733 float 
[0x3] 0.00000000 float 
[0x0] 0.00000000 float 
[0x1] 0.00000000 float 
[0x2] 0.00000000 float 
[0x3] 1.0000000 float 
+0

並不意味着_使用第一次旋轉的結果上的精確的負角度值來逆轉它_? –

+0

float4x4 :: ToEulerXYZ()? https://github.com/juj/MathGeoLib/blob/master/src/Math/float4x4.cpp –

+0

這樣就可以在單位軸周圍獲得歐拉而不是任意軸。 –

回答

0

OK,我會採取另一種刺在此。我的第一個答案是XYZ順序的旋轉。這個答案適用於ZYX訂單,現在我更瞭解MathGeoLib的工作原理。

MathGeoLib將位置向量表示爲列向量v = [x y z 1]^T其中^T是將行翻轉爲列的轉置運算符(反之亦然)。旋轉矩陣預乘列列向量。因此,如果我們有一個矩陣Rx(s)表示圍繞x軸旋轉s度,那麼表示圍繞y軸旋轉t度的旋轉,然後旋轉Rz(u)表示圍繞z軸旋轉u度的旋轉Rz(u),我們將它們組合起來並與v作爲Rx(s) Ry(t) Rz(u) v相乘,我們實際上首先應用z旋轉。但是我們仍然可以從組合矩陣中計算出角度,只是這些公式將與更常見的XYZ順序不同。

我們有如下的旋轉矩陣的左上方塊。 (除了對角線元素是1以外,第四行和所有列都是0;以後的計算決不會改變,因此我們可以安全地忽略)MathGeoLib似乎使用左手座標,因此旋轉矩陣爲:

 [1  0  0]   [ cos t 0 sin t]   [ cos u -sin u 0] 
Rx(s) = [0 cos s -sin s], Ry(t) = [  0 1  0], Rz(u) = [ sin u cos u 0] 
     [0 sin s cos s]   [-sin t 0 cos t]   [  0  0 1] 

(注意位置 - 號Ry(t),它的存在是因爲我們認爲在循環順序座標Rx(s)旋轉y和z; Ry(t)旋轉Z和X; Rz(u)旋轉x和y由於Ry(t)旋轉ž。 x不按字母順序排列,但按循環順序排列,旋轉方向與您對字母順序所期望的方向相反。

現在我們按照正確的順序將矩陣相乘。Rx(s) Ry(t)

[1  0  0][ cos t 0 sin t] [  cos t  0  sin t] 
[0 cos s -sin s][  0 1  0] = [ sin s*sin t cos s -sin s*cos t] 
[0 sin s cos s][-sin t 0 cos t] [-cos s*sin t sin s cos s*cos t] 

的與Rz(u)該產品是

[  cos t  0  sin t][ cos u -sin u 0] 
[ sin s*sin t cos s -sin s*cos t][ sin u cos u 0] = 
[-cos s*sin t sin s cos s*cos t][  0  0 1] 

[     cos t*cos u     -cos t*sin u  sin t] 
[ sin s*sin t*cos u+cos s*sin u -sin s*sin t*sin u+cos s*cos u -sin s*cos t] 
[-cos s*sin t*cos u+sin s*sin u cos s*sin t*sin u+sin s*cos u cos s*cos t] 

因此,我們可以計算出角度如下:

tan s = -(-sin s * cos t)/(cos s * cos t) = M23/M33 => s = -arctan2(M23,M33) 
sin t = M13 => t = arcsin(M13) 
tan u = -(-cos t * sin u)/(cos t * cos u) = M12/M11 => u = -arctan2(M12,M11) 

如果我們要實現這些計算,我們需要了解矩陣在MathGeoLib中的索引方式。索引是行重大,就像數學符號,但索引爲0(電腦型)開始,而不是在1(數學式的),所以你想要的C++公式

s = -atan2(M[1][2],M[2][2]); 
t = asin(M[0][2]); 
u = -atan2(M[0][1],M[0][0]); 

角度以弧度返回如此如果需要將需要轉換成度。當旋轉Z軸,Y軸和X軸位於標準位置(001),(010)和(100)時,應該測試該結果。

如果我們要扭轉關於非標準軸的旋轉,就像在您的示例中一樣,問題變得更加困難。但是,我認爲可以通過「座標變換」來完成。所以,如果我們的旋轉矩陣的奧祕是matrixRotation,我相信你可以只形成「共軛」矩陣

M = coordinateChangeMatrix*matrixRotation*coordinateChangeMatrix^{-1} 

,然後用上面的公式。這裏coordinateChangeMatrix將是矩陣

[Xaxis0 Xaxis1 Xaxis2 0] 
[Yaxis0 Yaxis1 Yaxis2 0] 
[Zaxis0 Zaxis1 Zaxis2 0] 
[  0  0  0 1] 

在旋轉X軸是(Xaxis0,Xaxis1,Xaxis2)。在你的例子中,這些數字將是(0.808...,-0.588...,0)。你應該確保旋轉矩陣是正交的,即X軸與它自己的點積是1,X軸與另一個軸的點積是0,並且對於任何其他軸是相同的。如果座標變換矩陣不是標準正交的,則計算可能仍然有效,但我不確定。

座標變換矩陣的逆可以使用float4x4::inverseOrthonormal來計算,或者如果它不是正交的,你可以使用float4x4::inverse,但正如我所提到的,我不知道它會如何工作。

+0

好吧,這很有道理,謝謝你的解釋,它甚至幾乎奏效! :)這種方式是正確的:float4x4 mat = coordinateChangeMatrix * matrixRotation * coordinateChangeMatrixInverse;除了最後一件事!檢索到的值都是他們應該是負面的。 Aka -30,-60,-40當輸入是30,60,40時。我可以對它們都進行否定,但是對此有一個很好的解釋嗎?是因爲這是倒退還是什麼? –

+1

天哪,這是一種解脫,它幾乎是正確的,即使它不完全正確!我想我知道問題是什麼:上面的計算是針對右手座標系的。 (旋轉萬向節中的另一個變量。)對於左手座標系,只會取消正弦函數前面的所有符號,或者等價地否定所記下的角度。我找不到MathGeoLib文檔中座標系的旋向性,但這意味着我們現在可以假定它是左旋的。只需將公式中的符號改爲s,t,u就可以更正。 –

+0

我剛剛編輯我的答案,使用左手座標系,並消除了語言中的不確定性。 –

0

如果你只是想能逆轉你在一個步驟已經有了旋轉的旋轉,可以反轉旋轉矩陣。 float4x4::InverseOrthonormal應該可以工作,而且速度快,準確。 float4x4::Inverse也可以工作,但速度較慢,準確性較差。

如果你真的想恢復角度,它是這樣的。 (有許多不同的約定,即使對XYZ也是如此;我認爲這個約定是匹配的,但是您可能需要對矩陣進行轉置或進行其他修改。如果這不起作用,我可以建議替代方案。 Wikipedia article有關歐拉角到矩陣轉換的描述。在所得到的矩陣,我們有

A11 = cos theta cos psi 
A21 = -cos theta sin psi 
A31 = sin theta 
A32 = -sin phi cos theta 
A33 = cos phi cos theta 

其中phi是繞x軸的旋轉,θ-是圍繞y軸的旋轉,和psi是圍繞z軸的旋轉。要恢復的角度,我們做

phi = -arctan2(A32,A33) 
theta = arcsin(A31) 
psi = -arctan2(A21,A11) 

角度可能不完全匹配原有的角度,但旋轉應該匹配。 arctan2是arctan函數的兩個參數形式,它考慮了參數代表的點的象限,並正確處理90度角。我想你可能不得不使用轉置來代替。這很簡單:你只需交換指數在上式中:

phi = -arctan2(A23,A33) 
theta = arcsin(A13) 
psi = -arctan2(A12,A11) 

如果沒有這些工作,我可以把在MathGeoLib圖書館仔細看看,找出他們在做什麼。

更新

我忽略考慮到圍繞旋轉在我以前的答覆軸的賬戶信息。現在我想我有一個處理它們的計劃。

這個想法是「改變座標」,然後在新座標中進行上述操作。我對細節有點朦朧,所以這個過程目前有點「鍊金術」。OP應該嘗試我的建議的各種組合,看看他們中的任何一個是否工作......沒有太多(目前只有4個......)。

該想法是使用旋轉軸的座標形成座標變換矩陣。我們這樣做是這樣的:

axisX: 0.80878228 -0.58810818 0.00000000 0.00000000 
axisY: 0.58811820 0.80877501 0.00000000 0.00000000 
axisZ: 0.00000000 0.00000000 1.0000000 0.00000000 
and..: 0.00000000 0.00000000 0.00000000 1.0000000 

我剛拍攝的3個3矢量axisX,axisY,axisZ,填補他們以0結尾,並在底部添加的行[0 0 0 1]

我還需要一個矩陣的逆。由於座標系是一個標準正交幀,所以反轉就是轉置。您可以使用庫中的InverseOrthonormal函數;它所做的只是形成轉置。

現在把你的神祕矩陣,它乘以座標變換矩陣,後乘以座標變換矩陣的逆。然後使用反向三角函數應用上面兩個計算之一。穿過我的手指,我認爲就是這樣......

如果這樣不行,那麼將神祕矩陣乘以座標變換矩陣的倒數,然後乘以座標變換矩陣。然後應用其中一組觸發公式。

是否行得通?

+0

是的,我需要角度,因爲我正在轉換格式,這就是他們如何存儲它。 –

+0

我發佈了兩套公式。其中之一應該工作。嘗試一下,讓我知道。 –

+0

我很欣賞這種努力,但是,這些數字並沒有加起來。我在我的問題中包含了一個樣本矩陣。也許原因是我的座標軸不是單位座標軸,它們是任意的自定義示例?希望我的樣本可以幫助激發一個鐘聲。我基本上得到0,0,你的例子的值,但他們不會產生關於任意軸的相同旋轉。 –