feat(cam-lower): tangent-aligned orientation law (inert) #117
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "patman/orient-law"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
SE(3) S-b. src/orient.rs: OrientationLaw (Fixed/TangentAligned), HeadingTable with curvature-predicted branch unwrapping (detector-not-corrector: |step|<pi enforced, curvature estimate can only refuse, never rewrite) + arc-length-driven sampling, TangentRates/AngularRates typed state, omega=kv alpha=k'v^2+kv. zeta=k\v^3+3k'vv.+kv.. per design 2.1 with time-domain FD validation. Inert: nothing calls it; existing outputs unchanged. Opus review PASS after C1 aliasing fix + R1/R2.
New src/orient.rs, the data model for the SE(3) angular half. Nothing in lower.rs calls it yet, so the emitted schedule is unchanged and every existing test is untouched. - OrientationLaw { Fixed(Quaternion), TangentAligned { offset } }. R(s) = Rz(phi(s) + phi0); Fixed(IDENTITY) is today's behaviour spelled out in the new vocabulary. - angular_state -> AngularRates: omega = kv, alpha = k'v^2 + kv_dot, zeta = k''v^3 + 3k'v*v_dot + k*v_ddot, computed in the uom dimension-checked currency. - HeadingTable: unwrapped heading phi(s) over a whole pass, accumulated and never wrapped (a closed loop sweeps 2pi). Tabulates the branch only; heading_at lifts the caller's exact tangent onto it, so the returned angle is exact rather than interpolated. The unwrap is curvature-checked. Tangents alone cannot distinguish a turn of 3pi/2 from one of -pi/2, so each step is compared against the trapezoid estimate (k[i-1] + k[i])/2 * ds. A step is accepted only when it is under pi in magnitude AND within UNWRAP_TOLERANCE (pi/2) of that estimate; anything else, including a non-finite sample, is refused via LowerError::HeadingUnwrapAmbiguous. Inside the accept region the chosen branch necessarily coincides with the naive nearest-to-zero one, so the curvature is a detector, not a corrector: its job is to turn silent aliasing into a loud refusal. The |step| < pi half is what establishes heading_at's exactness precondition, which the residual check alone does NOT imply. Coarse grids that cannot serve heading_at (a full circle at 2 or 3 samples, a 270 degree arc at 2) are therefore refused rather than answered. The residual hole -- curvature concentrated strictly between endpoint samples -- is stated in the type docs rather than papered over. Sample density follows arc length (build_default / samples_for, 0.1 mm spacing clamped to [MIN_SAMPLES, MAX_SAMPLES]) so a long pass keeps the spacing a short one gets and no interval can straddle a corner blend. build_default's docs carry its cost profile for the S-e wiring: one PathEval::eval and one f64 per sample, ~16 MiB and seconds-to-tens-of- seconds at the MAX_SAMPLES clamp (passes past ~209.7 m), single-threaded and precompute-side -- build once per pass, never per knot. Handedness (CCW-positive kappa, left normal, right-handed about +z) is inherited from the translational half, not re-derived; the conventions are pinned in the module docs and asserted in tests. The module docs also spell out that v_dot IS the world tangential acceleration while v_ddot is NOT the world tangential jerk (that carries an extra -k^2 v^3), since conflating the two is the obvious way to mis-wire the follow-up. Tests: closed-form circle/line pins; full-formula hand evaluation plus an independent time-domain finite-difference re-derivation of alpha and zeta; body-axis/offset orientation conventions; 2pi sweep on circle, rounded-rect and long-pass fixtures; route-1 (atan2 unwrap) vs route-2 (integral of kappa) agreement on real blend geometry; dphi/ds == kappa finite-difference cross-check; heading_at exactness on and between samples; and refusal pins for coarse grids, large-but-consistent steps, non-finite inputs, and a swept neighbourhood of near-reversals. Co-authored-by: patman-assist <patrick-ai@kgroo.co>