四元数的计算机表示;s精确到90度旋转



单位四元数比3x3正交矩阵有几个优点用于在计算机上表示三维旋转。

然而,有一件事让我对单位四元数感到失望表示为轴对齐90度旋转并不完全可代表。例如,以+x轴为+y轴,绕z轴旋转90度,表示为[w=sqrt(1/2), x=0, y=0, z=sqrt(1/2)]。意外/不愉快的后果包括:

  • 将浮点四元数表示的轴对齐90度旋转应用于向量v通常不会将v精确旋转90度
  • 四次将浮点四元数表示的轴对齐90度旋转应用于向量v通常不会产生精确的v
  • 对表示绕坐标轴旋转90度的浮点四元数进行平方不能精确地产生(可精确表示的)180度旋转围绕该坐标轴,将其提高到八次方不会产生单位四元数

由于"0"上四元数表示的这种不幸损失;漂亮的";旋转,我有时仍然会选择3x3矩阵用于我希望轴对齐的应用程序90度旋转及其组成,精确无浮点舍入误差。但是矩阵表示也不理想,因为它失去了有时需要的双重覆盖属性(即四元数在单位和360度旋转之间进行区分,但是3x3旋转矩阵没有)以及其他熟悉的期望的数值性质例如不需要重新正交化。

我的问题是:有没有一种单位四元数的计算机表示不受此影响不精确,并且也不失去双重覆盖特性?

我能想到的一个解决方案是表示四元数的4个元素中的每一个作为一对机器可表示的浮点数[a,b],意思是a+b√2。因此,四元数的表示将由八个浮点数组成。我认为这是可行的,但它似乎相当重量级;例如当计算长四元数序列的乘积时,简单四元数计算中的每一次乘法都会变成4次浮点乘法和2次浮点加法,并且每个加法将变成2个浮点加法。从试图编写通用库实现的角度来看,只要存在而不是的因素,那么所有额外的计算和存储似乎都毫无意义;漂亮的";旋转。

另一种可能的解决方案是表示每个四元数q=w+neneneba xi+yj+zk作为4元组[符号(w)*w2,符号(x)*x2,信号(y)*y2、符号(z)*z2<2]。这个表示是简洁的,并且对于感兴趣,但我不知道如何在这个表示中将两个四元数相乘。

另一种可能的方法是存储四元数q2,而不是通常的q,但是,再说一遍,我不知道如何不损失地相乘这两个表示在计算机上放在一起,而且双重保护性质显然已经丧失。

您可能想要检查纸张"浮点运算中操纵四元数的算法";2020年发布,可在线获取:

https://hal.archives-ouvertes.fr/hal-02470766/file/quaternions.pdf

它展示了如何进行精确的计算并避免无限的数值误差。

编辑:

您可以通过使用未规范化(即非单位)四元数来消除平方根。让我来解释一下这个想法。

具有两个单位三维矢量X和Y,表示为纯四元数,将X旋转到Y的四元数Q是

Q=X*(X+Y)/|X*(X+Y)|

分母取范数是个问题,因为它涉及一个平方根。

您可以将表达式扩展为:

Q=(1+X*Y)/sqrt(2+2*(X•Y))

如果我们将X=i和Y=j替换为90度旋转,则会得到

Q=(1+k)/sqrt(2)

因此,|1+k|=sqrt(2)。但我们实际上可以使用未归一化的四元数Q=1+k来执行旋转,我们所需要做的就是通过四元数的平方范数。

例如,Q=1+k的平方范数为|1+k | ^2=2(这正是因为你从未取过平方根),让我们将未归一化的四元数应用于向量X=i:

=(1+k)i(1-k)

=(i+k*i-i*k-k*i*k)

=(i+2 j-i)

=2 j

为了得到正确的结果,我们除以平方范数。

我还没有测试过,但我相信通过将未归一化的四元数应用于向量,然后将结果除以平方范数,你会得到确切的结果。

算法将是

  1. 创建未规范化的四元数Q=X*(X+Y)

  2. 将Q应用于向量为:v'=Q*v*~Q

  3. 通过平方范数归一化:v''=v'/|Q|^2

最新更新