How to code Publishers and Subscribers in ROS
With explanation and Python code
In the Robot Operating System (ROS), the concepts of publisher and subscriber can be explained using the analogy of a radio station:
- Publisher (Radio Station): Think of a publisher as a radio station that broadcasts information. The station decides what kind of information (topic) it will send out, such as news, music, or weather updates. It doesn’t care who is listening; its job is simply to transmit the message.
- Subscriber (Radio Listener): A subscriber is like someone tuning in to a specific radio station to listen to what’s being broadcast. They pick the station (topic) they are interested in, such as a music channel or a news channel, and receive only that information. If they don’t tune in to the station, they won’t get the broadcast.
So basically,
- The radio frequency is like the topic in ROS. Both publishers and subscribers need to agree on the same topic (or frequency) to communicate.
- There can be multiple listeners (subscribers) for a single station (publisher), just as multiple subscribers can receive messages from one publisher in ROS.
- The radio station doesn’t know or care how many people are listening, just like a ROS publisher doesn’t track its subscribers.
- Similarly, listeners can tune in or stop listening at any time without affecting the broadcaster.
Now, let’s dive into how to execute them in ROS
Step.1 —Creating the Publisher
Create a new node, we are going to name it Robot_news_station based on the example discussed before. Don’t know how? Check out my previous blog here!
Step.2
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.msg import String
class RobotNewsStationNode(Node):
def __init__(self):
super().__init__("robot_news_station")
self.publisher_ = self.create_publisher(String,"robot_news", 10)
self.counting = 0
self.counter_= self.create_timer(5,self.NewsPublisher)
self.get_logger().info("Robot News Station Online")
def NewsPublisher(self):
msg = String()
self.counting += 1
msg.data = "MESSAGE RECEIVED!" + str (self.counting)
self.publisher_.publish(msg)
def main(args=None):
rclpy.init(args=args)
node = RobotNewsStationNode()
rclpy.spin(node)
rclpy.shutdown()
if __name__== "__main__":
main()
Here, the command self.create_publisher makes a publisher. First parameter is the type of message sent through the topic. Remember, the publisher and subscriber need to have the same type of message exchange for it to succesfully work! Next is the topic name. This again needs to be the same in the publisher and subscriber side. A simple way to understand this is that — When you are listening to the radio station, it is important that your phone is in a particular frequency egs — 99.8 and the radio station also needs to trasmit in the same frequency. If you are tuned in for 100.3 , you won’t hear the music played in 99.8.
Next we define a timer node which repetitively publishes a message across the topic. Now run the node. (Check out my previous blog if you don’t know how to)
Step.3 -Few terminal commands
ros2 topic list
This will list out all the current topics running. robot_news should come up in this.
ros2 topic echo /robot_news
This will show the message that is sent through the topic robot_news
step.4 — Making subscriber
Create another node and name it smartphone.
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.msg import String
class SmartphoneNode(Node):
def __init__(self):
super().__init__("smartphone")
self.subscriber_= self.create_subscription(String, "robot_news", self.callback_robot_news,10)
self.get_logger().info("Smartphone activated")
def callback_robot_news(self,msg):
self.get_logger().info(msg.data)
def main(args=None):
rclpy.init(args=args)
node = SmartphoneNode()
rclpy.spin(node)
rclpy.shutdown()
if __name__== "__main__":
main()
Like before, self.create_subscription makes a subscriber. You will notice that the message type (String, here ) and the topic name are the exact same as to the publisher. Next ,we have a call back function which is called everytime we receive a mesage from the publisher.
Step .5 — Run both the nodes simultaneously in two different terminals and see the results!