Sidereon.GNSS.PreciseEphemeris (Sidereon v3.0.0)

Copy Markdown View Source

A precise-ephemeris source built directly from samples, with no SP3 text in the loop.

This is the Elixir surface over sidereon-core's sample-backed precise-ephemeris source. The canonical intermediate representation of a precise orbit/clock product is a set of per-satellite ECEF position (+ optional clock) samples on a time axis (Sidereon.GNSS.PreciseEphemerisSample); this module builds an interpolatable source from those samples directly. It drives the exact same interpolation substrate the SP3-parsed source uses, so Sidereon.GNSS.Observables.predict_ranges/3 accepts either kind of source.

A built source is held as a resource handle by the BEAM; evaluation operates on that handle.

Structural validation errors are atoms when they have no satellite payload (:empty, :mixed_timescale, :accuracy_samples_mismatch) and {reason, satellite_id} tuples when they identify a satellite. The latter reasons are :single_sample_satellite, :non_monotonic, :out_of_range, :non_finite, and :invalid_accuracy_value.

Round trip

{:ok, sp3} = Sidereon.GNSS.SP3.load("igs.sp3")
samples = Sidereon.GNSS.SP3.precise_ephemeris_samples(sp3)
{:ok, source} = Sidereon.GNSS.PreciseEphemeris.from_samples(samples)

For samples that are the faithful image of the interpolation fit nodes (the round-trip case above), the rebuilt source interpolates and predicts ranges byte-identically to the SP3-parsed source. Samples carrying lower precision interpolate at that precision.

Summary

Types

A sample-construction refusal, interpolation refusal, or boundary/input conversion error.

Validated error detail for an invalid interpolation policy.

Structural refusal returned while building a sample-backed precise source.

t()

Functions

Build a precise-ephemeris source from a list of Sidereon.GNSS.PreciseEphemerisSample structs.

Build a precise source from samples and identity-aligned accuracy sidecars.

Return the position-interpolation gap threshold factor carried by this sample-backed source.

Evaluate states for parallel satellite and J2000-second arrays.

Evaluate state batches while retaining structured error details for failed rows. Existing observable_states_at_j2000_s/3 behavior is unchanged.

Evaluate states for many satellites at one shared J2000-second epoch.

Return the satellite ids available in this sample-backed precise source.

Types

construction_error()

@type construction_error() ::
  sample_error() | interpolation_error() | atom() | tuple() | String.t()

A sample-construction refusal, interpolation refusal, or boundary/input conversion error.

interpolation_error()

@type interpolation_error() :: %{
  kind: String.t(),
  field: String.t(),
  value: String.t(),
  reason: String.t()
}

Validated error detail for an invalid interpolation policy.

sample_error()

@type sample_error() ::
  :empty
  | {:single_sample_satellite, String.t()}
  | {:non_monotonic, String.t()}
  | :mixed_timescale
  | {:out_of_range, String.t()}
  | {:non_finite, String.t()}
  | :accuracy_samples_mismatch
  | {:invalid_accuracy_value, String.t()}

Structural refusal returned while building a sample-backed precise source.

t()

@type t() :: %Sidereon.GNSS.PreciseEphemeris{
  handle: reference(),
  time_scale: String.t() | nil
}

Functions

from_samples(samples, opts \\ [])

@spec from_samples(
  [Sidereon.GNSS.PreciseEphemerisSample.t()],
  keyword()
) :: {:ok, t()} | {:error, construction_error()}

Build a precise-ephemeris source from a list of Sidereon.GNSS.PreciseEphemerisSample structs.

Samples are grouped by satellite. Each satellite's series must be strictly increasing in epoch and carry at least two samples, and every sample must share one time scale. Returns {:ok, %Sidereon.GNSS.PreciseEphemeris{}}, or {:error, reason} where reason is one of the structural validation reasons:

  • :empty - no samples supplied
  • {:single_sample_satellite, satellite_id} - a satellite has only one sample
  • {:non_monotonic, satellite_id} - a satellite's epochs are not strictly increasing
  • :mixed_timescale - samples carry more than one time scale
  • {:non_finite, satellite_id} - a sample position or clock value was not finite
  • {:out_of_range, satellite_id} - a sample epoch is not representable as J2000 seconds

A malformed satellite token or time scale in a sample is returned verbatim as {:error, reason} without raising. Options:

  • :gap_threshold_factor - multiple of nominal node spacing above which consecutive records mark a coverage gap (default 1.5, must be > 1.0).

A numeric factor at or below 1.0 returns an {:error, %{kind: "sp3_interpolation_options", field: "gap_threshold_factor", ...}} detail with the supplied value and core refusal reason.

from_samples_with_accuracy(samples, accuracy, opts \\ [])

@spec from_samples_with_accuracy(
  [Sidereon.GNSS.PreciseEphemerisSample.t()],
  [Sidereon.GNSS.PreciseEphemerisAccuracySample.t()],
  keyword()
) :: {:ok, t()} | {:error, construction_error()}

Build a precise source from samples and identity-aligned accuracy sidecars.

Returns :accuracy_samples_mismatch if the sidecars do not match the samples, or {:invalid_accuracy_value, satellite_id} when a sidecar's known variance is invalid. Sample validation uses the same typed reasons as from_samples/2. A rejected numeric gap threshold returns the typed interpolation_error() map.

gap_threshold_factor(precise_ephemeris)

@spec gap_threshold_factor(t()) :: float()

Return the position-interpolation gap threshold factor carried by this sample-backed source.

observable_states_at_j2000_s(source, satellites, epochs_j2000_s)

@spec observable_states_at_j2000_s(t(), [String.t()], [number()]) ::
  {:ok, Sidereon.GNSS.PreciseEphemeris.StateBatch.t()} | {:error, term()}

Evaluate states for parallel satellite and J2000-second arrays.

observable_states_at_j2000_s_detailed(source, satellites, epochs_j2000_s)

@spec observable_states_at_j2000_s_detailed(t(), [String.t()], [number()]) ::
  {:ok, Sidereon.GNSS.PreciseEphemeris.StateBatch.t()} | {:error, term()}

Evaluate state batches while retaining structured error details for failed rows. Existing observable_states_at_j2000_s/3 behavior is unchanged.

observable_states_at_shared_j2000_s(source, satellites, epoch_j2000_s)

@spec observable_states_at_shared_j2000_s(t(), [String.t()], number()) ::
  {:ok, Sidereon.GNSS.PreciseEphemeris.StateBatch.t()} | {:error, term()}

Evaluate states for many satellites at one shared J2000-second epoch.

satellites(source)

@spec satellites(t()) :: [String.t()] | {:error, term()}

Return the satellite ids available in this sample-backed precise source.