astra.propagator module¶
ASTRA Core Numerical Propagator — Segmented Cowell’s Method.
Implements a mission-operations–grade numerical orbit propagator using
Cowell’s direct integration with a Dormand-Prince DOP853 (8th-order,
error-estimate 5th/3rd order) adaptive-step integrator via SciPy’s
solve_ivp(method='DOP853').
Features
- 6-DOF coast arcs: Two-body + J2/J3/J4 + drag + 3rd-body gravity.
- 7-DOF powered arcs: Attitude-steered thrust with Tsiolkovsky-coupled mass depletion.
- Segmented orchestrator: Slices propagation at engine ignition/cutoff boundaries so
the integrator never steps across a force-model discontinuity.
High-fidelity data: JPL DE421 Sun/Moon via Skyfield; empirical atmospheric density from F10.7 and Ap (replacing a static exponential model).
Force model includes
- Two-body Keplerian gravity
- J2, J3, J4 zonal harmonic perturbations (WGS84)
- Empirical atmospheric drag (NRLMSISE-00 with space weather)
- Solar third-body point-mass perturbation (JPL DE421)
- Lunar third-body point-mass perturbation (JPL DE421)
- Finite continuous thrust (7-DOF powered arcs)
Numba / IEEE-754
JIT kernels use @njit(fastmath=True) (MTH-16), which allows reordering and
fused operations that can differ slightly from the pure-Python
_acceleration path. For validation, compare integrated trajectories
or segment-level energy, not bitwise-identical acceleration samples.
SRP / PHY-18
Cannonball SRP scales flux from 1 AU; uses a conical Earth umbra/penumbra
geometry (planar intersection model) to continuously scale solar pressure through
twilight regions — see DragConfig.srp_cylindrical_shadow (named for legacy compatibility).
References
- Vallado, D. A. (2013). Fundamentals of Astrodynamics and Applications.
- Montenbruck & Gill (2000). Satellite Orbits.
- Park et al. (2021). JPL Planetary Ephemerides DE440/DE441.
- astra.propagator.srp_illumination_factor_njit(r_km, r_sun_km, earth_radius_km, sun_radius_km)[source]¶
Public NJIT wrapper for the dual-cone SRP illumination factor (FM-1B fix). Delegates to
_srp_illumination_factor_dual_cone_njit. See that function for the full mathematical derivation (Montenbruck & Gill §3.4.2).
- astra.propagator.srp_illumination_factor(r_km, r_sun_km, earth_radius_km=6378.137, sun_radius_km=695700.0)[source]¶
Exact dual-cone SRP illumination factor ν in [0, 1] (FM-1B fix). Computes the fractional illumination of the solar disk as seen from
r_km, accounting for Earth’s occultation using exact spherical-cap intersection geometry (Montenbruck & Gill §3.4.2; Vallado 2013 Alg. 34). :param r_km: Geocentric satellite position (km), shape (3,). :param r_sun_km: Geocentric Sun position (km), shape (3,). :param earth_radius_km: Earth equatorial radius (km). :param sun_radius_km: Solar mean radius (km).- Returns:
0 = full eclipse, 1 = full sunlight, (0,1) = penumbra.
- Return type:
ν ∈ [0, 1]
- astra.propagator.srp_cylindrical_illumination_factor_njit(r_km, r_sun_km)[source]¶
Legacy cylindrical umbra model (ν=0 in-cylinder, ν=1 outside).
- astra.propagator.srp_cylindrical_illumination_factor(r_km, r_sun_km)[source]¶
Public pure-Python legacy cylindrical umbra model.
Deprecated since version 3.7.1: The cylindrical shadow model is less accurate than the dual-cone model. Use
srp_illumination_factor()instead, which applies the correct conical Earth umbra/penumbra geometry.
- class astra.propagator.NumericalState(t_jd, position_km, velocity_km_s, mass_kg=None, covariance_km2=None, error_message=None)[source]¶
Bases:
objectFull kinematic state vector at a single epoch. In 6-DOF (coast) mode, mass_kg is None and the state vector is [x, y, z, vx, vy, vz]. In 7-DOF (powered) mode, mass_kg tracks propellant depletion via Tsiolkovsky coupling: dm/dt = −F / (Isp·g₀). SE-01 Fix: frozen=True to match all other ASTRA output types (OrbitalState, FiniteBurn, ConjunctionEvent). Prevents accidental mutation of integration results. numpy array contents remain mutable by Python semantics, but field references (position_km, velocity_km_s, mass_kg) cannot be reassigned.
- t_jd¶
- position_km¶
- velocity_km_s¶
- mass_kg = None¶
- covariance_km2 = None¶
- error_message = None¶
- class astra.propagator.DragConfig(cd=2.2, area_m2=10.0, mass_kg=1000.0, cr=1.5, include_srp=True, model='NRLMSISE00', srp_conical_shadow=True, srp_area_m2=None)[source]¶
Bases:
objectAtmospheric drag and optional solar radiation pressure (SRP) inputs.
This dataclass is frozen (immutable) to prevent accidental mutation after construction. Create a new instance to modify parameters.
- cd¶
Aerodynamic drag coefficient (dimensionless). Default 2.2. Typical range: 2.0–2.5 for LEO satellites.
- Type:
float
- area_m2¶
Aerodynamic drag cross-section (m²). Default 10.0.
- Type:
float
- mass_kg¶
Spacecraft mass (kg). Default 1000.0.
- Type:
float
- cr¶
Solar radiation pressure reflectivity coefficient (dimensionless). Default 1.5. Range: 1.0 (absorber) to 2.0 (perfect reflector).
- Type:
float
- include_srp¶
Enable/disable SRP force model. Default True.
- Type:
bool
- model¶
Atmospheric density model.
"NRLMSISE00"(default) uses the NRLMSISE-00 empirical model with space-weather indices."EXPONENTIAL"uses a single-layer exponential profile (faster, lower fidelity).- Type:
str
- srp_conical_shadow¶
Use the conical (umbra/penumbra) Earth shadow model for SRP. Default True. When False, the satellite is assumed to always be in sunlight (conservative for SRP force magnitude).
- Type:
bool
- srp_area_m2¶
Optical cross-section for SRP (m²). Defaults to
area_m2whenNone, which is correct for compact spacecraft. Set explicitly for satellites where the solar-panel area differs significantly from the aerodynamic drag area.- Type:
float | None
- cd = 2.2¶
- area_m2 = 10.0¶
- mass_kg = 1000.0¶
- cr = 1.5¶
- include_srp = True¶
- model = 'NRLMSISE00'¶
- srp_conical_shadow = True¶
- srp_area_m2 = None¶
- property srp_cylindrical_shadow¶
Deprecated alias for srp_conical_shadow (LOW-02). Use srp_conical_shadow.
- class astra.propagator.SNCConfig(q_psd_m2_s3=1e-12, mode='white_noise')[source]¶
Bases:
objectState Noise Compensation (Process Noise) configuration. Defines the power spectral density (PSD) of unmodeled accelerations, typically used to prevent covariance collapse in long-duration propagations.
- q_psd_m2_s3 = 1e-12¶
- mode = 'white_noise'¶
- astra.propagator.propagate_cowell(state0, duration_s, dt_out=60.0, drag_config=None, include_third_body=True, rtol=None, atol=None, maneuvers=None, use_de=True, use_empirical_drag=True, include_stm=False, snc_config=None, coast_rtol=1e-08, coast_atol=1e-08, powered_rtol=1e-12, powered_atol=1e-12, _precomputed_sun=None, _precomputed_moon=None)[source]¶
Propagate an orbit using segmented Cowell’s method with DOP853. This is a mission-operations–grade numerical propagator that automatically segments the integration timeline at engine ignition/cutoff boundaries. Each segment uses the appropriate derivative function:
Coast segments: 6-DOF [r, v] — gravitational + drag.
Powered segments: 7-DOF [r, v, m] — adds thrust and Tsiolkovsky mass depletion.
The segmented approach ensures that
solve_ivpnever steps across a force-model discontinuity, eliminating truncation error at burn edges. Known Limitations:Geopotential truncated at J6.
Atmospheric scale height uses single-layer exponential profile; multi-altitude molecular mass variation is a third-order effect.
Powered-arc default mass absolute tolerance is 10⁻⁵ kg (0.01 g), which is loose for micro-thrusters on small spacecraft; pass
atolfor tighter mass conservation.SRP uses a dual-cone Earth umbra/penumbra shadow model (
_srp_illumination_factor_dual_cone_njit). The penumbra formula is the standard Montenbruck & Gill §3.4.2 planar circle-circle intersection — industry reference for Earth-orbit SRP shadow models. Planar approximation error is O(β²/12) ≈ 1.7×10⁻⁷, below IEEE-754 double precision significance.
- Parameters:
state0 – Initial state (position + velocity + optional mass).
duration_s – Total propagation duration in seconds.
dt_out – Output time step in seconds (default 60 s).
drag_config – Optional atmospheric drag parameters.
include_third_body – Include Sun/Moon gravity.
rtol – Top-level relative tolerance override (WARNING: Silently discards any fine-tuned
coast_rtolandpowered_rtolvalues).atol – Top-level absolute tolerance override (WARNING: Silently discards any fine-tuned
coast_atolandpowered_atolvalues).maneuvers – Optional list of
FiniteBurndefinitions. Burns must not overlap in time.use_de – Use JPL DE421 for Sun/Moon (True) or analytical (False).
use_empirical_drag – Use F10.7/Ap drag model (True) or static (False).
coast_rtol – Relative tolerance for coast arcs (default 1e-8).
coast_atol – Absolute tolerance for coast arcs (default 1e-8). For high-accuracy conjunction analysis, tighten to 1e-12.
powered_rtol – Relative tolerance for powered arcs (default 1e-12).
powered_atol – Absolute tolerance for powered arcs (default 1e-12).
- Returns:
List of
NumericalStateobjects at each output time step. If maneuvers are present, each state includes the current mass.
- astra.propagator.propagate_cowell_at_times(state0, times_jd, *, drag_config=None, include_third_body=True, use_de=True, maneuvers=None, include_stm=False, snc_config=None)[source]¶
Propagate to specific Julian Date epochs using the Cowell integrator.
Unlike
propagate_cowell()which returns states at uniformdt_outintervals, this function returns states at caller-specified epochs. This is essential for:Orbit determination residual computation at observation times.
Ephemeris generation at irregular cadences.
State interpolation at conjunction screening epochs.
Internally propagates with a dense output step and interpolates to the requested times using cubic spline interpolation on the propagated trajectory. The underlying force model, maneuver handling, and STM propagation are identical to
propagate_cowell().- Parameters:
state0 – Initial state (position + velocity + optional mass/covariance).
times_jd – 1-D array of Julian Dates at which states are requested. Must all be ≥
state0.t_jd. Need not be sorted (output will match the input order).drag_config – Optional atmospheric drag parameters.
include_third_body – Include Sun/Moon gravity (default True).
use_de – Use JPL DE421 ephemeris for Sun/Moon (default True).
maneuvers – Optional list of FiniteBurn objects.
include_stm – Propagate State Transition Matrix for covariance.
snc_config – Process noise configuration.
- Returns:
List of
NumericalStateobjects, one per requested epoch, in the same order astimes_jd.- Raises:
ValueError – If
times_jdis empty or contains epochs beforestate0.t_jd.
Example:
import astra import numpy as np state0 = astra.NumericalState( t_jd=2460000.5, position_km=np.array([6778.0, 0.0, 0.0]), velocity_km_s=np.array([0.0, 7.668, 0.0]), ) obs_times = np.array([2460000.51, 2460000.52, 2460000.55]) states = astra.propagate_cowell_at_times(state0, obs_times) for s in states: print(f"t={s.t_jd:.5f} r={s.position_km}")
- astra.propagator.propagate_cowell_batch(states, duration_s, dt_out=60.0, drag_config=None, maneuvers=None, include_third_body=True, include_stm=False, max_workers=None, use_empirical_drag=True)[source]¶
Propagate multiple satellites concurrently with the high-fidelity Cowell integrator. This is a production batch wrapper around
propagate_cowell()that parallelises propagation overNinitial states using aThreadPoolExecutor. It eliminates the ad-hocThreadPoolExecutorpattern that users had to replicate (and which already existed inline insidefind_conjunctions()). The input usesdict[str, NumericalState](satellite-ID → state) rather than a list, which is consistent with theTrajectoryMapconvention used throughout ASTRA (e.g.find_conjunctions). This also makes the key explicit and avoids any ambiguity when the caller needs to correlate inputs and outputs. :param states:dict[satellite_id, NumericalState]— one entry per satellite.The key (string) is used as the map key in the returned dict.
- Parameters:
duration_s – Total propagation duration in seconds (identical for all).
dt_out – Output step size in seconds (default 60 s).
drag_config – Optional
DragConfig; applied uniformly to all satellites unless overridden per-satellite in the future.maneuvers – Optional
dict[satellite_id, list[FiniteBurn]]. Missing keys default to an empty burn sequence.include_third_body – Enable Sun/Moon third-body gravity.
include_stm – Whether to propagate the 6x6 State Transition Matrix.
max_workers – Thread pool size. Defaults to
min(32, len(states)).use_empirical_drag – Whether to use empirical (F10.7/Ap) drag calculations.
Note
Atmosphere model (NRLMSISE-00 or exponential) and SRP are controlled via the
drag_configargument. SetDragConfig(model='NRLMSISE00', include_srp=True)to enable high-fidelity atmosphere and SRP; these are NOT separate kwargs. Returns:dict[satellite_id, list[NumericalState]]— propagated state histories. Satellites that fail propagation are absent from the dict; their error is logged at WARNING level.- Raises:
ValueError – If
statesis empty orduration_s<= 0.
- Example::
import astra, numpy as np s1 = astra.NumericalState(t_jd=2460000.5,
position_km=np.array([6778.0, 0.0, 0.0]), velocity_km_s=np.array([0.0, 7.668, 0.0]))
- s2 = astra.NumericalState(t_jd=2460000.5,
position_km=np.array([6788.0, 0.0, 0.0]), velocity_km_s=np.array([0.0, 7.658, 0.0]))
- results = astra.propagate_cowell_batch(
{“ISS”: s1, “DEBRIS-A”: s2}, duration_s=3600.0
) for sat_id, traj in results.items():
print(sat_id, len(traj), “steps”)