Sign in or create a free account to continue.

ROB-210 · Lesson 2 of 12 · 30 min

Rotation matrices in two and three dimensions

Position is only half of a pose. A gripper at the right place but facing the wrong way cannot pick anything up, and a camera that knows where it is but not which way it looks cannot locate what it sees. Orientation is harder to describe than position because rotations do not add like vectors: turning 90 degrees about x and then 90 degrees about y leaves an object in a different attitude from doing the same turns in the opposite order. The rotation matrix is the representation that handles this correctly. It is the workhorse of robot kinematics, the form used inside almost every library, and the foundation for the transforms, Denavit–Hartenberg parameters and Jacobians later in the course.

Rotation in the plane

Start in two dimensions. Suppose frame B is rotated by an angle \( \theta \) counter-clockwise relative to frame A, with the same origin. The unit x-axis of B, written in A's coordinates, is \( (\cos\theta, \sin\theta) \), and B's y-axis is \( (-\sin\theta, \cos\theta) \). Stacking these two columns gives the 2-D rotation matrix:

\[{}^{A}R_{B} = R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}\]

This matrix does two jobs, and keeping them distinct is the key to using rotations without confusion. First, it describes orientation: its columns are frame B's axes expressed in frame A. Second, it changes coordinates: multiplying a point's coordinates in B by \( {}^{A}R_{B} \) gives the same point's coordinates in A, \( {}^{A}\mathbf{p} = {}^{A}R_{B}\,{}^{B}\mathbf{p} \). The same matrix can also be read as an operator that rotates a vector by \( \theta \) within a single frame. All three readings are correct; trouble arises only when we switch between them without noticing.

Worked problem

Rotating a point in the plane

A planar robot's tool frame is rotated 30° relative to its base frame, with the same origin. A point is at \( (1, 0) \) m in the tool frame. Where is it in the base frame?

Show solution
  1. \( \cos 30^\circ = 0.866 \) and \( \sin 30^\circ = 0.5 \).
  2. \( {}^{B}\mathbf{p} = \begin{bmatrix} 0.866 & -0.5 \\ 0.5 & 0.866 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0.866 \\ 0.5 \end{bmatrix} \).
  3. This is simply the first column, the tool x-axis expressed in the base frame.

Answer: (0.866, 0.5) m. Multiplying by a unit axis vector picks out the corresponding column of the rotation matrix.

Rotation matrices in three dimensions

In three dimensions the idea is the same. The rotation matrix \( {}^{A}R_{B} \) is a 3 × 3 matrix whose columns are the unit vectors of frame B's x, y and z axes, each expressed in frame A:

\[{}^{A}R_{B} = \begin{bmatrix} {}^{A}\hat{\mathbf{x}}_B & {}^{A}\hat{\mathbf{y}}_B & {}^{A}\hat{\mathbf{z}}_B \end{bmatrix} = \begin{bmatrix} r_{11} & r_{12} & r_{13} \\ r_{21} & r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33} \end{bmatrix}\]

Each entry is a direction cosine, the cosine of the angle between one axis of B and one axis of A, because the dot product of two unit vectors is the cosine of the angle between them. That is why rotation matrices are also called direction cosine matrices, especially in aerospace. Reading a rotation matrix is a skill worth practicing: a column of (0, 0, −1) means that axis of B points straight down along A's negative z-axis; a column of (0.707, 0.707, 0) means it points diagonally between A's x and y axes.

The three elementary rotations

Rotations about the coordinate axes are the building blocks of all others. A rotation by \( \theta \) about x leaves the x-axis fixed and turns y and z in their plane; similarly for y and z. Writing \( c = \cos\theta \) and \( s = \sin\theta \):

\[R_x(\theta) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & c & -s \\ 0 & s & c \end{bmatrix}, \quad R_y(\theta) = \begin{bmatrix} c & 0 & s \\ 0 & 1 & 0 \\ -s & 0 & c \end{bmatrix}, \quad R_z(\theta) = \begin{bmatrix} c & -s & 0 \\ s & c & 0 \\ 0 & 0 & 1 \end{bmatrix}\]

Look closely at the sign pattern in \( R_y \): the negative sine sits below the diagonal, unlike the other two. This is not a typo. It follows from the right-hand rule, because the cyclic order of axes is x to y to z to x, so rotating about y turns z toward x. Many hand-derived kinematics errors trace back to getting this one sign wrong, so it is worth verifying with a quick test: \( R_y(90^\circ) \) should send the z-axis \( (0, 0, 1) \) to the x-axis \( (1, 0, 0) \).

