Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_action_status_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_action_status_bridge
Generic drop-in bridge that turns terminal ROS 2 action goal states into
structured medkit faults. It watches the /<action>/_action/status
(action_msgs/msg/GoalStatusArray) topic that every action server
publishes, so it works across Nav2, MoveIt 2, ros2_control’s controller
actions, and any custom action with no per-project code.
Why this matters
For the core ROS 2 league the authoritative “the goal failed” verdict lives on
the action-result channel, not on /diagnostics or /rosout:
- Nav2
NavigateToPose->GoalStatus = ABORTED - MoveIt
MoveGroup->GoalStatus = ABORTED(withMoveItErrorCodein the result) - ros2_control controller actions -> aborted goals
Neither the diagnostic bridge nor the log bridge sees this. This bridge does, generically, by observing the goal-status topic.
What it does
- Discovers every action on the graph by scanning for
*/_action/statustopics (re-scanned on a timer to catch actions that appear later, and to drop actions that vanish, e.g. a Nav2 lifecycle deactivate or a one-shot node). -
ABORTED (6)-> fault (SEVERITY_ERRORby default). -
CANCELED (5)-> fault only ifcanceled_is_fault(off by default; cancel is usually intentional). When enabled it emits a_CANCELEDcode. -
SUCCEEDED (4)->PASSEDto heal the action’s fault code (if enabled). -
fault_codeis<PREFIX>_<ACTION>_ABORTED(or_CANCELED), e.g.ACTION_NAVIGATE_TO_POSE_ABORTED.source_idis the action server’s node FQN (resolved from the status topic’s publisher, e.g./bt_navigator), so the fault associates with that node’s SOVD entity; it falls back to the action name only if no publisher is visible.
Per-action state, not per-goal
The fault is a property of the action, not of an individual goal. On every
status message the whole GoalStatusArray is scanned for the net state:
- if any goal is
ABORTED(orCANCELEDwhencanceled_is_fault), the action is failed (order of goals in the array does not matter); - otherwise, if the array has terminal goals and none are failing, the action is healthy.
A fault is raised only on the healthy -> failed transition and healed only on
failed -> healthy. This means one failed goal cannot heal an action while
another goal is still failed, and a dropped terminal message cannot leave a
fault stuck. Per-goal dedup (keyed on goal_id:status) only suppresses
duplicate log lines; it never gates the transition.
Scope: the terminal verdict, not the reason
This bridge delivers the generic “it aborted” event. The action-specific
reason (e.g. MoveItErrorCode.val = -26 START_STATE_IN_COLLISION, Nav2
error_code on Iron/Jazzy) lives in the action result message and is a separate
enrichment concern (a future action-result reader using runtime message
introspection / dynmsg). Per-project plugins are only needed for human-readable
labels, not to surface the fault.
Run it
ros2 launch ros2_medkit_action_status_bridge action_status_bridge.launch.py
Configuration (config/action_status_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
aborted_severity |
2 (ERROR) |
severity of an aborted goal |
canceled_is_fault |
false |
treat CANCELED as a fault |
heal_on_succeeded |
true |
send PASSED on a successful goal |
rescan_period_sec |
2.0 |
how often to look for new actions |
code_prefix |
ACTION |
prefix for generated codes |
exclude_actions |
[] |
action-name substrings to skip |
include_only_actions |
[] |
if set, only watch these |
dedup_capacity |
4096 |
remembered goal/status log keys |
exclude_actions / include_only_actions match as unanchored substrings of
the fully-qualified action name (e.g. nav matches /navigate_to_pose). Use a
longer fragment (or the full name) for exact targeting.
aborted_severity, code_prefix and dedup_capacity are range-checked and
normalized at load (out-of-range severity clamps to ERROR, a non-snake-case
code_prefix is upper-snake-cased, a non-positive dedup_capacity falls back to
the default), with a warning.
Limitations
-
Flapping: a retry loop that issues a fresh
goal_ideach attempt does not re-raise while the action stays failed (only net-state changes transition), but a true flap (fail -> succeed -> fail) does produce one raise + heal per cycle. There is no per-code rate throttle in this bridge; lower noise via the FaultReporter local filter if needed. - No per-code throttle: every action-level transition is forwarded.
-
CANCELED heal semantics: with
canceled_is_fault, a canceled action heals on the next non-failing terminal (a later SUCCEEDED), or when the canceled goal ages out of the action server’s retained status array and a non-failed terminal remains. It is not healed by an explicit “uncancel” because none exists.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_action_status_bridge
Forthcoming
- Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see. - Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines. -
canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array. - Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
- Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.