Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Motion

caliper-motion produces smooth, jerk-limited trajectories with O(1) closed-form sampling: a Trajectory answers sample(t) in constant time (position/velocity/acceleration), so it plays back cheaply and deterministically.

Jerk-limited S-curve profiles

The core is a 7-segment S-curve (jerk-limited trapezoidal) profile. It respects velocity, acceleration, and jerk limits (MotionLimits).

  • MOVE_J — joint-space, time-synchronized: all joints start and finish together, driven by the slowest joint's limits.
  • MOVE_L — Cartesian straight-line motion of the tool frame.
  • MOVE_C — Cartesian circular/arc motion.

The Cartesian entry points validate their caps, dt, and goal finiteness (non-finite goals are rejected), symmetric with the joint-space path — this was tightened in the audit.

MOVE_C fits the unique circle through the start / via / end tip positions and sweeps it the short way, so the parameterization passes through the via point on its way to the end (the naive arc frame could sweep the long way round — regression-tested). It is wired to every face: move_c in Rust and Python, and caliper move --target ... --via tx,ty,tz on the CLI, with oracle coverage (endpoint + via reached within joint velocity limits).

Waypoint retiming

retime_waypoints takes a joint-space waypoint path (for example, the output of the planner) and turns it into a playable, jerk-limited Trajectory. This is how a planned path becomes something a control loop or Studio can execute and record.

Time-optimal parameterization (TOPP)

caliper-motion also includes a time-optimal, acceleration-limited parameterization of a joint-space waypoint path (topp), with corner stops at every interior waypoint.

The reasoning is explicit in the code: a piecewise-linear path q(s) has a discontinuous tangent at every interior waypoint, so q''(s) is an unbounded Dirac there. Joint acceleration along the path is q̈ᵢ = q'ᵢ·s̈ + q''ᵢ·ṡ²; the q''·ṡ² term explodes at a corner unless the path velocity is zero there. Caliper therefore drives ṡ → 0 at each interior waypoint so the spike vanishes. Per segment the tangent q'(s) = Δq is constant, giving the two scalar bounds

|q̇ᵢ| = |Δqᵢ|·ṡ ≤ vmaxᵢ   ⟺   ṡ ≤ minᵢ vmaxᵢ/|Δqᵢ|
|q̈ᵢ| = |Δqᵢ|·s̈ ≤ amaxᵢ   ⟺   s̈ ≤ minᵢ amaxᵢ/|Δqᵢ|

and a rest-to-rest bang-bang (trapezoid/triangle) profile in s over [0,1] is time-optimal subject to those bounds. Segments are concatenated (rest between them) and resampled onto a uniform dt grid.

How motion is verified

All of caliper-motion is re-derived-correct but self-consistent-only: there is no third-party trajectory oracle (nothing Ruckig-class) wired in. The profiles are checked against Ruckig-class jerk-limited expectations and by property tests (endpoint exactness, monotonicity, limit adherence) rather than against an external reference implementation. This is one of the places where the trust comes from re-derivation plus invariants, not from an external cross-check.