Creating ROS nodes
The first node we are going to discuss is demo_topic_publisher.cpp. This node will publish an integer value on a topic called /numbers. Copy the current code into a new package or use this existing file from the code repository.
Here is the complete code:
#include "ros/ros.h" #include "std_msgs/Int32.h" #include <iostream> int main(int argc, char **argv) { ros::init(argc, argv,"demo_topic_publisher"); ros::NodeHandle node_obj; ros::Publisher number_publisher = node_obj.advertise<std_msgs::Int32>("/numbers",10); ros::Rate loop_rate(10); int number_count = 0; while (ros::ok()) { std_msgs::Int32 msg; msg.data = number_count; ROS_INFO("%d",msg.data); number_publisher.publish(msg); ros::spinOnce(); loop_rate.sleep(); ++number_count; } return 0; }
Here is the detailed explanation of the preceding code:
#include "ros/ros.h" #include "std_msgs/Int32.h" #include <iostream>
The ros/ros.h is the main header of ROS. If we want to use the roscpp client APIs in our code, we should include this header. The std_msgs/Int32.h is the standard message definition of the integer datatype.
Here, we are sending an integer value through a topic. So we should need a message type for handling the integer data. std_msgs contains the standard message definition of primitive datatypes. std_msgs/Int32.h contains the integer message definition:
ros::init(argc, argv,"demo_topic_publisher");
This code will initialize a ROS node with a name. It should be noted that the ROS node should be unique. This line is mandatory for all ROS C++ nodes:
ros::NodeHandle node_obj;
This will create a Nodehandle object, which is used to communicate with the ROS system:
ros::Publisher number_publisher = node_obj.advertise<std_msgs::Int32>("/numbers",10);
This will create a topic publisher and name the topic /numbers with a message type std_msgs::Int32. The second argument is the buffer size. It indicates how many messages need to be put in a buffer before sending. It should be set to high if the data sending rate is high:
ros::Rate loop_rate(10);
This is used to set the frequency of sending data:
while (ros::ok()) {
This is an infinite while loop, and it quits when we press Ctrl + C. The ros::ok() function returns zero when there is an interrupt; this can terminate this while loop:
std_msgs::Int32 msg; msg.data = number_count;
The first line creates an integer ROS message, and the second line assigns an integer value to the message. Here, data is the field name of the msg object:
ROS_INFO("%d",msg.data);
This will print the message data. This line is used to log the ROS information:
number_publisher.publish(msg);
This will publish the message to the topics /numbers:
ros::spinOnce();
This command will read and update all ROS topics. The node will not publish without a spin() or spinOnce() function:
loop_rate.sleep();
This line will provide the necessary delay to achieve a frequency of 10 Hz.
After discussing the publisher node, we can discuss the subscriber node, which is demo_topic_subscriber.cpp. Copy the code to a new file or use the existing file.
Here is the definition of the subscriber node:
#include "ros/ros.h" #include "std_msgs/Int32.h" #include <iostream> void number_callback(const std_msgs::Int32::ConstPtr& msg) { ROS_INFO("Received [%d]",msg->data); }
int main(int argc, char **argv) { ros::init(argc, argv,"demo_topic_subscriber"); ros::NodeHandle node_obj; ros::Subscriber number_subscriber = node_obj.subscribe("/numbers",10,number_callback); ros::spin(); return 0; }
Here is the code explanation:
#include "ros/ros.h" #include "std_msgs/Int32.h" #include <iostream>
This is the header needed for the subscribers:
void number_callback(const std_msgs::Int32::ConstPtr& msg) { ROS_INFO("Recieved [%d]",msg->data); }
This is a callback function that will execute whenever a data comes to the /numbers topic. Whenever a data reaches this topic, the function will call and extract the value and print it on the console:
ros::Subscriber number_subscriber = node_obj.subscribe("/numbers",10,number_callback);
This is the subscriber, and here we are giving the topic name needed to subscribe, the buffer size, and the callback function. We are subscribing the /numbers topic and we have already seen the callback function in the preceding section:
ros::spin();
This is an infinite loop in which the node will wait in this step. This code will fasten the callbacks whenever a data reaches the topic. The node will quit only when we press the Ctrl + C key.