Here's another technical article. The last one was about rendering; this time I'm switching to animation (specifically, rotation). Euler angles have well-known limitations, such as gimbal lock. Another slightly-less-well-known issue is the way in which there are many different (rx,ry,rz) triplets that all encode the same orientation, and writing a program to choose the "right" triplet for a given orientation is sometimes a lot more difficult than it would seem. This problem can come up when implementing a user-interface control for instance, or a dynamics engine. Any time that a program has an non-Euler orientation (expressed as a quaternion, a matrix, and axis and an angle, or whatever) and it has to convert it to a triplet of Euler angles that must fit in smoothly with a sequence of other Euler angles, you have to be careful how you choose which triplet to use.
It's not hard to find convert a quaternion to a This problem is solved easily enough by taking the previous frame's Euler angles into account when converting each frame's orientation from a quaternion to Euler angles. After finding a triplet that corresponds to the given quaternion (which probably has angles in some nominal range like -π ... π), we can add or subtract some multiple of 2π to each angle so that it's as close to the previous values as possible. That'll restore our x-angle function to the linear shape that we'd expect it to have.
There's one more problem though, and this one's subtler. If you
implement a rotation manipulator and you notice that 180-degree
"flips" are creeping into your results, you'll realize there's another
choice (like the ±2π one described above) that our
conversion has to make. To understand this one, let's start by
visualizing an example. Suppose we have an object that's rotated by
180 degrees around its z axis, and -90 degrees around its x axis
(assuming ZXY rotation order). That object would be
facing up, with its head towards us. Now suppose we took a different
object and rotated it by -90 degrees around its x axis, and 180
degrees around its
Y(
φ) X(θ) Z(ψ) = Y(π + φ) X(π - θ) Z(π + ψ)
where X, Y, and Z are rotation operators, and [θ, φ, ψ]
is our ZXY Euler triplet. But if we're going to use this "180 degree
identity", we need more than spatial intuition... we must show that
it's really correct. We can do that by converting the rotation
operators to quaternions, so that we have an algebra with which
to manipulate them. Because we can express rotation θ around a
unit vector q = (cos(θ/2), a sin(θ/2)),
our three rotation operators become
X(
θ) = cos(θ/2) + i sin(θ/2)Y( φ) = cos(φ/2) + j sin(φ/2)Z( ψ) = cos(ψ/2) + k sin(ψ/2)
And the two sides of the 180-degree identity can be written
(cos(
φ/2) + j sin(φ/2))
(cos(θ/2) + i sin(θ/2))
(cos(ψ/2) + k sin(ψ/2))
and
(-sin(
φ/2) + j cos(φ/2))
(sin(θ/2) + i cos(θ/2))
(-cos(ψ/2) + k cos(ψ/2)).
If you multiply-out both of those expressions (keeping in mind that
## Algorithm
Here's a summary of this technique, then. If you have a set of
"reference" angles [ φ,
_{0}ψ]. Then add/subtract multiples of 360 degrees:
_{0}θ = _{1}θ + _{0}n 2π_{θ1}φ = _{1}φ + _{0}n 2π_{φ1}ψ = _{1}ψ + _{0}n 2π
_{ψ1}
(where n, and _{φ1}n are integers) in order to minimize the distance from the reference angles,
_{ψ1}
δ
_{1} = | θ - _{1}θ | +
| φ - _{1}φ | +
| ψ - _{1}ψ |,
do the same thing for the angles produced by the 180-degree identity: θ = π + _{2}θ + _{1}n 2π_{θ2}φ = π - _{2}φ + _{1}n 2π_{φ2}ψ = π + _{2}ψ + _{1}n 2π_{ψ2}δ _{2} = | θ - _{2}θ | +
| φ - _{2}φ | +
| ψ - _{2}ψ |,
and pick whichever triplet ([ &phi, _{1}&psi] or [_{1}&theta, _{2}&phi, _{2}&psi]) is closer to the reference triplet.
_{2}## Further readingBy the way, if you're interested in this kind of thing, check out James Diebel's "quick reference guide". (Just kidding, it's anything but quick... it's exhaustive!). Also, Andrew J. Hanson is the biggest fan of quaternions that I've ever met and he has a book on visualizing them. I haven't read it, but if it's half as enthusiastic as his lectures then it's probably an insightful read. |
|||||