Skip to main content

Crate rockets_engine

Crate rockets_engine 

Source
Expand description

Powered, three-dimensional point-mass flight, using SI units and simulation time.

Prescribed motors supply thrust and consume propellant in proportion to impulse; Stages add serial or parallel staging with scheduled separations. Simulator integrates translation while ForceModel supplies environmental acceleration and Guidance supplies optional control commands. UniformGravity covers local flat-frame flight and CentralGravity covers planet-scale arcs; the default ballistics feature reuses ballistics-engine’s atmosphere and drag kernel.

Coordinates are right-handed; the conventional local frame is X/downrange, Y/up, Z/lateral, but CentralGravity works in an Earth-centered frame of the caller’s choosing. No time compression occurs inside this crate. This is a point-mass model, not an attitude, actuator or aerodynamic-lift simulation.

See the README and examples/boost_coast.rs for integration and model assumptions.

§rockets-engine

A Rust companion to ballistics-engine for powered, three-dimensional point-mass flight. It adds prescribed motor burns, changing mass, incremental RK4 integration and application-owned guidance hooks. The default adapter calls the existing ballistics-engine gravity/drag derivative function; it does not fork or modify that engine.

The crate is published on crates.io and consumes ballistics-engine 0.48.0 from crates.io. Rust 1.99.1 is pinned for development, matching the game workspace.

§Use

[dependencies]
rockets-engine = "0.2"

§Run

cargo test --locked --all-features
cargo run --locked --example boost_coast
cargo run --locked --example guidance_hook
cargo run --locked --example staging
cargo run --locked --example icbm_midcourse
cargo doc --locked --no-deps --open

boost_coast prints CSV for a synthetic small rocket through ignition, powered flight and coast. Its numbers are illustrative. guidance_hook demonstrates externally supplied control acceleration without a target-tracking algorithm. staging flies a three-stage rocket through separations and inter-stage coasts. icbm_midcourse coasts a post-boost state around a central-gravity Earth to a reentry handoff; it needs no features and shows the planet-scale use of the integrator.

§Basic use

use rockets_engine::{
    ControlInput, FlightState, IntegratorSettings, Motor, Rocket,
    Simulator, ThrustCurve, ThrustPoint, UniformGravity, Vec3,
};

let curve = ThrustCurve::new(vec![
    ThrustPoint { time_s: 0.0, thrust_n: 0.0 },
    ThrustPoint { time_s: 0.1, thrust_n: 20.0 },
    ThrustPoint { time_s: 0.9, thrust_n: 15.0 },
    ThrustPoint { time_s: 1.0, thrust_n: 0.0 },
])?;
let motor = Motor::new(curve, 0.04, 0.2)?; // 40 g propellant; ignition at t=0.2 s
let rocket = Rocket::new(0.18, Some(motor))?; // Dry mass includes the motor casing
let simulator = Simulator::new(
    rocket,
    UniformGravity::default(), // Gravity only; see the atmospheric adapter below
    IntegratorSettings::default(),
)?;
let state = FlightState {
    time_s: 0.0,
    position_m: Vec3::new(0.0, 2.0, 0.0),
    velocity_mps: Vec3::new(2.0, 8.0, 0.0),
};
let result = simulator.step(
    &state,
    0.05,
    ControlInput::along(Vec3::new(0.3, 1.0, 0.0)),
)?;
assert_eq!(result.state.time_s, 0.05);

To use the same aerodynamic force kernel as the game, replace UniformGravity with BallisticForces:

use rockets_engine::{ballistics::{Atmosphere, BallisticForces}, Vec3};
let forces = BallisticForces::new(
    0.025, // Diameter in metres
    vec![(0.0, 0.45), (0.8, 0.5), (1.2, 0.7), (3.0, 0.4)], // Actual Mach/Cd pairs
    Atmosphere::default(),
    Vec3::new(2.0, 0.0, 0.0), // Air velocity: positive X is a tailwind
)?;

