|  | 
|  | 1 | +// Copyright 2022 Carlos San Vicente | 
|  | 2 | +// Copyright 2016 Open Source Robotics Foundation, Inc. | 
|  | 3 | +// | 
|  | 4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | +// you may not use this file except in compliance with the License. | 
|  | 6 | +// You may obtain a copy of the License at | 
|  | 7 | +// | 
|  | 8 | +//     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | +// | 
|  | 10 | +// Unless required by applicable law or agreed to in writing, software | 
|  | 11 | +// distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | +// See the License for the specific language governing permissions and | 
|  | 14 | +// limitations under the License. | 
|  | 15 | + | 
|  | 16 | +#include <chrono> | 
|  | 17 | +#include <memory> | 
|  | 18 | +#include <string> | 
|  | 19 | + | 
|  | 20 | +#include "rclcpp/rclcpp.hpp" | 
|  | 21 | +#include "std_msgs/msg/string.hpp" | 
|  | 22 | + | 
|  | 23 | +using namespace std::chrono_literals; | 
|  | 24 | + | 
|  | 25 | +static_assert(std::atomic<std::uint32_t>::is_always_lock_free); | 
|  | 26 | + | 
|  | 27 | +class MinimalPublisher : public rclcpp::Node | 
|  | 28 | +{ | 
|  | 29 | +public: | 
|  | 30 | +  MinimalPublisher() | 
|  | 31 | +  : Node("minimal_publisher"), count_(0) | 
|  | 32 | +  { | 
|  | 33 | +    publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10); | 
|  | 34 | +    auto timer_callback = | 
|  | 35 | +      [this]() -> void { | 
|  | 36 | +        auto message = std_msgs::msg::String(); | 
|  | 37 | +        message.data = "Hello, world! " + std::to_string(this->count_++); | 
|  | 38 | +        RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); | 
|  | 39 | +        this->publisher_->publish(message); | 
|  | 40 | +      }; | 
|  | 41 | + | 
|  | 42 | +    realtime_callback_group_ = this->create_callback_group( | 
|  | 43 | +      rclcpp::CallbackGroupType::MutuallyExclusive, false); | 
|  | 44 | +    timer_ = this->create_wall_timer(500ms, timer_callback, realtime_callback_group_); | 
|  | 45 | + | 
|  | 46 | +    count_ = declare_parameter("count", 0); | 
|  | 47 | +    parameter_event_handler_ = std::make_shared<rclcpp::ParameterEventHandler>(this); | 
|  | 48 | +    auto param_callback = [this](const rclcpp::Parameter & p) { | 
|  | 49 | +        RCLCPP_INFO(this->get_logger(), "Count changed to: '%ld'", p.as_int()); | 
|  | 50 | +        count_.store(static_cast<std::uint32_t>(p.as_int())); | 
|  | 51 | +      }; | 
|  | 52 | +    parameter_callback_handle_ = | 
|  | 53 | +      parameter_event_handler_->add_parameter_callback("count", param_callback); | 
|  | 54 | +  } | 
|  | 55 | + | 
|  | 56 | +  rclcpp::CallbackGroup::SharedPtr get_realtime_callback_group() | 
|  | 57 | +  { | 
|  | 58 | +    return realtime_callback_group_; | 
|  | 59 | +  } | 
|  | 60 | + | 
|  | 61 | +private: | 
|  | 62 | +  rclcpp::TimerBase::SharedPtr timer_; | 
|  | 63 | +  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_; | 
|  | 64 | +  std::atomic<std::uint32_t> count_; | 
|  | 65 | +  rclcpp::CallbackGroup::SharedPtr realtime_callback_group_; | 
|  | 66 | +  std::shared_ptr<rclcpp::ParameterEventHandler> parameter_event_handler_; | 
|  | 67 | +  std::shared_ptr<rclcpp::ParameterCallbackHandle> parameter_callback_handle_; | 
|  | 68 | +}; | 
|  | 69 | + | 
|  | 70 | + | 
|  | 71 | +int main(int argc, char * argv[]) | 
|  | 72 | +{ | 
|  | 73 | +  rclcpp::init(argc, argv); | 
|  | 74 | + | 
|  | 75 | +  auto node = std::make_shared<MinimalPublisher>(); | 
|  | 76 | +  rclcpp::executors::StaticSingleThreadedExecutor default_callback_group_executor; | 
|  | 77 | +  rclcpp::executors::StaticSingleThreadedExecutor realtime_executor; | 
|  | 78 | + | 
|  | 79 | +  default_callback_group_executor.add_node(node); | 
|  | 80 | +  realtime_executor.add_callback_group( | 
|  | 81 | +    node->get_realtime_callback_group(), node->get_node_base_interface()); | 
|  | 82 | + | 
|  | 83 | +  // spin real-time tasks in a separate thread | 
|  | 84 | +  auto realtime_thread = std::thread( | 
|  | 85 | +    [&]() { | 
|  | 86 | +      realtime_executor.spin(); | 
|  | 87 | +    }); | 
|  | 88 | + | 
|  | 89 | +  default_callback_group_executor.spin(); | 
|  | 90 | +  realtime_thread.join(); | 
|  | 91 | + | 
|  | 92 | +  rclcpp::shutdown(); | 
|  | 93 | +  return 0; | 
|  | 94 | +} | 
0 commit comments