Hi, I'd like to contribute a powered descent / retropropulsion module to RocketPy — the ability to simulate a rocket re-igniting its motor (or a dedicated descent motor) after apogee to decelerate before landing, similar to what SpaceX does with Falcon 9 booster recovery.
This is currently missing from RocketPy. With 500+ university teams using the simulator, adding this capability would directly support vehicle recovery research and range safety analysis. I intend to use it for a peer-reviewed paper with a Vietnamese sounding rocket (VNSC-01/VNSC-02) as the worked example.
Proposed Architecture
After reading Flight.py, Rocket.py, Motor.py, and Environment.py, I believe the cleanest integration is a new flight phase inserted into the existing FlightPhases state machine (Option A below), rather than a subclass or a two-leg replay.
New Flight parameters
Flight(
rocket=...,
environment=...,
rail_length=...,
# ... existing params unchanged ...
descent_motor=None, # Motor instance, or None for ballistic descent
descent_trigger="apogee", # "apogee" | float (altitude m) | callable(t, y)
guidance_schedule=None, # pre-solved thrust schedule: Function(t) or array
)
guidance_schedule is intentionally pre-solved offline (e.g. with CasADi) and replayed during integration — no optimizer inside the ODE loop, so Monte Carlo runs stay fast.
- Flights without
descent_motor behave identically to today. Fully backward compatible.
New ODE derivative: u_dot_powered_descent
Structurally identical to u_dot_generalized, except:
net_thrust = descent_motor.thrust(t - t_ignition) (time-shifted to descent ignition)
- Thrust direction: body-frame −Z (retro) or guidance-commanded unit vector
- Mass:
rocket.dry_mass + descent_motor.mass(t - t_ignition)
Phase insertion (inside __check_simulation_events)
After apogee detection (currently flight.py:1113–1159), insert:
self.flight_phases.add_phase(
t_ignition,
derivative=self.u_dot_powered_descent,
callbacks=[self._start_descent_motor],
clear=True,
)
Minimal file footprint
| File |
Change |
rocketpy/simulation/flight.py |
New params + u_dot_powered_descent + descent trigger |
rocketpy/rocket/rocket.py |
Optional add_descent_motor() helper |
tests/test_flight.py |
Validation cases (3-DOF vacuum, analytical check) |
Motor, Environment, math utils |
No changes |
Implementation Plan
- now: Architecture discussion with maintainers (this issue)
- 3-DOF vacuum descent — constant thrust, point mass, no atmosphere; validate against Tsiolkovsky + gravity-turn analytical solution; write tests
- Open draft PR with 3-DOF implementation
- Atmosphere, 6-DOF, guidance schedule support
And if possible, please help me figure some question out,
-
Preferred integration point — New Flight arguments (Option A above) vs. a PoweredDescentFlight subclass vs. a composable FlightSegment approach? Subclassing is fragile given the __ private methods; I lean toward Option A.
-
Motor API — Should we support a separate descent_motor argument on Flight, or is there appetite for multi-burn support directly in Motor (i.e. discontinuous burn windows)?
-
Thrust direction convention — Body-frame −Z (opposing body axis) or inertial −V (opposing velocity vector)? The latter is correct for a hover-slam but requires a guidance input.
-
enh/events branch — I see an open enh/events branch on upstream. Will this affect the event/trigger system in ways I should design around now?
-
equations_of_motion parameter — Would equations_of_motion="powered_descent" be the right way to select this path, consistent with the existing "standard" / "solid_propulsion" options?
Background
I have a background in Aero/CFD, Propulsion, and GNC. The full design note (with class hierarchy analysis, ODE breakdown, and implementation sequence) is available — happy to share or attach.
Happy to hear if the maintainers prefer a different approach entirely before I invest in a deep implementation. Thanks for building such a clean simulator.
Hi, I'd like to contribute a powered descent / retropropulsion module to RocketPy — the ability to simulate a rocket re-igniting its motor (or a dedicated descent motor) after apogee to decelerate before landing, similar to what SpaceX does with Falcon 9 booster recovery.
This is currently missing from RocketPy. With 500+ university teams using the simulator, adding this capability would directly support vehicle recovery research and range safety analysis. I intend to use it for a peer-reviewed paper with a Vietnamese sounding rocket (VNSC-01/VNSC-02) as the worked example.
Proposed Architecture
After reading
Flight.py,Rocket.py,Motor.py, andEnvironment.py, I believe the cleanest integration is a new flight phase inserted into the existingFlightPhasesstate machine (Option A below), rather than a subclass or a two-leg replay.New
Flightparametersguidance_scheduleis intentionally pre-solved offline (e.g. with CasADi) and replayed during integration — no optimizer inside the ODE loop, so Monte Carlo runs stay fast.descent_motorbehave identically to today. Fully backward compatible.New ODE derivative:
u_dot_powered_descentStructurally identical to
u_dot_generalized, except:net_thrust = descent_motor.thrust(t - t_ignition)(time-shifted to descent ignition)rocket.dry_mass + descent_motor.mass(t - t_ignition)Phase insertion (inside
__check_simulation_events)After apogee detection (currently
flight.py:1113–1159), insert:Minimal file footprint
rocketpy/simulation/flight.pyu_dot_powered_descent+ descent triggerrocketpy/rocket/rocket.pyadd_descent_motor()helpertests/test_flight.pyMotor,Environment, math utilsImplementation Plan
And if possible, please help me figure some question out,
Preferred integration point — New
Flightarguments (Option A above) vs. aPoweredDescentFlightsubclass vs. a composableFlightSegmentapproach? Subclassing is fragile given the__private methods; I lean toward Option A.Motor API — Should we support a separate
descent_motorargument onFlight, or is there appetite for multi-burn support directly inMotor(i.e. discontinuous burn windows)?Thrust direction convention — Body-frame −Z (opposing body axis) or inertial −V (opposing velocity vector)? The latter is correct for a hover-slam but requires a guidance input.
enh/eventsbranch — I see an openenh/eventsbranch on upstream. Will this affect the event/trigger system in ways I should design around now?equations_of_motionparameter — Wouldequations_of_motion="powered_descent"be the right way to select this path, consistent with the existing"standard"/"solid_propulsion"options?Background
I have a background in Aero/CFD, Propulsion, and GNC. The full design note (with class hierarchy analysis, ODE breakdown, and implementation sequence) is available — happy to share or attach.
Happy to hear if the maintainers prefer a different approach entirely before I invest in a deep implementation. Thanks for building such a clean simulator.