Skip to content

Stop sensor subscribe-check timer once subscribed (fix #23 rmw_zenoh ERROR spam)#24

Merged
rolker merged 3 commits into
jazzyfrom
feature/issue-23
May 28, 2026
Merged

Stop sensor subscribe-check timer once subscribed (fix #23 rmw_zenoh ERROR spam)#24
rolker merged 3 commits into
jazzyfrom
feature/issue-23

Conversation

@rolker

@rolker rolker commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

SensorBase::subscribeCheck() was written for ROS 1's one-shot ros::Timer, but the ROS 2 port uses rclcpp::create_wall_timer — which always repeats (create_timer.hpp only takes autostart; no one-shot option exists in rclcpp). The original comment // subscribed, so bail out before setting a new timer describes semantics the new timer no longer has, so once a sensor subscribed, the 1 s check timer kept firing and subscribe() recreated subs_.imu / subs_.navsat_fix / etc. every tick. Under rmw_zenoh_cpp the per-second teardown raced in-flight samples, producing the sporadic ERROR logs reported in #23:

[mru_transform_node-1] [ERROR] [rmw_zenoh_cpp]: SubscriberCallback triggered over 0/bizzy/mavros/imu/data/sensor_msgs::msg::dds_::Imu_/RIHS01_…

The defect was latent since the ROS 2 port; the previous DDS RMW didn't log the teardown race, so it only became visible after the late-Apr-2026 Zenoh migration.

Changes

  • SensorBase::subscribeCheck() (mru_transform/include/mru_transform/sensor.hpp): restructured into early-returns on the not-ready paths (the single repeating constructor timer keeps polling) and subscribe_check_timer_->cancel() once subscribed. Cancelling a timer inside its own callback is the standard rclcpp one-shot idiom. One fix in the base covers all three sensor types.
  • subscribe() guards in orientation_sensor.cpp, position_sensor.cpp, velocity_sensor.cpp: early-return true if any of that sensor's subs_ members is already set. Defense-in-depth — with the timer cancel, subscribe() is normally never re-entered, but the guard prevents any future regression from tearing down a live subscription.
  • New regression test test/test_subscribe_once.cpp: drives a real OrientationSensor with a live publisher on the configured topic, spins past several timer periods, and asserts subscribe() runs exactly once and the check timer is cancelled. Verified to fail on the pre-fix code (subscribe call count climbs ~1 Hz) and pass after the fix.

Behavior note (intentional)

This restores the original "subscribe once to the first supported type, then stop" semantics. A topic publisher that later switches to a different supported type (e.g. ImuQuaternionStamped) will not be re-evaluated. That matches the ROS 1 behavior and the existing design; if dynamic type-switching on a live topic is ever wanted, please open a separate issue.

Test plan

  • colcon build (worktree): mru_transform builds cleanly.
  • colcon test: 9 tests, 0 failures (including the new test_subscribe_once).
  • Regression test verified to fail on the pre-fix code (stashed sensor.hpp revert) and pass with the fix restored.
  • Field validation: confirm the SubscriberCallback triggered over … ERROR spam stops in a fresh run of mru_transform_node against /bizzy/mavros/imu/data under rmw_zenoh.

Closes #23


Authored-By: Claude Code Agent
Model: Claude Opus 4.7 (1M context)

Claude Code Agent added 3 commits May 27, 2026 19:53
SensorBase::subscribeCheck() was written for a ROS 1 one-shot timer, but
the ROS 2 port uses rclcpp::create_wall_timer, which always repeats. Once
a sensor subscribed, the 1 s check timer was never cancelled and kept
firing, re-running subscribe() every tick and recreating the live
subscription. Under rmw_zenoh the per-second teardown raced in-flight
samples, producing "SubscriberCallback triggered over ..." ERROR spam.

- subscribeCheck() now early-returns on the not-ready paths (the single
  repeating constructor timer keeps polling) and cancels the timer once
  subscribed, restoring one-shot semantics in one place for all three
  sensor types.
- Add an already-subscribed guard to each subscribe() override as
  defense-in-depth so a live subscription is never torn down/recreated.
- Add test_subscribe_once: drives a sensor with a live publisher and
  asserts subscribe() runs exactly once and the check timer is cancelled
  (verified to fail before this fix).

Refs #23
Copilot AI review requested due to automatic review settings May 28, 2026 03:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes issue #23 by restoring subscribe-once behavior for sensor topic detection in the ROS 2 port, preventing repeated subscription teardown/recreation and the resulting rmw_zenoh_cpp error spam.

Changes:

  • Cancels SensorBase’s polling timer after a successful subscription while keeping retry polling for unknown/unsupported topics.
  • Adds already-subscribed guards to orientation, position, and velocity sensor subscription methods.
  • Adds a regression test that verifies subscribe() runs once and the check timer stops.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
mru_transform/include/mru_transform/sensor.hpp Stops the repeating subscribe-check timer after successful subscription.
mru_transform/src/orientation_sensor.cpp Avoids recreating an existing orientation subscription.
mru_transform/src/position_sensor.cpp Avoids recreating an existing position subscription.
mru_transform/src/velocity_sensor.cpp Avoids recreating an existing velocity subscription.
mru_transform/test/test_subscribe_once.cpp Adds regression coverage for subscribe-once timer behavior.
mru_transform/CMakeLists.txt Registers and links the new regression test.
.agent/work-plans/issue-23/progress.md Adds work-plan/progress documentation for issue #23.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@rolker
rolker merged commit 76b33f0 into jazzy May 28, 2026
1 check passed
@rolker
rolker deleted the feature/issue-23 branch May 28, 2026 03:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

subscribeCheck timer re-subscribes every second (ROS 1 one-shot semantics lost in ROS 2 port)

2 participants