四元数连接仅在轴对齐时才起作用

时间:2012-12-20 23:41:16

标签: java android math 3d quaternions

我有一个简单的四元数实现对象旋转。如果我创建两个四元数来表示关于相同轴对齐矢量(即沿X,Y或Z轴)的旋转,则结果与单个旋转相同,即它们的幅度之和(即按PI / 2旋转然后PI / 2再次与PI旋转相同)。那很好。

一旦旋转轴不是轴对齐的,那么连接就会偏离预期(由PI / 2旋转,然后PI / 2再次与PI旋转相同) 。那不好。

在仔细阅读我的代码几天后,我没有看到任何错误,所以现在让我问:我是否在某种程度上从根本上误解了四元数的工作原理?我在推理它们所代表的轴角旋转方面的四元数,因为坦率地说我并不完全理解四元数。

如果没有,你能查看我的代码吗? :-)我把整个事情(用Java编写 - 我的目标Android)推送到GitHub: https://github.com/wtracy/quaternions 在Quaternions目录下是一个Eclipse项目。 (您不应该需要Eclipse来阅读任何内容,但这很方便。)四元数类位于src /文件夹下。在test /文件夹中有JUnit测试和运行我的Quaternion类所需的类的存根。

我已尽力使我的代码和测试易于理解。我觉得愚蠢的要求互联网在我的代码中找到一个错误,但我的想法很简洁。 :-P

2 个答案:

答案 0 :(得分:3)

四元数乘法中有符号错误。

public Quaternion times(Quaternion q2) {
    Quaternion q1 = this;
    float w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z;
    float x = q1.x*q2.w + q1.w*q2.x + q1.z*q2.y - q1.y*q2.z;
    float y = q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x;
    float z = q1.w*q2.z - q2.x*q2.y + q1.y*q2.x + q1.z*q2.w;
    return new Quaternion(w, x, y, z);
}

写出的产品是

(w1 + x1*i + y1*j + z1*k)*(w2 + x2*i + y2*j + z2*k)
= w1*w2 - x1*x2 - y1*y2 - z1*z2
+ (w1*x2 + x1*w2 + y1*z2 - z1*y2)*i
+ (w1*y2 - x1*z2 + y1*w2 + z1*x2)*j
+ (w1*z2 + x1*y2 - y1*x2 + z1*w2)*k

因为

i*j = k    j*i = -k
j*k = i    k*j = -i
k*i = j    i*k = -j

xz的等式中有一个带有减号的错误项 - 如果两个轴相同则不会产生差异,因为一个也可以写(作为一个速记)

(r + v)*(s + w) = r*s - <v|w> + r*w + s*v + v×w

v×w = 0用于共线矢量,但如果轴不同则会显示。

此外,在z的等式中,

float z = q1.w*q2.z - q2.x*q2.y + q1.y*q2.x + q1.z*q2.w;
                          ^^^^^^^^^

你有一个错字,一次使用q2这两个因素。

应该是

public Quaternion times(Quaternion q2) {
    Quaternion q1 = this;
    float w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z;
    float x = q1.x*q2.w + q1.w*q2.x - q1.z*q2.y + q1.y*q2.z;
    float y = q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x;
    float z = q1.w*q2.z + q1.x*q2.y - q1.y*q2.x + q1.z*q2.w;
    return new Quaternion(w, x, y, z);
}

答案 1 :(得分:0)

  

一旦旋转轴不是轴对齐的,那么连接就会偏离预期(由PI / 2旋转,然后PI / 2再次与PI旋转相同)。那不好。

即使你得到正确的数学,你仍然会发现情况并非如此。一般而言,三维空间中的旋转不是可交换的。如果执行旋转A然后旋转B,通常会得到与第一次执行旋转B然后旋转A所产生的方向不同的方向。