How to Publish and Subscribe to Custom Messages in ROS Noetic

Let’s write a publisher and a subscriber node to use the custom message file we just created. I will borrow heavily from simple_publisher_node.cpp and simple_subscriber_node.cpp we made earlier in this tutorial.

We will create two files:

simple_publisher_node_custom_msgs.cpp and simple_subscriber_node_custom_msgs.cpp

To keep this code short, I will not use any comments. If you don’t understand something, take a look at the simple_publisher_node.cpp and simple_subscriber_node.cpp files from earlier in this tutorial.

Open up a new terminal window.

Move to the src folder of the package we created earlier called noetic_basics_part_1.

roscd noetic_basics_part_1/src

Let’s create a C++ program named simple_publisher_node_custom_msgs.cpp. The name for this node in ROS will be simple_publisher_node_custom_msgs

Type this command to open a brand new C++ file.

gedit simple_publisher_node_custom_msgs.cpp

Type the code below into the file.

#include "ros/ros.h"
#include "noetic_basics_part_1/noetic_basics_part_1_msg.h"
#include <sstream>

int main(int argc, char **argv) {
  ros::init(argc, argv, "simple_publisher_node_custom_msgs");
  ros::NodeHandle n;
  ros::Publisher pub = n.advertise<noetic_basics_part_1::noetic_basics_part_1_msg>("noetic_basics_part_1/message", 1000);
  ros::Rate loop_rate(10);
  while (ros::ok()) {
    noetic_basics_part_1::noetic_basics_part_1_msg msg;
    msg.A = 1;
    msg.B = 2;
    msg.C = 3;
    
    pub.publish(msg);
    ros::spinOnce();
   
    loop_rate.sleep();
  }
  return 0;
}

Click Save and close the editor.

Now type this command to open a brand new C++ file.

gedit simple_subscriber_node_custom_msgs.cpp
#include "ros/ros.h"
#include "noetic_basics_part_1/noetic_basics_part_1_msg.h"

void messageCallback(const noetic_basics_part_1::noetic_basics_part_1_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, "simple_subscriber_node_custom_msgs");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("noetic_basics_part_1/message", 1000, messageCallback);
  ros::spin();
  return 0;
}

Click Save and close the editor.

Let’s edit the CMakeLists.txt file for the noetic_basics_part_1 package. Open a new terminal window, and type this command:

roscd noetic_basics_part_1 
gedit CMakeLists.txt

Now add these lines to the bottom of the CMakeLists.txt file:

add_executable(simple_publisher_node_custom_msgs src/simple_publisher_node_custom_msgs.cpp)
target_link_libraries(simple_publisher_node_custom_msgs ${catkin_LIBRARIES})

add_executable(simple_subscriber_node_custom_msgs src/simple_subscriber_node_custom_msgs.cpp)
target_link_libraries(simple_subscriber_node_custom_msgs ${catkin_LIBRARIES})

Click Save and close the text editor.

Open a new terminal window, and type the following commands to build all the nodes in the noetic_basics_part_1 package:

cd ~/catkin_ws
catkin_make 

Now, open a new terminal window and go to the catkin_ws/devel/lib/noetic_basics_part_1/ folder.

cd ~/catkin_ws/devel/lib/noetic_basics_part_1/

Type dir to see the files listed. You will see the new executables we just created. Feel free to close the terminal window now.

24-new-executablesJPG

Ok, now that we have built our nodes, let’s run them.

Open up a new terminal window and launch the ROS Master.

roscore

In a new terminal tab, type the following command to run the publisher node:

rosrun noetic_basics_part_1 simple_publisher_node_custom_msgs

Here is the output. You shouldn’t see anything because we are not printing to the terminal window using the ROS_INFO command.

25-empty-outputJPG

Now, let’s run the subscriber node. Type the following command in a new terminal tab.

rosrun noetic_basics_part_1 simple_subscriber_node_custom_msgs

Here is the output:

