Acceleration-Based Parachute Triggers#
RocketPy lets parachute trigger functions access the state derivative
u_dot (which holds the accelerations at indices [3:6]) in addition to
pressure, height and the state vector. This enables avionics-style deployment
logic that mimics how real flight computers use accelerometer (IMU) data to
detect flight phases such as burnout, free-fall or liftoff.
Overview#
Built-in string and numeric triggers rely on altitude and vertical velocity. By writing a custom trigger function, you can additionally use acceleration to implement mission-specific logic, for example:
Motor burnout detection (sudden drop in acceleration)
Apogee detection combining near-zero velocity with downward acceleration
Free-fall / ballistic coast detection (low total acceleration)
Liftoff detection (high total acceleration)
For realistic noisy measurements, attach an Accelerometer sensor to the rocket and read it inside the
trigger instead of feeding the ideal u_dot directly.
Trigger function signatures#
A custom trigger callable may take 3, 4, or 5 arguments. RocketPy detects
the signature automatically and only computes u_dot when a trigger asks for
it (so legacy triggers pay no performance cost):
(pressure, height, state_vector)— the classic signature.(pressure, height, state_vector, u_dot)— name the 4th argumentu_dot(orudot/acc/acceleration) to receive the derivative; any other name receives thesensorslist instead.(pressure, height, state_vector, sensors, u_dot)— receive both.
state_vector is [x, y, z, vx, vy, vz, e0, e1, e2, e3, w1, w2, w3] and
u_dot is [vx, vy, vz, ax, ay, az, ...].
Built-in apogee trigger#
Deploys when the rocket starts descending (vertical velocity becomes negative):
rocket.add_parachute(
name="Main",
cd_s=10.0,
trigger="apogee",
sampling_rate=100,
lag=0.5,
)
Numeric altitude trigger#
Pass a number to deploy at a fixed height above ground level while descending:
rocket.add_parachute(
name="Main",
cd_s=10.0,
trigger=400, # meters above ground level
sampling_rate=100,
lag=0.5,
)
Custom trigger: motor burnout#
Burnout is highly mission-dependent, so it is best expressed as a custom trigger with user-defined thresholds.
Logic: detect a drop in vertical or total acceleration once the rocket is above a minimum height and still ascending.
def burnout_trigger_factory(
min_height=5.0,
min_vz=0.5,
az_threshold=-8.0,
total_acc_threshold=2.0,
):
def burnout_trigger(_pressure, height, state_vector, u_dot):
ax, ay, az = u_dot[3], u_dot[4], u_dot[5]
total_acc = (ax**2 + ay**2 + az**2) ** 0.5
vz = state_vector[5]
if height < min_height or vz <= min_vz:
return False
return az < az_threshold or total_acc < total_acc_threshold
return burnout_trigger
Attach it to a rocket:
rocket.add_parachute(
name="Drogue",
cd_s=1.0,
trigger=burnout_trigger_factory(
min_height=10.0,
min_vz=2.0,
az_threshold=-10.0,
total_acc_threshold=3.0,
),
sampling_rate=100,
lag=1.5,
)
Custom trigger: apogee by acceleration#
Logic: near-zero vertical velocity together with downward acceleration.
def apogee_acc_trigger(_pressure, _height, state_vector, u_dot):
vz = state_vector[5]
az = u_dot[5]
return abs(vz) < 1.0 and az < -0.1
rocket.add_parachute(
name="Main",
cd_s=10.0,
trigger=apogee_acc_trigger,
sampling_rate=100,
lag=0.5,
)
Custom trigger: free-fall#
Logic: low total acceleration while descending above a small height.
def freefall_trigger(_pressure, height, state_vector, u_dot):
ax, ay, az = u_dot[3], u_dot[4], u_dot[5]
total_acc = (ax**2 + ay**2 + az**2) ** 0.5
vz = state_vector[5]
return height > 5.0 and vz < -0.2 and total_acc < 11.5
rocket.add_parachute(
name="Drogue",
cd_s=1.0,
trigger=freefall_trigger,
sampling_rate=100,
lag=1.5,
)
Custom trigger: liftoff#
Logic: detect motor ignition by high total acceleration.
def liftoff_trigger(_pressure, _height, _state_vector, u_dot):
ax, ay, az = u_dot[3], u_dot[4], u_dot[5]
total_acc = (ax**2 + ay**2 + az**2) ** 0.5
return total_acc > 15.0
rocket.add_parachute(
name="Lift",
cd_s=0.5,
trigger=liftoff_trigger,
sampling_rate=100,
lag=0.1,
)
Custom trigger: using sensor measurements#
A 5-argument trigger receives both the sensors list and u_dot, so you
can cross-check a noisy accelerometer reading against the ideal derivative.
def advanced_trigger(_pressure, _height, _state_vector, sensors, u_dot):
if not sensors:
return False
acc_reading = sensors[0].measurement
if acc_reading is None or len(acc_reading) < 3:
return False
meas_az = acc_reading[2]
az = u_dot[5]
return az < -5.0 and meas_az < -5.0
rocket.add_parachute(
name="Advanced",
cd_s=1.5,
trigger=advanced_trigger,
sampling_rate=100,
)
Note
For realistic IMU behavior, attach a RocketPy sensor with its own noise
model and read it inside the trigger via sensors, instead of relying on
the ideal u_dot. See the Sensor Classes for available sensors.
Full example: dual deployment#
In RocketPy only one parachute is active at a time, so a dual-deploy avionics can be reproduced with two custom triggers — a drogue at burnout and a main at a lower altitude:
from rocketpy import Rocket, Flight, Environment
# Environment and rocket setup
env = Environment(latitude=32.99, longitude=-106.97, elevation=1400)
env.set_atmospheric_model(type="standard_atmosphere")
rocket = Rocket(...) # configure your rocket (motor, fins, etc.)
# Drogue: deploy shortly after burnout (acceleration drop while ascending)
def drogue_burnout_trigger(_pressure, height, state_vector, u_dot):
az = u_dot[5]
vz = state_vector[5]
return height > 10 and vz > 1 and az < -8.0
rocket.add_parachute(
name="Drogue",
cd_s=1.0,
trigger=drogue_burnout_trigger,
sampling_rate=100,
lag=1.5,
noise=(0, 8.3, 0.5), # pressure-signal noise
)
# Main: deploy below 800 m while descending
def main_deploy_trigger(_pressure, height, state_vector, u_dot):
vz = state_vector[5]
az = u_dot[5]
return height < 800 and vz < -5 and az > -15
rocket.add_parachute(
name="Main",
cd_s=10.0,
trigger=main_deploy_trigger,
sampling_rate=100,
lag=0.5,
noise=(0, 8.3, 0.5),
)
# Flight simulation
flight = Flight(
rocket=rocket,
environment=env,
rail_length=5.2,
inclination=85,
heading=0,
)
flight.all_info()