Three panels each showing a right-handed frame before and after a rotation of about 40 degrees. In the first panel the frame turns about the x-axis, in the second about the y-axis and in the third about the z-axis. Curved arrows around each fixed axis show the positive direction of rotation by the right-hand rule.
Elementary rotations about x, y and z. Positive angles follow the right-hand rule: thumb along the axis, fingers curl in the positive direction.

Properties of rotation matrices

Not every 3 × 3 matrix is a rotation. Because the columns are perpendicular unit vectors, a rotation matrix is orthonormal: \( R^\mathsf{T} R = I \). Because the frames are both right-handed, its determinant is +1 rather than −1, which would indicate a reflection. The set of all such matrices is called the special orthogonal group in three dimensions, SO(3):

\[SO(3) = \{ R \in \mathbb{R}^{3\times3} : R^\mathsf{T}R = I,\ \det R = +1 \}\]

These two conditions have useful consequences. The inverse of a rotation is simply its transpose, \( R^{-1} = R^\mathsf{T} \), which is far cheaper to compute than a general matrix inverse and numerically exact. Rotations preserve lengths and angles, so a rotated vector has the same norm, and the dot product of two rotated vectors equals the dot product of the originals. The product of two rotations is another rotation. Although a rotation matrix has nine entries, the orthonormality conditions impose six constraints, leaving three free parameters, which matches the three rotational degrees of freedom of a rigid body.

Properties of rotation matrices in SO(3).
PropertyStatementPractical use
Orthonormal columns\( R^\mathsf{T}R = I \)Columns are unit axes; check numerically for drift
Inverse is transpose\( R^{-1} = R^\mathsf{T} \)Reverse a frame change cheaply and exactly
Determinant +1\( \det R = 1 \)Distinguishes rotations from reflections
Closure\( R_1 R_2 \in SO(3) \)Chain rotations along a robot arm
Preserves lengths\( \lVert R\mathbf{v} \rVert = \lVert \mathbf{v} \rVert \)Rotated sensor data keep their scale
Not commutative\( R_1 R_2 \ne R_2 R_1 \) in generalOrder of rotations matters

Composing rotations

Suppose frame B is rotated relative to A, and frame C is rotated relative to B. The orientation of C relative to A is the product, with the frame labels canceling:

\[{}^{A}R_{C} = {}^{A}R_{B}\,{}^{B}R_{C}\]

To use this, we need to know how each rotation was specified. There are two ways to describe a sequence of rotations, and they give products in opposite orders. If each rotation is about an axis of the current, moving frame, called intrinsic or body-fixed rotations, we multiply on the right: first rotation leftmost. If each rotation is about an axis of the original, fixed frame, called extrinsic or space-fixed rotations, we multiply on the left: first rotation rightmost. A useful slogan is: moving frame, multiply right; fixed frame, multiply left.

Worked problem

Order matters

Compute \( R_x(90^\circ)R_z(90^\circ) \) and \( R_z(90^\circ)R_x(90^\circ) \) and compare where each sends the x-axis.

Show solution
  1. With \( c = 0 \) and \( s = 1 \): \( R_x(90^\circ) = \begin{bmatrix} 1&0&0\\0&0&-1\\0&1&0 \end{bmatrix} \) and \( R_z(90^\circ) = \begin{bmatrix} 0&-1&0\\1&0&0\\0&0&1 \end{bmatrix} \).
  2. \( R_xR_z = \begin{bmatrix} 0&-1&0\\0&0&-1\\1&0&0 \end{bmatrix} \): the first column says x is sent to \( (0,0,1) \), the z-axis.
  3. \( R_zR_x = \begin{bmatrix} 0&0&1\\1&0&0\\0&1&0 \end{bmatrix} \): x is sent to \( (0,1,0) \), the y-axis.

Answer: The products differ, so the final orientations differ. Try it with a book: turn it 90° about one edge then another, then repeat in the opposite order.

Two rows of three box sketches. In the top row a box with a marked face is rotated 90 degrees about x then 90 degrees about z. In the bottom row the same box is rotated about z first and then about x. The final boxes in the two rows face different directions.
Rotations do not commute. The same two 90° turns applied in opposite orders leave the box in different orientations.

Rotating vectors versus changing frames

