Skip to content

chc.mintime

Stability tier: experimental.

Minimum-time (time-optimal) control via Pontryagin's minimum principle -- the double integrator.

For a control-affine plant with a bounded input, PMP makes the time-optimal control bang-bang: the Hamiltonian is linear in u, so the optimum sits on a bound, u = -u_max * sign(switching fn), switching when it changes sign. For the double integrator x'' = u, |u| <= u_max driven to rest at the origin, that switching function is sigma = x + v|v|/(2 u_max) and the optimal trajectory needs at most one switch (accelerate, then brake on the switching parabola). The textbook complement to the quadratic-cost controllers in chc.control / chc.lqr: minimise time to target, not a quadratic cost.

Scoped to the double integrator (general PMP is a costate two-point boundary-value problem); NumPy float64, and the sign-based law is non-differentiable, so it lives outside the JAX control core.

BangBangResult dataclass

A time-optimal rollout: the trajectory, the applied control, and its switch count.

switching_function(x, v, u_max)

PMP switching function sigma = x + v|v|/(2 u_max); its sign picks the control.

bang_bang_control(x, v, u_max=1.0)

Time-optimal feedback for the double integrator: -u_max sign(sigma), the <=1-switch law.

Off the switching curve -u_max sign(sigma); on it -u_max sign(v) (brake to the origin); at the origin 0.

double_integrator_min_time(x0, v0, u_max=1.0)

Closed-form minimum time to drive x''=u, |u|<=u_max, from (x0, v0) to the origin.

From rest (v0 = 0) this is the familiar 2 sqrt(|x0| / u_max).

bang_bang_rollout(x0, v0, u_max=1.0, *, dt=0.01)

Open-loop time-optimal trajectory: bang u1 until the analytic switch time, then -u1.

Uses the closed-form switch time rather than a discrete sign(sigma) feedback, which would chatter across the switching curve; this gives the clean at-most-one-switch trajectory PMP predicts. Per-step integration is exact for the piecewise-constant control.