
Creating ROS messages
In this section, we will learn how to create a user-defined custom message using the .msg file, which will be used in our nodes. This contains a specification about the type of data to be transmitted. The ROS build system will use this file to create the necessary code to implement the message in the ROS computational framework or network.
In the previous section, Creating nodes, we created two nodes with a standard type message. Now, we will learn how to create custom messages with ROS tools.
First, create a msg folder in the chapter2_tutorials package. Furthermore, create a new chapter2_msg.msg file there and add the following lines:
int32 A int32 B int32 C
Furthermore, we will have to search for the following lines and uncomment them in the package.xml file:
<build_depend>message_generation</build_depend> <run_depend>message_runtime</run_depend>
These lines enable the configuration of the messages and services in the ROS build system. Also, we will add the message_generation line in CMakeList.txt:
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs message_generation )
Additionally, we have to find and uncomment the add_message_files lines in CMakeList.txt, along with adding the name of the new message file, as follows:
## Generate messages in the 'msg' folder add_message_files( FILES chapter2_msg.msg ) ## Generate added messages and services with any dependencies listed here generate_messages( DEPENDENCIES std_msgs )
Finally, we can build the package using the following command:
$ cd ~/catkin_ws/ $ catkin_make
To check whether everything is OK, we can use the rosmsg command:
$ rosmsg show chapter2_tutorials/chapter2_msg
This will show the contents of the chapter2_msg.msg file.
At this moment, we will create nodes that use the custom msg file described previously. This will be very similar to example_1a.cpp and example_1b.cpp, as discussed previously, but with the new message, chapter2_msg.msg.
The following code snippet is present in the example_2a.cpp file (https://github.com/kbipin/Robot-Operating-System-Cookbook/blob/master/chapter2_tutorials/src/example_2a.cpp):
#include "ros/ros.h" #include "chapter2_tutorials/chapter2_msg.h" #include <sstream> int main(int argc, char **argv) { ros::init(argc, argv, "example2a"); ros::NodeHandle n; ros::Publisher pub = n.advertise<chapter2_tutorials::chapter2_msg>("chapter2_tutorials/message", 100); ros::Rate loop_rate(10); while (ros::ok()) { chapter2_tutorials::chapter2_msg msg; msg.A = 1; msg.B = 2; msg.C = 3; pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); } return 0; }
Similarly, the following code snippet is present in the example_2b.cpp file (https://github.com/kbipin/Robot-Operating-System-Cookbook/blob/master/chapter2_tutorials/src/example_2b.cpp):
#include "ros/ros.h" #include "chapter2_tutorials/chapter2_msg.h" void messageCallback(const chapter2_tutorials::chapter2_msg::ConstPtr& msg) { ROS_INFO("I have received: [%d] [%d] [%d]", msg->A, msg->B, msg->C); } int main(int argc, char **argv) { ros::init(argc, argv, "example3_b"); ros::NodeHandle n; ros::Subscriber sub = n.subscribe("chapter2_tutorials/message", 100, messageCallback); ros::spin(); return 0; }
We can run both the publisher and the subscriber node with the following command:
$ rosrun chapter2_tutorials example2a $ rosrun chapter2_tutorials example2b
While running both nodes in two separate shells, we will see something similar to the following output:
... [ INFO] [1355280835.903686201]: I have received: [1] [2] [3] [ INFO] [1355280836.020326872]: I have received: [1] [2] [3] [ INFO] [1355280836.120367649]: I have received: [1] [2] [3] [ INFO] [1355280836.220260466]: I have received: [1] [2] [3] ...