37#ifndef REALTIME_TOOLS__REALTIME_PUBLISHER_HPP_
38#define REALTIME_TOOLS__REALTIME_PUBLISHER_HPP_
42#include <condition_variable>
49#include "rclcpp/create_publisher.hpp"
50#include "rclcpp/publisher.hpp"
54template <
class MessageT>
60 using PublisherSharedPtr =
typename rclcpp::Publisher<MessageT>::SharedPtr;
62 using PublishedType =
typename rclcpp::TypeAdapter<MessageT>::custom_type;
63 using ROSMessageType =
typename rclcpp::TypeAdapter<MessageT>::ros_message_type;
68 "This variable is deprecated, it is recommended to use the try_publish() method instead.")]]
73#pragma warning(disable : 4996)
75#pragma GCC diagnostic push
76#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
90 template <
typename NodeT>
92 NodeT && node,
const std::string & topic_name,
const rclcpp::QoS & qos,
93 const rclcpp::PublisherOptions & options = rclcpp::PublisherOptions())
96 return rclcpp::create_publisher<MessageT>(
97 std::forward<NodeT>(node), topic_name, qos, options);
112 initialize([&]() {
return publisher; });
118 RCLCPP_DEBUG(rclcpp::get_logger(
"realtime_tools"),
"Waiting for publishing thread to stop....");
120 while (is_running()) {
121 std::this_thread::sleep_for(std::chrono::microseconds(100));
124 rclcpp::get_logger(
"realtime_tools"),
"Publishing thread stopped, joining thread....");
125 if (thread_.joinable()) {
132#pragma GCC diagnostic pop
145 std::unique_lock<std::mutex>
lock(msg_mutex_);
146 keep_running_ =
false;
148 updated_cond_.notify_one();
160 "Use try_publish() method instead of this method. This method may be removed in future "
164 return turn_.load(std::memory_order_acquire) == State::REALTIME && msg_mutex_.try_lock();
173 std::unique_lock<std::mutex>
lock(msg_mutex_, std::try_to_lock);
188 std::unique_lock<std::mutex>
lock(msg_mutex_, std::try_to_lock);
191 std::unique_lock<std::mutex> scoped_lock(std::move(
lock));
194#pragma warning(disable : 4996)
196#pragma GCC diagnostic push
197#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
203#pragma GCC diagnostic pop
205 turn_.store(State::NON_REALTIME, std::memory_order_release);
207 updated_cond_.notify_one();
225 "Use try_publish() method instead of this method. This method may be removed in future "
240 "Use the try_publish() method to publish the message instead of using this method. This method "
241 "may be removed in future versions.")]]
244 turn_.store(State::NON_REALTIME, std::memory_order_release);
245#pragma GCC diagnostic push
246#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
248#pragma GCC diagnostic pop
258 "Use the try_publish() method to publish the message instead of using this method. This method "
259 "may be removed in future versions.")]]
270 "Use the try_publish() method to publish the message instead of using this method. This method "
271 "may be removed in future versions.")]]
275 updated_cond_.notify_one();
293 "This getter method will be removed. It is recommended to use the try_publish() instead of "
294 "accessing the msg_ variable.")]]
295 const MessageT & get_msg()
const
299#pragma warning(disable : 4996)
301#pragma GCC diagnostic push
302#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
308#pragma GCC diagnostic pop
320 const std::mutex &
get_mutex()
const {
return msg_mutex_; }
323 template <
typename PublisherCreator>
324 void initialize(PublisherCreator && creator)
326 publisher_ = creator();
328 keep_running_ =
true;
329 turn_ = State::LOOP_NOT_STARTED;
331 thread_ = std::thread(&RealtimePublisher::publishingLoop,
this);
336 while (!thread_.joinable() ||
337 turn_.load(std::memory_order_acquire) == State::LOOP_NOT_STARTED) {
338 std::this_thread::sleep_for(std::chrono::microseconds(100));
349 return turn_.load(std::memory_order_acquire) == State::REALTIME &&
lock.owns_lock();
356 bool is_running()
const {
return is_running_; }
369 void publishingLoop()
373 while (keep_running_) {
377 turn_.store(State::REALTIME, std::memory_order_release);
379 std::unique_lock<std::mutex> lock_(msg_mutex_);
380 updated_cond_.wait(lock_, [&] {
return turn_ == State::NON_REALTIME || !keep_running_; });
383#pragma warning(disable : 4996)
385#pragma GCC diagnostic push
386#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
392#pragma GCC diagnostic pop
398 publisher_->publish(outgoing);
404 PublisherSharedPtr publisher_;
405 std::atomic<bool> is_running_;
406 std::atomic<bool> keep_running_;
410 mutable std::mutex msg_mutex_;
411 std::condition_variable updated_cond_;
413 enum class State :
int { REALTIME, NON_REALTIME, LOOP_NOT_STARTED };
414 std::atomic<State> turn_;
417template <
class MessageT>
418using RealtimePublisherSharedPtr = std::shared_ptr<RealtimePublisher<MessageT>>;