Writing a Publisher (C++)

Create a package

First of all, you will have to create a new package, where you will place the code for your Publisher node. For this, you need to be in your ROS2 workspace src folder.

cd ~/ros2_ws/src

Now, execute the following command to create the package:

ros2 pkg create --build-type ament_cmake publisher_cpp --dependencies rclcpp std_msgs

You will get an output similar to this one:

This will automatically generate your package and all its necessary files and folders. Now, navigate to the 'ros2_ws/src/' folder in order to create your file.

Write the code

Inside the 'ros2_ws/src' folder, create a new file named publisher.cpp. Into this file, you will copy the following code

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/int32.hpp"
#include <chrono>

using namespace std::chrono_literals;

class SimplePublisher : public rclcpp::Node
{
public:
SimplePublisher()
: Node("simple_publisher"), count_(0)
{
publisher_ = this->create_publisher<std_msgs::msg::Int32>("counter");
timer_ = this->create_wall_timer(
500ms, std::bind(&SimplePublisher::timer_callback, this));
}

private:
void timer_callback()
{
auto message = std_msgs::msg::Int32();
message.data = count_;
count_++;
publisher_->publish(message);
}
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr publisher_;
size_t count_;
};

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<SimplePublisher>());
rclcpp::shutdown();
return 0;
}

Review the code

First, we define our class, which inherits from the rclcpp::Node class.

class SimplePublisher : public rclcpp::Node

Next, we have the constructor of our class:

SimplePublisher()

Within the constructor, we are initializing our node by calling to the constructor of the superclass Node, and also initializing a variable named count_ to 0.

: Node("simple_publisher"), count_(0)

Also within the constructor, we create our publisher_ and timer_ objects. As you will see later, they are actually created in the private section of our class, as shared pointers to these objects. Note that the timer object is bound to a function named timer_callback, which we will see next. This timer object will be triggered every 500ms.

publisher_ = this->create_publisher<std_msgs::msg::Int32>("counter");
timer_ = this->create_wall_timer(
500ms, std::bind(&SimplePublisher::timer_callback, this));

In the private section, we have the definition of the timer_callback function we introduced before. Inside this function, we are creating an Int32 message, which is given the value of the count_ variable. Then, we are going to increase the value of the count variable in 1, and we are going to publish the message into our topic. Remember that this function will be called every 500ms, as defined in the timer_ object.

void timer_callback()
{
auto message = std_msgs::msg::Int32();
message.data = count_;
count_++;
publisher_->publish(message);
}

Also in the private section, we are creating the shared pointers to our publisher and timer objects defined above, and we are also creating the variable count.

rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr publisher_;
size_t count_;

Finally, on the main function, all we do is create a SimplePublisher object, and make it spin until somebody terminates the program (Ctrl+C).

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<SimplePublisher>());
rclcpp::shutdown();
return 0;
}

Modify the CMakeLists.txt file

In the Build section of your CMakeLists.txt file, add the following lines to your CMakeLists.txt file, right above the ament_package() line.

add_executable(publisher_node src/publisher.cpp)
ament_target_dependencies(publisher_node rclcpp std_msgs)

install(TARGETS
publisher_node
DESTINATION lib/${PROJECT_NAME}
)

Compile the package

First of all, let's go the ros2_ws folder in order to be able to compile.

cd ~/ros2_ws;

Let's now execute the colcon command in order to build our node.

colcon build --symlink-install

You will get an output like the following one:

Finally, let's source the workspace.

source ~/ros2_ws/install/setup.bash

Testing the publisher

Let's run our publisher with the following command:

ros2 run publisher_cpp publisher_node

Now, in order to visualize the output, let's execute in a different shell the following command:

ros2 topic echo /counter

You will get an output like this:

Practice Online

Also, you can test this tutorial in ROSDS, using a ROSject which already contains all the code described in it. You can get the ROSject by clicking on the button below:

Above: Get ROSDS ROSject

The link above will take yo a page like the below one:

Now, you just need to Sign In (or Sign Up if you don't have an account yet) to ROSDS in order to launch the ROSject.