Building Custom Controllers¶
Pylot implements controllers using an object-oriented approach. The aircraft has a controller object which is queries at each time step to get the current control state. The aircraft passes its current state and controls to the controller, and the controller determines the new control state. Pylot comes with four built in controller classes (NoController, JoystickController, KeyboardController, and TimeSequenceController) which are all derived from the class BaseController.
A user can derive their own custom controller from BaseController (found in pylot/controllers.py). For Pylot to recognize this controller, it must be named UserDefinedController and placed in the current working directory in a file named user_defined_controller.py. BaseController contains one abstract method (get_control) that must be defined in the derived class. This method takes the time index, the current aircraft state vector, and the previous control state as arguments and returns the new control state as a dictionary. To ensure proper Pylot behavior, non-abstract methods should not be redefined.
The script user_defined_controller.py should contain at least the following (we recommend simply pasting this into your IDE):
from pylot.controllers import BaseController
class UserDefinedController(BaseController):
def __init__(self, control_dict, quit_flag, view_flag, pause_flag, data_flag, enable_interface):
"""Initializer.
Parameters
----------
control_dict: dict
Dictionary of control parameters declared in the airplane input JSON.
All other parameters are simply necessary for Pylot and should not be altered.
"""
super().__init__(quit_flag, view_flag, pause_flag, data_flag, enable_interface)
# Whatever setup you'd like to do for the controller should happen here
return
def get_control(self, t, state_vec, prev_controls):
"""Returns the controls based on the inputted state and keyboard/joystick inputs.
Parameters
----------
t : float
Time index.
state_vec : list
State vector of the entity being controlled.
prev_controls : dict
Previous control values.
Returns
-------
controls : dict
Dictionary of controls where the keys are the names of the controls and the values
are the control settings. Not that angular controls are specified in degrees. Non-
angular controls (such as throttle) vary from 0 to 1.
"""
# This is where you determine the control settings at each timestep
controls = {}
return controls
__init__ is run once when the controller is instantiated. All setup should happen in there. get_control is called at each integration step to determine the control settings for the aircraft.
If you’d like to read in inputs from a joystick or the keyboard, check out the source code for JoystickContoller and KeyboardController in pylot/controllers.py. That should give you a place to start. Happy experimenting!