Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

Package symbol

rmw_stats_shim package from graph_monitor repo

rmw_stats_shim rosgraph_monitor rosgraph_monitor_msgs rosgraph_monitor_test

ROS Distro
lyrical

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

Package symbol

rmw_stats_shim package from graph_monitor repo

rmw_stats_shim rosgraph_monitor rosgraph_monitor_msgs rosgraph_monitor_test

ROS Distro
rolling

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange

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

Package Summary

Version 0.3.2
License Apache License 2.0
Build type AMENT_CMAKE
Use RECOMMENDED

Repository Summary

Checkout URI https://github.com/ros-tooling/graph-monitor.git
VCS Type git
VCS Version main
Last Updated 2026-11-02
Dev Status DEVELOPED
Released RELEASED
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Package Description

Partial RMW shim library to instrument RMW API calls

Maintainers

  • Emerson Knapp

Authors

  • Emerson Knapp on behalf of Bonsai Robotics

RMW Stats Shim

Depends on a modified version of rmw_implementation to provide topic statistics calculation within the RMW layer of each node, without having to instrument application code.

This component

  • Wraps & intercepts some RMW API calls
  • Calculates “published period” statistics for every Publisher
  • Calculates “received period” statistics for every Subscription
  • Calculates “take age” statistics for every Subscription
    • This is the different between publish system timestamp and the time at which rmw_take is called, so is the sum of network latency plus executor latency
  • Creates a /topic_statistics Publisher for every Node and publishes to it periodically about the statistics from within the node

Key points:

  • Requires no subscriptions, no extra copies, to do statistics on all topics
  • Requires no modification to application code to use

Configuration

Set the following environment variables before launching a node to configure topic statistics

  • Required: RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
  • ROS_TOPIC_STATISTICS_WINDOW_SIZE - how many messages to use in rolling buffer for stats (stores only timestamp information, not contents data)
    • Default: 50
  • ROS_TOPIC_STATISTICS_TOPIC_NAME - name of the topic to publish statistics on
    • Default: /topic_statistics
  • ROS_TOPIC_STATISTICS_PUBLISH_PERIOD - Interval in seconds at which to periodically publish stats
    • Default: 1.0

Usage

colcon build --packages-select rmw_implementation rmw_stats_shim
source install/setup.bash
export RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim
# run any ROS 2 node/launch/etc

CHANGELOG

Changelog for package rmw_stats_shim

