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 import os
47 import signal
48 import sys
49 import threading
50 import time
51 import traceback
52 import types
53
54 try:
55 import urllib.parse as urlparse
56 except ImportError:
57 import urlparse
58
59 try:
60 import xmlrpc.client as xmlrpcclient
61 except ImportError:
62 import xmlrpclib as xmlrpcclient
63
64 import rospkg
65
66 import rosgraph.roslogging
67
68 import rospy.exceptions
69 import rospy.rostime
70
71 from rospy.names import *
72 from rospy.impl.validators import ParameterInvalid
73
74 from rosgraph_msgs.msg import Log
75 from functools import partial
76
77 _logger = logging.getLogger("rospy.core")
78
79
80
81
82 _TIMEOUT_SHUTDOWN_JOIN = 5.
83
84 import warnings
86 """This is a decorator which can be used to mark functions
87 as deprecated. It will result in a warning being emmitted
88 when the function is used."""
89 def newFunc(*args, **kwargs):
90 warnings.warn("Call to deprecated function %s." % func.__name__,
91 category=DeprecationWarning, stacklevel=2)
92 return func(*args, **kwargs)
93 newFunc.__name__ = func.__name__
94 newFunc.__doc__ = func.__doc__
95 newFunc.__dict__.update(func.__dict__)
96 return newFunc
97
98
99
100
101 ROSRPC = "rosrpc://"
104 """
105 utility function for parsing ROS-RPC URIs
106 @param uri: ROSRPC URI
107 @type uri: str
108 @return: address, port
109 @rtype: (str, int)
110 @raise ParameterInvalid: if uri is not a valid ROSRPC URI
111 """
112 if uri.startswith(ROSRPC):
113 dest_addr = uri[len(ROSRPC):]
114 else:
115 raise ParameterInvalid("Invalid protocol for ROS service URL: %s"%uri)
116 try:
117 if '/' in dest_addr:
118 dest_addr = dest_addr[:dest_addr.find('/')]
119 dest_addr, dest_port = dest_addr.split(':')
120 dest_port = int(dest_port)
121 except:
122 raise ParameterInvalid("ROS service URL is invalid: %s"%uri)
123 return dest_addr, dest_port
124
125
126
127
128 _rospy_logger = logging.getLogger("rospy.internal")
135 """Internal rospy client library debug logging"""
136 _rospy_logger.debug(msg, *args)
138 """Internal rospy client library debug logging"""
139 _rospy_logger.info(msg, *args)
144 """Internal rospy client library warn logging"""
145 _rospy_logger.warn(msg, *args)
146
149
150 name = kwargs.pop('logger_name', None)
151 throttle = kwargs.pop('logger_throttle', None)
152 level = kwargs.pop('logger_level', None)
153 once = kwargs.pop('logger_once', False)
154
155 rospy_logger = logging.getLogger('rosout')
156 if name:
157 rospy_logger = rospy_logger.getChild(name)
158 logfunc = getattr(rospy_logger, level)
159
160 if once:
161 caller_id = _frame_to_caller_id(inspect.currentframe().f_back.f_back)
162 if _logging_once(caller_id):
163 logfunc(msg, *args)
164 elif throttle:
165 caller_id = _frame_to_caller_id(inspect.currentframe().f_back.f_back)
166 if _logging_throttle(caller_id, throttle):
167 logfunc(msg, *args)
168 else:
169 logfunc(msg, *args)
170
173 _base_logger(msg, *args, logger_level='debug', **kwargs)
174
176 _base_logger(msg, *args, logger_level='info', **kwargs)
177
179 _base_logger(msg, *args, logger_level='warn', **kwargs)
180
181 -def logerr(msg, *args, **kwargs):
182 _base_logger(msg, *args, logger_level='error', **kwargs)
183
185 _base_logger(msg, *args, logger_level='critical', **kwargs)
186
187 logout = loginfo
188
189 logerror = logerr
193
194 last_logging_time_table = {}
195
197 """Do logging specified message periodically.
198
199 - caller_id (str): Id to identify the caller
200 - logging_func (function): Function to do logging.
201 - period (float): Period to do logging in second unit.
202 - msg (object): Message to do logging.
203 """
204 now = rospy.Time.now()
205
206 last_logging_time = self.last_logging_time_table.get(caller_id)
207
208 if (last_logging_time is None or
209 (now - last_logging_time) > rospy.Duration(period)):
210 self.last_logging_time_table[caller_id] = now
211 return True
212 return False
213
214
215 _logging_throttle = LoggingThrottle()
219 caller_id = (
220 inspect.getabsfile(frame),
221 frame.f_lineno,
222 frame.f_lasti,
223 )
224 return pickle.dumps(caller_id)
225
228 _base_logger(msg, logger_throttle=period, logger_level='debug')
229
231 _base_logger(msg, logger_throttle=period, logger_level='info')
232
234 _base_logger(msg, logger_throttle=period, logger_level='warn')
235
237 _base_logger(msg, logger_throttle=period, logger_level='error')
238
240 _base_logger(msg, logger_throttle=period, logger_level='critical')
241
251
252 _logging_once = LoggingOnce()
256 _base_logger(msg, logger_once=True, logger_level='debug')
257
259 _base_logger(msg, logger_once=True, logger_level='info')
260
262 _base_logger(msg, logger_once=True, logger_level='warn')
263
265 _base_logger(msg, logger_once=True, logger_level='error')
266
268 _base_logger(msg, logger_once=True, logger_level='critical')
269
270
271
272
273
274 MASTER_NAME = "master"
275
276 import warnings
277 import functools
279 """This is a decorator which can be used to mark functions
280 as deprecated. It will result in a warning being emmitted
281 when the function is used."""
282 @functools.wraps(func)
283 def newFunc(*args, **kwargs):
284 warnings.warn("Call to deprecated function %s." % func.__name__,
285 category=DeprecationWarning, stacklevel=2)
286 return func(*args, **kwargs)
287 return newFunc
288
291 """
292 Get the value of ROS_ROOT.
293 @param env: override environment dictionary
294 @type env: dict
295 @param required: if True, fails with ROSException
296 @return: Value of ROS_ROOT environment
297 @rtype: str
298 @raise ROSException: if require is True and ROS_ROOT is not set
299 """
300 if env is None:
301 env = os.environ
302 ros_root = rospkg.get_ros_root(env)
303 if required and not ros_root:
304 raise rospy.exceptions.ROSException('%s is not set'%rospkg.environment.ROS_ROOT)
305 return ros_root
306
307
308
309
310
311 _uri = None
313 """
314 Get this Node's URI.
315 @return: this Node's XMLRPC URI
316 @rtype: str
317 """
318 return _uri
319
321 """set the URI of the local node.
322 This is an internal API method, it does not actually affect the XMLRPC URI of the Node."""
323 global _uri
324 _uri = uri
325
326
327
328
329 _log_filename = None
354
356 - def emit(self, record):
358
359
360 logging.getLogger('rospy').addHandler(NullHandler())
361
362
363
364
365
366 _client_ready = False
370 """
371 Get the initialization state of the local node. If True, node has
372 been configured.
373 @return: True if local node initialized
374 @rtype: bool
375 """
376 return _client_ready
378 """
379 set the initialization state of the local node
380 @param initialized: True if node initialized
381 @type initialized: bool
382 """
383 global _client_ready
384 _client_ready = initialized
385
386 _shutdown_lock = threading.RLock()
387
388
389
390
391
392 _shutdown_flag = False
393 _in_shutdown = False
394
395
396
397
398 _shutdown_hooks = []
399 _preshutdown_hooks = []
400 _client_shutdown_hooks = []
401
402 _shutdown_threads = []
403
404 _signalChain = {}
407 """
408 @return: True if shutdown flag has been set
409 @rtype: bool
410 """
411 return _shutdown_flag
412
414 """
415 is_shutdown_requested is a state that occurs just before
416 is_shutdown. It is initiated when a shutdown requested is
417 received and continues until client shutdown handlers have been
418 called. After client shutdown handlers have been serviced, the
419 is_shutdown state becomes true.
420
421 @return: True if shutdown has been requested (but possibly not yet initiated)
422 @rtype: bool
423 """
424 return _in_shutdown
425
427 """
428 shared implementation of add_shutdown_hook and add_preshutdown_hook
429 """
430 if not callable(h):
431 raise TypeError("shutdown hook [%s] must be a function or callable object: %s"%(h, type(h)))
432 if _shutdown_flag:
433 _logger.warn("add_shutdown_hook called after shutdown")
434 if pass_reason_argument:
435 h("already shutdown")
436 else:
437 h()
438 return
439 with _shutdown_lock:
440 if hooks is None:
441
442 return
443 hooks.append(h)
444
463
465 """
466 Add client method to invoke when system shuts down. Unlike
467 L{add_shutdown_hook} and L{add_preshutdown_hooks}, these methods
468 will be called before any rospy internal shutdown code.
469
470 @param h: function with zero args
471 @type h: fn()
472 """
473 _add_shutdown_hook(h, _client_shutdown_hooks, pass_reason_argument=False)
474
476 """
477 Add method to invoke when system shuts down. Unlike
478 L{add_shutdown_hook}, these methods will be called before any
479 other shutdown hooks.
480
481 @param h: function that takes in a single string argument (shutdown reason)
482 @type h: fn(str)
483 """
484 _add_shutdown_hook(h, _preshutdown_hooks)
485
487 """
488 Add method to invoke when system shuts down.
489
490 Shutdown hooks are called in the order that they are
491 registered. This is an internal API method that is used to
492 cleanup. See the client X{on_shutdown()} method if you wish to
493 register client hooks.
494
495 @param h: function that takes in a single string argument (shutdown reason)
496 @type h: fn(str)
497 """
498 _add_shutdown_hook(h, _shutdown_hooks)
499
552
554 signal_shutdown("signal-"+str(sig))
555 prev_handler = _signalChain.get(sig, None)
556 if prev_handler is not None and not type(prev_handler) == int:
557 try:
558 prev_handler(sig, stackframe)
559 except KeyboardInterrupt:
560 pass
561
564 atexit.register(_ros_atexit)
568 """
569 register system signal handlers for SIGTERM and SIGINT
570 """
571 _signalChain[signal.SIGTERM] = signal.signal(signal.SIGTERM, _ros_signal)
572 _signalChain[signal.SIGINT] = signal.signal(signal.SIGINT, _ros_signal)
573
577 """
578 Validator that checks that parameter is a valid ROS topic name
579 """
580 def validator(param_value, caller_id):
581 v = valid_name_validator_resolved(param_name, param_value, caller_id)
582 if param_value == '/':
583 raise ParameterInvalid("ERROR: parameter [%s] cannot be the global namespace"%param_name)
584 return v
585 return validator
586
588 """
589 @return: instance for calling remote server or None if not a valid URI
590 @rtype: xmlrpclib.ServerProxy
591 """
592 if uri is None:
593 return None
594 uriValidate = urlparse.urlparse(uri)
595 if not uriValidate[0] or not uriValidate[1]:
596 return None
597 return xmlrpcclient.ServerProxy(uri)
598