ROS 2 topic statistics: read age and period at the subscriber boundary

ROS 2 subscription statistics can help separate stale input from uneven arrival spacing, provided the two measurements and their clocks are identified first. Message age measures a timestamp difference; message period measures the spacing between observations at the subscriber’s collector. Finding which network, publisher or executor operation caused a delay takes further tracing.

Consider a controller receiving updates regularly while acting on old information. A steady received period can coexist with elevated age. Uneven received periods, in turn, can come from buffering and subscriber scheduling as well as from an irregular publisher. Treat both patterns as hypotheses to investigate.

Enable topic statistics on the one subscription you want to measure

The official Jazzy tutorial source enables statistics through the subscription options, then passes those options to create_subscription. Inside an existing C++ rclcpp node, adapt the following fragment to your message type and callback:

rclcpp::SubscriptionOptions options;
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
options.topic_stats_options.publish_period = std::chrono::seconds(1);
options.topic_stats_options.publish_topic = "/controller_input_statistics";
subscription_ = this->create_subscription<MessageT>(
    "input", rclcpp::QoS(10), callback, options);

The one-second setting is the example’s collection/publication window. After rebuilding and starting your node, inspect the selected statistics topic with ros2 topic echo /controller_input_statistics. Statistics start only once the options variable is passed to the intended subscription. The fragment matches the documentation and pinned subscription-options header; compile it against your own distribution. The metrics probe that one subscription rather than the whole system.

Received age and received period answer different questions

The official Jazzy topic-statistics overview describes average, minimum, maximum, standard deviation and sample count for age and period. Measurements use milliseconds, and the configured statistics publication period also sets the collection-window period. The default described there is one second; set your control application’s acceptance limit separately.

MeasurementQuestion it can supportEvidence still needed
Received ageHow far apart are the collector observation time and its selected source timestamp?Timestamp origin, clock relationship and valid sample count
Received periodHow uneven is the spacing between successive collector observations?Publisher timing and downstream scheduling evidence
Window summaryDid this interval contain unusually large or variable observations?Individual events and the application’s timing budget

Record both metrics for the same subscription and collection interval. Keep the metric unit and sample count with every exported value. A mean without the corresponding maximum, spread and population can hide an intermittent problem or make an empty interval look healthy.

Identify the age timestamp in the installed version

Version checking matters here. The Jazzy explanation discusses a populated message header, but the examined Jazzy-branch rclcpp subscription-statistics implementation passes rmw_message_info_t to non-templated collector aliases. The corresponding age collector subtracts source_timestamp from the supplied observation time when both are nonzero. Its older, deprecated templated path instead reads header.stamp.

These are snapshots of specific branches; inspect your robot’s installed versions and call path before treating an age value as sensor acquisition age. A middleware source timestamp and an image exposure timestamp can describe different events. Also verify that the two clocks have a meaningful relationship; an unexplained negative age should trigger a clock and timestamp investigation.

Missing valid timestamps prevent that collector from accepting an age sample. That gap reflects measurement availability; keep missing values out of the average rather than filling them with zero, and expect the age and period populations to differ.

A three-arrival example explains the sample counts

Take synthetic collector observations at 100, 120 and 160 ms on one shared clock, with selected source timestamps at 60, 65 and 70 ms. These numbers illustrate the collector arithmetic.

Observation time Selected source timestamp Age Period since previous observation
100 ms 60 ms 40 ms First observation
120 ms 65 ms 55 ms 20 ms
160 ms 70 ms 90 ms 40 ms

The three age samples average about 61.67 ms, with a 90 ms maximum. Only two periods exist, averaging 30 ms. If the middle source timestamp is zero in the examined age-collector path, that age is omitted: the remaining two ages average 65 ms, while the two periods remain 20 and 40 ms. A changing age sample count can therefore leave the period population unchanged. Investigate the missing timestamp before substituting a zero-delay sample.

Use the window to choose the next observation

The examined period collector uses successive supplied observation times and ignores the message-info argument. It needs a previous observation before it can produce a period, and it measures arrival spacing at the subscriber rather than the publisher’s emission schedule.

For a proposed diagnostic capture, preserve the subscription identity, software versions, timestamp source, collection interval, both sample counts and the application’s age and gap limits. If age rises while period remains stable, investigate where information becomes old. If period varies, compare producer emission events with subscriber readiness and execution before assigning responsibility. The executor and callback-group guide explains the scheduling questions that need finer evidence than this aggregate view.

A small maximum in one collected window falls short of a worst-case deadline bound, and dropped-message counts and full event history come from other tools. When your next decision depends on causality, capture a trace or message-level record alongside these statistics.