GNSS positioning and astrodynamics: orbit propagation, passes, GNSS solves, and RINEX QC
Runs on your machine from its package; the steps are below.
At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Distributed as an MCP bundle (`https://github.com/neilberkman/sidereon/releases/download/v3.0.3/sidereon_3.0.3.mcpb`) — download it and import the bundle in your MCP client.
GNSS positioning and astrodynamics in Rust, with first-class interfaces in Python, C, Go, WebAssembly, and Elixir. Reference-validated, and bit-exact to public oracles where it counts.
sidereon is one engine: a Rust core for satellite orbit propagation, GNSS positioning, time and frame transforms, atmosphere models, and the standard exchange formats, exposed through idiomatic interfaces in six languages so the same validated math is reachable wherever you work.
Live demo: sidereon.dev: a real-time satellite tracker (globe, ground tracks, coverage, conjunction screening, orbit determination) computed in the browser via the WebAssembly build.
static_positioning / solve_static solves with covariance, leave-one-out redundancy diagnostics, and robust weighting (including one-call reference-station static: rover and reference RINEX in, station coordinate with covariance out), Doppler velocity with clock drift, RTK float and fixed (LAMBDA) with baselines built straight from raw RINEX (verified to millimeters against a published ITRF station pair), PPP float and fixed with SSR or Galileo HAS corrections driving the solve over broadcast ephemeris, static PPP with temporal-correlation covariance (calibrated day-length bounds), optional elevation cutoff, and optional tropospheric gradient estimation, DGNSS, across GPS/GLONASS/Galileo/BeiDou/QZSS, with DOP (G/P/H/V/T).P1 then P2, same map date, provenance
naming the line served), a bounded publication-status query (newest
published issue per center and line, its archive-reported publication text,
and its lag behind nominal - distinguishing "nothing published" from an
unreachable archive), a network-free next-issue due-time query with exact
identity and observed/predicted coverage, and a wider ultra pool including
the IGS combined ultra and Wuhan's hourly MGEX NRT line. Broadcast ephemerides as the
resilience floor are a recorded
design issue.cargo add sidereon
use sidereon::astro::passes::{look_angle, GroundStation, UtcInstant};
let line1 = "1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9009";
let line2 = "2 25544 51.6400 208.8657 0002644 250.3037 109.7782 15.49560812999990";
let elements = sidereon::astro::tle::parse(line1, line2)?.elements.to_element_set()?;
let station = GroundStation { latitude_deg: 51.5, longitude_deg: -0.1, altitude_m: 10.0 };
let when = UtcInstant::from_utc(2024, 1, 1, 12, 0, 0, 0).ok_or("bad datetime")?;
let look = look_angle(&elements, station, when)?;
println!("az {:.2} el {:.2} range {:.1} km", look.azimuth_deg, look.elevation_deg, look.range_km);
More runnable examples, in all six languages, are on the live demo.
The repo ships a single binary for working without writing code:
sidereon solve --obs rover.obs --nav brdc.nav # SPP per epoch, bounds always shown
sidereon qc --obs rover.obs # teqc-style observation quality report
sidereon inspect FILE [--window FROM THROUGH] # summarize a file and optionally scope SP3 continuity
sidereon metrics --enu-cov "..." # CEP / DRMS / R95 / ellipse from a covariance
sidereon tui --obs rover.obs --nav brdc.nav # replay a session in the terminal monitor
sidereon tui --ntrip host:2101 --mount MP ... # watch a live stream solve in real time
sidereon serve-mcp # expose the engine to AI agents over MCP
sidereon-core: the engine. SGP4/SDP4 propagation, coordinate and time transforms, RINEX/SP3/ANTEX/OMM/RTCM parsing, broadcast and precise ephemeris, SPP/RTK/PPP/static/DGNSS positioning, DOP and visibility, conjunction assessment, and the supporting numerical kernels.sidereon: the ergonomic Rust interface over sidereon-core. Product loaders, CRINEX encode/decode, Sun/Moon sky helpers, geodetic/topocentric and TLE look-angle/ground-track shortcuts, Doppler helpers, plus SPP/RTK/PPP/static solves with result structs and one error enum. This is the Rust interface, held to the same parity bar as the bindings below.sidereon-cli: the sidereon command-line tool over the engine: solve (SPP from RINEX with covariance-derived bounds always shown), qc, metrics, inspect, a terminal solution monitor (tui) that replays a logged RINEX session or watches a live NTRIP/TCP RTCM stream, and serve-mcp, a Model Context Protocol server exposing the engine to AI agents through task tools plus a typed capability graph. Built from this repo with cargo build -p sidereon-cli; not yet on crates.io.trust-region-least-squares: a standalone, independently publishable nonlinear least-squares solver that reproduces SciPy's trust-region-reflective least_squares bit-for-bit. It does not depend on the engine.The Rust interface is the sidereon crate above. The other language interfaces live in their own repositories, each over the same core:
sidereon-python (PyPI: sidereon)sidereon-csidereon-gosidereon-ex (Hex: sidereon)sidereon-wasm (npm: @neilberkman/sidereon)All Sidereon libraries release at the same version. New API and behavior changes are reviewed for equivalent coverage across the interfaces; see the coordinated release policy.
Evaluation is deterministic: the same product, the same version, and the same platform give identical bits, and releases that change evaluation bits for an existing surface say so in the changelog. Cross-platform bit identity holds only where a test pins it.
Every numerical routine is cross-checked against the reference implementation or published standard for its domain, not just internal goldens. Each check runs in the test suite against a committed reference fixture whose provenance (tool, version, source) is recorded, and many gates are bit-for-bit.
| Capability | Cross-checked against | Reference |
|---|---|---|
| SGP4 / SDP4 propagation | Vallado / CelesTrak verification states | Vallado, Crawford, Hujsak & Kelso, Revisiting Spacetrack Report #3, AIAA 2006-6753 |
| Frames, time, ephemerides (TEME/GCRS/ITRS, IAU 2006/2000A) | Pinned Skyfield vectors (ERFA/SOFA routines under the hood) | IAU SOFA / ERFA |
| Earth orientation | IERS Earth-orientation parameters | Petit & Luzum (eds.), IERS Conventions (2010), IERS TN 36 |
| Least-squares engine (TRF) | SciPy least_squares, bit-exact | Virtanen et al., SciPy 1.0, Nature Methods 17 (2020) |
| GNSS positioning (SPP / RTK / PPP) | RTKLIB oracle arcs and real IGS precise products | RTKLIB; International GNSS Service (IGS) |
| Geoid undulation (EGM96 15-arcminute) | PROJ (us_nga_egm96_15), to 5 mm | PROJ |
| RINEX observation QC - multipath (MP1/MP2) | teqc +qc on a real captured stream, to sub-micrometer | teqc |
| RTCM MSM lock-time to RINEX LLI | RTKLIB convbin decode of a real MSM stream | RTKLIB |
| RTCM 3 MSM1..MSM7, legacy 1001..1004 / 1009..1012, NavIC 1041, GLONASS 1230 and IGS SSR 4076 decoding | RTKLIB decode_rtcm3 of real multi-constellation streams and RTKLIB-encoded streams, bit for bit | RTKLIB |
| RTCM 3 SSR 1057..1270 and IGS SSR 4076 (every subtype, VTEC included) decoding | BNC SSR decoder on BNC-encoded, RTKLIB-encoded and real IGS SSR streams, bit for bit | BKG NTRIP Client (BNC) |
| RTCM 3 network RTK and transformation messages (1014-1017, 1021-1027, 1030-1032, 1034, 1035, 1037-1039) | pyrtcm message layouts, field for field | pyrtcm |
The per-crate test suites document the exact references, fixtures, and tolerances. The Python oracle version-pinning note records cross-version FITPACK and pseudo-inverse checks and the fixture-regeneration rules they establish.
MIT