Package node_manager_fkie
[frames] | no frames]

Source Code for Package node_manager_fkie

  1  #!/usr/bin/env python 
  2  # Software License Agreement (BSD License) 
  3  # 
  4  # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions 
  9  # are met: 
 10  # 
 11  #  * Redistributions of source code must retain the above copyright 
 12  #    notice, this list of conditions and the following disclaimer. 
 13  #  * Redistributions in binary form must reproduce the above 
 14  #    copyright notice, this list of conditions and the following 
 15  #    disclaimer in the documentation and/or other materials provided 
 16  #    with the distribution. 
 17  #  * Neither the name of Fraunhofer nor the names of its 
 18  #    contributors may be used to endorse or promote products derived 
 19  #    from this software without specific prior written permission. 
 20  # 
 21  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 22  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 23  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 24  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 25  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 26  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 27  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 28  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 29  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 30  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 31  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 32  # POSSIBILITY OF SUCH DAMAGE. 
 33   
 34  __author__ = "Alexander Tiderko (Alexander.Tiderko@fkie.fraunhofer.de)" 
 35  __copyright__ = "Copyright (c) 2012 Alexander Tiderko, Fraunhofer FKIE/US" 
 36  __license__ = "BSD" 
 37  __version__ = "0.3.13-0" # git describe --tags --dirty --always 
 38  __date__ = "2014-07-29"    # git log -1 --date=iso 
 39   
 40  import os 
 41  import sys 
 42  import socket 
 43  import threading 
 44  import argparse 
 45   
 46  PKG_NAME = 'node_manager_fkie' 
 47   
 48  import roslib; roslib.load_manifest(PKG_NAME) 
 49  import rospy 
 50  import roslib.network 
 51   
 52  #PYTHONVER = (2, 7, 1) 
 53  #if sys.version_info < PYTHONVER: 
 54  #  print 'For full scope of operation this application requires python version > %s, current: %s' % (str(PYTHONVER), sys.version_info) 
 55   
 56  from settings import Settings 
 57  from ssh_handler import SSHhandler, AuthenticationRequest 
 58  from screen_handler import ScreenHandler, ScreenSelectionRequest 
 59  from start_handler import StartHandler, StartException, BinarySelectionRequest 
 60  from progress_queue import InteractionNeededError 
 61  from name_resolution import NameResolution 
 62  from history import History 
 63  from file_watcher import FileWatcher 
 64  from common import get_ros_home, masteruri_from_ros 
 65  from master_view_proxy import LaunchArgsSelectionRequest 
 66   
 67  HOSTS_CACHE = dict() 
 68  ''' 
 69  the cache directory to store the results of tests for local hosts. 
 70  @see: L{is_local()} 
 71  ''' 
 72   
 73  _lock = threading.RLock() 
 74   
 75  main_form = None 
 76  _settings = None 
 77  _ssh_handler = None 
 78  _screen_handler = None 
 79  _start_handler = None 
 80  _name_resolution = None 
 81  _history = None 
 82  _file_watcher = None 
 83  _file_watcher_param = None 
 84  app = None 
 85   
