ROV with 9 or more Motors

Good morning,
We are building a 12‑motor ROV, and I noticed that in the configuration, under Vehicle Setup, I can only see 8 sliders for motor testing. How can I view all 12 motors?
Is there a way to display the additional N motors in the test area?

If we were to add even more thrusters (12 and above), what would be the correct procedure?

To add 12 motors, I created a new frame configuration in AP_Motors6DOF.hpp and defined the corresponding matrix in AP_Motors6DOF.cpp.
Regarding this, is there any documentation explaining how to calculate the motor values for each column? I haven’t found anything about this in the official documentation

Hi @Ruben_malacarne -

I don’t think ArduSub supports frames with more than 8 motors, even with a custom frame definition! Are any of your motors redundant, oriented in the same direction perhaps in pairs? They could be used in an 8 thruster configuration in this way, just connecting more than one to the same control signal… otherwise more in-depth modification of ArduSub may be required…

I believe ArduSub works with up to the 12 motors supported by its output channel (SERVOn_FUNCTION) parameters.

BlueOS is currently limited (for no intentional reason) to only show the first 8. We should be able to fix that quite soon, but it will require an update to be able to test the full set of available ones - sorry!

For more than 12 motors you would need to add parameter options for them in ArduSub, not just a custom frame design. For what it’s worth, we’re currently working our way towards supporting Lua-script-based motor configurations, in which case I believe you could add arbitrary numbers of motors, and not need to build custom firmware to do so.

I’m working on some, but it unfortunately isn’t completed yet.

As a very brief summary, the thruster contribution factors in ArduSub are answering the question “to achieve X commanded motion, how much should each thruster be engaged?”.

Thrust factors can be calculated for arbitrary motor orientations by

  1. calculating the matrix of control authorities (i.e. the maximal force/torque each motor can exert on the vehicle’s centre of mass, decomposed into the standard motion axes (roll, pitch, yaw, forward, lateral, throttle)), then
  2. inverting that matrix (or taking a pseudo-inverse in the case where you’re not using 6 thrusters) to get desired command proportions, then
  3. normalising (to ±1) either the whole matrix (to get balanced responses), or the set of contributions to each axis (to get maximal axis control authority, potentially at the cost of some cross-axis coupling when multiple axes are activated at once)

Note that with a sufficiently symmetric vehicle design the whole thruster factors matrix can be determined intuitively by hand, without specific calculations required. This thread may be of interest.

If you can share more about your motor placements and orientations I can help more, and/or I can try to give a more concrete worked example, but that will have to be later this week / next week some time.

Thank you. At the moment we are working to correctly set up the matrix, and with a frame similar to the BlueROV Heavy — but with four additional parallel thrusters — we obtain a matrix similar to the one shown in the image.

However, when we load it onto the ROV, it doesn’t seem to be configured correctly.Right now we’ve developed our own script which, given the position of the motors, computes the matrix by taking into account:Where the motor is located: its distance from the drone’s center of mass (the balance point), also known as the lever arm.Where it is pointing: whether it pushes upward, forward, sideways, or diagonally.How the propeller rotates: whether it spins clockwise (CW) or counter‑clockwise (CCW), since the rotation generates a torque on the vehicle.

We are wondering whether we are missing something that needs to be configured besides the CPP and header files.

I share an image of the configuration:

The order of trhusters are not the same of the Bluerov

What do you think?

Is wrong ?

(The ROV’s center of mass is slightly shifted upward.)

Parallel to what / which vehicle axes?

What do you mean by this? The firmware fails to load? The motors don’t spin? The motion between different axes is unexpectedly coupled?

At a quick glance the thrust factors look to at least be linearly independent, and have the kind of symmetry that could make for a feasible setup.

That said, it’s hard to say much about their correctness without also knowing either the thruster control authorities or their positions and orientations (to figure out some reasonable control authorities).

There are 8 horizontal thrusters (up and down) and 4 vertical thrusters, with a tilt angle of 40 degrees for the horizontal ones and 20 degrees for the vertical ones. I’m attaching an image to better illustrate the configuration.What I’m noticing is that some of these thrusters do not rotate in the correct direction as defined by the matrix. Besides configuring the matrix in the .cpp and header files of ap_motors6dof, is there anything else that needs to be set?Another question: if I’m moving along the X axis, should the vehicle correctly move forward?

Here you can find and image that describe the ROV

The front of the horizontal thrusters is facing outward from the ROV — forward (fore) for the front thrusters and aft for the rear thrusters.

If I’m understanding correctly, you’re saying there are two layers of horizontal thrusters, with 4 above the central plane and another 4 below the central plane? And from your diagram it looks like the ones from the higher level are directly over the top of the ones from the lower level (not offset / rotated around)?

Which axes are those 'tilt angle’s relative to?

The horizontal thrusters have the following orientation:

The fore thrusters have their front facing forward, but angled at 40 degrees.

The aft thrusters have their front facing the opposite direction, also angled at 40 degrees.

Currently, for operation, we are using the following configuration:

(Motor 3 has an inversion, so its sign is inverted)

However, if I wanted to make a more precise configuration, how should I calculate the thruster angles so that the auto-controls (autopilot) perform well respect to the Center of Mass? On that note, for optimal auto-control in depth hold or stabilize mode, is the Bar30 depth sensor sufficient?

I would recommend keeping the factors conceptually consistent so they’re easier to reason about and maintain - there are parameters available for inverting the output channel signal if need be (e.g. MOT_3_DIRECTION).

Not really sure what you’re asking here - different thruster angles just change which motion axes are prioritised. Whether your vehicle controls “perform well” depends on how much control you want over each axis (e.g. if you care a lot about forwards but not much about lateral control then you can orient your horizontal thrusters to point mostly forward).

Generally the thruster placements and orientations are determined with an assumed center of mass of the vehicle, after which the vehicle mass can be trimmed with buoyancy and ballast elements if it needs to be closer to that point. It would also be possible to calculate new thruster contribution factors for an arbitrary hypothetical center of mass (with corresponding sensor position offset parameter values to compensate), but if that results in heavily asymmetric factors then the vehicle may be unintuitive to control, especially due to inconsistent drag.

“Optimal” means the best within some context, and you haven’t specified what your performance requirements are (so there’s minimal context to evaluate in). The transients and variance of a Bar30’s measurements should be sufficiently low for most ROV use-cases, but the absolute accuracy may not be ideal (and can drift during extended submersion). Whether that’s a problem for your vehicle depends on what you’re trying to achieve.

Sorry, I may have caused some confusion. What I meant was: is there a way to calculate the control allocation matrix based on the thruster positions, knowing each thruster’s angle/orientation, its position, and the position of the center of mass?
The mathematics behind this is not very clear to me. Would it be possible to provide an example of how this calculation is done? I can also attach an image of a sample thruster configuration that we could use as a starting point.

So, To simplify the example, suppose the center of mass is at (0,0,0), and the thruster is located at the point shown in the image, with an inclination of 45∘, as shown above. How would I calculate the values of the six columns required by ArduPilot for that thruster?

Yep - that was what I was describing in the numbered steps in my initial response.

some extra context

At an abstract level, the autopilot exists to solve the problem: given an input motion command and the intrinsic capabilities of the vehicle frame, how much should each output channel be engaged to achieve that motion as closely as possible?

The first portion of that is handled by control algorithms with sensor feedback, which factor in both user commands and automated failsafe behaviour while compensating for things like the vehicle’s dynamics and communication latency, and maintaining safe usage of the components.

From there we end up with a set of instantaneously desired proportions of the vehicle’s motion capacity, which then gets passed to the hardware abstraction layer to split into commands for each physical actuator to engage with the real world.

The control system naively assumes each motion axis is controlled both linearly and independently, so there are limitations when that is not the case. As a few examples, we have ongoing work to help compensate for the power-scaling and forward/backward asymmetry of thruster-based outputs, but there is no compensation for the clipping that occurs when the autopilot requests more than 100% of an output’s capacity (e.g. if it contributes to two motion axes that are both requested at 100%, or if the user requests a speed that’s higher than the actuators can achieve).

The resulting forces (\vec{r}) that get applied to the vehicle can be expressed as a calculation, where a vector of desired motion components (\vec{d}) gets broken down through a set of engagement factors (\mathbf{F}) (which specify how much each output should be engaged to achieve that motion), which can then be recombined into forces by considering the capacity each actuator has for moving the vehicle (\mathbf{C}):

\vec{d} \mathbf{F} \mathbf{C} = \vec{r}

The control algorithm provides \vec{d}, so to try to achieve \vec{r} = \vec{d} there are two things we need to determine:

  1. How much force/torque can each motor contribute to each motion axis? (\mathbf{C})
    • This is based on the properties of the thruster itself, combined with its position and orientation in the vehicle (relative to its centre of mass), and isn’t something the vehicle directly knows about
    • In robotics this is referred to as the “control authorities” of the actuators
    • It can be calculated for each thruster independently, by decomposing the thrust vector into the translational motion axis forces, and then multiplying those by the perpendicular distances from the centre of mass to determine the rotational torques
  2. How much should each thruster be engaged to achieve a commanded motion? (\mathbf{F})
    • This is the table that goes into the code
    • \vec{r} = \vec{d} requires that \mathbf{F}\mathbf{C} = \mathbf{I}, so \mathbf{F} = \mathbf{C}^{-1} (i.e. you can calculate \mathbf{F} by inverting the matrix of control authorities, but that requires knowing the whole matrix first, so it cannot be done one thruster at a time)
      • In practice, \mathbf{F} also gets scaled, to help bound the output values
    • For highly symmetric configurations it is possible to determine \mathbf{F} by inspection, mostly just using the signs of the control authorities

Sign Convention

To start with, the positive directions are forward, right, and upwards, and the roll and pitch rotation angles follow a right-handed finger curl (with the thumb along the axis), while positive yaw is left-handed (i.e. clockwise, from above):

Not sure why that’s the case, but it’s how the factors are currently implemented :man_shrugging:

Actuator Control Authorities

Translation Forces

The translational components can be determined with trigonometry, though it may be easier to think of them in terms of proportions towards each axis that then get their magnitude normalised.

For a thruster i with maximum thrust T its translational components can be determined as

c_{x(i)} = \frac{T_i \cdot X_{pi}}{\sqrt{X_{pi}^2 + Y_{pi}^2 + Z_{pi}^2}}

where X_{pi} is the thrust proportion towards the X axis (following your diagram’s convention, with Z as the upwards (away from gravity) axis). In the case of your example thruster (which we can assign as i=1), there are equal amounts of thrust both forward and right, and no thrust upward, which we can express as

c_{x(1)} = \frac{T_1 \cdot 1}{\sqrt{1^2 + 1^2 + 0^2}} = \frac{T_1}{\sqrt{2}} = c_{y(1)}, \qquad c_{z(1)} = 0

Alternatively it is possible to calculate that using the rotation angles away from the axis (e.g. c_{x(1)} = T_1 \cos{(45)}\cos{(0)}).

Either approach can get complicated when the angles aren’t nicely aligned with the axis planes, so just use whatever is easier to define. If you only have one thruster type (which is usually the case) then you can also substitute T_i = 1 for simplicity.

Rotation Torques

Torque is determined by the perpendicular force being applied at a distance. We’ve already broken down the components, and know where the thruster is, so we can just apply

\begin{align} c_{r(i)} &= c_{x(i)}\cdot z_i - c_{z(i)}\cdot x_i \\ c_{p(i)} &= c_{y(i)} \cdot z_i + c_{z(i)}\cdot y_i \\ c_{y(i)} &= c_{x(i)}\cdot y_i - c_{y(i)}\cdot x_i \end{align}

Your example thruster is pointing directly through (out from) the centre of mass, so it exerts a purely translational force, and all three rotational control authorities are 0.

Note: If you want you can include a rotational component for the thruster’s propeller spin direction, but that is generally very small, often designed to be cancelled out with an opposing propeller acting along a similar axis, and requires extra work to calculate the distribution.

Actuator Engagement Factors

As mentioned earlier, these are determined by calculating the matrix inverse of the control authorities (or pseudo-inverse, when there aren’t exactly 6 thrusters). There are techniques for doing that by hand, but it’s generally not very fun more than once, and there are plenty of tools that can do it for you (e.g. Wolfram Alpha, or numpy.linalg.pinv if you’re familiar with Python).

Be aware that the autopilot is incapable of commanding outputs above magnitude 1 (i.e. 100%), so it’s common to normalise the factors for each motion axis, or normalise the matrix as a whole (prioritising the axes the vehicle has more authority over, at the cost of some performance when only weaker authority motions are commanded).

Feel free to follow up if this part is still confusing - your current example of only one thruster is just poorly suited to expressing this.

Evaluation

Note that multiplying the actuator control authorities matrix with the engagement factors matrix can calculate the control authorities of the vehicle as a whole (along the leading diagonal), and indicate any cross-axis coupling in the off-diagonal terms.