Skip to content
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

Add MAVLink receiver support, RADIO_RC_CHANNELS #24577

Closed
wants to merge 3 commits into from

Conversation

olliw42
Copy link
Contributor

@olliw42 olliw42 commented Aug 10, 2023

This is the first piece of adding what should be called a "MAVLink receiver".

This PR requires that the storm32.xml mavlink dialect file in https://github.com/ArduPilot/mavlink/tree/master/message_definitions/v1.0 is updated to that in the main mavlink repository.

The idea is simple, namely a receiver which does send its RC channel data (and other data such as link statistics) not via common protocols like SBus or CRSF but via a MAVLink message. Since it's such an obvious concept and so much desired, at least in the hobby world, I don't really know what else to say to make the case.

This message is implemented since in a while in my BetaPilot/Copter fork as well as in the mLRS project which provides a practical example of a MAVLink receiver, and also establishes a proof of concept, as well as demonstrates that the code PR'ed here works (in the setups used by those who tested/use it).

The RADIO_RC_CHANNELS mavlink message is currently located in the storm32.xml with ID 60045, but I'm happy to remove it from there and move it to any other location with any other ID you guys would suggest.

@magicrub
Copy link
Contributor

The PR for the proposed message is mavlink/mavlink#1919 which would need to be added to ArduPilot's mavlink fork too.

@olliw42
Copy link
Contributor Author

olliw42 commented Aug 14, 2023

The PR for the proposed message is mavlink/mavlink#1919 which would need to be added to ArduPilot's mavlink fork too.

yes, something needs to be done in the ArduPilot's mavlink fork. It is frankly however not so clear (to me) what the best action would be; I see a couple of approaches. I admit that I'm also not totally sure (lack of knowledge) how the technical aspect of handling changes in submodules would work here.

I think it would be very useful if you guys could come up with an opinion - or even decission - if

  1. you want to support a MAVLink receiver along the lines suggested here
  2. you are ok with the design of RADIO_RC_CHANNELS
  3. you are generally ok with the implementation approach taken in this PR

Maybe you find a chance to briefly discuss this in a dev call.

THX!

@olliw42
Copy link
Contributor Author

olliw42 commented Nov 27, 2023

I'd like to ask again if you maybe could find time to briefly discuss this topic in general and come up with an opinion or even decission on it.

I continue to argue, and see more and more signs pointing towards it, that this is just what "many" users would want to have, one connection for both mavlink and rc handling.
("many" users may not include your partners and other commercially oriented parties, which certainly are an most important driving force in ArduPilot, but the more casual and hobby users, which is a still existing group of users).

What would be helpful to know is your general opinion. Like
[] we like the concept and idea of a "mavlink receiver" and would be interested in it, but the PR sure needs work
[] we like the concept and idea of a "mavlink receiver" but don't consider it of interest for Ardupilot
[] we think the concept and idea of a "mavlink receiver" is flawed and is not suitable for Ardupilot

This PR is broken and needs an addition downstream in mavlink/pymavlink, sure, but easy enough. The question I wonder about is if it is worth to spend the effort. I'd be very happy to spend the effort, iff there is slight indication it may work out.

Thx.

@jlpoltrack
Copy link

jlpoltrack commented Nov 27, 2023

IMO, think that this makes a lot of sense and should be explored. As wireless links evolve it seems ideal to have a single link that can handle both MAVLink + RC.

Copy link
Collaborator

@Ryanf55 Ryanf55 Nov 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the unrelated and likely unintentional changes to submodules like the XRCE Client lib.

Copy link
Contributor Author

@olliw42 olliw42 Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try git checkout origin/master -- modules/Micro-XRCE-DDS-Client assuming your remote is origin

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MANY thx. Found a different workaround in the mean time. Thx again :)

Copy link
Collaborator

@Ryanf55 Ryanf55 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated changes need removed prior to merge.

Copy link
Contributor

@tridge tridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs an autotest, and needs cleanup of the submodule changes (remove ChibiOS and XRCE submodule changes)

on your question, the concept is good I think, just needs a bit of re-work

@@ -746,6 +747,9 @@ class GCS_MAVLINK
mavlink_message_t _channel_buffer;
mavlink_status_t _channel_status;

