Product of exponentials: build a robot arm’s forward kinematics

Build a two-joint arm's tool pose from fixed home screw axes and matrix exponentials. Check the result against geometry, inspect multiplication order, and connect space and body formulas.

By 14 min read

What you will learn

  • Record joint screw axes and the tool pose in one consistent home configuration.
  • Compute a planar arm's pose by multiplying joint matrix exponentials.
  • Check position and orientation with an independent geometric calculation.
  • Explain factor order and distinguish home axes from current joint axes.
  • Relate the space and body forms through a change of coordinates.

Before you start

Joint angles describe how a robot bends. Forward kinematics turns those angles into a tool position and orientation. The product of exponentials, or PoE, builds that map from each joint's screw axis and one home tool pose.

We will derive the formula for a two-link arm. Its geometry gives an independent check, so a wrong axis sign or multiplication order has a visible consequence.

Define the arm and its tool frame

Fix the shoulder at the origin of the space frame. Space x points right, y points up, and z points out of the page. Both revolute joints turn counterclockwise for positive angles, following the right-hand rule about +z.

  • The first link has length L₁ and shoulder angle θ₁.
  • The second link has length L₂ and elbow angle θ₂ relative to the first link.
  • The tool frame sits at the second link's tip, with its x axis along that link.

The home configuration sets both joint angles to zero. Both links point along space +x, and the tool axes align with the space axes. Link lengths and positions use metres; the equations use angles in radians.

We use column vectors. T = T_ST maps tool-frame coordinates into space-frame coordinates, as in the homogeneous transformations lesson. Its planar 3 × 3 form contains a 2 × 2 rotation, a two-coordinate translation, and bottom row (0, 0, 1).

Record the home screw axes

In three dimensions, a zero-pitch revolute screw has angular-first coordinates S = (ω, v), with unit axis direction ω and v = −ω × a. Here a is any point on the axis, expressed in the same frame. The twists and screw axes lesson explains the linear component's meaning.

For our home arm, choose a₁ = (0, 0, 0) and a₂ = (L₁, 0, 0). Both angular directions are (0, 0, 1), giving:

S₁ = (0, 0, 1; 0, 0, 0)
S₂ = (0, 0, 1; 0, −L₁, 0)

The semicolon separates angular and linear parts. At a positive unit angular rate, rotation around the second axis sends the space origin downward, which checks the minus sign in S₂.

For these revolute joints, θᵢ is angular displacement and Sᵢθ̇ᵢ has angular and linear velocity components. Keeping “rad” in rad/s helps track units, although radians are dimensionless in SI. A prismatic joint uses a different normalization: zero angular part, unit translation direction, and a joint variable measured in length.

All home screw axes stay in the same fixed space frame. Modern Robotics defines the space-form construction using joint axes at the zero configuration.

Exponentiate one revolute joint

For planar rotation about a = (aₓ, aᵧ), the reduced screw coordinates are (1, aᵧ, −aₓ). Their matrix form is:

[S] =
[0, −1, aᵧ;
1, 0, −aₓ;
0, 0, 0]

The matrix exponential E(θ) = exp([S]θ) follows this constant screw through angle θ. For this pure rotation, we can evaluate it directly: rotate a point's offset from a, then add a back.

x′ = a + R(θ)(x − a)
E(θ) = [R(θ), (I − R(θ))a; 0, 1]

Thus E keeps a fixed and rotates every offset around it. Writing c = cos θ and s = sin θ gives the full planar matrix:

E =
[c, −s, aₓ(1 − c) + aᵧs;
s, c, aᵧ(1 − c) − aₓs;
0, 0, 1]

This closed form evaluates the matrix exponential, including its translation. Applying a scalar exponential to each entry would produce a different operation. Modern Robotics develops the rigid-motion exponential from a constant screw; the planar exponential-map lesson derives the general rotation-translation coupling.

Build the complete forward map

The home tool pose is M = T(0, 0). Our chosen tool frame gives:

M =
[1, 0, L₁ + L₂;
0, 1, 0;
0, 0, 1]
E₁ = exp([S₁]θ₁)
E₂ = exp([S₂]θ₂)
T(θ₁, θ₂) = E₁E₂M

