Sidereon.GNSS.Broadcast (Sidereon v3.0.0)

Copy Markdown View Source

A parsed RINEX broadcast-navigation product (GPS LNAV, Galileo I/NAV+F/NAV, BeiDou D1/D2, GLONASS).

Holds the broadcast Keplerian elements and clock terms as a resource handle, the broadcast-ephemeris counterpart to Sidereon.GNSS.SP3. Pass a handle to Sidereon.GNSS.Positioning.solve/4 to position from broadcast ephemeris instead of a precise SP3 product. The navigation file is parsed exactly once; the parsed product is held as a reference, not re-parsed per call.

Parsing covers RINEX 2.xx, 3.xx and 4.xx files: GPS, QZSS, Galileo, BeiDou (including BeiDou geostationary satellites) and NavIC Keplerian records, GPS/QZSS CNAV-family records, and GLONASS (a PZ-90.11 state-vector model propagated by Runge-Kutta integration rather than Keplerian elements). A block that cannot be read is left out and reported by skipped/1, and a departure from the format read through by departures/1; one bad record does not cost the file's other records.

The orbit and clock models follow IS-GPS-200 (GPS LNAV), the Galileo OS-SIS-ICD (I/NAV + F/NAV), and the BeiDou BDS-SIS-ICD (D1/D2), parsed from RINEX 3.x/4.xx navigation records.

