Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro kilted showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro rolling showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro ardent showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro bouncy showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro crystal showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro eloquent showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro dashing showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro galactic showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro foxy showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro iron showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro lunar showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro jade showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro indigo showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro hydro showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro kinetic showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro melodic showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange

No version for distro noetic showing humble. Known supported distros are highlighted in the buttons above.

Package Summary

Version 0.6.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-07-30
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Gateway plugin that detects silent faults in the ROS 2 graph: QoS mismatches, topic-name typos, dead nodes, stale transforms, parameter drift, lifecycle expectations and pipeline timing budgets.

Maintainers

  • bburda

Authors

No additional authors.

ros2_medkit_graph_watchdog

Gateway plugin that detects silent faults in the ROS 2 graph: failures where every node is up, nothing logs an error, and the robot is still broken.

Detectors read the graph and raise faults through a ReportFault service client on the gateway node; the faults surface via FaultManager on the gateway /faults API.

This package carries the plugin skeleton, the central reliability gate that holds raises until the graph has quiesced, and two detectors, qos_mismatch and orphan. The remaining silent-fault classes land in follow-up changes, each against its own issue; their fault codes are already reserved in the frozen GRAPH_* namespace (see “Fault codes”).

Build

With the gateway built and sourced:

colcon build --packages-select ros2_medkit_graph_watchdog
colcon test --packages-select ros2_medkit_graph_watchdog && colcon test-result --verbose

Load into the gateway

ros2 run ros2_medkit_gateway gateway_node --ros-args \
  -p plugins:="[graph_watchdog]" \
  -p "plugins.graph_watchdog.path:=$(ros2 pkg prefix ros2_medkit_graph_watchdog)/lib/ros2_medkit_graph_watchdog/libros2_medkit_graph_watchdog.so"

Configuration (plugins.graph_watchdog.<key>)

Key Type Default Meaning
tick_interval_ms int 1000 Detector tick cadence.
warmup_cycles int 5 An entity must be continuously present for this many ticks before it arms. A mid-run restart re-warms it. Enforced centrally, see “Reliability (bringup-quiesce)” below.
prune_grace int 60 Default injected into every detector’s own config before configure(); a per-detector detectors.<id>.prune_grace overrides it. Used by detectors that keep per-key bookkeeping.
detectors.<id>.mode string | bool raise raise = push faults; advisory = observe, do not push; off = disabled. Bare off/no (YAML booleans) also disable; bare on/yes mean raise.
detectors.<id>.<field> any - Per-detector thresholds, passed to that detector’s configure().

Nested delivery. Keys are written dotted in YAML or --ros-args, and the gateway delivers them to the plugin as a nested object. A bare off is a YAML 1.1 boolean, so mode: off arrives as false, not the string "off"; both forms disable the detector.

Unknown keys are reported. Anything under detectors.<id> that the detector does not read produces one startup warning naming the key and listing the ones that exist, so a typo like allow_list: for allowlist: cannot silently do nothing. A typo in the detector id itself is warned about the same way, with the registered ids listed.

orphan keys

Key Type Default Meaning
mode string raise As above.
grace int 10 Consecutive sweeps a candidate pair must hold before it is reported. A staged bringup or a restart makes one side missing for a short time, which looks exactly like a typo until the other side appears.
max_edit_distance int 1 How many character edits the LEAF (the part after the last /) may differ by and still count as the same intended name. Values outside 1..8 keep the default: past a few edits a “near miss” starts matching unrelated topics.
namespace_edit_distance int 0 The same budget for the namespace, spent separately. 0 means the namespace must match to the character, which is what makes /robot1/scan and /robot2/scan two robots rather than a typo. Raise it to catch a misspelled namespace, and read the warning under the table first. Values outside 0..8 keep the default.
allowlist string[] [] Topic names never reported. Exact match only, never a prefix, so allowlisting /r1/scan does not also silence /r2/scan.

What this detector will not catch, on purpose. A pair whose names match once every run of digits is collapsed is treated as an enumeration of sensors, not a typo: /lidar_1 next to /lidar_2, each one-sided, is an ordinary state on a multi-sensor robot and reporting it would be a false alarm on every such machine. Collapsing runs rather than comparing character positions is what also covers /lidar_9 next to /lidar_10. The cost is that a typo which is a digit stops being reported. An appended digit is not that case: /scan1 collapses to /scan#, which is not /scan, so it is still reported.

A misspelled namespace is opt-in, and it can be expensive. /robott/scan against /robot/scan is one edit, but in the namespace, so by default it is not reported. Setting namespace_edit_distance: 1 reports it. Check the naming scheme before doing that: on a fleet named with letters, /amr_a and /amr_b are also one edit apart, and every robot in the fleet will be reported as a typo. A numbered fleet is safe, since /robot1 against /robot2 differs only in its numeric field and the rule above already spares it.

What it cannot catch at all. A namespace added or dropped by mistake, /scan against /robot/scan, is six edits apart, so no budget that is still specific will reach it. Do not rely on this detector for that class.

qos_mismatch keys

Key Type Default Meaning
mode string raise As above.
grace int 3 Consecutive ticks a topic must stay affected before it is reported. Endpoint discovery is not atomic, so a subscriber can be visible before a publisher’s QoS is, which reads as starvation for a tick or two.
allowlist string[] [] Subscriber FQNs never reported. Exact match only.

Where GRAPH_* faults hang

Every GRAPH_* fault is raised with source_id: graph_watchdog. That is an App the plugin publishes itself, from its own IntrospectionProvider, marked external: true. So:

  • GET /api/v1/apps/graph_watchdog/faults lists them.
  • GET /api/v1/components/<host>/faults lists them too, because the App is attached to the host Component and a Component resolves its fault scope through its child apps.

It has to be an entity the plugin owns. Scoping these faults to the host Component directly - the obvious choice - makes them reachable from no endpoint at all: collect_component_app_fqns only puts a Component’s own id in the scope set when external is true, and a runtime host Component built by HostInfoProvider never sets it. There is no server-level /faults/{code} route either, so the flat /faults list was the only place these faults existed.

File truncated at 100 lines see the full file

CHANGELOG
No CHANGELOG found.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged ros2_medkit_graph_watchdog at Robotics Stack Exchange