Robot statics: turn tool loads into holding torques

Use virtual work and a Jacobian transpose to calculate a robot arm's joint loads. Distinguish external and holding torque, check space and body frames, and interpret zero-torque loads.

By 14 min read

What you will learn

  • Derive a generalized joint load from virtual work and a Jacobian transpose.
  • Keep environment-on-robot loads separate from ideal holding actuator torques.
  • Combine a tool-point force with an added free couple.
  • Obtain the same joint torques from consistent space and body representations.
  • Explain why zero joint torque does not imply zero structural loading.

Before you start

A robot can hold its tool still while its motors produce torque. Robot statics connects the load at that tool to the effort required at the joints. The central calculation uses the transpose of a velocity Jacobian.

The calculation becomes easier to check when three choices stay explicit: who applies the force, where its moment is measured, and which velocity the Jacobian describes. We will use a two-link arm to make each choice visible.

Define the load and the static model

Fix a planar arm's shoulder at the space-frame origin. Space x points right, y points up, and z points out of the page. Positive joint angles and torques are counterclockwise about +z. The first link is 2 m long; the second is 1 m long. Shoulder angle θ₁ is measured from space +x. Elbow angle θ₂ is relative to the first link.

The tool frame sits at the tip, with its x axis along the second link. Its space orientation is φ = θ₁ + θ₂. We use radians in derivatives, metres for position, newtons for force, and newton metres for torque.

Throughout this lesson, F means a load applied by the environment to the robot. Its generalized joint load is τ_ext. An ideal actuator holding that load supplies τ_hold:

τ_ext = JᵀF
τ_hold + τ_ext = 0
τ_hold = −JᵀF

This model assumes rigid links, a fixed base and ideal joints. We omit gravity, friction, inertia and other applied loads. Real static equilibrium requires both net force and net moment to balance, including support reactions, as described in OpenStax's conditions for static equilibrium. The joint calculation alone does not list every internal force or base reaction.

Derive the Jacobian transpose from work

Write the joint coordinates as q = (θ₁, θ₂). Imagine a small, kinematically allowed change δq at the current posture. This virtual displacement tests how the applied load would do work; it does not assert that the held robot actually moves.

For a point task, δp = J_p δq and a force f does work fᵀδp. Substitution gives:

δW = fᵀδp
δW = fᵀJ_p δq
δW = (J_pᵀf)ᵀδq
τ_ext = J_pᵀf

The equality must hold for every virtual joint displacement. Each component of J_pᵀf is therefore the generalized force paired with that joint coordinate. Revolute coordinates give torques; prismatic coordinates give forces.

The same reasoning works with a complete rigid-body twist and its matching wrench. Their dot product is power, so FᵀJq̇ = (JᵀF)ᵀq̇. This is the power argument used in Modern Robotics' statics derivation. That source calls the applied disturbance −F and writes the opposing actuator torque as JᵀF. Our applied-load convention produces the minus sign in τ_hold above.

For a held arm the actual q̇ is zero. Evaluating the identity at a hypothetical nonzero rate remains a useful check; it is not a simulation of motion caused by the load.

Apply a force and a free couple at the tool

Let the tool origin be p = (pₓ, pᵧ), and let f = (fₓ, fᵧ) be the force there, expressed in fixed space axes. Add a free couple m_z about +z. A couple is a pure moment; it can do rotational work without a net force.

The planar geometric tool Jacobian maps joint rates to angular rate and tool-point velocity:

J_g =
[1, 1;
−pᵧ, −L₂ sin φ;
pₓ, L₂ cos φ]
(φ̇, ṗₓ, ṗᵧ) = J_g q̇

Pair those rows with the load F_tool = (m_z, fₓ, fᵧ). Here “tool” identifies the moment's reference point, while the force components still use space directions. The resulting formula is:

τ_ext = J_gᵀF_tool
τ_ext = J_pᵀf + (m_z, m_z)

Both joint angles contribute one-for-one to φ, so a pure tool couple contributes the same generalized torque to both joints. A position-only Jacobian would omit that rotational work.

There is also a direct geometric check. Let e be the elbow's position. The shoulder's force lever arm is p; the elbow's is p − e. Using the cross product's moment formula:

τ_ext,1 = pₓfᵧ − pᵧfₓ + m_z
τ_ext,2 = (pₓ − eₓ)fᵧ − (pᵧ − eᵧ)fₓ + m_z

