Satellite astrodynamics in Rust, with full Python bindings.
Satkit is a high-performance orbital mechanics library written in Rust with complete Python bindings via PyO3. It handles coordinate transforms, orbit propagation, time systems, gravity models, atmospheric density, and JPL ephemerides -- everything needed for satellite astrodynamics work.
Documentation and tutorials (Python examples, but the concepts and API apply equally to Rust) | Rust API reference
Note
Version 0.16.0 introduces several breaking changes: Frame::RIC is renamed to the canonical Frame::RTN (with RIC / RSW remaining as aliases, so existing code still compiles); a new Frame::NTW (velocity-aligned) is added; LVLH is now accepted as a maneuver/thrust frame; the uncertainty API is unified into set_pos_uncertainty(sigma, frame) / set_vel_uncertainty(sigma, frame) (the four old per-frame methods are removed, not deprecated); PropSettings::default() now uses GravityModel::EGM96 instead of JGM3; the Gauss-Jackson 8 fixed-step multistep integrator is available for long-duration propagation; and PropSettings::max_steps is now configurable. See CHANGELOG.md for the full list.
Rust:
cargo add satkitPython:
pip install satkitPre-built wheels are available for Linux, macOS, and Windows on Python 3.10--3.14.
After installing, download the required data files (gravity models, ephemerides, Earth orientation parameters):
import satkit as sk
sk.utils.update_datafiles() # one-time download; re-run periodically for fresh EOP/space weatherimport satkit as sk
tle = sk.TLE.from_lines([
"ISS (ZARYA)",
"1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9003",
"2 25544 51.6432 351.4697 0007417 130.5364 329.6482 15.48915330299357"
])
pos, vel = sk.sgp4(tle, sk.time(2024, 1, 2))import satkit as sk
import numpy as np
r0 = 6378e3 + 500e3 # 500 km altitude
v0 = np.sqrt(sk.consts.mu_earth / r0)
settings = sk.propsettings(
gravity_model=sk.gravmodel.egm96, # default; also jgm3, jgm2, itugrace16
gravity_degree=8,
integrator=sk.integrator.rkv98, # default; also rkv87, rkv65, rkts54,
# gauss_jackson8 (fixed-step multistep)
)
result = sk.propagate(
np.array([r0, 0, 0, 0, v0, 0]),
sk.time(2024, 1, 1),
end=sk.time(2024, 1, 1) + sk.duration.from_days(1),
propsettings=settings,
)
state = result.interp(sk.time(2024, 1, 1) + sk.duration.from_hours(6))import satkit as sk
time = sk.time(2024, 1, 1, 12, 0, 0)
coord = sk.itrfcoord(latitude_deg=42.0, longitude_deg=-71.0, altitude=100.0)
q = sk.frametransform.qitrf2gcrf(time)
gcrf_pos = q * coord.vectoruse satkit::{Instant, SolarSystem, jplephem};
let time = Instant::from_datetime(2024, 1, 1, 0, 0, 0.0)?;
let (pos, vel) = jplephem::geocentric_state(SolarSystem::Moon, &time)?;Full IERS 2010 Conventions reduction (IAU 2006/2000A precession-nutation) with Earth orientation parameters:
| Frame | Description |
|---|---|
| ITRF | International Terrestrial Reference Frame (Earth-fixed) |
| GCRF | Geocentric Celestial Reference Frame (inertial) |
| TEME | True Equator Mean Equinox (SGP4 output frame) |
| CIRS | Celestial Intermediate Reference System |
| TIRS | Terrestrial Intermediate Reference System |
| Geodetic | Latitude / longitude / altitude (WGS-84) |
Plus ENU, NED, and geodesic distance (Vincenty) utilities.
- Numerical -- Selectable adaptive Runge-Kutta integrators (9(8), 8(7), 6(5), 5(4)) plus RODAS4 (stiff) and Gauss-Jackson 8 (fixed-step multistep for high-precision long-duration propagation), with dense output, state transition matrix, and configurable force models
- SGP4 -- Standard TLE/OMM propagator with TLE fitting from precision states
- Keplerian -- Analytical two-body propagation
- Impulsive maneuvers -- Instantaneous delta-v applied at a scheduled time during propagation. Supported frames: GCRF (inertial), RTN (radial/tangential/normal — the CCSDS OEM convention, also exposed as
RSWandRICaliases), NTW (velocity-aligned — natural for prograde burns on eccentric orbits, where a pure +T delta-v adds exactly Δv to |v|), and LVLH (Local Vertical / Local Horizontal). Ergonomic helpersadd_prograde/add_retrograde/add_radial/add_normalfor common scalar-magnitude burns. - Continuous thrust -- Constant-acceleration thrust arcs over time windows in any of the frames above, integrated directly into the force model
- Automatic segmentation -- Propagation through maneuver sequences is handled transparently, including backward propagation
- Earth gravity: JGM2, JGM3, EGM96, ITU GRACE16 (spherical harmonics up to degree/order 360)
- Third-body gravity: Sun and Moon via JPL DE440/441 ephemerides
- Atmospheric drag: NRLMSISE-00 with automatic space weather data
- Solar radiation pressure: Cannonball model with shadow function
Seamless conversion between UTC, TAI, TT, TDB, UT1, and GPS time scales with full leap-second handling.
- JPL DE440/DE441 ephemerides for all planets, Sun, Moon, and barycenters
- Fast analytical Sun/Moon models for lower-precision work
- Sunrise/sunset and Moon phase calculations
SatKit uses numeris for all linear algebra (vectors, matrices, quaternions, ODE integration). If you also use nalgebra in your project, enable the nalgebra feature on numeris for zero-cost From/Into conversions between types:
numeris = { version = "0.5.7", features = ["nalgebra"] }| Feature | Default | Description |
|---|---|---|
omm-xml |
yes | XML OMM deserialization via quick-xml |
chrono |
no | TimeLike impl for chrono::DateTime |
Satkit needs external data for gravity models, ephemerides, and Earth orientation. Call update_datafiles() to download them automatically.
Downloaded once: JPL DE440/441 (~100 MB), gravity model coefficients, IERS nutation tables
Update periodically: Space weather indices (F10.7, Ap) and Earth orientation parameters (polar motion, UT1-UTC) -- both sourced from Celestrak.
The library is validated against:
- Vallado test cases for SGP4, coordinate transforms, and Keplerian elements
- JPL test vectors for DE440/441 ephemeris interpolation (10,000+ cases)
- ICGEM reference values for gravity field calculations
- GPS SP3 precise ephemerides for multi-day numerical propagation
157 Rust tests and 81 Python tests run on every commit across Linux, macOS, and Windows.
Tests require two sets of external data: the astro-data files (gravity models, ephemerides, etc.) and the test vectors (reference outputs for validation). Download both before running:
# Install the download helper
pip install requests
# Download test vectors
python python/test/download_testvecs.pyThen run tests with the environment variables pointing to the downloaded directories:
# Rust tests
SATKIT_DATA=astro-data SATKIT_TESTVEC_ROOT=satkit-testvecs cargo test
# Python tests
SATKIT_DATA=astro-data SATKIT_TESTVEC_ROOT=satkit-testvecs pytest python/test/- Rust: docs.rs/satkit
- Python: satkit.dev -- tutorials, Jupyter notebooks, and API reference
- D. Vallado, Fundamentals of Astrodynamics and Applications, 4th ed., 2013
- O. Montenbruck & E. Gill, Satellite Orbits: Models, Methods, Applications, 2000
- J. Verner, Runge-Kutta integration coefficients
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.