Sgp4
A Rust implementation of the SGP4 satellite propagation algorithm
Install / Use
/learn @neuromorphicsystems/Sgp4README
The SGP4 algorithm, ported to Rust from the reference Celestrak implementation [1].
The code was entirely refactored to leverage Rust's algebraic data types and highlight the relationship between the implementation and the reference mathematical equations [2].
SGP4 can be called from JavaScript or Python via WebAssembly wrappers. See https://github.com/wasmerio/sgp4 to install and use SGP4 as a WAPM package.
The numerical predictions are almost identical to Celestrak's. The observed differences (less than 2 × 10⁻⁷ km for the position and 10⁻⁹ km.s⁻¹ for the velocity three and a half years after the epoch) are well below the accuracy of the algorithm.
We drew inspiration from the incomplete https://github.com/natronics/rust-sgp4 to write mathematical expressions using UTF-8 characters.
- Documentation
- Environments without std or alloc
- Benchmark
- Variables and mathematical expressions
- Variables
- Mathematical expressions
- UT1 to Julian conversion
- Common initialization
- Near earth initialization
- High altitude near earth initialization
- Elliptic high altitude near earth initialization
- Deep space initialization
- Third body perturbations
- Resonant deep space initialization
- Geosynchronous deep space initialization
- Molniya deep space initialization
- Common propagation
- Near earth propagation
- High altitude near earth propagation
- Deep space propagation
- Third body propagation
- Resonant deep space propagation
- Lyddane deep space propagation
- References
Documentation
The code documentation is hosted at https://docs.rs/sgp4/latest/sgp4/.
Examples can be found in this repository's examples directory:
- examples/celestrak.rs retrieves the most recent Galileo OMMs from Celestrak and propagates them
- examples/omm.rs parses and propagates a JSON-encoded OMM
- examples/space-track.rs retrieves the 20 most recent launches OMMs from Space-Track and propagates them
- examples/tle.rs parses and propagates a TLE
- examples/tle_afspc.rs parses and propagates a TLE using the AFSPC compatibility mode
- examples/advanced.rs leverages the advanced API to (marginally) accelerate the propagation of deep space resonant satellites
To run an example (here examples/celestrak.rs), use:
cargo run --example celestrak
To run the Space-Track example, you must first assign your Space-Track.org credentials to the fields identity and password (see lines 3 and 4 in examples/space-track.rs).
Environments without std or alloc
This crate supports no_std environments. TLE parsing and SGP4 propagation do not require alloc either. We use num-traits with libm for floating point functions when std is not available.
See https://github.com/neuromorphicsystems/sgp4-no-std for a minimal no-std example that runs on Docker Linux x86_64.
All serde-related features, such as OMM parsing, require alloc.
Benchmark
The benchmark code is available at https://github.com/neuromorphicsystems/sgp4-benchmark. It compares two SGP4 implementations in different configurations:
cpp: the Celestrak implementation [1] in improved modecpp-afspc: the Celestrak implementation [1] in AFSPC compatibility modecpp-fastmath: the Celestrak implementation [1] in improved mode with thefast-mathcompiler flagcpp-afspc-fastmath: the Celestrak implementation [1] in AFSPC compatibility mode with thefast-mathcompiler flagrust: our Rust implementation in default moderust-afspc: our Rust implementation in AFSPC compatibility mode
This benchmark must not be confused with the code in this repository's bench directory. The latter considers only a small subset of the Celestrak catalogue (the tests recommended in [1]) and does not measure the original C++ implementation.
The present results were obtained using a machine with the following configuration:
- CPU - Intel Core i7-8700 @ 3.20GHz
- RAM - Kingston DDR4 @ 2.667 GHz
- OS - Ubuntu 16.04
- Compilers - Rust 1.44.1 and gcc 9.3.0
Accuracy measures the maximum propagation error of each implementation with respect to the reference implementation (cpp-afspc) over the full Celestrak catalogue (1 minute timestep over 24 hours).
| implementation | maximum position error | maximum speed error |
| -------------------- | ---------------------- | ------------------- |
| cpp-afspc | (reference) | (reference) |
| cpp | 1.05 km | 1.30 × 10⁻³ km.s⁻¹ |
| cpp-fastmath | 1.05 km | 1.30 × 10⁻³ km.s⁻¹ |
| cpp-afspc-fastmath | 4.21 × 10⁻⁸ km | 7.51 × 10⁻¹² km.s⁻¹ |
| rust | 1.05 km | 1.30 × 10⁻³ km.s⁻¹ |
| rust-afspc | 4.19 × 10⁻⁸ km | 7.46 × 10⁻¹² km.s⁻¹ |
The Rust and C++ fast-math errors have the same order of magnitude. In both cases, they can be attributed to mathematically identical expressions implemented with different floating-point operations.
Speed measures the time it takes to propagate every satellite in the Celestrak catalogue (1 minute timestep over 24 hours) using a single thread. 100 values are sampled per implementation.
| implementation | minimum | Q1 | median | Q3 | maximum | relative difference |
| -------------------- | ------- | ------ | ------ | ------ | ------- | ------------------- |
| cpp-afspc | 8.95 s | 9.02 s | 9.03 s | 9.06 s | 9.18 s | (reference) |
| cpp | 8.95 s | 9.01 s | 9.04 s | 9.06 s | 9.25 s | + 0 % |
| cpp-fastmath | 7.67 s | 7.74 s | 7.77 s | 7.79 s | 7.90 s | - 14 % |
| cpp-afspc-fastmath | 7.70 s | 7.74 s | 7.76 s | 7.79 s | 7.86 s | - 14 % |
| rust | 8.36 s | 8.41 s | 8.43 s | 8.45 s | 8.53 s | - 7 % |
| rust-afspc | 8.36 s | 8.41 s | 8.43 s | 8.46 s | 8.59 s | - 7 % |
Rust fast-math support is a work in progress (see https://github.com/rust-lang/rust/issues/21690). Similarly to C++, it should have a very small impact on accuracy while providing a substantial speed gain.
Variables and mathematical expressions
Variables
Each variable is used to store the result of one and only one expression. Most variables are immutable, with the exception of the variable (E + ω)ᵢ used to solve Kepler's equation and the state variables tᵢ, nᵢ and λᵢ used to integrate the resonance effects of Earth gravity.
The following tables list the variables used in the code and their associated mathematical symbol. Where possible, we used symbols from [2]. Partial expressions without a name in [2] follow the convention kₙ, n ∈ ℕ if they are shared between initialization and propagation, and pₙ, n ∈ ℕ if they are local to initialization or propagation.
- Initialization variables
- Propagation variables
- Third-body initialization variables
- Third-body propagation variables
Initialization variables
The following variables depend solely on epoch elements.
| variable | symbol | description |
| :-------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Elements::datetime.year() | yᵤ | Gregorian calendar year |
| Elements::datetime.month() | mᵤ | Gregorian calendar month in the range [1, 12] |
| Elements::datetime.day() | dᵤ | Gregorian calendar day in the range [1, 31] |
| Elements::datetime.hour() | hᵤ | Hours since midnight in the range [0, 23]
Related Skills
node-connect
338.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
338.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.6kCommit, push, and open a PR
