Posts Tagged ‘quaternion’

Euler Quaternions and the Trouble with Y-Up Space, Part 2

Welcome to my series of blogs about Eulers and Quaternions! This is part 2/2 of the series. See part 1 here. This series aims to talk about some of the difficulties that I’ve had in dealing with Euler <-> Quaternion transformations. In part 1, I talked about the difficulties around finding a transformation from Quaternion to Euler given a non-standard order of operations in the Euler and what it takes to actually derive the equations required to perform that transformation. We left off with equations that were useable; they did not however take into account the rotational singularities at the poles. For the unfamiliar, Euler rotations introduce two singularities into the space of rotations at the north and south poles of the rotation globe. As the Pitch approaches +90 or -90 degrees, the Yaw and Roll components degenerate further and further into a single rotational axis. This is known as gimbal lock.

As can be seen, the quickest way to detect for a singularity is to check if the Pitch component is +/-90. As detailed here (section Singularities), we can efficiently detect this by reusing our equation for pitch:

  • Θ, pitch: asin(-RPY12) = asin(2(q0q3 – q1q2))

Given the fact that at +/-90 degrees, sin(Θ) = 1/-1:

1 = 2(q0q3 – q1q2), -1 = 2(q0q3 – q1q2)

0.5 = q0q3 – q1q2, -0.5 = q0q3 – q1q2

So test = q0q3 – q1q2

If test is less than -0. 4999999 then we can assume a pitch of -90; if test is greater than 0.4999999 then we can assume a pitch of 90. We have a choice for what we could do with the degenerated yaw/roll rotational axis when a singularity is detected. Following in the footsteps of euclideanspace, I chose to put all rotation into the yaw. This means that we can assume an angle of 0 for roll. Applying all of this through our previous equations, we get:

When test > 0.4999999:

  • Φ, roll: 0
  • Θ, pitch: 90
  • Ψ, yaw: 2 * Math.atan2(q3, q1)

When test < -0.4999999:

  • Φ, roll: 0
  • Θ, pitch: -90
  • Ψ, yaw: -2 * Math.atan2(q3, q1)

You can get a better feel for this by following the derivation on the euclideanspace page. We now have a complete chain to convert a quaternion into a Y-Up Euler rotation! What’s nice about this is that we can now transform any order-of-operations Euler rotation into any other order-of-operations Euler rotation by transforming the first Euler representation into a quaternion then deriving the equations for getting an Euler rotation back from a quaternion with the second Euler representation. ie Roll, Pitch, Yaw into Yaw, Roll, Pitch, etc…

Hopefully this helps somebody out there because it sure as hell stumped me when I initially ran into this problem. Thank you for reading.


Euler Quaternions and the Trouble with Y-Up Space, Part 1

May 25, 2012 1 comment

Yesterday I did something that I didn’t think I was capable of. It involved quaternions, matrices and a decent amount of math. Let’s start with the problem definition:

  • We have a system that tracks rotations using quaternions
  • We would like people to be able to use Euler coordinates (Tait-Bryan angles if you’re picky)
  • Our world is Y-UP

Doesn’t sound too hard. In fact, half of it was fairly easy. Turning a set of Euler coordinates into a quaternion is as simple as creating three quaternions using angle axis pairs derived from the incoming Euler rotation. For us, the three Quaternions were as follows:

  • [Angle: Yaw, Axis: [0, 1, 0]]
  • [Angle: Pitch, Axis: [0, 0, 1]]
  • [Angle: Roll, Axis: [1, 0, 0]]

We create a combined rotation quaternion by conjugating the three quaternions together in the following order:

Roll * (Pitch * (Yaw) * Pitch-1) * Roll-1

This is all that is required to produce a quaternion from a set of Euler coordinates. Now, we also had to retrieve Euler coordinates from a given quaternion. This is more difficult than taking Euler coordinates and converting them into a quaternion as the task requires a fairly solid understanding of the math. This too would be simple, if it weren’t for the fact that the entire Internet agrees that Z-Up is the way to go for Euler/Quaternion conversions. From what I could tell, the equations for converting a rotation quaternion into a Y-Up Euler coordinate do not exist! (On the internet).

To my shock, horror and dismay, this meant that I had to derive the equations myself. Needless to say, this was a daunting task. But, after an arm and a leg… and the other arm… and the other leg… and parts of my face/body and an assortment of pieces from whichever organs remain… I was victorious. My glorious victory over the maths was quite euphoric.

First, let’s talk about why Y-Up Euler coordinates are so different from Z-Up Euler coordinates. The idea behind Euler coordinates is that given three angular values, you apply three rotational transformations in a predetermined order around three dynamic or constant axes (depending on convention) and arrive at a destination rotation.

Rotational transformations are not commutative, that means that applying them in a different order will produce a different rotation all-together. I won’t get into why that is but it has to do with the fact that the space of all 3D rotations is something akin to the surface of a 4 dimensional hypersphere and applying a rotation is like traveling from one point on the surface of that sphere to another surface point while always remaining on the surface. (Feel like going for a dip in some advanced math? Read here).

The effect is that a rotation quaternion composed from rotations around axes in the order ZYX is fundamentally different from one composed from rotations in the order YZX, which is what we want. So, the equations must be derived. I won’t delve very much into why the following works as that could take several blogs. First, we must build a rotation matrix that will compose our Euler coordinates in the order that we want. This is as simple as getting the angle-axis matrix formula and plugging some numbers into it. That formula is the following:

Where c is cos(θ), s is sin(θ) and C is 1-c, θ is the angle of rotation and (x,y,z) are the vector components of the axis. This is taken from here . By plugging in axis and angle, we construct three rotation matrices:

Yaw, about [0, 1, 0], angle sign Ψ (Psi):

Pitch, about [0, 0, 1], angle sign Θ (Theta):

Roll, about [1,0,0], angle sign Φ (Phi):

Now, we multiply the matrices together in the order (Roll)(Pitch)(Yaw), producing the following:

Next step is to refer to the Quaternion -> Rotation matrix formula:

This formula was taken from here. The quaternion components are [w, x, y, z] -> [0, 1, 2, 3]

Finally, to retrieve the Euler coordinates we must match the matrix form of the rotation quaternion to our RPY rotation matrix exploiting cells where the values are easy to retrieve. In this case, the values are as follows (Notation, Matrix Row Column where row and column are in the range [1,3]):

  • Φ, roll: atan2(RPY32, RPY22) = atan2(2(q0q1 + q2q3), q0q0 – q1q1 + q2q2 – q3q3)
  • Θ, pitch: asin(-RPY12) = asin(2(q0q3 – q1q2))
  • Ψ, yaw: atan2(RPY13, RPY11) = atan2(2(q0q2 + q1q3), q0q0 + q1q1 – q2q2 – q3q3)

This is almost enough. What is left is to test for pitch singularities (+90, -90) and treat them specially. Since this blog has gone on for far too long, I will stop now as what has been given is certainly enough to get a similar system working. In my next blog, I will detail how we could cheaply test for the singularities and what we could do in that case. You can do some advance reading on that here.