我有一个简单的四元数实现对象旋转。如果我创建两个四元数来表示关于相同轴对齐矢量(即沿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
答案 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
x
和z
的等式中有一个带有减号的错误项 - 如果两个轴相同则不会产生差异,因为一个也可以写(作为一个速记)
(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所产生的方向不同的方向。