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 import logging
41 import os
42 import signal
43 import sys
44 import threading
45 import time
46 import traceback
47 import types
48
49 try:
50 import urllib.parse as urlparse
51 except ImportError:
52 import urlparse
53
54 try:
55 import xmlrpc.client as xmlrpcclient
56 except ImportError:
57 import xmlrpclib as xmlrpcclient
58
59
60 import roslib.rosenv
61 import roslib.roslogging
62
63 import rospy.exceptions
64 import rospy.rostime
65
66 from rospy.names import *
67 from rospy.impl.validators import ParameterInvalid
68
69 from rosgraph_msgs.msg import Log
70
71 _logger = logging.getLogger("rospy.core")
72
73
74
75
76 _TIMEOUT_SHUTDOWN_JOIN = 5.
77
78 import warnings
80 """This is a decorator which can be used to mark functions
81 as deprecated. It will result in a warning being emmitted
82 when the function is used."""
83 def newFunc(*args, **kwargs):
84 warnings.warn("Call to deprecated function %s." % func.__name__,
85 category=DeprecationWarning, stacklevel=2)
86 return func(*args, **kwargs)
87 newFunc.__name__ = func.__name__
88 newFunc.__doc__ = func.__doc__
89 newFunc.__dict__.update(func.__dict__)
90 return newFunc
91
92
93
94
95 ROSRPC = "rosrpc://"
96
98 """
99 utility function for parsing ROS-RPC URIs
100 @param uri: ROSRPC URI
101 @type uri: str
102 @return: address, port
103 @rtype: (str, int)
104 @raise ParameterInvalid: if uri is not a valid ROSRPC URI
105 """
106 if uri.startswith(ROSRPC):
107 dest_addr = uri[len(ROSRPC):]
108 else:
109 raise ParameterInvalid("Invalid protocol for ROS service URL: %s"%uri)
110 try:
111 if '/' in dest_addr:
112 dest_addr = dest_addr[:dest_addr.find('/')]
113 dest_addr, dest_port = dest_addr.split(':')
114 dest_port = int(dest_port)
115 except:
116 raise ParameterInvalid("ROS service URL is invalid: %s"%uri)
117 return dest_addr, dest_port
118
119
120
121
122 _rospy_logger = logging.getLogger("rospy.internal")
123
124 _logdebug_handlers = []
125 _loginfo_handlers = []
126 _logwarn_handlers = []
127 _logerr_handlers = []
128 _logfatal_handlers = []
129
130
131
132
133
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)
141 """Internal rospy client library error logging"""
142 _rospy_logger.error(msg, *args)
144 """Internal rospy client library warn logging"""
145 _rospy_logger.warn(msg, *args)
146
168
170 """
171 Log a debug message to the /rosout topic
172 @param msg: message to log, may include formatting arguments
173 @type msg: str
174 @param args: format-string arguments, if necessary
175 """
176 if args:
177 msg = msg%args
178 for h in _logdebug_handlers:
179 h(msg)
180
182 """
183 Log a warning message to the /rosout topic
184 @param msg: message to log, may include formatting arguments
185 @type msg: str
186 @param args: format-string arguments, if necessary
187 """
188 if args:
189 msg = msg%args
190 for h in _logwarn_handlers:
191 h(msg)
192
194 """
195 Log an info 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 _loginfo_handlers:
203 h(msg)
204 logout = loginfo
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 _logerr_handlers:
216 h(msg)
217 logerror = logerr
218
220 """
221 Log an error message to the /rosout topic
222 @param msg: message to log, may include formatting arguments
223 @type msg: str
224 @param args: format-string arguments, if necessary
225 """
226 if args:
227 msg = msg%args
228 for h in _logfatal_handlers:
229 h(msg)
230
231
232
233
234 MASTER_NAME = "master"
235
237 """
238 Get the value of ROS_ROOT.
239 @param env: override environment dictionary
240 @type env: dict
241 @param required: if True, fails with ROSException
242 @return: Value of ROS_ROOT environment
243 @rtype: str
244 @raise ROSException: if require is True and ROS_ROOT is not set
245 """
246 if env is None:
247 env = os.environ
248 ros_root = env.get(roslib.rosenv.ROS_ROOT, None)
249 if required and not ros_root:
250 raise rospy.exceptions.ROSException('%s is not set'%roslib.rosenv.ROS_ROOT)
251 return ros_root
252
253
254
255
256
257 _uri = None
259 """
260 Get this Node's URI.
261 @return: this Node's XMLRPC URI
262 @rtype: str
263 """
264 return _uri
265
267 """set the URI of the local node.
268 This is an internal API method, it does not actually affect the XMLRPC URI of the Node."""
269 global _uri
270 _uri = uri
271
272
273
274
275 _log_filename = None
299
301 - def emit(self, record):
303
304
305 logging.getLogger('rospy').addHandler(NullHandler())
306
307
308
309
310
311 _client_ready = False
312
313
315 """
316 Get the initialization state of the local node. If True, node has
317 been configured.
318 @return: True if local node initialized
319 @rtype: bool
320 """
321 return _client_ready
323 """
324 set the initialization state of the local node
325 @param initialized: True if node initialized
326 @type initialized: bool
327 """
328 global _client_ready
329 _client_ready = initialized
330
331 _shutdown_lock = threading.RLock()
332
333
334
335
336
337 _shutdown_flag = False
338 _in_shutdown = False
339
340
341
342
343 _shutdown_hooks = []
344 _preshutdown_hooks = []
345 _client_shutdown_hooks = []
346
347 _shutdown_threads = []
348
349 _signalChain = {}
350
352 """
353 @return: True if shutdown flag has been set
354 @rtype: bool
355 """
356 return _shutdown_flag
357
359 """
360 is_shutdown_requested is a state that occurs just before
361 is_shutdown. It is initiated when a shutdown requested is
362 received and continues until client shutdown handlers have been
363 called. After client shutdown handlers have been serviced, the
364 is_shutdown state becomes true.
365
366 @return: True if shutdown has been requested (but possibly not yet initiated)
367 @rtype: bool
368 """
369 return _in_shutdown
370
372 """
373 shared implementation of add_shutdown_hook and add_preshutdown_hook
374 """
375 if type(h) not in [types.FunctionType, types.MethodType]:
376 raise TypeError("shutdown hook [%s] must be a function: %s"%(h, type(h)))
377 if _shutdown_flag:
378 _logger.warn("add_shutdown_hook called after shutdown")
379 h("already shutdown")
380 return
381 with _shutdown_lock:
382 if hooks is None:
383
384 return
385 hooks.append(h)
386
405
407 """
408 Add client method to invoke when system shuts down. Unlike
409 L{add_shutdown_hook} and L{add_preshutdown_hooks}, these methods
410 will be called before any rospy internal shutdown code.
411
412 @param h: function that takes in a single string argument (shutdown reason)
413 @type h: fn(str)
414 """
415 _add_shutdown_hook(h, _client_shutdown_hooks)
416
418 """
419 Add method to invoke when system shuts down. Unlike
420 L{add_shutdown_hook}, these methods will be called before any
421 other shutdown hooks.
422
423 @param h: function that takes in a single string argument (shutdown reason)
424 @type h: fn(str)
425 """
426 _add_shutdown_hook(h, _preshutdown_hooks)
427
429 """
430 Add method to invoke when system shuts down.
431
432 Shutdown hooks are called in the order that they are
433 registered. This is an internal API method that is used to
434 cleanup. See the client X{on_shutdown()} method if you wish to
435 register client hooks.
436
437 @param h: function that takes in a single string argument (shutdown reason)
438 @type h: fn(str)
439 """
440 _add_shutdown_hook(h, _shutdown_hooks)
441
494
496 signal_shutdown("signal-"+str(sig))
497 prev_handler = _signalChain.get(sig, None)
498 if prev_handler is not None and not type(prev_handler) == int:
499 try:
500 prev_handler(sig, stackframe)
501 except KeyboardInterrupt:
502 pass
503
506 atexit.register(_ros_atexit)
507
508
510 """
511 register system signal handlers for SIGTERM and SIGINT
512 """
513 _signalChain[signal.SIGTERM] = signal.signal(signal.SIGTERM, _ros_signal)
514 _signalChain[signal.SIGINT] = signal.signal(signal.SIGINT, _ros_signal)
515
516
517
519 """
520 Validator that checks that parameter is a valid ROS topic name
521 """
522 def validator(param_value, caller_id):
523 v = valid_name_validator_resolved(param_name, param_value, caller_id)
524 if param_value == '/':
525 raise ParameterInvalid("ERROR: parameter [%s] cannot be the global namespace"%param_name)
526 return v
527 return validator
528
530 """
531 @return: instance for calling remote server or None if not a valid URI
532 @rtype: xmlrpclib.ServerProxy
533 """
534 if uri is None:
535 return None
536 uriValidate = urlparse.urlparse(uri)
537 if not uriValidate[0] or not uriValidate[1]:
538 return None
539 return xmlrpcclient.ServerProxy(uri)
540