当我传入一个向量 (V) where 时,我希望创建一个旋转矩阵 (M) M * [0, 0, 1] (forward) = V
。
我这样做是因为我想使用这个矩阵来乘以其他向量以将它们放在本地空间中(不确定这是否是正确的术语,但希望你能理解)。
V = [0, 1, 0]
M = ?
Result = M * V = [0, 0, -1]
那么如果在乘以M之后[0,0,1]
向上倾斜了90度就变成了……什么是?[0,1,0]
M
三维旋转很难思考,甚至更难用文字解释。但是,可以将您的左手形成近似于一组三维轴的东西。查看以下描述弗莱明左手规则的维基百科页面;特别是,看第二张图,它的手指标记为I、B和F:http ://en.wikipedia.org/wiki/Fleming's_left-hand_rule_for_motors
用你自己的手做同样的排列,而不是标记手指I、B和F,让我们称它们为x、y和z。此外,我们会说这三个手指在手掌处相交的点是原点,点 (0 0 0),并且从原点向这些手指/拇指之一的尖端移动是在移动积极的方向。
向量v = (0 1 0) 是食指上的一个点(我们称之为y)。我们想旋转这个点以形成点 (0 0 -1)。该点位于z轴(拇指)上,但它是负数,因此它位于原点“下方”一个单位,方向是从拇指尖到原点。
因此,要将点 (0 1 0) 旋转为 (0 0 -1),我们需要围绕x轴(您的中指)旋转它。想象一下,将一张 CD 光盘放在您的中指上,推动它,使其位于您的食指和拇指定义的平面上 - ( x , y ) 平面 - 并在距离其中心一个单位的光盘上放置一个标记。现在想象将该标记与食指对齐,使该标记位于点 (0 1 0)。您可以围绕中指旋转圆盘,使标记位于点 (0 0 -1)。因此,所需的旋转是围绕x轴的旋转。
以下 Wikipedia 页面为您提供了在三维空间中围绕x、y和z轴的旋转方程。绕x轴旋转的矩阵为:
/1 0 0 \
|0 cos θ -sin θ|
\0 sin θ cos θ/
如果您要使用右手旋转圆盘,则定义矩阵以使 θ 的负值对应于右手的顺时针运动(反之亦然,正值)。我们需要旋转的角度是负四分之一圈,因此所需的矩阵是:
/1 0 0\
|0 0 1|
\0 -1 0/
请记住,角度可以用度数或弧度表示,因此如果您在代码中实现更通用的旋转,您需要检查您的数学库所期望的。
因此,您将获得一个局部z轴V=(vx,vy,vz)
和一个朝向的局部xU=(ux,uy,uz)
轴,其中U
和V
是单位向量:
局部y轴为W=Normalized(Cross(V,U))
。现在如果U
不完全垂直于V
它需要用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)
创建一个单位向量。
即使是手工,简单,轻松。仅通过检查,可以看出 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 ]
我也必须解决同样的问题。尽管如此,还是有人需要这个,我在这里找到了一种正确的方法[ 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 则失败