Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Late response; this answer is for people who come across this question in the future rather than for the questioner.</p> <p>I disagree with the other two answers regarding only normalizing a quaternion occasionally. The standard formulae for using a quaternion to rotate/transform a vector or to generate a rotation/transformation matrix implicitly assume the quaternion is normalized. The errors that result from using an unnormalized quaternion are proportional to the square of the quaternion's magnitude. Quadratic error growth is something best avoided.</p> <p>If you normalize frequently you don't need square root. A first order approximation works quite nicely. Here's what I use for quaternions as IEEE doubles, somewhat stylized:</p> <pre><code>double qmagsq = quat.square_magnitude(); if (std::abs(1.0 - qmagsq) &lt; 2.107342e-08) { quat.scale (2.0 / (1.0 + qmagsq)); } else { quat.scale (1.0 / std::sqrt(qmagsq)); } </code></pre> <p>Note that I'm using the first order Padé approximant <code>2.0/(1.0+qmagsq)</code> rather than the first order Taylor expansion <code>0.5*(3.0-qmagsq)</code> to estimate <code>1.0/std::sqrt(qmagsq)</code>. This approximation, if valid, replaces the square root call by a simple division. The key is to find when that approximation is valid, which is where that magic number 2.107342e-08 comes into play.</p> <p>Why a Padé approximant? Two reasons. One is that for values of <code>qmagsq</code> close to one, <code>1+qmagsq</code> loses less precision than does <code>3-qmagsq</code>. The other is that the Padé approximant cuts the error by a factor of three compared to the Taylor expansion. For values of <code>qmagsq</code> between 0 and 2, the error in this approximation is less than <code>(1-qmagsq)^2 / 8</code>. The magic number 2.107342e-08 represents where this error is more that half an ULP for IEEE doubles. If you are taking reasonable small steps, the square of the magnitude of the quaternion will always be within that limit. You'll never be calling <code>sqrt</code>.</p> <p>The one exception to this "normalize always" paradigm might be if you are using a Lie group integration technique to propagate quaternions. If you don't know what that means, you are probably using the equivalent of <code>q(t+Δt) = q(t) + dq(t)/dt*Δt</code> to propagate a quaternion. You're still using that Euler step somewhere even if you are using a higher order integration technique that isn't a Lie group integrator.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COAre you aware of any tests & statistics for error accumulation w/o normalization, with pure `sqrt`-based, and with approximate normalization? Note 1: "The standard formulae... implicitly assume"---there are no de jure standard formulae, are there? Any formula may be used, as long as it is correct according to quaternion calculus, and your problem's specific requirements. Note 2: for transformation matrices calculated as in my answer, the absolute error is proportional to magnitude^2, but the relative error (which is more important) is not. Note 3: normalization introduces additional errors.
      singulars
    2. CONormalization is a kludge to drag the quaternion back to the unit 3-sphere. The reason quaternions drift off the manifold is because that Euler step is in a sense invalid mathematically: The unit quaternions are a group, not an algebra. Not using unit quaternions is also invalid; now you don't have a chart on so(3). Do it right (e.g., Lie group integration techniques) and the quaternion will pretty much stay on the manifold. You might still need to normalize occasionally.
      singulars
    3. COAs far as my square root approximation is concerned: By design it's accurate to within half an ULP over its design range. It occasionally differs from `1/std::sqrt(x)` in the least significant bit, but that's because `std::sqrt(x)` is also accurate to within half an ULP. Which answer is right when they do differ? Neither one. The right answer is halfway in between.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload