Package node_manager_fkie :: Module default_cfg_handler
[frames] | no frames]

Source Code for Module node_manager_fkie.default_cfg_handler

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Fraunhofer nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32   
 33  from python_qt_binding.QtCore import QObject, Signal 
 34  import threading 
 35  import time 
 36   
 37  import rospy 
 38   
 39  import node_manager_fkie as nm 
 40   
 41   
 42  try: 
 43      from multimaster_msgs_fkie.srv import ListDescription, ListNodes  # , LoadLaunch, Task 
 44  except ImportError, e: 
 45      import sys 
 46      print >> sys.stderr, "Can't import services of default_cfg_fkie. Is default_cfg_fkie package compiled?" 
 47      raise ImportError(str(e)) 
 48   
 49   
50 -class DefaultConfigHandler(QObject):
51 ''' 52 A class to retrieve the list of nodes from the default configuration service. 53 The received node list will be published by sending a QT signal. To retrieve 54 the configuration a new thread will be created. 55 ''' 56 node_list_signal = Signal(str, str, list) 57 ''' 58 node_list_signal is a signal, which is emitted, if a new list with nodes is 59 retrieved. The signal has the URI of the service, the name of the service and 60 a list with node names as parameter. 61 ''' 62 description_signal = Signal(str, str, list) 63 ''' 64 description_signal is a signal, which is emitted, if a new list with descriptions is 65 retrieved. The signal has the URI of the service, the name of the service and 66 a list with descriptions (U{multimaster_msgs_fkie.srv.ListDescription<http://docs.ros.org/api/multimaster_msgs_fkie/html/srv/ListDescription.html>} Response) parameter. 67 ''' 68 err_signal = Signal(str, str, str) 69
70 - def __init__(self):
71 QObject.__init__(self) 72 self.__serviceThreads = {} 73 self._lock = threading.RLock()
74
75 - def stop(self):
76 print " Shutdown default config update threads..." 77 for _, service in self.__serviceThreads.iteritems(): 78 service.join(3) 79 print " Default config update threads are off!"
80
81 - def requestNodeList(self, service_uri, service, delay_exec=0.0):
82 ''' 83 This method starts a thread to get the informations about the default 84 configured nodes. If all informations are retrieved, a C{node_list_signal} of 85 this class will be emitted. If for given service a thread is 86 already running, the request will be ignored. 87 This method is thread safe. 88 89 @param service_uri: the URI of the service 90 @type service_uri: C{str} 91 @param service: the name of service to get the node list 92 @type service: C{str} 93 @param delay_exec: delayd the execution 94 @type delay_exec: C{float} 95 ''' 96 with self._lock: 97 if (service_uri, service) not in self.__serviceThreads: 98 upthread = ServiceThread(service_uri, service, delay_exec) 99 upthread.update_signal.connect(self._on_node_list) 100 upthread.err_signal.connect(self._on_err) 101 self.__serviceThreads[(service_uri, service)] = upthread 102 upthread.start()
103
104 - def requestDescriptionList(self, service_uri, service, delay_exec=0.0):
105 ''' 106 This method starts a thread to get the descriptions from the default 107 configuration node. If all informations are retrieved, a C{description_signal} of 108 this class will be emitted. If for given service a thread is 109 already running, the request will be ignored. 110 This method is thread safe. 111 112 @param service_uri: the URI of the service 113 @type service_uri: C{str} 114 @param service: the name of service to get the description 115 @type service: C{str} 116 @param delay_exec: delayd the execution 117 @type delay_exec: C{float} 118 ''' 119 with self._lock: 120 if (service_uri, service) not in self.__serviceThreads: 121 upthread = ServiceDescriptionThread(service_uri, service, delay_exec) 122 upthread.update_signal.connect(self._on_descr_list) 123 upthread.err_signal.connect(self._on_err) 124 self.__serviceThreads[(service_uri, service)] = upthread 125 upthread.start()
126
127 - def _on_node_list(self, service_uri, service, nodes):
128 with self._lock: 129 try: 130 thread = self.__serviceThreads.pop((service_uri, service)) 131 del thread 132 except KeyError: 133 pass 134 self.node_list_signal.emit(service_uri, service, nodes)
135
136 - def _on_descr_list(self, service_uri, service, items):
137 with self._lock: 138 try: 139 thread = self.__serviceThreads.pop((service_uri, service)) 140 del thread 141 except KeyError: 142 pass 143 self.description_signal.emit(service_uri, service, items)
144
145 - def _on_err(self, service_uri, service, msg):
146 with self._lock: 147 try: 148 thread = self.__serviceThreads.pop((service_uri, service)) 149 del thread 150 except KeyError: 151 pass 152 self.err_signal.emit(service_uri, service, msg)
153 154
155 -class ServiceThread(QObject, threading.Thread):
156 ''' 157 A thread to to retrieve the list of nodes from the default configuration 158 service and publish it by sending a QT signal. 159 ''' 160 update_signal = Signal(str, str, list) 161 err_signal = Signal(str, str, str) 162
163 - def __init__(self, service_uri, service, delay_exec=0.0, parent=None):
164 QObject.__init__(self) 165 threading.Thread.__init__(self) 166 self._service_uri = service_uri 167 self._service = service 168 self._delay_exec = delay_exec 169 self.setDaemon(True)
170
171 - def run(self):
172 ''' 173 ''' 174 if self._service and self._service_uri: 175 try: 176 if self._delay_exec > 0: 177 time.sleep(self._delay_exec) 178 _, resp = nm.starter().callService(self._service_uri, self._service, ListNodes) 179 self.update_signal.emit(self._service_uri, self._service, resp.nodes) 180 except: 181 import traceback 182 lines = traceback.format_exc(1).splitlines() 183 rospy.logwarn("Error while retrieve the node list from %s[%s]: %s", str(self._service), str(self._service_uri), str(lines[-1])) 184 self.err_signal.emit(self._service_uri, self._service, lines[-1])
185 186
187 -class ServiceDescriptionThread(QObject, threading.Thread):
188 ''' 189 A thread to to retrieve the list with descriptions from the default configuration 190 service and publish it by sending a QT signal. 191 ''' 192 update_signal = Signal(str, str, list) 193 err_signal = Signal(str, str, str) 194
195 - def __init__(self, service_uri, service, delay_exec=0.0, parent=None):
196 QObject.__init__(self) 197 threading.Thread.__init__(self) 198 self._service_uri = service_uri 199 self._service = service 200 self._delay_exec = delay_exec 201 self.setDaemon(True)
202
203 - def run(self):
204 ''' 205 ''' 206 if self._service: 207 try: 208 if self._delay_exec > 0: 209 time.sleep(self._delay_exec) 210 _, resp = nm.starter().callService(self._service_uri, self._service, ListDescription) 211 self.update_signal.emit(self._service_uri, self._service, [resp]) 212 except: 213 import traceback 214 lines = traceback.format_exc(1).splitlines() 215 rospy.logwarn("Error while retrieve the description from %s[%s]: %s", str(self._service), str(self._service_uri), str(lines[-1])) 216 self.err_signal.emit(self._service_uri, self._service, lines[-1])
217