I’m interested in best practices / techniques for providing additional data from a roboclaw serial interface (main battery voltage, temperature, etc) that is currently managed by a ros2 control hardware interface.
ros2_control currently calls roboclaw serial interface during read/write requests. This serial interface provides access to additional data that I would like to also publish to ROS2 (battery levels, current, temp, etc). Ideally, this additional data could be exposed for access by behavior management process, etc, and at a different frequency than the main control loop.
There are a few options:
Option 1: just read and publish the non-controls data during hardware_interface::read calls. Bad practice, this impacts both separation of concerns, overall readability, and potentially slows down the main control loop
Option 2: Extend hardware_interface’s underlying lifecycle node base class methods (on_activate, etc) for publishing this non-controls data via a timer. I am not sure how I feel about this, but it seems better than Option 1. Still seems to muddy the water between a specialized controls interface to hardware and other interfaces
Option 3: Independent ROS2 component provides both controls interface (via topics) and publishes additional data I would like ros2_control to have low-level, direct access to the hardware, so I’m not a fan of this approach either.
What do you all think? Is there a recommend design choice or precedent, probably something I’m not considering?
Thanks @christophfroehlich and @ottojo for the feedback. I think I had a fundamental misunderstanding about what a hardware interface actually does…
Here’s my understanding of the “best” approach:
Update interface to extract additional state information that I want to make available to controllers
Create a broadcaster/controller to publish this information to ROS
One of my pain points is that I really don’t want to have to read ALL states at the same rate. I.e., maybe I only want to read battery voltage once every 30 seconds. I can of course add some logic to the read() call to handle this, but curious if there are any mechanisms to provide the hardware_interface with needs to be read? I.e., a vector of strings for each state that’s needed (allowing each controller could drive its own rate). Any practical recommendations or things that I’m missing?
This really depends on how you access your data. You wrote that you use the serial interface? This limits you to a single hardware component, because afaik you cannot connect with two processes to the same serial without an additional layer in between. (Otherwise you could write two independent hardware components running on a different update rate).
Within one hardware component, there is no ros2_control-way in doing so. I’d suggest using the time and implement a logic to poll the housekeeping data only once in a while.