Skip to content

feat: introduce per-constellation data supertypes#71

Merged
siebc merged 1 commit into
masterfrom
sc/gnss-supertype
Jul 5, 2026
Merged

feat: introduce per-constellation data supertypes#71
siebc merged 1 commit into
masterfrom
sc/gnss-supertype

Conversation

@giove-a

@giove-a giove-a commented Jul 5, 2026

Copy link
Copy Markdown

Summary

Introduces per-constellation abstract supertypes for decoder data types, mirroring the equivalent refactor in GNSSSignals.jl. This lets Galileo I/NAV (E1B) and F/NAV (E5a) share their identical ephemeris/clock completeness checks via subtype dispatch instead of duplicated per-signal copies.

Two new abstract types sit between AbstractGNSSData and the concrete per-signal data types:

  • AbstractGPSData <: AbstractGNSSDataGPSL1CAData, GPSL1C_DData, GPSCNAVData
  • AbstractGalileoData <: AbstractGNSSDataGalileoE1BData, GalileoE5aData

Constellation membership is now encoded at each struct's definition site (the <: Abstract*Data line written anyway), so a new signal inherits the shared behaviour with nothing to remember.

What collapsed

is_ephemeris_decoded and is_clock_correction_decoded were byte-identical for E1B and E5a — the two signals carry the same orbital (t_0e, M_0, e, sqrt_A, …, C_is) and clock (t_0c, a_f0, a_f1, a_f2) field sets. They now dispatch once on AbstractGalileoData (in src/galileo/galileo.jl) instead of once per signal — 4 methods → 2.

Genuinely per-signal checks stay on the concrete types: is_health_status_decoded (E1B carries E1-B/E5b health, E5a only E5a), is_decoding_completed_for_positioning, and is_sat_healthy.

Why GPS didn't collapse equally

The GPS supertype is added for symmetry and future-proofing (a home for any GPS-wide fact that surfaces later), but there is no current GPS duplication to remove:

  • The "two signals, one message" case already shares maximally. L5I and L2C broadcast the identical CNAV message and already share a single GPSCNAVData type — reuse is at 100%, nothing to collapse.
  • The three distinct GPS data types use structurally different message formats. LNAV (subframe-based), CNAV-2 (subframe-2/3 pages), and CNAV (message-type based) have different field sets, so their completeness predicates are genuinely different — not near-duplicates.

Performance

No runtime or allocation impact. The change is dispatch-only: struct layouts are unchanged, abstract supertypes are a compile-time construct, and Julia specializes methods on the concrete argument type regardless of an abstract signature annotation. Verified on the collapsed method: dispatch resolves to the single AbstractGalileoData method, return type infers to concrete Bool, 0 allocations at a concrete call site, and no dynamic dispatch in the specialized body (pure inlined getfield/isnothing).

Scope

This is the decoded-data hierarchy only. A cross-package get_time_system(decoder_state) accessor was considered and deliberately left out: PositionVelocityTime.jl already derives the time system from the ranging signal (GNSSSignals.get_time_system(state.system)), which is the authoritative source, so a parallel decoder-state path would only invite drift.

Tests & docs

  • New test/gnss_supertype.jl (wired into runtests.jl): asserts the type hierarchy, that every Galileo type dispatches to the single supertype method (which), and the collapsed methods' behaviour for both signals.
  • docs/src/api.md documents both new supertypes.
  • Full suite: 2483/2483 pass under GNSSSignals 3.2, including Aqua (no method ambiguities/piracy).

🤖 Generated with Claude Code

@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.14%. Comparing base (016c740) to head (83ee266).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #71      +/-   ##
==========================================
- Coverage   98.15%   98.14%   -0.01%     
==========================================
  Files          14       14              
  Lines        1517     1513       -4     
==========================================
- Hits         1489     1485       -4     
  Misses         28       28              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Add AbstractGPSData and AbstractGalileoData as intermediate abstract
supertypes between AbstractGNSSData and the concrete per-signal data
types. Constellation membership is now encoded at each struct definition
site (the `<: Abstract*Data` line written anyway), so a new signal
inherits the shared behaviour with nothing to remember.

is_ephemeris_decoded and is_clock_correction_decoded were byte-identical
for Galileo I/NAV (E1B) and F/NAV (E5a) — the same orbital and clock
fields must be present — so they are a per-constellation fact. They now
dispatch once on AbstractGalileoData (in galileo/galileo.jl) instead of
once per signal (4 methods -> 2). Genuinely per-signal checks
(is_health_status_decoded, is_decoding_completed_for_positioning,
is_sat_healthy) stay on the concrete types.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@giove-a
giove-a force-pushed the sc/gnss-supertype branch from 4a3c746 to 83ee266 Compare July 5, 2026 09:55
@siebc
siebc merged commit 9e5cba6 into master Jul 5, 2026
9 checks passed
@siebc
siebc deleted the sc/gnss-supertype branch July 5, 2026 10:06
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.

2 participants