At zero joint angles, both exponentials equal identity, so T = M. Omitting M would put the home tool at the space origin and lose its home orientation and offset. Here L₂ enters through M, while L₁ enters through both M and S₂.

For this arm, multiplying the matrices yields the familiar geometric result:

pₓ = L₁ cos θ₁ + L₂ cos(θ₁ + θ₂)
pᵧ = L₁ sin θ₁ + L₂ sin(θ₁ + θ₂)
R_tool = R(θ₁ + θ₂)

For a serial chain with n joints, the space form extends to T = exp([S₁]θ₁) ⋯ exp([Sₙ]θₙ)M. Spatial arms use 4 × 4 transforms and six-coordinate screws. This planar example retains only x, y and rotation about z.

Multiply a concrete example

Take L₁ = 2 m, L₂ = 1 m, θ₁ = π/2 and θ₂ = −π/2. The first link points up. The second link's space angle is zero, so it points right from the elbow at (0, 2) m.

The shoulder exponential rotates about the origin. The elbow exponential rotates clockwise about its home point (2, 0) m:

E₁ =
[0, −1, 0;
1, 0, 0;
0, 0, 1]
E₂ =
[0, 1, 2;
−1, 0, 2;
0, 0, 1]

Apply the product to the tool origin. M first places that origin at (3, 0). E₂ takes it to (2, −1), and E₁ takes that point to (1, 2) m.

The two rotation blocks multiply to identity. The complete tool pose is therefore:

T =
[1, 0, 1;
0, 1, 2;
0, 0, 1]

Trigonometry checks both outputs: p = (2 cos(π/2) + cos 0, 2 sin(π/2) + sin 0) = (1, 2), and θ₁ + θ₂ = 0. Checking position alone would miss an incorrect tool orientation.

Change the joints and arm geometry

The experiment multiplies the two closed-form exponentials and M. It separately evaluates the link-vector formula for comparison. Both calculations use floating-point arithmetic.

Two fixed home screw axes

Build the tool pose from joint exponentials

T = E₁E₂M maps tool coordinates to the fixed space frame. The second joint angle is relative to the first link. Positive angles turn counterclockwise.

90
-90
2.00
1.00
  • Gray dashes: home arm
  • Amber links: current arm
  • Blue ring: reversed product
Home arm, current arm, and tool frame in fixed space coordinatesSpace x points right and y points up, in metres with equal scales. The shoulder stays at the origin. The elbow is at (0.000000, 2.000000), and the tool is at (1.000000, 2.000000). The dashed home arm extends to (3.000000, 0.000000). Black tool-axis arrows show orientation. A blue ring at (5.000000, 2.000000) shows the result of swapping the fixed-axis factors.-1.8-0.51.22.54.25.5xy
All positions use metres in the fixed space frame, with equal horizontal and vertical scales. The square marks the shoulder. Tool x uses a solid black arrow; tool y uses dashes. Each arrow has display length 0.35 m. Plot bounds follow the visible geometry; overlapping markers remain distinct in the numeric readouts.
PoE tip in space (m)
(1.000000, 2.000000)
Trig tip in space (m)
(1.000000, 2.000000)
Tool x direction in space
(1.000000, 0.000000)
Tool y direction in space
(0.000000, 1.000000)
Joint-angle sum (degrees)
0.000
Position agreement error (m)
0.000000
Rotation agreement error
0.000000
Reversed-product tip (m)
(5.000000, 2.000000)
Reversal separation (m)
4.000000
Home tool pose M
1.0000.0003.000
0.0001.0000.000
0.0000.0001.000
Shoulder exponential E₁
0.000-1.0000.000
1.0000.0000.000
0.0000.0001.000
Home-elbow exponential E₂
0.0001.0002.000
-1.0000.0002.000
0.0000.0001.000
Tool pose T = E₁E₂M
1.0000.0001.000
0.0001.0002.000
0.0000.0001.000

Reversing the fixed-axis factors changes the endpoint. Both products have the same planar orientation, because their rotation angles add, but the translations differ.

