4

我一直在为即将到来的项目研究四元数,并且遇到了一个我无法解决的概念问题。

归一化四元数的方法如下:

q_mag = sqrt(q0^2+q1^2+q2^2+q3^2)
q0 = q0/q_mag  
q1 = q1/q_mag   
q2 = q2/q_mag  
q3 = q3/q_mag

直截了当,就像规范化任何其他向量一样。但我的问题是这种归一化方法如何保留相同的旋转信息。使用表示轴角表示的四元数的定义,如下所示,

angle = 2 * acos(q0)
x = qx / sqrt(1-q0*q0)
y = qy / sqrt(1-q0*q0)
z = qz / sqrt(1-q0*q0)

由于标准化操作对 x、y、z 值进行了同等缩放,因此您旋转的轴永远不会改变。但是角度本身的值会随着归一化操作而发生剧烈变化。

那么使用保留 q0 的值并仅调整其他点以达到归一化的方法不是更有意义吗?

4

2 回答 2

5

数学答案:单位四元数表示 3D 空间中的旋转。任何其他(即:非单位)四元数不代表旋转,因此公式 angle = 2 * acos(q0) 不适用于这些四元数。因此,归一化时角度没有变化,因为您将归一化的四元数一开始并不代表旋转。

编程答案:浮点运算存在精度问题。这些问题会导致小错误,如果累积起来可能会变成大错误。当两个单位四元数相乘时,数学结果是另一个单位四元数。然而,单位四元数乘法的浮点实现可能会导致四元数的范数接近 1 但不等于 1。在这种情况下,我们将对四元数进行归一化以纠正错误。当我们归一化时,我们将 q0 除以非常接近 1 的范数,因此 q0 的值没有重大变化。因为我们提前标准化,所以范数总是非常接近 1,我们不需要担心精度。

迟到的答案,但我希望它有所帮助。

于 2014-01-17T19:13:49.533 回答
0

我知道这有点像死神,抱歉,但我认为这可能对未来的读者有用。

除非我完全弄错了,否则实际上最好不要在归一化时保留角度以考虑舍入误差(在使用四元数表示旋转的情况下,尤其是在游戏中)。让我解释一下原因:

假设您有两个四元数(我将它们称为从这里开始) Q1Q2它们应该代表旋转,但由于舍入误差而不是单位,并且您想将它们相乘(我将调用结果Q3. 我们也希望这是一个单位四元数)。假设t1是一个变量,当与 的每个分量相乘时Q1,它Q1变成一个单位四元数(这意味着t1一个除以 的欧几里得长度Q1,但这在这里真的不相关。t2对 做同样的事情Q2。如果我们现在将四元数后归一化(即Q3 = (t1*Q1)(t2*Q2))我们得到以下内容:

Q3.w = t1*Q1.w*t2*Q2.w - t1*Q1.x*t2*Q2.x - t1*Q1.y*t2*Q2.y - t1*Q1.z*t2*Q2.z
Q3.x = t1*Q1.w*t2*Q2.x + t1*Q1.x*t2*Q2.w + t1*Q1.y*t2*Q2.z - t1*Q1.z*t2*Q2.y
Q3.y = t1*Q1.w*t2*Q2.y - t1*Q1.x*t2*Q2.z + t1*Q1.y*t2*Q2.w + t1*Q1.z*t2*Q2.x
Q3.z = t1*Q1.w*t2*Q2.z + t1*Q1.x*t2*Q2.y - t1*Q1.y*t2*Q2.x + t1*Q1.z*t2*Q2.w

可以重写为

Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)

换句话说,Q3=(t1*Q1)(t2*Q2)=(t1*t2)(Q1*Q2)。如您所见,在乘法之后以这种方式归一化会产生与对两个输入预乘法进行归一化相同的四元数。这意味着我们只需在将旋转应用于向量/网格/点之前进行归一化,而不是在每次计算之后,因为无论四元数偏离单位多远,它都会产生相同的结果。

现在让我们看一下相同的计算,但是使用保留角度的方式来制作四元数单元(t变量现在仅与非实数(又名 xyz)部分相乘时构成四元数单元):

Q3.w = Q1.w*Q2.w - t1*Q1.x*t2*Q2.x - t1*Q1.y*t2*Q2.y - t1*Q1.z*t2*Q2.z
Q3.x = Q1.w*Q2.x + t1*Q1.x*Q2.w + t1*Q1.y*t2*Q2.z - t1*Q1.z*t2*Q2.y
Q3.y = Q1.w*Q2.y - t1*Q1.x*t2*Q2.z + t1*Q1.y*Q2.w + t1*Q1.z*t2*Q2.x
Q3.z = Q1.w*Q2.z + t1*Q1.x*t2*Q2.y - t1*Q1.y*t2*Q2.x + t1*Q1.z*Q2.w

注意 的非实部如何Q3不再具有共同因子这意味着Q3以这种方式规范化后期操作可能会导致与您在规范化Q2Q1以这种方式预操作时得到的四元数不同。

归一化四元数并不是一个便宜的操作,因此最好将非角度保留方式用于游戏等内容,因为您需要较少使用它,尤其是在合成大量旋转时。我不确定其他四元数运算是否同样适用,但考虑到您可能会大量乘以四元数,至少在我看来,最好使用非角度保持方式。

于 2019-05-09T12:35:30.020 回答