feat(core): atmospheric measurement propagation — refraction + ionospheric delay biases with correction hooks - #145
Conversation
…elay biases with correction hooks (atmospheric-measurement-propagation) Completes the atmospheric-measurement-propagation change (15/15 tasks), the final change of the propagation tier. All additive: default radar generation, every constructor/TOML, and all calibrated benchmarks are byte-for-byte unchanged. - thresh-core/propagation/refraction: Bean-Dutton/CRPL exponential- profile ray integral (Bouguer's rule, fixed-count Simpson) returning elevation bending + excess range; ITU-R P.834-8 worked values reproduced (zenith excess matches the canonical ~2.31 m dry delay to <0.1 mm); 4/3-Earth cheap tier with the cos-phi obliquity factor, cross-checked within [0.90, 0.98] of the exponential tier; explicit 1-degree validity floor; correct_refraction one-step fixed-point inverse; targets at/below station altitude yield exactly zero bias - thresh-core/propagation/iono_delay: dr = 40.308193*STEC/f^2 (constant provenance fetched + bit-pinned), thin-shell obliquity (450 km IGS/ GLONASS convention, configurable), exact 1/f^2 tests, L/S/X band magnitudes, closed-form correction, Chapman->VTEC bridge verified against the analytic N_max*H*sqrt(2*pi*e) integral - thresh-synth: opt-in generate_radar_biased (bias-then-noise, azimuth untouched); iono leg gated on target altitude >= shell height (the documented step-function: sub-ionospheric targets accumulate none of the TEC) — no phantom iono bias on aircraft - Corrections compose via correct_atmosphere at the RAE->Cartesian seam; mismatched-parameter honesty measured: +-10% N_s / +-25% VTEC leave approximately the mis-set fraction (spec amended to state the truthful near-linear guarantee) - The demonstration the tier was built toward, through the real benchmark runner (three runs, same seed/noise): honest MOTP 34.81 / ANEES 1.544; biased-uncorrected 84.65 / 6.290 (2.43x / 4.07x, MOTA bit-identical — the bias is invisible to association); corrected 34.80 / 1.544 (within 0.02%). ANIS measured structurally blind (1.5947 -> 1.5948): smooth bias absorbed into the filter state — the NEES-vs-NIS distinction as a live measurement - Benchmark invariance: all four calibrated scenarios digit-for-digit identical to the pre-change baseline Adversarially reviewed (4 lenses, 3-skeptic votes): 5 findings confirmed, 0 rejected, all fixed — a major sign bug (negative excess for targets below an elevated station), the missing cos-phi obliquity in the 4/3 tier (cross-check band tightened from the masking [0.85, 1.35] to [0.90, 0.98]), the unconditional iono application, the spec/test residual-guarantee mismatch, and a false ANIS doc claim. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 44 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughChangesAtmospheric propagation
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant ScenarioRunner
participant RadarGenerator
participant PropagationModels
participant CartesianConverter
ScenarioRunner->>RadarGenerator: generate biased radar measurements
RadarGenerator->>PropagationModels: apply refraction and ionospheric delay
PropagationModels-->>RadarGenerator: apparent range and elevation
RadarGenerator-->>ScenarioRunner: noisy measurements
ScenarioRunner->>CartesianConverter: convert measurements with correction enabled
CartesianConverter->>PropagationModels: remove modeled atmospheric bias
PropagationModels-->>CartesianConverter: corrected geometry
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/thresh-core/src/propagation/iono_delay.rs`:
- Around line 125-135: Validate both public serde configuration structs at
deserialization: in crates/thresh-core/src/propagation/iono_delay.rs lines
125-135, enforce finite non-negative vtec_tecu, positive shell_height_m, and
positive frequency_hz; in crates/thresh-core/src/propagation/refraction.rs lines
145-155, enforce finite non-negative refractivity, positive scale height, and
minimum elevation within (0, π/2]. Reject invalid values before either
configuration can be used for propagation.
In `@crates/thresh-data/src/benchmark.rs`:
- Around line 253-270: Update the feature-gated manifest constructors
adsb_manifest and nuscenes_manifest to initialize the new atmosphere_bias field
as None and atmosphere_correction as false, preserving their existing defaults
and ensuring both feature builds type-check.
- Around line 2572-2591: Extend the invariant assertions in the benchmark test
to verify corrected.idf1 matches honest.idf1 using the existing bitwise
comparison style, and assert that corrected ANIS remains effectively unchanged
from honest ANIS using the documented tolerance. Keep the existing MOTA, IDF1,
MOTP, and ANEES checks intact.
In `@openspec/changes/atmospheric-measurement-propagation/design.md`:
- Around line 68-74: Update the benchmark results table near the documented
atmospheric bias comparison to include an IDF1 column with values for the
honest, uncorrected, and corrected runs, using the values produced by
atmospheric_bias_demonstration_through_runner. Keep the existing claim that IDF1
is bit-identical only if those recorded values verify it; otherwise remove the
claim.
- Line 81: Resolve the shell-height default consistently across the design
document: update the earlier 400 km decision and all dependent specifications to
450 km, or explicitly mark 400 km as superseded. Correct the decision
cross-reference so the default is attributed to the appropriate Decision
3/Decision 4 entry, preserving reproducibility with
IonoDelayConfig::shell_height_m.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 138a8ec6-1033-4c7d-83c0-3c4f584cbcd6
📒 Files selected for processing (9)
crates/thresh-core/src/lib.rscrates/thresh-core/src/propagation/iono_delay.rscrates/thresh-core/src/propagation/mod.rscrates/thresh-core/src/propagation/refraction.rscrates/thresh-data/src/benchmark.rscrates/thresh-synth/src/measurement_gen.rsopenspec/changes/atmospheric-measurement-propagation/design.mdopenspec/changes/atmospheric-measurement-propagation/specs/tropospheric-refraction/spec.mdopenspec/changes/atmospheric-measurement-propagation/tasks.md
…sserts, design consistency - RefractionConfig/IonoDelayConfig gain validate() called at every public evaluation entry point (finite/sign checks with clear panics — the DpConfig/ForceModelConfig pattern); should_panic tests added - adsb/nuscenes test manifests gain the four ScenarioParameters fields added since #136 (measurement_model, tracker_noise_sigma, atmosphere_bias, atmosphere_correction) — these cfg(test)+cfg(feature) literals were latently broken because no CI job runs cargo test with those features; verified with cargo test -p thresh-data --features adsb - Demonstration test now asserts corrected-IDF1 bit-equality and that ANIS stays within 0.01 of honest in both biased runs (the structural- blindness claim is asserted, not just recorded) - design.md: three-run table gains the IDF1 column (0.9750 across all runs); Decision 3's stale 400 km shell default corrected to the implemented 450 km with supersession note; divergence bullet anchored to Decision 3 explicitly Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
…hive completed change (#146) Implementation merged in #145 (15/15 tasks). Syncs the three delta specs into main specs — tropospheric-refraction, ionospheric-group-delay, and biased-measurement-generation — then moves the change to openspec/changes/archive/2026-07-17-atmospheric-measurement-propagation. This closes the five-change propagation tier. openspec validate --all --strict --no-interactive: 48/48 post-archive. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>



Summary
Implements
atmospheric-measurement-propagation(#144 spec; 15/15 tasks) — the final change of the propagation tier. Radar measurements gain the deterministic bias physics they were missing (refraction bending, ionospheric group delay), trackers gain the correction hooks, and the eval-consistency layer gets its closed-loop demonstration. All additive: default generation, every constructor/TOML, and all calibrated benchmarks byte-for-byte unchanged.thresh-core/propagation
Δr = 40.308193·STEC/f²(constant provenance fetched + bit-pinned), 450 km thin-shell obliquity (GLONASS/IGS convention), exact 1/f² scaling, L/S/X magnitudes (3.18 m / 0.60 m / 0.054 m at 10 TECU, 45°), Chapman→VTEC bridge verified against the analyticN_max·H·√(2πe)integralcorrect_atmosphereat the RAE→Cartesian seam; honesty measured — ±10% N_s / ±25% VTEC mis-sets leave ≈ the mis-set fraction (the spec states the truthful near-linear guarantee)thresh-synth
Opt-in
generate_radar_biased(bias-then-noise); the iono leg is gated on target altitude ≥ shell height — the documented step-function, so sub-ionospheric aircraft accumulate zero phantom TEC delay.The demonstration (what the tier was built toward)
Three runs through the real benchmark runner, same seed and noise realisation:
Benchmark invariance (task 4.5)
All four calibrated scenarios digit-for-digit identical to the pre-change baseline (diff empty):
orbital-iss0.8926/981.4041/0.9461/0.9474 · ANEES 1.4529 / ANIS 2.2042 —orbital-starlink-train0.9248/1602.0943/0.9622/0.9629 · 3.6243/2.5441 —ballistic-mrbm0.9978/397.6703/0.9989/0.9989 · 2.7569/2.5442 —synth-cv-clean0.9355/56.4910/0.9667/0.9672 · 3.2636/3.2760.Verification
-D warnings, fmt, rustdoc-Dwarnings,openspec validate --all --strict --no-interactive46/46🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Tests