explainer
Space and body Jacobians: map joint rates to rigid motion
Build space and body Jacobians from joint screw axes, recover the physical tool velocity, and compare their ranks with a position-only task. Explore a planar two-link arm and verify its derivatives in Python.
What you will learn
- Construct Jacobian columns by transforming joint screw axes into the required frame.
- Convert joint rates into space and body twists with an explicit angular-first convention.
- Recover the tool point's physical velocity from either twist representation.
- Explain why a position singularity can coexist with full column rank in a pose Jacobian.
Before you start
Two joint motors set the motion of a robot arm, but the tool has both a position and an orientation. A Jacobian tells us which instantaneous tool motions those joint rates produce.
Space and body Jacobians describe the same rigid motion in different frames. Their linear twist coordinates need careful interpretation: a spatial linear coordinate generally differs from the physical velocity of the tool point. This lesson calculates both representations and shows how the choice of task changes the meaning of a singularity.
Map joint rates to a twist
Let T = T_sb describe the tool frame b in a fixed space frame s. It maps body-coordinate column points into space coordinates. A serial robot has joint coordinates θ = (θ₁, …, θₙ) and current rates θ̇.
Use angular-first twists V = (ω, v). In three dimensions this gives six rows; a planar model keeps (ω_z, vₓ, vᵧ). The two Jacobians satisfy:
V_s = J_s(θ)θ̇
V_b = J_b(θ)θ̇
V̂_s = ṪT⁻¹, V̂_b = T⁻¹Ṫ
Each column answers one question: what twist results when that joint moves at unit rate and the others stop? Multiplying each column by its rate and adding gives the complete twist. Modern Robotics introduces the space Jacobian through these joint contributions.
The arm below has two revolute joints. Its joint rates and angular twist coordinate use rad/s; linear twist coordinates use m/s. The planar twist Jacobians are 3 × 2. Their angular row converts angular rates, while their linear rows carry length per radian.
Build space columns from home screw axes
Let Sᵢ be joint i's screw axis in the space frame at the home configuration. The product-of-exponentials formula is:
T(θ) = exp(Ŝ₁θ₁) ⋯ exp(Ŝₙθₙ) M
Earlier joints move joint i's axis relative to space. Define Pᵢ as the product of their exponentials, in the same order. Then the corresponding Jacobian column is:
Pᵢ = exp(Ŝ₁θ₁) ⋯ exp(Ŝᵢ₋₁θᵢ₋₁)
J_s,i = Ad_(Pᵢ) Sᵢ
J_s,1 = S₁
The adjoint transforms the screw's angular and linear parts together. The first column stays fixed because no joint precedes it. Column i depends on preceding joint coordinates, not on later ones.
For our planar arm, link lengths are L₁ = 2 m and L₂ = 1 m. Both positive joint rotations point along +z. At home, both links lie along +x, so the planar home screws are S₁ = (1, 0, 0) and S₂ = (1, 0, −2).
At shoulder angle θ₁, the elbow axis passes through (2 cos θ₁, 2 sin θ₁). Its normalized linear coordinates are (2 sin θ₁, −2 cos θ₁). Thus:
J_s =
[ 1, 1 ]
[ 0, 2 sin θ₁ ]
[ 0, −2 cos θ₁ ]
This matrix does not depend on the elbow angle θ₂. The physical tip velocity still does, because the tip's location changes with θ₂.
Build body columns and change frames
Let Bᵢ describe each home screw in the home tool frame. The body form of forward kinematics is T = M exp(B̂₁θ₁) ⋯ exp(B̂ₙθₙ). To build body column i, express Bᵢ in the current tool frame using the inverse of the later joint motions:
Qᵢ = exp(−B̂ₙθₙ) ⋯ exp(−B̂ᵢ₊₁θᵢ₊₁)
J_b,i = Ad_(Qᵢ) Bᵢ
J_b,n = Bₙ
The negative signs and reversed order come from inverting that later product. The last column stays fixed because the final joint's relationship to the tool frame does not depend on preceding joints. Modern Robotics derives this body-column construction.
For the same tool origin and axes, every column obeys the twist frame-change rule:
J_s = Ad_T J_b
J_b = Ad_(T⁻¹) J_s
The adjoint is invertible, so these matrices have the same rank. They also have the same joint-rate null space: a rate vector produces zero full twist in one frame exactly when it does in the other.
Our tool frame sits at the tip, with x along link 2. Its home origin is (3, 0), giving B₁ = (1, 0, 3) and B₂ = (1, 0, 1). The planar body Jacobian becomes:
J_b =
[ 1, 1 ]
[ 2 sin θ₂, 0 ]
[ 2 cos θ₂ + 1, 1 ]
Recover the physical tool velocity
Let p be the tool origin in space coordinates. A spatial twist defines the rigid-motion field u(x) = ω_s × x + v_s. Evaluating it at the tool origin gives:
ṗ = ω_s × p + v_s = Rv_b
The body linear coordinate v_b expresses the tool-origin velocity in body axes. Multiplying by R expresses that physical velocity in space axes. Neither value means that the tool origin changes coordinates within its own attached frame; those body coordinates remain zero.
We can also differentiate the position directly. The elbow angle is relative to link 1, so the tool heading is φ = θ₁ + θ₂ and its position is p = (2 cos θ₁ + cos φ, 2 sin θ₁ + sin φ). Therefore the position-task Jacobian is:
J_p =
[ −2 sin θ₁ − sin φ, −sin φ ]
[ 2 cos θ₁ + cos φ, cos φ ]
ṗ = J_p θ̇
Deleting the angular row of J_s would give v_s, which usually differs from ṗ. The point Jacobian lesson develops this direct derivative and the distinction between instantaneous velocity and a finite step.
Calculate both Jacobians for a two-link arm
Choose θ₁ = 90°, θ₂ = −90°, and θ̇ = (0.5, −0.25) rad/s. The tip is at p = (1, 2) m, and the tool heading is zero. The body and space axes currently align, though their origins differ.
J_s =
[ 1, 1 ]
[ 0, 2 ]
[ 0, 0 ]
J_b =
[ 1, 1 ]
[ −2, 0 ]
[ 1, 1 ]
Multiplying by the joint rates gives V_s = (0.25, −0.5, 0) and V_b = (0.25, −1, 0.25). The first entry in each triple is rad/s; the others are m/s.
Recover the tool velocity from the spatial representation:
ω_s × p = (−0.5, 0.25) m/s
ṗ = (−0.5, 0.25) + (−0.5, 0)
ṗ = (−1, 0.25) m/s
Since R = I here, the last two body-twist entries give the same physical velocity directly. The position matrix J_p = [−2, 0; 1, 1] produces it too. All three calculations agree.
Change the pose and isolate joint contributions
Use Shoulder only and Elbow only to see each column's contribution. Changing the rates changes the output twist, while the Jacobian matrices remain tied to the selected configuration. A stopped arm still has a Jacobian describing the motions it could produce.
The amber arrow shows the physical tool velocity at the tip. The blue dashed arrow shows v_s at the space origin. Both use a half-second display scale to fit velocity arrows on meter axes; their endpoints are not predictions of a finite trajectory.
The Position-null motion preset keeps the tip instantaneously still while changing its orientation. Read the position rank and full-pose rank separately before interpreting that motion.
State the task before naming a singularity
The full planar pose includes orientation and two position coordinates. This arm has only two joints, so its 3 × 2 pose Jacobians can span at most two independent twist directions. They cannot command three arbitrary pose-velocity components at once.
For this arm, J_s and J_b retain rank 2 at every configuration. In J_s, the two angular entries equal one, while the difference between the columns has a linear part of length L₁ = 2. No nonzero combination of the two columns can cancel the complete twist.
The position-only matrix has a different rank condition:
det J_p = L₁L₂ sin θ₂ = 2 sin θ₂
It has rank 2 when sin θ₂ ≠ 0, and rank 1 at the straight or folded configurations. Modern Robotics defines a singularity through a drop from a Jacobian's attainable maximum rank. Here, the position map loses a direction even though the full-pose map keeps its two independent columns.
At the straight pose θ = (0, 0), J_p = [0, 0; 3, 1]. Rates (0.25, −0.75) give ṗ = 0 but angular velocity 0.25 − 0.75 = −0.5 rad/s. These rates belong to the position task's null space, not the full-pose null space.
Near a collinear configuration, the position columns become nearly dependent. Producing some tip velocities can then require large joint rates. A small nonzero elbow angle still gives exact rank 2; rounding a displayed determinant to zero does not turn it into an exact singularity.
The kinematic singularities lesson tests requested tip velocities at these poses. Compare the reachable part of each request with its residual, then see how a nearby pose changes the required joint rates.
Connect velocity maps to control and statics
A velocity controller must specify the output it wants: a complete twist, a position velocity, or another task derivative. It must also specify the frame. Solving for joint rates cannot repair a mismatch between a spatial linear coordinate and a measured tip velocity.
The same checks apply to learned models. If a model predicts joint rates, its predicted tool motion follows through the chosen Jacobian at the current pose. Comparing that prediction with a target requires matching the task, frame, and units; adding more output coordinates does not add physical degrees of freedom.
Force calculations use the dual map. A consistent tool wrench F and twist V pair through power, so the corresponding joint-load coordinates involve τ = JᵀF. Use J_s with a space wrench or J_b with a body wrench, each with the correct moment reference origin. The robot statics lesson derives the load and holding-torque signs with this same arm.
These calculations describe instantaneous kinematics. A constant joint-rate step changes the arm configuration and its Jacobian over time. Joint limits, torque limits, and collision constraints require additional models.
Check the matrices and a numerical derivative in Python
This standard-library example calculates both twist representations and the tool velocity. It then compares the analytic velocity with a central difference over a finite time interval. The difference is an approximation with a visible error.
from math import cos, hypot, pi, sin
def position(q):
a, b = q
return 2*cos(a)+cos(a+b), 2*sin(a)+sin(a+b)
def jacobians(q):
a, b = q
js = ((1, 1), (0, 2*sin(a)), (0, -2*cos(a)))
jb = ((1, 1), (2*sin(b), 0), (2*cos(b)+1, 1))
return js, jb
def apply(matrix, rates):
return tuple(row[0]*rates[0]+row[1]*rates[1]
for row in matrix)
def show(values):
parts = [f"{value:.6f}" for value in values]
return "(" + ", ".join("0.000000" if float(part) == 0
else part for part in parts) + ")"
q, rates = (pi/2, -pi/2), (0.5, -0.25)
js, jb = jacobians(q)
vs, vb = apply(js, rates), apply(jb, rates)
p = position(q)
tip = (vs[1]-vs[0]*p[1], vs[2]+vs[0]*p[0])
phi = sum(q)
from_body = (cos(phi)*vb[1]-sin(phi)*vb[2],
sin(phi)*vb[1]+cos(phi)*vb[2])
assert hypot(tip[0]-from_body[0], tip[1]-from_body[1]) < 1e-12
h = 0.1 # seconds on each side of the current time
before = position(tuple(a-h*r for a, r in zip(q, rates)))
after = position(tuple(a+h*r for a, r in zip(q, rates)))
difference = tuple((b-a)/(2*h) for a, b in zip(before, after))
error = hypot(difference[0]-tip[0], difference[1]-tip[1])
print("Space twist:", show(vs))
print("Body twist:", show(vb))
print("Tool velocity:", show(tip))
print("Velocity from body:", show(from_body))
print("Central difference:", show(difference))
print(f"Difference error: {error:.9f} m/s")
Expected output:
Space twist: (0.250000, -0.500000, 0.000000)
Body twist: (0.250000, -1.000000, 0.250000)
Tool velocity: (-1.000000, 0.250000)
Velocity from body: (-1.000000, 0.250000)
Central difference: (-0.999583, 0.249974)
Difference error: 0.000417428 m/s
For this smooth trajectory, the central-difference truncation error decreases quadratically with h near zero. Extremely small h can expose floating-point cancellation. Neither a finite difference nor the displayed decimal precision replaces the analytic derivative.
Try it yourself
Exercise 1. Keep the worked configuration θ = (90°, −90°), but set the rates to (0, 0.5) rad/s. Calculate V_s, V_b, and the physical tip velocity. Why is the spatial linear pair different from the tip velocity?
Show solution: use the elbow column
Half of the second space column gives V_s = (0.5, 1, 0). Half of the second body column gives V_b = (0.5, 0, 0.5). Since the body axes align with space at this pose, the physical tip velocity is (0, 0.5) m/s.
From the spatial twist, ω_s × p = (−1, 0.5) m/s. Adding v_s = (1, 0) gives (0, 0.5). The spatial linear pair describes the motion field at the space origin, while the tip sits at (1, 2).
Exercise 2. At the straight pose θ = (0, 0), verify that rates (0.25, −0.75) leave the tip position instantaneously unchanged. Find the angular velocity and explain whether those fixed rates keep the tip at (3, 0) for a whole second.
Show solution: distinguish the position task from the full pose
The position Jacobian gives ṗ = (0, 3 × 0.25 − 0.75) = (0, 0). The angular velocity is −0.5 rad/s, so the full twist is nonzero. This matches position rank 1 and full-pose rank 2.
Holding those rates gives θ₁(t) = 0.25t and tool heading φ(t) = −0.5t. The exact position is (2 cos(0.25t) + cos(0.5t), 2 sin(0.25t) − sin(0.5t)). At one second it is approximately (2.815407, 0.015382) m. A zero instantaneous position derivative did not guarantee a fixed position over a finite interval.
Sources and further study
- Lynch and Park, Modern Robotics: Space Jacobian constructs columns from home screw axes and preceding joint motions.
- Lynch and Park, Modern Robotics: Body Jacobian derives the inverse-later-motion formula and the adjoint relationship between Jacobians.
- Lynch and Park, Modern Robotics: Singularities explains attainable rank, task dimensions, and planar position singularities.