Skip to main content

Crate astrodyn_bevy

Crate astrodyn_bevy 

Source
Expand description

§astrodyn_bevy

A Rust port of NASA JEOD (JSC Engineering Orbital Dynamics, v5.4) with Bevy ECS wiring on top.

astrodyn_bevy reimplements JEOD’s spacecraft dynamics — spherical-harmonics gravity, Earth rotation (precession/nutation/polar motion), atmospheric drag, solar radiation pressure, gravity-gradient torque, multi-step integrators, time-scale conversion (TAI/UTC/UT1/TDB/TT/GMST), DE4xx ephemerides — as pure Rust crates, then exposes them through a thin Bevy adapter so they slot into any Bevy app.

Status: pre-1.0. Tier 3 cross-validated against JEOD Trick simulations (see the Tier3-Regeneration wiki page). API may change before 1.0.

§Architecture

Three layers, separated by hard dependency rules:

  • astrodyn_* — pure Rust physics crates, zero Bevy dependency. Math, integrators, frame transforms, gravity, time scales, ephemerides.
  • astrodyn — orchestration and recipes. Composes astrodyn_* into a pipeline; the single API surface for any ECS adapter. Zero Bevy dependency.
  • astrodyn_bevy (this crate) — thin Bevy glue. Components, systems that delegate to astrodyn, plugin registration. Depends only on astrodyn + bevy.

See the Strategy and Type-System wiki pages for architecture detail and the typed-quantity layer.

§Quick start

[dependencies]
bevy = "0.18"
astrodyn_bevy = "0.1"
use bevy::prelude::*;
use astrodyn_bevy::prelude::*;
use astrodyn_bevy::recipes::{earth, orbital_elements, vehicle};
use astrodyn::Earth;

fn setup(mut commands: Commands) {
    let earth_recipe = earth::point_mass();
    let mu = earth_recipe.source.mu.m3_per_s2();
    let earth_entity = commands
        .spawn((
            GravitySourceC(earth_recipe.source),
            SourceInertialPositionC::default(),
            TranslationalStateC::<Earth>::default(),
        ))
        .id();

    let cfg = VehicleBuilder::new()
        .from_orbital_elements(orbital_elements::iss(), mu)
        .three_dof_point_mass(vehicle::iss_mass())
        .rk4()
        .gravity(GravityControl::new_spherical(0_usize, GravityGradient::Skip))
        .build();

    cfg.spawn_bevy::<Earth>(&mut commands, &[earth_entity]);
}

fn main() {
    App::new()
        .add_plugins(MinimalPlugins)
        .add_astrodyn(10.0)
        .add_systems(Startup, setup)
        .run();
}

The typestate VehicleBuilder rejects misuse at compile time (no integrator chosen, no state set, mismatched coordinate frames). Errors render in physics language — “expected Position<RootInertial>, found Position<Ecef> — apply a FrameTransform<Ecef, RootInertial> first” — not as PhantomData mismatches.

A full worked example lives in examples/typed_mission.rs.

§Verification

Three test tiers, all part of the definition of done for every release:

  • Tier 1 — unit tests on pure functions (round-trips, convergence).
  • Tier 2 — comparison against static reference vectors extracted from JEOD source files (gravity test cases, Euler angle tables).
  • Tier 3 — end-to-end trajectory cross-validation: propagate from the same initial conditions as a JEOD Trick simulation and compare position, velocity, attitude, and angular velocity over hours or days. Reference CSVs are committed to the repo.
cargo nextest run --workspace -E 'not test(tier3_)'   # fast: Tier 1 + 2
cargo nextest run --workspace -E 'test(tier3_)'       # Tier 3

cargo nextest run --workspace works on a fresh clone without $JEOD_HOME — every tier (unit, Tier 2, Tier 3) reads from committed fixtures under test_data/. $JEOD_HOME is required only when regenerating those fixtures via the extract_* binaries under crates/astrodyn_verif_jeod/src/bin/ or refreshing the verbatim mirror at crates/astrodyn_verif_jeod/test_data/jeod_inputs/. See CLAUDE.md for the full build / test / regen workflow.

§Documentation

Most docs live on the project wiki: architecture and phase history (Strategy), typed-quantity primer (Type-System), Tier 3 regeneration recipe (Tier3-Regeneration), the JEOD↔astrodyn_bevy capability matrix, per-SIM coverage map, and audit findings.

The one exception that stays in the repo is docs/JEOD_invariants.md — the catalog of JEOD C++ invariants and where each is enforced in our Rust port. It lives next to the code because tags like // JEOD_INV: XX.YY in source are consistency-checked against the catalog.

