GNSS single-point positioning (SPP): recover a receiver position, clock bias, and geometry diagnostics from one epoch of pseudorange observations against a precise SP3 ephemeris or a broadcast navigation product.
This is the Elixir surface over the astrodynamics-gnss SPP solver. Given an
ephemeris source — an Orbis.SP3 product or an Orbis.BroadcastEphemeris
handle (GPS / Galileo / BeiDou / GLONASS) — a set of single-frequency
pseudoranges, the receive epoch, and the broadcast/atmosphere parameters, it
runs the transmit-time iteration and trust-region least-squares solve in the
crate and returns an Orbis.PointPositioning.Solution. A mixed-constellation
set is solved together with one receiver clock per system. No positioning math
lives on the Elixir side; this module marshals units and epoch arguments and
decodes the result.
Units at the boundary
- pseudoranges and the initial guess position/clock are meters;
- the recovered
positionis ITRF/IGS ECEF meters, matching the SP3 frame; geodeticlatitude/longitude are radians and height is meters;rx_clock_sis seconds;- pressure is hPa, temperature is kelvin, relative humidity is a
fraction in
[0, 1]; - the Klobuchar
alpha/betacoefficients are passed in their broadcast units.
The epoch is interpreted in the SP3 product's own time scale (typically GPST);
no leap-second shifting is applied. The seconds-since-J2000, second-of-day, and
fractional day-of-year arguments the crate needs are derived from the supplied
epoch via Orbis.GnssTime.
Example
{:ok, sp3} = Orbis.SP3.load("igs.sp3")
observations = [{"G01", 2.41e7}, {"G02", 2.49e7}, {"G05", 2.05e7}, {"G07", 2.30e7}]
{:ok, solution} =
Orbis.PointPositioning.solve(sp3, observations, ~N[2020-06-24 12:00:00],
ionosphere: true,
troposphere: true,
klobuchar_alpha: {1.0e-8, 2.2e-8, -6.0e-8, -1.2e-7},
klobuchar_beta: {96_256.0, 131_072.0, -65_536.0, -589_824.0}
)
solution.position.x_m
solution.rx_clock_s
Summary
Types
An epoch as a NaiveDateTime or {{y, m, d}, {h, min, s}} tuple.
A {satellite_id, pseudorange_m} pseudorange observation.
Functions
Solve single-point positioning for one receive epoch.
Types
@type epoch() :: NaiveDateTime.t() | tuple()
An epoch as a NaiveDateTime or {{y, m, d}, {h, min, s}} tuple.
A {satellite_id, pseudorange_m} pseudorange observation.
Functions
@spec solve( Orbis.SP3.t() | Orbis.BroadcastEphemeris.t(), [observation()], epoch(), keyword() ) :: {:ok, Orbis.PointPositioning.Solution.t()} | {:error, term()}
Solve single-point positioning for one receive epoch.
source is a loaded ephemeris product — an Orbis.SP3 precise product or an
Orbis.BroadcastEphemeris broadcast-navigation product. observations is a
list of {satellite_id, pseudorange_m} pairs (ids like "G01", pseudoranges
in meters), and epoch is a NaiveDateTime or {{y, m, d}, {h, min, s}}
tuple in the product's time scale.
Options
:ionosphere- apply the broadcast Klobuchar ionosphere correction (defaultfalse); the L1 delay is scaled to each satellite's carrier by(f_L1/f)^2, covering GPS L1, Galileo E1, and BeiDou B1I (a system with no modeled single-frequency carrier, e.g. GLONASS, is rejected):troposphere- apply the Saastamoinen/Niell troposphere correction (defaultfalse):klobuchar_alpha- broadcast alpha coefficients, 4-tuple (default zeros):klobuchar_beta- broadcast beta coefficients, 4-tuple (default zeros):pressure_hpa- surface pressure, hPa (default1013.25):temperature_k- surface temperature, kelvin (default288.15):relative_humidity- relative humidity fraction[0, 1](default0.5):initial_guess-{x_m, y_m, z_m, b_m}start point (default all zeros):with_geodetic- also return the geodetic position (defaulttrue)
A mixed GPS+Galileo+BeiDou+GLONASS observation set is solved together with one receiver clock per GNSS (an inter-system bias is the difference between a system's clock and the reference system's), and dilution of precision is reported for the combined geometry as well.
Returns {:ok, %Orbis.PointPositioning.Solution{}} or {:error, reason},
where reason is one of {:too_few_satellites, used, required} (required is
3 + n_systems), :singular_geometry, {:duplicate_observation, sat},
{:ephemeris_lost, sat}, or {:ionosphere_unsupported, sat} (the ionosphere
correction was requested for a system with no modeled single-frequency carrier).