// for mavlink radio
mavlink_radio_t _mavlink_radio_packet;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to make this a pointer and allocate on first receiver so we don't pay for it on every connection

Copy link
Contributor Author

@olliw42 olliw42 Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is actually not needed for this PR but a leftover. Will be needed for a followup PR doing link statistics. Field removed.

@@ -6407,6 +6410,12 @@ bool GCS_MAVLINK::accept_packet(const mavlink_status_t &status,
return true;
}

// handle messages from a mavlink receiver
if ((msg.compid == MAV_COMP_ID_TELEMETRY_RADIO) &&
(msg.msgid == MAVLINK_MSG_ID_RADIO_RC_CHANNELS)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this bypasses signing checks, for a packet that can control the vehicle, this is very dangerous, we must not bypass those checks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I 100% agree that signing checks should not be bypassed, but I can't see anything in the function accept_packet() which would do something related to signing.
Could you maybe drop a hint of what I'm missing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll need to look when not on my phone, I thought signing used this for a bypass check

libraries/GCS_MAVLink/GCS_Common.cpp Show resolved Hide resolved
@@ -140,6 +140,13 @@ bool MAVLink_routing::check_and_forward(GCS_MAVLINK &in_link, const mavlink_mess
int16_t target_component = -1;
get_targets(msg, target_system, target_component);

// handle messages from a mavlink receiver as if it had target_system = our system, target_component = 0
if ((msg.compid == MAV_COMP_ID_TELEMETRY_RADIO) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the msg not have target_system?

Copy link
Contributor Author

@olliw42 olliw42 Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no. Pl see the post on this below. #24577 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This precludes having redundant receivers on-board.

You can target the message easily enough - we use the same technique on things like ADSB receivers. If no explicit target has been specified on the device then it waits for a heartbeat to arrive and (after filtering for appropriate vehicle type and MAV_TYPE). It then locks onto the flight controller, targetting it and using a source system the same as that flight controller. component ID can default to TELEMETRY_RADIO but should also be configurable (and that ID should have no relevance to the way the packet is processed on the flight controller, to allow for redundancy)

Copy link
Contributor

@peterbarker peterbarker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename files for case sensitivity (i.e. MAVLink not Mavlink)

I think I like this concept.

libraries/AP_RCProtocol/AP_RCProtocol.h Show resolved Hide resolved
libraries/AP_RCProtocol/AP_RCProtocol.cpp Outdated Show resolved Hide resolved
libraries/GCS_MAVLink/GCS_Common.cpp Show resolved Hide resolved
Comment on lines +144 to +148
if ((msg.compid == MAV_COMP_ID_TELEMETRY_RADIO) &&
(msg.msgid == MAVLINK_MSG_ID_RADIO_RC_CHANNELS)) {
target_system = mavlink_system.sysid;
target_component = 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look great

Add fields to the packet for target system/component.

Copy link
Contributor Author

@olliw42 olliw42 Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

concerning targets, pl see post below. #24577 (comment).

@tridge
Copy link
Contributor

tridge commented Nov 27, 2023

@olliw42 please ping on code-review discord channel when ready for re-review

@wvarty
Copy link

wvarty commented Nov 28, 2023

This work looks like it may also be helpful for the in-flight dev work to add mavlink as a serial protocol to ELRS.
I think the most valuable contribution will be the link stats though (suggested as a subsequent PR in the description), which is a slightly more complicated topic, as things like RSSIdBm and SNR are missing as OSD elements in mainline ardu.

@olliw42
Copy link
Contributor Author

olliw42 commented Nov 28, 2023

first off, many thx for the positive general response, this is very helpfull and encouraging.

@tridge @peterbarker

on the topic of target fields for this message.

It does not have any. The reasons are outlined in the first post of mavlink/mavlink#1921, in the two subchapters "Routing", and in last post in its last subchapter.
In a nutshell: These target fields would have to be populated with values, which the receiver thus would need to know somehow. I can't see a reasonable way how it could auto-determine them, and explicit configuration via a parameter is anything than user friendly, IMHO.
Not using targets comes with cons, but I judged the overall balance of cons vs pros to be better than for other options which came to my mind.

This is a very relevant "detail" and should be done right, and thus discussed well.

@khancyr
Copy link
Contributor

khancyr commented Nov 28, 2023

You can put the target field.
If they aren't used, they will be at 0 that will be broadcast in mavlink routing, so that is the same as not having the field.
But as the fields are presents, those that have ability to manage parameters would be able to benefit of them.
That shouldn't collide with the way you propose to use the message I think

@olliw42
Copy link
Contributor Author

olliw42 commented Nov 28, 2023

This PR needs an associated PR to https://github.com/ArduPilot/mavlink in order to bring in the RADIO_RC_CHANNELS message.

Which is a serious problem for me. It seems that github does not allow to have forks of both the main repo and a fork of that main repo. Unfortunately I do have a fork of https://github.com/mavlink/mavlink, of which https://github.com/ArduPilot/mavlink is a fork of. It seems I'm doomed.

What can I do?

In the meanwhile, I have rebased and updated the respective PR to the main repo: mavlink/mavlink#1919. I also add a post there listening the discussion points, like the targets topic.

@olliw42
Copy link
Contributor Author

olliw42 commented Nov 28, 2023

You can put the target field. If they aren't used, they will be at 0 that will be broadcast in mavlink routing, so that is the same as not having the field. But as the fields are presents, those that have ability to manage parameters would be able to benefit of them. That shouldn't collide with the way you propose to use the message I think

I sure have thought about this but found it not to achieve the desired goals, that is, comes with costs which outweight the benefits. IMHO.

In my mind the message should "exist" only on the system, but not outside of it. However, if it is generally considered acceptable that these messages are normally broadcasted, even beyond the system, then there is no issue and I'm trying to solve a non-issue.

I could reproduce here now the arguments and discussion in the linked posts,but I'm not sure how helpfull it would be to reproduce all arguments, in essentially just different words. Maybe I can kindly ask you to read the two respective paragraphs in the first post of mavlink/mavlink#1921. I have just reread them and find then sufficiently ok.

The reasons IMHO are largely the same reasons for why you find special code for MAVLINK_MSG_ID_RADIO_STATUS, MAVLINK_MSG_ID_RADIO, like here https://github.com/ArduPilot/ardupilot/blob/master/libraries/GCS_MAVLink/MAVLink_routing.cpp#L117-L121 or here https://github.com/ArduPilot/ardupilot/blob/master/libraries/GCS_MAVLink/GCS_Common.cpp#L6405-L6408.

The extend, let me mention few things which are different to a normal MAVLink component (autopilot, gimbal, companion,...)

  • The receiver has a system_id different from both the GCS (or GCSes) and the autopilot (or autopilots). Generically its system_id would be 51 like for the SiK radios.
  • The receiver is normally not emitting a HEARTBEAT message (it could and would have to if it wants to support e.g. the parameter service, but it should not just for the sake of being a receiver).

Each of these point can be debated, with pros and cons.

Note also that the RADIO_RC_CHANNELS message (and others of this set not part of this PR) must not be emitted by anything else than a mavlink receiver (without this constraint it is indeed easily possible to create all sorts of situations producing conflicts)

@khancyr
Copy link
Contributor

khancyr commented Nov 28, 2023

I have read your other post before answering.
What you are proposing, and it is fine to me, is a special handling for this message and prevent it to be fowarded (we will need to check this carefully). Fine on this point.
How are you doing this ? We got a new message that don't have target system. So in mavlink routing perspective that is a implicitly a broadcast message by default. Do we agree on that ?

Normally, your intend for this message is that it is send directly from the receiver to whatever will handle its msg content and should prevent the forwarding by the special handling ? I got it right ?

What I say is : instead of doing implicity mavlink broadcast, add the target field. It will do explicit mavlink broadcast. Then we can still apply the special handling. It shouldn't change anything on your case and PR.
But for those that want to do targeting and forwarding, they can do it now. So we can have unparametrized receiver and parametrized one's using the same message. Is my reasoning clear enough and right ?

@olliw42
Copy link
Contributor Author

olliw42 commented Nov 28, 2023

many thx for your further comments. Your reasoning is clear, but I do have a bit of a different perspective on it.

We got a new message that don't have target system. So in mavlink routing perspective that is a implicitly a broadcast message by default. Do we agree on that ?

absolutely

Normally, your intend for this message is that it is send directly from the receiver to whatever will handle its msg content ...? I got it right ?

here I divert. I read "send directly" to imply a fully targeted message, going just from the receiver to exactly one other endpoint (target_sysid != 0 and target_compid != 0 in mavlink routing speach). I instead think that normally it should be send to all components of the system, autopilot, gimbal, companion, camera, .... whatever. That is target_sysid != 0 and target_compid == 0, in mavlink routing speach.

Then we can still apply the special handling.

I agree with you in adding the target fields in so far as it is better to add them now for just in case. One drawback of the design of RADIO_RC_CHANNELS is that it can't be extended later (at least not without dismaying cost). So, any mistake now will bite later. In that sense it's better to just add them.

If you guys would not mind having the speical handling, problem seems to be solved.

However: Let's think for a moment about how it would read in the standard's docs. I mean, eventually the message should become standard and move into common.xml, right. We would essentially suggest to write: "The message has target fields but these should not be normally used and in fact each implementation should add special code to handle the message properly in the normal cases."? I would find that pretty odd in terms standardization, and I have doubts it would run well.

Also, if that special code is there, you can't get around it by pure mavlink means (i.e. not changing the code), so the target_sysid field will be irrelevant, and all you could do is to play with target_compid.

I want to mention again that there never ever should be a situation there one would send that message to anything else than components of the system it is connected to. (in particular it must not send e.g. from the ground to the vehicle, or from the vehicle to the ground). That is target_sysid must always be that of the system. So in the docs we actually would write "The message has target fields but these should not be normally used and in fact each implementation should add special code to handle the message properly in the normal cases. In addition target_sysid must be that of the system the receiver is connected to".

In my mind the two things "special code to handle routing" and "target fields for normal mavlink routing" are kind of mutually exclusive options.

I will not mind all that, if that is what the preference is. I'm just not convinced. :)

@tridge
Copy link
Contributor

tridge commented Nov 28, 2023

@olliw42 ok, I understand and agree on why it doesn't have target fields

Copy link
Contributor

@tridge tridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm stuck on my phone for this review, so hard to look in detail sorry

}

// update the field, so that the backend can see it
memcpy(&(mavlink_radio.rc_channels), packet, sizeof(mavlink_radio_rc_channels_t));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a structure assignment instead of memcpy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added virtual handlers to backend, which makes this field and line go altogether. Done.

// handle mavlink radio
void handle_radio_rc_channels(const mavlink_radio_rc_channels_t* packet);
struct {
mavlink_radio_rc_channels_t rc_channels;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be chewing a chunk of ram per instance? We have a lot of instances

Copy link
Contributor Author

@olliw42 olliw42 Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is located in the frontend, so should be "just" one of them, as I understand it.
Very usefull comment. Added virtual handlers to backend, which makes this field go altogether. Nice. Done.


uint16_t rc_chan[MAX_RCIN_CHANNELS];
for (uint8_t i = 0; i < count; i++) {
rc_chan[i] = ((int32_t)frontend.mavlink_radio.rc_channels.channels[i] * 5) / 32 + 1500;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment explaining this maths would be nice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice. done.

@@ -61,3 +61,7 @@
#ifndef AP_RCPROTOCOL_FASTSBUS_ENABLED
#define AP_RCPROTOCOL_FASTSBUS_ENABLED AP_RCPROTOCOL_BACKEND_DEFAULT_ENABLED && AP_RCPROTOCOL_SBUS_ENABLED
#endif

#ifndef AP_RCPROTOCOL_MAVLINK_RADIO_ENABLED
#define AP_RCPROTOCOL_MAVLINK_RADIO_ENABLED AP_RCPROTOCOL_BACKEND_DEFAULT_ENABLED
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe default enable only on 2M flash boards? I haven't looked at flash cost of the feature

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -6407,6 +6410,12 @@ bool GCS_MAVLINK::accept_packet(const mavlink_status_t &status,
return true;
}

// handle messages from a mavlink receiver
if ((msg.compid == MAV_COMP_ID_TELEMETRY_RADIO) &&
(msg.msgid == MAVLINK_MSG_ID_RADIO_RC_CHANNELS)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll need to look when not on my phone, I thought signing used this for a bypass check

@olliw42
Copy link
Contributor Author

olliw42 commented Nov 29, 2023

I haven't flight tested the last round of changes yet. Will do ASAP. all good, passed.

@olliw42
Copy link
Contributor Author

olliw42 commented Nov 30, 2023

@tridge
if nothing new comes up it seems two points are left:

  • settle signing concerns
    * how to bring in RADIO_RC_CHANNELS message (or how to deal with both a fork and a fork of a fork in github)

@olliw42
Copy link
Contributor Author

olliw42 commented Dec 3, 2023

it would be much appreciated if you maybe could find time again to briefly discuss this PR in the dev call. It seems to me it has made progress, and it would be sad if it couldn't be finished. Many thx in advance.

@olliw42
Copy link
Contributor Author

olliw42 commented Dec 6, 2023

@jlpoltrack thankfully volunteered to submit the PR for merging the RDAIO_RC_CHANNELS message into your mavlink repo: ArduPilot/mavlink#343.

so, the point which is left to settle are the signing concerns.

@olliw42
Copy link
Contributor Author

olliw42 commented Dec 9, 2023

Addendum:
I want to mention that the lines which raised security concerns in signing situations, https://github.com/ArduPilot/ardupilot/pull/24577/files#diff-a8cfae886a15156d6cab6c16716a6081f6d0f3fe8a5d730a3f23ab6f740fcfecR6415-R6422, are not really relevant nor crucial for the message and concept to work.
That is, I would not hesitate for a second to remove them if there are any concerns with them which can't be settled now.
I added them as they made sense to me, but think that most users who would be interested in using a mavlink receiver as of today won't have SYSID_ENFORCE set anyway, so no harm done with removing the lines.
If that helps to draw a decission sooner than later :)

Addendum II:
It might have be the function accept_unsigned_callback() (https://github.com/ArduPilot/ardupilot/blob/master/libraries/GCS_MAVLink/GCS_Signing.cpp#L114-L127) which might have been in mind when suspecting the singing issue in the function accept_packet(). It also has special treatment for RADIO_STATUS.

@olliw42
Copy link
Contributor Author

olliw42 commented Dec 11, 2023

@peterbarker @khancyr @tridge devcall maybe?
:)

Copy link
Contributor

@peterbarker peterbarker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good, I just have concerns about the lack of targetting.

My major concern on the lack of targetting of the mavlink message is that (a) it's relatively easily solveable in a user-friendly manner, and that if you've got swarms of vehicles seeing each other's traffic you really don't want vehicles seeing other vehicle's messages! If you have your RC receiver feeding into e.g. cmavnode - then you're likely to get that sort of problem!

@@ -140,6 +140,13 @@ bool MAVLink_routing::check_and_forward(GCS_MAVLINK &in_link, const mavlink_mess
int16_t target_component = -1;
get_targets(msg, target_system, target_component);

// handle messages from a mavlink receiver as if it had target_system = our system, target_component = 0
if ((msg.compid == MAV_COMP_ID_TELEMETRY_RADIO) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This precludes having redundant receivers on-board.

You can target the message easily enough - we use the same technique on things like ADSB receivers. If no explicit target has been specified on the device then it waits for a heartbeat to arrive and (after filtering for appropriate vehicle type and MAV_TYPE). It then locks onto the flight controller, targetting it and using a source system the same as that flight controller. component ID can default to TELEMETRY_RADIO but should also be configurable (and that ID should have no relevance to the way the packet is processed on the flight controller, to allow for redundancy)

libraries/AP_RCProtocol/AP_RCProtocol.cpp Outdated Show resolved Hide resolved
@olliw42
Copy link
Contributor Author

olliw42 commented Dec 13, 2023

This precludes having redundant receivers on-board.

not necessarily, the different receivers could be given different system id's. I agree however that this is not what one may like, but fortunately MAVLink provides a canonical pattern for how to handle that.

One should define multiple MAV_COMP_ID_TELEMETRY_RADIO, i.e. also in additon MAV_COMP_ID_TELEMETRY_RADIO2, MAV_COMP_ID_TELEMETRY_RADIO3, ...

These are not currently existing in MAVLink. But could be added any time, on desire.

My major concern on the lack of targetting of the mavlink message is that (a) it's relatively easily solveable in a user-friendly manner

You can target the message easily enough - we use the same technique on things like ADSB receivers. If no explicit target has been specified on the device then it waits for a heartbeat to arrive and (after filtering for appropriate vehicle type and MAV_TYPE). It then locks onto the flight controller, targetting it and using a source system the same as that flight controller. component ID can default to TELEMETRY_RADIO but should also be configurable (and that ID should have no relevance to the way the packet is processed on the flight controller, to allow for redundancy)

we are approaching a limit cycle. I had explained why it's not a good option to having to wait for a heartbeat.

I very well know this mechanism and use it e.g. also in the STorM32 controller and it's working great there too. But not so well here.

Let me try again. In this approach the rc channels data are send out only after a flight controller has been detected. This is - IMHO - absolutely not hwat one wants, as a user. E.g.,

  • one could not test that receiver without an attached working fc
  • other components such as gimbals or cameras which may use the message and its data could not start working with that data before the fc has booted up and revealed itself
  • one could not test these other component's rc data handling without an attached working fc
  • one could not use that receiver without a fc in the system or conncetion to that fc. E.g. one could not attach such a receiver to a STorM32 gimbal for dual operation (without nasty code tricks).
  • ... I propbably missed more "little" annoyences comming from this

I just see a bag full of inconveniences. Let's put it that way: If that would be what the final result would be I would actually be totally not interested in using such a receiver...

and that if you've got swarms of vehicles seeing each other's traffic you really don't want vehicles seeing other vehicle's messages! If you have your RC receiver feeding into e.g. cmavnode - then you're likely to get that sort of problem!

that's why there are these routing rules which say that the message should be routed as if it had target_system = system id and target_component = 0 so as to not ever go beyond it's attached system. :)

@peterbarker
Copy link
Contributor

This precludes having redundant receivers on-board.

not necessarily, the different receivers could be given different system id's. I agree however that this is not what one may like, but fortunately MAVLink provides a canonical pattern for how to handle that.

One should define multiple MAV_COMP_ID_TELEMETRY_RADIO, i.e. also in additon MAV_COMP_ID_TELEMETRY_RADIO2, MAV_COMP_ID_TELEMETRY_RADIO3, ...

I absolutely do not subscribe to the MAV_COMP_ID_* concept of allocating functions to IDs. HEARTBEAT tells you what sort of thing a mavlink node is, and with only a 255-entry namespace we are so going to run out why the time you add enough IDs for as many things as you could potentially have on random vehicles.

My major concern on the lack of targetting of the mavlink message is that (a) it's relatively easily solveable in a user-friendly manner

You can target the message easily enough - we use the same technique on things like ADSB receivers. If no explicit target has been specified on the device then it waits for a heartbeat to arrive and (after filtering for appropriate vehicle type and MAV_TYPE). It then locks onto the flight controller, targetting it and using a source system the same as that flight controller. component ID can default to TELEMETRY_RADIO but should also be configurable (and that ID should have no relevance to the way the packet is processed on the flight controller, to allow for redundancy)

we are approaching a limit cycle. I had explained why it's not a good option to having to wait for a heartbeat.

I'm sorry, I must have missed that argument somewhere. Can you point that out somewhere, please?

I very well know this mechanism and use it e.g. also in the STorM32 controller and it's working great there too. But not so well here.

Let me try again. In this approach the rc channels data are send out only after a flight controller has been detected. This is - IMHO - absolutely not hwat one wants, as a user. E.g.,

* one could not test that receiver without an attached working fc

Or manually configuring a target system/component on the unit.

* other components such as gimbals or cameras which may use the message and its data could not start working with that data before the fc has booted up and revealed itself

And if users want to use a separate RC receiver for the camera vs the flight controller? In the case you here you'd need to configure the source system manually on the device providing hte mavlink message. Also a good use of target system/component - but does require configuration

* one could not test these other component's rc data handling without an attached working fc

Not without configuring the source system manually. Configurability of the source component is important to allow for redundancy.

* one could not use that receiver without a fc in the system or conncetion to that fc. E.g. one could not attach such a receiver to a STorM32 gimbal for dual operation (without nasty code tricks).

.. no, just configuration. 99% of cases out there you plug-and-play. 1% of the cases require (and probably desire!) configuration.

that's why there are these routing rules which say that the message should be routed as if it had target_system = system id and target_component = 0 so as to not ever go beyond it's attached system. :)

We shouldn't need to add routing rules for new messages, and "legacy" software NOT having this filtering/routing (root cause of tacking routing onto MAVLink based on magic field names/explicit listing) mean that these messages would leak and create havoc.

@olliw42
Copy link
Contributor Author

olliw42 commented Dec 28, 2023

many thx for taking your time and looking at it again, but I think it's the type of discussion I don't want to be in.

Concerning heartbeat and type and id, I normally couldn't agree more, and I believe that some years back it was me who worked hard to convince the mavlink folks that this is how it has to be, and get respective language into the docs. Yet for the mavlink receiver I came (and still come) to a different conclusion, IMHO it just adds loads of complexity for no purpose except of clinging to a principle, using a sledgehammer to crack a nut.

It's a weired discussion. There is absolutely nothing in ArduPilot which would adhere to that mavlink principle you've mentioned, to the contrary. I just looked up again how some mavlink components are handled, to reasure that's accurate. For mavlink components like GPS, optical flow, proximity, rangefinder, OSD, the handling is as crude as it can be, and far off any principle like the one you suggested. Gimbal and camera are somewhat better, since here there is indeed a find phase, yet it's strictly required to use predefined gimbal and camera ids, in obvious contrast to your position. The greemsy driver (and possibly others) breaks mavlink principles also in other fundamental ways.

So, frankly, it feels like been drawn into a discussion which ArduPilot hasn't settled for itself, and most of the time is happy to violate, and all what is clear to me is that I don't want to be in that discussion.

Concerning ease of use, user friendliness, we are not going to share common ground. All this configuration talk may indeed look easy and natural to you, but it's a reason for the sentiment that ArduPilot is - comparatively - complicated to set up and use. ArduPilot's mindset doesn't appear to match up with most user's idea of ease of use, and to be frank, I here will trust my own judgment much more than that of any ArduPilot member.

So, where to go from here.

Your comments imply that the mavlink receiver has to also emit a heartbeat, and that the discovery of that component should be based on it and moreover be untight from any predefined ids. If that is the position, I'd like to say that it's not me who is going to pursue this or even try to implement this. In that case, it probably would be appropiate to just close that PR.

If however all we are talking about is the routing and target id thing, i.e. no heartbeat and type and etc. pp, then we may have a deal. It's easy enough to modify the above code and the xml definition, and I will be fine with doing this (see #25838 for how it may look like).

To sum up, I see two options:

  • close the PR and forget the thing
  • remove routing code and add target ids to xml definition

@auturgy
Copy link
Contributor

auturgy commented Dec 28, 2023

@peterbarker I find myself on the fence with this: as we've discussed, I agree that ensuring that the implementation covers as many use cases as possible is important, but I think we also need to ensure that we don't let perfect be the enemy of good. Would getting this in as a compile/custom build server option provide sufficient protection for you? I think that if we do that, it provides both a safety net and a base to continue to evolve this.

@olliw42
Copy link
Contributor Author

olliw42 commented Jan 13, 2024

@peterbarker @auturgy what's up?
I had changed the message to include targets

no good? dead horse?

Copy link
Contributor

@peterbarker peterbarker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very partial review only; I was only looking for the handling of the failure flags

rc_chan[i] = ((int32_t)packet->channels[i] * 5) / 32 + 1500;
}

bool failsafe = (packet->flags & RADIO_RC_CHANNELS_FLAGS_FAILSAFE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not sufficient. If the values are frozen we don't want to use them either!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean by "froozen"
the case when frames are not received is handled by the upper level code
if you mean handling missing frames bit: IMHO this is exactly as for sbus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants