在四元数标准化期间维持旋转

时间:2013-09-10 04:05:58

标签: quaternions

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

规范化四元数的方法如下:

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值的方法并仅调整其他点以达到规范化是不是更有意义?

2 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:0)

抱歉,我知道这有点坏,但是我认为这可能对将来的读者有用。

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

让我们假设您有两个四元数(从现在开始,我将它们称为Q1Q2),它们代表旋转,但由于舍入误差而不是单位,并且您想将它们相乘(我将结果称为Q3。我们也希望将其作为单位四元数)。假设t1是一个变量,当与Q1的每个分量相乘时,Q1变成一个单位四元数(这意味着t1被一个除以欧氏长度Q1,但在这里确实不相关。t2Q2做同样的事情。如果现在将规范化后的四元数相乘(即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变量现在仅与非实数部分(aka 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进行了规范化,那么请在操作前进行操作。

对四元数进行归一化并不是一项便宜的操作,因此最好将非角度保留方式用于游戏之类的东西,因为您不需要那么频繁地使用它,尤其是在合成大量旋转时。我不确定其他四元数运算是否也能保持同样的效果,但是考虑到您可能会大量增加四元数,至少在我看来,使用非保留角度的方法更为可取。