官术网_书友最值得收藏!

Creating ROS nodes

In this section, we are going to learn how to create two nodes, where one will publish data and the other will receive this data. This is the most basic way of communicating between two nodes in the ROS system.

We created the ROS package chapter2_tutorials in the earlier section Creating a ROS package and metapackage. Now, we will navigate to the chapter2_tutorials/src/ folder using the following command:

$ roscd chapter2_tutorials/src/

We will create two files with the names example_1a.cpp and example_1b.cpp. The example_1a.cpp file will create a node named example1a, which publishes the data "Hello World!" on the /message topic. Moreover, the example_1b.cpp file will create a node named example1b, which subscribes to the /message topic and receives the data sent by the example1a node, and shows the data in the shell.

We can copy the following code inside the example_1a.cpp file, or download it from the repository (https://github.com/kbipin/Robot-Operating-System-Cookbook/blob/master/chapter2_tutorials/src/example_1a.cpp):

#include "ros/ros.h" 
#include "std_msgs/String.h" 
#include <sstream> 
 
int main(int argc, char **argv) 
{ 
  ros::init(argc, argv, "example1a"); 
  ros::NodeHandle n; 
  ros::Publisher pub = n.advertise<std_msgs::String>("message", 100); 
  ros::Rate loop_rate(10); 
  
  while (ros::ok()) 
  { 
    std_msgs::String msg; 
    std::stringstream ss; 
    ss << "Hello World!"; 
    msg.data = ss.str(); 
    pub.publish(msg); 
     
    ros::spinOnce(); 
    loop_rate.sleep(); 
  } 
  return 0; 
} 

We will discuss the preceding code to understand the ROS development framework in detail. The headers to be included are ros/ros.h, std_msgs/String.h, and sstream. ros/ros.h includes all the files needed for working with ROS, and std_msgs/String.h includes the header that defines the type of message used for publishing to the ROS computational network:

#include "ros/ros.h" 
#include "std_msgs/String.h" 
#include <sstream> 

Here, we will initialize the node and set the name. It should be remembered that the name must be unique:

ros::init(argc, argv, "example1a"); 

This is the handler of the processes associated with the node, which allow it to interact with the environment:

ros::NodeHandle n; 

At this point, we will instantiate a publisher with the name of the topic and the type, which also specifies the size of a buffer in the second parameter (if the topic is publishing data quickly, the buffer will keep at least 100 messages):

ros::Publisher pub = n.advertise<std_msgs::String>("message", 100); 

The next line of code sets the data sending frequency, which, in this case, is 10 Hz:

ros::Rate loop_rate(10); 

The next ros::ok() line stops the node if Ctrl + C is pressed or if ROS stops all the nodes:

while (ros::ok()) 
{

In this part of the code, we will create a variable for the message with the correct type to send the data:

std_msgs::String msg; 
std::stringstream ss; 
ss << "Hello World!"; 
msg.data = ss.str(); 
pub.publish(msg); 

Moreover, we will continue by sending the message, using the previously defined semantics of the publisher:

pub.publish(msg); 

The spinOnce function takes care of handling all of the internal ROS events and actions, such as reading from subscribed topics; however, spinOnce performs one iteration in the main loop of ROS, in order to allow the user to perform actions between iterations, while the spin function runs the main loop without interruption.

Finally, at this point, we sleep for the required time to get a 10 Hz frequency:

loop_rate.sleep();

We have successfully created a publisher node. Likewise, we will now create the subscriber node. Copy the following code inside the example_1b.cpp file, or download it from the repository (https://github.com/kbipin/Robot-Operating-System-Cookbook/blob/master/chapter2_tutorials/src/example_1b.cpp):

#include "ros/ros.h" 
#include "std_msgs/String.h" 
 
void messageCallback(const std_msgs::String::ConstPtr& msg) 
{ 
  ROS_INFO("Thanks: [%s]", msg->data.c_str()); 
} 
 
int main(int argc, char **argv) 
{ 
  ros::init(argc, argv, "example1b"); 
  ros::NodeHandle n; 
  ros::Subscriber sub = n.subscribe("message", 100, messageCallback); 
  ros::spin(); 
  return 0; 
} 

Let's discuss the source code. As discussed previously, ros/ros.h includes all the files necessary for using the node with ROS, and std_msgs/String.h defines the type of message used:

#include "ros/ros.h" 
#include "std_msgs/String.h" 
#include <sstream> 

The following source code shows the type of function callback that is invoked in response to an action, which in this case is the reception of a string message on subscribed topics. This function allows us to process the received message data; in this case, it displays the message data on the Terminal:

void messageCallback(const std_msgs::String::ConstPtr& msg) 
{ 
  ROS_INFO("Thanks: [%s]", msg->data.c_str()); 
}

At this point, we will create a subscriber and start to listen to the topic with the name message where the buffer size will be of 100, and the function to handle the message will be messageCallback:

ros::Subscriber sub = n.subscribe("message", 1000, messageCallback); 

Finally, the line ros::spin() is the main loop where the node begins to read the topics, and, when a message arrives, messageCallback is called. When the user presses Ctrl + C, the node exits the loop and ends:

ros::spin(); 
主站蜘蛛池模板: 茂名市| 德惠市| 泰安市| 织金县| 保靖县| 临汾市| 河曲县| 进贤县| 吴旗县| 中山市| 荃湾区| 甘德县| 蓝田县| 黑山县| 长治市| 三原县| 宝丰县| 永善县| 文安县| 平阴县| 焦作市| 上蔡县| 东港市| 绥中县| 新干县| 霍城县| 潜江市| 和田市| 桂林市| 嘉义市| 仙居县| 章丘市| 清水县| 买车| 江门市| 霍城县| 泰兴市| 灵山县| 黎城县| 石首市| 兴海县|