0
$\begingroup$

I'd like to do some work in a std::thread and then occasionally pass this data to the ROS thread for publishing or further processing. The only way I can see how to inject events with data into a nodes event loop is with a ROS message. Essentially I'm looking for the equivalent of the boost asio post method.

Some community packages like ros2_socketcan, have this pattern of needing a worker thread to do some external io, and then passing the results back into the ros2 context https://github.com/autowarefoundation/ros2_socketcan/tree/main

This particular package attempts to deal with this issue by sharing references to mutable objects between the two threads and then being careful, but this pattern is fragile at best, and prone to lifetime and other nuanced issues which may result in UB (of which there are a few in this particular package)

The alternative is to create a anonymous node in the worker thread and have it publish data back to the main node, but this seems excessive when all I want is a thread safe mechanism to invoke a callback on the run-loop of the main node.

Is there a better alternative?

$\endgroup$

1 Answer 1

0
$\begingroup$

I would use a timer callback (with multithreaded executor) for this, similar to this previous answer.

The callback can block indefinitely, so it can be used as the equivalent of a thread.

You will still need some thread synchronisation logic though.

$\endgroup$
2
  • $\begingroup$ Its not clear me me how I can use a periodic timer to send a notify to the ROS node. I could see how this might work with a single shot timer with a timeout of zero but ROS2 doesn't even support single shot timers $\endgroup$
    – user40668
    Commented May 6 at 0:54
  • $\begingroup$ Did you read the answer I linked to? The timer is not used as a timer, just as a means to run a callback, which either can block indefinitely (i.e. a while(rclcpp::ok()) { wait_for_work(time_out); }) or which can return every now and then but instantly is retriggerd as its period was lapsed. If it does not answer your question, please clarify in what way it is not applicable to your case. Re. the single shot timer: this is irrelevant in the context of this answer, but yes it exists in ROS 2: just add this->timer_->cancel() to the callback and it will not be retriggered unless reset(). $\endgroup$
    – JRTG
    Commented May 6 at 8:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.