# Lesson 6: Rotating a vector: the q v q* sandwich

Source: https://quaternion.steppeschool.com/rotate-vector-with-quaternion/ (part of "Quaternions, Visually" by Steppeschool, free)

We have a vector, for example a point on a 3D model or the direction a camera looks, and a quaternion. How do we turn the vector? We put it in a sandwich: q on the left, the vector in the middle, q* on the right.

## 6.1 The sandwich

First we write the vector as a quaternion with zero real part, $v = [0, v_x, v_y, v_z]$. We call it a pure quaternion. Then:

$$v' = q \otimes v \otimes q^*$$

The result has w = 0 again. Its x, y, z part is the turned vector.

> **Interactive visual: The two halves of the sandwich.** **Try it:** a vector v across the axis. The blue arrow is where one multiplication, q ⊗ v, takes it: half of the turn. The orange arrow is after the second multiplication: the full turn.

> **Interactive visual: Any vector, any axis.** **Try it:** move θ and look at the numbers in the panel. After the first multiplication, q ⊗ v has a w that is not zero: it is not a plain vector yet. The second multiplication by q* cleans it up. The tip of v moves on the dashed circle around the axis.

## 6.2 Why two multiplications

Let’s do one by hand. Take q = 90° about z and the vector v = x axis. In i, j, k form: $q = \frac{1}{\sqrt2}(1 + k)$, $q^* = \frac{1}{\sqrt2}(1 - k)$ and $v = i$. We only need the table from lesson 5.

$$\begin{aligned}
q \otimes v &= \tfrac{1}{\sqrt2}(1 + k)\,i = \tfrac{1}{\sqrt2}(i + ki) = \tfrac{1}{\sqrt2}(i + j)\\
(q \otimes v) \otimes q^* &= \tfrac12 (i + j)(1 - k) = \tfrac12 (i - ik + j - jk) = \tfrac12 (i + j + j - i) = j
\end{aligned}$$

x became y: a quarter turn about z. After the first step we were only halfway, at 45°.

Now a vector on the axis itself, v = k. A turn about z must not move it:

$$\begin{aligned}
q \otimes v &= \tfrac{1}{\sqrt2}(1 + k)\,k = \tfrac{1}{\sqrt2}(-1 + k) \qquad \leftarrow \text{a real part appeared: not a vector}\\
(q \otimes v) \otimes q^* &= \tfrac12 (-1 + k)(1 - k) = \tfrac12 (-1 + k + k + 1) = k
\end{aligned}$$

So one multiplication alone is not enough. It turns the part of v that is perpendicular to the axis by only half the angle, and it pushes the part along the axis into w. The second multiplication, by q*, adds the other half of the turn and brings the leaked part back. That’s why q holds θ/2, as we saw in lesson 4.

**Look closer:** Try the "x" vector with the "z" axis: v is perpendicular to the axis, and w stays 0 even after the first step. With the tilted vector, part of v lies along the axis, and that part creates the leak. That’s the part the second multiplication removes.

## 6.3 A faster formula for code

Two full quaternion products cost 32 multiplications. If we expand the sandwich once on paper, we get the same result with fewer operations. With $\mathbf u = (x, y, z)$, the vector part of q:

$$\mathbf t = 2\,(\mathbf u \times \mathbf v), \qquad \mathbf v' = \mathbf v + w\,\mathbf t + \mathbf u \times \mathbf t$$

This is what our C library uses in `quat_rotate`.

## 6.4 Object frame to world, and back

A frame is just a set of three axes: the object’s own axes, or the world’s. The orientation q is the turn that takes the object from its start pose, where its axes lie on the world axes, to where it is now. So we have two directions:

- **Object → world:** $v_{world} = q \otimes v_{object} \otimes q^*$. Example: where does the object’s arrow point in the world?

- **World → object:** $v_{object} = q^* \otimes v_{world} \otimes q$. Example: the light comes from above in the world, so from which side does the object see it?

> **Interactive visual: One vector, two frames.** **Try it:** turn the object with the sliders. Above you see the world, where "up" never moves. Below you see the same moment from the object: now the object stands still and "up" has moved. q ⊗ v ⊗ q* goes one way, q* ⊗ v ⊗ q the other.

**Trap:** Mixing up the two directions is a very common bug. So always check with one easy case: a +90° turn about z must take the object’s x axis to the world’s y axis. If you get −y, you used the wrong direction.

## ✓ Check yourself

**Q: q = [0.707, 0, 0, 0.707] (yaw 90°). Turn v = (1, 0, 0) from the object frame to the world.**

(0, 1, 0). The x axis of the object now points along the world’s y.

**Q: Does rotating change the length of a vector?**

No. A unit quaternion only turns, it never stretches. If the lengths change, q does not have length 1.

## Sources and further reading

- J. Solà, "Quaternion kinematics for the error-state Kalman filter", 2017 <https://arxiv.org/abs/1711.02508>: chapter 2: the rotation formula and why it needs q on both sides
- G. Sanderson and B. Eater, "Visualizing quaternions: an explorable video series" <https://eater.net/quaternions>: the same idea shown as two half turns