The handle API applies the core store's selection: among a satellite's records a query selects as RTKLIB seleph and selgeph do, and a selected record RTKLIB satexclude excludes (unhealthy, or with an accuracy worse than RTKLIB's limit) yields no state. The direct parse_rinex_nav_records/1, parse_rinex_nav_lenient/1, parse_rinex_glonass_records/1, parse_rinex_glonass_lenient/1, and encode_rinex_nav/1 routes expose the caller-owned raw record-list contracts without that selection.

Epochs

position/3 interprets the query epoch in GPS time (GPST). A NaiveDateTime or {{year, month, day}, {hour, minute, second}} is converted to a continuous second-of-J2000 via Sidereon.GNSS.Time; the crate maps that onto each system's own time scale (BDT for BeiDou, UTC-referenced for GLONASS) before selecting the governing record. No leap-second shifting is applied to the supplied epoch.

Summary

Functions

Time-dependent CNAV URA_NED bound in metres.

Nominal CNAV URA in metres for a URA ED/NED0 index.

Departures from the RINEX NAV format the parsed product read through, including header records whose values cannot be read.

Serialize the Keplerian broadcast records to RINEX navigation text.

Encode a caller-supplied list of full broadcast records to canonical RINEX NAV text.

Number of GLONASS state-vector records held by the parsed product.

GLONASS broadcast state-vector records held by the parsed product. Health does not filter them; a query selects as RTKLIB selgeph does and a selected record that is not healthy yields no state.

Broadcast ionosphere coefficients over the whole file.

Broadcast ionosphere coefficients in effect at epoch (GPS time): each set is the one of its system and model transmitted latest at or before it.

GPS minus UTC leap seconds from the NAV header, if present.

Parse a RINEX 3.x or 4.xx navigation file from disk.

Like load/1 but raises on failure.

GPS/QZSS record-family preference used by mixed LNAV/CNAV selection.

Parse an in-memory RINEX 3.x or 4.xx navigation text buffer into a handle.

Parse raw GLONASS RINEX NAV records while retaining skipped slot identities.

Parse every representable GLONASS state-vector record from RINEX NAV text.

Parse supported RINEX NAV records leniently.

Parse all supported RINEX NAV records in file order without the broadcast store's health, message-family, or CNAV usability filters.

Evaluate the broadcast state of satellite sat_id at epoch.

Number of Keplerian records held by the parsed product.

Keplerian broadcast records held by the parsed product.

Detailed GPS, Galileo, BeiDou, and CNAV-family records in file order.

Blocks of the navigation file the parsed product could not read, each with its line and reason. One unreadable record does not cost the file's other records.

Types

message_preference()

@type message_preference() :: :legacy | :modern

nav_message()

@type nav_message() ::
  :gps_lnav
  | :gps_cnav
  | :gps_cnav2
  | :qzss_lnav
  | :qzss_cnav
  | :qzss_cnav2
  | :galileo_inav
  | :galileo_fnav
  | :galileo_unclassified
  | :beidou_d1
  | :beidou_d2
  | :navic_lnav

t()

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

Functions

cnav_ura_ned(cnav, time)

Time-dependent CNAV URA_NED bound in metres.

cnav_ura_nominal(index)

@spec cnav_ura_nominal(integer()) :: float() | nil

Nominal CNAV URA in metres for a URA ED/NED0 index.

departures(broadcast)

@spec departures(t()) :: [Sidereon.GNSS.Broadcast.NavDiagnostic.t()]

Departures from the RINEX NAV format the parsed product read through, including header records whose values cannot be read.

encode_nav(broadcast)

@spec encode_nav(t()) ::
  {:ok, String.t()}
  | {:error, {:not_representable, non_neg_integer(), String.t()}}

Serialize the Keplerian broadcast records to RINEX navigation text.

Returns {:ok, text}: RINEX 3.04, or RINEX 4.02 frames when a CNAV-family record is present. Re-parsing the output reconstructs the same records. The text covers the records records/1 returns; GLONASS state-vector records are not serialized. Returns {:error, {:not_representable, line, reason}} for a record set the writer refuses (a CNAV-family record together with an unclassified Galileo record).

encode_rinex_nav(records)

@spec encode_rinex_nav([Sidereon.GNSS.Broadcast.DetailedRecord.t()]) ::
  {:ok, String.t()} | {:error, term()}

Encode a caller-supplied list of full broadcast records to canonical RINEX NAV text.

This is independent of a parsed Broadcast handle and does not apply the store's default filtering policy. Pass DetailedRecord values such as those returned by parse_rinex_nav_records/1; the list may be reordered or reduced by the caller. The text is RINEX 3.04, or RINEX 4.02 frames when a CNAV-family record is present, with a PGM / RUN BY / DATE header record.

Returns {:error, {:not_representable, line, reason}} for a record set the writer refuses: one holding both a CNAV-family record, which only RINEX 4 holds, and an unclassified Galileo record, which only RINEX 3 holds. line is 0 for a record built in code.

glonass_record_count(broadcast)

@spec glonass_record_count(t()) :: non_neg_integer()

Number of GLONASS state-vector records held by the parsed product.

glonass_records(broadcast)

@spec glonass_records(t()) :: [Sidereon.GNSS.Broadcast.GlonassRecord.t()]

GLONASS broadcast state-vector records held by the parsed product. Health does not filter them; a query selects as RTKLIB selgeph does and a selected record that is not healthy yields no state.

iono_corrections(broadcast)

@spec iono_corrections(t()) :: Sidereon.GNSS.Broadcast.IonoCorrections.t()

Broadcast ionosphere coefficients over the whole file.

Each set is the one of its system and model transmitted latest, from the header or a RINEX 4 ionosphere frame; a set neither states is nil.

iono_corrections_at(broadcast, epoch)

@spec iono_corrections_at(t(), NaiveDateTime.t() | tuple()) ::
  {:ok, Sidereon.GNSS.Broadcast.IonoCorrections.t()} | {:error, term()}

Broadcast ionosphere coefficients in effect at epoch (GPS time): each set is the one of its system and model transmitted latest at or before it.

leap_seconds(broadcast)

@spec leap_seconds(t()) :: float() | nil

GPS minus UTC leap seconds from the NAV header, if present.

load(path)

@spec load(String.t()) :: {:ok, t()} | {:error, term()}

Parse a RINEX 3.x or 4.xx navigation file from disk.

Returns {:ok, %Sidereon.GNSS.Broadcast{}} or {:error, reason}. The file is read and parsed once; the parsed product is held as a resource handle.

load!(path)

@spec load!(String.t()) :: t()

Like load/1 but raises on failure.

message_preference(broadcast)

@spec message_preference(t()) :: message_preference()

GPS/QZSS record-family preference used by mixed LNAV/CNAV selection.

parse(text, opts \\ [])

@spec parse(
  String.t(),
  keyword()
) :: {:ok, t()} | {:error, term()}

Parse an in-memory RINEX 3.x or 4.xx navigation text buffer into a handle.

parse_rinex_glonass_lenient(text)

@spec parse_rinex_glonass_lenient(String.t()) ::
  {:ok, Sidereon.GNSS.Broadcast.GlonassParse.t()} | {:error, term()}

Parse raw GLONASS RINEX NAV records while retaining skipped slot identities.

The core parser keeps every readable record and reports the source token of every unrepresentable GLONASS slot, each record of a representable slot that could not be read, and each departure from the format read through. Every list preserves source order.

parse_rinex_glonass_records(text)

@spec parse_rinex_glonass_records(String.t()) ::
  {:ok, [Sidereon.GNSS.Broadcast.GlonassRecord.t()]} | {:error, term()}

Parse every representable GLONASS state-vector record from RINEX NAV text.

This direct parser returns every readable record in file order, whatever its health.

parse_rinex_nav_lenient(text)

@spec parse_rinex_nav_lenient(String.t()) ::
  {:ok, Sidereon.GNSS.Broadcast.RinexNavParse.t()} | {:error, term()}

Parse supported RINEX NAV records leniently.

Header errors remain {:error, reason}. Blocks that cannot be read are omitted from records and reported in skipped with their line; departures from the format read through are reported in departures, and every block of another kind (GLONASS, SBAS, RINEX 4 non-ephemeris frames, messages not decoded) in other. Records remain in file order.

parse_rinex_nav_records(text)

@spec parse_rinex_nav_records(String.t()) ::
  {:ok, [Sidereon.GNSS.Broadcast.DetailedRecord.t()]} | {:error, term()}

Parse all supported RINEX NAV records in file order without the broadcast store's health, message-family, or CNAV usability filters.

The returned DetailedRecord values retain the full core record needed by encode_rinex_nav/1, including issue/time tags, group delays, and CNAV parameters.

position(broadcast, sat_id, epoch)

@spec position(t(), String.t(), NaiveDateTime.t() | tuple()) ::
  {:ok, Sidereon.GNSS.Broadcast.State.t()} | {:error, term()}

Evaluate the broadcast state of satellite sat_id at epoch.

sat_id is the canonical RINEX token, e.g. "G01" (GPS PRN 1), "E12", "C30", "R07". epoch is a NaiveDateTime or a {{year, month, day}, {hour, minute, second}} tuple, interpreted in GPS time.

Returns {:ok, %Sidereon.GNSS.Broadcast.State{}} with the ECEF position (meters) and satellite clock offset (seconds), {:error, :no_ephemeris} when no broadcast record covers that satellite at that epoch (the validity window has no match; this is not extrapolated), or {:error, reason} for a malformed satellite token or a non-integer-second tuple epoch.

Evaluating the same satellite across a window reuses the parsed handle; the navigation file is never re-read.

record_count(broadcast)

@spec record_count(t()) :: non_neg_integer()

Number of Keplerian records held by the parsed product.

records(broadcast)

@spec records(t()) :: [Sidereon.GNSS.Broadcast.Record.t()]

Keplerian broadcast records held by the parsed product.

The store keeps the records of the messages used for single-frequency positioning: GPS LNAV, GPS/QZSS CNAV-family, QZSS LNAV, Galileo I/NAV and Galileo records whose data sources name no single message, BeiDou D1/D2 and NavIC LNAV. Health does not filter them: a query selects among a satellite's records as RTKLIB seleph does, and a selected record RTKLIB satexclude excludes yields no state.

records_detailed(broadcast)

@spec records_detailed(t()) :: [Sidereon.GNSS.Broadcast.DetailedRecord.t()]

Detailed GPS, Galileo, BeiDou, and CNAV-family records in file order.

skipped(broadcast)

Blocks of the navigation file the parsed product could not read, each with its line and reason. One unreadable record does not cost the file's other records.