Changing a length defines a different arm and updates its home axes and M. Changing an angle keeps that geometry fixed. Position error compares PoE with independent trigonometry; rotation error is the Frobenius norm of the rotation-block difference. The joint-angle sum keeps full turns visible. Displayed zeros can hide floating-point roundoff.

Start with Shoulder only and Elbow only. In the first case the full arm rotates about the origin; in the second, the elbow stays at (L₁, 0). Then return to the worked example and compare the reversed-product marker.

Changing a link length defines a different robot geometry. The experiment rebuilds the affected home axis and M. Changing an angle preserves those home quantities.

The dashed arm shows the chosen zero configuration. Solid and dashed tool-axis arrows distinguish x and y. Hiding the reversed marker allows the equal-scale plot to focus on the physical arm, while the numeric comparison stays available.

This ideal model assumes rigid links, exact joint locations and a fixed base. It omits collision checks, mechanical joint limits, compliance and motor dynamics. A calculated pose alone does not establish that a real robot can safely reach it.

Keep factor order and axis coordinates straight

For a column vector, the rightmost matrix acts first. In E₁E₂M, M maps tool coordinates into the home space placement; E₂ and then E₁ act on that placement. Matrix-factor order encodes the chain's geometry.

The joint labels still run from shoulder to elbow. The formula does not require the robot to move its elbow first in time. In this ideal arm, any feasible joint trajectory ending at the same (θ₁, θ₂) gives the same pose.

Reversing the fixed-axis factors gives E₂E₁M. In the worked example, E₁ sends the home tip (3, 0) to (0, 3), then E₂ sends it to (5, 2) m. That result lies outside this arm's maximum reach of 3 m.

Both products have zero net angle in this example. Planar rotation matrices commute, but rotations about different centres include translations that generally make the full transforms noncommutative. Special joint settings can still make the two products agree.

The physical elbow axis moves when θ₁ changes. After the shoulder's quarter-turn it passes through (0, 2), but S₂ in the home formula still refers to (2, 0). Inserting the current axis into E₁E₂M counts the upstream coordinate change again and gives the wrong model.

You can use a current axis with a consistent formulation. Its exponential is E₂,current = E₁E₂E₁⁻¹, so E₂,current E₁M = E₁E₂M. The adjoint transformations lesson explains the corresponding change of screw coordinates.

Express the same model in the home tool frame

The body form records each axis in the home tool frame. Its constants satisfy [Bᵢ] = M⁻¹[Sᵢ]M, or Bᵢ = Ad_(M⁻¹)Sᵢ. Conjugating the exponential then gives:

Bᵢ = Ad_(M⁻¹)Sᵢ
T = M exp([B₁]θ₁) exp([B₂]θ₂)

The joint factors retain their 1, 2 order. Modern Robotics presents this home end-effector-frame formula.

Our home tool sits at space x = L₁ + L₂ with aligned axes. In its coordinates, the shoulder lies at (−L₁ − L₂, 0) and the elbow at (−L₂, 0). The planar body screws are therefore B₁ = (1, 0, L₁ + L₂) and B₂ = (1, 0, L₂), using angular-first three-coordinate notation.

For the worked lengths these become (1, 0, 3) and (1, 0, 1). Substituting them into the body formula gives the same complete pose. Keeping the frame and home configuration explicit prevents mixing these positive linear components with the space screws' components.

PoE still needs measured base, axis and tool conventions. A different tool offset changes M; expressing the model in another base frame also changes the space-axis coordinates. Once the forward map is correct, the Jacobian lesson differentiates it to relate joint rates to tip velocity.

The space and body Jacobians lesson continues this same arm model. Build each velocity column from a screw axis, then compare tool-point velocity with the body's full twist.

That derivative also lets an optimizer backpropagate a position loss through kinematics. An accurate geometric model supports this calculation; it does not by itself capture motor effort, contact, or every source of real-world error.

Reproduce the matrix product in Python

This Python 3 example uses only the standard library. It implements the planar revolute exponential and ordinary matrix multiplication, then compares the result with trigonometry. The optional reversed product deliberately swaps the fixed home-axis factors.