§License

Licensed under either of

at your option.

NASA JEOD itself is distributed under NASA’s open-source license and is not redistributed by this project.

Re-exports§

pub use app_ext::AstrodynAppExt;
pub use body_action::add_body_action_via;
pub use body_action::body_action_intake_system;
pub use body_action::body_action_system;
pub use body_action::body_action_unregistered_planet_fence_system;
pub use body_action::BodyActionCommandsExt;
pub use body_action::BodyActionEvent;
pub use body_action::BodyActionsR;
pub use body_action::RegisteredPlanetsR;
pub use frame_attach_system::frame_attach_system;
pub use frame_attach_system::propagate_frame_attached_state_post_integration_system;
pub use frame_attach_system::propagate_frame_attached_state_system;
pub use kinematic_propagation::propagate_state_from_root_post_integration_system;
pub use kinematic_propagation::propagate_state_from_root_system;
pub use mass_tree::composite_mass_system;
pub use mass_tree::MassTreeQueries;
pub use mass_tree::MassTreeView;
pub use scenario::ScenarioHandles;
pub use scenario::SimulationBuilderBevyExt;
pub use source_mutator::SourceMutator;
pub use source_mutator::SourceReader;
pub use wrench::wrench_aggregation_system;
pub use bundles::*;
pub use components::*;
pub use sets::*;
pub use systems::*;

Modules§

app_ext
AstrodynAppExt — ergonomic App setup and fixed-step advancement.
body_action
Bevy adapter for astrodyn::BodyAction: queue body actions against an entity at startup or mid-sim, then have them applied by body_action_system each tick before the rest of the pipeline runs.
bundles
Convenience bundles for spawning common entity types.
components
Bevy Component newtypes wrapping astrodyn typed siblings (state, mass, gravity controls, interactions, derived states).
frame_attach_system
Bevy systems for frame-attached body integration.
frame_param
Bevy-native SystemParams for cross-frame state computation (Frame-Tree-ECS-Native § 13).
kinematic_propagation
Bevy system for kinematic state propagation root → leaves.
mass_tree
Bevy-side ECS mass-tree adapter.
prelude
Mission-crate prelude: use astrodyn_bevy::prelude::*;.
recipes
Recipe catalogue re-export: use astrodyn_bevy::recipes::*;.
scenario
SimulationBuilder → Bevy App bridge — the canonical mission entry point for whole-scenario composition.
sets
AstrodynSet — the Bevy SystemSet partition that mirrors JEOD’s per-step pipeline.
source_mutator
Source-state read/write API for Bevy missions.
systems
Bevy Systems that delegate per-body work to astrodyn per-body orchestration functions. Each system queries the relevant components, calls into astrodyn, and writes the result back. No physics algorithms live here.
validation
Runtime validation of JEOD invariants.
wrench
Bevy system for composite-rigid-body wrench aggregation.

Structs§

AstrodynPlugin
Unified JEOD plugin — registers all pipeline systems and schedule sets.
AtmosphereConfig
Planet-level atmosphere configuration (ECS-agnostic).
AtmosphereModelR
Bevy resource wrapping AtmosphereConfig with an entity reference for the planet whose rotation matrix is used for geodetic conversion.
EphemerisR
Bevy resource wrapping astrodyn::Ephemeris for DE4xx ephemeris access.
IntegrationDtR
Bit-exact f64 pipeline integration timestep.
MassTreeR
Bevy resource wrapping MassTree for multi-body vehicles.
PolarMotionR
Optional Bevy resource for polar motion (xp, yp) in radians.
RootFrameEntityR
Bevy resource holding the Entity of the root frame entity in the ECS-native frame hierarchy. The root frame entity carries components::FrameTransC / components::FrameRotC / components::FrameAngVelC at identity and is the parent of every source’s inertial frame entity (which is the parent of every body or pfix frame entity, and so on). Spawned by AstrodynPlugin::build before any source/body registration so the registration systems can ChildOf-link their frame entities to it. Mission code reads cross-frame state via crate::frame_param::RelativeFrameState and crate::frame_param::FrameOrigin.
SimulationTimeR
Bevy resource wrapping SimulationTime.

Enums§

AtmosphereModel
Selectable atmosphere model.

Traits§

VehicleConfigBevyExt
Bevy-side terminal for astrodyn::VehicleBuilder.

Functions§

register_planet_systems
Register the planet-generic system instantiations needed for a downstream multi-planet mission.