From 9ff48836eba6d60bca54d36d828a7f1c2481499f Mon Sep 17 00:00:00 2001 From: Julian Oes Date: Tue, 22 Sep 2026 11:19:41 +1200 Subject: [PATCH] fix(mavlink): support external gimbal manager on gimbal mode link A gimbal with its own gimbal manager is typically connected to a MAVLink instance in gimbal mode. That mode only handles a whitelist of incoming messages and only streams a few messages, so the external gimbal manager was never discovered there and would not have received any setpoints. Accept GIMBAL_MANAGER_STATUS as well as COMMAND_ACK (for the DO_GIMBAL_MANAGER_CONFIGURE that we send, otherwise it is retried until it times out) and stream GIMBAL_MANAGER_SET_PITCHYAW in gimbal mode. This also makes the check to not ingest the gimbal device information of an external gimbal manager work on such a link, as that depends on having seen its GIMBAL_MANAGER_STATUS. While at it, ignore the status of gimbal managers of other systems, e.g. forwarded from another vehicle. Only a manager on our vehicle is ours to talk to. Assisted-by: Claude:claude-fable-5-1 Signed-off-by: Julian Oes --- src/modules/mavlink/mavlink_main.cpp | 1 + src/modules/mavlink/mavlink_receiver.cpp | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/modules/mavlink/mavlink_main.cpp b/src/modules/mavlink/mavlink_main.cpp index 803e626479b..12271aca210 100644 --- a/src/modules/mavlink/mavlink_main.cpp +++ b/src/modules/mavlink/mavlink_main.cpp @@ -1783,6 +1783,7 @@ constexpr StreamRateDefault streams_mode_gimbal[] = { // Note: streams requiring low latency come first {"AUTOPILOT_STATE_FOR_GIMBAL_DEVICE", 20.0f}, {"GIMBAL_DEVICE_SET_ATTITUDE", 20.0f}, + {"GIMBAL_MANAGER_SET_PITCHYAW", 20.0f}, }; constexpr StreamRateDefault streams_mode_extvision[] = { diff --git a/src/modules/mavlink/mavlink_receiver.cpp b/src/modules/mavlink/mavlink_receiver.cpp index 6ff30a1bef8..62a76a3f800 100644 --- a/src/modules/mavlink/mavlink_receiver.cpp +++ b/src/modules/mavlink/mavlink_receiver.cpp @@ -489,6 +489,17 @@ void MavlinkReceiver::handle_messages_in_gimbal_mode(mavlink_message_t &msg) handle_message_gimbal_device_attitude_status(&msg); break; + case MAVLINK_MSG_ID_GIMBAL_MANAGER_STATUS: + // The component on this link might be an external gimbal manager. + handle_message_gimbal_manager_status(&msg); + break; + + case MAVLINK_MSG_ID_COMMAND_ACK: + // Needed for the commands we send (e.g. DO_GIMBAL_MANAGER_CONFIGURE), + // otherwise they are retried until they time out. + handle_message_command_ack(&msg); + break; + case MAVLINK_MSG_ID_COMMAND_LONG: { mavlink_command_long_t cmd; mavlink_msg_command_long_decode(&msg, &cmd); @@ -3711,7 +3722,9 @@ MavlinkReceiver::handle_message_gimbal_manager_status(mavlink_message_t *msg) { // Ignore our own gimbal manager: PX4 streams this itself from the autopilot // component, and we only care about external gimbal managers here. - if (msg->sysid == mavlink_system.sysid && msg->compid == mavlink_system.compid) { + // Also ignore gimbal managers of other systems (e.g. forwarded from another + // vehicle), only a manager on our vehicle is ours to talk to. + if (msg->sysid != mavlink_system.sysid || msg->compid == mavlink_system.compid) { return; }