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 """rospy internal core implementation library"""
36
37 from __future__ import with_statement
38
39 import atexit
40 import logging
41 import os
42 import signal
43 import sys
44 import threading
45 import time
46 import traceback
47 import types
48 import urlparse
49 import xmlrpclib
50
51 import roslib.rosenv
52 import roslib.roslogging
53
54 import rospy.exceptions
55
56 from rospy.names import *
57 from rospy.impl.validators import ParameterInvalid
58
59 from rosgraph_msgs.msg import Log
60
61 _logger = logging.getLogger("rospy.core")
62
63
64
65
66 _TIMEOUT_SHUTDOWN_JOIN = 5.
67
68 import warnings
70 """This is a decorator which can be used to mark functions
71 as deprecated. It will result in a warning being emmitted
72 when the function is used."""
73 def newFunc(*args, **kwargs):
74 warnings.warn("Call to deprecated function %s." % func.__name__,
75 category=DeprecationWarning, stacklevel=2)
76 return func(*args, **kwargs)
77 newFunc.__name__ = func.__name__
78 newFunc.__doc__ = func.__doc__
79 newFunc.__dict__.update(func.__dict__)
80 return newFunc
81
82
83
84
85 ROSRPC = "rosrpc://"
86
88 """
89 utility function for parsing ROS-RPC URIs
90 @param uri: ROSRPC URI
91 @type uri: str
92 @return: address, port
93 @rtype: (str, int)
94 @raise ParameterInvalid: if uri is not a valid ROSRPC URI
95 """
96 if uri.startswith(ROSRPC):
97 dest_addr = uri[len(ROSRPC):]
98 else:
99 raise ParameterInvalid("Invalid protocol for ROS service URL: %s"%uri)
100 try:
101 if '/' in dest_addr:
102 dest_addr = dest_addr[:dest_addr.find('/')]
103 dest_addr, dest_port = dest_addr.split(':')
104 dest_port = int(dest_port)
105 except:
106 raise ParameterInvalid("ROS service URL is invalid: %s"%uri)
107 return dest_addr, dest_port
108
109
110
111
112 _rospy_logger = logging.getLogger("rospy.internal")
113
114 _logdebug_handlers = []
115 _loginfo_handlers = []
116 _logwarn_handlers = []
117 _logerr_handlers = []
118 _logfatal_handlers = []
119
120
121
122
123
125 """Internal rospy client library debug logging"""
126 _rospy_logger.debug(msg, *args)
128 """Internal rospy client library error logging"""
129 _rospy_logger.error(msg, *args)
131 """Internal rospy client library warn logging"""
132 _rospy_logger.warn(msg, *args)
133
155
157 """
158 Log a debug message to the /rosout topic
159 @param msg: message to log, may include formatting arguments
160 @type msg: str
161 @param args: format-string arguments, if necessary
162 """
163 if args:
164 msg = msg%args
165 for h in _logdebug_handlers:
166 h(msg)
167
169 """
170 Log a warning message to the /rosout topic
171 @param msg: message to log, may include formatting arguments
172 @type msg: str
173 @param args: format-string arguments, if necessary
174 """
175 if args:
176 msg = msg%args
177 for h in _logwarn_handlers:
178 h(msg)
179
181 """
182 Log an info message to the /rosout topic
183 @param msg: message to log, may include formatting arguments
184 @type msg: str
185 @param args: format-string arguments, if necessary
186 """
187 if args:
188 msg = msg%args
189 for h in _loginfo_handlers:
190 h(msg)
191 logout = loginfo
192
194 """
195 Log an error message to the /rosout topic
196 @param msg: message to log, may include formatting arguments
197 @type msg: str
198 @param args: format-string arguments, if necessary
199 """
200 if args:
201 msg = msg%args
202 for h in _logerr_handlers:
203 h(msg)
204 logerror = logerr
205
207 """
208 Log an error message to the /rosout topic
209 @param msg: message to log, may include formatting arguments
210 @type msg: str
211 @param args: format-string arguments, if necessary
212 """
213 if args:
214 msg = msg%args
215 for h in _logfatal_handlers:
216 h(msg)
217
218
219
220
221 MASTER_NAME = "master"
222
224 """
225 Get the value of ROS_ROOT.
226 @param env: override environment dictionary
227 @type env: dict
228 @param required: if True, fails with ROSException
229 @return: Value of ROS_ROOT environment
230 @rtype: str
231 @raise ROSException: if require is True and ROS_ROOT is not set
232 """
233 if env is None:
234 env = os.environ
235 ros_root = env.get(roslib.rosenv.ROS_ROOT, None)
236 if required and not ros_root:
237 raise rospy.exceptions.ROSException('%s is not set'%roslib.rosenv.ROS_ROOT)
238 return ros_root
239
240
241
242
243
244 _uri = None
246 """
247 Get this Node's URI.
248 @return: this Node's XMLRPC URI
249 @rtype: str
250 """
251 return _uri
252
254 """set the URI of the local node.
255 This is an internal API method, it does not actually affect the XMLRPC URI of the Node."""
256 global _uri
257 _uri = uri
258
259
260
261
262 _log_filename = None
286
288 - def emit(self, record):
290
291
292 logging.getLogger('rospy').addHandler(NullHandler())
293
294
295
296
297
298 _client_ready = False
299
300
302 """
303 Get the initialization state of the local node. If True, node has
304 been configured.
305 @return: True if local node initialized
306 @rtype: bool
307 """
308 return _client_ready
310 """
311 set the initialization state of the local node
312 @param initialized: True if node initialized
313 @type initialized: bool
314 """
315 global _client_ready
316 _client_ready = initialized
317
318 _shutdown_lock = threading.RLock()
319
320
321
322
323
324 _shutdown_flag = False
325 _in_shutdown = False
326
327
328
329
330 _shutdown_hooks = []
331 _preshutdown_hooks = []
332 _client_shutdown_hooks = []
333
334 _shutdown_threads = []
335
336 _signalChain = {}
337
339 """
340 @return: True if shutdown flag has been set
341 @rtype: bool
342 """
343 return _shutdown_flag
344
346 """
347 is_shutdown_requested is a state that occurs just before
348 is_shutdown. It is initiated when a shutdown requested is
349 received and continues until client shutdown handlers have been
350 called. After client shutdown handlers have been serviced, the
351 is_shutdown state becomes true.
352
353 @return: True if shutdown has been requested (but possibly not yet initiated)
354 @rtype: bool
355 """
356 return _in_shutdown
357
359 """
360 shared implementation of add_shutdown_hook and add_preshutdown_hook
361 """
362 if type(h) not in [types.FunctionType, types.MethodType]:
363 raise TypeError("shutdown hook [%s] must be a function: %s"%(h, type(h)))
364 if _shutdown_flag:
365 _logger.warn("add_shutdown_hook called after shutdown")
366 h("already shutdown")
367 return
368 with _shutdown_lock:
369 if hooks is None:
370
371 return
372 hooks.append(h)
373
392
394 """
395 Add client method to invoke when system shuts down. Unlike
396 L{add_shutdown_hook} and L{add_preshutdown_hooks}, these methods
397 will be called before any rospy internal shutdown code.
398
399 @param h: function that takes in a single string argument (shutdown reason)
400 @type h: fn(str)
401 """
402 _add_shutdown_hook(h, _client_shutdown_hooks)
403
405 """
406 Add method to invoke when system shuts down. Unlike
407 L{add_shutdown_hook}, these methods will be called before any
408 other shutdown hooks.
409
410 @param h: function that takes in a single string argument (shutdown reason)
411 @type h: fn(str)
412 """
413 _add_shutdown_hook(h, _preshutdown_hooks)
414
416 """
417 Add method to invoke when system shuts down.
418
419 Shutdown hooks are called in the order that they are
420 registered. This is an internal API method that is used to
421 cleanup. See the client X{on_shutdown()} method if you wish to
422 register client hooks.
423
424 @param h: function that takes in a single string argument (shutdown reason)
425 @type h: fn(str)
426 """
427 _add_shutdown_hook(h, _shutdown_hooks)
428
481
483 signal_shutdown("signal-"+str(sig))
484 prev_handler = _signalChain.get(sig, None)
485 if prev_handler is not None and not type(prev_handler) == int:
486 try:
487 prev_handler(sig, stackframe)
488 except KeyboardInterrupt:
489 pass
490
493 atexit.register(_ros_atexit)
494
495
497 """
498 register system signal handlers for SIGTERM and SIGINT
499 """
500 _signalChain[signal.SIGTERM] = signal.signal(signal.SIGTERM, _ros_signal)
501 _signalChain[signal.SIGINT] = signal.signal(signal.SIGINT, _ros_signal)
502
503
504
506 """
507 Validator that checks that parameter is a valid ROS topic name
508 """
509 def validator(param_value, caller_id):
510 v = valid_name_validator_resolved(param_name, param_value, caller_id)
511 if param_value == '/':
512 raise ParameterInvalid("ERROR: parameter [%s] cannot be the global namespace"%param_name)
513 return v
514 return validator
515
517 """
518 @return: instance for calling remote server or None if not a valid URI
519 @rtype: xmlrpclib.ServerProxy
520 """
521 if uri is None:
522 return None
523 uriValidate = urlparse.urlparse(uri)
524 if not uriValidate[0] or not uriValidate[1]:
525 return None
526 return xmlrpclib.ServerProxy(uri)
527