Writing a Subscriber (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 subscriber_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 subscriber.cpp. Into this file, you will copy the following code

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/int32.hpp"
using std::placeholders::_1;

class SimpleSubscriber : public rclcpp::Node
{
public:
SimpleSubscriber()
: Node("simple_subscriber")
{
subscription_ = this->create_subscription<std_msgs::msg::Int32>(
"counter", std::bind(&SimpleSubscriber::topic_callback, this, _1));
}

private:
void topic_callback(const std_msgs::msg::Int32::SharedPtr msg)
{
RCLCPP_INFO(this->get_logger(), "I heard: '%d'", msg->data);
}
rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr subscription_;
};

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

Review the code

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

class SimpleSubscriber : public rclcpp::Node

Next, we have the constructor of our class:

SimpleSubscriber()

Within the constructor, we are initializing our node by calling to the constructor of the superclass Node.

: Node("simple_subscriber")

Also within the constructor, we create our subscription_ object. As you will see later, it is actually created in the private section of our class, as a shared pointer to these object. Note that the subscription_ object is bound to a function named topic_callback, which we will see next. This function will be triggered every time a new message is published into the /counter topic.

subscription_ = this->create_subscription<std_msgs::msg::Int32>(
"counter", std::bind(&SimpleSubscriber::topic_callback, this, _1));

In the private section, we have the definition of the topic_callback function we introduced before. Inside this function, we are just generating a log message, which will print the contents of the msg->data variable. This variable will contain the message published into the /counter topic. Remember that this function will be triggered every time a new message is published into the /counter topic.

void topic_callback(const std_msgs::msg::Int32::SharedPtr msg)
{
RCLCPP_INFO(this->get_logger(), "I heard: '%d'", msg->data);
}

Also in the private section, we are creating the shared pointer to our subscription_ object defined above.

rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr subscription_;

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

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<SimpleSubscriber>());
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(subscriber_node src/subscriber.cpp)
ament_target_dependencies(subscriber_node rclcpp std_msgs)

install(TARGETS
subscriber_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 Subscriber

Let's run our subscriber with the following command:

ros2 run subscriber_cpp subscriber_node

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

ros2 topic pub /counter std_msgs/Int32 "{data: '5'}"

The above command will start publishing (in a loop) an integer (with a value of 5) into the /counter topic.

From the Shell where you executed the Subscriber, you will get the following:

And from the Shell where you publisher into the topic, you wll get the following:

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.