Calculate two holding torques

Choose θ₁ = π/2 and θ₂ = −π/2. The elbow is at (0, 2) m and the tool is at (1, 2) m, with φ = 0. Apply a downward force f = (0, −2) N and a counterclockwise couple m_z = 0.5 N·m.

The force has a 1 m horizontal lever arm about either joint, giving −2 N·m at each. The added couple contributes +0.5 N·m to each:

τ_ext = (−1.5, −1.5) N·m
τ_hold = (1.5, 1.5) N·m

The Jacobian at this posture provides the same result:

J_g =
[1, 1;
−2, 0;
1, 1]
F_tool = (0.5, 0, −2)

Now test virtual rates q̇ = (0.5, −0.25) rad/s. The instantaneous tool quantities would be φ̇ = 0.25 rad/s and ṗ = (−1, 0.25) m/s. Load virtual power is 0.5(0.25) + 0(−1) − 2(0.25) = −0.375 W. Joint virtual power is −1.5(0.5) − 1.5(−0.25) = −0.375 W.

Switching only the force to (−2, 0) N changes the lever arms. The shoulder receives 4 N·m from the force; the elbow receives zero. With the same couple, external torques become (4.5, 0.5) N·m, so holding torques are (−4.5, −0.5) N·m.

Change the posture and applied load

The experiment calculates the load from the geometric tool Jacobian and independently checks matching space and body formulations. Force controls always refer to fixed space axes. Torque pairs list shoulder first, elbow second.

Environment-on-robot load

Balance a tool force and a free couple

Link lengths are 2 m and 1 m. The environment applies the selected load at the tool. Ideal holding torque cancels its generalized joint torque, with gravity, friction and inertia omitted.

90
-90
0.00
-2.00
0.50

Force components use the fixed space axes. Torque pairs list the shoulder first and elbow second. Positive joint torque and a positive tool couple act counterclockwise about +z, out of the page. The couple is an added pure moment; its value appears in the control and is separate from the drawn force.

A planar arm with an external force at its toolThe shoulder is at the space origin, elbow at (0.000000, 2.000000) metres and tool at (1.000000, 2.000000) metres. Equal-scale axes use metres. The blue force arrow represents (0.000000, -2.000000) newtons, using display scale 0.4 metres per newton. The added tool couple is 0.50 newton metres. External joint torques are (-1.500000, -1.500000) newton metres, and holding torques are (1.500000, 1.500000) newton metres.-0.8-1.31.20.73.22.7xy
Space x points right and y points up, in metres with equal scales. Amber links join the shoulder square, elbow ring and tool dot. Black tool x is solid and tool y is dashed, each with display length 0.35 m. The blue force uses 0.4 m of display length per newton; an open blue ring means zero force. This arrow scale does not describe a displacement. Plot bounds follow the arm and force arrow.

Virtual-work check: use hypothetical joint rates (0.500000, -0.250000) rad/s at this posture. These rates test the power identity. The actual arm stays still, so its actual mechanical power is zero.

Tool position p (m)
(1.000000, 2.000000)
External joint torques (N·m)
(-1.500000, -1.500000)
Ideal holding torques (N·m)
(1.500000, 1.500000)
Space-wrench moment (N·m)
-1.500000
Body-frame force (N)
(0.000000, -2.000000)
Space-form joint torques (N·m)
(-1.500000, -1.500000)
Body-form joint torques (N·m)
(-1.500000, -1.500000)
Frame agreement error (N·m)
0.000000
Virtual tool-point velocity (m/s)
(-1.000000, 0.250000)
Virtual angular velocity (rad/s)
0.250000
Load virtual power (W)
-0.375000
Joint virtual power (W)
-0.375000
Virtual power error (W)
0.000000
Geometric tool Jacobian: (angle rate, space-frame point velocity) from joint rates
OutputJoint 1Joint 2
φ̇1.0001.000
ṗₓ-2.0000.000
ṗᵧ1.0001.000

Each ideal holding torque is the negative of its external joint torque. The space and body calculations give the same generalized load.

The first Jacobian row uses rad/rad; the point rows use m/rad. Space and body torque readouts pair each Jacobian with a wrench at its own reference origin. Frame error is the larger Euclidean torque difference from the point-based calculation. Displayed zeros can hide roundoff.

