Skip to content

feat(commander): external modes setpoint types & reliability#27683

Merged
mrpollo merged 7 commits into
mainfrom
external_modes_setpoint_types
Jul 3, 2026
Merged

feat(commander): external modes setpoint types & reliability#27683
mrpollo merged 7 commits into
mainfrom
external_modes_setpoint_types

Conversation

@bkueng

@bkueng bkueng commented Jun 17, 2026

Copy link
Copy Markdown
Member

Background

This started out with reliability issues: DDS topics do not use reliable transfer, which for most cases is fine as topics are regularly updated or checked for a reply. But there are some exceptions:

  1. mode_completed signalling
  2. fw setpoint configuration
  3. config overrides
  4. vehicle control mode (setpoint configuration)

We started to see topic drops in very rare cases for modes that switch between setpoint types.

Solution

The cleanest solution would be to use reliable transfer for these topics.
I tried that in the past and it resulted in severe topic drops for all telemetry messages, making it unusable.

So this PR addresses the cases individually, there is a simple solution for each:

  1. the topic is re-published continuously until there is a mode switch
  2. similar: ensure the configuration is re-published regularly
  3. a confirmation is added to PX4
  4. for this one I took the opportunity to do a bigger change, see next section

Setpoint types

This PR switches from using VehicleControlMode to a specific setpoint type message with reply.
Reasons:

  • in case a VehicleControlMode was dropped (e.g. when the mode switched setpoint type), no confirmation was returned, and resulting in wrong controller flags.
  • cleaner interface separation: external modes do not need to configure (or know) which controller to run for a certain setpoint
  • allows for external modes to check for compatibility: e.g. a mode using fixed-wing setpoint types can now be rejected on a multicopter.
  • allows for further extensions, like a setpoint timeout

It also adds a timeout to the setpoint config, but is not implemented yet.

