How to Implement Publisher and Subscriber in a Single ROS Node

Learn how to combine a Publisher and Subscriber into a single ROS node using Python. Includes full code examples for Pub/Sub communication.

ROS (Robot Operating System)

ROS is a middleware that provides libraries and tools to support the development of robot applications. It enables easy communication between robots.

Pub/Sub Communication

In ROS, an executable connected to the ROS network is called a “Node,” and messages are exchanged between nodes via named buses called “Topics.” The node that sends messages is called a Publisher, and the node that receives messages is called a Subscriber.

PubSub Communication

Environment

  • ROS Kinetic
  • Ubuntu 16.04 LTS
  • Python 3.8.5

Publisher Program

#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String

def talker():
    # Publisher('Topic Name', Type, Queue Size)
    pub = rospy.Publisher('chatter', String, queue_size=10)
    # Initialize node
    rospy.init_node('talker', anonymous=True)
    # Loop rate
    rate = rospy.Rate(10) # 10hz

    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        # Publish data
        pub.publish(hello_str)
        rate.sleep()

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass

Subscriber Program

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)

def listener():
    # Initialize node
    rospy.init_node('listener', anonymous=True)
    # Subscriber('Topic Name', Type, Callback function)
    rospy.Subscriber("chatter", String, callback)
    # Wait until callback is called
    rospy.spin()

if __name__ == '__main__':
    listener()

Combined Publisher and Subscriber Program

When implementing both Publisher and Subscriber functionality in a single node, the code looks like the following. In this example, the same node publishes messages to the chatter topic while simultaneously subscribing to it.

#!/usr/bin/env python
# coding: utf-8
import rospy
from std_msgs.msg import String

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)

def controller():
    # Initialize node
    rospy.init_node('controller', anonymous=True)
    # Subscriber
    sub = rospy.Subscriber('chatter', String, callback)
    # Publisher
    pub = rospy.Publisher('chatter', String, queue_size=1)
    # Loop rate
    rate = rospy.Rate(10)

    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        # Publish data
        pub.publish(hello_str)
        rate.sleep()

if __name__ == '__main__':
    try:
        controller()
    except rospy.ROSInterruptException:
        pass

References