Mixer customization and override


I would like to check if there is any interest in using the passthrough mixer to override the regular mixer behaviour and implement custom mixers.
This is motivated by:

  • research purposes: test new mixer concepts different from the multirotor mixer already implemented;
  • educational purposes, i.e., how does the mixer work under the hood?

As an example, in our research lab we have developed a tilt-arm quadrotor, which in addition to the four motors has four servos to let the arms tilt independently from each other (thus we have 4+4 control variables):

The control architecture we developed includes a nonlinear mixer which computes the eight control variables (four motors PWM and four servo angles) based on the required forces and moments.
Since the PX4 mixing architecture only allows for a linear mixer (with offsets) to be implemented, we employed a passthrough mixer so as to be able to directly pilot the actuators, thus bypassing the multirotor mixing mechanism.
The actual nonlinear mixer, together with the controller, was implemented in a module upstream the passthrough mixer.

This solution works, however it breaks the interface established at the level of control group:
the idea of control group is to publish normalized forces and moments (to the actuator_controls_X topic where X is usually 0) which are then fed to the mixer.
But when using a passthrough mixer, one has to publish actuator demands on the same topic. The result is that the mixing system might misinterpret the request coming from the higher level (e.g., in control group #0 the fourth input is interpreted as the throttle, but if using a passthrough mixer this is actually the demand to motor#4).
To see what I mean, have a look at this piece of code in the px4iofirmware module:

Possible solutions:

  • introduce some structure in the architecture: define a new custom mixer class at the same level of the multirotor mixer. this has the advantage of not disrupting the interface at the mixer input, and it avoids using the passthrough mixer; however it requires handling separately controller and mixer.
  • if one wants to keep the architecture as unstructured as possible (i.e. keep controller and custom mixer in the same module, and use a passthrough mixer - this makes sense in a research framework), one idea could be to add a new control group (say, associated with topic actuator_controls_X) explicitly dedicated to the usage of the passthrough mixer (i.e. the actuator demands are published on actuator_controls_X) while still publishing the required forces/moments on actuator_controls_0, though this information would not be used for control, rather for monitoring and logging purposes. This would preserve the role of actuator_controls_0 as the channel where the information on forces/moments runs.

I had some discussion about this with @MaEtUgR at the dev summit, and I think @tumbili and @bresch might be interested as well.

Related work:

In this PR, direct motor control is implemented by sending the individual actuator control actions through mavros, bypassing the mixer. Direct motor control is sought as a desirable feature. However, the bottleneck is the serial communication bandwidth. This can be avoided if the actuator commands come e.g. from a controller running on a module onboard the FCU.

Again, some comments on direct access to actuators from companion:

In these works, a common problem is which mixer to use for non-conventional UAV configurations.

In this work, a “physical” mixer which takes forces and moments is developed. the usage of passthrough mixer is envisaged.

Apologies for the long post, hope that some interesting discussion can take place.



Yes, I am facing a similar issue right now with the NaNs being expected to passthrough the mixer to indicate motors should be disarmed.

I feel it would make the system significantly more flexible to remove that forced assignment of controls index 3 to NAN. If the PX4IO firmware has access to the armed/disarmed state can we move that to the pwm_limit functionally. Currently it reduces the orthogonality of the system - we can’t change the actuator_controls indices because it also require PX4IO firmware changes.

I see the reasoning is to force the motors to a safe state (which should propagate from the throttle = NAN) while leaving servo channels free to move.

Maybe a PWM_MAIN_MOTOR_MASK parameter, set as 11110000 to have the first 4 MAIN channels treated as motors?

What do you think is a better way to to let PX4IO know the difference between motor and servo channels?

The current system also causes problems if PX4 moves to a 6DOF mixer and control strategy. The vertical thrust command is negative (positive down with the aircraft axes), but should be able to ask for a positive or negative thrust in Z.

There are hidden dependencies occurring where that controls[3] index is being forced positive, or set to NAN on the PX4IO. In addition land_detector checks the raw value of that index for landing without taking the absolute value.

@simopanzer Thanks for your post. Interesting work you guys have done. I am currently trying to understand the mixing architecture used in the px4. I also want to implement a custom mixer for a similar drone as yours. But i’m a bit stuck at the moment.

I think it’s on topic to mention recent changes taking a step towards making the mixer more modular: https://github.com/PX4/Firmware/pull/12790
We need support for dynamic mixers but to get there certain historic patterns have to be refactored.

@simonpanzer Can you give me the procedure which you have followed in order to achieve 4+4 motors tiltrotor quadcopter?
I have mad a custom airframe and implemented it in SITL but wasn’t able to implement a custom mixer file?

@Jarvis2991 I defined a custom module implementing my own controller and mixing system. The outputs of such mixer are the control actions for the 4 motors and 4 servos. I publish them respectively on the uorb topics actuator_controls_0 and actuator_controls_1.

Then, I defined a .main.mix file as described here:
with one Simple mixer element for each of the 4+4 actuators.
That is, the mixer basically passes through the four motor control actions to MAIN outputs 1-4, and the four servo control actions to MAIN outputs 5-8.

Thanks, have understood the second part but in first part, can you please elaborate it ?
I need to make a new custom module in which folder and where to change the file name and what are the actuator controls need to be subscribed ?
Mixers will be changed at every point the servo angles are changed, so how to take servo angles?

@simopanzer i understand that what you have done is an “easy” way to implement a custom mixer that it is necessary for many custom Vtol design, but that is limited by the mavlink band width.
There is any way to do it inside the autopilot?
Or if it is too difficult, to have a companion mcu running the mixer code?

@Pbecchi actually our custom mixer is running on the autopilot. In this way the NuttX real time operating system running onboard guarantees execution of the code at the desired rate. Further, running the code on the autopilot avoids the intrinsic lag associated with the communication channel, which unavoidably leads to degradation of performance of the feedback control loop.

@simopanzer Thanks Simone, this is exactely what i would like to do for my Vtol.
I looked to the code but it is not an easy navigation!
I will appreciate any advise or guidance on how to approach this SW modification.
There is any documentation available?

Hello Simone, nice work you guys are doing!

Im working on a Quad Tiltrotor as well and thinking about implementing a custom mixer by my own. I understand it would split control and mixer logic, but ain’t it somehow desirable? Just trying to figure out the possible outcomes, glad if you could help me with that!


Hi! @simopanzer, thanks for your excellent PR, and this is what I am doing.
We design a tilt quadrotor just like yours, and the theoretical derivation is completed. we now want to experimental verification based on the PX4 and Pixhawk.
The question is : Should I modify it in the original quad-rotor mixer file or create a new mixer ?
also, should I create a new UAV model file myself ?
@lfdiniz, we can have a discuss I think.

Hi @Andrew5c i’m working on something similar though for a tricopter. We can discuss if you like and help each other. Thank you

I am trying to achieve a similar thing here. I would like to send actuator commands for a quadrotor from a companion computer via RTPS (I think the bandwidth should then be high enough right?).
I’ve managed to achieve this by directly publishing to actuator_outputs, but this seems like a very stupid solution (in simulation if the commands are not sent at 250Hz, the simulator would adjust its time to match the publishing frequency).
Would a better way be to publish to actuator_controls_X and write a custom mixer to translate this to rotor commands? Or would there be another better solution?
Preferably I would also like to be able to switch from the offboard control described above back to autonomous hover control…

Do you find a way in this. I am struggling.