26-subscriber-outputJPG-1

When you’re done, press Ctrl + C in all open terminal windows.

How to Create Custom Messages in ROS Noetic

Up until now, we have worked with standard type messages (e.g. strings). Let’s see how we can create our own custom messages in ROS.

Open a new terminal window, and type the following command to go to the noetic_basics_part_1 package:

roscd noetic_basics_part_1

Create a msg folder inside that package.

mkdir msg

Move inside that folder.

cd msg

Create a new .msg file

gedit noetic_basics_part_1_msg.msg

Add the following lines.

int32 A
int32 B
int32 C
17-create-message-fileJPG

Click Save and close out the window.

In the code above, we have written three message descriptions. Specifically, we have declared three signed 32-bit integers. The syntax for a message description is:

fieldtype fieldname

Now, go back to the package.

roscd noetic_basics_part_1

Open the package.xml file.

gedit package.xml

Uncomment these two lines by deleting the arrows on each side:

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

Click Save, and then close the editor.

Now open CMakeList.txt.

gedit CMakeList.txt

Add message_generation inside the find_package(catkin REQUIRED COMPONENTS…) scope.

19-message-generationJPG

Also uncomment the add_message_files (…) lines and add the name of the message you just created.

20-uncommentJPG

Now uncomment the generate_messages(…) lines.

21-uncomment-2JPG

Since we made all these changes, we now need to build the package.

cd ~/catkin_ws/
catkin_make

Check to see if everything built properly by typing the following command:

rosmsg show noetic_basics_part_1/noetic_basics_part_1_msg

Here is what you should see:

22-what-you-should-seeJPG

You can also see the custom message you just created by typing this command:

rosmsg list

The message types are listed in alphabetic order by package name.

You can also just see a list of message types for just the noetic_basics_part_1 package.

rosmsg package noetic_basics_part_1

How to Run a Node in ROS Noetic

How to Run a C++ Node

Ok, now that we have built our nodes, let’s run them.

Open up a new terminal window and launch the ROS Master.

roscore

In a new terminal tab, type the following command to run the publisher node:

rosrun noetic_basics_part_1 simple_publisher_node

Here is the output:

13-publisher-node-outputJPG

Now, let’s run the subscriber node. Type the following command in a new terminal tab.

rosrun noetic_basics_part_1 simple_subscriber_node
14-subsriber-node-outputJPG

You’ll notice that the syntax for running a node in ROS is:

rosrun package-name executable-name

In a new terminal tab, check to see which nodes are running.

rosnode list
15-rostopic-listJPG

The /rosout node is a special node that starts up automatically when you launch the ROS Master. It is responsible for managing ROS-specific output messages to the terminal window.

If you want to find out information about the publisher node, you can type:

rosnode info /simple_publisher_node

That command aboves gives you a full account of what the node is all about. To find out more information about the subscriber node, type:

rosnode info /simple_subscriber_node

There are a bunch of commands for ROS nodes.

To list all active topics, type:

rostopic list

You can see the /message topic is currently active.

Now try these commands, and see what you get:

rostopic info message
rostopic type /message
rostopic bw /message

You can find out what all these commands mean at the ROS website here.

To visualize the publish-subscribe relationships between the nodes, type the following command:

rqt graph
16-node-graphJPG

An incoming arrow indicates that a node subscribed to the topic. An outgoing arrow indicates that a node publishes to the topic.

You can close all terminal windows when you’re ready by pressing CTRL + C on your keyboard on each window.

How to Run a Python Node

In a new terminal window, launch ROS.

roscore

Open a new terminal window, and execute simple_python_publisher.py.

rosrun noetic_basics_part_1 simple_python_publisher.py

Here is the output:

13b-python-publisher-outputJPG-1

Open another terminal window and type:

rosrun noetic_basics_part_1 simple_python_subscriber.py
13c-python-subscriber-outputJPG-1

To stop the program, type CTRL+C in all terminal windows.