PX4 internal modes also make use of this (except they do not need to publish the topics as it's known at compile-time). So the new information flow is:

nav_state -> setpoint type -> vehicle control mode flags

Apart from the added setpoint type compatibility check, the behavior is expected to be the same.

Adding a new setpoint type

When adding a new setpoint message, a new type needs to be added to msg/versioned/SetpointConfig.msg, and handled in src/modules/commander/ModeUtil/setpoint_types.cpp. Then it can be used for internal and/or external modes.

Other changes

  • remove unused VehicleAngularAccelerationSetpoint.msg
  • remove unused flag_control_acceleration_enabled

This depends on Auterion/px4-ros2-interface-lib#209

Note: it is a breaking API change for external modes and requires updating both sides. The API version is incremented and if there is a mismatch, an external mode raises an appropriate exception.

@github-actions github-actions Bot added vehicle:fixed-wing Fixed-wing-specific behavior. vehicle:copter Copter-specific behavior. scope:control Rate, attitude, position, allocation, or actuator control. scope:navigation Missions, RTL, geofence, takeoff, landing, or navigator behavior. scope:offboard Offboard mode, external setpoints, companion-computer control, or offboard failsafe behavior. scope:commander Arming, modes, failsafe, health checks, or vehicle state. scope:uorb uORB messages, generated interfaces, or message translation. scope:middleware DDS, ROS 2, Cyphal/UAVCAN, zenoh, or bridge layers. labels Jun 17, 2026
Comment thread msg/versioned/SetpointConfig.msg
@bkueng bkueng changed the title feat: external modes setpoint types & reliability feat(commander): external modes setpoint types & reliability Jun 18, 2026
@github-actions github-actions Bot added the kind:feature Request or change that adds new functionality. label Jun 18, 2026
@bkueng bkueng force-pushed the external_modes_setpoint_types branch from 436b382 to 1ec77b1 Compare June 19, 2026 08:03
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

💡 Commit messages could be improved

Not blocking, but these commit messages could use some cleanup.

Commit Message Suggestion
545b14f329 chore: use setpoint_config in mc_raptor and mc_nn_control Missing conventional commit format (e.g. "feat(ekf2): add something")

See the commit message convention for details.


This comment will be automatically removed once the issues are resolved.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🔎 FLASH Analysis

px4_fmu-v5x [Total VM Diff: 880 byte (0.04 %)]
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +872  +0.0%    +872    .text
    +0.1%    +196  +0.1%    +196    [section .text]
    +5.3%    +188  +5.3%    +188    UxrceddsClient::run()
    [NEW]    +172  [NEW]    +172    ucdr_serialize_setpoint_config_reply()
    [NEW]    +168  [NEW]    +168    mode_util::getControlMode()
    [NEW]    +156  [NEW]    +156    ucdr_serialize_config_overrides()
     +76%    +104   +76%    +104    ModeManagement::checkConfigControlSetpointUpdates()
    +0.5%     +92  +0.5%     +92    uORB::compressed_fields
   -99.5%     +78 -99.5%     +78    [52 Others]
    [NEW]     +70  [NEW]     +70    ModeManagement::getSetpointType()
     +32%     +56   +32%     +56    ModeManagement::ModeManagement()
    [NEW]     +56  [NEW]     +56    mode_util::isSetpointTypeValid()
     +15%     +40   +15%     +40    mode_util::getVehicleControlMode()
    +1.6%     +20  +1.6%     +20    Commander::dataLinkCheck()
     +21%     +16   +21%     +16    ModeManagement::~ModeManagement()
     +13%     +16   +13%     +16    RtlDirect::on_active()
    [DEL]     -16  [DEL]     -16    __orb_config_control_setpoints
    -9.2%     -52  -9.2%     -52    Commander::control_status_leds()
   -17.7%     -56 -17.7%     -56    ucdr_serialize_vehicle_control_mode()
    [DEL]     -72  [DEL]     -72    Modes::Mode::Mode()
    [DEL]    -156  [DEL]    -156    ModeManagement::updateControlMode()
    -2.5%    -204  -2.5%    -204    on_topic_update()
  +0.1%      +8  +0.1%      +8    .ramfunc
    +1.2%      +4  +1.2%      +4    Ekf::measurementUpdate()
     +20%      +4   +20%      +4    get_orb_meta()
     +14%      +1   +14%      +1    __perf_count_veneer
   -12.5%      -1 -12.5%      -1    __stm32_transmit.isra.0_veneer
  +0.1% +1.47Ki  [ = ]       0    .debug_abbrev
  +0.0%     +80  [ = ]       0    .debug_aranges
  +0.0%    +168  [ = ]       0    .debug_frame
  +0.1% +17.5Ki  [ = ]       0    .debug_info
  +0.0% +1.84Ki  [ = ]       0    .debug_line
    +100%      +1  [ = ]       0    [Unmapped]
    +0.0% +1.84Ki  [ = ]       0    [section .debug_line]
  +0.0%    +741  [ = ]       0    .debug_loclists
  -0.0%     -13  [ = ]       0    .debug_rnglists
    +200%      +2  [ = ]       0    [Unmapped]
    -0.0%     -15  [ = ]       0    [section .debug_rnglists]
  +0.1% +2.74Ki  [ = ]       0    .debug_str
  -0.4%      -1  [ = ]       0    .shstrtab
  +0.0%    +225  [ = ]       0    .strtab
    [DEL]     -11  [ = ]       0    CSWTCH.795
    [NEW]     +11  [ = ]       0    CSWTCH.796
    [NEW]     +39  [ = ]       0    ModeManagement::getSetpointType()
    +2.0%      +1  [ = ]       0    ModeManagement::update()
    [DEL]     -66  [ = ]       0    ModeManagement::updateControlMode()
    [DEL]     -38  [ = ]       0    Modes::Mode::Mode()
    +0.1%     +23  [ = ]       0    [section .strtab]
   -18.0%     -16  [ = ]       0    ___ZN7sensors22VehicleAngularVelocity21FilterAngularVelocityEiPfi_veneer
    [DEL]     -31  [ = ]       0    __orb_config_control_setpoints
    [NEW]     +31  [ = ]       0    __orb_config_overrides_confirm
    [NEW]     +22  [ = ]       0    __orb_setpoint_config
    [NEW]     +28  [ = ]       0    __orb_setpoint_config_reply
    [DEL]     -44  [ = ]       0    __orb_vehicle_angular_acceleration_setpoint
     +62%     +16  [ = ]       0    __perf_set_elapsed_veneer
    [NEW]     +74  [ = ]       0    mode_util::getControlMode()
     +20%     +18  [ = ]       0    mode_util::getVehicleControlMode()
    [NEW]     +55  [ = ]       0    mode_util::isSetpointTypeValid()
    [NEW]     +54  [ = ]       0    ucdr_serialize_config_overrides()
    [NEW]     +59  [ = ]       0    ucdr_serialize_setpoint_config_reply()
  +0.0%    +224  [ = ]       0    .symtab
    [DEL]     -32  [ = ]       0    CSWTCH.795
    [NEW]     +32  [ = ]       0    CSWTCH.796
    +100%     +16  [ = ]       0    Commander::checkWorkerThread()
    +3.6%     +16  [ = ]       0    Commander::handle_command()
   -33.3%     -16  [ = ]       0    Commander::updateTunes()
   -20.0%     -16  [ = ]       0    HomePosition::update()
    +100%     +16  [ = ]       0    ModeExecutors::hasFreeExecutors()
    +100%     +16  [ = ]       0    ModeExecutors::valid()
   -50.0%     -16  [ = ]       0    ModeManagement::currentModeAcceptsOffboardSetpoints()
    [NEW]     +32  [ = ]       0    ModeManagement::getSetpointType()
   -33.3%     -16  [ = ]       0    ModeManagement::onDisarm()
    +100%     +16  [ = ]       0    ModeManagement::printStatus()
    [DEL]     -48  [ = ]       0    ModeManagement::updateControlMode()
    [DEL]     -64  [ = ]       0    Modes::Mode::Mode()
     +33%     +32  [ = ]       0    RcvTopicsPubs::init()
    +100%     +16  [ = ]       0    RtlDirect::on_active()
   -16.7%     -16  [ = ]       0    RtlDirect::set_rtl_item()
   -58.5%    +272  [ = ]       0    [19 Others]
    +0.3%     +32  [ = ]       0    [section .symtab]
   -40.0%     -32  [ = ]       0    ___ZN7sensors22VehicleAngularVelocity21FilterAngularVelocityEiPfi_veneer
   -25.0%     -16  [ = ]       0    __net_unlock_veneer
   +39% +3.14Ki  [ = ]       0    [Unmapped]
  +0.1% +29.0Ki  +0.0%    +880    TOTAL

px4_fmu-v6x [Total VM Diff: 848 byte (0.04 %)]
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +848  +0.0%    +848    .text
    +5.3%    +188  +5.3%    +188    UxrceddsClient::run()
    +0.1%    +172  +0.1%    +172    [section .text]
    [NEW]    +172  [NEW]    +172    ucdr_serialize_setpoint_config_reply()
    [NEW]    +168  [NEW]    +168    mode_util::getControlMode()
    [NEW]    +156  [NEW]    +156    ucdr_serialize_config_overrides()
     +76%    +104   +76%    +104    ModeManagement::checkConfigControlSetpointUpdates()
    +0.5%     +92  +0.5%     +92    uORB::compressed_fields
   -99.5%     +78 -99.5%     +78    [50 Others]
    [NEW]     +70  [NEW]     +70    ModeManagement::getSetpointType()
     +32%     +56   +32%     +56    ModeManagement::ModeManagement()
    [NEW]     +56  [NEW]     +56    mode_util::isSetpointTypeValid()
     +15%     +40   +15%     +40    mode_util::getVehicleControlMode()
    +1.6%     +20  +1.6%     +20    Commander::dataLinkCheck()
     +21%     +16   +21%     +16    ModeManagement::~ModeManagement()
     +13%     +16   +13%     +16    RtlDirect::on_active()
    [DEL]     -16  [DEL]     -16    __orb_config_control_setpoints
    -9.2%     -52  -9.2%     -52    Commander::control_status_leds()
   -17.7%     -56 -17.7%     -56    ucdr_serialize_vehicle_control_mode()
    [DEL]     -72  [DEL]     -72    Modes::Mode::Mode()
    [DEL]    -156  [DEL]    -156    ModeManagement::updateControlMode()
    -2.5%    -204  -2.5%    -204    on_topic_update()
  +0.1% +1.47Ki  [ = ]       0    .debug_abbrev
  +0.0%     +80  [ = ]       0    .debug_aranges
  +0.0%    +168  [ = ]       0    .debug_frame
  +0.1% +17.4Ki  [ = ]       0    .debug_info
  +0.0% +1.84Ki  [ = ]       0    .debug_line
    [DEL]      -6  [ = ]       0    [Unmapped]
    +0.0% +1.85Ki  [ = ]       0    [section .debug_line]
  +0.0%    +875  [ = ]       0    .debug_loclists
  -0.0%     -15  [ = ]       0    .debug_rnglists
  +0.1% +2.74Ki  [ = ]       0    .debug_str
  +1.3%      +3  [ = ]       0    .shstrtab
  +0.0%    +225  [ = ]       0    .strtab
    [DEL]     -11  [ = ]       0    CSWTCH.795
    [NEW]     +11  [ = ]       0    CSWTCH.796
    [NEW]     +39  [ = ]       0    ModeManagement::getSetpointType()
    +2.0%      +1  [ = ]       0    ModeManagement::update()
    [DEL]     -66  [ = ]       0    ModeManagement::updateControlMode()
    [DEL]     -38  [ = ]       0    Modes::Mode::Mode()
    +0.1%     +23  [ = ]       0    [section .strtab]
    [DEL]     -31  [ = ]       0    __orb_config_control_setpoints
    [NEW]     +31  [ = ]       0    __orb_config_overrides_confirm
    [NEW]     +22  [ = ]       0    __orb_setpoint_config
    [NEW]     +28  [ = ]       0    __orb_setpoint_config_reply
    [DEL]     -44  [ = ]       0    __orb_vehicle_angular_acceleration_setpoint
    [NEW]     +74  [ = ]       0    mode_util::getControlMode()
     +20%     +18  [ = ]       0    mode_util::getVehicleControlMode()
    [NEW]     +55  [ = ]       0    mode_util::isSetpointTypeValid()
    [NEW]     +54  [ = ]       0    ucdr_serialize_config_overrides()
    [NEW]     +59  [ = ]       0    ucdr_serialize_setpoint_config_reply()
  +0.0%    +224  [ = ]       0    .symtab
    [DEL]     -32  [ = ]       0    CSWTCH.795
    [NEW]     +32  [ = ]       0    CSWTCH.796
    +100%     +16  [ = ]       0    Commander::checkWorkerThread()
    +3.6%     +16  [ = ]       0    Commander::handle_command()
   -33.3%     -16  [ = ]       0    Commander::updateTunes()
   -20.0%     -16  [ = ]       0    HomePosition::update()
    +100%     +16  [ = ]       0    ModeExecutors::hasFreeExecutors()
    +100%     +16  [ = ]       0    ModeExecutors::valid()
   -50.0%     -16  [ = ]       0    ModeManagement::currentModeAcceptsOffboardSetpoints()
    [NEW]     +32  [ = ]       0    ModeManagement::getSetpointType()
   -33.3%     -16  [ = ]       0    ModeManagement::onDisarm()
    +100%     +16  [ = ]       0    ModeManagement::printStatus()
    [DEL]     -48  [ = ]       0    ModeManagement::updateControlMode()
    [DEL]     -64  [ = ]       0    Modes::Mode::Mode()
    +100%     +16  [ = ]       0    RtlDirect::on_active()
   -16.7%     -16  [ = ]       0    RtlDirect::set_rtl_item()
   -50.0%    +176  [ = ]       0    [10 Others]
    +0.6%     +64  [ = ]       0    [section .symtab]
    [DEL]     -32  [ = ]       0    __orb_config_control_setpoints
    [NEW]     +32  [ = ]       0    __orb_config_overrides_confirm
    [NEW]     +48  [ = ]       0    __orb_setpoint_config
   +71% +3.17Ki  [ = ]       0    [Unmapped]
  +0.1% +29.0Ki  +0.0%    +848    TOTAL

Updated: 2026-06-30T08:30:59

@azerupi azerupi left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks good to me

@beniaminopozzan

Copy link
Copy Markdown
Member

@bkueng

The cleanest solution would be to use reliable transfer for these topics.
I tried that in the past and it resulted in severe topic drops for all telemetry messages, making it unusable.

would you consider having different QoS for different topics?

Comment thread src/modules/commander/ModeUtil/setpoint_types.cpp
Comment thread src/modules/commander/ModeUtil/control_mode.cpp
@bkueng

bkueng commented Jun 29, 2026

Copy link
Copy Markdown
Member Author

would you consider having different QoS for different topics?

That is what I tested, only setting some topics as reliable, but it affected all other topics too.

bkueng added 3 commits June 30, 2026 09:54
Allows an external mode to check if the request got processed
Important for external modes in case a topic sample gets dropped.
@bkueng bkueng force-pushed the external_modes_setpoint_types branch from 1ec77b1 to 48e0d07 Compare June 30, 2026 07:55
bkueng added 4 commits June 30, 2026 10:24
Switches from using VehicleControlMode to a specific setpoint type message
with reply.
Reasons:
- in case a VehicleControlMode was dropped (e.g. when the mode switched
  setpoint type), no confirmation was returned, and resulting in wrong
  controller flags.
- cleaner interface separation: external modes do not need to configure
  (or know) which controller to run for a certain setpoint
- allows for external modes to check for compatibility: e.g. a mode using
  fixed-wing setpoint types can now be rejected on a multicopter.
- allows for further extensions, like a setpoint timeout

This makes it a bit more effort to add a new setpoint type. Specifically,
setpoint_types.cpp needs to be extended when adding a new setpoint message.

PX4 internal modes also make use of the setpoint types. The information
flow is:
nav_state -> setpoint type -> vehicle control mode flags

It also adds a timeout to the setpoint config, but is not implemented
yet.

This changes the interface for external modes and thus the compatibility
version is increased.
@bkueng bkueng force-pushed the external_modes_setpoint_types branch from 48e0d07 to df468e7 Compare June 30, 2026 08:25

@mahima-yoga mahima-yoga left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks!

@bkueng

bkueng commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

@mrpollo do you want to hold off with merging this?
We also tested this on a Skynode in SIH with some of our modes.

@mahima-yoga

mahima-yoga commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Since it's ready to be merged I wouldn't hold off since it's a really good improvement and also solves some sporadic issues with setpoint reliability. @mrpollo - would appreciate if this could be in the 1.18 release

@mrpollo

mrpollo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

I think this is fine to come in now for v1.18, the only thing I am now thinking is the Test Team doesn't currently have any test cards that include a companion computer and code running using the ROS 2 interface, we should likely have a test that does, even if its just a simple behavior API check that can be verified with a log. If anyone wants to help me describe how that would work I would make sure you get a proper dinner on me ;)

@mrpollo mrpollo merged commit 5d2cec9 into main Jul 3, 2026
76 of 77 checks passed
@mrpollo mrpollo deleted the external_modes_setpoint_types branch July 3, 2026 19:33
@mahima-yoga

Copy link
Copy Markdown
Contributor

@mrpollo sure! Happy to help

@bkueng

bkueng commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

Thanks everyone.

I can also help. Probably the simplest is to run the goto example: https://github.com/Auterion/px4-ros2-interface-lib/tree/main/examples/cpp/modes/goto.
It can be started from any location and it flies a fixed pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind:feature Request or change that adds new functionality. scope:commander Arming, modes, failsafe, health checks, or vehicle state. scope:control Rate, attitude, position, allocation, or actuator control. scope:middleware DDS, ROS 2, Cyphal/UAVCAN, zenoh, or bridge layers. scope:navigation Missions, RTL, geofence, takeoff, landing, or navigator behavior. scope:offboard Offboard mode, external setpoints, companion-computer control, or offboard failsafe behavior. scope:uorb uORB messages, generated interfaces, or message translation. vehicle:copter Copter-specific behavior. vehicle:fixed-wing Fixed-wing-specific behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants