feat(cam): double-S profiles with nonzero boundary velocities #56

Merged
patman merged 1 commit from patman/cam-boundary-v into main 2026-07-09 23:28:13 +00:00 AGit
Owner

PR4b: plan_with_boundary_velocities(displacement, v_start, v_end, limits) — the general Biagiotti & Melchiorri 2008 sec 3.4 double-S (eqs. 3.30-3.34): per-side saturation casework, eq. 3.31 feasibility precheck (bitwise-consistent with the bracket invariant), eq. 3.32 closed-form peak when both sides saturate. Documented deviation, reviewer-verified: the gamma*a_max reduction recipe is replaced by bisection on peak velocity — cruise-less displacement is proven strictly monotone and continuous across both saturation regimes, so bisection is sound where gamma-reduction has no convergence guarantee; residual absorbs into the >= 0 cruise, measured endpoint errors ~1e-15 (test tolerances 1e-9, honest). New PlanError::{InvalidBoundaryVelocity, Infeasible}. Proptest pins exact reduction to plan_rest_to_rest at v=0. Line-count note: 198 non-blank non-test by the awk convention used across this stack; ~216 if measured as diff-added lines including docs — flagging per the <200 rule. Stacked on patman/cam-sample (#55).

PR4b: plan_with_boundary_velocities(displacement, v_start, v_end, limits) — the general Biagiotti & Melchiorri 2008 sec 3.4 double-S (eqs. 3.30-3.34): per-side saturation casework, eq. 3.31 feasibility precheck (bitwise-consistent with the bracket invariant), eq. 3.32 closed-form peak when both sides saturate. Documented deviation, reviewer-verified: the gamma*a_max reduction recipe is replaced by bisection on peak velocity — cruise-less displacement is proven strictly monotone and continuous across both saturation regimes, so bisection is sound where gamma-reduction has no convergence guarantee; residual absorbs into the >= 0 cruise, measured endpoint errors ~1e-15 (test tolerances 1e-9, honest). New PlanError::{InvalidBoundaryVelocity, Infeasible}. Proptest pins exact reduction to plan_rest_to_rest at v=0. Line-count note: 198 non-blank non-test by the awk convention used across this stack; ~216 if measured as diff-added lines including docs — flagging per the <200 rule. Stacked on patman/cam-sample (#55).
Add plan_with_boundary_velocities(): the general double-S solve
(Biagiotti & Melchiorri 2008 SS3.4) between boundary speeds v_start and
v_end with zero boundary accelerations, sharing the seven-phase
ScurveProfile shape. Feasibility precheck rejects displacements shorter
than the pure velocity-change ramp (new PlanError::Infeasible); boundary
speeds outside [0, v_max] are rejected (InvalidBoundaryVelocity). When
v_max is unreachable the peak velocity comes from the closed-form
both-saturated quadratic, falling back to bounded bisection on the
monotone cruise-less displacement for the mixed/unsaturated cases
(documented deviation from B&M's gamma*a_max reduction recipe, which
lacks a convergence guarantee near the feasibility boundary).
plan_rest_to_rest is reproduced as the v_start = v_end = 0 special case,
property-tested to 1e-9 per phase duration.

Co-authored-by: patman-assist <patrick-ai@kgroo.co>
patman changed target branch from patman/cam-sample to main 2026-07-09 23:28:07 +00:00
patman merged commit b76afc9e68 into main 2026-07-09 23:28:13 +00:00
Sign in to join this conversation.
No description provided.