Broadcast-ephemeris accuracy: compare a broadcast navigation product against a precise SP3 product over a window.
This is the standard broadcast-orbit / clock accuracy check (the orbit and clock pieces of the signal-in-space range error, SISRE). For each satellite at each epoch it differences the broadcast-evaluated ECEF position and clock against the precise SP3 values, decomposes the position error into radial / along-track / cross-track (RAC) components, and summarizes the differences as RMS and maximum statistics per satellite and overall.
Both products are evaluated through Orbis.GNSS.Ephemeris, so the frame
(ITRF/IGS ECEF, meters), the time scale (GPST), and the clock sign convention
(positive = satellite clock ahead of system time) are exactly as documented
there. Only epochs where both sources return a valid state contribute to the
statistics; an epoch missing from either product is skipped, never extrapolated.
RAC frame
The radial/along-track/cross-track unit vectors are built from the precise
state: radial along the position vector, cross-track along the orbital angular
momentum r x v, and along-track completing the right-handed triad. The SP3
position/clock interpolation does not expose a velocity, so the velocity is
derived by a centered finite difference of the precise position
((r(t+dt) - r(t-dt)) / 2dt, falling back to a one-sided difference at a window
edge). The position-difference vector broadcast - precise is projected onto
this triad.
Expected magnitudes
GPS LNAV broadcast orbits differ from IGS precise orbits at roughly the 1-2 m RMS level (3D), dominated by the along-track and radial components; Galileo and BeiDou MEO are comparable. A result far outside this band (tens of meters or more) indicates a parse or evaluation defect rather than normal broadcast error.
The broadcast models follow IS-GPS-200 (GPS LNAV), the Galileo OS-SIS-ICD, and the BeiDou BDS-SIS-ICD; the precise product is SP3-c / SP3-d (IGS).
Example
{:ok, broadcast} = Orbis.GNSS.Broadcast.load("BRDC.rnx")
{:ok, sp3} = Orbis.GNSS.SP3.load("igs.sp3")
report =
Orbis.GNSS.BroadcastComparison.compare(broadcast, sp3, ["G01", "E11"], %{
from: ~N[2020-06-25 02:00:00],
to: ~N[2020-06-25 04:00:00],
step_s: 300
})
report.overall.orbit_3d_rms_m # 3D orbit RMS over all satellites, meters
report.per_satellite["G01"].radial_rms_mBroadcast-vs-precise on a sample day
Comparing the GPS LNAV broadcast message against the GBM precise SP3 product for
2020 day-of-year 177 — all GPS satellites over a multi-hour window at a 15 min
step — gives an overall 3D orbit RMS of about 1.5 m (max ~4 m), split as
roughly 1.1 m radial / 0.9 m along-track / 0.5 m cross-track, the expected GPS
broadcast accuracy. The raw clock differences (clock_rms_m) are larger
(several meters) because the broadcast and precise clocks are referenced to
different time datums, which differ by a common per-epoch offset that drifts
over the day. clock_datum_removed_rms_m removes that common offset (the
per-epoch median over satellites) and reports the actual signal-in-space clock
error, which is several times smaller.
The same call works against a broadcast product with no change of shape, so
mix gnss.broadcast_diff --nav BRDC.rnx --sp3 igs.sp3 --from ... --to ...
prints this table from the command line.
Summary
Functions
Compare a broadcast product against a precise SP3 product over window.
Functions
@spec compare( Orbis.GNSS.Broadcast.t(), Orbis.GNSS.SP3.t(), [String.t()], Orbis.GNSS.Ephemeris.window() ) :: Orbis.GNSS.BroadcastComparison.Report.t()
Compare a broadcast product against a precise SP3 product over window.
broadcast is an Orbis.GNSS.Broadcast handle and precise an
Orbis.GNSS.SP3 handle for the same day; sat_ids is a list of canonical
RINEX tokens; window is the Orbis.GNSS.Ephemeris window map (:from,
:to, :step_s). Returns an Orbis.GNSS.BroadcastComparison.Report.
The window should sit within both the SP3 file span and the broadcast records'
fit intervals; epochs missing from either product are counted in
report.missing and excluded from the statistics.