Controllers#
RocketPy can simulate active, in-flight control systems — such as air brakes or
other actuators — through a controller function that you attach to a
controllable object (for example, an rocketpy.AirBrakes added with
Rocket.add_air_brakes). During the flight simulation, RocketPy calls your
controller function at the appropriate times, letting it read the current
simulation state and command the actuator.
This page describes the controller-function interface and how its call timing is governed. For a complete, runnable example that puts these pieces together, see the Air Brakes Example.
The Controller Function#
A controller function receives information about the simulation up to the current time step and sets the state of the controlled object. It must take in the following arguments, in this order:
time(float): The current simulation time in seconds.sampling_rate(float orNone): The rate at which the controller function is called, measured in Hertz (Hz). It isNonefor continuous controllers, so guard any1 / sampling_ratecomputation againstNone.state(list): The state vector of the simulation. The state is a list containing the following values, in this order:x: The x position of the rocket, in meters.y: The y position of the rocket, in meters.z: The z position of the rocket, in meters.v_x: The x component of the velocity of the rocket, in meters per second.v_y: The y component of the velocity of the rocket, in meters per second.v_z: The z component of the velocity of the rocket, in meters per second.e0: The first component of the quaternion representing the rotation of the rocket.e1: The second component of the quaternion representing the rotation of the rocket.e2: The third component of the quaternion representing the rotation of the rocket.e3: The fourth component of the quaternion representing the rotation of the rocket.w_x: The x component of the angular velocity of the rocket, in radians per second.w_y: The y component of the angular velocity of the rocket, in radians per second.w_z: The z component of the angular velocity of the rocket, in radians per second.
state_history(list): A record of the rocket’s state at each step throughout the simulation. The state_history is organized as a list of lists, with each sublist containing a state vector. The last item in the list always corresponds to the previous state vector, providing a chronological sequence of the rocket’s evolving states.observed_variables(list): A list containing the variables that the controller function returns. The return of each controller function call is appended to the observed_variables list. The initial value in the first step of the simulation of this list is provided by theinitial_observed_variablesargument.The controlled object (e.g.
air_brakes): the instance being controlled, whose attributes the function sets (for example,air_brakes.deployment_level).
Note
The controller function accepts 6, 7, or 8 parameters for backward compatibility:
6 parameters (original):
time,sampling_rate,state,state_history,observed_variables, and the controlled object.7 parameters (with sensors): adds
sensorsas the 7th parameter.8 parameters (with environment): adds
sensorsandenvironmentas the 7th and 8th parameters.
The environment parameter provides access to atmospheric conditions (wind, temperature, pressure, elevation) without relying on global variables. This enables proper serialization of rockets with controllers and improves code modularity. Available methods include
environment.elevation,environment.wind_velocity_x(altitude),environment.wind_velocity_y(altitude),environment.speed_of_sound(altitude), and others.Anything can be returned by the controller function. The returned values are saved in the
observed_variableslist at every time step and can then be accessed by the controller function at the next time step. The saved values can also be accessed after the simulation is finished, which is useful for debugging and for plotting the results.The controller function can also be defined in a separate file and imported into the simulation script. This includes importing
corcppcode into Python.
Discrete vs. Continuous Controllers#
The sampling_rate argument determines when the controller function is
called during the flight simulation:
Discrete controller (
sampling_rateset to a number, e.g.10): the controller function is called at fixed intervals of1 / sampling_rateseconds. This mirrors a real flight computer that reads its sensors and updates its actuators at a fixed frequency, and is the recommended choice when you want the simulation to reflect the actual control-loop rate of your hardware.Continuous controller (
sampling_rate=None): the controller function is called at every solver step of the numerical integrator. Use this when you want the control law to act as a continuous function of the state rather than a sampled one (for example, when validating a control model analytically).
Warning
For continuous controllers, sampling_rate is passed to your controller
function as None. Any computation such as 1 / sampling_rate (a
common pattern for rate-limiting deployment) must guard against None to
avoid a TypeError.
Note
Discrete controllers add their sampling instants as time nodes to the
simulation, so remember to set time_overshoot=False in the Flight
to make the integrator stop exactly at those instants. Continuous
controllers do not add time nodes; they are evaluated on the integrator’s
own steps.