[英]Rotation and direction of a vector in 3D space - Inverse Order
我在3D空間中有兩個向量, S
(開始)和T
(目標),並且我想找到允許這種變換的旋轉矩陣(RM)。
我知道通過計算叉積 S × T
可以獲得旋轉軸。 S
和T
之間的角度由tan⁻¹(||S × T||, S·T)
,其中S·T
是S和T之間的點積 。
這給了我旋轉矢量rotvec = [S x T; angle]
rotvec = [S x T; angle]
(叉積標准化)。 然后,通過使用函數vrrotvec2mat (在MATLAB中)或transforms3d.axangles.axangle2mat (在Python中),我可以獲得與從S
到T
的轉換相對應的旋轉矩陣。
在我的應用中, T
由點積 RM·D
,其中D
是3x1
向量。 我的目標 是找到RM 。 我知道S
, T
和D
,但是我很難理解其背后的數學原理。
實際上,我想在S
和T'
之間找到一個RM,其中T'
是在應用D
(方向)之前的目標矢量。
更多背景信息 :我想從相機坐標系中的3D點獲取人體關節角度。
為了完成這項工作,您還需要旋轉中心(旋轉后保持不變的點)...現在,我們需要兩個變換矩陣,一個代表變換之前的坐標系,另一個代表變換之后的坐標系。
要構建3D變換矩陣,您需要3個垂直基矢量和原點位置,請參見:
現在旋轉軸將是基本向量之一,我們可以使用S,T
作為第二個向量,因此我們可以使用叉積計算第三個向量,並且原點將成為旋轉中心:
X = cross(S,T); // rotation axis
X /= |X|; // unit vector
Y = S; // start vector
Y /= |Y|; // unit vector
Z = cross(X,Y); // Z perpendicular to X,Y
Z /= |Z|; // unit vector
O = center_of_rotation;
因此,從中構造4x4變換矩陣A
並對B
執行相同操作,但使用T
而不是S
現在我們要計算差分變換,因此,如果p=(x,y,z,1)
是要變換的任意點,則:
p' = Inverse(A)*p
p' = B*p'
因此,您的變換矩陣M
為:
M = Inverse(A)*B;
請注意,如果您使用其他方程式(乘法順序,矩陣方向等),則方程式可能會發生變化,這將與標准OpenGL約定一起使用。
您還可以使用完整的偽逆矩陣來更有效和准確地計算Inverse(A)
。
如您所見,您不需要任何角度測量法和角度即可(矢量數學很好用)
[Edit1] C ++示例
它使用VCL(您可以忽略的AnsiString和mm_log)和我的向量數學運算(使用的函數在第一個鏈接中)。
//---------------------------------------------------------------------------
AnsiString matrix_prn(double *a)
{
int i; AnsiString s;
for (s ="(",i=0;i<16;i+=4) { if (a[i]>=0.0) s+=" "; s+=AnsiString().sprintf("%2.3lf,",a[i]); } s[s.Length()]=')'; s+="\r\n";
for (s+="(",i=1;i<16;i+=4) { if (a[i]>=0.0) s+=" "; s+=AnsiString().sprintf("%2.3lf,",a[i]); } s[s.Length()]=')'; s+="\r\n";
for (s+="(",i=2;i<16;i+=4) { if (a[i]>=0.0) s+=" "; s+=AnsiString().sprintf("%2.3lf,",a[i]); } s[s.Length()]=')'; s+="\r\n";
for (s+="(",i=3;i<16;i+=4) { if (a[i]>=0.0) s+=" "; s+=AnsiString().sprintf("%2.3lf,",a[i]); } s[s.Length()]=')';
return s;
}
//---------------------------------------------------------------------------
AnsiString vector_prn(double *a)
{
int i; AnsiString s;
for (s ="(",i=0;i<3;i++) { if (a[i]>=0.0) s+=" "; s+=AnsiString().sprintf("%2.3lf,",a[i]); } s[s.Length()]=')';
return s;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
int i;
double O[3]={0.00, 0.00,0.00}; // center ofrotation
double S[3]={4.10,-9.44,0.54}; // start vector
double T[3]={1.40,-9.08,4.10}; // end vector
double A[16],_A[16],B[16],M[16],X[3],Y[3],Z[3];
// A
vector_mul(X,S,T); // rotation axis
vector_one(X,X); // unit vector
vector_one(Y,S); // unit start vector
vector_mul(Z,X,Y); // Z perpendicular to X,Y
vector_one(Z,Z); // unit vector
for (i=0;i<3;i++)
{
A[ 0+i]=X[i];
A[ 4+i]=Y[i];
A[ 8+i]=Z[i];
A[12+i]=O[i];
A[(i<<2)+3]=0.0;
} A[15]=1.0;
// B
vector_one(Y,T); // unit end vector
vector_mul(Z,X,Y); // Z perpendicular to X,Y
vector_one(Z,Z); // unit vector
for (i=0;i<3;i++)
{
B[ 0+i]=X[i];
B[ 4+i]=Y[i];
B[ 8+i]=Z[i];
B[12+i]=O[i];
B[(i<<2)+3]=0.0;
} B[15]=1.0;
// M = B*Inverse(A)
matrix_inv(_A,A);
matrix_mul(M,_A,B);
mm_log->Lines->Add("A");
mm_log->Lines->Add(matrix_prn(A));
mm_log->Lines->Add("B");
mm_log->Lines->Add(matrix_prn(B));
mm_log->Lines->Add("M");
mm_log->Lines->Add(matrix_prn(M));
mm_log->Lines->Add("");
vector_one(S,S); // unit start vector
vector_one(T,T); // unit end vector
mm_log->Lines->Add("S = "+vector_prn(S));
matrix_mul_vector(X,M,S);
mm_log->Lines->Add("X = "+vector_prn(X));
mm_log->Lines->Add("T = "+vector_prn(T));
}
//-------------------------------------------------------------------------
結果如下:
A
(-0.760, 0.398,-0.514, 0.000)
(-0.361,-0.916,-0.175, 0.000)
(-0.540, 0.052, 0.840, 0.000)
( 0.000, 0.000, 0.000, 1.000)
B
(-0.760, 0.139,-0.635, 0.000)
(-0.361,-0.903, 0.235, 0.000)
(-0.540, 0.408, 0.736, 0.000)
( 0.000, 0.000, 0.000, 1.000)
M
( 0.959, 0.258,-0.115, 0.000)
(-0.205, 0.916, 0.345, 0.000)
( 0.194,-0.307, 0.932, 0.000)
( 0.000, 0.000, 0.000, 1.000)
S = ( 0.398,-0.916, 0.052)
X = ( 0.139,-0.903, 0.408) // X = M * S
T = ( 0.139,-0.903, 0.408)
如您所見,如果我將單位S
轉換為M
,就得到了單位T
向量。 PS。 我的matrix_mul_vector
和vector_mul
假定w=1.0
但是當O=(0.0,0.0,0.0)
,矢量和點相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.