Blog.

ROS Topics Publishing & Subscribing

Cover Image for ROS Topics Publishing & Subscribing
AURA Digital Labs
AURA Digital Labs

ROS Topics: The Heartbeat of Robotic Communication

ROS (Robot Operating System) is the de facto standard for robot software development. At the core of its elegant architecture lies the publish-subscribe communication mechanism, built upon the concept of topics. Understanding ROS topics – how to publish and subscribe to them – is fundamental to building any ROS-based application. This post dives deep into this crucial aspect, explaining the concepts, providing practical examples, and addressing common pitfalls.

What are ROS Topics?

Imagine a bustling city where information needs to be efficiently shared. ROS topics act like the city's communication channels, allowing different parts of your robot's software (nodes) to exchange data asynchronously. Each topic has a name (e.g., /sensor/camera/image, /cmd_vel) and a message type that defines the structure of the data transmitted. Nodes can act as publishers, sending data to a specific topic, or as subscribers, receiving data from a topic. Crucially, publishers and subscribers don't need to know about each other directly – the ROS infrastructure handles the connection and data routing.

Publishing to a Topic

Publishing data involves creating a node that sends messages to a specific topic. This process typically follows these steps:

  1. Choose a message type: ROS uses custom message types defined using the .msg file format. These messages define the data structure (e.g., integers, floats, arrays) to be transmitted.

  2. Create a publisher: Your node uses the rospy library (Python) or roscpp (C++) to create a publisher object. This object is associated with a specific topic and message type.

  3. Construct and publish messages: You create message instances, fill them with your data, and use the publisher object's publish() method to send them to the topic.

Here's a simplified Python example using rospy:

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

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    rate = rospy.Rate(1) # 1hz
    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()

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

This code publishes a string message to the /chatter topic at a rate of 1Hz. The queue_size parameter specifies the number of messages to buffer if subscribers are slow to process them.

Subscribing to a Topic

Subscribing to a topic involves creating a node that receives messages from a specified topic. The process includes:

  1. Define a callback function: This function will be executed whenever a new message arrives on the subscribed topic. The function receives the message as an argument.

  2. Create a subscriber: Use rospy.Subscriber (Python) or ros::Subscriber (C++) to create a subscriber object. This links the callback function to the topic and message type.

  3. Start the ROS node: Once the subscriber is created, the node needs to be started using rospy.spin() to handle incoming messages.

Let's illustrate with a Python subscriber that listens to the /chatter topic:

#!/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():
    rospy.init_node('listener', anonymous=True)
    rospy.Subscriber("chatter", String, callback)
    rospy.spin()

if __name__ == '__main__':
    listener()

This subscriber prints the received messages to the console.

Important Considerations

  • Message Types: Defining appropriate message types is crucial. Incorrect message types lead to communication errors.

  • Topic Names: Use descriptive and consistent topic names to improve code readability and maintainability. Follow ROS naming conventions (e.g., /robot_name/sensor/data).

  • Queue Size: Properly setting the queue_size is important. A small queue size can lead to message loss if subscribers are slow, while a large queue size can consume excessive memory.

  • Error Handling: Implement robust error handling to gracefully manage communication failures and unexpected events.

  • Rate Limiting: For high-frequency data, consider rate limiting to avoid overwhelming subscribers or network bandwidth.

Beyond the Basics: Advanced Techniques

ROS topics offer advanced features like:

  • Topic remapping: Allows you to dynamically change the topic name at runtime.
  • Topic wildcards: Enable subscribing to multiple topics based on pattern matching.
  • Topic introspection: Tools like rostopic provide functionalities to check topic status, message types, and publishers/subscribers.

Conclusion

Understanding ROS topics and how to effectively publish and subscribe to them is essential for ROS development. By mastering these core concepts, you'll be well-equipped to build complex and robust robotic systems, harnessing the power and flexibility of ROS's communication infrastructure. Remember to explore the vast resources available online, including the official ROS documentation and numerous tutorials, to further enhance your skills in this area. Happy ROS coding!