§Model and units

  • All values use SI units: metres, seconds, kilograms, newtons and m/s². Time is simulation time. Any game time compression belongs outside this crate.
  • For local flight the fixed right-handed frame is X downrange, Y up, Z lateral. With BallisticForces, position Y is absolute altitude above sea level; the weather station has its own altitude. Launch elevation is encoded in velocity and thrust direction, not a rotating coordinate frame.
  • For planet-scale flight, integrate in an Earth-centered frame with CentralGravity: position measured from Earth’s center, inverse-square gravity in both magnitude and direction. icbm_midcourse shows the pattern. The flat-frame models (UniformGravity, BallisticForces) are invalid at intercontinental ranges; CentralGravity is invalid (singular) at its own center and carries no atmosphere.
  • Thrust is piecewise linear in time since ignition. Curves must start at zero time, have at least two samples, strictly increase in time and have positive total impulse. Nonzero endpoint thrust is supported.
  • Fuel consumption is proportional to delivered impulse. If I(t) is accumulated impulse, I_total is total impulse and mp is initial propellant mass, remaining fuel is mp × (1 − I(t)/I_total). This assumes constant effective exhaust velocity I_total/mp; the prescribed thrust already includes exhaust/pressure effects. There is no separate motor pressure compensation.
  • Mass is computed analytically at every RK4 stage rather than numerically integrating and clamping an independent fuel state. Dry mass is positive and fuel cannot become negative. At burnout thrust is zero and the empty motor remains attached.
  • A Rocket is a base mass plus any number of Stages, each with its own motor schedule and an optional separation time. Total thrust sums over attached burning motors, so serial and parallel (strap-on) staging share one model. At separation the stage’s dry mass, motor and unspent propellant leave the vehicle; separating a burning stage (hot staging) ends its thrust. Rocket::new keeps the 0.1 single-motor shape.
  • Ignition, every curve knot, burnout and every stage separation split the integration grid. RK4 uses the appropriate one-sided mass and force at discontinuities: a step closing on a separation still sees the departing stage, and the next step opens without it, including burns shorter than the maximum timestep.
  • The default maximum internal step is 0.01 seconds, sized for motor burns. In vacuum coast (midcourse) raise it — seconds per step is plenty under central gravity; the Kepler-invariant tests integrate orbits at 1–2 s steps. This is fixed-step RK4, not an adaptive solver; choose a timestep suitable for the forces and confirm convergence for new vehicle models.

This baseline follows the thrust-curve, propellant-mass, gravity and drag structure illustrated by NASA’s model rocket simulation. The force model is consistent with NASA’s rocket thrust equation.

§Guidance and other forces

Guidance::command(GuidanceContext) returns a ControlInput. A closure can implement the hook directly. The context contains the current flight state, motor output, mass, requested duration and configured steering limit.

  • Guidance is called once per step_guided call. Its command is held constant during that call’s internal RK4 stages and substeps.
  • thrust_direction is normalized. It describes externally supplied orientation; it does not model attitude, angular velocity, gimbal travel or turning rate. FixedDirection provides a simple unguided orientation.
  • steering_acceleration_mps2 is a world-frame acceleration supplied by an external actuator/control model. The solver caps its vector magnitude using max_steering_accel_mps2, which defaults to zero. It may act during coast; its physical availability and direction are the caller’s responsibility.
  • The core has no target, seeker, interception or Godot entity types. Controllers can own their own state and inputs without changing the integrator.
  • ForceModel::acceleration supplies environmental acceleration at each RK4 stage with that stage’s current mass. A closure can implement this hook too. Keep it deterministic and free of side effects. BallisticForces::acceleration_in_wind supports wrappers that sample spatial or time-dependent wind.

The atmospheric adapter uses the body’s own Cd-versus-Mach curve and updates both SI mass and the engine’s imperial mass mirror. It includes gravity and drag; bullet-specific spin, yaw, Magnus, Coriolis and postprocessing effects are disabled. Standard atmosphere delegates to the upstream altitude model: humidity affects density, while this derivative path uses dry-air sound speed. Uniform atmosphere obeys the upstream direct-mode limits (0 ≤ density < 2 kg/m³, sound speed > 200 m/s); a zero density retains gravity but removes drag. UniformGravity(Vec3::zeros()) gives an inertial vacuum.

The upstream ICAO atmosphere is defined to about 80 km; do not fly BallisticForces above it. Wrap it in AltitudeSwitch with a vacuum model above a cutoff (UniformGravity for flat-frame flight, CentralGravity for Earth-centered arcs) when a trajectory leaves the atmosphere.

§Save, replay and host integration

Simulator does not hold evolving flight state. Each step returns a new FlightState, end-of-step motor/mass telemetry and its internal step count. An error leaves the caller’s state untouched. Invalid numeric inputs and non-finite results return errors, and each call has a bounded substep budget.

The default serde feature serializes FlightState and MotorPhase. To resume a flight, restore the state with the same motor schedule, vehicle, environment and solver settings. Motor fuel/phase are derived from simulation time, so they cannot drift apart in a snapshot. Save any stateful guidance controller separately. Invalid deserialized states are rejected when stepped. A controller’s mutations are not rolled back if integration fails after the guidance call.