A common source of confusion is the difference between rotating an object and re-expressing a fixed object in a rotated frame. Suppose a vector \( \mathbf{v} \) is fixed in space and we rotate our frame by \( \theta \) about z. The vector's new coordinates are obtained with \( R_z(\theta)^\mathsf{T} = R_z(-\theta) \), because from the turned frame's point of view the vector appears to have rotated the other way. If instead we rotate the vector itself by \( \theta \) within a fixed frame, its new coordinates are \( R_z(\theta)\mathbf{v} \). Both are valid operations; the frame-label notation tells us which is which. \( {}^{A}\mathbf{v} = {}^{A}R_{B}\,{}^{B}\mathbf{v} \) is a change of frame for the same vector; \( {}^{B}\mathbf{v} = ({}^{A}R_{B})^\mathsf{T}\,{}^{A}\mathbf{v} \) goes the other way.

Worked problem

Re-expressing gravity in a tilted sensor frame

An IMU on a robot is pitched 20° nose-down: its frame S is related to the level world frame W by \( {}^{W}R_{S} = R_y(20^\circ) \). Gravity in the world frame is \( {}^{W}\mathbf{g} = (0, 0, -9.81) \) m/s². What is gravity in the sensor frame?

Show solution
  1. We need \( {}^{S}\mathbf{g} = ({}^{W}R_{S})^\mathsf{T}\,{}^{W}\mathbf{g} = R_y(-20^\circ)\,{}^{W}\mathbf{g} \).
  2. With \( c = 0.940 \) and \( s = 0.342 \), \( R_y(-20^\circ) = \begin{bmatrix} 0.940 & 0 & -0.342 \\ 0 & 1 & 0 \\ 0.342 & 0 & 0.940 \end{bmatrix} \).
  3. Multiply: \( {}^{S}\mathbf{g} = (0.342 \times 9.81,\; 0,\; -0.940 \times 9.81) = (3.36, 0, -9.22) \) m/s².

Answer: About (3.36, 0, −9.22) m/s². This is how an accelerometer measures tilt: the ratio of components gives the pitch, \( \arctan(3.36/9.22) = 20^\circ \). (Real accelerometers report the reaction to gravity, so the signs flip.)

Numerical care

Rotation matrices computed from floating-point numbers drift slightly away from orthonormality as they are multiplied repeatedly, for example when integrating a gyroscope's readings over many time steps. The columns gradually lose unit length and perpendicularity, and the matrix starts to scale and shear vectors as well as rotate them. The standard fix is to re-orthonormalize from time to time, either by a Gram–Schmidt step on the columns or, more robustly, by replacing R with the nearest rotation matrix from its singular value decomposition, \( R \leftarrow UV^\mathsf{T} \) where \( R = U\Sigma V^\mathsf{T} \). Checking \( \lVert R^\mathsf{T}R - I \rVert \) is a cheap health test.

Building, checking and repairing rotation matrices
import numpy as np
def Rx(t): c, s = np.cos(t), np.sin(t); return np.array([[1,0,0],[0,c,-s],[0,s,c]])
def Rz(t): c, s = np.cos(t), np.sin(t); return np.array([[c,-s,0],[s,c,0],[0,0,1]])
np.set_printoptions(precision=3, suppress=True)
R = Rx(np.radians(30)) @ Rz(np.radians(45))
print("R =\n", R)
print("R^T R = I ?", np.allclose(R.T @ R, np.eye(3)), " det =", round(np.linalg.det(R), 6))

# drift: compose many small noisy steps, then repair with the SVD
rng = np.random.default_rng(1)
Q = np.eye(3)
for _ in range(10000):
    Q = Q @ (Rz(0.001) + rng.normal(0, 1e-6, (3, 3)))
print("error before repair:", f"{np.linalg.norm(Q.T @ Q - np.eye(3)):.1e}")
U, _, Vt = np.linalg.svd(Q); Q = U @ Vt
print("error after repair: ", f"{np.linalg.norm(Q.T @ Q - np.eye(3)):.1e}")
Output
R =
 [[ 0.707 -0.707  0.   ]
 [ 0.612  0.612 -0.5  ]
 [ 0.354  0.354  0.866]]
R^T R = I ? True  det = 1.0
error before repair: 5.0e-04
error after repair:  1.7e-15

Rotation matrices in practice

