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.14.1 replaces nalgebra with numeris for all linear algebra (matrices, quaternions, ODE solvers). numeris is a standalone, no_std-compatible library that unifies these in a single crate, making them available to projects beyond satkit. Performance is equivalent, and all tests pass with matching residuals. If your code uses nalgebra types, enable the nalgebra feature on numeris for zero-cost conversions. Please open an issue if you hit any problems.
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.jgm3,
gravity_degree=8,
integrator=sk.integrator.rkv98, # default; also rkv87, rkv65, rkts54
)
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 IAU-2006/2000 reduction 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)) 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
- 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.5", 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
142 tests (106 unit + 36 doc-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/test.py- 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
MIT