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
160
161 last_logging_time_table = {}
162
163 - def __call__(self, caller_id, logging_func, period, msg):
164 """Do logging specified message periodically.
165
166 - caller_id (str): Id to identify the caller
167 - logging_func (function): Function to do logging.
168 - period (float): Period to do logging in second unit.
169 - msg (object): Message to do logging.
170 """
171 now = rospy.Time.now()
172
173 last_logging_time = self.last_logging_time_table.get(caller_id)
174
175 if (last_logging_time is None or
176 (now - last_logging_time) > rospy.Duration(period)):
177 logging_func(msg)
178 self.last_logging_time_table[caller_id] = now
179
180
181 _logging_throttle = LoggingThrottle()
185 frame, _, lineno, _, code, _ = frame_record
186 caller_id = (
187 inspect.getabsfile(frame),
188 lineno,
189 frame.f_lasti,
190 )
191 return pickle.dumps(caller_id)
192
197
202
207
210 caller_id = _frame_record_to_caller_id(inspect.stack()[1])
211 _logging_throttle(caller_id, logerr, period, msg)
212
217
218
219
220
221
222 MASTER_NAME = "master"
223
224 import warnings
225 import functools
227 """This is a decorator which can be used to mark functions
228 as deprecated. It will result in a warning being emmitted
229 when the function is used."""
230 @functools.wraps(func)
231 def newFunc(*args, **kwargs):
232 warnings.warn("Call to deprecated function %s." % func.__name__,
233 category=DeprecationWarning, stacklevel=2)
234 return func(*args, **kwargs)
235 return newFunc
236
239 """
240 Get the value of ROS_ROOT.
241 @param env: override environment dictionary
242 @type env: dict
243 @param required: if True, fails with ROSException
244 @return: Value of ROS_ROOT environment
245 @rtype: str
246 @raise ROSException: if require is True and ROS_ROOT is not set
247 """
248 if env is None:
249 env = os.environ
250 ros_root = rospkg.get_ros_root(env)
251 if required and not ros_root:
252 raise rospy.exceptions.ROSException('%s is not set'%rospkg.environment.ROS_ROOT)
253 return ros_root
254
255
256
257
258
259 _uri = None
261 """
262 Get this Node's URI.
263 @return: this Node's XMLRPC URI
264 @rtype: str
265 """
266 return _uri
267
269 """set the URI of the local node.
270 This is an internal API method, it does not actually affect the XMLRPC URI of the Node."""
271 global _uri
272 _uri = uri
273
274
275
276
277 _log_filename = None
301
303 - def emit(self, record):
305
306
307 logging.getLogger('rospy').addHandler(NullHandler())
308
309
310
311
312
313 _client_ready = False
317 """
318 Get the initialization state of the local node. If True, node has
319 been configured.
320 @return: True if local node initialized
321 @rtype: bool
322 """
323 return _client_ready
325 """
326 set the initialization state of the local node
327 @param initialized: True if node initialized
328 @type initialized: bool
329 """
330 global _client_ready
331 _client_ready = initialized
332
333 _shutdown_lock = threading.RLock()
334
335
336
337
338
339 _shutdown_flag = False
340 _in_shutdown = False
341
342
343
344
345 _shutdown_hooks = []
346 _preshutdown_hooks = []
347 _client_shutdown_hooks = []
348
349 _shutdown_threads = []
350
351 _signalChain = {}
354 """
355 @return: True if shutdown flag has been set
356 @rtype: bool
357 """
358 return _shutdown_flag
359
361 """
362 is_shutdown_requested is a state that occurs just before
363 is_shutdown. It is initiated when a shutdown requested is
364 received and continues until client shutdown handlers have been
365 called. After client shutdown handlers have been serviced, the
366 is_shutdown state becomes true.
367
368 @return: True if shutdown has been requested (but possibly not yet initiated)
369 @rtype: bool
370 """
371 return _in_shutdown
372
374 """
375 shared implementation of add_shutdown_hook and add_preshutdown_hook
376 """
377 if not callable(h):
378 raise TypeError("shutdown hook [%s] must be a function or callable object: %s"%(h, type(h)))
379 if _shutdown_flag:
380 _logger.warn("add_shutdown_hook called after shutdown")
381 if pass_reason_argument:
382 h("already shutdown")
383 else:
384 h()
385 return
386 with _shutdown_lock:
387 if hooks is None:
388
389 return
390 hooks.append(h)
391
410
412 """
413 Add client method to invoke when system shuts down. Unlike
414 L{add_shutdown_hook} and L{add_preshutdown_hooks}, these methods
415 will be called before any rospy internal shutdown code.
416
417 @param h: function with zero args
418 @type h: fn()
419 """
420 _add_shutdown_hook(h, _client_shutdown_hooks, pass_reason_argument=False)
421
423 """
424 Add method to invoke when system shuts down. Unlike
425 L{add_shutdown_hook}, these methods will be called before any
426 other shutdown hooks.
427
428 @param h: function that takes in a single string argument (shutdown reason)
429 @type h: fn(str)
430 """
431 _add_shutdown_hook(h, _preshutdown_hooks)
432
434 """
435 Add method to invoke when system shuts down.
436
437 Shutdown hooks are called in the order that they are
438 registered. This is an internal API method that is used to
439 cleanup. See the client X{on_shutdown()} method if you wish to
440 register client hooks.
441
442 @param h: function that takes in a single string argument (shutdown reason)
443 @type h: fn(str)
444 """
445 _add_shutdown_hook(h, _shutdown_hooks)
446
499
501 signal_shutdown("signal-"+str(sig))
502 prev_handler = _signalChain.get(sig, None)
503 if prev_handler is not None and not type(prev_handler) == int:
504 try:
505 prev_handler(sig, stackframe)
506 except KeyboardInterrupt:
507 pass
508
511 atexit.register(_ros_atexit)
515 """
516 register system signal handlers for SIGTERM and SIGINT
517 """
518 _signalChain[signal.SIGTERM] = signal.signal(signal.SIGTERM, _ros_signal)
519 _signalChain[signal.SIGINT] = signal.signal(signal.SIGINT, _ros_signal)
520
524 """
525 Validator that checks that parameter is a valid ROS topic name
526 """
527 def validator(param_value, caller_id):
528 v = valid_name_validator_resolved(param_name, param_value, caller_id)
529 if param_value == '/':
530 raise ParameterInvalid("ERROR: parameter [%s] cannot be the global namespace"%param_name)
531 return v
532 return validator
533
535 """
536 @return: instance for calling remote server or None if not a valid URI
537 @rtype: xmlrpclib.ServerProxy
538 """
539 if uri is None:
540 return None
541 uriValidate = urlparse.urlparse(uri)
542 if not uriValidate[0] or not uriValidate[1]:
543 return None
544 return xmlrpcclient.ServerProxy(uri)
545