Skip to content

fix: gate PVT satellites on decoding completeness#51

Merged
giove-a merged 1 commit into
masterfrom
sc/check-decoder-state
Jul 7, 2026
Merged

fix: gate PVT satellites on decoding completeness#51
giove-a merged 1 commit into
masterfrom
sc/check-decoder-state

Conversation

@giove-a

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

Copy link
Copy Markdown

Summary

calc_pvt now admits a satellite into the solve only once its decoder has
fully decoded the navigation data a fix needs — not just that the satellite
reports healthy.

This pairs GNSSDecoder's newly exported is_decoding_completed_for_positioning
with the existing is_sat_healthy check:

healthy_indices = findall(
    x -> is_decoding_completed_for_positioning(x.decoder) && is_sat_healthy(x.decoder),
    states,
)

Completeness is checked first: once it holds, the broadcast health bit
is_sat_healthy inspects is guaranteed to have been decoded, so the two
predicates compose without a separate nothing guard.

Why

Previously a satellite could pass the health check while its decoder had not
yet recovered the full data set required to position from it (time of week,
ephemeris, SV clock polynomial, and — where carried in the required set — the
week number and single-band group delay). Using such a satellite risks a bad
or failed fix. The new gate ensures every satellite entering the least-squares
solve carries a complete, self-consistent data set.

Changes

  • src/PositionVelocityTime.jl — add the is_decoding_completed_for_positioning
    gate alongside is_sat_healthy in calc_pvt.
  • Project.toml — bump GNSSDecoder compat "3.6""3.7" (the release that
    exports the new function).

Testing

Verified against GNSSDecoder 3.7.0 that both the GPS L1 C/A and Galileo E1B
test fixtures' data blocks pass the new gate (and correctly fail when a
required field such as TOW/WN is dropped), so the existing test suite's
healthy-satellite counts are preserved.

🤖 Generated with Claude Code

Pair GNSSDecoder's newly exported is_decoding_completed_for_positioning
with the existing is_sat_healthy check in calc_pvt. A satellite now enters
the solve only once its decoder has recovered the full navigation data set
a fix needs (TOW, ephemeris, SV clock polynomial, …) and promoted raw_data
to data. Checking completeness first guarantees the broadcast health bit is
already decoded, so the two predicates compose without a separate nothing
guard.

Requires the export, so bump the GNSSDecoder compat to 3.7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.30%. Comparing base (e1976ef) to head (c91b115).

Additional details and impacted files
@@           Coverage Diff           @@
##           master      #51   +/-   ##
=======================================
  Coverage   98.30%   98.30%           
=======================================
  Files           7        7           
  Lines         472      473    +1     
=======================================
+ Hits          464      465    +1     
  Misses          8        8           

☔ 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.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1)

Time benchmarks
master c91b115... master / c91b115...
calc_pvt/GPSL1/4sats/cold 0.0441 ± 0.0036 ms 0.044 ± 0.0063 ms 1 ± 0.17
calc_pvt/GPSL1/4sats/warm 0.0393 ± 0.0067 ms 0.0393 ± 0.0072 ms 1 ± 0.25
calc_pvt/GPSL1/9sats/cold 0.0639 ± 0.0022 ms 0.064 ± 0.0019 ms 0.999 ± 0.045
calc_pvt/GPSL1/9sats/warm 0.0399 ± 0.0011 ms 0.0398 ± 0.00098 ms 1 ± 0.036
calc_pvt/GalileoE1B/4sats/cold 0.0393 ± 0.007 ms 0.0394 ± 0.0079 ms 0.998 ± 0.27
calc_pvt/GalileoE1B/4sats/warm 19.1 ± 3.4 μs 18.9 ± 3 μs 1.01 ± 0.24
calc_pvt/GalileoE1B/5sats/cold 0.0421 ± 0.0071 ms 0.0423 ± 0.0072 ms 0.996 ± 0.24
calc_pvt/GalileoE1B/5sats/warm 22 ± 4.5 μs 22 ± 4.2 μs 1 ± 0.28
time_to_load 2.51 ± 0.03 s 2.51 ± 0.063 s 0.997 ± 0.028
Memory benchmarks
master c91b115... master / c91b115...
calc_pvt/GPSL1/4sats/cold 0.552 k allocs: 25.2 kB 0.552 k allocs: 25.2 kB 1
calc_pvt/GPSL1/4sats/warm 0.493 k allocs: 21.5 kB 0.493 k allocs: 21.5 kB 1
calc_pvt/GPSL1/9sats/cold 0.78 k allocs: 31.5 kB 0.78 k allocs: 31.5 kB 1
calc_pvt/GPSL1/9sats/warm 0.622 k allocs: 21.7 kB 0.622 k allocs: 21.7 kB 1
calc_pvt/GalileoE1B/4sats/cold 0.541 k allocs: 24.5 kB 0.541 k allocs: 24.5 kB 1
calc_pvt/GalileoE1B/4sats/warm 0.372 k allocs: 14.7 kB 0.372 k allocs: 14.7 kB 1
calc_pvt/GalileoE1B/5sats/cold 0.58 k allocs: 25.2 kB 0.58 k allocs: 25.2 kB 1
calc_pvt/GalileoE1B/5sats/warm 0.422 k allocs: 15.9 kB 0.422 k allocs: 15.9 kB 1
time_to_load 0.149 k allocs: 11.2 kB 0.149 k allocs: 11.2 kB 1

@giove-a
giove-a merged commit 8fe32d4 into master Jul 7, 2026
8 checks passed
@giove-a
giove-a deleted the sc/check-decoder-state branch July 7, 2026 12:47
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