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  from node_manager_fkie.common import utf8 
 41   
 42   
 43  try: 
 44      from multimaster_msgs_fkie.srv import ListDescription, ListNodes  # , LoadLaunch, Task 
 45  except ImportError, e: 
 46      import sys 
 47      print >> sys.stderr, "Can't import services of default_cfg_fkie. Is default_cfg_fkie package compiled?" 
 48      raise ImportError(utf8(e)) 
 49   
 50   
51 -class DefaultConfigHandler(QObject):
52 ''' 53 A class to retrieve the list of nodes from the default configuration service. 54 The received node list will be published by sending a QT signal. To retrieve 55 the configuration a new thread will be created. 56 ''' 57 node_list_signal = Signal(str, str, list) 58 ''' 59 node_list_signal is a signal, which is emitted, if a new list with nodes is 60 retrieved. The signal has the URI of the service, the name of the service and 61 a list with node names as parameter. 62 ''' 63 description_signal = Signal(str, str, list) 64 ''' 65 description_signal is a signal, which is emitted, if a new list with descriptions is 66 retrieved. The signal has the URI of the service, the name of the service and 67 a list with descriptions (U{multimaster_msgs_fkie.srv.ListDescription<http://docs.ros.org/api/multimaster_msgs_fkie/html/srv/ListDescription.html>} Response) parameter. 68 ''' 69 err_signal = Signal(str, str, str) 70
71 - def __init__(self):
72 QObject.__init__(self) 73 self.__serviceThreads = {} 74 self._lock = threading.RLock()
75
76 - def stop(self):
77 print " Shutdown default config update threads..." 78 for _, service in self.__serviceThreads.iteritems(): 79 service.join(3) 80 print " Default config update threads are off!"
81
82 - def requestNodeList(self, service_uri, service, delay_exec=0.0):
83 ''' 84 This method starts a thread to get the informations about the default 85 configured nodes. If all informations are retrieved, a C{node_list_signal} of 86 this class will be emitted. If for given service a thread is 87 already running, the request will be ignored. 88 This method is thread safe. 89 90 @param service_uri: the URI of the service 91 @type service_uri: C{str} 92 @param service: the name of service to get the node list 93 @type service: C{str} 94 @param delay_exec: delayd the execution 95 @type delay_exec: C{float} 96 ''' 97 with self._lock: 98 if (service_uri, service) not in self.__serviceThreads: 99 upthread = ServiceThread(service_uri, service, delay_exec) 100 upthread.update_signal.connect(self._on_node_list) 101 upthread.err_signal.connect(self._on_err) 102 self.__serviceThreads[(service_uri, service)] = upthread 103 upthread.start()
104
105 - def requestDescriptionList(self, service_uri, service, delay_exec=0.0):
106 ''' 107 This method starts a thread to get the descriptions from the default 108 configuration node. If all informations are retrieved, a C{description_signal} of 109 this class will be emitted. If for given service a thread is 110 already running, the request will be ignored. 111 This method is thread safe. 112 113 @param service_uri: the URI of the service 114 @type service_uri: C{str} 115 @param service: the name of service to get the description 116 @type service: C{str} 117 @param delay_exec: delayd the execution 118 @type delay_exec: C{float} 119 ''' 120 with self._lock: 121 if (service_uri, service) not in self.__serviceThreads: 122 upthread = ServiceDescriptionThread(service_uri, service, delay_exec) 123 upthread.update_signal.connect(self._on_descr_list) 124 upthread.err_signal.connect(self._on_err) 125 self.__serviceThreads[(service_uri, service)] = upthread 126 upthread.start()
127
128 - def _on_node_list(self, service_uri, service, nodes):
129 with self._lock: 130 try: 131 thread = self.__serviceThreads.pop((service_uri, service)) 132 del thread 133 except KeyError: 134 pass 135 self.node_list_signal.emit(service_uri, service, nodes)
136
137 - def _on_descr_list(self, service_uri, service, items):
138 with self._lock: 139 try: 140 thread = self.__serviceThreads.pop((service_uri, service)) 141 del thread 142 except KeyError: 143 pass 144 self.description_signal.emit(service_uri, service, items)
145
146 - def _on_err(self, service_uri, service, msg):
147 with self._lock: 148 try: 149 thread = self.__serviceThreads.pop((service_uri, service)) 150 del thread 151 except KeyError: 152 pass 153 self.err_signal.emit(service_uri, service, msg)
154 155
156 -class ServiceThread(QObject, threading.Thread):
157 ''' 158 A thread to to retrieve the list of nodes from the default configuration 159 service and publish it by sending a QT signal. 160 ''' 161 update_signal = Signal(str, str, list) 162 err_signal = Signal(str, str, str) 163
164 - def __init__(self, service_uri, service, delay_exec=0.0, parent=None):
165 QObject.__init__(self) 166 threading.Thread.__init__(self) 167 self._service_uri = service_uri 168 self._service = service 169 self._delay_exec = delay_exec 170 self.setDaemon(True)
171
172 - def run(self):
173 ''' 174 ''' 175 if self._service and self._service_uri: 176 try: 177 if self._delay_exec > 0: 178 time.sleep(self._delay_exec) 179 _, resp = nm.starter().callService(self._service_uri, self._service, ListNodes) 180 self.update_signal.emit(self._service_uri, self._service, resp.nodes) 181 except: 182 import traceback 183 lines = traceback.format_exc(1).splitlines() 184 rospy.logwarn("Error while retrieve the node list from %s[%s]: %s", utf8(self._service), utf8(self._service_uri), utf8(lines[-1])) 185 self.err_signal.emit(self._service_uri, self._service, lines[-1])
186 187
188 -class ServiceDescriptionThread(QObject, threading.Thread):
189 ''' 190 A thread to to retrieve the list with descriptions from the default configuration 191 service and publish it by sending a QT signal. 192 ''' 193 update_signal = Signal(str, str, list) 194 err_signal = Signal(str, str, str) 195
196 - def __init__(self, service_uri, service, delay_exec=0.0, parent=None):
197 QObject.__init__(self) 198 threading.Thread.__init__(self) 199 self._service_uri = service_uri 200 self._service = service 201 self._delay_exec = delay_exec 202 self.setDaemon(True)
203
204 - def run(self):
205 ''' 206 ''' 207 if self._service: 208 try: 209 if self._delay_exec > 0: 210 time.sleep(self._delay_exec) 211 _, resp = nm.starter().callService(self._service_uri, self._service, ListDescription) 212 self.update_signal.emit(self._service_uri, self._service, [resp]) 213 except: 214 import traceback 215 lines = traceback.format_exc(1).splitlines() 216 rospy.logwarn("Error while retrieve the description from %s[%s]: %s", utf8(self._service), utf8(self._service_uri), utf8(lines[-1])) 217 self.err_signal.emit(self._service_uri, self._service, lines[-1])
218