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
38
39 import atexit
40 try:
41 import cPickle as pickle
42 except ImportError:
43 import pickle
44 import inspect
45 import logging
46 from hashlib import md5
47 import os
48 import signal
49 import sys
50 import threading
51 import time
52 import traceback
53 import types
54
55 try:
56 import urllib.parse as urlparse
57 except ImportError:
58 import urlparse
59
60 try:
61 import xmlrpc.client as xmlrpcclient
62 except ImportError:
63 import xmlrpclib as xmlrpcclient
64
65 import rospkg
66
67 import rosgraph.roslogging
68
69 import rospy.exceptions
70 import rospy.rostime
71
72 from rospy.names import *
73 from rospy.impl.validators import ParameterInvalid
74
75 from rosgraph_msgs.msg import Log
76 from functools import partial
77
78 _logger = logging.getLogger("rospy.core")
79
80
81
82
83 _TIMEOUT_SHUTDOWN_JOIN = 5.
84
85 import warnings
87 """This is a decorator which can be used to mark functions
88 as deprecated. It will result in a warning being emitted
89 when the function is used."""
90 def newFunc(*args, **kwargs):
91 warnings.warn("Call to deprecated function %s." % func.__name__,
92 category=DeprecationWarning, stacklevel=2)
93 return func(*args, **kwargs)
94 newFunc.__name__ = func.__name__
95 newFunc.__doc__ = func.__doc__
96 newFunc.__dict__.update(func.__dict__)
97 return newFunc
98
99
100
101
102 ROSRPC = "rosrpc://"
105 """
106 utility function for parsing ROS-RPC URIs
107 @param uri: ROSRPC URI
108 @type uri: str
109 @return: address, port
110 @rtype: (str, int)
111 @raise ParameterInvalid: if uri is not a valid ROSRPC URI
112 """
113 if uri.startswith(ROSRPC):
114 dest_addr = uri[len(ROSRPC):]
115 else:
116 raise ParameterInvalid("Invalid protocol for ROS service URL: %s"%uri)
117 try:
118 if '/' in dest_addr:
119 dest_addr = dest_addr[:dest_addr.find('/')]
120 dest_addr, dest_port = dest_addr.split(':')
121 dest_port = int(dest_port)
122 except:
123 raise ParameterInvalid("ROS service URL is invalid: %s"%uri)
124 return dest_addr, dest_port
125
126
127
128
129 _rospy_logger = logging.getLogger("rospy.internal")
130
131
132
133
134
135 -def rospydebug(msg, *args, **kwargs):
136 """Internal rospy client library debug logging"""
137 _rospy_logger.debug(msg, *args, **kwargs)
139 """Internal rospy client library debug logging"""
140 _rospy_logger.info(msg, *args, **kwargs)
142 """Internal rospy client library error logging"""
143 _rospy_logger.error(msg, *args, **kwargs)
145 """Internal rospy client library warn logging"""
146 _rospy_logger.warn(msg, *args, **kwargs)
147
150 caller_id = (
151 inspect.getabsfile(frame),
152 frame.f_lineno,
153 frame.f_lasti,
154 )
155 return pickle.dumps(caller_id)
156
157
158 -def _base_logger(msg, args, kwargs, throttle=None,
159 throttle_identical=False, level=None, once=False):
160
161 rospy_logger = logging.getLogger('rosout')
162 name = kwargs.pop('logger_name', None)
163 if name:
164 rospy_logger = rospy_logger.getChild(name)
165 logfunc = getattr(rospy_logger, level)
166
167 if once:
168 caller_id = _frame_to_caller_id(inspect.currentframe().f_back.f_back)
169 if _logging_once(caller_id):
170 logfunc(msg, *args, **kwargs)
171 elif throttle_identical:
172 caller_id = _frame_to_caller_id(inspect.currentframe().f_back.f_back)
173 throttle_elapsed = False
174 if throttle is not None:
175 throttle_elapsed = _logging_throttle(caller_id, throttle)
176 if _logging_identical(caller_id, msg) or throttle_elapsed:
177 logfunc(msg, *args, **kwargs)
178 elif throttle:
179 caller_id = _frame_to_caller_id(inspect.currentframe().f_back.f_back)
180 if _logging_throttle(caller_id, throttle):
181 logfunc(msg, *args, **kwargs)
182 else:
183 logfunc(msg, *args, **kwargs)
184
187 _base_logger(msg, args, kwargs, level='debug')
188
190 _base_logger(msg, args, kwargs, level='info')
191
193 _base_logger(msg, args, kwargs, level='warn')
194
195 -def logerr(msg, *args, **kwargs):
196 _base_logger(msg, args, kwargs, level='error')
197
199 _base_logger(msg, args, kwargs, level='critical')
200
201 logout = loginfo
202
203 logerror = logerr
231
232
233 _logging_throttle = LoggingThrottle()
237 _base_logger(msg, args, kwargs, throttle=period, level='debug')
238
240 _base_logger(msg, args, kwargs, throttle=period, level='info')
241
243 _base_logger(msg, args, kwargs, throttle=period, level='warn')
244
246 _base_logger(msg, args, kwargs, throttle=period, level='error')
247
249 _base_logger(msg, args, kwargs, throttle=period, level='critical')
250
253
254 last_logging_msg_table = {}
255
257 """Do logging specified message only if distinct from last message.
258
259 - caller_id (str): Id to identify the caller
260 - msg (str): Contents of message to log
261 """
262 msg_hash = md5(msg.encode()).hexdigest()
263
264 if msg_hash != self.last_logging_msg_table.get(caller_id):
265 self.last_logging_msg_table[caller_id] = msg_hash
266 return True
267 return False
268
269
270 _logging_identical = LoggingIdentical()
274 _base_logger(msg, args, kwargs, throttle=period, throttle_identical=True,
275 level='debug')
276
278 _base_logger(msg, args, kwargs, throttle=period, throttle_identical=True,
279 level='info')
280
282 _base_logger(msg, args, kwargs, throttle=period, throttle_identical=True,
283 level='warn')
284
286 _base_logger(msg, args, kwargs, throttle=period, throttle_identical=True,
287 level='error')
288
290 _base_logger(msg, args, kwargs, throttle=period, throttle_identical=True,
291 level='critical')
292
303
304 _logging_once = LoggingOnce()
308 _base_logger(msg, args, kwargs, once=True, level='debug')
309
311 _base_logger(msg, args, kwargs, once=True, level='info')
312
314 _base_logger(msg, args, kwargs, once=True, level='warn')
315
317 _base_logger(msg, args, kwargs, once=True, level='error')
318
320 _base_logger(msg, args, kwargs, once=True, level='critical')
321
322
323
324
325
326 MASTER_NAME = "master"
327
328 import warnings
329 import functools
331 """This is a decorator which can be used to mark functions
332 as deprecated. It will result in a warning being emitted
333 when the function is used."""
334 @functools.wraps(func)
335 def newFunc(*args, **kwargs):
336 warnings.warn("Call to deprecated function %s." % func.__name__,
337 category=DeprecationWarning, stacklevel=2)
338 return func(*args, **kwargs)
339 return newFunc
340
343 """
344 Get the value of ROS_ROOT.
345 @param env: override environment dictionary
346 @type env: dict
347 @param required: if True, fails with ROSException
348 @return: Value of ROS_ROOT environment
349 @rtype: str
350 @raise ROSException: if require is True and ROS_ROOT is not set
351 """
352 if env is None:
353 env = os.environ
354 ros_root = rospkg.get_ros_root(env)
355 if required and not ros_root:
356 raise rospy.exceptions.ROSException('%s is not set'%rospkg.environment.ROS_ROOT)
357 return ros_root
358
359
360
361
362
363 _uri = None
365 """
366 Get this Node's URI.
367 @return: this Node's XMLRPC URI
368 @rtype: str
369 """
370 return _uri
371
373 """set the URI of the local node.
374 This is an internal API method, it does not actually affect the XMLRPC URI of the Node."""
375 global _uri
376 _uri = uri
377
378
379
380
381 _log_filename = None
406
408 - def emit(self, record):
410
411
412 logging.getLogger('rospy').addHandler(NullHandler())
413
414
415
416
417
418 _client_ready = False
422 """
423 Get the initialization state of the local node. If True, node has
424 been configured.
425 @return: True if local node initialized
426 @rtype: bool
427 """
428 return _client_ready
430 """
431 set the initialization state of the local node
432 @param initialized: True if node initialized
433 @type initialized: bool
434 """
435 global _client_ready
436 _client_ready = initialized
437
438 _shutdown_lock = threading.RLock()
439
440
441
442
443
444 _shutdown_flag = False
445 _in_shutdown = False
446
447
448
449
450 _shutdown_hooks = []
451 _preshutdown_hooks = []
452 _client_shutdown_hooks = []
453
454 _shutdown_threads = []
455
456 _signalChain = {}
459 """
460 @return: True if shutdown flag has been set
461 @rtype: bool
462 """
463 return _shutdown_flag
464
466 """
467 is_shutdown_requested is a state that occurs just before
468 is_shutdown. It is initiated when a shutdown requested is
469 received and continues until client shutdown handlers have been
470 called. After client shutdown handlers have been serviced, the
471 is_shutdown state becomes true.
472
473 @return: True if shutdown has been requested (but possibly not yet initiated)
474 @rtype: bool
475 """
476 return _in_shutdown
477
479 """
480 shared implementation of add_shutdown_hook and add_preshutdown_hook
481 """
482 if not callable(h):
483 raise TypeError("shutdown hook [%s] must be a function or callable object: %s"%(h, type(h)))
484 if _shutdown_flag:
485 _logger.warn("add_shutdown_hook called after shutdown")
486 if pass_reason_argument:
487 h("already shutdown")
488 else:
489 h()
490 return
491 with _shutdown_lock:
492 if hooks is None:
493
494 return
495 hooks.append(h)
496
515
517 """
518 Add client method to invoke when system shuts down. Unlike
519 L{add_shutdown_hook} and L{add_preshutdown_hooks}, these methods
520 will be called before any rospy internal shutdown code.
521
522 @param h: function with zero args
523 @type h: fn()
524 """
525 _add_shutdown_hook(h, _client_shutdown_hooks, pass_reason_argument=False)
526
528 """
529 Add method to invoke when system shuts down. Unlike
530 L{add_shutdown_hook}, these methods will be called before any
531 other shutdown hooks.
532
533 @param h: function that takes in a single string argument (shutdown reason)
534 @type h: fn(str)
535 """
536 _add_shutdown_hook(h, _preshutdown_hooks)
537
539 """
540 Add method to invoke when system shuts down.
541
542 Shutdown hooks are called in the order that they are
543 registered. This is an internal API method that is used to
544 cleanup. See the client X{on_shutdown()} method if you wish to
545 register client hooks.
546
547 @param h: function that takes in a single string argument (shutdown reason)
548 @type h: fn(str)
549 """
550 _add_shutdown_hook(h, _shutdown_hooks)
551
604
606 signal_shutdown("signal-"+str(sig))
607 prev_handler = _signalChain.get(sig, None)
608 if callable(prev_handler):
609 try:
610 prev_handler(sig, stackframe)
611 except KeyboardInterrupt:
612 pass
613
616 atexit.register(_ros_atexit)
620 """
621 register system signal handlers for SIGTERM and SIGINT
622 """
623 _signalChain[signal.SIGTERM] = signal.signal(signal.SIGTERM, _ros_signal)
624 _signalChain[signal.SIGINT] = signal.signal(signal.SIGINT, _ros_signal)
625
629 """
630 Validator that checks that parameter is a valid ROS topic name
631 """
632 def validator(param_value, caller_id):
633 v = valid_name_validator_resolved(param_name, param_value, caller_id)
634 if param_value == '/':
635 raise ParameterInvalid("ERROR: parameter [%s] cannot be the global namespace"%param_name)
636 return v
637 return validator
638
639 _xmlrpc_cache = {}
640 _xmlrpc_lock = threading.Lock()
643 """
644 @return: instance for calling remote server or None if not a valid URI
645 @rtype: xmlrpclib.ServerProxy
646 """
647 if uri is None:
648 return None
649 uriValidate = urlparse.urlparse(uri)
650 if not uriValidate[0] or not uriValidate[1]:
651 return None
652 if not cache:
653 return xmlrpcclient.ServerProxy(uri)
654 if uri not in _xmlrpc_cache:
655 with _xmlrpc_lock:
656 if uri not in _xmlrpc_cache:
657 _xmlrpc_cache[uri] = _LockedServerProxy(uri)
658 return _xmlrpc_cache[uri]
659
662
664 xmlrpcclient.ServerProxy.__init__(self, *args, **kwargs)
665 self._lock = threading.Lock()
666
668 with self._lock:
669 return xmlrpcclient.ServerProxy._ServerProxy__request(
670 self, methodname, params)
671