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
76 _logger = logging.getLogger("rospy.core")
77
78
79
80
81 _TIMEOUT_SHUTDOWN_JOIN = 5.
82
83 import warnings
85 """This is a decorator which can be used to mark functions
86 as deprecated. It will result in a warning being emmitted
87 when the function is used."""
88 def newFunc(*args, **kwargs):
89 warnings.warn("Call to deprecated function %s." % func.__name__,
90 category=DeprecationWarning, stacklevel=2)
91 return func(*args, **kwargs)
92 newFunc.__name__ = func.__name__
93 newFunc.__doc__ = func.__doc__
94 newFunc.__dict__.update(func.__dict__)
95 return newFunc
96
97
98
99
100 ROSRPC = "rosrpc://"
103 """
104 utility function for parsing ROS-RPC URIs
105 @param uri: ROSRPC URI
106 @type uri: str
107 @return: address, port
108 @rtype: (str, int)
109 @raise ParameterInvalid: if uri is not a valid ROSRPC URI
110 """
111 if uri.startswith(ROSRPC):
112 dest_addr = uri[len(ROSRPC):]
113 else:
114 raise ParameterInvalid("Invalid protocol for ROS service URL: %s"%uri)
115 try:
116 if '/' in dest_addr:
117 dest_addr = dest_addr[:dest_addr.find('/')]
118 dest_addr, dest_port = dest_addr.split(':')
119 dest_port = int(dest_port)
120 except:
121 raise ParameterInvalid("ROS service URL is invalid: %s"%uri)
122 return dest_addr, dest_port
123
124
125
126
127 _rospy_logger = logging.getLogger("rospy.internal")
134 """Internal rospy client library debug logging"""
135 _rospy_logger.debug(msg, *args)
137 """Internal rospy client library debug logging"""
138 _rospy_logger.info(msg, *args)
143 """Internal rospy client library warn logging"""
144 _rospy_logger.warn(msg, *args)
145
146 logdebug = logging.getLogger('rosout').debug
147
148 logwarn = logging.getLogger('rosout').warning
149
150 loginfo = logging.getLogger('rosout').info
151 logout = loginfo
152
153 logerr = logging.getLogger('rosout').error
154 logerror = logerr
155
156 logfatal = logging.getLogger('rosout').critical
183
184
185 _logging_throttle = LoggingThrottle()
189 caller_id = (
190 inspect.getabsfile(frame),
191 frame.f_lineno,
192 frame.f_lasti,
193 )
194 return pickle.dumps(caller_id)
195
200
203 caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
204 _logging_throttle(caller_id, loginfo, period, msg)
205
208 caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
209 _logging_throttle(caller_id, logwarn, period, msg)
210
213 caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
214 _logging_throttle(caller_id, logerr, period, msg)
215
220
221
222
223
224
225 MASTER_NAME = "master"
226
227 import warnings
228 import functools
230 """This is a decorator which can be used to mark functions
231 as deprecated. It will result in a warning being emmitted
232 when the function is used."""
233 @functools.wraps(func)
234 def newFunc(*args, **kwargs):
235 warnings.warn("Call to deprecated function %s." % func.__name__,
236 category=DeprecationWarning, stacklevel=2)
237 return func(*args, **kwargs)
238 return newFunc
239
242 """
243 Get the value of ROS_ROOT.
244 @param env: override environment dictionary
245 @type env: dict
246 @param required: if True, fails with ROSException
247 @return: Value of ROS_ROOT environment
248 @rtype: str
249 @raise ROSException: if require is True and ROS_ROOT is not set
250 """
251 if env is None:
252 env = os.environ
253 ros_root = rospkg.get_ros_root(env)
254 if required and not ros_root:
255 raise rospy.exceptions.ROSException('%s is not set'%rospkg.environment.ROS_ROOT)
256 return ros_root
257
258
259
260
261
262 _uri = None
264 """
265 Get this Node's URI.
266 @return: this Node's XMLRPC URI
267 @rtype: str
268 """
269 return _uri
270
272 """set the URI of the local node.
273 This is an internal API method, it does not actually affect the XMLRPC URI of the Node."""
274 global _uri
275 _uri = uri
276
277
278
279
280 _log_filename = None
304
306 - def emit(self, record):
308
309
310 logging.getLogger('rospy').addHandler(NullHandler())
311
312
313
314
315
316 _client_ready = False
320 """
321 Get the initialization state of the local node. If True, node has
322 been configured.
323 @return: True if local node initialized
324 @rtype: bool
325 """
326 return _client_ready
328 """
329 set the initialization state of the local node
330 @param initialized: True if node initialized
331 @type initialized: bool
332 """
333 global _client_ready
334 _client_ready = initialized
335
336 _shutdown_lock = threading.RLock()
337
338
339
340
341
342 _shutdown_flag = False
343 _in_shutdown = False
344
345
346
347
348 _shutdown_hooks = []
349 _preshutdown_hooks = []
350 _client_shutdown_hooks = []
351
352 _shutdown_threads = []
353
354 _signalChain = {}
357 """
358 @return: True if shutdown flag has been set
359 @rtype: bool
360 """
361 return _shutdown_flag
362
364 """
365 is_shutdown_requested is a state that occurs just before
366 is_shutdown. It is initiated when a shutdown requested is
367 received and continues until client shutdown handlers have been
368 called. After client shutdown handlers have been serviced, the
369 is_shutdown state becomes true.
370
371 @return: True if shutdown has been requested (but possibly not yet initiated)
372 @rtype: bool
373 """
374 return _in_shutdown
375
377 """
378 shared implementation of add_shutdown_hook and add_preshutdown_hook
379 """
380 if not callable(h):
381 raise TypeError("shutdown hook [%s] must be a function or callable object: %s"%(h, type(h)))
382 if _shutdown_flag:
383 _logger.warn("add_shutdown_hook called after shutdown")
384 if pass_reason_argument:
385 h("already shutdown")
386 else:
387 h()
388 return
389 with _shutdown_lock:
390 if hooks is None:
391
392 return
393 hooks.append(h)
394
413
415 """
416 Add client method to invoke when system shuts down. Unlike
417 L{add_shutdown_hook} and L{add_preshutdown_hooks}, these methods
418 will be called before any rospy internal shutdown code.
419
420 @param h: function with zero args
421 @type h: fn()
422 """
423 _add_shutdown_hook(h, _client_shutdown_hooks, pass_reason_argument=False)
424
426 """
427 Add method to invoke when system shuts down. Unlike
428 L{add_shutdown_hook}, these methods will be called before any
429 other shutdown hooks.
430
431 @param h: function that takes in a single string argument (shutdown reason)
432 @type h: fn(str)
433 """
434 _add_shutdown_hook(h, _preshutdown_hooks)
435
437 """
438 Add method to invoke when system shuts down.
439
440 Shutdown hooks are called in the order that they are
441 registered. This is an internal API method that is used to
442 cleanup. See the client X{on_shutdown()} method if you wish to
443 register client hooks.
444
445 @param h: function that takes in a single string argument (shutdown reason)
446 @type h: fn(str)
447 """
448 _add_shutdown_hook(h, _shutdown_hooks)
449
502
504 signal_shutdown("signal-"+str(sig))
505 prev_handler = _signalChain.get(sig, None)
506 if prev_handler is not None and not type(prev_handler) == int:
507 try:
508 prev_handler(sig, stackframe)
509 except KeyboardInterrupt:
510 pass
511
514 atexit.register(_ros_atexit)
518 """
519 register system signal handlers for SIGTERM and SIGINT
520 """
521 _signalChain[signal.SIGTERM] = signal.signal(signal.SIGTERM, _ros_signal)
522 _signalChain[signal.SIGINT] = signal.signal(signal.SIGINT, _ros_signal)
523
527 """
528 Validator that checks that parameter is a valid ROS topic name
529 """
530 def validator(param_value, caller_id):
531 v = valid_name_validator_resolved(param_name, param_value, caller_id)
532 if param_value == '/':
533 raise ParameterInvalid("ERROR: parameter [%s] cannot be the global namespace"%param_name)
534 return v
535 return validator
536
538 """
539 @return: instance for calling remote server or None if not a valid URI
540 @rtype: xmlrpclib.ServerProxy
541 """
542 if uri is None:
543 return None
544 uriValidate = urlparse.urlparse(uri)
545 if not uriValidate[0] or not uriValidate[1]:
546 return None
547 return xmlrpcclient.ServerProxy(uri)
548