from math import cos, sin, radians, hypot


def multiply(a, b):
    return tuple(tuple(sum(a[i][k] * b[k][j] for k in range(3))
                       for j in range(3)) for i in range(3))


def revolute(axis_point, angle):
    x, y = axis_point
    c, s = cos(angle), sin(angle)
    d = 2 * sin(angle / 2) ** 2
    return ((c, -s, d*x + s*y),
            (s, c, d*y - s*x),
            (0, 0, 1))


def pair(values):
    return '(' + ', '.join(
        f'{0.0 if abs(x) < 0.5e-6 else x:.6f}' for x in values
    ) + ')'


def check(l1, l2, degrees1, degrees2):
    a, b = radians(degrees1), radians(degrees2)
    home = ((1, 0, l1+l2), (0, 1, 0), (0, 0, 1))
    e1, e2 = revolute((0, 0), a), revolute((l1, 0), b)
    pose = multiply(multiply(e1, e2), home)
    reverse = multiply(multiply(e2, e1), home)
    tip = (pose[0][2], pose[1][2])
    trig = (l1*cos(a) + l2*cos(a+b), l1*sin(a) + l2*sin(a+b))
    error = hypot(*(x-y for x, y in zip(tip, trig)))
    assert error < 1e-12
    assert hypot(pose[0][0]-cos(a+b), pose[1][0]-sin(a+b)) < 1e-12
    print(f'Angles: ({degrees1}, {degrees2}) degrees')
    print('PoE tip:', pair(tip), 'trig tip:', pair(trig))
    print('Tool x:', pair((pose[0][0], pose[1][0])))
    print('Reversed tip:', pair((reverse[0][2], reverse[1][2])))


check(2, 1, 90, -90)
check(2, 1, 0, 0)
check(1, 1, 0, 180)

Expected output:

Angles: (90, -90) degrees
PoE tip: (1.000000, 2.000000) trig tip: (1.000000, 2.000000)
Tool x: (1.000000, 0.000000)
Reversed tip: (5.000000, 2.000000)
Angles: (0, 0) degrees
PoE tip: (3.000000, 0.000000) trig tip: (3.000000, 0.000000)
Tool x: (1.000000, 0.000000)
Reversed tip: (3.000000, 0.000000)
Angles: (0, 180) degrees
PoE tip: (0.000000, 0.000000) trig tip: (0.000000, 0.000000)
Tool x: (-1.000000, 0.000000)
Reversed tip: (0.000000, 0.000000)

The expression 2 sin²(θ/2) evaluates 1 − cos θ without subtracting nearly equal numbers at tiny angles. Printed zeros still reflect rounding. The example assumes the finite positive lengths and finite angles supplied in its three calls.

Try it yourself

Exercise 1. Let L₁ = 2 m, L₂ = 1 m, θ₁ = 0 and θ₂ = π/2. Find the home tool pose, final tip and tool x direction. Does reversing the two factors change this result?

Show the isolated-elbow solution

The home pose has identity rotation and translation (3, 0) m. E₁ is identity, while E₂ rotates around (2, 0), taking the home tip to (2, 1) m.

The tool x direction is (0, 1) and tool y is (−1, 0). Since E₁ is identity, E₁E₂M and E₂E₁M agree here. This special case gives no permission to exchange the factors for arbitrary joint angles.

Exercise 2. Keep L₁ = 2 m and L₂ = 1 m, but set both angles to π. Calculate the correct tip, tool orientation and reversed-product tip. Why can an angle sum of 2π coexist with a changed tip position?

Show the two-half-turn solution

The first link points left, placing the elbow at (−2, 0) m. The second link points right because θ₁ + θ₂ = 2π, so the correct tip is (−1, 0) m. Its tool rotation is identity.

For the reversed product, E₁ first takes the home tip (3, 0) to (−3, 0). A half-turn about the home elbow (2, 0) takes that point to (7, 0) m, eight metres from the correct tip.

The two joints rotate about different centres. Their total orientation can return to identity while the full rigid transform retains a translation. Neither endpoint computation represents a record of the robot's physical motion over time.

Sources and further study