四元数和标准化

Seb*_*ski 20 normalization quaternions

我知道如果我想旋转矢量,则需要对四元数进行归一化.

但有没有任何理由不自动规范化四元数?如果有,那么四元数运算会导致非标准化四元数?

  • 乘以两个四元数?
  • 点产品?

对不起,如果这个问题有点模糊.我还在尝试绕着四元数缠绕我.

Dav*_*men 33

迟到的反应; 这个答案适用于将来遇到这个问题的人,而不是提问者.

我不同意有关仅偶尔标准化四元数的其他两个答案.使用四元数来旋转/变换矢量或生成旋转/变换矩阵的标准公式隐含地假设四元数是标准化的.使用非标准化四元数产生的误差与四元数的平方成正比.最好避免二次误差增长.

如果经常标准化,则不需要平方根.一阶近似非常有效.这是我用于四元数的IEEE加倍,有点风格化:

double qmagsq = quat.square_magnitude();
if (std::abs(1.0 - qmagsq) < 2.107342e-08) {
    quat.scale (2.0 / (1.0 + qmagsq));
}
else {
    quat.scale (1.0 / std::sqrt(qmagsq));
}
Run Code Online (Sandbox Code Playgroud)

请注意,我使用的是第一阶Padé逼近2.0/(1.0+qmagsq)而不是第一阶泰勒展开0.5*(3.0-qmagsq)来估算1.0/std::sqrt(qmagsq).该近似值如果有效,则通过简单除法替换平方根调用.关键是要找出何时有效,这就是幻数2.107342e-08发挥作用的地方.

为什么Padé接近?两个原因.一个是,对于qmagsq接近一个的值,1+qmagsq失去的精度要低于一个3-qmagsq.另一个是,与泰勒展开相比,Padé近似将误差减少了三倍.对于qmagsq介于0和2之间的值,此近似值中的误差小于(1-qmagsq)^2 / 8.幻数2.107342e-08表示此错误超过IEEE的ULP的一半.如果采取合理的小步骤,四元数量值的平方将始终在该限制范围内.你永远不会打电话sqrt.

这种"常规规范化"范例的一个例外可能是,如果您使用李群集成技术来传播四元数.如果您不知道这意味着什么,那么您可能正在使用相当于q(t+?t) = q(t) + dq(t)/dt*?t传播四元数的方法.即使您使用的是不是Lie组积分器的高阶积分技术,您仍然在某处使用Euler步骤.

  • 归一化是将四元数拖回单位3球的一种方法.四元数偏离流形的原因是因为欧拉步在某种意义上是无效的数学:单位四元数是一个群,而不是代数.不使用单位四元数也无效; 现在你没有图表(3).做得对(例如,李群集成技术)和四元数将几乎停留在多方面.您可能仍需要偶尔进行标准化. (3认同)
  • @chtz-关于x = 1的“ 1 / sqrt(x)”的一阶泰勒逼近是“(3-x)/ 2”,并且在误差方面比“ 2 /(1+ x)表示x接近1。有时Padé近似值非常神奇。这是魔术效果很好的情况之一。 (2认同)
  • 您知道 IEEE 单精度 (`float`) 浮点数的幻数吗? (2认同)

小智 9

产生四元数的任何操作都需要进行标准化,因为浮点进动错误将导致它不是单位长度.

我建议不要出于性能原因自动执行标准化的标准例程.任何有能力的程序员都应该了解精度问题并且能够在必要时对数量进行标准化 - 并且并不总是需要具有单位长度的四元数.

矢量运算也是如此.

  • 这只是过早优化:即使无关紧要,也要让开发人员进行额外的容易出错的工作. (2认同)

vpo*_*yev 5

有趣的是,构建旋转矩阵是一种不需要标准化四元数的操作,可以节省一个sqrt:

M = [w*w+x*x-y*y-z*z, 2*(-w*z+x*y),    2*(w*y+x*z);
     2*(w*z+x*y),     w*w-x*x+y*y-z*z, 2*(-w*x+y*z);
     2*(-w*y+x*z),    2*(w*x+y*z),     w*w-x*x-y*y+z*z] / (w*w+x*x+y*y+z*z)
Run Code Online (Sandbox Code Playgroud)

(用MATLAB-ish表示法)表示四元数w+x*i+y*j+z*k.

此外,如果您使用齐次坐标和4x4变换矩阵,您还可以保存一些除法运算:只需制作一个3x3旋转部分,就好像四元数被标准化一样,然后将其平方长度放入(4,4) - 元素中:

M = [w*w+x*x-y*y-z*z, 2*(-w*z+x*y),    2*(w*y+x*z),     0;
     2*(w*z+x*y),     w*w-x*x+y*y-z*z, 2*(-w*x+y*z),    0;
     2*(-w*y+x*z),    2*(w*x+y*z),     w*w-x*x-y*y+z*z, 0;
     0,               0,               0,               w*w+x*x+y*y+z*z].
Run Code Online (Sandbox Code Playgroud)

乘以翻译矩阵等,像往常一样进行完整的转换.这样你可以这样做,例如,

[xh yh zh wh]' = ... * OtherM * M * [xold yold zold 1]';
[xnew ynew znew] = [xh yh zh] / wh.
Run Code Online (Sandbox Code Playgroud)

当然,仍然建议至少偶尔标准化四元数(其他操作也可能需要).

  • @DavidHammen:(1)你好像假设转换矩阵必须是正交的.即使在你的工作中确实如此,这也不是一般要求.你理解"齐次坐标"是什么意思,对吗?(2)涉及除以'w*w + x*x + y*y + z*z'的无Sqrt计算正是我在第一个语句(在答案中)的意思.4x4矩阵本身是一个无分区修复. (4认同)