Controller Class

The controller class is central the this library as it has connections to many other components. To ensure compatibility with all components, controllers should always inherit from the abstract_controller class. The abstract controller class can optionally do logging, state filtering, friction compensation and gravity compensation.

Class Methods

Every specific controller, inheriting from the abstract controller class has to implement a

controller.get_control_output_(self, x, t)

method, which should return an array-like object with shape=(2,) representing the torques to be sent to the motors. The get_control_output_ or more precisely the get_control_output (without underscore) of the abstract controller will be called by the simulator and the hardware control loop during hardware experiments. In addition to this function controllers can optionally have the methods

controller.set_parameters(self, ...)
controller.set_goal(self, goal)
controller.init_(self)
controller.reset_(self)
controller.save_(self, save_dir)
controller.get_forecast(self)
controller.get_init_trajectory(self)

set_parameter can be used to set controller specific parameters and set_goal can be used to set the goal and maybe compute internal controller properties which depend on the goal. The init_ method will be called before the execution and reset_ can be used to reset parameters inside the controller. save_ is used to store controller parameters to be able retrace the controller properties after execution. get_forecast can be implemented in predictive controllers to return the predicted trajectory and get_init_trajectory can return the initialy planned trajectory of the controller (e.g. the trajectory a controller is supposed to stabilize). If the latter two trajectory returning methods are implemented these trajectories can ba plotted in the animation funciton of the simulator.

Logging, Filtering and Compensation

The abstract controller class has methods implemented for logging, state filtering and friction/gravity compensation.

To use the state filtering one has to call set_filter_args method with the desired filter parameters. The filter is then initialized during the controller.init and incoming state measurements are filtered before being parsed to the get_control_output_ method. By default no filtering is used.

Friction compensation can be turned on by calling set_friction_compensation with the desired friction parameters. Gravity compensation is activated with set_gravity_compensation with a plant object as parameter. Note that gravity can only be fully compensated on the fully actuated double pendulum. Friction and gravity compensation torques are both added to the torque returned by the get_control_output_ method.

The controller internally logs the total controller torque in u_hist, the friciton compensation torque in u_fric_hist, the gravity compensation torque in u_grav_hist, the state history in x_hist and the filtered states in xfilt_hist and they can be accesses via the controller object.

Writing your own controller

If you want to write your own controller you may want to use the template below. The only method that is strictly necessary and has to be implemented is the get_control_output method. The other methods are optional.

from double_pendulum.controller.abstract_controller import AbstractController


class ControllerTemplate(AbstractController):
    """Controller Template"""

    def __init__(self):
        super().__init__()

    def set_parameters(self):
        """
        Set controller parameters. Optional.
        Can be overwritten by actual controller.
        """
        pass

    def set_goal(self, x):
        """
        Set the desired state for the controller. Optional.
        Can be overwritten by actual controller.

        Parameters
        ----------
        x : array_like, shape=(4,), dtype=float,
            state of the double pendulum,
            order=[angle1, angle2, velocity1, velocity2],
            units=[rad, rad, rad/s, rad/s]
        """
        self.goal = x

    def init_(self):
        """
        Initialize the controller. Optional.
        Can be overwritten by actual controller.
        Initialize function which will always be called before using the
        controller.
        """
        pass

    def reset_(self):
        """
        Reset the Controller. Optional
        Can be overwritten by actual controller.
        Function to reset parameters inside the controller.
        """
        pass

    def get_control_output_(self, x, t=None):
        """
        The function to compute the control input for the double pendulum's
        actuator(s).
        Supposed to be overwritten by actual controllers. The API of this
        method should not be changed. Unused inputs/outputs can be set to None.

        Parameters
        ----------
        x : array_like, shape=(4,), dtype=float,
            state of the double pendulum,
            order=[angle1, angle2, velocity1, velocity2],
            units=[rad, rad, rad/s, rad/s]
        t : float, optional
            time, unit=[s]
            (Default value=None)

        Returns
        -------
        array_like
            shape=(2,), dtype=float
            actuation input/motor torque,
            order=[u1, u2],
            units=[Nm]
        """
        u = [0.0, 0.0]
        return u

    def save_(self, save_dir):
        """
        Save controller parameters. Optional
        Can be overwritten by actual controller.

        Parameters
        ----------
        save_dir : string or path object
            directory where the parameters will be saved
        """
        pass

    def get_forecast(self):
        """
        Get a forecast trajectory as planned by the controller. Optional.
        Can be overwritten by actual controller.

        Returns
        -------
        list
            Time array
        list
            X array
        list
            U array
        """
        return [], [], []

    def get_init_trajectory(self):
        """
        Get an initial (reference) trajectory used by the controller. Optional.
        Can be overwritten by actual controller.

        Returns
        -------
        list
            Time array
        list
            X array
        list
            U array
        """
        return [], [], []