PX4 for control research purposes: direct motor control

Hi there,

I’ve written a little bit of explanation about the reason of my development and the different alternatives I’ve considered. If you want to go directly to the point, you can read the “Development” section.


I’m researching with quadcopters and I’ve chosen to use PX4 as the firmware I want to use for testing the algorithms I’m working on. They are mainly in the field of Model Predictive Control (MPC). My purpose is to use them as low-level controllers and I don’t want to use the typical cascade of PID controllers of PX4 (just want to keep it there as a backup for possible malfunctioning of the MPC controllers).

The thing is that the output of the MPC controllers is the thrust of each motor in the multicopter, which can be translated to PWM if a proper characterization of the Motor+Propeller is done (it is in the to-do list and, by now I’ll work with SITL). That is why I need to directly write to PWM motors.


To write directly to PWM control I though about several approaches (also thanks to the discussion in the Slack channel with the PX4 community members):

  1. Custom mixer + Offboard mode writing to the actuator_control topic: I would rely on MAVLink and the controller running in a companion computer. Since I need high rates (ideally 400Hz because of the ESC rates) I’ve discarded this option. Besides, the fact of having to write mixers seems more like a workaround rather than a proper development.
  2. Offboard mode + ROS2 writing to actuator_output: I would rely on FastRTPS bridge (which I like it better) and the algorithm running in a companion computer. It is missing if the communication between the companion and the Pixhawk 4 will be able to handle such rates. In case it doesn’t, we’ll have to wait till the FMUv6 comes out. What I don’t like about this approach is the use of offboard control. Initially, I’d like to run the controller in the companion computer, hence with the offboard mode would suffice. However, if the communication is not fast enough I’ll have to write some custom controller in running in the Pixhawk and this would discard the offboard option.
  3. Custom control mode + ROS2, this is the chosen one and is explained in the development section.


You can find the code of the development in this branch and I’ve been inspired by this PR.

The idea behind the development in the branch is the following:

  • Create a vehicle control mode that, when activated, the mixer_module writes to the actuator_output taking the value from a custom topic instead of mixing the values from actuator_controls.
  • The creation of this new topic which is read by the mixer (I call it actuator_direct_control.msg) would allow both create custom controllers inside the PX4, e.g. as modules or write to this topic using the FastRTPS.

The development in the branch works. However, I’m really interested in knowing your opinion since some of the lines I’ve written I did it by copy-pasting without knowing if this is the proper way to handle this. Besides, I have other doubts:

  • Subscription to the new topic: In the mixer_module, I’ve used a SubscriptionCallbackWorkItem to get the values from this new topic. Is this the proper subscription object to use? What is the functionality difference between this and the Subscription object? I lack knowledge of the overall PX4 low-level architecture.
  • Disabling rate controller: when changing to the new flight mode, I firstly disabled all the controllers in the Commander.cpp file, including the rate controller. When doing this the SITL simulation hangs and any input in the command line has no effect. By leaving this controller enabled, this behavior does not happen.

I think that this is all. Thank you for getting up to this line. I would really appreciate some feedback. :slight_smile:



Thanks @PepMS for the follow up on this module!

@dagar we would like to have this module compatible with motor testing from QGC. Any suggestions on that?

@PepMS You might have done this already, but good idea to cross link to the PX4 Slack #control channel

@hamishwillee yep, already did so. Thanks anyway!

Hi, the link of your code is broken. Could you please provide details in this. I am looking for solutions.

I am under the impression that publishing to actuator_output won’t work for all purposes anyway. It works for SITL simulation or UAV_CAN. But for PWM or DSHOT, the mixer directly uses the interface updateOutputs() to set the motor values. actuator_output is just published by the mixer for information in this case.