AstroProp
AstroProp provides force models, orbital propagators, and stopping conditions for modelling spacecraft motion. AstroProp provides interfaces to the extensive numerical integration libraries in Julia's OrdinaryDiffEq.jl. AstroProp is tested against the General Mission Analysis Tool (GMAT).
Quick Start
The example below shows how to propagate a spacecraft using various stopping conditions:
using AstroEpochs, AstroStates, AstroFrames, AstroUniverse
using AstroModels, AstroCallbacks, AstroProp, OrdinaryDiffEq
# Spacecraft
sat = Spacecraft(
state=CartesianState([7000.0, 300.0, 0.0, 0.0, 7.5, 0.03]),
time=Time("2015-09-21T12:23:12", TAI(), ISOT()),
coord_sys=CoordinateSystem(earth, ICRFAxes()),
)
# Forces + integrator
gravity = PointMassGravity(earth, (moon, sun))
forces = ForceModel(gravity)
integ = IntegratorConfig(Tsit5(); dt=10.0, reltol=1e-9, abstol=1e-9)
prop = OrbitPropagator(forces, integ)
# Propagate for 1 hour (3600 seconds)
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), 3600.0))
# Propagate to an absolute time
target_time = Time("2015-09-22T12:00:00", TDB(), ISOT())
propagate!(prop, sat, StopAt(sat, target_time))
# Propagate to periapsis (r·v = 0, increasing crossing)
propagate!(prop, sat, StopAt(sat, PosDotVel(), 0.0; direction=+1))
println(get_state(sat, Keplerian()))
# Propagate backward for 2 hours using negative duration
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), -7200.0); direction=:infer)
# Stop when |r| reaches 7000 km
propagate!(prop, sat, StopAt(sat, PosMag(), 7000.0))
println(get_state(sat, SphericalRADEC()))
# Propagate multiple spacecraft with multiple stopping conditions
sc1 = Spacecraft(); sc2 = Spacecraft()
stop_sc1_node = StopAt(sc1, PosZ(), 0.0)
stop_sc2_periapsis = StopAt(sc2, PosDotVel(), 0.0; direction=+1)
propagate!(prop, [sc1, sc2], stop_sc1_node, stop_sc2_periapsis)Function Syntax
propagate
Propagates one or more spacecraft under specified forces to one or more stopping conditions.
Syntax:
sol = propagate!(propagator, spacecraft, stops...; direction=:forward, kwargs...)Parameters:
propagator: AnOrbitPropagatorcontaining the force model and integrator configurationspacecraft: ASpacecraftorVector{Spacecraft}to propagatestops...: One or moreStopAtstopping conditions (varargs)direction: (optional):forward(default),:backward, or:infer- controls time integration directionkwargs...: Additional keyword arguments passed to the ODE solver
Returns:
sol: ODE solution object from DifferentialEquations.jl
Common usage patterns:
# Single spacecraft, single stop
propagate!(prop, sat, stop)
# Single spacecraft, multiple stops
propagate!(prop, sat, stop1, stop2, stop3)
# Multiple spacecraft, multiple stops
propagate!(prop, [sat1, sat2], stop1, stop2)
# With direction keyword
propagate!(prop, sat, stop; direction=:backward)See the following sections for detailed configuration:
- Force Model Configuration - Setting up gravitational forces
- Integrator Selection - Choosing integrators and tolerances
- Stopping Conditions - State-based and time-based stop syntax
Propagator Configuration
An OrbitPropagator combines a force model and integrator configuration to define how spacecraft motion is computed. This section covers the configuration of both components.
Basic setup pattern:
# 1. Define the gravitational forces
gravity = PointMassGravity(central_body, (perturbers...,))
forces = ForceModel(gravity)
# 2. Configure the numerical integrator
integ = IntegratorConfig(algorithm; dt=step, reltol=rtol, abstol=atol)
# 3. Create the propagator
prop = OrbitPropagator(forces, integ)Force Model Configuration
The force model defines the dynamics for propagation. Currently, AstroProp only supports point-mass gravity models through PointMassGravity.
Basic usage:
# Earth-centered with perturbations from Moon and Sun
gravity = PointMassGravity(earth, (moon, sun))
forces = ForceModel(gravity)Components:
- Central body: The primary gravitational body (e.g.,
earth,mars,sun) - Perturbing bodies: Tuple of additional bodies whose gravity affects the trajectory (e.g.,
(moon, sun))
Common configurations:
# LEO - Earth only (fast, low-fidelity)
gravity_leo = PointMassGravity(earth, ())
# LEO/MEO - Earth with Moon and Sun (standard accuracy)
gravity_standard = PointMassGravity(earth, (moon, sun))
# Interplanetary - Sun-centered with planetary perturbations
gravity_interplanetary = PointMassGravity(sun, (earth, mars, jupiter))Integrator Selection
AstroProp leverages Julia's DifferentialEquations.jl ecosystem, providing access to a wide range of high-performance numerical integrators. The choice of integrator and its parameters affects both the accuracy and speed of your propagation.
Common Integrators
Recommended integrators for orbital mechanics:
Tsit5(): Tsitouras 5th order adaptive method. Good default choice for most applications with moderate accuracy requirements.Vern9(): Verner 9th order adaptive method. Higher accuracy for demanding applications like precision orbit determination.DP5(): Dormand-Prince 5th order method. Classic choice, similar performance to Tsit5.Vern7(): Verner 7th order method. Balance between Vern9 accuracy and Tsit5 speed.
For a complete list of available integrators, see the DifferentialEquations.jl documentation.
Integrator Parameters
The IntegratorConfig accepts several key parameters that control integration behavior:
dt - Initial/suggested step size (seconds)
- Sets the initial time step for adaptive integrators
- Typical values: 10-60 seconds for LEO, 60-600 seconds for GEO, 86400.0 for interplanetary
- Smaller steps increase computation time but may improve accuracy near discontinuities
reltol - Relative error tolerance
- Controls accuracy relative to the magnitude of the state
- Typical values:
1e-9to1e-12for high-precision work,1e-6to1e-9for general use - Smaller values = higher accuracy but slower computation
abstol - Absolute error tolerance
- Controls absolute error floor (important when state components are near zero)
- Typical values:
1e-9to1e-12for position/velocity - Should generally match or be slightly smaller than
reltol
Example configurations:
# Fast propagation (lower accuracy)
integ_fast = IntegratorConfig(Tsit5(); dt=60.0, reltol=1e-6, abstol=1e-6)
# Standard propagation (good balance)
integ_standard = IntegratorConfig(Tsit5(); dt=10.0, reltol=1e-9, abstol=1e-9)
# High-precision propagation
integ_precise = IntegratorConfig(Vern9(); dt=10.0, reltol=1e-12, abstol=1e-12)If you're unsure, start with Tsit5() with dt=10.0, reltol=1e-9, and abstol=1e-9. Adjust based on your accuracy requirements and performance needs.
Stopping Conditions
AstroProp supports two categories of stopping conditions: state-based and time-based.
State-Based Stopping Conditions
State-based stops trigger when a calculated quantity (position, velocity, or derived value) crosses a target value. These use calculation variables from AstroCallbacks:
# Stop at periapsis (r·v = 0, velocity increasing)
StopAt(sat, PosDotVel(), 0.0; direction=+1)
# Stop at apoapsis (r·v = 0, velocity decreasing)
StopAt(sat, PosDotVel(), 0.0; direction=-1)
# Stop when radius reaches 7000 km (any direction)
StopAt(sat, PosMag(), 7000.0; direction=0)
# Stop at ascending node (z = 0, increasing)
StopAt(sat, PosZ(), 0.0; direction=+1)The direction parameter specifies which zero-crossing triggers the stop:
+1: Trigger when value is increasing (positive derivative)-1: Trigger when value is decreasing (negative derivative)0: Trigger on any crossing (default)
The direction parameter on StopAt for state-based stops controls which side of the zero-crossing triggers the callback. This is different from the direction keyword on propagate!() which controls the time integration direction.
Time-Based Stopping Conditions
Time-based stops allow propagation for a specified duration or until an absolute epoch:
Elapsed Time Stops:
# Propagate forward for 3600 seconds
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), 3600.0))
# Propagate forward for 2.5 days
propagate!(prop, sat, StopAt(sat, PropDurationDays(), 2.5))
# Propagate backward for 1 hour (negative duration)
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), -3600.0); direction=:infer)Absolute Time Stops:
# Propagate to a future epoch
sat = Spacecraft(
time=Time("2015-09-21T12:23:12", TAI(), ISOT()),
)
target = Time("2015-09-22T12:00:00", UTC(), ISOT())
propagate!(prop, sat, StopAt(sat, target))
# Propagate backward to a past epoch
past = Time("2015-09-20T12:00:00", UTC(), ISOT())
propagate!(prop, sat, StopAt(sat, past); direction=:infer)Time-based stopping conditions must use direction=0 (the default). The event crossing direction concept does not apply to time-based stops. Use the direction keyword on propagate!() to control backward vs forward propagation.
Direction Keywords
The propagate!() function accepts a direction keyword to control time integration:
:forward(default): Integrate forward in time. This is the most common case.:backward: Integrate backward in time explicitly.:infer: Automatically infer direction from the time-based stop condition.
When to use :infer:
The :infer keyword is particularly useful in optimization and when the propagation direction may vary:
# Optimization variable (can be positive or negative)
duration = optimize_parameter # Could be -1000.0 or +1000.0
# Using :infer allows the sign to determine direction automatically
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), duration); direction=:infer)Direction Sign Semantics:
For PropDurationSeconds and PropDurationDays, the sign of the duration encodes the propagation direction:
- Positive duration: Forward propagation
- Negative duration: Backward propagation
This design enables clean optimization code where the duration variable can explore both positive and negative values.
When using time-based stops with optimization, use direction=:infer and let the duration sign indicate direction. This avoids the need for manual if-tests to switch between forward and backward propagation.
Conflict Detection:
AstroProp validates that explicit directions don't contradict duration signs:
# These cause errors:
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), -100.0); direction=:forward) # Error!
propagate!(prop, sat, StopAt(sat, PropDurationDays(), 2.0); direction=:backward) # Error!
# These are valid:
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), -100.0); direction=:backward) # ✓
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), -100.0); direction=:infer) # ✓
propagate!(prop, sat, StopAt(sat, PropDurationSeconds(), 100.0); direction=:forward) # ✓Time Scale Handling
AstroProp automatically selects the appropriate time scale for propagation based on the central body of the force model:
- Earth-centered propagation: Use Terrestrial Time (TT)
- All other bodies: Use Barycentric Dynamical Time (TDB)
This ensures the correct dynamical time scale is used in the integration of the equations of motion. Time scale conversions are handled automatically:
- Input times (on the spacecraft or in
StopAt) can be in any scale - The propagator converts to the appropriate scale (TT or TDB) based on the force model's central body
- The final spacecraft time is updated in the same propagation scale
The integration time scale is determined by the central body in your dynamics model. You can express spacecraft states in any coordinate or time system and AstroProp will still use the appropriate dynamical time scale for the integration of the equations of motion under the hood.
Core Functions
AstroProp.OrbitPropagator — Type
OrbitPropagatorOrbital propagator configuration combining force models and integration settings.
Fields
forces::ForceModel: Force model defining the orbital dynamicsinteg::IntegratorConfig: Integration configuration (solver, tolerances, step size)
Examples
gravity = PointMassGravity(earth,(moon,sun))
forces = ForceModel(gravity)
integ = IntegratorConfig(Tsit5(); dt=10.0, reltol=1e-9, abstol=1e-9)
prop = OrbitPropagator(forces, integ)AstroProp.IntegratorConfig — Type
IntegratorConfigConfiguration parameters for orbital integration using DifferentialEquations.jl solvers.
Fields
integrator::Any: ODE solver algorithm (e.g.,Vern7(),Tsit5())dt::Union{Nothing, Float64}: Fixed step size in seconds, orNothingfor adaptive steppingreltol::Float64: Relative tolerance for integration accuracyabstol::Float64: Absolute tolerance for integration accuracy
Example
integ = IntegratorConfig(Vern7(); dt=3600.0, abstol = 1e-12, reltol=1e-12)AstroProp.propagate! — Function
propagate!(op::OrbitPropagator, sc_or_scs, stops...; direction=:forward, kwargs...)Numerically integrate spacecraft equations of motion using propagator until stopping conditions are met.
Arguments
op::OrbitPropagator: Propagator configuration containing force model and integrator settingssc_or_scs: SingleSpacecraftorVector{Spacecraft}to propagatestops...: One or moreStopAtstopping conditions
Keyword Arguments
direction::Symbol=:forward: Time integration direction:forward- Integrate forward in time (default):backward- Integrate backward in time:infer- Automatically determine from time-based stop conditions (duration sign or time comparison)
kwargs...: Additional arguments passed to the underlying ODE solver
Notes
The direction keyword controls time integration direction (which way time moves). This is different from StopAt's direction field, which controls event crossing direction for state-based stops (increasing/decreasing zero-crossing detection).
Returns
ODESolution from DifferentialEquations.jl containing the complete trajectory solution. Access final states via sol.u[end], times via sol.t, or interpolate at any time.
Examples
using AstroEpochs, AstroStates, AstroFrames, AstroUniverse
using AstroModels, AstroCallbacks, AstroProp, OrdinaryDiffEq
# Spacecraft
sat = Spacecraft(
state=CartesianState([7000.0, 300.0, 0.0, 0.0, 7.5, 0.03]),
time=Time("2015-09-21T12:23:12", TAI(), ISOT()),
#name="SC-StopAt",
coord_sys=CoordinateSystem(earth, ICRFAxes()),
)
# Forces + integrator
gravity = PointMassGravity(earth, (moon,sun))
forces = ForceModel(gravity)
integ = IntegratorConfig(Tsit5(); dt=10.0, reltol=1e-9, abstol=1e-9)
prop = OrbitPropagator(forces, integ)
# Propagate to periapsis
propagate!(prop, sat, StopAt(sat, PosDotVel(), 0.0; direction=+1))
# Propagate backwards to node
propagate!(prop, sat, StopAt(sat, PosX(), 0.0); direction=:backward)
# Propagate multiple spacecraft with multiple stopping conditions
sc1 = Spacecraft(); sc2 = Spacecraft()
stop_sc1_node = StopAt(sc1, PosZ(), 0.0)
stop_sc2_periapsis = StopAt(sc2, PosDotVel(), 0.0; direction=+1)
propagate!(prop, [sc1,sc2], stop_sc1_node, stop_sc2_periapsis)
This interface will be deprecated in future releases.
propagate!(model::DynSys, config::IntegratorConfig, stop_conditions...;
direction=:forward, prop_stm=false, kwargs...)Propagate spacecraft orbital states using numerical integration.
AstroProp.StopAt — Type
StopAt{S,V<:AbstractCalcVariable,T}Generic stopping condition for orbital propagation based on calculated quantities or time.
Fields
subject::S: The object to evaluate (e.g.,Spacecraft,Maneuver,CelestialBody)var::V: The calculation variable to monitor (e.g.,PosX(),VelMag(),PropDurationSeconds())target::T: Target value to stop at (numeric value or vector matching calc output)direction::Int: Event crossing direction for state-based stops (-1: decreasing, 0: any, +1: increasing)- For time-based stops (PropDuration*), must be 0 (event crossing not applicable)
- For state-based stops, controls which direction of zero-crossing triggers the event
Constructor
StopAt(subject, var, target; direction::Int=0)Notes
The direction field is for event crossing direction (state-based stops only). For time integration direction (forward/backward), use the direction keyword in propagate!().
Examples
# Stop when spacecraft reaches ascending node (z-position = 0, increasing)
sc = Spacecraft(state=CartesianState([7000.0, 0, 0, 0, 7.5, 0]))
stop_cond = StopAt(sc, PosZ(), 0.0; direction=+1)
# Stop at apoapsis (position dot velocity = 0, decreasing)
stop_apo = StopAt(sc, PosDotVel(), 0.0; direction=-1)
# Stop after 1 hour (time-based: direction must be 0)
stop_time = StopAt(sc, PropDurationSeconds(), 3600.0)API Reference
AstroProp.DynSys — Type
DynSys(; spacecraft, forces)Container for a dynamic system segment.
Keyword Arguments
spacecraft: Vector of spacecraft structs (subtypes ofSpacecraft)forces: OrbitODE model (e.g. CartesianForceModel)
Fields
spacecraft::Vector{<:Spacecraft}: Collection of spacecraft to propagateforces::OrbitODE: Force model defining the dynamics
Constructor
DynSys(; spacecraft, forces)Example
sc = Spacecraft()
gravity = PointMassGravity(earth, ())
sys = DynSys(spacecraft=[sc], forces=gravity)Notes
This interface will be deprecated in future releases
AstroProp.ForceModel — Type
ForceModel{N} <: OrbitODEA collection of orbital dynamics forces and perturbations for spacecraft propagation.
Fields
forces::NTuple{N, OrbitODE}: Tuple of force models (e.g., gravity, drag, solar radiation pressure)center::Union{CelestialBody, Nothing}: Central gravitational body, determined automatically from forces
Constructor
ForceModel(forces...)
ForceModel(force_tuple)The central body is automatically determined from the primary gravitational force in the model.
Example
gravity = PointMassGravity(earth, ())
model = ForceModel(gravity)AstroProp.ForceModel — Method
ForceModel(forces...)
ForceModel(force_tuple)Create a force model for orbital propagation from one or more force components.
Arguments
forces...: Variable number of force objects (e.g.,PointMassGravity)force_tuple: Tuple of force objects
Returns
ForceModel{N}: Force model with N force components
The central gravitational body is automatically determined from the primary gravitational force in the collection.
Examples
gravity = PointMassGravity(earth)
model = ForceModel(gravity)AstroProp.IntegratorTimeCalc — Type
IntegratorTimeCalc <: AbstractCalcVariableBase type for stopping conditions based on integrator time rather than spacecraft state. These are specific to propagation contexts and cannot be used as general calculation variables.
Subtypes
PropDurationSeconds: Stop after a specified number of secondsPropDurationDays: Stop after a specified number of days
Notes
These types are handled specially in propagate!() by setting the integration time span directly rather than using callbacks. They derive from AbstractCalcVariable for type safety in StopAt but do not have corresponding make_calc() implementations.
AstroProp.PointMassGravity — Type
PointMassGravityCombined force model for central body gravity and N-body point-mass perturbations.
Fields
central_body::CelestialBody: The central body about which dynamics are referenced.perturbers::Tuple{Vararg{CelestialBody}}: Other celestial bodies treated as point-mass perturbers.dependencies::Vector{Type{<:AbstractVar}}: Vector of variable dependencies (e.g.,PosVel)num_funs::Int: Number of functions in the ODE
AstroProp.PosVel — Type
PosVel <: AbstractStatePosition-velocity state representation for orbital propagation. This is a legacy state type used internally by the propagation system.
Fields
numvars::Int: Number of state variables (always 6 for position and velocity)
Notes
This struct is marked for deprecation and should be replaced with new state representations from AstroStates.
AstroProp.PropDurationDays — Type
PropDurationDays <: IntegratorTimeCalcStopping condition based on elapsed time in days.
Usage
# Stop after 2.5 days
StopAt(sc, PropDurationDays(), 2.5)AstroProp.PropDurationSeconds — Type
PropDurationSeconds <: IntegratorTimeCalcStopping condition based on elapsed time in seconds.
Usage
# Stop after 1 hour (3600 seconds)
StopAt(sc, PropDurationSeconds(), 3600.0)AstroProp.StopAt — Method
StopAt(subject::Spacecraft, target_time::Time; direction::Int=0)Convenience constructor to stop at an absolute time by converting to elapsed seconds. Supports both forward propagation (target after current) and backward propagation (target before current).
Arguments
subject::Spacecraft: The spacecraft being propagatedtarget_time::Time: The absolute time to stop at (can be past or future)direction::Int=0: Event crossing direction (must be 0 for time-based stops)
Notes
This direction parameter is for event crossing (not applicable to time stops, always use 0). For time integration direction (forward/backward in time), use the direction keyword in propagate!() with values :forward, :backward, or :infer.
Example
using AstroEpochs
sat = Spacecraft(
time=Time("2025-12-25T11:00:00", UTC(), ISOT()),
)
# Forward to future time (default direction=:forward in propagate! works)
stop_future = StopAt(sat, Time("2025-12-26T12:00:00", UTC(), ISOT()))
propagate!(prop, sat, stop_future) # Uses default direction=:forward
# Backward to past time (use direction=:infer in propagate! to auto-detect)
stop_past = StopAt(sat, Time("2025-12-24T12:00:00", UTC(), ISOT()))
propagate!(prop, sat, stop_past; direction=:infer) # Infers :backward from negative elapsed time
# OR explicitly:
propagate!(prop, sat, stop_past; direction=:backward)AstroProp.StopAtApoapsis — Method
StopAtApo(sc::Spacecraft)Constructs a ContinuousCallback for stopping at apoapsis of sc. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp.StopAtAscendingNode — Method
StopAtAscendingNode(sc::Spacecraft)Constructs a ContinuousCallback for stopping at ascending node of sc. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp.StopAtDays — Method
StopAtDays(days::Float64)Returns a DiscreteCallback that stops the integrator after days of simulation time. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp.StopAtPeriapsis — Method
StopAtPeriapsis(sc::Spacecraft)Constructs a ContinuousCallback for stopping at periapsis of sc. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp.StopAtRadius — Method
StopAtRadius(sc::Spacecraft, target_radius::Float64)Returns a ContinuousCallback that triggers when norm(pos) - target_radius = 0. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp.StopAtSeconds — Method
StopAtSeconds(seconds::Float64)Returns a DiscreteCallback that stops the integrator at t = seconds. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp._build_callback — Method
_build_callback(cond::StopAt, dynsys)Build a DifferentialEquations.jl ContinuousCallback for a StopAt condition.
AstroProp._posvel_from_u — Method
function posvelfrom_u(u, dynsys, sc::Spacecraft)
Extract a 6x1 Cartesian pos/vel slice for a spacecraft from integrator state u
AstroProp._sc_index — Method
scindex(dynsys, sc::Spacecraft)
Find spacecraft index in a DynSys
AstroProp._subject_update_from_u! — Method
subjectupdatefromu!(subject, dynsys, u)
Update a subject from the integrator state u (specialize per subject type)
AstroProp._subject_update_from_u! — Method
subjectupdatefromu!(sc::Spacecraft, dynsys, u)
Map Cartesian state slice to spacecraft struct state
AstroProp.accel_eval! — Method
accel_eval!(model::PointMassGravity, t::Time, x̄::Vector,
x̄̇::Vector, sc::Spacecraft, params; jac::Dict = Dict())Evaluate the acceleration due to point-mass gravity from central and perturbing bodies.
AstroProp.apsis_condition — Method
apoapsis_condition(sc::Spacecraft)Returns a closure that evaluates the apoapsis condition r ⋅ v = 0 using the spacecraft's registered :posvel index in the ODE registry. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp.ascnode_condition — Method
ascnode_condition(sc::Spacecraft)Returns a closure that evaluates the ascending node condition z = 0 using the spacecraft's registered :posvel index in the ODE registry. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
AstroProp.check_duplicates — Method
function check_duplicates(bodies::Tuple{Vararg{CelestialBody}})Validate that all names in force model are unique
AstroProp.compute_point_mass_gravity! — Method
nbody_perts(t::Time, center::CelestialBody, pert_bodies::Tuple{Vararg{CelestialBody}}; jac::Bool=false)Compute the gravitational acceleration on a central body due to a tuple of perturbing bodies using Newtonian point-mass gravity.
Arguments
t::Time: State epochposvel::VectorOrbit state (position and velocity)center::CelestialBody: The central body of propagationpert_bodies::Tuple{Vararg{CelestialBody}}: Tuple of perturbing celestial bodies (e.g., Moon, Sun)jac::Bool: Optional keyword (default =false) to return the Jacobian of the perturbing acceleration with respect to the central body's positiontol::Real: Optional tolerance on singularity testing (default 1e-12)
Returns
- If
jac == false:a_pert::Vector{Float64}— total perturbing acceleration - If
jac == true:(a_pert::Vector{Float64}, jacobian::Matrix{Float64})
Notes
- Requires
AstroUniverse.translate(from::CelestialBody, to::CelestialBody, jd_tdb::Float64)to return the vector fromfromtotoin inertial coordinates. - Units must be consistent with the gravitational parameters (
mu) of the celestial bodies.
AstroProp.make_calc — Method
make_calc(subject, var)Create a calculation object from a subject and variable for use in stopping conditions.
Arguments
subject: The object to evaluate (e.g.,Spacecraft,Maneuver,CelestialBody)var: The calculation variable (must be <: AbstractOrbitVar)
Returns
A calculation object that can be used with get_calc() to evaluate the variable on the subject.
Extensibility
This is an extensibility point for the stopping condition framework. Users and packages should extend this function for new subject/variable combinations:
# Example extension for a custom subject type
make_calc(my_object::MyType, v::AbstractOrbitVar) = CustomCalc(my_object, v)Examples
# Built-in case: spacecraft orbital variables
calc = make_calc(spacecraft, PosX())
current_x = get_calc(calc)AstroProp.propagate! — Method
This interface will be deprecated in future releases.
propagate!(model::DynSys, config::IntegratorConfig, stop_conditions...;
direction=:forward, prop_stm=false, kwargs...)Propagate spacecraft orbital states using numerical integration.
AstroProp.propagate! — Method
propagate!(op::OrbitPropagator, sc_or_scs, stops...; direction=:forward, kwargs...)Numerically integrate spacecraft equations of motion using propagator until stopping conditions are met.
Arguments
op::OrbitPropagator: Propagator configuration containing force model and integrator settingssc_or_scs: SingleSpacecraftorVector{Spacecraft}to propagatestops...: One or moreStopAtstopping conditions
Keyword Arguments
direction::Symbol=:forward: Time integration direction:forward- Integrate forward in time (default):backward- Integrate backward in time:infer- Automatically determine from time-based stop conditions (duration sign or time comparison)
kwargs...: Additional arguments passed to the underlying ODE solver
Notes
The direction keyword controls time integration direction (which way time moves). This is different from StopAt's direction field, which controls event crossing direction for state-based stops (increasing/decreasing zero-crossing detection).
Returns
ODESolution from DifferentialEquations.jl containing the complete trajectory solution. Access final states via sol.u[end], times via sol.t, or interpolate at any time.
Examples
using AstroEpochs, AstroStates, AstroFrames, AstroUniverse
using AstroModels, AstroCallbacks, AstroProp, OrdinaryDiffEq
# Spacecraft
sat = Spacecraft(
state=CartesianState([7000.0, 300.0, 0.0, 0.0, 7.5, 0.03]),
time=Time("2015-09-21T12:23:12", TAI(), ISOT()),
#name="SC-StopAt",
coord_sys=CoordinateSystem(earth, ICRFAxes()),
)
# Forces + integrator
gravity = PointMassGravity(earth, (moon,sun))
forces = ForceModel(gravity)
integ = IntegratorConfig(Tsit5(); dt=10.0, reltol=1e-9, abstol=1e-9)
prop = OrbitPropagator(forces, integ)
# Propagate to periapsis
propagate!(prop, sat, StopAt(sat, PosDotVel(), 0.0; direction=+1))
# Propagate backwards to node
propagate!(prop, sat, StopAt(sat, PosX(), 0.0); direction=:backward)
# Propagate multiple spacecraft with multiple stopping conditions
sc1 = Spacecraft(); sc2 = Spacecraft()
stop_sc1_node = StopAt(sc1, PosZ(), 0.0)
stop_sc2_periapsis = StopAt(sc2, PosDotVel(), 0.0; direction=+1)
propagate!(prop, [sc1,sc2], stop_sc1_node, stop_sc2_periapsis)
AstroProp.rebind — Method
rebind(stop_condition::StopAt, owner_map::Dict{Any,Any})Create a new StopAt condition with updated subject references based on an owner mapping.
Arguments
stop_condition::StopAt: The original stopping conditionowner_map::Dict{Any,Any}: Mapping from old subjects to new subjects
Returns
A new StopAt with the subject updated according to the mapping, while preserving the variable, target, and direction unchanged.
Usage
This function is used internally when transferring stopping conditions between different propagation contexts where the subject objects may need to be remapped.
Example
old_stop = StopAt(old_spacecraft, PosX(), 7000.0)
owner_map = Dict(old_spacecraft => new_spacecraft)
new_stop = rebind(old_stop, owner_map)
# new_stop.subject == new_spacecraft, other fields unchangedAstroProp.stop_affect! — Method
stop_affect!(integrator)Callback effect to stop the integration. This interface is replaced by AstroCallbacks Calcs and will be deprecated in future releases.
Index
AstroProp.DynSysAstroProp.ForceModelAstroProp.ForceModelAstroProp.IntegratorConfigAstroProp.IntegratorTimeCalcAstroProp.OrbitPropagatorAstroProp.PointMassGravityAstroProp.PosVelAstroProp.PropDurationDaysAstroProp.PropDurationSecondsAstroProp.StopAtAstroProp.StopAtAstroProp.StopAtApoapsisAstroProp.StopAtAscendingNodeAstroProp.StopAtDaysAstroProp.StopAtPeriapsisAstroProp.StopAtRadiusAstroProp.StopAtSecondsAstroProp._build_callbackAstroProp._posvel_from_uAstroProp._sc_indexAstroProp._subject_update_from_u!AstroProp._subject_update_from_u!AstroProp.accel_eval!AstroProp.apsis_conditionAstroProp.ascnode_conditionAstroProp.check_duplicatesAstroProp.compute_point_mass_gravity!AstroProp.make_calcAstroProp.propagate!AstroProp.propagate!AstroProp.propagate!AstroProp.rebindAstroProp.stop_affect!