# How to Add a New Control Algorithm

The control algorithm in Apollo consists of one or more controllers that can be easily changed or replaced with different algorithms. Each controller outputs one or more control commands to `CANbus`. The default control algorithm in Apollo contains a lateral controller (LatController) and a longitudinal controller (LonController). They are responsible for the vehicle control in the lateral and longitudinal directions respectively.

The new control algorithm does not have to follow the default pattern, e.g., one lateral controller + one longitudinal controller. It could be a single controller or a combination of any number of controllers.

Complete the following task sequence to add a new control algorithm:

1. Create a controller
2. Add the new controller configuration into the `control_config` file
3. Register the new controller

The steps are elaborated below for better understanding:

## Create a Controller

All controllers must inherit the base class `Controller`, which defines a set of interfaces. Here is an example of a controller implementation:

```c++
namespace apollo {
namespace control {

class NewController : public Controller {
 public:
  NewController();
  virtual ~NewController();
  Status Init(const ControlConf* control_conf) override;
  Status ComputeControlCommand(
      const localization::LocalizationEstimate* localization,
      const canbus::Chassis* chassis, const planning::ADCTrajectory* trajectory,
      ControlCommand* cmd) override;
  Status Reset() override;
  void Stop() override;
  std::string Name() const override;
};
}  // namespace control
}  // namespace apollo
```



## Add a New Controller Configuration to the control_config File

To add the new controller configuration complete the following steps:

1. Define a `proto` for the new controller configurations and parameters based on the algorithm requirements. A example `proto` definition of `LatController` can be found at:  `modules/control/proto/lat_controller_conf.proto`
2. After defining the new controller `proto`, e.g., `new_controller_conf.proto`, type the following:

    ```protobuf
    syntax = "proto2";

    package apollo.control;

    message NewControllerConf {
        double parameter1 = 1;
        int32 parameter2 = 2;
    }
    ```

3. Update `control_conf.proto` at  `modules/control/proto/control_conf.proto`:

    ```protobuf
    optional apollo.control.NewControllerConf new_controller_conf = 15;
    ```

4. Update `ControllerType` in this file:

    ```protobuf
    enum ControllerType {
        LAT_CONTROLLER = 0;
        LON_CONTROLLER = 1;
        NEW_CONTROLLER = 2;
      };
    ```

5. When the `protobuf` definition is complete, update the control configuration file accordingly at `modules/control/conf/control_conf.pb.txt`

```
Note: The above `control/conf` file is the default for Apollo.  Your project may use a different control configuration file.
```

## Register the New Controller

To activate a new controller in the Apollo system, register the new controller in `ControllerAgent`.  Go to:

> modules/control/controller/controller_agent.cc

Type your registration information in the shell. For example:

```c++
void ControllerAgent::RegisterControllers() {
  controller_factory_.Register(
      ControlConf::NEW_CONTROLLER,
      []() -> Controller * { return new NewController(); });
}
```

After this code update sequence is complete, you new controller should take effect in the Apollo system.
