Skip to content

longTauGnssCoupling: coast-cap + graded-taper (primitives + scheduler + engine)#86

Merged
bobvan merged 1 commit into
mainfrom
bravo/longtau-coast-cap-all
May 29, 2026
Merged

longTauGnssCoupling: coast-cap + graded-taper (primitives + scheduler + engine)#86
bobvan merged 1 commit into
mainfrom
bravo/longtau-coast-cap-all

Conversation

@bobvan
Copy link
Copy Markdown
Owner

@bobvan bobvan commented May 29, 2026

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 τ 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 (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 binary 1 if converging else interval latch + 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_tdev ctor 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-capcoast_tdev from char into the scheduler ctor + per-epoch p22_at_tau closure; --coast-cap-k-sigma confidence factor.

Scope / dependencies

Test plan

  • 48 tests (coast-cap unit + scheduler integration + TDEV-fit + project_p22_coast). Default-off / byte-identical when --coast-cap absent. Full suite 1428 passed; both flags in --help.
  • closedLoopServoSim A/B (Charlie) on honest Q[3,3] (qFromCharPerActuator: derive Q[3,3] (sigma_do_freq) from char ADEV #83): --coast-cap on vs off — hump drops, >60 s coast no longer diverges.
  • Lab A/B on PiFace/clkPoC3 after the sim validates (Main coordinates).

🤖 Generated with Claude Code

… + 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant