explainer
Inverse dynamics: calculate the torque a robot’s motion needs
Calculate joint torque from a robot arm’s pose, velocity, and requested acceleration. Account for gravity, coupling, friction, and a known tip force, then see how actuator limits change the resulting acceleration.
What you will learn
- Distinguish inverse dynamics from inverse kinematics and forward dynamics.
- Calculate actuator torque from inertia, velocity products, gravity, friction, and a known external force.
- Check the force convention before adding a Jacobian-transpose term.
- Recompute both joint accelerations when either actuator clips its torque.
- Explain why an instantaneous torque calculation does not guarantee trajectory tracking.
Before you start
A robot arm can need substantial torque while barely moving. Holding it horizontally costs torque against gravity; accelerating it adds an inertial demand. The elbow motor can also need torque when the requested relative elbow acceleration is zero.
Inverse dynamics calculates those joint torques from the arm's current configuration, velocity, and desired acceleration. This lesson uses two rods whose numbers you can check by hand, then limits the actuator commands to see which acceleration the arm can actually produce.
Start with a known state and an acceleration request
The input state is (q, q̇): joint angles and joint angular velocities. Add a requested acceleration q̈_req, a physical model, and any known external loads. For this fully actuated arm, inverse dynamics returns the two required actuator torques.
| Problem | Known inputs | Output |
|---|---|---|
| Inverse kinematics | Desired tool pose and robot geometry | Joint configuration q |
| Inverse dynamics | q, q̇, requested q̈, model, known loads | Joint torque τ |
| Forward dynamics | q, q̇, applied τ, model, known loads | Joint acceleration q̈ |
Inverse kinematics can provide a configuration for a task. A timed motion plan adds velocities and accelerations. Inverse dynamics evaluates the torque that motion requires at each state.
The word inverse names the direction of this physical calculation. Computing torque uses a mass-matrix multiplication. Forward dynamics solves the mass-matrix system to recover acceleration from torque.
Specify the arm and its coordinates
Use two uniform slender rods in a vertical plane. Each has length 1 m, mass 1 kg, a center of mass halfway along its length, and rotational inertia I = mL²/12 = 1/12 kg·m² about its own center. Both joints have ideal direct torque actuation.
World x points right and world y points upward. Angle q₁ measures the shoulder counterclockwise from world x; q₂ measures the elbow relative to the first link. The second rod's absolute angle is q₁ + q₂.
The model uses radians, rad/s, rad/s², and joint torques in N·m. The lab exposes angles in degrees and converts them before calculation. Positive generalized torque acts in the direction of increasing its joint coordinate.
Gravity points down with magnitude g₀, normally 9.81 m/s². Optional viscous friction has coefficient b in N·m·s/rad, and the environment can apply a known world-frame force F at the tip. The model omits gearing, rotor inertia, elastic joints, payloads, dry friction, and unknown contact reactions.
The robot dynamics lesson develops this arm's inertia and energy model. Full extension creates a kinematic singularity for some tool tasks, but the joint-space mass matrix remains positive definite for these rods.
Add the contributions to actuator torque
Write the equation of motion with gravity and friction on the left:
M(q) q̈ + c(q, q̇) + g(q) + bq̇ = τ + J(q)ᵀF
τ_req = M(q) q̈_req + c(q, q̇) + g(q) + bq̇ − J(q)ᵀF
Each term in the second line contributes joint torque. The matrix M depends on configuration; c contains velocity-product terms, including Coriolis and centrifugal effects. Here c already includes the multiplication commonly written as C(q, q̇)q̇; different valid C matrices can represent the same c.
The vector g(q) is the gravity-compensation term on the left side of this equation. Physical gravity applies generalized torque −g(q). The modeled viscous force acts as −bq̇, so its compensation contributes +bq̇ to the actuator command.
Drake's InverseDynamics documentation describes this calculation and explicitly excludes actuator limits from inverse dynamics itself. It writes gravitational force on the other side of the equation, so its gravity symbol carries the opposite meaning to g(q) here.
For the two equal rods, the mass matrix has entries:
M₁₁ = 5/3 + cos q₂
M₁₂ = M₂₁ = 1/3 + (1/2) cos q₂
M₂₂ = 1/3
Its off-diagonal entries connect one joint's acceleration to torque at the other joint. Inverse dynamics keeps these terms when assembling the command.
Accelerate the shoulder while holding relative elbow acceleration at zero
Start horizontally at q = (0, 0) with q̇ = (0, 0). Use gravity 9.81 m/s², no tip force, and no friction. Request q̈_req = (1, 0) rad/s².
At this configuration:
M = [[8/3, 5/6], [5/6, 1/3]] kg·m²
g = (19.62, 4.905) N·m
M q̈_req = (8/3, 5/6) N·m
The shoulder supports the first rod's weight at a 0.5 m horizontal lever arm and the second rod's weight at 1.5 m: 9.81(0.5 + 1.5) = 19.62 N·m. The elbow supports the second rod's weight at 0.5 m, giving 4.905 N·m. Adding the inertial demand gives:
τ_req = (22.286667, 5.738333) N·m, rounded
The second torque includes 5/6 N·m of inertial effort even though q̈₂ is zero. The whole second rod still changes its absolute angular velocity as q₁ accelerates. Zero relative elbow acceleration requires the motor to enforce that coordinated motion.
Setting both requested accelerations to zero reduces the torques to (19.62, 4.905) N·m. With zero velocity, these torques hold the ideal arm horizontally. Zero acceleration at a nonzero velocity would instead mean maintaining that velocity at this instant.
Account for a known force on the tip
F means the force the environment applies to the arm, expressed in world coordinates. Virtual work maps that force to generalized joint torque JᵀF, as in robot statics. Its signed contribution changes the actuator torque needed for the same acceleration.
In the horizontal configuration, a vertical force Fy has lever arms 2 m about the shoulder and 1 m about the elbow:
JᵀF = (2Fy, Fy) N·m
Set Fy = +5 N and request a stationary hold. The actuator command becomes (19.62, 4.905) − (10, 5) = (9.62, −0.095) N·m. The small negative elbow torque offsets the excess upward moment of the tip force about that joint.
Reversing the force to Fy = −5 N raises the requested horizontal holding torques to (29.62, 9.905) N·m. The direction of the external force changes whether it helps support the weight.
An assumed force must actually exist for this prediction to hold. This example supplies a known force; it does not solve for a contact reaction or guarantee that a support can provide it.
Check which body applies the force when comparing implementations. Modern Robotics' recursive Newton–Euler presentation defines its tip wrench as the load the robot applies to the environment. That convention reverses the external-load sign relative to F here.
Include velocity products and friction
The velocity-product terms vanish when q̇ = 0. Once the joints move, they can contribute torque even if requested acceleration is zero. For these rods:
c₁ = −(1/2) sin q₂ (2q̇₁q̇₂ + q̇₂²)
c₂ = (1/2) sin q₂ q̇₁²
Choose the moving preset: q = (30°, 60°), q̇ = (1, −0.5) rad/s, q̈_req = (1, −1) rad/s², b = 0.2 N·m·s/rad, and no tip force. The rounded contributions are:
| Contribution | Shoulder, N·m | Elbow, N·m |
|---|---|---|
| M q̈_req | 1.583333 | 0.250000 |
| c | 0.324760 | 0.433013 |
| g | 12.743564 | 0.000000 |
| b q̇ | 0.200000 | −0.100000 |
| Total requested | 14.851657 | 0.583013 |
The second rod points vertically, making its gravity moment about the elbow zero at this instant. Its velocity-product term remains nonzero. Viscous friction opposes the negative elbow velocity, so its compensation contributes a negative elbow torque.
For larger open-chain robots, recursive Newton–Euler propagates link motions outward and required wrenches inward. It avoids explicitly forming every matrix entry while retaining rigid-body dynamics. The lab uses the explicit two-joint equations so you can inspect each contribution.
Compare required and applied torque
The lab calculates a command for one instantaneous state. It clips each actuator independently to the displayed symmetric bound, then uses forward dynamics to solve for the acceleration those applied torques produce.
The default 25 N·m limit accommodates both requested torques. Choose Torque-limited acceleration to reduce that limit to 20 N·m and inspect the acceleration error. Horizontal hold removes the acceleration request, while Gravity-free acceleration isolates inertial torque.
Supported tip applies the known +5 N vertical force. Moving bent arm adds joint velocities and viscous friction. Presets set all inputs, and sliders retain that preset's displayed velocity, gravity, and friction values.
Orange links show the current pose. Curved blue arrows show applied torque signs with schematic lengths; the table supplies the magnitudes. The diagram stays at the selected state because this experiment does not integrate time.
Recompute motion when a torque limit clips the command
Let each actuator supply torque between −L and +L. The lab applies this policy:
τ_applied,i = clip(τ_req,i, −L, +L)
M q̈_realized = τ_applied + JᵀF − c − g − bq̇
Return to the default horizontal acceleration request and set L = 20 N·m. Only the shoulder command clips, giving τ_applied = (20, 5.738333) N·m, rounded. The realized acceleration is q̈_realized = (−2.92, 9.8) rad/s².
The shoulder accelerates opposite its requested direction, and the relative elbow acceleration rises from zero to 9.8 rad/s². The unchanged elbow torque was correct for the original coordinated acceleration. Changing the shoulder torque changes the coupled motion that both torques produce.
Subtracting the requested equation from the applied equation gives a useful check:
M (q̈_realized − q̈_req) = τ_applied − τ_req
The torque deficit is (−2.286667, 0) N·m, rounded, and the acceleration error is (−3.92, 9.8) rad/s². Multiplying by the horizontal M recovers that deficit. A solver can use Cholesky factors to solve this positive-definite system without forming an explicit numerical inverse.
This checks one instant. A whole trajectory also needs feasible velocities, positions, actuator thermal loads, changing external forces, and torque at every state. Adjusting trajectory time scaling can reduce inertial demands, but gravity compensation can remain necessary even at rest.
Use inverse dynamics inside a tracking controller
A feedforward command predicts the torque a desired motion requires from a model. Model error, unexpected loads, and initial position or velocity error can still make the physical robot depart from the plan. Feedback uses measured state to correct those departures.
Feedforward control follows a smooth speed reference through a simpler joint model. Compare the predicted torque with feedback correction, then change inertia, drag, and an unmeasured load.
The feedback control lesson follows that correction through time in a single-joint speed experiment. Compare a fixed feedforward command with a controller that reacts to measured error, then test an unexpected load, sensor bias, and a torque limit.
Open-loop and closed-loop control focuses on the choice to use a measurement in the command. Its position experiment separates a calibrated schedule from corrections for drift and starting error.
An ideal computed-torque controller forms a corrected acceleration request:
a_cmd = q̈_d + Kd(q̇_d − q̇) + Kp(q_d − q)
τ_cmd = M(q) a_cmd + c(q, q̇) + g(q) + bq̇ − J(q)ᵀF
With an exact model, known force, full actuation, and no saturation, substitution gives q̈ = a_cmd. For error e = q_d − q, the resulting equation is ë + Kd ė + Kp e = 0. Positive diagonal gains give decaying error in that ideal setting.
Russ Tedrake's manipulator-control notes develop gravity compensation and inverse-dynamics feedback from a force-controlled example. Real implementations need measured state, suitable gains, actuator interfaces, and a response to saturation. The lab evaluates the torque mapping and its limits; it does not run a feedback controller.
A learned dynamics model can estimate a missing torque contribution, such as load-dependent friction. Its usefulness depends on comparisons with measured motion and effort over relevant states. A small training error alone does not establish tracking stability or safe behavior outside those states.
Dynamic parameter identification fits specified inertia, mass-moment, and friction coefficients from measured motion and torque. Varied motion helps distinguish those coefficients; a separate trajectory checks how well the fitted model predicts new data.
Reproduce the torque and acceleration checks in Python
This standard-library program models the same two unit rods. It calculates required torque, clips each command, and solves the two-joint system with Cholesky factors. Input angles use radians; the moving case converts its angles explicitly.
from math import cos, sin, sqrt, radians, isfinite
def experiment(q, qd, qdd, limit=25, gravity=9.81, damping=0, force=(0, 0)):
values = (*q, *qd, *qdd, limit, gravity, damping, *force)
if not all(isfinite(v) for v in values) or min(limit, gravity, damping) < 0:
raise ValueError("Use finite inputs and nonnegative limit, gravity, and damping")
q1, q2 = q
w1, w2 = qd
m11 = 5 / 3 + cos(q2)
m12 = 1 / 3 + cos(q2) / 2
m22 = 1 / 3
c = (-sin(q2) / 2 * (2 * w1 * w2 + w2 * w2),
sin(q2) / 2 * w1 * w1)
g = (gravity * (1.5 * cos(q1) + 0.5 * cos(q1 + q2)),
gravity * 0.5 * cos(q1 + q2))
fx, fy = force
external = (-(sin(q1) + sin(q1 + q2)) * fx
+ (cos(q1) + cos(q1 + q2)) * fy,
-sin(q1 + q2) * fx + cos(q1 + q2) * fy)
bias = tuple(c[i] + g[i] + damping * qd[i] - external[i] for i in range(2))
requested = (m11 * qdd[0] + m12 * qdd[1] + bias[0],
m12 * qdd[0] + m22 * qdd[1] + bias[1])
applied = tuple(max(-limit, min(limit, t)) for t in requested)
rhs = tuple(applied[i] - bias[i] for i in range(2))
l11 = sqrt(m11)
l21 = m12 / l11
l22 = sqrt(m22 - l21 * l21)
y1 = rhs[0] / l11
y2 = (rhs[1] - l21 * y1) / l22
a2 = y2 / l22
a1 = (y1 - l21 * a2) / l11
return requested, applied, (a1, a2)
def pair(values):
return "(" + ", ".join(f"{0.0 if abs(v) < 0.5e-6 else v:.6f}" for v in values) + ")"
cases = [
("accelerate", (0, 0), (0, 0), (1, 0), {}),
("hold", (0, 0), (0, 0), (0, 0), {}),
("gravity-free", (0, 0), (0, 0), (1, 0), {"gravity": 0}),
("supported", (0, 0), (0, 0), (0, 0), {"force": (0, 5)}),
("moving", (radians(30), radians(60)), (1, -0.5), (1, -1), {"damping": 0.2}),
("limited", (0, 0), (0, 0), (1, 0), {"limit": 20}),
]
for name, q, qd, qdd, options in cases:
requested, applied, acceleration = experiment(q, qd, qdd, **options)
print(f"{name}: requested={pair(requested)}; applied={pair(applied)}; qdd={pair(acceleration)}")
Expected output, with torque pairs in N·m and acceleration pairs in rad/s²:
accelerate: requested=(22.286667, 5.738333); applied=(22.286667, 5.738333); qdd=(1.000000, 0.000000)
hold: requested=(19.620000, 4.905000); applied=(19.620000, 4.905000); qdd=(0.000000, 0.000000)
gravity-free: requested=(2.666667, 0.833333); applied=(2.666667, 0.833333); qdd=(1.000000, 0.000000)
supported: requested=(9.620000, -0.095000); applied=(9.620000, -0.095000); qdd=(0.000000, 0.000000)
moving: requested=(14.851657, 0.583013); applied=(14.851657, 0.583013); qdd=(1.000000, -1.000000)
limited: requested=(22.286667, 5.738333); applied=(20.000000, 5.738333); qdd=(-2.920000, 9.800000)
The example assumes these two rods and an applied force known at the current state. A reusable simulator also needs an integration method and checks on geometry, units, and input ranges.
Try it yourself
Exercise 1: rotate the extended arm upward. Set q = (90°, 0°), q̇ = 0, q̈_req = (1, 0) rad/s², and F = (0, 5) N. Keep gravity at 9.81 m/s² and the torque limit at 25 N·m. Calculate required torque and explain what happened to the gravity and tip-force contributions.
Check the vertical-arm calculation
Both rods now lie on the vertical line through the shoulder. Gravity and the upward tip force have zero moment arms about both joints at this instant. Their generalized torque contributions are zero.
The relative elbow angle remains zero, so M stays [[8/3, 5/6], [5/6, 1/3]]. Required torque is (2.666667, 0.833333) N·m, rounded, and both joints remain within their limits. Check with experiment((radians(90), 0), (0, 0), (1, 0), force=(0, 5)).
Exercise 2: limit an elbow-acceleration request. Use the horizontal pose, zero joint velocity, zero gravity, and no force or friction. Request q̈ = (0, 2) rad/s² and set the common torque limit to 1.5 N·m. Find the requested torques, applied torques, and both realized accelerations.
Check the coupled acceleration after clipping
Multiplying M by (0, 2) gives requested torque (5/3, 2/3) N·m. Only the shoulder exceeds 1.5 N·m, so applied torque is (1.5, 2/3) N·m. The torque deficit is (−1/6, 0) N·m.
Solving gives realized acceleration (−2/7, 19/7) rad/s², approximately (−0.285714, 2.714286). The unchanged elbow torque accompanies a different elbow acceleration because the shoulder motion changed. Call experiment((0, 0), (0, 0), (0, 2), limit=1.5, gravity=0) to verify it.
Sources and further study
- Kevin Lynch and Frank Park, Modern Robotics: Newton–Euler Inverse Dynamics: recursive link-motion and wrench calculations, including its robot-on-environment tip-load convention.
- Drake, InverseDynamics: a state-and-acceleration interface, gravity compensation, and the separate issue of actuator limits.
- Russ Tedrake, Robotic Manipulation: Manipulator Control: feedforward acceleration, gravity compensation, and feedback for trajectory tracking.
Continue with forward dynamics to follow the motion produced by an applied torque over time.