86 -def settings():
87 ''' 88 @return: The global settings 89 @rtype: L{Settings} 90 ''' 91 global _settings 92 return _settings
93
94 -def ssh():
95 ''' 96 @return: The SSH handler to handle the SSH connections 97 @rtype: L{SSHhandler} 98 ''' 99 global _ssh_handler 100 return _ssh_handler
101
102 -def screen():
103 ''' 104 @return: The screen handler to the screens. 105 @rtype: L{ScreenHandler} 106 @see: U{http://linuxwiki.de/screen} 107 ''' 108 global _screen_handler 109 return _screen_handler
110
111 -def starter():
112 ''' 113 @return: The start handler to handle the start of new ROS nodes on local or 114 remote machines. 115 @rtype: L{StartHandler} 116 ''' 117 global _start_handler 118 return _start_handler
119
120 -def nameres():
121 ''' 122 @return: The name resolution object translate the the name to the host or 123 ROS master URI. 124 @rtype: L{NameResolution} 125 ''' 126 global _name_resolution 127 return _name_resolution
128
129 -def history():
130 ''' 131 @return: The history of entered parameter. 132 @rtype: L{History} 133 ''' 134 global _history 135 return _history
136
137 -def file_watcher():
138 ''' 139 @return: The file watcher object with all loaded configuration files. 140 @rtype: L{FileWatcher} 141 ''' 142 global _file_watcher 143 return _file_watcher
144
145 -def file_watcher_param():
146 ''' 147 @return: The file watcher object with all configuration files referenced by parameter value. 148 @rtype: L{FileWatcher} 149 ''' 150 global _file_watcher_param 151 return _file_watcher_param
152 153
154 -def is_local(hostname, wait=False):
155 ''' 156 Test whether the given host name is the name of the local host or not. 157 @param hostname: the name or IP of the host 158 @type hostname: C{str} 159 @return: C{True} if the hostname is local or None 160 @rtype: C{bool} 161 @raise Exception: on errors while resolving host 162 ''' 163 if (hostname is None): 164 return True 165 with _lock: 166 if hostname in HOSTS_CACHE: 167 if isinstance(HOSTS_CACHE[hostname], threading.Thread): 168 return False 169 return HOSTS_CACHE[hostname] 170 171 try: 172 machine_addr = socket.inet_aton(hostname) 173 local_addresses = ['localhost'] + roslib.network.get_local_addresses() 174 # check 127/8 and local addresses 175 result = hostname.startswith('127.') or hostname in local_addresses 176 with _lock: 177 HOSTS_CACHE[hostname] = result 178 return result 179 except socket.error: 180 # the hostname must be resolved => do it in a thread 181 if wait: 182 result = __is_local(hostname) 183 return result 184 else: 185 thread = threading.Thread(target=__is_local, args=((hostname,))) 186 thread.daemon = True 187 with _lock: 188 HOSTS_CACHE[hostname] = thread 189 thread.start() 190 return False
191
192 -def __is_local(hostname):
193 import roslib 194 import roslib.network 195 try: 196 machine_addr = socket.gethostbyname(hostname) 197 except socket.gaierror: 198 import traceback 199 print traceback.format_exc() 200 with _lock: 201 HOSTS_CACHE[hostname] = False 202 return False 203 local_addresses = ['localhost'] + roslib.network.get_local_addresses() 204 # check 127/8 and local addresses 205 result = machine_addr.startswith('127.') or machine_addr in local_addresses 206 with _lock: 207 HOSTS_CACHE[hostname] = result 208 return result
209
210 -def finish(*arg):
211 ''' 212 Callback called on exit of the ros node. 213 ''' 214 # close all ssh sessions 215 global _ssh_handler 216 if not _ssh_handler is None: 217 _ssh_handler.close() 218 global _history 219 if not _history is None: 220 try: 221 _history.storeAll() 222 except Exception as e: 223 print >> sys.stderr, "Error while store history: %s"%e 224 global main_form 225 import main_window 226 if isinstance(main_form, main_window.MainWindow): 227 main_form.finish() 228 global app 229 if not app is None: 230 app.exit()
231 232
233 -def setTerminalName(name):
234 ''' 235 Change the terminal name. 236 @param name: New name of the terminal 237 @type name: C{str} 238 ''' 239 sys.stdout.write("\x1b]2;%s\x07"%name)
240
241 -def setProcessName(name):
242 ''' 243 Change the process name. 244 @param name: New process name 245 @type name: C{str} 246 ''' 247 try: 248 from ctypes import cdll, byref, create_string_buffer 249 libc = cdll.LoadLibrary('libc.so.6') 250 buff = create_string_buffer(len(name)+1) 251 buff.value = name 252 libc.prctl(15, byref(buff), 0, 0, 0) 253 except: 254 pass
255
256 -def init_settings():
257 global _settings 258 _settings = Settings()
259
260 -def init_globals(masteruri):
261 # initialize the global handler 262 global _ssh_handler 263 global _screen_handler 264 global _start_handler 265 global _name_resolution 266 global _history 267 global _file_watcher 268 global _file_watcher_param 269 _ssh_handler = SSHhandler() 270 _screen_handler = ScreenHandler() 271 _start_handler = StartHandler() 272 _name_resolution = NameResolution() 273 _history = History() 274 _file_watcher = FileWatcher() 275 _file_watcher_param = FileWatcher() 276 277 # test where the roscore is running (local or remote) 278 __is_local('localhost') ## fill cache 279 return __is_local(_name_resolution.getHostname(masteruri)) ## fill cache
280
281 -def init_arg_parser():
282 parser = argparse.ArgumentParser() 283 parser.add_argument("--version", action="version", version="%s %s" % ( "%(prog)s", __version__)) 284 parser.add_argument("-f", "--file", nargs=1, help="loads the given file as default on start") 285 286 group = parser.add_argument_group('echo') 287 group.add_argument("--echo", nargs=2, help="starts an echo dialog instead of node manager", metavar=('name', 'type')) 288 group.add_argument("--hz", action="store_true", help="shows only the Hz value instead of topic content in echo dialog") 289 290 return parser
291
292 -def init_echo_dialog(prog_name, masteruri, topic_name, topic_type, hz=False):
293 # start ROS-Master, if not currently running 294 StartHandler._prepareROSMaster(masteruri) 295 name = ''.join([prog_name, '_echo']) 296 rospy.init_node(name, anonymous=True, log_level=rospy.DEBUG) 297 setTerminalName(rospy.get_name()) 298 setProcessName(rospy.get_name()) 299 import echo_dialog 300 return echo_dialog.EchoDialog(topic_name, topic_type, hz, masteruri)
301
302 -def init_main_window(prog_name, masteruri, launch_files=[]):
303 # start ROS-Master, if not currently running 304 StartHandler._prepareROSMaster(masteruri) 305 rospy.init_node(prog_name, anonymous=False, log_level=rospy.DEBUG) 306 setTerminalName(rospy.get_name()) 307 setProcessName(rospy.get_name()) 308 import main_window 309 local_master = init_globals(masteruri) 310 return main_window.MainWindow(launch_files, not local_master, launch_files)
311 312 #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 313 #%%%%%%%%%%%%% MAIN %%%%%%%% 314 #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 315
316 -def main(name):
317 try: 318 from python_qt_binding.QtGui import QApplication 319 except: 320 print >> sys.stderr, "please install 'python_qt_binding' package!!" 321 sys.exit(-1) 322 323 init_settings() 324 masteruri = settings().masteruri() 325 parser = init_arg_parser() 326 args = rospy.myargv(argv=sys.argv) 327 parsed_args = parser.parse_args(args[1:]) 328 # Initialize Qt 329 global app 330 app = QApplication(sys.argv) 331 332 # decide to show main or echo dialog 333 global main_form 334 if parsed_args.echo: 335 main_form = init_echo_dialog(name, masteruri, parsed_args.echo[0], parsed_args.echo[1], parsed_args.hz) 336 else: 337 main_form = init_main_window(name, masteruri, parsed_args.file) 338 339 # resize and show the qt window 340 if not rospy.is_shutdown(): 341 os.chdir(settings().PACKAGE_DIR) # change path to be able to the images of descriptions 342 # main_form.resize(1024, 720) 343 screen_size = QApplication.desktop().availableGeometry() 344 if main_form.size().width() >= screen_size.width() or main_form.size().height() >= screen_size.height()-24: 345 main_form.showMaximized() 346 else: 347 main_form.show() 348 exit_code = -1 349 rospy.on_shutdown(finish) 350 exit_code = app.exec_()
351