Note: This tutorial assumes that you have completed the previous tutorials: writing a simple publisher and subscriber. |
Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
Publishing messages in rospy
Description: Writing a simple publisher and subscriber already introduced you to the basics of creating rospy Nodes that publish and receive messages on ROS Topics. As you get more experienced with ROS and rospy, you may wish to learn some advanced syntax for publishing that will save you some typing -- as well as make your code more robust to future changes.Tutorial Level: INTERMEDIATE
Next Tutorial: Publishing and Subscribing to Images rospy_tutorials/Tutorials/WritingImagePublisherSubscriber
First, lets look at the publish call:
1 pub.publish(String(str))
rospy already knows that you're trying to publish std_msgs.msg.String objects, so you can shorten this to:
1 pub.publish(str)
rospy will automatically create the std_msgs.msg.String instance for you.
If the message takes in multiple arguments, you must specify them in the order that they are declared in the .msg file. For example, std_msgs/ColorRGBA:
$ rosmsg show std_msgs/ColorRGBA float32 r float32 g float32 b float32 a
would be initialized with r, g, b, and a as the arguments, e.g.:
1 pub.publish(0.1, 0.2, 0.3, 0.4)
Now, this is very handy, but it's also brittle. If you want to add a new field to the ColorRGBA type, you will have to go through all the Python code that uses it (rosmsg users std_msgs/ColorRGBA) and add the new field to your arguments. This can be a pain, especially if the field is optional.
Luckily, there's a more robust way of specifying the fields that also lets you omit any fields that you wish to assign default values. You simply use Python keyword arguments to specify the fields you wish to assign. The rest are assigned default values (zero for numerical values, empty lists for arrays, empty string for strings):
1 pub.publish(a=1.0)
This will publish a ColorRGBA message with a=1.0 and the rest of the fields (r, g, b) assigned to zero. Working example:
talker_color.py
1 #!/usr/bin/env python
2 import roslib; roslib.load_manifest('beginner_tutorials')
3 import rospy
4 from std_msgs.msg import ColorRGBA
5 def talker():
6 #pub = rospy.Publisher('chatter', String)
7 pub = rospy.Publisher('chatter_color', ColorRGBA)
8 rospy.init_node('talker_color')
9 while not rospy.is_shutdown():
10 pub.publish(a=1.0)
11 rospy.sleep(1.0)
12 if __name__ == '__main__':
13 try:
14 talker()
15 except rospy.ROSInterruptException: pass
listener_color.py
1 #!/usr/bin/env python
2 import roslib; roslib.load_manifest('beginner_tutorials')
3 import rospy
4 from std_msgs.msg import ColorRGBA
5 def callback(data):
6 rospy.loginfo(rospy.get_name()+ "I heard r=%s g=%s b=%s a=%s", data.r, data.g, data.b, data.a)
7
8 def listener():
9 rospy.init_node('listener_color', anonymous=True)
10 rospy.Subscriber("chatter_color", ColorRGBA, callback)
11 rospy.spin()
12
13 if __name__ == '__main__':
14 listener()