feat!: enrich PVT solution with IFB reference bands, units, and course over ground#50
Merged
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #50 +/- ##
==========================================
+ Coverage 98.27% 98.30% +0.02%
==========================================
Files 7 7
Lines 464 472 +8
==========================================
+ Hits 456 464 +8
Misses 8 8 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
Benchmark Results (Julia v1)Time benchmarks
Memory benchmarks
|
…e over ground
- Replace the raw `inter_frequency_biases::Dict{Symbol,Float64}` with
`Dict{Symbol,InterFrequencyBias}`, where each `InterFrequencyBias` bundles the
bias `value` with the `reference` band it is measured against — the anchor whose
delay is folded into the clock biases. `band_ifb_layout`/`decide_bias_layout` now
thread the per-coverage-component reference band through to `calc_pvt`, so each
bias's anchor is explicit rather than implicit, and a disconnected constellation
can report distinct references per band.
- Add `course_over_ground::typeof(1.0°)` to `PVTSolution`: the azimuth of the
velocity vector in the local ENU frame, degrees clockwise from true North in
`[0, 360)°`, via the new `calc_course_over_ground` helper. This is the
velocity-derived direction of motion (COG), not vehicle heading.
- Attach Unitful units to the metre-valued fields of `PVTSolution`/`SatInfo`:
`time_correction`, the `inter_system_biases` values, `InterFrequencyBias.value`
and `SatInfo.residual` are now `typeof(1.0m)`, alongside the degree-valued
`course_over_ground`. The least-squares solver still runs on plain `Float64`;
units are attached only at the output boundary and stripped at the warm-start
seed, so there is no runtime cost.
- Warm-start each IFB column from the previous solution only when that band's
reference band is unchanged; a reference change makes the stored value refer to a
different anchor, so the column is seeded at 0 instead. (The IFB enters the design
linearly, so this affects convergence, not the converged estimate.)
- Fix `calc_uncorrected_time` double-counting the code phase for jointly tracked
satellites: reduce the shared code phase modulo one data symbol so the
whole-symbol part already counted by the bit term is not added twice (a no-op for
single-signal sats). Update the E5a/L2C test fixtures to build realistic
measurements (whole data symbols in the bit count, residual chips in the code
phase) instead of packing the whole sub-TOW interval into the code phase.
BREAKING CHANGE: `PVTSolution` gains a `course_over_ground` field, so the exported
struct's positional-constructor arity/order and field layout change. Several fields
are now Unitful quantities rather than bare `Float64` metres: `time_correction`, the
`inter_system_biases` values and `SatInfo.residual` are `typeof(1.0m)`. And
`inter_frequency_biases` is now `Dict{Symbol,InterFrequencyBias}` — read `.value`
(a `typeof(1.0m)`) and `.reference` (the anchor band) instead of a bare `Float64`.
Consumers doing arithmetic must handle the units (e.g. `ustrip(u"m", x)`), and
positional construction and reflection-based code must be updated. Reading via
keyword construction and the accessor fields is otherwise unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
giove-a
force-pushed
the
sc/enrich-pvt-solution
branch
from
July 7, 2026 09:51
57182f9 to
b17cf63
Compare
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.
feat!: enrich PVT solution with IFB reference bands, units, and course over ground
Summary
Enriches
PVTSolutionwith an explicit inter-frequency-bias representation, acourse-over-ground field, and
Unitfulunits on its metre-valued fields, andtightens the warm-start seeding of the inter-frequency biases. Also fixes a
code-phase double-count in
calc_uncorrected_timefor jointly tracked satellites.This is a breaking release (
4.0.0): thePVTSolutionfield layout and severalfield types change.
What changed
Inter-frequency biases carry their reference band (
InterFrequencyBias)inter_frequency_biasesis nowDict{Symbol, InterFrequencyBias}instead ofDict{Symbol, Float64}. EachInterFrequencyBiasbundles:value::typeof(1.0m)— the bias, in metres, relative toreference;reference::Symbol— the band its bias is measured against (the anchor whosedelay is folded into the clock biases).
The reference band is chosen per coverage component and threaded from
band_ifb_layout→decide_bias_layout→calc_pvt, so each reported bias'sanchor is explicit rather than implicit. A disconnected constellation can in
principle report distinct references per band.
Course over ground
Adds
course_over_ground::typeof(1.0°): the azimuth of the velocity vector in thelocal ENU frame at
position, clockwise from true North, wrapped to[0, 360)°(the GNSS COG convention). It is the velocity-derived direction of motion, not
vehicle heading — a single-antenna receiver cannot observe heading.
0°when thehorizontal velocity is zero. Computed by the new
calc_course_over_groundhelper.Units on metre-valued fields
time_correction, theinter_system_biasesvalues,InterFrequencyBias.value, andSatInfo.residualare nowtypeof(1.0m)Unitfulquantities (joining thedegree-valued
course_over_ground).position/velocitystay plainECEF(Geodesyinterop) and
relative_clock_driftstays dimensionless. The least-squares solverstill runs on plain
Float64; units are attached only at the output boundary andstripped at the warm-start seed, so there is no runtime cost (a
Quantity{Float64}is bit-identical to a
Float64).Reference-aware IFB warm start
Each IFB column is seeded from the previous solution only when that band's reference
band is unchanged. On a reference change the stored value refers to a different
anchor, so the column is seeded at
0instead. The IFB enters the design linearly,so this affects convergence, not the converged estimate.
Fix:
calc_uncorrected_timecode-phase double-countFor jointly tracked satellites, reduce the shared code phase modulo one data symbol
so the whole-symbol part already counted by the bit term is not added twice (a no-op
for single-signal sats). E5a/L2C test fixtures updated to build realistic
measurements (whole data symbols in the bit count, residual chips in the code phase).
Breaking changes / migration
PVTSolutiongainscourse_over_ground, changing the positional-constructorarity/order and the field layout — update positional construction and
reflection-based code. Keyword construction is unaffected.
time_correction,inter_system_biasesvalues, andSatInfo.residualare nowUnitfultypeof(1.0m)quantities, not bareFloat64metres. Code doingarithmetic on them must handle units, e.g.
ustrip(u"m", pvt.time_correction).inter_frequency_biasesis nowDict{Symbol, InterFrequencyBias}. Readpvt.inter_frequency_biases[:L5].value(atypeof(1.0m)) and.reference(the anchor band) instead of a bare
Float64.Testing
updated to compare against
Unitfulquantities) and the newcalc_course_over_groundtests.🤖 Generated with Claude Code