Every real DC/BLDC motor's torque falls roughly linearly as its speed rises — full torque only at stall (ω = 0), zero torque at its no-load top speed ωmax. A robot joint can only occupy points (ω, τ) on or inside that envelope; nothing outside it is physically achievable, no matter what the controller asks for.
Feasible envelope (per direction of rotation):
τ_max(ω) = τ_stall · (1 − |ω| / ω_max), 0 ≤ |ω| ≤ ω_max
Joint dynamics (rigid link + point load, rotating about the joint):
τ_required = I·α_desired + b·ω
τ_actual = clamp(τ_required, −τ_max(ω), +τ_max(ω))
α_actual = (τ_actual − b·ω) / I
Trajectory tracking (desired velocity from a target-angle error):
ω_desired = clamp(Kp·(θ_target − θ), −ω_cmd, +ω_cmd)
α_desired = (ω_desired − ω) / τ_response
- Every simulation step computes the torque the controller would need (required τ) to hit the commanded speed, then clamps it to whatever the actuator can actually deliver at the joint's current speed (actual τ) — exactly the same saturation a real speed controller runs into.
- Whenever required τ exceeds the envelope, the joint accelerates slower than commanded and the live scatter trace on the chart hugs the diagonal envelope boundary instead of sitting inside it.
- A heavier load raises the inertia I in τ = I·α + b·ω, so the same commanded acceleration needs more torque — pushing the operating point against the envelope more of the time. The inertia sweep quantifies that.