我知道,如果我想旋转一个向量,那么四元数就需要标准化。
但是,有什么理由不自动使四元数正常化呢?如果有,什么四元数运算会导致非规范化的四元数?
对不起,如果这个问题有点模糊。我还在试着把头绕着四元数。
发布于 2012-07-26 11:09:27
任何产生四元数的运算都需要标准化,因为浮点进动误差会导致它不是单位长度。
出于性能原因,我建议不要使用标准例程自动执行规范化。任何有能力的程序员都应该意识到精度问题,并且能够在必要的时候将数量正常化--而且并不总是需要有一个单位长度的四元数。
向量运算也是如此。
发布于 2012-10-17 12:52:07
这个答案是给将来遇到这个问题的人的,而不是给提问者的。
我不同意另外两个答案,只是偶尔将四元数正常化。使用四元数旋转/变换矢量或生成旋转/变换矩阵的标准公式隐式地假定四元数是标准化的。使用未归一化的四元数所产生的误差与四元数大小的平方成正比。二次错误增长是最好的避免。
如果你经常正常化,你不需要平方根。一阶近似很好地工作。以下是我在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));
}
注意,我使用的是一阶Padé近似2.0/(1.0+qmagsq)
,而不是一阶Taylor展开0.5*(3.0-qmagsq)
来估计1.0/std::sqrt(qmagsq)
。这种近似,如果有效,则用简单的除法替换平方根调用。关键是要找出当这个近似是有效的,这就是那个神奇的数字2.107342e-08发挥作用的地方。
为什么是Padé近似?有两个原因。其一,对于接近1的qmagsq
值,1+qmagsq
损失的精度低于3-qmagsq
。另一种是Padé近似将误差与Taylor展开相比减少了3倍。对于0到2之间的qmagsq
值,此近似下的误差小于(1-qmagsq)^2 / 8
。神奇的数字2.107342e-08代表这个错误超过一半的ULP为IEEE双倍。如果你正在采取合理的小步骤,四元数大小的平方将始终在这个限制之内。你永远不会给sqrt
打电话。
如果您使用Lie组集成技术来传播四元数,那么这个“正常化始终”范式的一个例外可能是。如果您不知道这意味着什么,您可能会使用等效的q(t+Δt) = q(t) + dq(t)/dt*Δt
来传播一个四元数。您仍然在使用Euler步骤,即使您使用的是一种高阶集成技术,而不是Lie组积分器。
发布于 2013-03-10 16:59:41
如果一个单位四元数是通过对其一次导数进行数值积分得到的,则积分器可以利用一个简单的误差反馈将其自动归一化。
设q表示四元数的4×1列矩阵,dq表示它的时间导数。然后将dq+0.5(1-q.q)q/τ发送给积分器代替dq,并使用适当的时间常数τ将q.q连续规范化,q.q表示内积。
我模拟了一个保守的,清晰的Bricard机制,在无重力空间中漂浮了360万秒,几乎是42天。四元数代表浮基体的方向。总能量保持不变至百万分之一以内,时间常数τ为0.5秒。数值积分器DE采用绝对误差容差为10^-12,相对误差容差为零。
http://www.amazon.com/Computer-Solution-Ordinary-Differential-Equations/dp/0716704617/
四元数通常是通过数值积分得到的。如果积分器内部没有归一化,则会积累幅度和相位误差。归一化四元数沿单位球面移动,其第一次导数与该球面相切。如果四元数偏离单位球体,它将开始累积相位误差,而在积分器外正常化的相位误差是无法修正的。因此,为了减小相位误差,四元数必须在数值积分器内连续归一化。
https://stackoverflow.com/questions/11667783
复制相似问题