从两个3D向量定义的旋转中计算3x3旋转矩阵的有效方法 [英] Efficient way to calculate a 3x3 rotation matrix from the rotation defined by two 3D Vectors
问题描述
虽然我找到了两种解决方案,但我很好奇是否有众所周知的方法来执行此操作,因为这似乎是一项很常见的任务.
While I've found 2 solutions to this, I was curious if there is well known method to perform this operation since it seems a fairly common task.
以下是伪代码的两种显而易见的方法...
Here are the 2 obvious methods psudo-code...
这是很合逻辑的,但是调用sin
两次,并且cos
一次(在角度计算和轴角度到矩阵的转换中).
This is quite logical, but calls sin
twice and cos
once (in the angle calculation and axis angle to matrix conversion).
Matrix3x3 rotation_between_vectors_to_matrix(const Vector v1, const Vector v2)
{
angle = v1.angle(v2);
axis = v1.cross(v2);
/* maths for this is well known */
Matrix3x3 matrix = axis_angle_to_matrix(axis, angle);
return matrix;
}
编辑:最直接的功能相当慢,但是正如此处答复中所指出的那样:可以通过从以下位置获取angle_sin
和angle_cos
来避免计算角度.轴长和v1,v2
点积.
Edit: The most straightforward function is a quite slow, however as has been pointed out in the replies here: calculating the angle can be avoided by getting angle_sin
and angle_cos
, from the axis length and v1,v2
dot product respectively.
这是我发现的另一种方法,该方法从向量构造两个3x3矩阵并返回差值.
Here's another method I found which constructs two 3x3 matrices from the vectors and returns the difference.
但是,这比可以优化的轴/角度计算要慢(如上所述).
However this is slower then axis/angle calculation which can be optimized (mentioned above).
注意.假设两个向量都已归一化,矩阵是主要列(OpenGL).
Matrix3x3 rotation_between_vectors_to_matrix(const Vector v1, const Vector v2)
{
Matrix3x3 m1, m2;
axis = v1.cross(v2);
axis.normalize();
/* construct 2 matrices */
m1[0] = v1;
m2[0] = v2;
m1[1] = axis;
m2[1] = axis;
m1[2] = m1[1].cross(m1[0]);
m2[2] = m2[1].cross(m2[0]);
/* calculate the difference between m1 and m2 */
m1.transpose();
Matrix3x3 matrix = m2 * m1;
return matrix;
}
是否有更好的方法来执行此计算?
Are there better ways to perform this calculation?
编辑:该问题的目的不是对每种方法进行微优化和基准测试.相反-我很好奇是否有一些我不知道的完全不同和更好的方法.
The purpose of this question is NOT to micro-optimize and benchmark each method. Instead - I was curious if there is some totally different and superior method which I didn't know about.
注意:为了简化示例,我特意省去了检查共线性矢量(轴为零长度)的简并情况的问题.
Note: I purposefully left out checks for the degenerate case for co-linear vectors (where the axis is zero length), to keep the examples simple.
推荐答案
可以同时优化您发布的两种方法.
Both the methods you've posted can be optimised.
与其使用acos
查找两个矢量之间的角度,还不如完全避免查找角度.如何? Rodrigues的轴角公式仅需要sin θ
,cos θ
和
Instead of using acos
to find the angle between the two vectors, a better thing to do is to avoid finding the angle at all. How? The axis-angle formula by Rodrigues requires only sin θ
, cos θ
and 1 - cos θ
, so finding the actual angle is redundant.
我们知道v1
和v2
是单位向量; v1 · v2 = |v1| |v2| cos θ
因为|v1| = |v2| = 1
,v1 · v2
直接给我们cos θ
,所以找到1 - cos θ
并不昂贵. v1 × v2 = |v1| |v2| sin θ n = sin θ n
,其中n
是垂直于v1
和v2
的单位矢量,找到|v1 × v2|
叉积的大小将直接给出sin θ
.
We know that v1
and v2
are unit vectors; v1 · v2 = |v1| |v2| cos θ
since |v1| = |v2| = 1
, v1 · v2
directly gives us cos θ
, finding 1 - cos θ
isn't costly. v1 × v2 = |v1| |v2| sin θ n = sin θ n
, where n
is a unit vector perpendicular to v1
and v2
, finding |v1 × v2|
the magnitude of the cross product would directly give sin θ
.
现在我们有了sin θ
和cos θ
,我们可以使用Rodrigues forumla直接形成旋转矩阵; 这是一个简单的实现.
Now that we've sin θ
and cos θ
, we can directly form the rotation matrix by using Rodrigues forumla; here's a simple implementation.
在将两个正交框架构造为矩阵之后,可以避免进行第二次转置.这是证据.
After you've constructed two orthonormal frames as matrices, you can avoid the second transpose you do. Here's the proof.
说A
和B
是两个矩阵,因为您要从A
旋转到B
,我们需要一些矩阵X
,将其与A
相乘将得到B
:
Say A
and B
be the two matrices, since you want to rotate from A
to B
we need some matrix X
which when multiplied with A
will give B
:
XA = B
XA = B
X =BA⁻¹
这就是您所需要的;当您将X
预乘到A
时,您将得到B
.但是,您找到的是Y
This is all you need; when you pre-multiply X
to A
you'd get B
. However, what you find is Y
Y =AB⁻¹
Y = AB⁻¹
YB = A
然后您转置Y
以获得Y⁻¹
,即
Y⁻¹YB=Y⁻¹A
Y⁻¹YB = Y⁻¹A
B =Y⁻¹A
您可以执行上述仅涉及一个转置的方法,而不是进行两个逆操作(在此进行转置).
Instead of doing two inverses (transpose here), you can just do the above method which involves only one transpose.
我仍然要说,如果没有以优化形式对方法进行基准测试,我们不能说方法2比方法1更快.因此,我真的敦促您在这两种方法之间进行基准测试(带有一些非平凡的负载)然后得出一个结论.
I'd still say that without benchmarking the methods in their optimized forms, we cannot say method 2 is faster than method 1. So I'd really urge you to benchmark between the two methods (with some non-trivial load) and then draw a conclusion.
这篇关于从两个3D向量定义的旋转中计算3x3旋转矩阵的有效方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!