Math 四元数与数值稳定性

Math 四元数与数值稳定性,math,rotation,quaternions,rotational-matrices,numerical-stability,Math,Rotation,Quaternions,Rotational Matrices,Numerical Stability,我正在学习单位四元数以及如何使用它们来表示和合成旋转。维基百科说它们比矩阵表示法在数值上更稳定,但没有给出参考。有人能向我解释一下(最好是通过一些数学推理)为什么使用单位四元数来处理旋转(例如,对于OpenGL应用程序)比使用旋转矩阵在数值上更稳定?这仅仅是因为避免了万向节锁吗?不确定这是否符合您的口味,但我还是要试一试:旋转矩阵的问题在于它包含冗余信息。您有9个值,用于编码仅具有3个自由度的变换 由于这种冗余,矩阵中的9个值存在约束,以形成有效的旋转矩阵。矩阵必须是正交的,这意味着行向量必须是

我正在学习单位四元数以及如何使用它们来表示和合成旋转。维基百科说它们比矩阵表示法在数值上更稳定,但没有给出参考。有人能向我解释一下(最好是通过一些数学推理)为什么使用单位四元数来处理旋转(例如,对于OpenGL应用程序)比使用旋转矩阵在数值上更稳定?这仅仅是因为避免了万向节锁吗?

不确定这是否符合您的口味,但我还是要试一试:旋转矩阵的问题在于它包含冗余信息。您有9个值,用于编码仅具有3个自由度的变换

由于这种冗余,矩阵中的9个值存在约束,以形成有效的旋转矩阵。矩阵必须是正交的,这意味着行向量必须是正交的(每个向量的长度为1,每对向量的标量积为0)

在更新旋转矩阵时,通常通过将其与增量旋转矩阵连接,会引入数值错误。这些错误随着每次更新而累积。除非您对此做些什么,否则行向量将越来越远离正交。一旦矩阵距离正交足够远,它就可以开始明显地使其应用到的几何体变形(倾斜、缩放等)


使用旋转矩阵时,可以通过定期对行向量进行正交规格化来避免这些问题。这只需要一些简单的向量运算,所以没什么大不了的。

维基百科的文章有偏见。

截至2014年4月18日:

在计算机上进行多次旋转时,舍入误差 必然积累。一个四元数,有点偏了 表示归一化后的旋转:一个稍微 “关闭”可能不再是正交的,并且很难转换回“关闭” 真正交矩阵

这是有偏见的。重新正交旋转矩阵没有什么困难,例如,请参见:

四元数也必须重新标准化:“一个稍微有点偏离的四元数 表示归一化后的旋转”。四元数在这里没有明显的优势

我将尝试在维基百科上解决这个问题。这种有偏见的观点也出现在维基百科的其他地方(

这回答了您的问题。


更新:我忘了提到:万向节锁在这里不起作用;四元数和旋转矩阵都不受此影响


一些旁注。尽管四元数比旋转矩阵更紧凑,但使用四元数将减少整个应用程序中的数值计算,这一点并不明确,请参见:

仅供记录:旋转矩阵已在资源受限的微控制器上成功地用于跟踪方向,见William Premerlani和Paul Bizard。我还拥有在微控制器(MSP430)上跟踪方向的第一手经验我只能说旋转矩阵对于跟踪方向是快速稳定的

我的观点是:当用于跟踪方向时,旋转矩阵和四元数之间没有显著差异。

如果您已经有一个使用四元数表示旋转的库,那么请坚持使用四元数;如果您的库已经使用旋转矩阵,那么请使用旋转矩阵。即使一个表示可以为您节省一些浮点操作,也没有必要将您的应用程序/库更改为使用另一个表示即使在资源有限的微控制器上,节省也微不足道

我所看到的四元数的唯一真正优点是,四元数可以用于插值。无论是旋转矩阵还是欧拉角都不能做到这一点

“万向节锁”是一个骗人的把戏——矩阵和单位四元数都不是天生受万向节锁约束的

矩阵在保持旋转序列的数值稳定性方面实际上比四元数有一点优势,因为生成矩阵乘积中的每个元素所需的FP操作较少。四元数在易于纠正数值漂移方面有一点优势(要真正做好矩阵的计算,需要进行SVD)


不过,老实说,这不太可能对你的应用产生重大影响,而且数值稳定性背后的理论也变得相当复杂。如果你真的对这一领域感兴趣,我可以推荐Higham的数值算法的准确性和稳定性。

使用单位四元数可能比矩阵更不稳定

一,。 如果你转换单位四元数并假设它是单位(而不是按平方大小加权系数),你会得到显著的误差。如果你从断开的矩阵转换回四元数,反之亦然,你会很快达到不稳定的旋转

  • 四元数的顺序相乘,将它们漂移到非均匀长度。和前面一样,可能会产生断开的矩阵
  • 为了避免这种错误,您应该在每次产生舍入错误的操作之后对四元数进行规范化。或者假设您的四元数是非连续的,并通过加权(大约额外的8flops)转换为矩阵


    注:许多操作的执行速度比使用单位更快,例如从矩阵转换。我有一个应用程序,其中有一个“car”跟随样条线。我计算样条线的导数以定义正向向量,然后计算左向量和上向量以创建方向矩阵。然后我将其分解为四元数

    当我将这些四元数转换为an中的关键帧时