1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 """
35 Python adapter for calling ROS Master API. While it is trivial to call the
36 Master directly using XML-RPC, this API provides a safer abstraction in the event
37 the Master API is changed.
38 """
39
40 try:
41 from xmlrpc.client import ServerProxy
42 except ImportError:
43 from xmlrpclib import ServerProxy
44
45 from . names import make_caller_id
46 from . rosenv import get_master_uri
47 from . network import parse_http_host_and_port
48
50 """
51 Base class of ROS-master related errors.
52 """
53 pass
54
56 """
57 Call to Master failed. This generally indicates an internal error
58 in the Master and that the Master may be in an inconsistent state.
59 """
60 pass
61
63 """
64 Master returned an error code, which indicates an error in the
65 arguments passed to the Master.
66 """
67 pass
68
69
70 ROSMasterException = MasterException
71 Error = MasterError
72 Failure = MasterFailure
73
75 """
76 @param master_uri: (optional) override environment's ROS_MASTER_URI
77 @type master_uri: str
78 @return: True if Master is available
79 """
80 return Master('rosgraph', master_uri=master_uri).is_online()
81
83 """
84 API for interacting with the ROS master. Although the Master is
85 relatively simple to interact with using the XMLRPC API, this
86 abstraction layer provides protection against future updates. It
87 also provides a streamlined API with builtin return code checking
88 and caller_id passing.
89 """
90
91 - def __init__(self, caller_id, master_uri=None):
92 """
93 :param caller_id: name of node to use in calls to master, ``str``
94 :param master_uri: (optional) override default ROS master URI, ``str``
95 :raises: :exc:`ValueError` If ROS master uri not set properly
96 """
97
98 if master_uri is None:
99 master_uri = get_master_uri()
100 self._reinit(master_uri)
101
102 self.caller_id = make_caller_id(caller_id)
103 if self.caller_id[-1] == '/':
104 self.caller_id = self.caller_id[:-1]
105
107 """
108 Internal API for reinitializing this handle to be a new master
109
110 :raises: :exc:`ValueError` If ROS master uri not set
111 """
112 if master_uri is None:
113 raise ValueError("ROS master URI is not set")
114
115 try:
116 parse_http_host_and_port(master_uri)
117 except ValueError:
118 raise ValueError("invalid master URI: %s"%(master_uri))
119
120 self.master_uri = master_uri
121 self.handle = ServerProxy(self.master_uri)
122
124 """
125 Check if Master is online.
126
127 NOTE: this is not part of the actual Master API. This is a convenience function.
128
129 @param master_uri: (optional) override environment's ROS_MASTER_URI
130 @type master_uri: str
131 @return: True if Master is available
132 """
133 try:
134 self.getPid()
135 return True
136 except:
137 return False
138
140 """
141 Check master return code and return the value field.
142
143 @param args: master return value
144 @type args: (int, str, XMLRPCLegalValue)
145 @return: value field of args (master return value)
146 @rtype: XMLRPCLegalValue
147 @raise rosgraph.masterapi.Error: if Master returns ERROR.
148 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
149 """
150 code, msg, val = args
151 if code == 1:
152 return val
153 elif code == -1:
154 raise Error(msg)
155 else:
156 raise Failure(msg)
157
158
159
160
162 """
163 Parameter Server: delete parameter
164 @param key: parameter name
165 @type key: str
166 @return: 0
167 @rtype: int
168 """
169 return self._succeed(self.handle.deleteParam(self.caller_id, key))
170
172 """
173 Parameter Server: set parameter. NOTE: if value is a
174 dictionary it will be treated as a parameter tree, where key
175 is the parameter namespace. For example:::
176 {'x':1,'y':2,'sub':{'z':3}}
177
178 will set key/x=1, key/y=2, and key/sub/z=3. Furthermore, it
179 will replace all existing parameters in the key parameter
180 namespace with the parameters in value. You must set
181 parameters individually if you wish to perform a union update.
182
183 @param key: parameter name
184 @type key: str
185 @param value: parameter value.
186 @type value: XMLRPCLegalValue
187 @return: 0
188 @rtype: int
189 """
190 return self._succeed(self.handle.setParam(self.caller_id, key, value))
191
193 """
194 Retrieve parameter value from server.
195 @param key: parameter to lookup. If key is a namespace,
196 getParam() will return a parameter tree.
197 @type key: str
198 getParam() will return a parameter tree.
199
200 @return: parameterValue. If key is a namespace,
201 the return value will be a dictionary, where each key is a
202 parameter in that namespace. Sub-namespaces are also
203 represented as dictionaries.
204 @rtype: XMLRPCLegalValue
205 """
206 return self._succeed(self.handle.getParam(self.caller_id, key))
207
209 """
210 Search for parameter key on parameter server. Search starts in caller's namespace and proceeds
211 upwards through parent namespaces until Parameter Server finds a matching key.
212
213 searchParam's behavior is to search for the first partial match.
214 For example, imagine that there are two 'robot_description' parameters::
215
216 /robot_description
217 /robot_description/arm
218 /robot_description/base
219 /pr2/robot_description
220 /pr2/robot_description/base
221
222 If I start in the namespace /pr2/foo and search for
223 'robot_description', searchParam will match
224 /pr2/robot_description. If I search for 'robot_description/arm'
225 it will return /pr2/robot_description/arm, even though that
226 parameter does not exist (yet).
227
228 @param key: parameter key to search for.
229 @type key: str
230 @return: foundKey
231 @rtype: str
232 """
233 return self._succeed(self.handle.searchParam(self.caller_id, key))
234
236 """
237 Retrieve parameter value from server and subscribe to updates to that param. See
238 paramUpdate() in the Node API.
239 @param key: parameter to lookup.
240 @type key: str
241 @param caller_api: API URI for paramUpdate callbacks.
242 @type caller_api: str
243 @return: parameterValue. parameterValue is an empty dictionary if the parameter has not been set yet.
244 @rtype: XMLRPCLegalValue
245 """
246 return self._succeed(self.handle.subscribeParam(self.caller_id, caller_api, key))
247
249 """
250 Retrieve parameter value from server and subscribe to updates to that param. See
251 paramUpdate() in the Node API.
252 @param key: parameter to lookup.
253 @type key: str
254 @param caller_api: API URI for paramUpdate callbacks.
255 @type caller_api: str
256 @return: numUnsubscribed. If numUnsubscribed is zero it means that the caller was not subscribed to the parameter.
257 @rtype: int
258 """
259 return self._succeed(self.handle.unsubscribeParam(self.caller_id, caller_api, key))
260
262 """
263 Check if parameter is stored on server.
264 @param key: parameter to check
265 @type key: str
266 @return: [code, statusMessage, hasParam]
267 @rtype: [int, str, bool]
268 """
269 return self._succeed(self.handle.hasParam(self.caller_id, key))
270
272 """
273 Get list of all parameter names stored on this server.
274 This does not adjust parameter names for caller's scope.
275
276 @return: [code, statusMessage, parameterNameList]
277 @rtype: [int, str, [str]]
278 """
279 return self._succeed(self.handle.getParamNames(self.caller_id))
280
281
282
283
285 """
286 Get the PID of this server
287 @return: serverProcessPID
288 @rtype: int
289 @raise rosgraph.masterapi.Error: if Master returns ERROR.
290 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
291 """
292 return self._succeed(self.handle.getPid(self.caller_id))
293
295 """
296 Get the URI of this Master
297 @return: masterUri
298 @rtype: str
299 @raise rosgraph.masterapi.Error: if Master returns ERROR.
300 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
301 """
302 return self._succeed(self.handle.getUri(self.caller_id))
303
305 """
306 Register the caller as a provider of the specified service.
307 @param service str: Fully-qualified name of service
308 @param service_api str: Service URI
309 @param caller_api str: XML-RPC URI of caller node
310 @return: ignore
311 @rtype: int
312 @raise rosgraph.masterapi.Error: if Master returns ERROR.
313 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
314 """
315 return self._succeed(self.handle.registerService(self.caller_id, service, service_api, caller_api))
316
318 """
319 Lookup all provider of a particular service.
320 @param service: fully-qualified name of service to lookup.
321 @type: service: str
322 @return (int, str, str): (code, message, serviceUrl). service URL is provides
323 and address and port of the service. Fails if there is no provider.
324 @raise rosgraph.masterapi.Error: if Master returns ERROR.
325 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
326 """
327 return self._succeed(self.handle.lookupService(self.caller_id, service))
328
329
331 """
332 Unregister the caller as a provider of the specified service.
333 @param service: Fully-qualified name of service
334 @type service: str
335 @param service_api: API URI of service to unregister. Unregistration will only occur if current
336 registration matches.
337 @type service_api: str
338 @return: (code, message, numUnregistered). Number of unregistrations (either 0 or 1).
339 If this is zero it means that the caller was not registered as a service provider.
340 The call still succeeds as the intended final state is reached.
341 @rtype: (int, str, int)
342 @raise rosgraph.masterapi.Error: if Master returns ERROR.
343 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
344 """
345 return self._succeed(self.handle.unregisterService(self.caller_id, service, service_api))
346
347
349 """
350 Subscribe the caller to the specified topic. In addition to receiving
351 a list of current publishers, the subscriber will also receive notifications
352 of new publishers via the publisherUpdate API.
353 @param topic str: Fully-qualified name of topic to subscribe to.
354 @param topic_type: Datatype for topic. Must be a package-resource name, i.e. the .msg name.
355 @type topic_type: str
356 @param caller_api: XML-RPC URI of caller node for new publisher notifications
357 @type caller_api: str
358 @return: (code, message, publishers). Publishers is a list of XMLRPC API URIs
359 for nodes currently publishing the specified topic.
360 @rtype: (int, str, list(str))
361 @raise rosgraph.masterapi.Error: if Master returns ERROR.
362 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
363 """
364 return self._succeed(self.handle.registerSubscriber(self.caller_id, topic, topic_type, caller_api))
365
366
368 """
369 Unregister the caller as a publisher of the topic.
370 @param topic: Fully-qualified name of topic to unregister.
371 @type topic: str
372 @param caller_api: API URI of service to unregister. Unregistration will only occur if current
373 @type caller_api: str
374 registration matches.
375 @return: (code, statusMessage, numUnsubscribed).
376 If numUnsubscribed is zero it means that the caller was not registered as a subscriber.
377 The call still succeeds as the intended final state is reached.
378 @rtype: (int, str, int)
379 @raise rosgraph.masterapi.Error: if Master returns ERROR.
380 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
381 """
382 return self._succeed(self.handle.unregisterSubscriber(self.caller_id, topic, caller_api))
383
385 """
386 Register the caller as a publisher the topic.
387 @param topic: Fully-qualified name of topic to register.
388 @type topic: str
389 @param topic_type: Datatype for topic. Must be a
390 package-resource name, i.e. the .msg name.
391 @type topic_type: str
392 @param caller_api str: ROS caller XML-RPC API URI
393 @type caller_api: str
394 @return: subscriberApis.
395 List of current subscribers of topic in the form of XMLRPC URIs.
396 @rtype: [str]
397 @raise rosgraph.masterapi.Error: if Master returns ERROR.
398 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
399 """
400 return self._succeed(self.handle.registerPublisher(self.caller_id, topic, topic_type, caller_api))
401
403 """
404 Unregister the caller as a publisher of the topic.
405 @param topic: Fully-qualified name of topic to unregister.
406 @type topic: str
407 @param caller_api str: API URI of service to
408 unregister. Unregistration will only occur if current
409 registration matches.
410 @type caller_api: str
411 @return: numUnregistered.
412 If numUnregistered is zero it means that the caller was not registered as a publisher.
413 The call still succeeds as the intended final state is reached.
414 @rtype: int
415 @raise rosgraph.masterapi.Error: if Master returns ERROR.
416 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
417 """
418 return self._succeed(self.handle.unregisterPublisher(self.caller_id, topic, caller_api))
419
421 """
422 Get the XML-RPC URI of the node with the associated
423 name/caller_id. This API is for looking information about
424 publishers and subscribers. Use lookupService instead to lookup
425 ROS-RPC URIs.
426 @param node: name of node to lookup
427 @type node: str
428 @return: URI
429 @rtype: str
430 @raise rosgraph.masterapi.Error: if Master returns ERROR.
431 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
432 """
433 return self._succeed(self.handle.lookupNode(self.caller_id, node_name))
434
436 """
437 Get list of topics that can be subscribed to. This does not return topics that have no publishers.
438 See L{getSystemState()} to get more comprehensive list.
439 @param subgraph: Restrict topic names to match within the specified subgraph. Subgraph namespace
440 is resolved relative to the caller's namespace. Use '' to specify all names.
441 @type subgraph: str
442 @return: [[topic1, type1]...[topicN, typeN]]
443 @rtype: [[str, str],]
444 @raise rosgraph.masterapi.Error: if Master returns ERROR.
445 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
446 """
447 return self._succeed(self.handle.getPublishedTopics(self.caller_id, subgraph))
448
450 """
451 Retrieve list topic names and their types.
452
453 New in ROS 1.2.
454
455 @rtype: (int, str, [[str,str]] )
456 @return: (code, statusMessage, topicTypes). topicTypes is a list of [topicName, topicType] pairs.
457 """
458 return self._succeed(self.handle.getTopicTypes(self.caller_id))
459
461 """
462 Retrieve list representation of system state (i.e. publishers, subscribers, and services).
463 @rtype: [[str,[str]], [str,[str]], [str,[str]]]
464 @return: systemState
465
466 System state is in list representation::
467 [publishers, subscribers, services].
468
469 publishers is of the form::
470 [ [topic1, [topic1Publisher1...topic1PublisherN]] ... ]
471
472 subscribers is of the form::
473 [ [topic1, [topic1Subscriber1...topic1SubscriberN]] ... ]
474
475 services is of the form::
476 [ [service1, [service1Provider1...service1ProviderN]] ... ]
477
478 @raise rosgraph.masterapi.Error: if Master returns ERROR.
479 @raise rosgraph.masterapi.Failure: if Master returns FAILURE.
480 """
481 return self._succeed(self.handle.getSystemState(self.caller_id))
482