RFC: addressing for the MAVLink-M messages that direct a specific system - #10
RFC: addressing for the MAVLink-M messages that direct a specific system#10TSC21 wants to merge 2 commits into
Conversation
Every message in the dialect is broadcast: none carries
target_system or target_component, so a message that orders one
system to do something cannot say which system it is for. A station
tasking a sensor on one aircraft, or ordering an effector to engage,
puts that message where every system reading the dialect sees it.
With two aircraft on a shared bearer, or one aircraft carrying two
payloads that both speak the dialect, nothing in the message
separates them.
The eleven messages that command a system, or that hand something
to a named one, carry the two fields: FIRES, SPLASH_CORRECTION,
TARGET_HANDOVER, ESAD_ARMING, ESAD_CONFIG, SENSOR_TASKING,
CAS_9LINE, TERMINAL_CONTROL, ENGAGEMENT_DIRECTIVE, CALL_FOR_FIRE and
LOITER_MUNITION_CONTROL. The messages that describe the world keep
broadcasting, because a contact is a contact and anything listening
should draw it.
The names are the ones MAVLink reserves. mavgen fills the target
offsets in the message-entry table only for fields called
target_system and target_component, and that table is what a router
reads to place a message: FIRES becomes {53020, 124, 64, 64, 3, 40,
41}, where 3 is the have-target flag and 40 and 41 are the byte
offsets. A field named anything else leaves that row at zero and the
message keeps flooding every endpoint.
The fields are part of the message rather than an extension, so the
wire format and the CRC change. This dialect is under development
and its messages can still be replaced, which is the moment to put
addressing in the message body where it belongs.
51e2e3f to
00bad7c
Compare
|
Q1 - not an oversight. The design assumes addressing. The MAVLink-M swarm dataflow concept specifies "Addressed TARGET_HANDOVER per target to the chosen shooter's sysid", and lists "addressed handoff" among the things the dialect already provides. It explicitly rules out the alternative: "What is explicitly not supported is a third, unsafe pattern - broadcasting one target to everyone and letting whoever arrives strike it. That produces convergence: multiple munitions wasted on one target, and multiple armed aircraft meeting at one point in space." store_id, effector_id and esad_id all carry "0 = all" semantics. No track_uid on ESAD_ARMING, ESAD_CONFIG, SENSOR_TASKING, TERMINAL_CONTROL, CAS_9LINE. Q2 - agree with the split; ESAD_ARMING especially. Q3 - yes, use the reserved names on MAVLINK_M_ACK. |
|
Thanks @ryanjAA, that answers all three. Q1: that settles it. Addressing was always the design, it just was not in a place a router can act on. Good point on store_id, effector_id and esad_id as well. Those pick the device inside an aircraft, these new fields pick the aircraft, and 0 still means all at both levels. Q2: good, the split stays as posted and TARGET_CUE stays broadcast. Q3: I will add it to this PR. Concretely, origin_sysid becomes target_system, since it already names the system the ack has to get back to, target_component goes next to it, and ack_sysid goes away because the frame header already says who is sending. That leaves MAVLINK_M_ACK looking like COMMAND_ACK in common. Tell me if ack_sysid is there for a reason I am missing, otherwise I will push that here. On track_uid, agreed, and I think it belongs in its own PR because it answers a different question: these fields say who has to act, track_uid says what the message is about. Your ESAD_ARMING against ESAD_STATE example is the clearest one. It hits SENSOR_TASKING too, where you cannot tell a sensor which track to watch, so a ground station ends up sending coordinates and the task cannot follow a moving target. Happy to write that one up if nobody else is on it. So: the ack change lands here, this PR covers who has to act, and what the message is about comes separately. If that works for you, an approval once the ack commit is up and this can stop being an RFC. |
MAVLINK_M_ACK closes the loop on a message one system sent to
another, so it has exactly one correct destination: the originator of
the acknowledged message. A field of its own naming that originator
stays invisible to a router, which places messages from the
message-entry table mavgen generates and finds a zeroed target row
there, so an acknowledgment reaches every endpoint on the bearer.
The reserved names carry the destination. target_system names the
originator the acknowledgment belongs to, and target_component names
the consumer inside it, which an aircraft carrying two systems that
speak the dialect needs in order to place the answer. The
acknowledging system is the source of the MAVLink frame, so the frame
header identifies it and the message body leaves that to the header.
The dialect generates MAVLINK_M_ACK as {53004, 224, 69, 69, 3, 16,
17}: 3 is the have-target flag and 16 and 17 are the byte offsets of
the two fields. The payload holds at 69 bytes, the CRC changes as a
field change requires, and the other twenty-five messages generate
byte-identical entry rows.
|
MAVLINK_M_ACK carries target_system and target_component, and ack_sysid is gone because the frame header already says who is sending. It generates as {53004, 224, 69, 69, 3, 16, 17}, so a router can place it, and the payload stays at 69 bytes since two fields go in and two come out. Every other message in the dialect generates a byte-identical entry row. I left origin_sysid alone on TRACK_IDENTITY, TARGET_CUE, PARTICIPANT_POSITION and ENGAGEMENT_DIRECTIVE. Those say who a report is about, not where it goes, so they are not the same field wearing a different name. |
Contributed on behalf of RIIS, LLC.
Opening this as an RFC. If the answer is that routing belongs outside the dialect I am happy to close it, but I think a message whose definition singles out one recipient should be able to name it, the same way core MAVLink already does.
What I ran into
While integrating the dialect into QGC, which consumes the situational-awareness messages and originates sensor tasking and nothing else, I checked the dialect for addressing and there is none. All 26 messages are broadcast, none of them carries
target_systemortarget_component.For the messages that describe the world that looks right and I am reading it as intended. A contact is a contact, and anything listening should be able to draw it.
For the messages whose definition directs a single system it is a spec gap.
SENSOR_TASKINGtasks one sensor, yet it cannot say which one, so the tasking goes out and every system reading the dialect sees it. The same shape repeats across the dialect's other directive messages. On one aircraft with one payload that works by luck. With two aircraft on a shared bearer, or one aircraft carrying two payloads that both speak the dialect, nothing in the message separates them.What we do today in QGC is pick the link: we send sensor tasking only on the selected vehicle's link. That works because we own the link. It does nothing for anyone routing this over a shared bus, a mesh or a router, and it does not separate two payloads on the same aircraft.
What this PR does
Adds
target_systemandtarget_componentto the eleven messages whose definitions direct a specific system or hand something to a named one:FIRES,SPLASH_CORRECTION,TARGET_HANDOVER,ESAD_ARMING,ESAD_CONFIG,SENSOR_TASKING,CAS_9LINE,TERMINAL_CONTROL,ENGAGEMENT_DIRECTIVE,CALL_FOR_FIRE,LOITER_MUNITION_CONTROL.The messages that describe the world are left alone.
On scope, to be explicit: this adds no capability and no semantics, it only lets a directive the dialect already defines name its recipient, using the same two reserved field names core MAVLink uses for the purpose. The integration behind this RFC exercises
SENSOR_TASKINGand nothing else; the rest of the list is swept because a definitions change should treat every directive in the dialect consistently, not because I implement them or plan to.The fields are part of the message, not an extension. That changes the wire format and the CRC. The dialect is still under development and the messages can be replaced, so this is the moment to put addressing in the message body rather than bolt it on the end later.
Why the field names matter
This is the part I would have got wrong if I had named the fields something of my own.
A router does not read the XML. It reads the message-entry table mavgen generates, and mavgen fills the target offsets in that table only for fields called exactly
target_systemandtarget_component. With the change,SENSOR_TASKINGgenerates as:where 3 is the have-target flag and 22 and 23 are the byte offsets of the two fields in the payload. That is what lets a router find the target at a fixed offset without knowing anything else about the message, look up which endpoint that system was last heard on, and send it there instead of to everyone.
A picture message stays as it is:
Flag 0, no offsets, so a router floods it to every endpoint, which is what you want for a contact.
Worth saying out loud: the router still has to have this dialect compiled in. A router that does not know 53050 cannot read its target fields and will broadcast it, so addressing in the message helps the routers that carry the dialect and changes nothing for the ones that do not.
Questions
TARGET_CUEwas the one I went back and forth on, since its description says it is relayed to one or more consumers, and I left it broadcast.MAVLINK_M_ACKalready hasack_sysid, so I left it alone. Would you rather it used the reserved names too, so a router can place an acknowledgement back to the asker?Happy to extend or narrow this whichever way you prefer.