The SGPPropagator implements the SGP4/SDP4 propagation models for orbital prediction. SGP4 is a standard method for satellite tracking and includes simplified perturbations from Earth oblateness and atmospheric drag, making it suitable for operational satellite tracking and near-Earth orbit propagation. It is widely used with Two-Line Element (TLE) data provided by NORAD and other space tracking organizations.
SGP4 propagation is based on Two-Line Element (TLE) sets, a compact data format for orbital elements. Brahe supports both traditional and modern TLE formats:
Classic Format: Traditional numeric NORAD catalog numbers (5 digits, up to 99999)
Alpha-5 Format: Extended alphanumeric catalog numbers for satellites beyond 99999
The initialization automatically detects and handles both formats.
Rather than hard-coding TLE strings, you can query live satellite data from CelesTrak or Space-Track and get a ready-to-use propagator in a single call. This is the most common workflow for operational satellite tracking:
ThisexampleshowshowtoqueryasatellitefromCelesTrakandconvertittoapropagatorinafewsteps,whichisthemostcommonusecase."""import brahe as bh# Initialize EOP databh.initialize_eop()# Get an SGP4 propagator for the ISS directly from CelesTrakclient = bh.celestrak.CelestrakClient()iss_prop = client.get_sgp_propagator(catnr=25544, step_size=60.0)print(f"Created propagator: {iss_prop.get_name()}")print(f"Epoch: {iss_prop.epoch}")# Propagate forward 1 orbit period (~93 minutes for ISS)iss_prop.propagate_to(iss_prop.epoch + bh.orbital_period(iss_prop.semi_major_axis))state = iss_prop.current_state()print("\nState after 1 orbit:")print(f" Position: [{state[0]:.1f}, {state[1]:.1f}, {state[2]:.1f}] m")print(f" Velocity: [{state[3]:.1f}, {state[4]:.1f}, {state[5]:.1f}] m/s")# Expected output:# Created propagator: ISS (ZARYA)# Epoch: 2025-11-02 10:09:34.283 UTC# State after 1 orbit:# Position: [6451630.2, -2126316.1, 34427.2] m# Velocity: [2019.6, 5281.4, 6006.2] m/s
//! to a propagator in a few steps, which is the most common use case.//!//! FLAGS = ["CI-ONLY"]#[allow(unused_imports)]usebraheasbh;usebh::celestrak::CelestrakClient;usebh::traits::SStatePropagator;usebh::utils::Identifiable;fnmain(){bh::initialize_eop().unwrap();// Get an SGP4 propagator for the ISS directly from CelesTrakletclient=CelestrakClient::new();letmutiss_prop=client.get_sgp_propagator_by_catnr(25544,60.0).unwrap();println!("Created propagator: {}",iss_prop.get_name().unwrap_or("Unknown"));println!("Epoch: {}",iss_prop.epoch);// Propagate forward 1 orbit period (~93 minutes for ISS)iss_prop.propagate_to(iss_prop.epoch+bh::orbital_period(iss_prop.semi_major_axis()));letstate=iss_prop.current_state();println!("\nState after 1 orbit:");println!(" Position: [{:.1}, {:.1}, {:.1}] m",state[0],state[1],state[2]);println!(" Velocity: [{:.1}, {:.1}, {:.1}] m/s",state[3],state[4],state[5]);// Expected output:// Created propagator: ISS (ZARYA)// Epoch: 2025-11-02 10:09:34.283 UTC// State after 1 orbit:// Position: [6451630.2, -2126316.1, 34427.2] m// Velocity: [2019.6, 5281.4, 6006.2] m/s}
The SGP propagator implements the StateProvider trait, allowing direct state computation at arbitrary epochs without stepping. Because SGP4 uses closed-form solutions, state queries are efficient and do not require building a trajectory.
SGP4 natively outputs states in the TEME (True Equator Mean Equinox) frame. For specialized applications, you can access states in the intermediate PEF (Pseudo-Earth-Fixed) frame:
importbraheasbhbh.initialize_eop()line1="1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927"line2="2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537"prop=bh.SGPPropagator.from_tle(line1,line2,60.0)# Keep only 50 most recent states for memory efficiencyprop.set_eviction_policy_max_size(50)# Propagate many stepsprop.propagate_steps(200)print(f"Trajectory length: {len(prop.trajectory)}")# Will be 50# Alternative: Keep states within 30 minutes of currentprop.reset()prop.set_eviction_policy_max_age(1800.0)# 1800 seconds = 30 minutesprop.propagate_steps(200)print(f"Trajectory length with age policy: {len(prop.trajectory)}")# Expected output:# Trajectory length: 50# Trajectory length with age policy: 31
usebraheasbh;usebrahe::traits::{SStatePropagator,Trajectory};fnmain(){bh::initialize_eop().unwrap();letline1="1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927";letline2="2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537";letmutprop=bh::SGPPropagator::from_tle(line1,line2,60.0).unwrap();// Keep only 50 most recent states for memory efficiencyprop.set_eviction_policy_max_size(50).unwrap();// Propagate many stepsprop.propagate_steps(200);println!("Trajectory length: {}",prop.trajectory.len());// Will be 50// Alternative: Keep states within 30 minutes of currentprop.reset();prop.set_eviction_policy_max_age(1800.0).unwrap();// 1800 seconds = 30 minutesprop.propagate_steps(200);println!("Trajectory length with age policy: {}",prop.trajectory.len());// Expected output:// Trajectory length: 50// Trajectory length with age policy: 31}
Unlike the Keplerian propagator, SGP4 initial conditions are derived from the TLE and cannot be changed. Attempting to call set_initial_conditions() will result in a panic:
importbraheasbhimportnumpyasnpline1="1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927"line2="2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537"prop=bh.SGPPropagator.from_tle(line1,line2,60.0)# This will raise an error - SGP initial conditions come from TLE# prop.set_initial_conditions(...) # Don't do this!# To use different orbital elements, create a KeplerianPropagator instead
// This will panic - SGP initial conditions come from TLE// prop.set_initial_conditions(...); // Don't do this!// To use different orbital elements, create a KeplerianPropagator instead