For deterministic replay, retain the same fixed public update cadence, control inputs and environment history. Internal grids are anchored to each public step; changing how calls are partitioned can change floating-point results. Cross-platform bit-for-bit identity is not promised.

For Counterbattery, a future CbBallistics adapter can repeatedly call step to precompute an unguided powered arc, or call step_guided at the simulation cadence for live control. Convert world coordinates once at that boundary, especially absolute altitude and side-facing X. The host must detect terrain and unit collisions over each returned movement interval; the library does not stop on a ground plane. No game integration is included in this crate.

§Scope of 0.2

The engine models translation with prescribed motor burns across serial or parallel stages, in flat or Earth-centered frames. It does not yet model throttle or restart within a stage, launch rails, changing drag geometry, body attitude, lift coefficients, actuator dynamics, seekers, Earth rotation (Coriolis and launch-site velocity are the caller’s responsibility in an ECI frame), orbit perturbations such as J2, or terrain collision localization. Guidance hooks provide the boundary for future control models; they are not a built-in autopilot.

§Validation

The tests check the ideal rocket equation and analytic position in vacuum, RK4 convergence, delayed ignition, nonzero endpoint thrust, short burns, zero-thrust intervals, fuel bounds, wind/mass/drag response, control limits, invalid inputs, work limits, and snapshot replay. Unpowered trajectories are compared against the upstream RK4 solver across multiple vehicle, wind and atmosphere configurations. Staging tests cover exact mass drops at separation, hot-staging thrust overlap, inter-stage coast phases, parallel boosters and two-burn Δv against Tsiolkovsky — including a regression for one-sided mass at a step closing exactly on a separation. Central-gravity tests assert Kepler invariants: a circular orbit closes to millimetres and an ICBM-scale midcourse ellipse conserves specific energy and angular momentum to better than 1 part in 10¹⁰. These checks establish numerical behavior and compatibility, not empirical validation of a particular real motor or airframe.

cargo fmt --all -- --check
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo test --locked --all-features
cargo test --locked --no-default-features
cargo test --locked --no-default-features --features ballistics
cargo test --locked --no-default-features --features serde

ballistics enables the companion adapter and its ballistics-engine dependency. serde enables snapshot serialization. Disabling both leaves the integrator, motor, guidance and custom force hooks usable on their own.

Licensed under MIT; see the repository’s LICENSE file.

Modules§

ballistics
Adapter to ballistics-engine 0.48’s public derivative kernel.

Structs§

AltitudeSwitch
Routes to one of two force models depending on altitude (position Y).
CentralGravity
Inverse-square gravity toward a fixed center, for planet-scale flight.
ControlInput
World-frame controls held constant for one caller-requested simulation step.
FixedDirection
Unguided orientation: thrust always follows the specified fixed world axis. This does not simulate passive body alignment or attitude dynamics.
FlightState
Complete translational state. Motor phase and fuel are derived from time and configuration.
GuidanceContext
Snapshot supplied once to guidance for each crate::Simulator::step_guided call.
IntegratorSettings
Integration accuracy, work budget and external control authority.
Motor
A single, prescribed motor burn with constant effective exhaust velocity.
MotorSample
Instantaneous motor output, derived entirely from configuration and simulation time.
Rocket
Base structural mass plus an ordered set of stages.
RocketSample
Motor output and total current vehicle mass.
Simulator
Stateless RK4 stepper over an immutable vehicle, force model and settings.
Stage
One separable stage: structural mass carried until a scheduled separation, plus an optional motor with its own burn schedule.
StepResult
Result of a successful advancement. An error never overwrites the caller’s input state.
ThrustCurve
Validated, piecewise-linear thrust curve with exact piecewise-quadratic impulse.
ThrustPoint
One measured or synthetic thrust sample, relative to motor ignition.
UniformGravity
Constant gravity with no atmosphere. Use a zero vector for an inertial vacuum.

Enums§

Error
Checked construction, integration and user-supplied model errors.
MotorPhase
Motor lifecycle. A spent motor stays attached and contributes to dry mass.

Constants§

EARTH_MU_M3_S2
Standard gravitational parameter of Earth, in cubic metres per second squared.

Traits§

ForceModel
Environmental acceleration hook (gravity, drag, wind, etc.), without motor or controls.
Guidance
Application-owned controller hook, independent of entities, targets and render timing.

Type Aliases§

Result
Result type shared by the solver and extension hooks.
Vec3
Three-dimensional SI vector in the fixed world frame.