GNSS Measurement Model¶
Purpose¶
This specification defines the GNSS receiver measurement model implemented by
GnssMeasurement and GNSSMeasurements. The model generates
pseudorange, Doppler, and carrier phase observations from receiver state,
GNSS transmitter ephemerides, receiver/transmitter clock corrections, and
optional propagation delays.
State, Time, and Frame Contract¶
All vectors in this specification are expressed in options.frame. The
current C++ implementation requires receiver and transmitter states to share a
defined common inertial frame; the lunar filtering project uses
Frame::MOON_CI for receiver states and GNSS channel states after
constellation setup.
The receiver state vector is interpreted through
GnssMeasurementOptions::indices:
where
The receiver clock bias b_R and drift d_R are represented in
options.clock_bias_unit. They are converted to SI seconds before entering
the range equations:
Epochs passed to Compute and Precompute are receiver signal-reception
epochs:
The scale of t_R is options.receive_time_scale. GNSS constellation
ephemerides are tabulated in TAI seconds and are evaluated in
options.ephemeris_time_scale; the current implementation enforces TAI for
the ephemeris scale. Cislunar simulations commonly set the receiver receive
epoch scale to TDB and let the measurement model convert receive epochs to TAI
for GNSS ephemeris interpolation.
GNSS Transmitter State Interpolation¶
For each PRN, GnssConstellation::SetSatelliteStates receives tabulated
states
The constellation fits a piecewise Chebyshev model for the six-dimensional state:
where
Runtime satellite state evaluation uses this Chebyshev model. The original
state table may still be carried in each GnssChannel as ephemeris-message
metadata.
Light-Time Iteration¶
For a receiver position r_R(t_R) and transmitter PRN s, the transmit
epoch is solved iteratively in the ephemeris time scale:
The iteration stops when
or when options.light_time_max_iterations is reached. The convergence
tolerance is options.light_time_tolerance_s.
Clock terms and group delays are not used to solve the physical light-time epoch; they enter the measurement equations below.
Geometry¶
After light-time convergence, define
Transmitter Clock Corrections¶
The transmitter effective clock bias is
where tx_clock_bias_s is \(\Delta t_S\),
relativistic_correction_s is \(\Delta t_S^\mathrm{rel}\), and
group_delay_s is \(\Delta t_S^\mathrm{grp}\).
The current transmitter relativistic correction is the state-based broadcast GNSS form
The transmitter effective clock drift is
Propagation Delays¶
Shapiro Delay¶
When options.apply_shapiro_delay is true, the one-way gravitational delay
from the Sun is represented as a range correction:
where
The Sun position \(r_\odot(t_R)\) is supplied by
SetSunPositionProvider or by the default Sun provider. The legacy
options.shapiro_mu and options.shapiro_body_position fields are not
used by the current implementation.
Ionosphere / Plasma Delay¶
The ionosphere/plasma correction is represented as a positive code delay in meters:
It is disabled by default. When
options.apply_ionosphere_plasma_delay is true, the delay is supplied by one
of:
SetCustomIonospherePlasmaDelayModelfor a custom online link-by-link model.SetIonospherePlasmaRayTraceOptionsfor built-in link-by-link evaluation with the plasma ray tracer inenvironment/plasma/tec/raytrace.SetBatchCustomIonospherePlasmaDelayModelfor a custom precompute model over all epochs and all channels.options.default_ionosphere_plasma_delay_mwhen no provider is installed.
The built-in raytrace option calls pecsim::trace_ray directly. The caller
must supply the pecsim::RayTraceConfig and, when desired, the IRI model
selection; GNSSMeasurements does not choose Kp, step size, integrator,
correction method, cutoff radius, or GCPM/IRI settings. The GNSS channel
frequency is copied into RayTraceConfig::freq_Hz by default, but this can
be disabled through use_channel_frequency. Receiver and transmitter
positions are converted from options.frame to
GnssIonospherePlasmaRayTraceOptions::raytrace_frame before tracing, and
the receive epoch is converted from options.receive_time_scale to
raytrace_epoch_scale.
The raytracer returns a path profile. The GNSS measurement uses
PathProfile::tec_delay_m by default:
When delay_mode is TEC_PLUS_HIGHER_ORDER, the second- and third-order
terms reported by the raytracer are added to this code delay.
The sign convention is dispersive:
Observable Equations¶
Let
The receiver clock range and range-rate terms are
The transmitter clock range and range-rate terms are
Pseudorange¶
The pseudorange observable is
Doppler¶
The Doppler observable in Hz is
The current implementation does not include time derivatives of Shapiro or plasma delay in Doppler.
Carrier Phase¶
The non-integer carrier phase observable in cycles is
where \(\phi_0\) is phase_bias_cycles.
If the measurement state includes an integer ambiguity \(N\), the emitted carrier observable is
Visibility and Channel Selection¶
Visibility is receiver-dependent and is evaluated in GNSSMeasurements.
For each occluding body, the line of sight is retained only if the spherical
body does not block the receiver-transmitter segment.
For near-surface points, visibility is evaluated using an elevation threshold
For space-to-space links, visibility is evaluated using a tangent-line occlusion test. C/N0 thresholding is then optionally applied:
Noise and Covariance¶
For each selected channel, the measurement covariance is diagonal in the current implementation:
using the subset and order requested by options.observables.
When C/N0 is finite, the tracking-loop noise models provide:
If a channel does not have a finite positive standard deviation for an
observable, the filter wrapper uses a fallback standard deviation of 1 in
that observable’s native unit.
Jacobian Convention¶
The analytic Jacobian currently includes first-order derivatives of geometric range, range rate, receiver clock bias, receiver clock drift, and optional carrier integer ambiguity with respect to the receiver state.
For pseudorange:
For Doppler:
For carrier phase:
Derivatives of transmitter ephemeris interpolation, light-time coupling, Shapiro delay, plasma delay, and C/N0-based noise with respect to receiver state are not included in the current analytic Jacobian.
Online and Precompute Equivalence¶
The online path computes
one epoch at a time.
The precompute path computes the same measurement epochs for vectors
receive_times and user_states:
When a batch ionosphere/plasma provider is configured, precompute first builds all light-time-corrected channels without running the online plasma model:
then calls the batch provider to fill \(\Delta \rho_{\mathrm{plasma},ij}\) for each epoch/channel before evaluating the observables. This keeps visibility, light-time, transmitter clock terms, and batch plasma simulation ordered explicitly, and it avoids doing an online raytrace that would be overwritten by the batch result.
In the staged Lunar GNSS ODTS scenario, this contract is implemented with an
explicit file boundary: LunarGnssODTSSimulation::Precompute writes all
light-time-corrected links with zero plasma delay, precompute_delays.py
fills the delay terms with GCPM/IRI ray tracing, and
LunarGnssODTSSimulation::Run merges the delay file back into the truth
channels before generating pseudorange, Doppler, and optional TDCP
measurements. TDCP is represented as a carrier-range difference in meters and
is processed by the UDU stochastic-cloning filter because its measurement model
depends on both the current and previous receiver state.