Rotation matrices are ideal for computation: composing rotations is a matrix product, rotating a vector is a matrix-vector product, inverting is a transpose, and there are no special cases or singularities. Their drawbacks are redundancy, nine numbers for three degrees of freedom, and opacity: few people can look at nine direction cosines and picture the orientation. For storage, communication and human interfaces, robot software therefore uses more compact representations, Euler angles, axis-angle and quaternions, which are the subject of the next lesson. Internally, almost every robotics library converts to rotation matrices or quaternions to do the arithmetic.

A useful mental check when reading any rotation matrix is to look at each column in turn and ask where that axis of the rotated frame points. For a camera looking straight down at a table from above, with the image's x to the right, the matrix relative to a world frame with z up has a third column of (0, 0, −1), because the camera's optical z-axis points down. If a calibration routine returns a third column with a positive z component, something is upside down.

Common mistakes

  • MistakePutting the negative sine in the wrong place in \( R_y \).

    InsteadIn \( R_y(\theta) \) the \( -\sin\theta \) sits in row 3, column 1; test by checking that \( R_y(90^\circ) \) sends z to x.

  • MistakeInverting a rotation matrix with a general matrix inverse.

    InsteadUse the transpose, which is exact and cheaper.

  • MistakeMultiplying rotations in the wrong order.

    InsteadRotations about moving axes multiply on the right; rotations about fixed axes multiply on the left.

  • MistakeConfusing rotating a vector with changing the frame it is expressed in.

    InsteadUse frame labels: \( {}^{A}R_{B} \) converts B coordinates to A coordinates; its transpose goes back.

  • MistakeLetting a repeatedly updated rotation matrix drift.

    InsteadRe-orthonormalize periodically, for example with the SVD.

Summary and key terms

  • A rotation matrix \( {}^{A}R_{B} \) has frame B's unit axes, expressed in A, as its columns.
  • It converts coordinates, \( {}^{A}\mathbf{p} = {}^{A}R_{B}\,{}^{B}\mathbf{p} \), and can also act as a rotation operator.
  • Elementary rotations about x, y and z are the building blocks; note the sign pattern of \( R_y \).
  • Rotation matrices form SO(3): orthonormal with determinant +1, so the inverse is the transpose.
  • Composition is matrix multiplication, and order matters because rotations do not commute.
  • Moving-frame rotations multiply on the right; fixed-frame rotations multiply on the left.
  • Floating-point drift should be repaired by re-orthonormalizing, for example with the SVD.
Rotation matrix
A 3 × 3 orthonormal matrix with determinant +1 describing orientation and changing coordinates.
Direction cosine
The cosine of the angle between an axis of one frame and an axis of another.
Elementary rotation
A rotation about one coordinate axis.
SO(3)
The group of all 3-D rotation matrices.
Orthonormal
Having columns that are mutually perpendicular unit vectors.
Intrinsic rotation
A rotation about an axis of the moving, body-fixed frame.
Extrinsic rotation
A rotation about an axis of the original, fixed frame.
Composition
Combining rotations by multiplying their matrices.
Re-orthonormalization
Correcting a drifted matrix back to the nearest true rotation.
Right-hand rule
The convention that positive rotation curls the fingers of the right hand with the thumb along the axis.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. Write \( R(90^\circ) \) in 2-D and apply it to \( (2, 1) \).

    Show answer

    \( \begin{bmatrix}0&-1\\1&0\end{bmatrix}(2,1) = (-1, 2) \).

  2. What is \( R_z(180^\circ) \)?

    Show answer

    \( \mathrm{diag}(-1, -1, 1) \).

  3. Where does \( R_x(90^\circ) \) send the y-axis?

    Show answer

    To \( (0, 0, 1) \), the z-axis.

  4. Where does \( R_y(90^\circ) \) send the z-axis?

    Show answer

    To \( (1, 0, 0) \), the x-axis.

  5. A matrix has determinant −1 and orthonormal columns. Is it a rotation?

    Show answer

    No; it includes a reflection.

  6. What is the inverse of \( R_z(35^\circ) \)?

    Show answer

    \( R_z(-35^\circ) = R_z(35^\circ)^\mathsf{T} \).

  7. How many independent parameters does a 3-D rotation have?

    Show answer

    Three.

  8. A frame is rotated about its own z then its own new x. In which order do you multiply?

    Show answer

    \( R = R_z R_x \) (moving frame, multiply on the right).

  9. The same two rotations are about the fixed z then fixed x. What is R?

    Show answer

    \( R = R_x R_z \) (fixed frame, multiply on the left).

  10. A camera rotation matrix has third column \( (0, 0, -1) \) in a z-up world. Which way does it look?

    Show answer

    Straight down.

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz