-
Notifications
You must be signed in to change notification settings - Fork 2.1k
MANUAL_CONTROL: Redefine the use of z (throttle) to be independent to vehicle's thrust direction
#1922
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Previously, the `z` component definition relied on having a knowledge of which direction the thrust would result in, depending on it's value. However this is a bad practice as the ManaulControl message itself should be agnostic to a vehicle type (either reverse-thrustable ones like Rover, or ones with only positive thrust like conventional quadcopters). With this new definition, the MANUAL_CONTROL message will not be vehicle-specific and truly represent the Joystick / RC Transmitter's throttle position
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most importantly remove:
Positive values are positive thrust, negative values are negative thrust.
That part causes ambiguity and confusion because what happens if the vehicle does not have any negative thrust? In practice, this message was designed and is broadly used to report joystick positions over MAVLink. But with this definition, it instead results in the MAVLink-enabled remotes needing to understand the thrust situation of the vehicle just to be able to report the throttle stick or slider position.
It's sad that the original easier to understand definition was abandoned in https://github.com/mavlink/mavlink/pull/64/files
but
https://github.com/mavlink/mavlink/pull/464/files
really started the confusion in my eyes.
I'd vote for a very clear definition like this:
https://github.com/PX4/PX4-Autopilot/blob/7977ba3217422b042a6848ef529d9ea61ba0b686/msg/ManualControlSetpoint.msg#L24-L27
but for this message, I think the ship has sailed and a new one would need to be added for backwards compatibility.
| <field type="int16_t" name="x" invalid="INT16_MAX">X-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to forward(1000)-backward(-1000) movement on a joystick and the pitch of a vehicle.</field> | ||
| <field type="int16_t" name="y" invalid="INT16_MAX">Y-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to left(-1000)-right(1000) movement on a joystick and the roll of a vehicle.</field> | ||
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to a separate slider movement with maximum being 1000 and minimum being -1000 on a joystick and the thrust of a vehicle. Positive values are positive thrust, negative values are negative thrust.</field> | ||
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to throttle high (1000) - throttle low (-1000) on a joystick. Centered throttle should result in value of 0 (center).</field> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to throttle high (1000) - throttle low (-1000) on a joystick. Centered throttle should result in value of 0 (center).</field> | |
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Joystick or slider fully down corresponds to -1000, fully up to 1000, the center position to 0.</field> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this. Before we were saying its another slider, now we're enforcing that the alignment of that slider is "up/down". I think the desired change is just to remove the emphasis on the positive/negative thrust. Something like.
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to throttle high (1000) - throttle low (-1000) on a joystick. Centered throttle should result in value of 0 (center).</field> | |
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally the axis is mapped to vehicle thrust. Vehicles that support only positive thrust map the range from maximum thrust (1000) to mininimum (-1000). Vehicles that support negative thrusts map the range from maximum positive thrust (1000) to maximum negative thrust (-1000), with 0 (centred) implying no thrust).</field> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before we were saying its another slider
Conceptually it should represent an analog input axis be it slider, stick axis or whatever else someone would like to map. In most cases, it will be a stick axis which might be worth mentioning but certainly not enforcing.
now we're enforcing that the alignment of that slider is "up/down"
My wording is not general enough. I do not want to enforce that. The axis just needs to have a minimum and maximum if that's up, down, sideways or diagonal is up to the user. Again in most cases, I'm pretty sure it's up and down.
Generally the axis is mapped to vehicle thrust.
That is exactly the part that is in my eyes only half the story. Manual up, forward, gas is the first thing that comes to mind but often it's mapped to steer vertical or even horizontal speed. I'd try to avoid mentioning an exact use because even though it's true in certain scenarios it can be very confusing in others.
Vehicles that support only positive thrust map the range from maximum thrust (1000) to mininimum (-1000). Vehicles that support negative thrusts map the range from maximum positive thrust (1000) to maximum negative thrust (-1000), with 0 (centred) implying no thrust).
Very good wording. Whatever the thrust, speed or other desired quantity range is, should be mapped to the full available input range -1000 to 1000.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whatever the thrust, speed or other desired quantity range is, should be mapped to the full available input range -1000 to 1000.
@MaEtUgR No, that's good wording ^^^ :-)
Perhaps we should make it that simple?
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to throttle high (1000) - throttle low (-1000) on a joystick. Centered throttle should result in value of 0 (center).</field> | |
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. The value may be mapped to thrust, speed, throttle, or any other property. The range of possible property values should be mapped across the full movement range of the axis.</field> |
Similar changes could be made to the other axes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coming back to this in 2025 after PX4/PX4-Autopilot#24576, which is a product of my suggested consistent use of the throttle/z range and the existing inconsistent use. I might slowly lean towards a completely new message defining the input in a specific consistent way because as much as I'd like to correct MANUAL_CONTROL I'm not sure how many use cases break if we clarify the definition and use it consistently 😬
If there's another easy way to ensure the transition is smooth, I'm eager to learn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MaEtUgR There's some appetite for improve messages here. The best way forward would be to create a PR that outlines the messages you'd like to see. I can then add to the dev call (I added, but only as a heads up, not a concrete proposal).
I'm not sure of the right split, but we've previously discussed splitting button press behavior from slider/axis control, basic axis + additional axis. Fixed axis + configurable axes. And so on. Open to suggestions that minimise bandwidth and allow for easy extension in future (or no need for extension in future).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how many use cases break if we clarify the definition and use it consistently
@MaEtUgR It looks like QGC is the only supplier, and both PX4 and ArduPilot map this "to the same effect". What this means is that we can really only clarify the definition to "what QGC does". How PX4/Ardupilot interprets that is the same, so we should capture that as well, at least as "in general". We should do that and nothing else here.
|
As the wording is now "Positive values are positive thrust, negative values are negative thrust.". That implies that on a vehicle with only positive thrust you have to have a deadzone from the low position of the axis range to the centre. I bet that no one actually does that. This is conceptually a breaking change from a MAVLink perspective but I think it makes sense, if we can get the wording right. I will take to the dev call this evening.
|
Oddly, I'm looking at doing the opposite in (non-Sub) ArduPilot (ArduPilot/ardupilot#22259) - actually taking action based on the buttons field in Turns out that MissionPlanner actually already does what you're suggesting here - makes mavlink calls rather than passing through the button bits (a small impediment to my little project). |
Sounds daft unless the functions you want don't have corresponding mavlink messages, or can't do so for some reason. I understand that in Canberra they call you "Mad Peter" :-) Currently
The send-a-mavlink-message approach seems much smarter and more flexible.
|
|
On Tue, 29 Nov 2022, Hamish Willee wrote:
The send-a-mavlink-message approach seems much smarter and more flexible.
* The GCS does not need to know anything about the flight stack than it already knows - what commands are supported. (and even those can be in many cases checked without side effects). It doesn't need to
know what parameters the flight stack uses to map button presses or what functions are called.
* The flight stack doesn't have to have special code paths to process instructions it is already processing through mavlink.
* The manual control message doesn't have to cope with the possiblity of joysticks with more buttons than we expose.
That's all true, and we did note the first two when we discussed.
In this case one of our partners wanted to have fence enable/disable on a
button. MissionPlanner didn't permit binding that to a button, and would
need patching and updating to support the functionality. Having the
function instantly available was what I was after - as soon as it was
available in ArduPilot it could be configured.
I would *like* MissionPlanner to use our DO_AUX_FUNC list (I was mistaken
in my initial assesment there; it has specialised code for each function
it offers). Addition of an arbitrary-number-combo-box interface into the
relevant configuration page might fix things.
Problem with that last is that now *every* GCS has to have this interface.
The list of valid functions will be different autopilot-to-autopilot....
and while ArduPilot has a convenient list of functions that can be
activated by MAVLink (I might actually generate a aux_func.xml at some
stage), other autopilots may not...
There are advantages both ways for storing the configuration in the GCS
and on the vehicle; one allows you to switch laptops and know the config
will be the same. The other allows the interface to change between
laptops based on input devices....
|
|
@peterbarker There was an orthogonal discussion here #1848 which looks at the use case of a MAVLink joystick. This is a joystick that does not need to be connected to a GCS when used. The idea was that a joystick would have a component metadata mechanism to configure its buttons a lot like the mavlink camera API - i.e. you'd query the joystick for its axes and buttons and get metadata back on what is supported. The buttons would have set options that map to parameter values - i.e. button 1 might have param_button_1 on the joystick with options "enable fence", "kill switch". My point is that the sending mavlink command mechanism is more flexible here too. Component information helps with the problem of knowing what the joystick can do, and means that the autopilot doesn't need to have any extra config to work. It's just an idea at this time. |
|
Anyway, appreciate that you're probably making a pragmatic decision based on what mission planner does now (and PX4). Nothing is going to change in any sort of short timeframe so you can do what you like. But if you go with sending mavlink commands that will work whatever is done in future with the MANUAL_CONTROL message. |
|
Discussed this in the 20250410 dev call. This was explained to me as follows (capturing so I don't have to ask this all again!)
Upshot I am not sure how to change the messages but if we change anything we break everything. I'm not sure how we'd fix this - presumably a similar message where the definitions are as intended by @julianoes Is that about right? Feel free to edit this if I misunderstood! |
That's debatable. The naming would indicate this but the way it is described and implemented does not.
They way how I read this is that @junwoo091400 does not actually want to change/break anything but merely document how it is actually used and implemented in QGC. |
|
Ping @Williangalvani |
|
So here's the summary of the whole landscape on MANUAL_CONTROL: QGC
PX4 Ardupilot
Thus, it seems fairly customized per vehicle type, and the unification of the definition won't be trivial (expected range already differs per vehicle in Firmwares), and will lead breaking changes (e.g. [-1000, 1000] range will be rejected for Arducopter, PX4, etc) So I think there isn't really a solution here, and the best we could do is just to clarify this difference of MANUAL_CONTROL.z per vehile type in the MAVLink message definition, and support this legacy implementation. Thoughts?p.s. It's interesting that QGC originally allowed users to choose whether RC transmitter's throttle channel is spring loaded or not, but now that logic isn's used AFAIK (assumes not spring loaded): mavlink/qgroundcontrol#1827 Also, the Rover / Submarine control for PX4 through QGC is broken exactly due to this mismatch. So only the 'positive thrust' worked before, due to the (debatable) wrong implementation on Firmware side (not considering neative MANUAL_CONTROL.z range when Rover/Submarine) |
| <field type="int16_t" name="x" invalid="INT16_MAX">X-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to forward(1000)-backward(-1000) movement on a joystick and the pitch of a vehicle.</field> | ||
| <field type="int16_t" name="y" invalid="INT16_MAX">Y-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to left(-1000)-right(1000) movement on a joystick and the roll of a vehicle.</field> | ||
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to a separate slider movement with maximum being 1000 and minimum being -1000 on a joystick and the thrust of a vehicle. Positive values are positive thrust, negative values are negative thrust.</field> | ||
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to throttle high (1000) - throttle low (-1000) on a joystick. Centered throttle should result in value of 0 (center).</field> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to throttle high (1000) - throttle low (-1000) on a joystick. Centered throttle should result in value of 0 (center).</field> | |
| <field type="int16_t" name="z" invalid="INT16_MAX">Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Due to legacy reasons, [0, 1000] is used for PX4, ArduCopter, ArduPlane and ArduSub, whereas [-1000, 1000] is used for ArduRover. However originally, it generally corresponds to throttle high (1000) - throttle low (-1000) on a joystick. Centered throttle should result in value of 0 (center).</field> |
|
I stand with @junwoo091400's latest suggestion. Many times I thought about ways of remapping (for the sole purpose of following the spec) ArduSub to [-1000,1000], but I never got to a solution that wouldn't brake things. |
|
Thanks @junwoo091400 for the implementation overview!
I reached the same conclusion. Usage varies due to the ambiguous definition. Initially, I aimed for a consistent across vehicle types and with the other axes [-1000, 1000] full range in PX4, but transitioning cleanly proved infeasible. PX4 now enforces a [0, 1000] range and clamps negative values in that field (not rejecting the entire message), aligning with what QGC mostly sends and others mimic.
I agree and like your very specific description of how the field is used but would leave away the last part Long-term, I plan to introduce a new message that clearly defines remote input axes without ambiguous ranges or assumptions about their use of different vehicle types and modes on the receiving end. |
|
Without having read everything, so how do you go backwards, or actively down? |
Description
Previously, the
zcomponent definition relied on having a knowledge of which direction the thrust would result in, depending on its value, which is tied to the vehicle's setup (e.g. Rover, which can take in reverse-throttle commands vs. conventional quadcopter with only positive throttle).This is a bad practice because:
MANUAL_CONTROLmessage for each different type of vehicle to use the 'correct' range ofz. So having a GCS with a Joystick input will have to know which range of throttle would result in positive/negative thrust for each connected vehicle, which doesn't make sense.With this new definition, the MANUAL_CONTROL message will not be vehicle-specific and truly represent the Joystick / RC Transmitter's throttle position.
Alternatives
We could keep the convention as is 🤔
Discussion Points
Context
This issue was discussed in a PX4 PR trying to standardize the range for throttle internally: PX4/PX4-Autopilot#15949 (comment)