Compare the downward and leftward presets before changing the joint angles. Select Pure tool couple to see equal joint loads with no force arrow. Then compare the two straight-arm presets: an axial force produces zero joint torque, while the downward force requires holding torques of (6, 2) N·m.

The metre grid uses equal scales. The blue arrow uses a stated display scale of 0.4 m per newton so force direction and magnitude can share the drawing with the arm. It represents a force, not a predicted displacement. The couple has its own numeric value.

The virtual-rate pair stays fixed as the posture changes. Its power readouts check the algebra at each posture. Holding the actual arm still gives zero mechanical power, although a real motor may still consume electrical power and produce heat.

Match each wrench to its Jacobian

The space and body Jacobians lesson distinguishes a spatial twist's linear component v_s from the velocity of the tool origin. In the plane, ṗ = v_s + ω × p, with ω along z.

A force applied at p has a moment about the space origin. The complete planar space wrench is:

m_s = m_z + pₓfᵧ − pᵧfₓ
F_s = (m_s, fₓ, fᵧ)

Pair F_s with J_s. For the worked posture:

J_s =
[1, 1;
0, 2;
0, 0]
F_s = (−1.5, 0, −2)
J_sᵀF_s = (−1.5, −1.5)

Pairing J_s with (0.5, 0, −2) would incorrectly give (0.5, 0.5). That combination uses a moment about the tool alongside a velocity representation referenced to the space origin.

For the body frame at the tool, the moment is m_z and the force becomes Rᵀf. Thus F_b = (m_z, Rᵀf). If T maps body coordinates into space coordinates, the dual transformations are J_b = Ad_(T⁻¹)J_s and F_b = Ad_TᵀF_s. They preserve J_bᵀF_b = J_sᵀF_s. Review wrench transformations for how the reference-point shift enters this relation; Modern Robotics develops the same power-invariant wrench transformation.

At the worked posture R is identity, so F_b = (0.5, 0, −2), and J_b equals J_g numerically. The nonzero tool offset still makes J_s and F_s different. Shared axis directions do not imply shared moment origins.

Interpret a load with zero joint torque

Straighten both joints: θ₁ = θ₂ = 0 and p = (3, 0) m. A force (−2, 0) N lies along both links. With no couple, its moment about either joint is zero, so τ_ext = (0, 0).

The links can still carry compression, and the fixed base must supply a reaction. Zero generalized joint torque does not mean zero stress, unlimited load capacity, or structural safety. Link stiffness, buckling, bearings and supports require their own analysis.

The point-position Jacobian has rank one here: every instantaneous tip velocity is vertical. The axial force is orthogonal to those allowed point velocities, so it does no first-order virtual work. This is a null-space relation for J_pᵀ.

The complete planar pose Jacobian still has two independent columns for this arm. For example, q̇ = (0.25, −0.75) rad/s gives ṗ = (0, 0) at the straight posture but φ̇ = −0.5 rad/s. A pure couple can do virtual work along that joint direction even though a point force cannot. A singularity statement must identify the task and its Jacobian.

This is an instantaneous statement at one posture. It does not promise that a finite joint motion keeps the tool point fixed.

Separate ideal statics from a complete robot model

The transpose maps a specified external load into generalized joint loads. It does not calculate the force that an arbitrary motor command will actually create in contact. That problem also depends on contact constraints, compliance, friction and the controller.

Gravity adds loads even when the tool is empty. Accelerating links adds inertial terms. Actuator limits, gearing and joint friction affect what holding effort is available. Estimating these effects is necessary before using the ideal result to size hardware or command a real system.

The robot dynamics lesson builds these terms for a two-joint arm with distributed link mass. Its torque budget shows how inertia, velocity coupling, gravity, and viscous joint friction contribute to the required actuator effort.

The transpose also appears when differentiating a scalar loss through a robot's forward kinematics: if a loss depends on p, its joint gradient is J_pᵀ∇ₚloss. This is the same multivariate chain-rule structure, discussed in Jacobian matrices. A learned loss gradient becomes a physical force only when its interpretation and units justify that choice.

Reproduce the calculation in Python

This Python 3 example uses only the standard library. It checks direct lever-arm torques against both the geometric tool and space-wrench calculations. Its virtual rates match the experiment.

from math import cos, sin, radians


def transpose_times(j, load):
    return tuple(sum(j[row][col] * load[row] for row in range(3))
                 for col in range(2))


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


