从两个3D向量定义的旋转中计算3x3旋转矩阵的有效方法 [英] Efficient way to calculate a 3x3 rotation matrix from the rotation defined by two 3D Vectors

查看:817
本文介绍了从两个3D向量定义的旋转中计算3x3旋转矩阵的有效方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然我找到了两种解决方案,但我很好奇是否有众所周知的方法来执行此操作,因为这似乎是一项很常见的任务.

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_sinangle_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.

我们知道v1v2是单位向量; v1 · v2 = |v1| |v2| cos θ因为|v1| = |v2| = 1v1 · v2直接给我们cos θ,所以找到1 - cos θ并不昂贵. v1 × v2 = |v1| |v2| sin θ n = sin θ n,其中n是垂直于v1v2的单位矢量,找到|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.

AB是两个矩阵,因为您要从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屋!

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