Package node_manager_fkie
|
|
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 import argparse
35 import os
36 import roslib.network
37 import rospy
38 import socket
39 import sys
40 import threading
41
42 from master_discovery_fkie.common import get_hostname
43 from node_manager_fkie.common import get_ros_home, masteruri_from_ros
44 from node_manager_fkie.file_watcher import FileWatcher
45 from node_manager_fkie.history import History
46 from node_manager_fkie.master_view_proxy import LaunchArgsSelectionRequest
47 from node_manager_fkie.name_resolution import NameResolution
48 from node_manager_fkie.progress_queue import InteractionNeededError
49 from node_manager_fkie.screen_handler import ScreenHandler, ScreenSelectionRequest
50 from node_manager_fkie.settings import Settings
51 from node_manager_fkie.ssh_handler import SSHhandler, AuthenticationRequest
52 from node_manager_fkie.start_handler import StartException, AdvRunCfg
53 from node_manager_fkie.start_handler import StartHandler, BinarySelectionRequest
54
55
56 PKG_NAME = 'node_manager_fkie'
57
58 __author__ = "Alexander Tiderko (Alexander.Tiderko@fkie.fraunhofer.de)"
59 __copyright__ = "Copyright (c) 2012 Alexander Tiderko, Fraunhofer FKIE/US"
60 __license__ = "BSD"
61 __version__ = "0.7.2"
62 __date__ = "2017-01-27"
63
64
65
66
67
68
69 HOSTS_CACHE = dict()
70 '''
71 the cache directory to store the results of tests for local hosts.
72 @see: L{is_local()}
73 '''
74
75 _LOCK = threading.RLock()
76
77 _MAIN_FORM = None
78 _SETTINGS = None
79 _SSH_HANDLER = None
80 _SCREEN_HANDLER = None
81 _START_HANDLER = None
82 _NAME_RESOLUTION = None
83 _HISTORY = None
84 _FILE_WATCHER = None
85 _FILE_WATCHER_PARAM = None
86 _QAPP = None
87
88
90 '''
91 @return: The global settings
92 @rtype: L{Settings}
93 '''
94 return _SETTINGS
95
96
98 '''
99 @return: The SSH handler to handle the SSH connections
100 @rtype: L{SSHhandler}
101 '''
102 return _SSH_HANDLER
103
104
106 '''
107 @return: The screen handler to the screens.
108 @rtype: L{ScreenHandler}
109 @see: U{http://linuxwiki.de/screen}
110 '''
111 return _SCREEN_HANDLER
112
113
115 '''
116 @return: The start handler to handle the start of new ROS nodes on local or
117 remote machines.
118 @rtype: L{StartHandler}
119 '''
120 return _START_HANDLER
121
122
124 '''
125 @return: The name resolution object translate the the name to the host or
126 ROS master URI.
127 @rtype: L{NameResolution}
128 '''
129 return _NAME_RESOLUTION
130
131
133 '''
134 @return: The history of entered parameter.
135 @rtype: L{History}
136 '''
137 return _HISTORY
138
139
141 '''
142 @return: The file watcher object with all loaded configuration files.
143 @rtype: L{FileWatcher}
144 '''
145 return _FILE_WATCHER
146
147
149 '''
150 @return: The file watcher object with all configuration files referenced by
151 parameter value.
152 @rtype: L{FileWatcher}
153 '''
154 return _FILE_WATCHER_PARAM
155
156
158 '''
159 Returns the host name used in a url, if it is a name. If it is an IP an
160 empty string will be returned.
161
162 @return: host or '' if url is an IP or invalid
163
164 @rtype: C{str}
165 '''
166 return NameResolution.get_ros_hostname(url)
167
168
170 '''
171 Test whether the given host name is the name of the local host or not.
172 @param hostname: the name or IP of the host
173 @type hostname: C{str}
174 @return: C{True} if the hostname is local or None
175 @rtype: C{bool}
176 @raise Exception: on errors while resolving host
177 '''
178 if hostname is None:
179 return True
180 with _LOCK:
181 if hostname in HOSTS_CACHE:
182 if isinstance(HOSTS_CACHE[hostname], threading.Thread):
183 return False
184 return HOSTS_CACHE[hostname]
185 try:
186 socket.inet_aton(hostname)
187 local_addresses = ['localhost'] + roslib.network.get_local_addresses()
188
189 result = hostname.startswith('127.') or hostname in local_addresses
190 with _LOCK:
191 HOSTS_CACHE[hostname] = result
192 return result
193 except socket.error:
194
195 if wait:
196 result = __is_local(hostname)
197 return result
198 else:
199 thread = threading.Thread(target=__is_local, args=((hostname,)))
200 thread.daemon = True
201 with _LOCK:
202 HOSTS_CACHE[hostname] = thread
203 thread.start()
204 return False
205
206
208 '''
209 Test the hostname whether it is local or not. Uses socket.gethostbyname().
210 '''
211 try:
212 machine_addr = socket.gethostbyname(hostname)
213 except socket.gaierror:
214 with _LOCK:
215 HOSTS_CACHE[hostname] = False
216 return False
217 local_addresses = ['localhost'] + roslib.network.get_local_addresses()
218
219 result = machine_addr.startswith('127.') or machine_addr in local_addresses
220 with _LOCK:
221 HOSTS_CACHE[hostname] = result
222 return result
223
224
244
245
247 '''
248 Change the terminal name.
249 @param name: New name of the terminal
250 @type name: C{str}
251 '''
252 sys.stdout.write("\x1b]2;%s\x07" % name)
253
254
256 '''
257 Change the process name.
258 @param name: New process name
259 @type name: C{str}
260 '''
261 try:
262 from ctypes import cdll, byref, create_string_buffer
263 libc = cdll.LoadLibrary('libc.so.6')
264 buff = create_string_buffer(len(name) + 1)
265 buff.value = name
266 libc.prctl(15, byref(buff), 0, 0, 0)
267 except:
268 pass
269
270
274
275
300
301
303 parser = argparse.ArgumentParser()
304 parser.add_argument("--version", action="version", version="%s %s" % ("%(prog)s", __version__))
305 parser.add_argument("-f", "--file", nargs=1, help="loads the given file as default on start")
306 parser.add_argument("-m", "--muri", nargs=1, default='', help="starts ROS master with given URI, usefull on hosts "
307 "with multiple interfaces. ROS_HOSTNAME will be set "
308 "to the host of this URI, but only if it is not an IP.")
309
310 group = parser.add_argument_group('echo')
311 group.add_argument("--echo", nargs=2, help="starts an echo dialog instead of node manager", metavar=('name', 'type'))
312 group.add_argument("--hz", action="store_true", help="shows only the Hz value instead of topic content in echo dialog")
313 group.add_argument("--ssh", action="store_true", help="connects via SSH")
314
315 return parser
316
317
318 -def init_echo_dialog(prog_name, masteruri, topic_name, topic_type, hz=False, use_ssh=False):
332
333
334 -def init_main_window(prog_name, masteruri, launch_files=[]):
335 '''
336 Intialize the environment to start Node Manager.
337 '''
338
339 StartHandler._prepareROSMaster(masteruri)
340
341 try:
342 log_level = getattr(rospy, rospy.get_param('/%s/log_level' % prog_name, "INFO"))
343 except Exception as err:
344 print "Error while set the log level: %s\n->INFO level will be used!" % err
345 log_level = rospy.INFO
346 rospy.init_node(prog_name, anonymous=False, log_level=log_level)
347 set_terminal_name(prog_name)
348 set_process_name(prog_name)
349 from node_manager_fkie.main_window import MainWindow
350 local_master = init_globals(masteruri)
351 return MainWindow(launch_files, not local_master, launch_files)
352
353
354
355
356
357
359 '''
360 Start the NodeManager or EchoDialog.
361 :param name: the name propagated to the rospy.init_node()
362 :type name: str
363 '''
364 try:
365 from python_qt_binding.QtGui import QApplication
366 except:
367 try:
368 from python_qt_binding.QtWidgets import QApplication
369 except:
370 print >> sys.stderr, "please install 'python_qt_binding' package!!"
371 sys.exit(-1)
372
373 init_settings()
374 parser = init_arg_parser()
375 args = rospy.myargv(argv=sys.argv)
376 parsed_args = parser.parse_args(args[1:])
377 if parsed_args.muri:
378 masteruri = parsed_args.muri[0]
379 hostname = NameResolution.get_ros_hostname(masteruri)
380 os.environ['ROS_MASTER_URI'] = masteruri
381 if hostname:
382 os.environ['ROS_HOSTNAME'] = hostname
383 masteruri = settings().masteruri()
384
385 global _QAPP
386 _QAPP = QApplication(sys.argv)
387
388
389 global _MAIN_FORM
390 try:
391 if parsed_args.echo:
392 _MAIN_FORM = init_echo_dialog(name, masteruri, parsed_args.echo[0],
393 parsed_args.echo[1], parsed_args.hz,
394 parsed_args.ssh)
395 else:
396 _MAIN_FORM = init_main_window(name, masteruri, parsed_args.file)
397 except Exception as err:
398 sys.exit("%s" % err)
399
400 exit_code = 0
401
402 if not rospy.is_shutdown():
403
404 os.chdir(settings().PACKAGE_DIR)
405
406 screen_size = QApplication.desktop().availableGeometry()
407 if (_MAIN_FORM.size().width() >= screen_size.width() or
408 _MAIN_FORM.size().height() >= screen_size.height() - 24):
409 _MAIN_FORM.showMaximized()
410 else:
411 _MAIN_FORM.show()
412 exit_code = -1
413 rospy.on_shutdown(finish)
414 exit_code = _QAPP.exec_()
415 return exit_code
416