def check(name, degrees1, degrees2, fx, fy, couple):
    q1, q2 = radians(degrees1), radians(degrees2)
    ex, ey = 2*cos(q1), 2*sin(q1)
    c, s = cos(q1+q2), sin(q1+q2)
    px, py = ex+c, ey+s
    jg = ((1, 1), (-py, -s), (px, c))
    js = ((1, 1), (0, ey), (0, -ex))
    tool_load = (couple, fx, fy)
    space_load = (couple+px*fy-py*fx, fx, fy)
    external = transpose_times(jg, tool_load)
    space_result = transpose_times(js, space_load)
    direct = (px*fy-py*fx+couple,
              (px-ex)*fy-(py-ey)*fx+couple)
    for candidate in (space_result, direct):
        assert max(abs(a-b) for a, b in zip(external, candidate)) < 1e-12
    rates = (0.5, -0.25)  # Hypothetical, for the virtual-power check.
    velocity = tuple(sum(row[i]*rates[i] for i in range(2)) for row in jg)
    load_power = sum(a*b for a, b in zip(tool_load, velocity))
    joint_power = sum(a*b for a, b in zip(external, rates))
    assert abs(load_power-joint_power) < 1e-12
    print(name)
    print('Tool position (m):', pair((px, py)))
    print('External torques (N m):', pair(external))
    print('Holding torques (N m):', pair(tuple(-x for x in external)))
    print('Load / joint virtual power (W):', pair((load_power, joint_power)))


check('Downward force and couple', 90, -90, 0, -2, 0.5)
check('Leftward force and couple', 90, -90, -2, 0, 0.5)
check('Straight arm, axial force', 0, 0, -2, 0, 0)

Expected output:

Downward force and couple
Tool position (m): (1.000000, 2.000000)
External torques (N m): (-1.500000, -1.500000)
Holding torques (N m): (1.500000, 1.500000)
Load / joint virtual power (W): (-0.375000, -0.375000)
Leftward force and couple
Tool position (m): (1.000000, 2.000000)
External torques (N m): (4.500000, 0.500000)
Holding torques (N m): (-4.500000, -0.500000)
Load / joint virtual power (W): (2.125000, 2.125000)
Straight arm, axial force
Tool position (m): (3.000000, 0.000000)
External torques (N m): (0.000000, 0.000000)
Holding torques (N m): (0.000000, 0.000000)
Load / joint virtual power (W): (0.000000, 0.000000)

The input cases use finite values in the ideal planar model. The assertions allow small floating-point errors; printing six decimals does not make the underlying calculations exact.

Try it yourself

Exercise 1. At θ₁ = π/2 and θ₂ = −π/2, apply f = (1, −1) N and m_z = −0.25 N·m. Find the external and ideal holding torques. Check load virtual power with q̇ = (0.5, −0.25) rad/s.

Show the diagonal-load solution

The shoulder lever arm is (1, 2) m. Its force moment is 1(−1) − 2(1) = −3 N·m. The elbow lever arm is (1, 0) m, giving −1 N·m. Adding the couple gives τ_ext = (−3.25, −1.25) N·m and τ_hold = (3.25, 1.25) N·m.

At these virtual rates, ṗ = (−1, 0.25) m/s and φ̇ = 0.25 rad/s. Load power is 1(−1) − 1(0.25) − 0.25(0.25) = −1.3125 W. The joint check is −3.25(0.5) − 1.25(−0.25) = −1.3125 W.

Exercise 2. Straighten the arm and apply f = (−2, 0) N with a couple of +0.5 N·m. Find the holding torques. For virtual rates (0.25, −0.75) rad/s, why does zero tool-point velocity coexist with nonzero load virtual power?

Show the straight-arm couple solution

The axial force has zero moment about either joint. The couple contributes τ_ext = (0.5, 0.5) N·m, requiring τ_hold = (−0.5, −0.5) N·m.

At the straight posture, the point Jacobian has rows (0, 0) and (3, 1). Therefore ṗᵧ = 3(0.25) − 0.75 = 0 and ṗₓ = 0. The tool still has angular rate φ̇ = 0.25 − 0.75 = −0.5 rad/s. The couple's virtual power is 0.5(−0.5) = −0.25 W, matching 0.5(0.25) + 0.5(−0.75) at the joints.

Removing the couple makes both generalized torques zero. The axial force still loads the links and fixed support. The position-only null direction says nothing about eliminating those reaction loads.

Sources and further study