向量在3D空间中的旋转和方向-逆序 [英] Rotation and direction of a vector in 3D space - Inverse Order

查看:119
本文介绍了向量在3D空间中的旋转和方向-逆序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在3D空间中有两个向量,分别是S(开始)和T(目标),并且我想找到允许这种变换的旋转矩阵(RM).

I have two vectors in 3D-space, S (Start) and T (Target), and I want to find the Rotation Matrix (RM) that allows such transformation.

我知道通过计算叉积 S × T,我得到了旋转轴. ST之间的夹角由tan⁻¹(||S × T||, S·T)给出,其中S·T是S和T之间的点积.

I know that by computing the cross product S × T I get the rotation axis. The angle between S and T is given by tan⁻¹(||S × T||, S·T), where S·T is the dot product between S and T.

这给了我旋转矢量rotvec = [S x T; angle](叉积被归一化).然后使用 vrrotvec2mat (在MATLAB中)或

This gives me the rotation vector rotvec = [S x T; angle] (the cross product is normalized). Then by using function vrrotvec2mat (in MATLAB) or transforms3d.axangles.axangle2mat (in Python) I can obtain the rotation matrix that corresponds to the transformation from S to T.

在我的应用程序中,T点积 RM·D给出,其中D3x1向量. 我的目标是找到RM .我知道STD,但是我很难理解其背后的数学原理.

In my application T is given by the dot product RM·D, where is D is a 3x1 vector. My goal is to find RM. I know S, T and D, but I am having trouble to understand the math behind this.

在实践中,我想在ST'之间找到一个RM,其中T'是在应用D(方向)之前的目标矢量.

In practice I want to find a RM between S and T', where T' is the target vector before D (the direction) has been applied.

更多上下文信息:我想从相机坐标系中的3D点获取人体关节角度.

A little more context: I want to obtain body joint angles from 3D points in the camera coordinate system.

推荐答案

为完成这项工作,您还需要旋转中心(旋转后保持不变的点)...现在,我们需要两个变换矩阵,其中一个表示转换前后的坐标系.

In order to make this work you also need the center of rotation (point that stays the same after rotation)... Now we need two transform matrices one representing coordinate system before and one after the transform.

要构建3D变换矩阵,您需要3个垂直基矢量和原点位置,请参见:

To construct your 3D transform matrix you need 3 perpendicular basis vectors and origin position see:

现在旋转轴将是基本向量之一,我们可以将S,T用作第二个向量,以便我们可以使用叉积计算第三个向量,并且原点将成为旋转中心:

now rotation axis will be one of the basis vectors and we can use S,T as second one so the third we can compute with cross product and the origin will be the center of rotation:

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)是要变换的任意点,则:

So construct 4x4 transform matrix A from those. And do the same for B but use T instead of S. Now we want to compute the difference transform so if p=(x,y,z,1) is any point to transform then:

p' = Inverse(A)*p 
p' = B*p'         

所以您的变换矩阵M是:

M = Inverse(A)*B;

请注意,如果您使用其他惯例(乘法顺序,矩阵方向等),则方程式可能会发生变化.

Beware this will work with standard OpenGL conventions if you use different one (multiplication order, matrix orientation, etc) the equation might change.

您还可以使用完整的伪逆矩阵来更有效,更准确地计算Inverse(A).

You can also use full pseudo inverse matrix to compute the Inverse(A) more effectively and accurately.

如您所见,您不需要任何角度测量法也不需要角度(矢量数学很好用)

As you can see you do not need any goniometrics nor angle to do this (vector math is nice in this)

[Edit1] C ++示例

它使用VCL(您可以忽略的AnsiString和mm_log)和我的向量数学运算(使用的函数在第一个链接中).

Its using VCL (AnsiString and mm_log which you can ignore) and my vector math (used functions are in the first link).

//---------------------------------------------------------------------------
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)

如您所见,是否用M转换了S单位,我得到了T单位向量. PS.我的matrix_mul_vectorvector_mul假定为w=1.0,但与O=(0.0,0.0,0.0)一样,向量和点都是相同的.

As you can see if I transform unit S by M I got the unit T vector. PS. my matrix_mul_vector and vector_mul assumes w=1.0 but as O=(0.0,0.0,0.0) the vectors and points are the same.

这篇关于向量在3D空间中的旋转和方向-逆序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