GSOC 2022 - Custom Controller Implementation Using MathWorks Simulink Code Generation

Hello everybody, I am Emre Saldiran. I am a first-year Ph.D. student at Cranfield University. This summer, I will be working on developing a systematic and sustainable way to implement a custom controller into ArduPilot. This project is mentored by the @iampete and @tridge. In this blog, I will summarize the project’s aim/objective and deliverables to further discuss it with the community.

There have been multiple interests specifically from the research communities asking about how to implement and test their own controller into ArduPilot’s codebase. Even simple “custom control” search in the forum shows multiple results. This project aims to allow the implementation of a custom controller into ArduPilot either via hand coding or via Matlab/Simulink code generation. Although this project will mostly benefit the research community, the attractions ArduPilot would receive from the them will bring new and novel ideas into the codebase more quickly.

The attempt for this problem so far does not offer a sustainable and generic way to do this. For example; My own position and attitude controller implementation for Copter in INDI: Incremental Nonlinear Dynamic Inversion #20511 hack around the attitude and position library to allow in flight controller switching. The attempt in ADRC: Active Disturbance Rejection Control #20243 is although neater, it assumes the output signal is generated in PID controller, which is not always the case. Due to my familiarity with implementing my own controller in ArduCopter, this project will focus on allowing custom attitude controllers in ArduCopter as a starter.

This project consists of two parts. In the first part, a systematic and easy way to implement a custom controller by hand-coding will be developed, and the second part will focus on implementing Matlab/Simulink based controller via automatic code generated.

Regardless of its method, a custom controller implementation should have the following features to allow it to be used in all flight modes and flight regimes, and switch between the original controller smoothly.

  1. In-flight controller switching: This functionality will allow switching between the original and custom controller using RC switch mid-flight.
  2. Isolated from the original controller: The custom controller should be separated from the current controller library to reduce maintenance load and prevent user from accidently changing something in the core controller library. This separation would also make merging new controller easier.
  3. Reset integrator terms: The controller should reset integrator-like terms depending on the motor spool state to allow arming and taking off with a custom controller. Ex: the controller specifically designed to test the vehicle’s ground effect response.
  4. Reset any filter: All of the filters should be reset when switching between controllers to provide a smooth transition.
  5. Active axis bitmask: Bitmask parameter to choose which attitude axis users want their controller to be active. This would allow testing each axis one at a time.
  6. Easy access to already existing methods in the attitude controller library.

Most of these requirements come from the researcher’s point of view. In addition to the above, the custom controller support should,

  1. have as minimum flash cost as possible
  2. have a bare minimum example to allow CI testing
  3. be selectable with a compile-time flag to prevent it from being used accidentally even in master.
  4. have architecture to allow expanding the list of supported custom libraries.

ArduCopter attitude controller library is a huge and math-heavy piece of code, but almost all of these are related to the input shaping or input manipulation methods. After all these input shaping methods, finally, the attitude controller is run. We do not need to replicate each functionality inside the original attitude controller library to have the custom controller support because all of the input shaping/construction functions calls “attitude_controller_run_quat” at the end, which is simply speaking, P controller that outputs the target angular rate that will be used in angular rate controller.

I have two approaches to tackle these requirements. My initial attempt for the first approach is in PR. This approach meets most of these requirements.

I would be interested to know what the community and any member of the development team think about this project. I would appreciate anyone suggestions in advance.

UPDATE 2022-07-28: The second approach PR can be found here Custom Controller Support 2nd Version by esaldiran · Pull Request #21216 · ArduPilot/ardupilot · GitHub.

I also added a README file that explains how to use the custom controller, how to add your own custom controller, and how the custom controller interacts with the main controller. The readme file is accessible at this link ardupilot/libraries/AC_CustomControl at custom-cont-v3 · esaldiran/ardupilot · GitHub.


Regarding “custom controllers”, it would be advisable to show examples how one can include external libraries in the Ardupilot code. From simple case like header-only Eigen to sth more complicated like link a QP solver (e.g. qpOASES or OSQP). It doesn’t have to be a working controller, a toy example is enough. I feel like most people drop the idea to implement custom controller, because there’re no working examples of how to use external libraries with Ardupilot WAF build system, which is rather obscure one.

Good point regarding external library support. I imagined most of the custom controllers would not be optimization-based method like MPC, given the microcontroller computation power. Although it is not in the scope of this project, it would be good to have this functionality. I heard firsthand how some people want to include Eigen library and struggle to do so.

Super awesome project!

Hello, I am very happy that this feature will be included in ArduPilot. For our research on flight controllers, we have created an interface for Copter and Plane in an ArduPilot fork in the past. This already fulfills some of the goals described above, but not all. All further info can be found via this thread:

Maybe parts of our code can be reused. Please feel free to contact me if you have any questions.

1 Like

Hi Yannic, I checked your repo and it looks really interesting. With this custom controller support, you can create a new backend and put generated code inside without creating a new flight mode. I might have to contact you for code generation stuff.

I wrote an update post in GSOC 2022 - Custom Controller Implementation Update - Adding New Controller By Hand Coding that explains how to implement your own custom controller and how to use it.

The custom controller PR got merged. It turned out to be a little different than the blog post. Feel free to give it a try Custom Controller Support 2nd Version by esaldiran · Pull Request #21216 · ArduPilot/ardupilot · GitHub