Writing C++ Publisher in ROS2
There are three ways to to write a C++ publisher in ROS2, namely:
- Old-school approach
- Object-oriented (member-function) approach
- Local function (lambda) approach
Below is an example of each approach to write a C++ node publishing “Hello World”. The code is taken from here: https://github.com/ros2/examples/tree/foxy/rclcpp/topics/minimal_publisher
Old-school (not-composable) approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include #include #include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/string.hpp" using namespace std::chrono_literals; /* We do not recommend this style anymore, because composition of multiple * nodes in the same executable is not possible. Please see one of the subclass * examples for the "new" recommended styles. This example is only included * for completeness because it is similar to "classic" standalone ROS nodes. */ int main(int argc, char * argv[]) { rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("minimal_publisher"); auto publisher = node->create_publisher("topic", 10); std_msgs::msg::String message; auto publish_count = 0; rclcpp::WallRate loop_rate(500ms); while (rclcpp::ok()) { message.data = "Hello, world! " + std::to_string(publish_count++); RCLCPP_INFO(node->get_logger(), "Publishing: '%s'", message.data.c_str()); try { publisher->publish(message); rclcpp::spin_some(node); } catch (const rclcpp::exceptions::RCLError & e) { RCLCPP_ERROR( node->get_logger(), "unexpectedly failed with %s", e.what()); } loop_rate.sleep(); } rclcpp::shutdown(); return 0; } |
Object-oriented (member-function) approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include <chrono> #include <memory> #include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/string.hpp" using namespace std::chrono_literals; /* This example creates a subclass of Node and uses std::bind() to register a * member function as a callback from the timer. */ class MinimalPublisher : public rclcpp::Node { public: MinimalPublisher() : Node("minimal_publisher"), count_(0) { publisher_ = this->create_publisher<std_msgs::msg::string>("topic", 10); timer_ = this->create_wall_timer( 500ms, std::bind(&MinimalPublisher::timer_callback, this)); } private: void timer_callback() { auto message = std_msgs::msg::String(); message.data = "Hello, world! " + std::to_string(count_++); RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); publisher_->publish(message); } rclcpp::TimerBase::SharedPtr timer_; rclcpp::Publisher<std_msgs::msg::string>::SharedPtr publisher_; size_t count_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<minimalpublisher>()); rclcpp::shutdown(); return 0; }</minimalpublisher></std_msgs::msg::string></std_msgs::msg::string></memory></chrono> |
Local function (lambda) approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include #include #include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/string.hpp" using namespace std::chrono_literals; /* This example creates a subclass of Node and uses a fancy C++11 lambda * function to shorten the callback syntax, at the expense of making the * code somewhat more difficult to understand at first glance. */ class MinimalPublisher : public rclcpp::Node { public: MinimalPublisher() : Node("minimal_publisher"), count_(0) { publisher_ = this->create_publisher("topic", 10); auto timer_callback = [this]() -> void { auto message = std_msgs::msg::String(); message.data = "Hello, world! " + std::to_string(this->count_++); RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); this->publisher_->publish(message); }; timer_ = this->create_wall_timer(500ms, timer_callback); } private: rclcpp::TimerBase::SharedPtr timer_; rclcpp::Publisher::SharedPtr publisher_; size_t count_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared()); rclcpp::shutdown(); return 0; } |