Orbis.GNSS.SolutionReport (Orbis v0.9.0)

Copy Markdown View Source

A consolidated, read-only diagnostic for a single-point-positioning result.

Given an already-computed Orbis.GNSS.Positioning.Solution, an ephemeris source, and the receive epoch, build/4 assembles one report that explains the solved position: the per-satellite sky geometry (elevation / azimuth), the post-fit pseudorange residuals, the RAIM integrity verdict and per- satellite normalized residuals, and a top-level solution summary including the dilution-of-precision scalars and the residual RMS.

This module performs no estimation. Every value is read straight from an existing primitive, so each field is traceable to its source:

  • residual_m is copied from Solution.residuals_m, paired with Solution.used_sats by index (the same pairing Orbis.GNSS.QC.raim/2 uses);
  • normalized_residual is copied from Orbis.GNSS.QC.raim/2's normalized_residuals map;
  • elevation_deg / azimuth_deg come from Orbis.GNSS.Observables.predict/5 evaluated at the solved position, with predict's defaults (light-time and Sagnac corrections on);
  • dop, geodetic, the ECEF position, metadata, and every integrity scalar are passed through verbatim;
  • residual_rms_m is the only newly derived scalar — the root mean square of the post-fit residuals over the used satellites.

Row ordering

Satellite rows are emitted used satellites first, then rejected satellites; within each group rows are sorted by elevation_deg descending, with nil elevation last (a rejected satellite with no ephemeris cannot be located in the sky).

Example

{:ok, solution} = Orbis.GNSS.Positioning.solve(sp3, observations, epoch)
{:ok, report} = Orbis.GNSS.SolutionReport.build(solution, sp3, epoch)

report.summary.residual_rms_m
report.summary.integrity.fault_detected?

report |> Orbis.GNSS.SolutionReport.format() |> Enum.each(&IO.puts/1)

Summary

Functions

Assemble a %Orbis.GNSS.SolutionReport{} from a solved result, its ephemeris source, and the receive epoch.

Render an already-built report as a deterministic list of human-readable lines: a summary header followed by one line per satellite row, in the report's row order.

Types

satellite_row()

@type satellite_row() :: %{
  satellite_id: String.t(),
  used?: boolean(),
  elevation_deg: float() | nil,
  azimuth_deg: float() | nil,
  residual_m: float() | nil,
  normalized_residual: float() | nil,
  rejected_reason: atom() | nil
}

summary()

@type summary() :: %{
  position: %{ecef: map(), geodetic: map() | nil},
  n_used: non_neg_integer(),
  n_rejected: non_neg_integer(),
  dop: map() | nil,
  residual_rms_m: float(),
  integrity: map(),
  metadata: map(),
  status: atom()
}

t()

@type t() :: %Orbis.GNSS.SolutionReport{
  satellites: [satellite_row()],
  summary: summary()
}

Functions

build(solution, source, epoch, opts \\ [])

@spec build(
  Orbis.GNSS.Positioning.Solution.t(),
  Orbis.GNSS.SP3.t(),
  NaiveDateTime.t(),
  keyword()
) ::
  {:ok, t()} | {:error, term()}

Assemble a %Orbis.GNSS.SolutionReport{} from a solved result, its ephemeris source, and the receive epoch.

Returns {:ok, report} on success or a tagged {:error, reason} for a malformed solution, source, or epoch. Never raises.

Options

  • :raim - a keyword list forwarded verbatim to Orbis.GNSS.QC.raim/2 (supports :p_fa, :weights, :n_systems).
  • :weights, :p_fa - convenience top-level options merged into the :raim options. A value given here takes precedence over the same key inside :raim.

The integrity block and per-satellite normalized residuals come from the single Orbis.GNSS.QC.raim/2 call those options drive, so the report cannot diverge from RAIM.

format(solution_report)

@spec format(t()) :: [String.t()]

Render an already-built report as a deterministic list of human-readable lines: a summary header followed by one line per satellite row, in the report's row order.

Pure formatting — it performs no new computation and calls no primitive.

summary_lines(report)

@spec summary_lines(t()) :: [String.t()]

Alias for format/1.