Trajectory Generation, step 3
Velocity and acceleration limits
Turn joint limits into the fastest legal move: accelerate, cruise, brake.
Builds on Position, velocity & acceleration and Mass, inertia & F = ma, from the free Foundations.
Write and run this step in the simulator with ProLimits instead of durations
So far you picked and hoped the joints could keep up. Real drives have hard limits: a top speed and a top acceleration for each joint. This arm publishes them as arm.vmax and arm.amax (rad/s and rad/s², in joint order). The fastest legal move turns the question around: given the limits, what is the shortest ?
The trapezoid
Use the limits the whole way: accelerate at , cruise at , then brake at . Plotted against time, the velocity is a trapezoid. Reaching full speed takes , and braking takes the same time again, so
Or a triangle
If , the move is over before the joint reaches . The cruise disappears and the velocity becomes a triangle that peaks at halfway through:
Where the joint is at time t
Let be the peak speed (, or for a triangle), and let . The distance travelled after time is:
| phase | while | distance |
|---|---|---|
| accelerate | ||
| cruise | ||
| brake |
The joint angle is then .
Your task
Implement trapezoid_duration(dq, vmax, amax) and trapezoid(q0, qf, vmax, amax, t) for a single joint: scalars in and out, with clamped to .
The starter moves the shoulder only, using arm.vmax[1] and arm.amax[1]. The first move is long enough to cruise; the second is a short triangle. For now the starter moves at constant speed, so its acceleration spikes at both ends of each move.
The commands are graded: speed within 1.02·vmax, acceleration within 1.05·amax, and each move within 3% of the optimal time.