Home        Store        Learn        Blog

How to control thrusters independently

Hello everyone,

I would like to know if there is some way to control thrusters of a heavy bluerov2 independently.
I read that it was not possible via mavlink in 2018. I am asking if today that’s changed.

If not, is there an other way to do it ?

Thank you for the answer(s)

Hi @Guillaume1, welcome to the forum :slight_smile:

QGroundControl provides a Motors Setup page which allows you to manually test individual motors. I searched the QGC github page for Motor Test and found this commit, which shows that src/Vehicle/Vehicle.cc uses the mavlink message MAV_CMD_DO_MOTOR_TEST to achieve that. Your ROV will need to be armed to use it (as with any thruster/motor message), and I believe you’ll need to be in Manual mode.

I’m not sure what your use-case is, so if you’re just after a testing scenario then the information above is likely sufficient. If you’re wanting to understand how the thruster directions are understood by ArduSub:

  • the BlueROV2 Heavy frame configuration is here
  • the add_motor_raw_6dof function signature is here
  • info on making/adding a custom frame configuration to ArduSub is here (you could conceivably make a custom configuration which moves up to 6 thrusters individually with your normal joystick movements, assuming you’re happy to operate only in manual mode)

If you’re wanting to keep your frame the same but sometimes control individual thrusters then if you particularly want you could create an inverse-mapping of the frame configuration which would allow you to set motion based on individual motor control. That kind of control is likely much better off inside ArduSub though, since it can operate at a much faster rate and doesn’t have communication overhead. You could possibly add a custom control mode that basically does manual mode but with an inverse mapping in front, or ideally a lower level one that bypasses the existing mapping and just directly sets motor values.

1 Like

Hello Eliot,

Thank you for your fast answer !

In simulation I built some command laws taking into account the fact that we can control each thrusters independently. The goal is to stabilize the ROV in a certain pitch and roll using Python and ROS.
However, override function only allows to command directly the orientations and the forward/backward, upward/downward movements. That is why I want to know if there is a way to control each thrusters independently.

Thank you,


Hi Guillaume,

While this can definitely be a fun and interesting thing to experiment with, you’re likely to get much tighter control by using ArduSub for it due to the higher frequency measurement readings and reduced communication overhead. Are you aware of Stabilise mode? If not, have a look at the Pitch/Roll control section of the ArduSub docs :slight_smile:

Note that control in any particular direction or rotation axis is only possible with appropriately placed thrusters. The BlueROV2 Heavy can control both pitch and roll, whereas the standard frame configuration has no pitch control capabilities.

Hi Eliot,

I didn’t knew that but I would like to do it myself with my own control laws and the manual mode.
However, do you know how this stabilize mode is made ? Does it use override channel or does it control each thrusters independently ?


It’s part of ArduSub, which is the firmware that runs on the Pixhawk itself. RC_OVERRIDE is part of mavlink, which is the communication protocol for communicating with an ArduSub (or more general ArduPilot) autopilot device. The pixhawk firmware needs to be able to accept mavlink messages as input commands, and send them to update status to external devices like the ground control station (generally QGroundControl for ArduSub devices), but all the actual motor control is done by a PID controller which sends the the desired direction/rotations to the selected frame configuration mapping, which then sends the relevant commands to each motor.

For more of an understanding of how ArduSub works, here’s

Note that the ArduPilot codebase is quite large and interconnected, so it can definitely be difficult to understand all the different components of it and how they fit together. At some point I’m hoping to map out more clearly how ArduSub fits within the ArduPilot code, but I don’t expect that to be done until at least a few months from now, and quite possibly not until the end of the year.

Hi @Guillaume1,

While working on adding some other pymavlink documentation I just found the MAV_CMD_DO_SET_SERVO message, which enables you to set individual servo output values directly, bypassing the thruster directionality mapping altogether (a normal blueROV2’s thrusters are assigned to ‘servo’ outputs 1-6). There’s also the SERVO_OUTPUT_RAW message which allows setting individual values for all the servo outputs at once (you could specify port 0 and then set all the thruster values in one command). SERVO_OUTPUT_RAW is available directly through pymavlink using the master.mav.servo_output_raw_send function, whereas MAV_CMD_DO_SET_SERVO needs to be sent via a command_long_send message.

I don’t believe these messages are compatible with the RC_OVERRIDE messages though - you either control all the outputs directly, or you use the more standard approach where you specify the desired motion and allow ArduSub to determine the thruster outputs. If you try to use both at the same time my understanding is that the RC_OVERRIDE controls will override any servo output messages you send for the thrusters.

Hello Eliot,

Thanks for that answer. That is very interesting and I think it should work using pymavlink. However, I am using mavros and as far as I know, it is impossible to use pymavlink and mavros at the same time right ?

I would like to keep using mavros, hence, do you know if a MAV_CMD_DO_SET_SERVO command exists for mavros ?

Thank you !!

Best regards


I haven’t used mavros before, but this comment by @patrickelectric from a couple of years ago is likely helpful to you - it seems that mavros uses pymavlink.

Given the above, that seems very likely. More generally, mavros has to have some way of sending mavlink messages, and the mavlink protocol is set up such that if you’re able to send one then you can likely send all of them, as long as you can put the right pieces of information in the right place :slight_smile:

Hi Eliot,

Thanks a lot for your help !

1 Like

This has come up again elsewhere and it turns out those messages don’t do what I thought they did at the time.

  • MAV_CMD_DO_SET_SERVO does allow setting servo values directly, but only for servo output ports that aren’t assigned as motors
  • SERVO_OUTPUT_RAW is used to communicate the current output values (e.g. from the flight controller to the ground control station), not set/command them

There has apparently been an open GitHub issue for multiple years for making this functionality possible in a convenient way, but it unfortunately hasn’t yet been enabled/made possible, and will likely require changes to the mavlink protocol.

As a summary of the ‘hacky’ options I can think of:

  • Persistent: Vehicles with <= 6 thrusters can make an ArduSub build with a custom frame that sets a single unique factor of 1.0 for each thruster, at which point it can then be controlled using RC_CHANNELS_OVERRIDE messages, where the RC Input channels 1-6 would correspond to individual thruster activations (this should only be used with MANUAL flight mode - stabilisation modes will have a really bad time)
  • Temporary or Persistent: backup the servo outputs, then change them to correspond to RCIN_ instead of Motor_ → because they’re not recognised as motors, they can then be controlled directly using RC_CHANNELS_OVERRIDE or DO_SET_SERVO depending on setup. NOTE: not registering as motors also means arming isn’t required, and failsafes don’t work, so be very careful if doing this! I’ve implemented this approach as part of a larger example program here.
    Temporary if backed up values restored once done (as in my example), but persistent if vehicle is shut down before restoring occurs (in which case parameters need to be restored manually, or do a full reset to defaults).
  • Temporary: Use MAV_CMD_DO_MOTOR_TEST (least effect on other flight modes - not sure if can control multiple thrusters at once)