A compact, fitted mean-element approximation of a satellite's orbit.
Sidereon.GNSS.ReducedOrbit fits a list of ECEF position samples into a compact
mean-element model that can be evaluated cheaply. It is not orbit
determination and not a substitute for SGP4 or precise ephemeris: it
deliberately discards short-period structure and reports the residual it leaves
behind (rms_m/max_m on the fit, and sample-backed drift/3).
Models
Two models are available, chosen with the :model option on fit/2:
:circular_secular(the default) - a circular orbit intended for near-circular orbits (Galileo).:eccentric_secular- adds eccentricity through a nonsingular(h, k)parameterization, recovering the radiala·esignal (~hundreds of km for GPS/BeiDou) while degrading smoothly to the circular model ase -> 0.
circular_secular
A circular orbit (eccentricity fixed at zero) whose orbital plane precesses at
a constant nodal rate. At an offset dt = t - t0 from the reference epoch the
angles advance linearly,
u(t) = arg_lat0 + n * dt # argument of latitude
raan(t) = raan0 + raan_rate * dt
e = 0and the inertial (GCRS) position is the in-plane circle rotated by the node and
inclination, r = Rz(raan) * Rx(i) * a * [cos u, sin u, 0].
The nodal rate raan_rate is fitted, but seeded from the J2 secular nodal
regression (Vallado, Fundamentals of Astrodynamics and Applications):
raan_rate_j2 = -1.5 * n * J2 * (Re / a)^2 * cos(i)Both the fitted value (raan_rate_rad_s) and the J2 seed (raan_rate_j2_rad_s)
are kept; raan_rate_mode is "fitted_j2_seeded". The model does not claim to
be a pure J2 propagation.
eccentric_secular
Eight free elements: the four circular plane elements plus h = e·sin ω,
k = e·cos ω, L0 (mean argument of latitude at epoch), and n. The core
fit returns e and ω. At an offset dt the model advances
λ = L0 + n·dt, forms the mean anomaly M = λ − ω, solves Kepler's equation
E − e·sin E = M, and places the satellite at radius r = a(1 − e·cos E) and
argument of latitude u = ω + ν. The (h, k) form is nonsingular: at e = 0
it reproduces circular_secular exactly with arg_lat0 = L0. The struct then
carries h, k, e, and arg_perigee_rad (= ω).
Frames
Fitting and evaluation run internally in GCRS; positions are returned in
ECEF (ITRF) meters by default, or GCRS via frame: :gcrs. ECEF velocity
includes the Earth-rotation transport term. Sample/query epochs are interpreted
consistently for the Earth-rotation conversion; the ECEF product (the primary
output) is self-consistent across the fit, evaluation, and drift.
Expected accuracy
Representative drift values depend on the sample span, cadence, and orbit class.
Measure a fitted model with drift/3 against caller-provided truth samples.
This is a compact approximation for caching or visibility, never a substitute for precise source data.
Summary
Functions
Evaluate the model error against truth samples.
Fit a mean-element model to ECEF samples.
Position of the model at epoch, ECEF (ITRF) meters by default.
Position and velocity of the model at epoch.
Types
@type t() :: %Sidereon.GNSS.ReducedOrbit{ a_m: float(), arg_lat_rad: float(), arg_perigee_rad: float() | nil, e: float(), epoch: NaiveDateTime.t(), fit: map(), frame: String.t(), h: float() | nil, i_rad: float(), k: float() | nil, mean_motion_rad_s: float(), model: String.t(), raan_rad: float(), raan_rate_j2_rad_s: float(), raan_rate_mode: String.t(), raan_rate_rad_s: float(), time_scale: String.t(), version: pos_integer() }
Functions
@spec drift(t(), [{epoch(), {number(), number(), number()}}], keyword()) :: {:ok, map()} | {:error, term()}
Evaluate the model error against truth samples.
Returns
{:ok, %{per_epoch: [%{epoch:, error_m:}], max_m:, rms_m:, threshold_horizon:,
requested:, used:}}where threshold_horizon is the first epoch the ECEF error exceeds
:threshold_m (or nil if it never does / no threshold given).
@spec fit( [{epoch(), {number(), number(), number()}}], keyword() ) :: {:ok, t()} | {:error, term()}
Fit a mean-element model to ECEF samples.
Options
:model-:circular_secular(default) or:eccentric_secular. The circular model fixes eccentricity at zero (suited to near-circular orbits); the eccentric model recovers thea·eradial signal for GPS and other eccentric orbits. See the moduledoc accuracy table.:frame-:ecef(default):time_scale- the scale the sample epochs are in ("UTC"default)
Epochs are interpreted in the model's time scale (recorded on the result). The
reference epoch t0 is the earliest sample, so the result is independent of the
caller's sample order.
Returns {:ok, %Sidereon.GNSS.ReducedOrbit{}} or a tagged error:
{:too_few_samples, got, required}, :invalid_window, :invalid_cadence,
:singular_plane_fit, :raan_ambiguous, {:unsupported_source_frame, frame},
{:unsupported_model, model}, :transform_unavailable, :fit_did_not_converge.
Position of the model at epoch, ECEF (ITRF) meters by default.
Pass frame: :gcrs for the inertial position. Returns
{:ok, %{x_m:, y_m:, z_m:}} or {:error, reason}.
Position and velocity of the model at epoch.
ECEF velocity includes the Earth-rotation transport term. Returns
{:ok, %{position: %{x_m:, y_m:, z_m:}, velocity: %{vx_m_s:, vy_m_s:, vz_m_s:}}}.