feat(cam-lower): angular certificate math as pure functions #119
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "patman/angular-cert"
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-d. src/angular_cert.rs: AngularCert (+EXACT_ZERO, is_informative), FeedSups, AngularWindow, omega4_sup (Omega=k'''v^4+6k''v^2v.+3k'v.^2+4k'vv..+kv... — reviewer re-derived term-for-term), angular_jump_sum (seam zeta jumps, v^3), trapezoidal integrator bias zeta*dt^3/12 (re-derived, orientation bound only). D=sum(window durations) internal — under-covering structurally inexpressible. Windowed per S6 (recommended, revisable); S7 peaks reported not enforced. Not yet called. Opus review PASS after D1/D2.
Stack step S-d of the SE(3) angular lowering design (docs/superpowers/se3-lowering-design.md section 3). New src/angular_cert.rs. Nothing in lower.rs calls any of it yet -- these are pure functions of already-computed sups, so the emitted schedule and the translational certificate are both untouched. - AngularCert { max_orientation_err, max_angular_velocity_err, and the three reported peaks } + EXACT_ZERO, which is the true bound for a fixed orientation law rather than a placeholder. - omega4_sup: the angular sibling of r4_sup. Omega_sup = |k'''|v^4 + 6|k''|v^2|v_dot| + 3|k'|v_dot^2 + 4|k'|v|v_ddot| + |k||v_dddot| Structural cross-check for reviewers: this mirrors the checked-in translational r4_N with every kappa index shifted up one and the -k^3 v^4 frame-rotation term absent, since a scalar heading has no frame to rotate. - angular_jump_sum: |k|_sup * sum|delta v_ddot| + v_sup^3 * sum_seams |delta k''|. The seam term has no translational sibling -- the world jerk depends only on k and k', both continuous across a G3 seam, while zeta depends on k'', which jumps at every host/blend seam. - build_angular_cert: the windowed accumulation plus the (dt^3/12) * sum|zeta_k| integrator-bias term. That bias is the trapezoidal quadrature error of advance_rigid_body's Lie step; about a fixed axis the Magnus/commutator error is exactly zero, but trapezoidal integration of a quadratic omega is not, and the residual does not cancel. The design doc calls omitting it the single most likely implementation error, so it has its own mutation test. The pass duration D is DERIVED as the sum of the windows' durations, not taken as a parameter. An independent D is unsound in one direction: if the windows under-cover the pass, sum(Omega_p * D_p) under-bounds the true variation over the uncovered stretch while max_orientation_err still multiplies the full D, so the certificate would assert a bound it does not have. Deriving D makes that gap impossible to express rather than something every caller must remember not to do; S-c's piece_windows_tile_the_pass_contiguously pins that the intended windows tile the pass. Consequently a Fixed orientation law must use AngularCert::EXACT_ZERO directly rather than an empty-window call, and a test pins that the two are NOT synonyms. Omega has an independent numerical validation, not just transcriptions of the same algebra: on an analytic fixture (kappa cubic in s, s quartic in t) zeta from orient::angular_state is central-differenced once in time and compared against omega4_sup fed pointwise values. The fixture uses all-positive coefficients so every term of Omega is positive and the triangle inequality is exactly tight, making that comparison an equality rather than an inequality with somewhere to hide. An Omega_sup that is too small is unsound, not merely wrong, so a second test pins the soundness direction over a whole interval. FeedSups carries the s-domain (v, v_dot, v_ddot, v_dddot) sups in typed form; its docs restate that v_ddot is NOT the world tangential jerk. DECISIONS (Patrick-revisable; recorded because he may come back to them): S6 -- implemented the design doc's recommended per-piece windowed sup accumulation. AngularWindow pairs each piece's Omega_sup with the time spent in it, so a blend's huge Omega_sup multiplies milliseconds rather than the whole pass duration. windowing_is_far_tighter_than_a_pass_wide_ sup pins the resulting >50x tightening on the design doc's own 20 mm blend / 1.3 m pass example; without windowing the angular bound would be vacuous. Applied to the angular certificate only. S7 -- peaks are reported, not enforced: build_angular_cert passes them through as magnitudes and a test pins that they never move the bounds. The logged alternative (feed an angular cap back into cam_plan's Span::speed_cap) changes the planning contract and belongs in its own stack. S3 is NOT implemented here: the translational certificate's skipped- junction term has no angular counterpart because the design refuses that case instead. Co-authored-by: patman-assist <patrick-ai@kgroo.co>