ROB-210 · Lesson 4 of 12 · 30 min

Homogeneous transforms and rigid-body motion

A pose combines position and orientation, and robots need to chain poses constantly: the camera relative to the wrist, the wrist relative to the base, the base relative to the map, the object relative to the camera. Doing this with separate rotation matrices and translation vectors works, but the bookkeeping quickly becomes error-prone. The homogeneous transformation matrix packs a rotation and a translation into a single 4 × 4 matrix, so that changing frames, composing poses and inverting them all become matrix operations. This lesson develops homogeneous transforms, the group SE(3) they form, and the habits that make them reliable in real code.

Combining rotation and translation

Suppose frame B is both rotated and translated relative to frame A. A point P has coordinates \( {}^{B}\mathbf{p} \) in B. To find its coordinates in A, we first rotate them into A's orientation and then add the position of B's origin:

\[{}^{A}\mathbf{p} = {}^{A}R_{B}\,{}^{B}\mathbf{p} + {}^{A}\mathbf{p}_{B}\]

This is an affine map, not a linear one, because of the added translation. That makes chaining awkward: going from C to B to A gives \( {}^{A}R_{B}({}^{B}R_{C}\,{}^{C}\mathbf{p} + {}^{B}\mathbf{p}_{C}) + {}^{A}\mathbf{p}_{B} \), and every additional frame adds another nested layer. The trick of homogeneous coordinates removes the problem by appending a fourth coordinate equal to 1 to every point.

The homogeneous transformation matrix

Write a point as \( (x, y, z, 1) \) and define the 4 × 4 matrix:

\[{}^{A}T_{B} = \begin{bmatrix} {}^{A}R_{B} & {}^{A}\mathbf{p}_{B} \\ \mathbf{0}^\mathsf{T} & 1 \end{bmatrix} = \begin{bmatrix} r_{11} & r_{12} & r_{13} & p_x \\ r_{21} & r_{22} & r_{23} & p_y \\ r_{31} & r_{32} & r_{33} & p_z \\ 0 & 0 & 0 & 1 \end{bmatrix}\]

Then the frame change becomes a single matrix product, \( {}^{A}\tilde{\mathbf{p}} = {}^{A}T_{B}\,{}^{B}\tilde{\mathbf{p}} \), where the tilde marks homogeneous coordinates. Multiplying out confirms that the top three rows reproduce the affine formula and the last row keeps the 1. Like a rotation matrix, the transform has several readings: it describes the pose of frame B relative to A (the columns are B's axes and B's origin, all expressed in A); it converts coordinates from B to A; and it can act as an operator that moves a body within one frame.

Free vectors such as directions and velocities are written with a fourth coordinate of 0 rather than 1. Then the translation column is multiplied by zero and only the rotation acts, exactly as lesson 1 required: displacements are unaffected by moving the origin. This 0-or-1 convention lets a single matrix handle both points and vectors correctly.

Worked problem

A camera on a robot wrist