0.3.2 (2026-11-02)

  • fix(rmw_stats_shim): populate TopicStatistic min and max (#79) Fixes #78. [EndpointStatistics::periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} set only [mean]{.title-ref}, so [min]{.title-ref} and [max]{.title-ref} in every [TopicStatistic]{.title-ref} stayed zero. [RollingMeanAccumulator]{.title-ref} had nothing to fill them from, since it only kept a running sum. This adds [getRollingMin()]{.title-ref} and [getRollingMax()]{.title-ref} to [RollingMeanAccumulator]{.title-ref}. They scan the values still in the window, so they cover the same [ROS_TOPIC_STATISTICS_WINDOW_SIZE]{.title-ref} samples as the mean, and values that leave the window drop out of both. [periodMsg()]{.title-ref} and [ageMsg()]{.title-ref} now fill [min]{.title-ref} and [max]{.title-ref} from them. The scan is linear in the window size and runs once per published statistic, not per message. Tests:

    - [test_rolling_mean_accumulator.cpp]{.title-ref} checks min and max on a partly filled window and after the window wraps.

    - [EndpointStatistics.MessagesReportWindowMinAndMax]{.title-ref} in [test_stat_collector.cpp]{.title-ref} feeds periods of 10, 20 and 6 ms and ages of 7, 3 and 15 ms, then checks [mean]{.title-ref}, [min]{.title-ref} and [max]{.title-ref} in both messages. Without the change in [stat_collector.cpp]{.title-ref} it fails with [min]{.title-ref} and [max]{.title-ref} at 0. Built with colcon on Jazzy ([rosgraph_monitor_msgs]{.title-ref} and [rmw_stats_shim]{.title-ref} with [BUILD_TESTING=ON]{.title-ref}); [test_rolling_mean_accumulator]{.title-ref}, [test_stat_collector]{.title-ref} and [test_timer]{.title-ref} pass, and the pre-commit hooks pass on the changed files. ---------

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76) Follows up #75. [StatCollector]{.title-ref} is a process-wide singleton. Its maps ([nodes_]{.title-ref}, [stat_publishers_]{.title-ref}, [publishers_]{.title-ref}, [subscriptions_]{.title-ref}) were accessed with no locking from three kinds of thread:

    - DDS and executor threads: [onPublish]{.title-ref}/[onReceive]{.title-ref}, called from the wrapped [rmw_publish]{.title-ref}/[rmw_take*]{.title-ref}.

    • Any thread creating or destroying entities: [add*]{.title-ref}/[remove*]{.title-ref}.

    - The stats [Timer]{.title-ref} thread: [publishStatistics]{.title-ref}. A rehash during an insert while another thread ran [find]{.title-ref} caused a SIGSEGV in [StatCollector::onReceive]{.title-ref} ([stat_function.h]{.title-ref}/[find]{.title-ref} frame) during test teardown in a downstream CI. To solve it, add mutex protection for this state. Use separate mutexes for nodes vs endpoints. ## Performance This adds one uncontended mutex lock per publish/take in every process with the shim loaded. The downstream project plans to benchmark it.

  • fix(rmw_stats_shim): make Timer::stop idempotent (#75) ## Problem Since #50, [~StatCollector]{.title-ref} calls [timer_->stop()]{.title-ref} explicitly. Then [~optional<Timer>]{.title-ref} runs [~Timer]{.title-ref}, which calls [stop()]{.title-ref} again. The second call does [thread_.join()]{.title-ref} on an empty [std::thread]{.title-ref}, which throws [std::system_error]{.title-ref} ([Invalid argument]{.title-ref}) during static destruction. As a result, in 0.3.0 every process that loads the shim ([RMW_IMPLEMENTATION_WRAPPER=rmw_stats_shim]{.title-ref}) aborts on a normal exit: ` terminate called after throwing an instance of 'std::system_error' what(): Invalid argument ... Timer::stop timer.cpp:43 ... Timer::~Timer timer.cpp:16 ... StatCollector::~StatCollector stat_collector.cpp:309[ This showed up as 19 failing test executables downstream when we bumped to 0.3.0: the tests passed, but every process SIGABRTed at exit. ## Fix Guard the join with `joinable()]{.title-ref}, matching the header's documented contract for [stop()]{.title-ref} ("No-op if not running"). ## Tests Adds [rmw_stats_shim/test/test_timer.cpp]{.title-ref}, the package's first tests: stop without start, stop twice, destroy after stop, restart after stop. They fail on [main]{.title-ref} and pass with this change (built and run on Jazzy). ## Not in this PR [StatCollector]{.title-ref}'s [nodes_]{.title-ref}, [publishers_]{.title-ref} and [subscriptions_]{.title-ref} maps are still accessed without a lock from DDS listener threads ([onReceive]{.title-ref}/[onPublish]{.title-ref}), the main thread (endpoint add/remove) and the stats timer thread. We've seen a SIGSEGV in [onReceive]{.title-ref} from this. I'll follow up separately.

  • fix(rmw_stats_shim): lock StatCollector endpoint maps (#76)

File truncated at 100 lines see the full file

Package Dependencies

System Dependencies

No direct system dependencies.

Dependant Packages

No known dependants.

Launch files

No launch files found

Messages

No message files found.

Services

No service files found

Plugins

No plugins found.

Recent questions tagged rmw_stats_shim at Robotics Stack Exchange