Sidereon.GNSS.Positioning.Solution (Sidereon v3.0.0)

Copy Markdown View Source

A single-point-positioning solution at one receive epoch.

position is the converged ITRF/IGS ECEF position in meters. geodetic is the same point as %{lat_rad, lon_rad, height_m} when geodetic output was requested (the default), otherwise nil. rx_clock_s is the reference-system receiver clock bias in seconds; system_clocks_s is a map of GNSS letter (e.g. "G", "E") to that system's absolute receiver clock in seconds (a single entry for a one-system solve, one per constellation for a mixed solve). These are per-system clocks, not biases: the inter-system bias of a system is its clock minus the reference system's (rx_clock_s). dop carries the dilution-of-precision scalars for any full-rank geometry; a single-system solve uses the bit-exact four-state cofactor, a multi-system solve a general inverse with one clock column per constellation, and is nil only when the geometry is rank-deficient. system_tdops is a map of GNSS letter to that system's time DOP (the square root of its clock cofactor variance), one entry per constellation in the solve; the reference system's value equals dop.tdop, and the map is empty when the geometry is rank-deficient. rx_clock_drift_s_s is populated by solve_with_doppler/5 and is nil for pseudorange-only solves. position_covariance carries the unit-variance ECEF and local ENU position covariance blocks in square metres. residuals_m are the post-fit pseudorange residuals in meters, in used_sats order. pseudorange_variances_m2 and effective weights are aligned to the same satellites; the former are the estimator's code variances in square metres, while the latter are inverse variances and include final Huber factors when robust reweighting is enabled. used_sats are the contributing satellite id strings (e.g. "G01"); rejected_sats pairs each excluded satellite id with its reason. Strict SSR size refusals retain {:ssr_correction_exceeds_limit, %{orbit_m: value, clock_m: value}}. (the ionosphere correction was requested and the satellite has no resolvable carrier, such as a GLONASS satellite with no channel or a channel outside -7..6). A satellite is reported with the first reason that applies, tested in that order. metadata reports solver iterations, convergence, the corrections applied, and the geometry redundancy: used_count, the distinct systems, the redundancy (degrees of freedom, used_count - (3 + systems)), raim_checkable? (redundancy >= 1), and geometry_quality with the core observability tier, rank, condition number, GDOP, RAIM checkability, and covariance-validation flag. An exactly determined fix has redundancy < 1, forcing the residuals near zero and leaving the fix unverifiable by RAIM. When the opt-in :huber reweighting runs, metadata also carries :huber with the outer_iterations count and the final_scale_m (the last MAD robust scale in meters); the key is absent on the default static path.

Summary

Types

Dilution-of-precision scalars for the solved geometry.

Receiver geodetic position in radians and metres.

Solver metadata and applied correction flags. converged describes how the whole solve ended.

Receiver ECEF position in metres.

Unit-variance receiver position covariance blocks.

Why a satellite was left out of the solve, the first reason that applies in this order.

How a solve ended. The first four are the trust-region solver's own termination states. :selection_settled is a converged SPP or static solve: a least-squares step below 1e-4 m at a satellite selection that held, RTKLIB estpos's norm(dx) < 1E-4. :outer_budget_exhausted is a robust-reweighted solve that ran out of outer iterations before it settled; converged is then false.

t()

Decoded single-point-positioning receiver solution.

Types

dop()

@type dop() :: %{
  gdop: float(),
  pdop: float(),
  hdop: float(),
  vdop: float(),
  tdop: float()
}

Dilution-of-precision scalars for the solved geometry.

geodetic()

@type geodetic() :: %{lat_rad: float(), lon_rad: float(), height_m: float()}

Receiver geodetic position in radians and metres.

metadata()

@type metadata() :: %{
  :iterations => non_neg_integer(),
  :converged => boolean(),
  :status => status(),
  :ionosphere_applied => boolean(),
  :troposphere_applied => boolean(),
  :used_count => non_neg_integer(),
  :systems => [String.t()],
  :redundancy => integer(),
  :raim_checkable? => boolean(),
  :geometry_quality => Sidereon.GeometryQuality.t(),
  :ut1_degraded => nil | :before_coverage | :after_coverage,
  optional(:fde) => %{
    excluded: [{String.t(), :raim_excluded}],
    iterations: non_neg_integer(),
    raim: Sidereon.GNSS.QC.raim_result()
  },
  optional(:huber) => %{
    outer_iterations: non_neg_integer(),
    final_scale_m: float()
  }
}

Solver metadata and applied correction flags. converged describes how the whole solve ended.

position()

@type position() :: %{x_m: float(), y_m: float(), z_m: float()}

Receiver ECEF position in metres.

position_covariance()

@type position_covariance() :: %{ecef_m2: [[float()]], enu_m2: [[float()]]}

Unit-variance receiver position covariance blocks.

rejection_reason()

@type rejection_reason() ::
  :no_ephemeris
  | :low_elevation
  | :sbas_withdrawn
  | :sbas_iono_uncovered
  | :ionosphere_carrier_unresolved
  | {:ssr_correction_exceeds_limit, %{orbit_m: float(), clock_m: float()}}

Why a satellite was left out of the solve, the first reason that applies in this order.

status()

@type status() ::
  :gradient_tolerance
  | :cost_tolerance
  | :step_tolerance
  | :max_evaluations
  | :selection_settled
  | :outer_budget_exhausted
  | :outer_oscillation

How a solve ended. The first four are the trust-region solver's own termination states. :selection_settled is a converged SPP or static solve: a least-squares step below 1e-4 m at a satellite selection that held, RTKLIB estpos's norm(dx) < 1E-4. :outer_budget_exhausted is a robust-reweighted solve that ran out of outer iterations before it settled; converged is then false.

t()

@type t() :: %Sidereon.GNSS.Positioning.Solution{
  dop: dop() | nil,
  geodetic: geodetic() | nil,
  metadata: metadata(),
  position: position(),
  position_covariance: position_covariance(),
  pseudorange_variances_m2: [float()] | nil,
  rejected_sats: [{String.t(), rejection_reason()}],
  residuals_m: [float()],
  rx_clock_drift_s_s: float() | nil,
  rx_clock_s: float(),
  system_clocks_s: %{required(String.t()) => float()},
  system_tdops: %{required(String.t()) => float()},
  used_sats: [String.t()],
  weights: [float()] | nil
}

Decoded single-point-positioning receiver solution.