A camera frame C is mounted on a wrist frame W so that \( {}^{W}T_{C} \) has rotation \( R_x(180^\circ) \) (the camera looks back along the wrist's negative z-axis) and translation \( (0.05, 0, 0.10) \) m. The camera sees an object at \( {}^{C}\mathbf{p} = (0.02, -0.01, 0.30) \) m. Where is the object in the wrist frame?

Show solution
  1. \( R_x(180^\circ) = \mathrm{diag}(1, -1, -1) \).
  2. Rotate: \( (0.02,\; 0.01,\; -0.30) \).
  3. Translate: \( (0.02 + 0.05,\; 0.01 + 0,\; -0.30 + 0.10) = (0.07, 0.01, -0.20) \) m.

Answer: (0.07, 0.01, −0.20) m in the wrist frame: 0.2 m below the wrist origin along its negative z-axis, which is where a downward-looking camera on an upright wrist would expect it.

Composition: chaining frames

The great advantage of homogeneous transforms is that chaining frames is just multiplication, with frame labels canceling:

\[{}^{A}T_{C} = {}^{A}T_{B}\,{}^{B}T_{C} = \begin{bmatrix} {}^{A}R_{B}\,{}^{B}R_{C} & {}^{A}R_{B}\,{}^{B}\mathbf{p}_{C} + {}^{A}\mathbf{p}_{B} \\ \mathbf{0}^\mathsf{T} & 1 \end{bmatrix}\]

The block form shows what happens: rotations multiply, and the translation of C is first rotated into A's orientation and then added to B's offset. A whole robot arm, as lessons 5 and 6 show, is described by a chain of such transforms from the base through each link to the tool: \( {}^{0}T_{6} = {}^{0}T_{1}\,{}^{1}T_{2} \cdots {}^{5}T_{6} \). A mobile manipulator adds the robot's pose in the map at the front of the chain, and a camera adds its mounting transform at the end.

As with rotations, the order of multiplication encodes whether a motion is described in the fixed frame or the moving frame. Post-multiplying, \( T\,T_{\text{motion}} \), applies the motion relative to the current, moving frame: 'move 10 cm along the tool's own z-axis'. Pre-multiplying, \( T_{\text{motion}}\,T \), applies it relative to the fixed frame: 'move 10 cm up in the world'. Industrial robot pendants offer exactly these two jog modes, usually called tool and world (or base) coordinates.

A diagram of four frames, labeled map, base, wrist and camera, drawn as small axis triads at different positions and orientations. Curved arrows connect map to base, base to wrist, and wrist to camera, each labeled with its transform. A longer dashed arrow from map directly to camera is labeled as the product of the three transforms.
Chaining transforms: the camera pose in the map is the product of the transforms along the chain, with inner frame labels canceling.

The inverse transform

Inverting a transform reverses the direction of description: \( {}^{B}T_{A} = ({}^{A}T_{B})^{-1} \). Because the rotation part is orthonormal, the inverse has a closed form that is cheaper and more accurate than a general 4 × 4 inverse:

\[({}^{A}T_{B})^{-1} = \begin{bmatrix} {}^{A}R_{B}^\mathsf{T} & -{}^{A}R_{B}^\mathsf{T}\,{}^{A}\mathbf{p}_{B} \\ \mathbf{0}^\mathsf{T} & 1 \end{bmatrix}\]

The translation part is not simply \( -\mathbf{p} \). It must be rotated, because the offset from B back to A has to be expressed in B's axes. Forgetting this rotation is the single most common transform bug; it produces results that look right when the rotation is close to the identity and wrong otherwise, so it can survive simple tests.

Worked problem

Where is the robot base as seen from the camera?

A fixed camera above a work cell has pose \( {}^{B}T_{C} \) relative to the robot base, with rotation \( R_z(90^\circ) \) and position \( (1.0, 0.5, 2.0) \) m. Find the position of the base origin in the camera frame.

Show solution
  1. \( R = R_z(90^\circ) = \begin{bmatrix} 0&-1&0\\1&0&0\\0&0&1 \end{bmatrix} \), so \( R^\mathsf{T} = \begin{bmatrix} 0&1&0\\-1&0&0\\0&0&1 \end{bmatrix} \).
  2. \( R^\mathsf{T}\mathbf{p} = (0.5, -1.0, 2.0) \).
  3. The inverse translation is \( -R^\mathsf{T}\mathbf{p} = (-0.5, 1.0, -2.0) \).

Answer: The base origin is at (−0.5, 1.0, −2.0) m in the camera frame. The naive answer, (−1.0, −0.5, −2.0), would be wrong because it ignores the 90° rotation.

SE(3): the group of rigid-body motions

Homogeneous transforms with a rotation in SO(3) and any translation form the special Euclidean group SE(3). Like SO(3), it is closed under multiplication and inversion, and every element preserves distances and angles: a rigid-body motion moves an object without stretching, shearing or mirroring it. An element of SE(3) has six degrees of freedom, three for rotation and three for translation, even though the matrix has sixteen entries. The planar version, SE(2), uses 3 × 3 matrices with a 2-D rotation and a 2-D translation and is the natural language for mobile robots on flat ground:

\[T_{SE(2)} = \begin{bmatrix} \cos\theta & -\sin\theta & x \\ \sin\theta & \cos\theta & y \\ 0 & 0 & 1 \end{bmatrix}\]

Seeing poses as elements of a group is more than tidy mathematics. It explains why poses should not be averaged or interpolated component by component, why errors in pose estimation are best described in a local tangent space, and why the exponential map of lesson 7 is the right tool for integrating velocities into poses.

Everyday operations with homogeneous transforms.
OperationFormulaCostCommon bug
Change frame of a point\( {}^{A}\tilde{\mathbf{p}} = {}^{A}T_{B}\,{}^{B}\tilde{\mathbf{p}} \)12 multiplicationsUsing w = 0 for a point
Change frame of a vectorSame with w = 0, or \( R\mathbf{v} \)9 multiplicationsAdding the translation to a velocity
Compose\( {}^{A}T_{C} = {}^{A}T_{B}\,{}^{B}T_{C} \)36 multiplications (exploiting structure)Wrong multiplication order
Invert\( [R^\mathsf{T},\; -R^\mathsf{T}\mathbf{p}] \)9 multiplicationsUsing \( -\mathbf{p} \) without rotating
Relative pose\( {}^{B}T_{C} = ({}^{A}T_{B})^{-1}\,{}^{A}T_{C} \)Invert plus composeInverting the wrong transform

Relative poses and the hand-eye problem

Many practical calculations ask for the transform between two frames that are both known relative to a third. If a motion-capture system reports the poses of a robot base and a target in its own frame, \( {}^{M}T_{B} \) and \( {}^{M}T_{G} \), the target relative to the robot is \( {}^{B}T_{G} = ({}^{M}T_{B})^{-1}\,{}^{M}T_{G} \). The pattern is always the same: invert the transform that has the wanted frame on the wrong side, then multiply so that the labels cancel.

A famous version is hand-eye calibration. A camera is mounted on a robot's wrist, and we need the fixed but unknown transform X from the wrist to the camera. Moving the robot between poses and observing a fixed calibration target from each gives equations of the form \( A X = X B \), where A is the known wrist motion from the robot's forward kinematics and B is the camera motion measured from the target. Several motions with different rotation axes determine X. Libraries such as OpenCV's calibrateHandEye solve it; the quality of the result depends on choosing varied, well-separated poses.

Transforms in code

In software, transforms are usually stored as 4 × 4 arrays, or as a quaternion plus a translation vector in messages such as geometry_msgs/TransformStamped. The listing builds the transforms from the camera example, composes and inverts them, and checks the closed-form inverse against NumPy's general inverse.

Composing and inverting homogeneous transforms
import numpy as np
np.set_printoptions(precision=3, suppress=True)
def Rz(t): c, s = np.cos(t), np.sin(t); return np.array([[c,-s,0],[s,c,0],[0,0,1]])
def Rx(t): c, s = np.cos(t), np.sin(t); return np.array([[1,0,0],[0,c,-s],[0,s,c]])
def T(R, p): M = np.eye(4); M[:3,:3] = R; M[:3,3] = p; return M
def inv(M):
    R, p = M[:3,:3], M[:3,3]
    return T(R.T, -R.T @ p)

T_B_W = T(Rz(np.radians(45)), [0.4, 0.0, 0.6])       # wrist in base
T_W_C = T(Rx(np.pi), [0.05, 0.0, 0.10])              # camera in wrist
p_C = np.array([0.02, -0.01, 0.30, 1.0])             # object seen by camera
p_B = T_B_W @ T_W_C @ p_C
print("object in base:", p_B[:3])
print("closed-form inverse matches:", np.allclose(inv(T_B_W), np.linalg.inv(T_B_W)))
print("naive inverse translation:  ", -T_B_W[:3,3])
print("correct inverse translation:", inv(T_B_W)[:3,3])
Output
object in base: [0.442 0.057 0.4  ]
closed-form inverse matches: True
naive inverse translation:   [-0.4 -0.  -0.6]
correct inverse translation: [-0.283  0.283 -0.6  ]

Worked problem

Jogging in tool versus world coordinates

A tool has pose \( {}^{B}T_{E} \) with rotation \( R_y(90^\circ) \) and position \( (0.5, 0, 0.4) \) m. Find the new tool position after a 0.1 m move along z (a) in tool coordinates and (b) in base coordinates.

Show solution
  1. \( R_y(90^\circ) = \begin{bmatrix} 0&0&1\\0&1&0\\-1&0&0 \end{bmatrix} \), whose third column, the tool z-axis in the base frame, is \( (1, 0, 0) \).
  2. (a) Post-multiply by a translation of \( (0,0,0.1) \): the position becomes \( \mathbf{p} + R(0,0,0.1) = (0.5 + 0.1, 0, 0.4) = (0.6, 0, 0.4) \).
  3. (b) Pre-multiply: the position becomes \( (0.5, 0, 0.4 + 0.1) = (0.5, 0, 0.5) \).

Answer: In tool coordinates the tool moves forward along its own z-axis, which points along base x, to (0.6, 0, 0.4); in base coordinates it moves straight up to (0.5, 0, 0.5). The orientation is unchanged in both cases.

Good habits

Name every transform with both frames, such as T_base_cam, and write the composition so the inner names match. Store frame names with data in messages and logs, as tf2 does with frame_id and child_frame_id. Check transforms visually in RViz by displaying axis triads, because a flipped axis is obvious in a picture and invisible in a table of numbers. Test round trips: transforming a point forward and back with the inverse should reproduce it to machine precision. Finally, be careful when reading other people's conventions. Some libraries store the transform from parent to child, others from child to parent, and the words 'from' and 'to' are used inconsistently. ROS tf2 lookups, for example, take a target frame and a source frame and return the transform that converts data from the source frame into the target frame.

Common mistakes

  • MistakeInverting a transform by negating its translation.

    InsteadUse \( -R^\mathsf{T}\mathbf{p} \) for the inverse translation.

  • MistakeApplying a full transform, including translation, to a velocity or direction.

    InsteadUse a fourth coordinate of 0 for vectors, or rotate them only.

  • MistakeMultiplying transforms with mismatched frame labels.

    InsteadWrite \( {}^{A}T_{B}\,{}^{B}T_{C} \) so inner labels match; name variables T_parent_child.

  • MistakeConfusing tool-frame and world-frame motions.

    InsteadPost-multiply for motions in the moving frame; pre-multiply for motions in the fixed frame.

  • MistakeAveraging poses component by component.

    InsteadTreat poses as elements of SE(3); average rotations properly, for example with quaternions.

Summary and key terms

  • A homogeneous transform packs rotation R and translation p into a 4 × 4 matrix.
  • Points use a fourth coordinate of 1 and free vectors 0, so one matrix handles both correctly.
  • Chaining frames is matrix multiplication with inner frame labels canceling.
  • The inverse is \( [R^\mathsf{T}, -R^\mathsf{T}\mathbf{p}] \), not simply a negated translation.
  • Post-multiplication applies motions in the moving frame; pre-multiplication in the fixed frame.
  • Rigid-body motions form the group SE(3), and planar motions SE(2).
  • Relative poses and hand-eye calibration follow from inverting and composing known transforms.
Pose
The position and orientation of a frame or body.
Homogeneous coordinates
Coordinates with an extra fourth entry, 1 for points and 0 for vectors.
Homogeneous transform
A 4 × 4 matrix combining a rotation and a translation.
Affine map
A linear map followed by a translation.
Composition
Chaining transforms by multiplication.
SE(3)
The group of rigid-body motions in three dimensions.
SE(2)
The group of rigid-body motions in the plane.
Relative pose
The pose of one frame expressed in another, found by inverting and composing.
Hand-eye calibration
Finding the fixed transform between a robot's wrist and a mounted camera.
Tool coordinates
Motions described relative to the tool's own frame.

Practice problems

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

  1. Write the homogeneous coordinates of the point (2, 3, 4) and of the direction (0, 0, 1).

    Show answer

    (2, 3, 4, 1) and (0, 0, 1, 0).

  2. A transform has R = I and p = (1, 2, 3). Where does it send the point (1, 1, 1)?

    Show answer

    (2, 3, 4).

  3. Where does the same transform send the direction (1, 1, 1)?

    Show answer

    (1, 1, 1); translation does not affect directions.

  4. Invert the transform with R = I and p = (1, 2, 3).

    Show answer

    R = I, p = (−1, −2, −3); with no rotation the naive negation is correct.

  5. Invert the transform with \( R = R_z(180^\circ) \) and p = (1, 0, 0).

    Show answer

    \( R^\mathsf{T} = R_z(180^\circ) \); \( -R^\mathsf{T}\mathbf{p} = (1, 0, 0) \).

  6. How many DOF does an element of SE(3) have?

    Show answer

    Six.

  7. Write \( {}^{B}T_{G} \) given \( {}^{M}T_{B} \) and \( {}^{M}T_{G} \).

    Show answer

    \( ({}^{M}T_{B})^{-1}\,{}^{M}T_{G} \).

  8. A robot at (2, 1) facing 90° in SE(2) sees a point 1 m straight ahead. Where is it in the map?

    Show answer

    (2, 2).

  9. Which multiplication order moves a tool along its own axis?

    Show answer

    Post-multiplication, T times the motion.

  10. What equation does hand-eye calibration solve?

    Show answer

    \( AX = XB \).

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz