Mastering ROS for Robotics Programming(Second Edition)
上QQ阅读APP看书,第一时间看更新

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.