longTauGnssCoupling: coast-cap + graded-taper (primitives + scheduler + engine)#86
Merged
Conversation
… + engine) Bounds the adaptive coast interval by the DO's STOCHASTIC wander, not just the deterministic drift budget tau=sqrt(2*T/D). Targets the tau~64-256s long-tau TDEV hump (2026-05-29 overnight: PiFace 6.4ns@64s, MadHat 3.6ns@256s) where a quiet DO (D~0) pinned tau at max_interval and coasted blind while its random-walk wander accumulated -- exactly where the GNSS reference is at its best. (Squash of the reviewed stack: #80 primitives [charlie-approved] + #84 scheduler wiring + #85 engine wiring.) PRIMITIVES (discipline.py, pure functions): - coast_cap_from_tdev: invert a power-law freerun TDEV; ~138s for an 85ps OCXO, <1s for a 1.17ns TCXO; slope<=0 -> +inf (no cap). - coast_cap_from_p22: largest tau with k*sqrt(P22(tau))<=budget, P22 from a caller closure; variance-space compare w/ boundary epsilon. - normalized_distance_to_lock: map sqrt(P22)/sigma_total -> [0,1] (0=locked, 1=far) -- the single derived signal every policy reads. - graded_interval: geometric taper replacing the binary "1 if converging else interval" latch + its 1->120s cliff; continuous + monotone so it cannot chatter. SCHEDULER (DisciplineScheduler.compute_adaptive_interval): all baseline paths flow through a coast-cap + taper tail. coast_tdev ctor arg -> TDEV cap; p22_at_tau closure (per-call) -> P22 cap; distance_to_lock (per-call) -> graded taper. The quiet-DO branch (D<1e-9 -> max_interval, the exact over-coast) now gets capped. ENGINE (--coast-cap, default off): - do_state.derive_coast_tdev_from_char: log-log fit of the DO freerun TDEV curve -> (tdev_ref, slope, 1.0). - DOFreqEst.project_p22_coast: predict-only P[2,2] table, one O(max_tau) projection/epoch. - --coast-cap -> coast_tdev from char into the scheduler ctor + per-epoch p22_at_tau closure; --coast-cap-k-sigma confidence factor. SCOPE: wires the COAST-CAP (tdev+p22). The graded taper hook (distance_to_lock) is implemented + tested but the engine does not yet pass it -- deferred to disciplineModeFsm, which defines the convergence metric + thresholds. Main DOFreqEst path only; CM_TDC unchanged. The p22 cap is honest only with Q-from-char (qFromCharPerActuator, sep. PR): an inflated Q over-grows P22 and caps the coast spuriously short. DEFAULT-OFF / byte-identical when --coast-cap absent. 48 tests across test_discipline_coast_cap / test_coast_tdev_char / test_project_p22_coast; full suite 1428 pass. Validate in closedLoopServoSim before hardware. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bounds the adaptive coast interval by the DO's stochastic wander, not just the deterministic drift budget
τ=√(2·T/D). Targets the tau~64–256 s long-tau TDEV hump (2026-05-29 overnight: PiFace 6.4 ns @ 64 s, MadHat 3.6 ns @ 256 s) where a quiet DO (D≈0) pinned τ atmax_intervaland coasted blind while its random-walk wander accumulated — exactly where the GNSS reference is at its best.Squash of the reviewed stack (per Bob, fewer merges): #80 primitives (Charlie-approved) + #84 scheduler wiring + #85 engine wiring. Those three are closed in favor of this PR.
Primitives (
discipline.py, pure)coast_cap_from_tdev— invert a power-law freerun TDEV; ~138 s for an 85 ps OCXO, <1 s for a 1.17 ns TCXO; slope≤0 → +inf (no cap).coast_cap_from_p22— largest τ with k·√(P22(τ))≤budget, P22 from a caller closure; variance-space compare with a boundary epsilon.normalized_distance_to_lock— √(P22)/σ_total → [0,1] (0=locked, 1=far); the single derived signal every policy reads.graded_interval— geometric taper replacing the binary1 if converging else intervallatch + its 1→120 s cliff; continuous + monotone (can't chatter).Scheduler (
compute_adaptive_interval)All baseline paths flow through a coast-cap + taper tail.
coast_tdevctor arg → TDEV cap;p22_at_tau(per-call) → P22 cap;distance_to_lock(per-call) → taper. The quiet-DO branch (the exact over-coast) now gets capped.Engine (
--coast-cap, default off)do_state.derive_coast_tdev_from_char— log-log fit of the DO freerun TDEV curve →(tdev_ref, slope, 1.0).DOFreqEst.project_p22_coast— predict-only P[2,2] table, one O(max_tau) projection/epoch.--coast-cap→coast_tdevfrom char into the scheduler ctor + per-epochp22_at_tauclosure;--coast-cap-k-sigmaconfidence factor.Scope / dependencies
distance_to_lockyet — deferred to disciplineModeFsm (which defines the convergence metric + thresholds). Main DOFreqEst path only; CM_TDC unchanged.import mathdup-conflict indo_state.py(both add it) — resolve by keeping one line.Test plan
--coast-capabsent. Full suite 1428 passed; both flags in--help.--coast-capon vs off — hump drops, >60 s coast no longer diverges.🤖 Generated with Claude Code