# Combining Quaternion Rotations

I'm trying to understand Quaternions in relation to rotation and orientation.

As an example in learning, I'm trying to rotate a point (e.g. at [0.7071, 0, -0.7071], on the unit sphere) about the line x=z (or the vector [0.7071, 0, 0.7071] for a unit vector pointing in x/z direction. It should rotate around the unit sphere, passing through [0,1,0]

I've read that "multiple rotations are just multiplication", but if that's the case, why are the following are not equivalent?

# This version does what I want, rotates a point about the line x=z
val q = Quaternion().setAngleAxis(toRadians(45), 0.7071, 0, 0.7071)

# neither of the following multiplications produce the equivalent to the above q
val qx = Quaternion().setAngleAxis(toRadians(45), 1, 0, 0)
val qy = Quaternion().setAngleAxis(toRadians(45), 0, 1, 0)
val q1 = qx.mul(qy)
val q2 = qy.mul(qx)


(My reasoning is like looking at a unit vector starting in the x direction, which if I rotate 45 degrees in the y axis would give me a vector pointing in the z=x direction, but this is clearly naive as it doesn't work)

An example plot of qx * qy (but using 5 degree rotations instead of 45) is: The q rotation I want gives me: My understanding is qx and qy represent rotations about the given axis, or indeed also represent orientations, and if I use these independently and plot them, I get what I would expect, a point being rotated as required.

But if I start from either one of these, why doesn't the multiplication of the other (which represents an initial orientation multiplied by a rotation) result in a rotation that would rotate a point by both the x and the y axis?

Which leads me to the question, what does qx * qy (or vica verca) represent here? (I think this is the key bit I'm not understanding.)

Is it possible to apply something to qx or qy to get the original q directly?

Multiplying two quaternions gives you a quaternion equivalent to performing the two rotations they represent in sequence.

q3 = q1 * q2
q3 * object = q1 * (q2 * object)
// "Perform rotation q2 with respect to the world axes, then q1"
// Or equivalently: "Perform rotation q1 about your local axes, then q2"

q4 = q2 * q1
q4 * object = q2 * (q1 * object)
// "Perform rotation q1 with respect to the world axes, then q2"
// Or equivalently: "Perform rotation q2 about your local axes, then q1"


(Notice that rotating around the object's local axes - ones that spin with the object - means applying the rotations in the opposite order than if we consider our axes fixed in the world reference frame)

These two possible sequences will generally give different results from one another, and different results from a single rotation along an axis intermediate between the axes of q1 and q2, because 3D rotation is extremely order-dependent.

This isn't just a quirk of quaternions, but something true of orientations in three-dimensional space themselves.

Our experience from translation might mislead us. With a translation like (+1, +2, +3), we can separate it into...

• a translation by 1 unit along the x axis

• a translation by 2 units along the y axis

• and a translation by 3 units along the z axis

...and perform the three axis-aligned translations one at a time, in any order, and still get the same result of applying the composed translation all at once.

Rotation does not work that way, so an intuition calibrated on translation can easily lead us to false conclusions. You can verify this for yourself with the axes in your example. Grab an object with an identifiable top/right/front, and mentally map its sides to axes.

• Place it on a table, and find an axis 45 degrees between the x and z axes you picked. Twist the object 45 degrees about that axis, and remember what that orientation looks like.

• Now repeat the experiment, but this time rotate 45 degrees around just the x axis first, then 45 degrees about the z axis, wherever it ends up.

You'll observe that the orientation you get at the end is different between the two experiments.

Rotation is not simply separable into axis-aligned components.

Or to be more precise: there will be many possible trios of axis-aligned rotations that give the same resulting orientation as any orientation you formed some other way (that's how Euler angles / Tait-Bryan angles work), but there's not such a simple mapping between the combined and separated forms like there is for translation. You can't just take the same angle and repeat it/split it proportionally between the components of its axis and get the same result. The trigonometry of the conversion is messy and has lots of counter-intuitive edge cases. As shown in the link above, sometimes applying a rotation about x and y gives you a rotation about the z!

So, to recap: it is true that to combine rotations expressed as quaternions, all you have to do is multiply those quaternions. But that represents a specific kind of combination, which is composition: applying one rotation, then the other, in sequence.

Our intuition about what this composition should do may depart significantly from the reality, unless we spend a lot of time turning mugs around in our hands. (Just remember to finish your coffee or tea first!)

• Thanks @DMGregory, I did read your "I'm rotating an object on two axes, so why does it keep twisting around the third axis?" page in researching this question, but I'm still hung up on the problem of thinking about if a quarternion represents an orientation (e.g. initial camera orientation along the x axis) and then I apply a rotation around the y axis, what is actually happening to the new camera orientation - it doesn't feel to me as though I'd have an orientation that would do what I expect. I will experiment with this though. Jan 12, 2021 at 9:07
• also to add I had understood associativity of q1 and q2, I just didn't know if either way around would give the equivalent (but wouldn't have understood why a certain order would have worked, had it produced it - which hinted to me anyway that they couldn't have produced the same output) Jan 12, 2021 at 9:08

Is it possible to apply something to qx or qy to get the original q directly?

Yes it is! The transformation you're looking for is $$\qy^{-1} * qx * qy\$$

(My reasoning is like looking at a unit vector starting in the x direction, which if I rotate 45 degrees in the y axis would give me a vector pointing in the z=x direction, but this is clearly naive as it doesn't work)

This will give you a rotation that turns the vector $$\(\sqrt{2}/2,0,\sqrt{2}/2)\$$ into $$\(1,0,0)\$$ -- either $$\q1\$$ or $$\q2\$$, depending on what order you apply the rotations. That's not what you're looking for, though. The rotation you want, $$\q\$$, should turn the vector $$\(\sqrt{2}/2,0,\sqrt{2}/2)\$$ into itself, and rotates the rest of the world 45° around it. (It doesn't send the x unit vector anywhere very interesting.)

$$\qx\$$ turns $$\(1,0,0)\$$ into itself, and rotates the rest of the world 45° around it.

$$\qy\$$ turns $$\(\sqrt{2}/2,0,\sqrt{2}/2)\$$ into $$\(1,0,0)\$$.

So, the step-by-step process is:

• [$$\qy\$$] Move your desired axis from $$\(\sqrt{2}/2,0,\sqrt{2}/2)\$$ to $$\(1,0,0)\$$
• [$$\qx\$$] Rotate everything around your axis (now at $$\(1,0,0)\$$)
• [$$\qy^{-1}\$$] Move your axis back to $$\(\sqrt{2}/2,0,\sqrt{2}/2)\$$

Composition like this reads right-to-left, so the end-result is $$\qy^{-1} * qx * qy\$$.

• ... while writing this answer I kept forgetting which direction qy went in. I think I've got it right now, but it's still possible I've dropped a minus sign somewhere and the correct answer is qy * qx * qy^(-1). Can someone double-check my reasoning? Jan 12, 2021 at 12:29
• your transform is correct! qy-1 * qx * qy does indeed give the original q. Jan 12, 2021 at 18:01

In a sense it is true that multiple rotations are just multiplication. However, multiplying rotations is not commutative (ab != ba).

To see this, take an irregular rectangular object like a book. Rotate 90 degrees around the x axis followed by a rotation of 90 degrees around the y axis. Now try again with the y axis first, followed by the x axis.

This is important because when you apply multiple rotations, they will be applied in sequence. That is, it will rotate from the position it was left in from the previous rotation.

Because of this it is not the same to make a rotation around the (x=z)-axis compared to the x followed by z axis.