Sidereon.GNSS.SBAS (Sidereon v3.0.0)

Copy Markdown View Source

Satellite-based augmentation corrections.

The correction store, SBAS message decoding, corrected broadcast ephemeris source, and corrected SPP solve all delegate to the core SBAS implementation.

Summary

Functions

Evaluate an SBAS-corrected broadcast satellite state.

Evaluate an SBAS-corrected state at exact state and broadcast-selection queries.

Decode one 250-bit framed or 226-bit body SBAS message under the strict policy, which refuses a preamble other than 0x53, 0x9A and 0xC6.

Decode one 250-bit framed or 226-bit body SBAS message or raise.

Decode one SBAS block under policy.

Encode a raw unsupported SBAS payload.

Read SBAS-source position variance at independent exact state and selection queries.

Create an empty correction store.

Parse ESA EMS-style SBAS log lines under the strict policy.

Parse ESA EMS-style SBAS log lines or raise.

Read an EMS log, keeping every line's disposition; see Sidereon.GNSS.SBAS.Log.

Parse RTKLIB SBAS log lines under the strict policy; errors as parse_ems/1.

Parse RTKLIB SBAS log lines or raise.

Read an RTKLIB SBAS log, keeping every line's disposition; options as parse_ems_log/2.

Return ready SBAS GEO ids for an epoch.

Sample an SBAS-corrected broadcast source over a grid.

Read an SBAS-selected state using exact state and broadcast-selection queries.

Run SPP against an SBAS-corrected broadcast source.

Run SPP at an exact receive epoch against an SBAS-corrected broadcast source.

Build a correction store from EMS log text.

Build a correction store from decoded message tuples.

Build a correction store from RTKLIB SBAS log text.

Read the SBAS transmission-placement clock at exact state and selection queries.

Count the corrections a source GEO addressed to active PRN-mask bits that name no satellite, per 1-based PRN mask number.

Types

departure()

@type departure() ::
  {:unrecognized_preamble, 0..255} | {:declared_message_type, 0..63, 0..63}

epoch()

@type epoch() :: NaiveDateTime.t() | tuple() | number()

error()

@type error() ::
  :not_found
  | :invalid_input
  | String.t()
  | {:sbas_encode_error, sbas_encode_error_fields()}
  | Sidereon.argument_error()

policy()

@type policy() :: :strict | :lenient

sbas_encode_error_fields()

@type sbas_encode_error_fields() :: %{
  variant: String.t(),
  message_type: non_neg_integer() | nil,
  field: String.t() | nil,
  index: non_neg_integer() | nil,
  value: String.t() | nil,
  width: non_neg_integer() | nil,
  signed: boolean() | nil,
  preamble: non_neg_integer() | nil,
  bytes: non_neg_integer() | nil,
  bits_past_payload: boolean() | nil,
  part: String.t() | nil,
  expected: [integer()] | nil,
  found: [integer()] | nil,
  expected_count: non_neg_integer() | nil,
  found_count: non_neg_integer() | nil,
  half: non_neg_integer() | nil,
  velocity_code: boolean() | nil,
  record: non_neg_integer() | nil,
  reason: String.t() | nil
}

t()

@type t() :: %Sidereon.GNSS.SBAS{handle: reference()}

Functions

clock_relativity_for_state_at_epoch_query(broadcast, store, geo_id, satellite_id, state_query, position_ecef_m, opts \\ [])

@spec clock_relativity_for_state_at_epoch_query(
  Sidereon.GNSS.Broadcast.t(),
  t(),
  String.t(),
  String.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  {number(), number(), number()},
  keyword()
) :: :not_applicable | :unavailable | {:term, float()} | {:error, term()}

Evaluate SBAS-source clock relativity for a state at its exact query.

corrected_position(broadcast, sbas, geo_id, satellite_id, epoch, opts \\ [])

Evaluate an SBAS-corrected broadcast satellite state.

corrected_position!(broadcast, store, geo_id, satellite_id, epoch, opts \\ [])

corrected_position_at_epoch_query(broadcast, store, geo_id, satellite_id, epoch, opts \\ [])

