rospy/2008-09-18 rospy Specification Review
Package Developer: KenConley
Reviewers:
Agenda
The focus of this review will be going over the rospy client API for writing services and nodes. In particular:
- what are the impediments to learning rospy for the first time?
- what APIs would you like to see (de)streamlined?
- what APIs are missing/should be removed?
Please add your questions/answers here:
- Is there a way to determine what type of message is being passed over a topic?
Package Specification
A canonical rospy publisher:
1 import rostools; rostools.update_path('rospy_demo')
2
3 import sys
4 import time
5 import rospy
6 from std_msgs.msg import String
7
8 def talker():
9 pub = rospy.TopicPub("chatter", String)
10 rospy.ready('talker', anonymous=True)
11 count = 0
12 while not rospy.is_shutdown():
13 pub.publish(String("hello world %d"%count))
14 count += 1
15 time.sleep(0.01)
16
17 if __name__ == '__main__':
18 try:
19 talker()
20 except KeyboardInterrupt, e:
21 pass
22 print "exiting"
A canonical rospy listener:
1 import rostools; rostools.update_path('rospy_demo')
2
3 import sys
4 import rospy
5 from std_msgs.msg import String
6
7 def callback(data):
8 print rospy.get_caller_id(), "I heard %s"%data.data
9
10 def listener():
11 rospy.ready('listener')
12 rospy.TopicSub("chatter", String, callback)
13 rospy.spin()
14
15 if __name__ == '__main__':
16 listener()
A canonical rospy service
1 import rostools; rostools.update_path('rospy_tutorials')
2
3 from rospy_tutorials.srv import *
4 import rospy
5
6 def add_two_ints(req):
7 return AddTwoIntsResponse(req.a + req.b)
8
9 def add_two_ints_server():
10 rospy.ready('add_two_ints_server')
11 s = rospy.Service('add_two_ints', AddTwoInts, add_two_ints)
12 s.register()
13 rospy.spin()
14
15 if __name__ == "__main__":
16 add_two_ints_server()
A canonical rospy service client:
1 import rostools; rostools.update_path('rospy_tutorials')
2
3 import sys
4 import os
5 import rospy
6 from rospy_tutorials.srv import *
7
8 def add_two_ints_client(x, y):
9 rospy.wait_for_service('add_two_ints')
10 try:
11 add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
12 # simplified style
13 resp1 = add_two_ints(x, y)
14 # formal style
15 resp2 = add_two_ints.call(AddTwoIntsRequest(x, y))
16 return resp1.sum
17 except rospy.ServiceException, e:
18 print "Service call failed: %s"%e
19
20 if __name__ == "__main__":
21 add_two_ints_client(random.randint(-50000, 50000), random.randint(-50000, 50000))
Key features
- ROS client library for Python nodes
Dependencies
rostools : rostools contains a Python library for manipulating names, .msg/.srv files, etc...
Testing strategy
- unit tests against client API
- generic test suite against XML-RPC API
- node/service integration tests
- cross validation with roscpp equivalent nodes and services
Minutes
- API calls differ from C++ naming and structure, not for a good reason other than history.
- Don't want to return a node instance, because they're really singletons.
- spin() is a potentially confusing name, but we're keeping it.
TODO:
- Rename rostools.update_path() for clarity of what it does.
- Revisit package.msg generation location, which is awkward, and, more importantly, is different from comparable C++ inclusion. We currently lack a better solution.
- Rename rospy.ready() to rospy.init_node()
Rename TopicPub() to advertise_topic()
Rename TopicSub() to subscribe_topic()
- Rename some of the service-related calls
Post-meeting addendums:
- using init_node instead of init to clarify the role of init as it is unnecessary for ROS service clients
- changed advertiseTopic/etc to advertise_topic to reflect coding standards
- keeping update_path as-is, but updating documentation and examples to be more explicit
TopicPub/TopicSub will stay around for those that prefer to know that constructors are in fact constructors
Conclusion
NEEDS MORE WORK.
Work on TODOs and schedule another 1/2 hour meeting.