diff --git a/rocketpy/control/controller.py b/rocketpy/control/controller.py index e81e70915..18ec5ebfa 100644 --- a/rocketpy/control/controller.py +++ b/rocketpy/control/controller.py @@ -17,7 +17,7 @@ def __init__( self, interactive_objects, controller_function, - sampling_rate, + sampling_rate=None, initial_observed_variables=None, name="Controller", ): @@ -72,7 +72,8 @@ def __init__( relevant information in the `observed_variables` list. .. note:: The function will be called according to the sampling rate - specified. + specified. If unspecified, the default sampling rate is set to None, meaning that the + controller function will be called at every solver step of the simulation. sampling_rate : float The sampling rate of the controller function in Hertz (Hz). This means that the controller function will be called every diff --git a/rocketpy/simulation/flight.py b/rocketpy/simulation/flight.py index 2293d9706..a884d3fe4 100644 --- a/rocketpy/simulation/flight.py +++ b/rocketpy/simulation/flight.py @@ -777,7 +777,14 @@ def __simulate(self, verbose): self.y_sol = phase.solver.y if verbose: print(f"Current Simulation Time: {self.t:3.4f} s", end="\r") - + for controller in self._continuous_controllers: + controller( + self.t, + self.y_sol, + [step[1:] for step in self.solution[:-1]], + self.sensors, + self.env, + ) if self.__check_simulation_events(phase, phase_index, node_index): break # Stop if simulation termination event occurred @@ -1576,6 +1583,9 @@ def __init_equations_of_motion(self): def __init_controllers(self): """Initialize controllers and sensors""" self._controllers = self.rocket._controllers[:] + self._continuous_controllers = [ + c for c in self._controllers if c.sampling_rate is None + ] self.sensors = self.rocket.sensors.get_components() # reset controllable object to initial state (only airbrakes for now) @@ -4488,6 +4498,9 @@ def add_parachutes(self, parachutes, t_init, t_end): def add_controllers(self, controllers, t_init, t_end): for controller in controllers: + # Skip node creation for continuous controllers + if controller.sampling_rate is None: + continue # Calculate start of sampling time nodes controller_time_step = 1 / controller.sampling_rate controller_node_list = [