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

Math 基于两个向量创建旋转矩阵,math,vector,matrix,rotation,Math,Vector,Matrix,Rotation,我希望在传入向量(V)时创建一个旋转矩阵(M),其中M*[0,0,1](向前)=V 我这样做是因为我想用这个矩阵乘以其他向量,把它们放到局部空间(不确定这是否是正确的术语,但希望你能理解) 因此,如果[0,0,1]在乘以M之后向上倾斜90度,变成[0,1,0]。。。什么是M?即使是用手,也很简单,很简单。仅通过检查,可以看出M基本上交换了y轴和z轴,而x轴则单独存在 此阵列执行以下任务: [1 0 0] M = [0 0 1] [0 -1 0] M * [0, 1,

我希望在传入向量(V)时创建一个旋转矩阵(M),其中
M*[0,0,1](向前)=V

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


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

即使是用手,也很简单,很简单。仅通过检查,可以看出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   ]

三维旋转很难思考,甚至在文本中更难解释。然而,你可以把左手变成一组近似的三维轴。看看下面描述弗莱明左手法则的维基百科页面;特别是,请看第二张图,图中的手指标记为I、B和F:

用你自己的手做同样的形状,而不是标记手指I、B和F,让我们称它们为x、y和z。此外,我们会说,这三个手指在手掌处相交的点是原点,即点(0),从原点向其中一个手指/拇指的尖端移动是正向移动的

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

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

下面的Wikipedia页面为您提供了以下公式。绕x轴旋转的矩阵为:

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

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

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

因此,您将获得一个局部z-轴
V=(vx,vy,vz)
和一个朝向
U=(ux,uy,uz)的局部x-轴,其中
U
V
单位向量:

局部y轴是
W=标准化(交叉(V,U))
。现在,如果
U
V
不完全垂直,则需要使用
U=归一化(交叉(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)
创建了一个单位向量。

我还必须解决同样的问题。尽管如此,还是有人需要这个我在这里找到了一个合适的方法

下面是如何用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;
Eigen::vector3fa(34,0,1);
本征::向量3B(2,2,1);
a=a/a.标准();
浮动b_范数=b.范数();
b=b/b_标准;
本征::向量3f v=a.交叉(b);
浮点数s=v.norm();
浮点数c=a.dot(b);
本征::矩阵x3f vx;

vx可能值得指出的是,虽然有无穷多个变换矩阵映射(0 1 0)到(0 0-1),但并非所有变换矩阵都是旋转矩阵。此外,在旋转矩阵中,执行的旋转必须是围绕y轴和z轴的自然整圈数,以及围绕x轴的自然整圈数加上四分之一圈(在适当方向)的总和绕x轴旋转。相关问题:旋转矩阵的列对应于局部x、y、z轴的组件。
    | Ux  Wx  Vx |
M = | Uy  Wy  Vy |
    | Uz  Wz  Vz |
  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;