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: An OrbitPropagator containing the force model and integrator configuration
  • spacecraft: A Spacecraft or Vector{Spacecraft} to propagate
  • stops...: One or more StopAt stopping conditions (varargs)
  • direction: (optional) :forward (default), :backward, or :infer - controls time integration direction
  • kwargs...: 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:

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-9 to 1e-12 for high-precision work, 1e-6 to 1e-9 for 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-9 to 1e-12 for 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)
Starting Point

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)
Event Crossing Direction

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 Direction Parameter

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.

Optimization Compatibility

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
Force Model Central Body

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.OrbitPropagatorType
OrbitPropagator

Orbital propagator configuration combining force models and integration settings.

Fields

  • forces::ForceModel: Force model defining the orbital dynamics
  • integ::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)
source
AstroProp.IntegratorConfigType
IntegratorConfig

Configuration 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, or Nothing for adaptive stepping
  • reltol::Float64: Relative tolerance for integration accuracy
  • abstol::Float64: Absolute tolerance for integration accuracy

Example

integ = IntegratorConfig(Vern7(); dt=3600.0, abstol = 1e-12, reltol=1e-12)
source
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 settings
  • sc_or_scs: Single Spacecraft or Vector{Spacecraft} to propagate
  • stops...: One or more StopAt stopping 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)
source
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.

source
AstroProp.StopAtType
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)
source

API Reference

AstroProp.DynSysType
DynSys(; spacecraft, forces)

Container for a dynamic system segment.

Keyword Arguments

  • spacecraft: Vector of spacecraft structs (subtypes of Spacecraft)
  • forces: OrbitODE model (e.g. CartesianForceModel)

Fields

  • spacecraft::Vector{<:Spacecraft}: Collection of spacecraft to propagate
  • forces::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

source
AstroProp.ForceModelType
ForceModel{N} <: OrbitODE

A 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)
source
AstroProp.ForceModelMethod
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)
source
AstroProp.IntegratorTimeCalcType
IntegratorTimeCalc <: AbstractCalcVariable

Base 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 seconds
  • PropDurationDays: 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.

source
AstroProp.PointMassGravityType
PointMassGravity

Combined 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
source
AstroProp.PosVelType
PosVel <: AbstractState

Position-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.

source
AstroProp.PropDurationDaysType
PropDurationDays <: IntegratorTimeCalc

Stopping condition based on elapsed time in days.

Usage

# Stop after 2.5 days
StopAt(sc, PropDurationDays(), 2.5)
source
AstroProp.PropDurationSecondsType
PropDurationSeconds <: IntegratorTimeCalc

Stopping condition based on elapsed time in seconds.

Usage

# Stop after 1 hour (3600 seconds)
StopAt(sc, PropDurationSeconds(), 3600.0)
source
AstroProp.StopAtMethod
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 propagated
  • target_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)
source
AstroProp.StopAtApoapsisMethod
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.

source
AstroProp.StopAtAscendingNodeMethod
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.

source
AstroProp.StopAtDaysMethod
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.

source
AstroProp.StopAtPeriapsisMethod
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.

source
AstroProp.StopAtRadiusMethod
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.

source
AstroProp.StopAtSecondsMethod
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.

source
AstroProp._posvel_from_uMethod

function posvelfrom_u(u, dynsys, sc::Spacecraft)

Extract a 6x1 Cartesian pos/vel slice for a spacecraft from integrator state u

source
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.

source
AstroProp.apsis_conditionMethod
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.

source
AstroProp.ascnode_conditionMethod
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.

source
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 epoch
  • posvel::Vector Orbit state (position and velocity)
  • center::CelestialBody: The central body of propagation
  • pert_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 position
  • tol::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 from from to to in inertial coordinates.
  • Units must be consistent with the gravitational parameters (mu) of the celestial bodies.
source
AstroProp.make_calcMethod
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)
source
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.

source
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 settings
  • sc_or_scs: Single Spacecraft or Vector{Spacecraft} to propagate
  • stops...: One or more StopAt stopping 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)
source
AstroProp.rebindMethod
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 condition
  • owner_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 unchanged
source
AstroProp.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.

source

Index