基于两个向量创建旋转矩阵

时间:2013-03-26 22:16:38

标签: math vector matrix rotation

当我传入M * [0, 0, 1] (forward) = V的向量(V)时,我希望创建一个旋转矩阵(M)。

我这样做是因为我想使用这个矩阵将其他向量相乘以将它们放在局部空间中(不确定这是否是正确的术语,但希望你能理解)。

V = [0, 1, 0]
M = ?
Result = M * V = [0, 0, -1]

因此,如果[0,0,1]在乘以M之后向上倾斜90度成为[0,1,0] ...那么M是什么?

4 个答案:

答案 0 :(得分:4)

三维旋转很难思考,甚至​​在文本中难以解释。但是,可以将左手形成近似于一组三维轴的东西。请看以下描述弗莱明左手规则的维基百科页面;特别是,请查看第二个图表,其中的手指标记为 I B F http://en.wikipedia.org/wiki/Fleming's_left-hand_rule_for_motors

用自己的手做同样的形成,而不是标记手指 B F ,让我们称之为< em> x , y z 。此外,我们会说这三个手指在手掌处相交的点是原点,点(0 0 0),并且从原点朝向其中一个手指/拇指的尖端移动的点正在移动积极的方向。

向量 v =(0 1 0)是食指上的一个点(我们称之为 y )。我们想要旋转此点以形成点(0 0 -1)。此点位于 z 轴(拇指)上,但它是负的,因此它位于原点“下方”的一个单位,从拇指尖朝向原点。

因此,要将点(0 1 0)旋转为(0 0 -1),我们需要围绕 x 轴(中指)旋转它。想象一下,将一张光盘放在你的中指上,按下它,使它位于你的食指和拇指所定义的平面上 - ( x y )平面 - 和在光盘的中心放置一个标记。现在想象一下将该标记与食指对齐,使标记位于该点(0 1 0)。您可以围绕中指旋转光盘,使标记位于该点(0 0 -1)。因此,所需的旋转是围绕 x 轴的旋转。

以下维基百科页面为您提供了rotations in three-dimensional space around the x, y, and z axes的等式。围绕 x 轴旋转的矩阵是:

/1     0        0   \
|0   cos θ    -sin θ|
\0   sin θ     cos θ/

如果您使用右手旋转光盘,则定义矩阵,使得θ的负值对应右手的顺时针运动(反之亦然,为正值)。我们需要旋转的角度是负四分之一转,因此所需的矩阵是:

/1    0     0\
|0    0     1|
\0   -1     0/

请记住,角度可以用度数或弧度表示,因此如果在代码中实现更一般的旋转,则需要检查数学库所期望的内容。

答案 1 :(得分:1)

即使用手,轻松,轻松。通过检查,可以看出M基本上交换了y轴和z轴,只留下了x。

这个数组完成了这项任务:

    [1  0  0]
M = [0  0  1]
    [0 -1  0]

M * [0, 1, 0] = [0, 0, -1]

请注意,此解决方案在对这两个特定向量具有相同影响的转换矩阵集中并不是唯一的。事实上,有无数的这样的矩阵。这是一个:

     [sqrt(2)/2     0    sqrt(2)/2]
M2 = [sqrt(2/2)     0   -sqrt(2)/2]
     [0            -1         0   ]

答案 2 :(得分:1)

因此,您向V=(vx,vy,vz)提供了本地 z -axis U=(ux,uy,uz)和本地 x -axis,其中U并且V单位向量:

本地 y -axis为W=Normalized(Cross(V,U))。现在,如果UV不完全相同,则需要使用U=Normalized(Cross(W,V))

进行更正

3×3旋转矩阵

    | Ux  Wx  Vx |
M = | Uy  Wy  Vy |
    | Uz  Wz  Vz |

请注意Cross(A,B) = (Ay*Bz-Az*By, Az*Bx-Ax*Bz, Ax*By-Ay*Bz)是叉积运算符,Normalized(A) = (Ax,Ay,Az)/SQRT(Ax*Ax+Ay*Ay+Az*Az)创建单位向量。

答案 3 :(得分:0)

我还必须解决类似的问题。不过,有人需要这个,我在这里找到了一种合适的方法[https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d/]

这是用c ++计算的方式

  Eigen::Vector3f a(34, 0, 1);
  Eigen::Vector3f b(2, 2, 1);
  a = a/a.norm();
  float b_norm = b.norm();
  b = b/b_norm;

  Eigen::Vector3f v = a.cross(b);
  float s = v.norm();
  float c = a.dot(b);
  Eigen::Matrix3f vx;
  vx << 0, -v[2], v[1], v[2], 0, -v[0], -v[1], v[0], 0;
  Eigen::Matrix3f r = Eigen::Matrix3f::Identity(3,3);
  if(s != 0 ){
    r = r + vx + vx*vx*((1-c)/std::pow(s, 2));
  }else{
    std::cout<< "doesn't work if a == -b"<< std::endl;
  }

  std::cout<<"Testing..."<< std::endl;
  std::cout << "b: " << b.transpose() << std::endl;
  std::cout << "After projected: b: "<< (r*a).transpose() << std::endl;

注意:如果a = -b

,该操作将失败