@spec corrected_position_at_epoch_query(
  Sidereon.GNSS.Broadcast.t(),
  t(),
  String.t(),
  String.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Evaluate an SBAS-corrected state at exact state and broadcast-selection queries.

decode(bytes, form \\ :body_226)

@spec decode(binary(), atom() | String.t()) ::
  {:ok, Sidereon.GNSS.SBAS.Message.t()} | {:error, error()}

Decode one 250-bit framed or 226-bit body SBAS message under the strict policy, which refuses a preamble other than 0x53, 0x9A and 0xC6.

decode!(bytes, form \\ :body_226)

@spec decode!(binary(), atom() | String.t()) :: Sidereon.GNSS.SBAS.Message.t()

Decode one 250-bit framed or 226-bit body SBAS message or raise.

decode_with_policy(bytes, form, policy)

@spec decode_with_policy(binary(), atom() | String.t(), policy()) ::
  {:ok, Sidereon.GNSS.SBAS.Message.t(),
   %{pad_bits: 0..63, departures: [departure()]}}
  | {:error, error()}

Decode one SBAS block under policy.

Returns {:ok, message, %{pad_bits: bits, departures: departures}}: pad_bits are the six bits completing the last byte, as read, and departures those read under :lenient (a preamble other than the three SBAS values, as {:unrecognized_preamble, preamble}). A length or CRC failure is refused under both policies.

encode_unsupported(message_type, preamble, data, opts \\ [])

@spec encode_unsupported(0..63, 0..255, binary(), keyword()) ::
  {:ok, binary(), [departure()]} | {:error, error()}

Encode a raw unsupported SBAS payload.

data must hold the 27-byte 212-bit payload. Options select :form (:body_226 by default), :policy (:strict by default), and :pad_bits (zero by default). Strict mode returns typed :sbas_encode_error fields for encoder refusals; lenient mode reports an unrecognized preamble as a departure.

ephemeris_variance_at_epoch_queries(broadcast, store, geo_id, satellite_id, state_query, selection_query, opts \\ [])

@spec ephemeris_variance_at_epoch_queries(
  Sidereon.GNSS.Broadcast.t(),
  t(),
  String.t(),
  String.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  keyword()
) :: float() | nil | {:error, term()}

Read SBAS-source position variance at independent exact state and selection queries.

fast(sbas, geo_id, satellite_id)

fast!(store, geo_id, satellite_id)

geo_nav(sbas, geo_id)

geo_nav!(store, geo_id)

iono_grid(sbas, geo_id)

iono_grid!(store, geo_id)

long_term(sbas, geo_id, satellite_id)

long_term!(store, geo_id, satellite_id)

new(opts \\ [])

@spec new(keyword()) :: t()

Create an empty correction store.

parse_ems(text)

@spec parse_ems(String.t()) ::
  {:ok, [Sidereon.GNSS.SBAS.LogBlock.t()]} | {:error, term()}

Parse ESA EMS-style SBAS log lines under the strict policy.

Returns {:error, reason} for a record line the log reader would refuse or leave unread; parse_ems_log/2 reads the rest of such a log and reports it.

parse_ems!(text)

@spec parse_ems!(String.t()) :: [Sidereon.GNSS.SBAS.LogBlock.t()]

Parse ESA EMS-style SBAS log lines or raise.

parse_ems_log(text, opts \\ [])

@spec parse_ems_log(
  String.t(),
  keyword()
) :: {:ok, Sidereon.GNSS.SBAS.Log.t()} | {:error, term()}

Read an EMS log, keeping every line's disposition; see Sidereon.GNSS.SBAS.Log.

Options: :policy (:strict by default; :lenient reads a record whose declared message type differs from the type its message carries and reports it) and :reference_week (a full GPS week near the log's time, which resolves a NovAtel OEM3 10-bit week).

parse_rtklib(text)

@spec parse_rtklib(String.t()) ::
  {:ok, [Sidereon.GNSS.SBAS.LogBlock.t()]} | {:error, term()}

Parse RTKLIB SBAS log lines under the strict policy; errors as parse_ems/1.

parse_rtklib!(text)

@spec parse_rtklib!(String.t()) :: [Sidereon.GNSS.SBAS.LogBlock.t()]

Parse RTKLIB SBAS log lines or raise.

parse_rtklib_log(text, opts \\ [])

@spec parse_rtklib_log(
  String.t(),
  keyword()
) :: {:ok, Sidereon.GNSS.SBAS.Log.t()} | {:error, term()}

Read an RTKLIB SBAS log, keeping every line's disposition; options as parse_ems_log/2.

ready_geos(sbas, epoch)

Return ready SBAS GEO ids for an epoch.

ready_geos!(store, epoch)

sample(broadcast, sbas, geo_id, satellites, arg, step_s, opts \\ [])

Sample an SBAS-corrected broadcast source over a grid.

sample!(broadcast, store, geo_id, satellites, window, step_s, opts \\ [])

sbas_protection_levels(geometry, error_model, k \\ SbasKMultipliers.precision_approach())

Compute SBAS horizontal and vertical protection levels.

The error model supplies one range-error budget per geometry row. Returned values are meters except :d_en_m2, which is square meters.

selected_state_at_epoch_queries(broadcast, store, geo_id, satellite_id, state_query, selection_query, opts \\ [])

@spec selected_state_at_epoch_queries(
  Sidereon.GNSS.Broadcast.t(),
  t(),
  String.t(),
  String.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  keyword()
) :: {:ok, map() | nil} | {:error, term()}

Read an SBAS-selected state using exact state and broadcast-selection queries.

solve_broadcast(broadcast, sbas, geo_id, observations, epoch, opts \\ [])

Run SPP against an SBAS-corrected broadcast source.

The :qzss_clock (:gps or :separate) and :troposphere_model (:rtklib or :saastamoinen_niell) options select the core solve models.

solve_broadcast!(broadcast, store, geo_id, observations, epoch, opts \\ [])

solve_broadcast_at_exact_epoch(broadcast, store, geo_id, observations, civil_epoch, exact_epoch, opts \\ [])

@spec solve_broadcast_at_exact_epoch(
  Sidereon.GNSS.Broadcast.t(),
  t(),
  String.t(),
  [{String.t(), number()}],
  epoch(),
  Sidereon.GNSS.Time.ExactEpoch.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Run SPP at an exact receive epoch against an SBAS-corrected broadcast source.

store_from_ems(text, opts \\ [])

Build a correction store from EMS log text.

store_from_ems!(text, opts \\ [])

store_from_messages(messages, opts \\ [])

Build a correction store from decoded message tuples.

store_from_messages!(messages, opts \\ [])

store_from_rtklib(text, opts \\ [])

Build a correction store from RTKLIB SBAS log text.

store_from_rtklib!(text, opts \\ [])

transmit_clock_at_epoch_queries(broadcast, store, geo_id, satellite_id, state_query, selection_query, opts \\ [])

@spec transmit_clock_at_epoch_queries(
  Sidereon.GNSS.Broadcast.t(),
  t(),
  String.t(),
  String.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  Sidereon.GNSS.Time.ExactEpochQuery.t(),
  keyword()
) :: {:ok, %{clock_s: float(), degraded: atom() | nil} | nil} | {:error, term()}

Read the SBAS transmission-placement clock at exact state and selection queries.

unassigned_mask_corrections(sbas, geo_id)

@spec unassigned_mask_corrections(t(), String.t()) ::
  {:ok, %{required(pos_integer()) => non_neg_integer()}} | {:error, term()}

Count the corrections a source GEO addressed to active PRN-mask bits that name no satellite, per 1-based PRN mask number.

The RTCA DO-229 mask numbers 1..37 are GPS, 38..61 GLONASS slots 1..24 and 120..158 SBAS; any other active bit keeps its place among the active bits, so the corrections after it still reach their own satellites, and the corrections addressed to it are applied to no satellite and counted here. geo_id is the GEO's broadcast PRN token, such as "S120", as ready_geos/2 returns it. Returns {:ok, %{mask_number => count}}, {:error, :not_found} when the GEO has no partition in the store, or {:error, reason} for a GEO id that names no SBAS satellite.

unassigned_mask_corrections!(store, geo_id)