|
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 __author__ = "Alexander Tiderko (Alexander.Tiderko@fkie.fraunhofer.de)"
35 __copyright__ = "Copyright (c) 2012 Alexander Tiderko, Fraunhofer FKIE/US"
36 __license__ = "BSD"
37 __version__ = "0.2"
38 __date__ = "2012-02-01"
39
40 import os
41 import sys
42 import signal
43 import socket
44 import threading
45
46 import roslib; roslib.load_manifest('node_manager_fkie')
47 import rospy
48
49
50
51
52
53 from ssh_handler import SSHhandler, AuthenticationRequest
54 from screen_handler import ScreenHandler, ScreenSelectionRequest
55 from start_handler import StartHandler, StartException
56 from progress_queue import InteractionNeededError
57 from name_resolution import NameResolution
58 from history import History
59
60
61
62
63 PACKAGE_DIR = ''.join([roslib.packages.get_dir_pkg(os.path.abspath(os.path.dirname(sys.argv[0])))[0], os.path.sep])
64 ROBOTS_DIR = ''.join([PACKAGE_DIR, os.path.sep, 'images', os.path.sep])
65
66 CFG_PATH = ''.join(['.node_manager', os.sep])
67 '''@ivar: configuration path to store the history.'''
68
69 LESS = "/usr/bin/less -fKLnQrSU"
70 STARTER_SCRIPT = 'rosrun node_manager_fkie remote_nm.py'
71 RESPAWN_SCRIPT = 'rosrun node_manager_fkie respawn'
72 '''
73 the script used on remote hosts to start new ROS nodes
74 '''
75
76 HOSTS_CACHE = dict()
77 '''
78 the cache directory to store the results of tests for local hosts.
79 @see: L{is_local()}
80 '''
81
82 HELP_FILE = ''.join([PACKAGE_DIR, os.path.sep, 'README.rst'])
83
84 _lock = threading.RLock()
85
87 '''
88 Creates a command string to run with a terminal prefix
89 @param cmd: the list with a command and args
90 @type cmd: [str,..]
91 @param title: the title of the terminal
92 @type title: str
93 @return: command with a terminal prefix
94 @rtype: str
95 '''
96 if os.path.isfile('/usr/bin/xterm'):
97 return str(' '.join(['/usr/bin/xterm', '-geometry 112x35', '-title', str(title), '-e', ' '.join(cmd)]))
98 elif os.path.isfile('/usr/bin/konsole'):
99 return str(' '.join(['/usr/bin/konsole', '--noclose', '-title', str(title), '-e', ' '.join(cmd)]))
100
101 main_form = None
102 _ssh_handler = None
103 _screen_handler = None
104 _start_handler = None
105 _name_resolution = None
106 _history = None
107 app = None
108
110 '''
111 @return: The SSH handler to handle the SSH connections
112 @rtype: L{SSHhandler}
113 '''
114 global _ssh_handler
115 return _ssh_handler
116
118 '''
119 @return: The screen handler to the screens.
120 @rtype: L{ScreenHandler}
121 @see: U{http://linuxwiki.de/screen}
122 '''
123 global _screen_handler
124 return _screen_handler
125
127 '''
128 @return: The start handler to handle the start of new ROS nodes on local or
129 remote machines.
130 @rtype: L{StartHandler}
131 '''
132 global _start_handler
133 return _start_handler
134
136 '''
137 @return: The name resolution object translate the the name to the host or
138 ROS master URI.
139 @rtype: L{NameResolution}
140 '''
141 global _name_resolution
142 return _name_resolution
143
145 '''
146 @return: The history of entered parameter.
147 @rtype: L{History}
148 '''
149 global _history
150 return _history
151
153 '''
154 Test whether the given host name is the name of the local host or not.
155 @param hostname: the name or IP of the host
156 @type hostname: C{str}
157 @return: C{True} if the hostname is local or None
158 @rtype: C{bool}
159 @raise Exception: on errors while resolving host
160 '''
161 if (hostname is None):
162 return True
163 with _lock:
164 if hostname in HOSTS_CACHE:
165 if isinstance(HOSTS_CACHE[hostname], threading.Thread):
166 return False
167 return HOSTS_CACHE[hostname]
168
169 try:
170 machine_addr = socket.inet_aton(hostname)
171 local_addresses = ['localhost'] + roslib.network.get_local_addresses()
172
173 result = machine_addr.startswith('127.') or machine_addr in local_addresses
174 with _lock:
175 HOSTS_CACHE[hostname] = result
176 return result
177 except socket.error:
178
179 thread = threading.Thread(target=__is_local, args=((hostname,)))
180 thread.daemon = True
181 thread.start()
182 with _lock:
183 HOSTS_CACHE[hostname] = thread
184 return False
185
187 import roslib
188 try:
189 machine_addr = socket.gethostbyname(hostname)
190 except socket.gaierror:
191 import traceback
192 print traceback.format_exc()
193 with _lock:
194 HOSTS_CACHE[hostname] = False
195 return
196 local_addresses = ['localhost'] + roslib.network.get_local_addresses()
197
198 result = machine_addr.startswith('127.') or machine_addr in local_addresses
199 with _lock:
200 HOSTS_CACHE[hostname] = result
201
202
204 '''
205 Returns the ROS HOME depending on ROS distribution API.
206 @return: ROS HOME path
207 @rtype: C{str}
208 '''
209 try:
210 import rospkg.distro
211 distro = rospkg.distro.current_distro_codename()
212 if distro in ['electric', 'diamondback', 'cturtle']:
213 import roslib.rosenv
214 return roslib.rosenv.get_ros_home()
215 else:
216 import rospkg
217 return rospkg.get_ros_home()
218 except:
219
220
221 import roslib.rosenv
222 return roslib.rosenv.get_ros_home()
223
224
226 '''
227 Returns the master URI depending on ROS distribution API.
228 @return: ROS master URI
229 @rtype: C{str}
230 '''
231 try:
232 import rospkg.distro
233 distro = rospkg.distro.current_distro_codename()
234 if distro in ['electric', 'diamondback', 'cturtle']:
235 return roslib.rosenv.get_master_uri()
236 else:
237 import rosgraph
238 return rosgraph.rosenv.get_master_uri()
239 except:
240 return os.environ['ROS_MASTER_URI']
241
259
260
262 '''
263 Change the terminal name.
264 @param name: New name of the terminal
265 @type name: C{str}
266 '''
267 sys.stdout.write("".join(["\x1b]2;",name,"\x07"]))
268
269
271 '''
272 Change the process name.
273 @param name: New process name
274 @type name: C{str}
275 '''
276 try:
277 from ctypes import cdll, byref, create_string_buffer
278 libc = cdll.LoadLibrary('libc.so.6')
279 buff = create_string_buffer(len(name)+1)
280 buff.value = name
281 libc.prctl(15, byref(buff), 0, 0, 0)
282 except:
283 pass
284
285
286
287
288
289
290
291 -def main(name, anonymous=False):
292 global CFG_PATH
293 masteruri = masteruri_from_ros()
294 CFG_PATH = ''.join([get_ros_home(), os.sep, 'node_manager', os.sep])
295 '''
296 Creates and runs the ROS node.
297 '''
298 if not os.path.isdir(CFG_PATH):
299 os.makedirs(CFG_PATH)
300
301 args = rospy.myargv(argv=sys.argv)
302
303 if len(args) >= 4 and args[1] == '-t':
304 name = ''.join([name, '_echo'])
305 anonymous = True
306
307 try:
308 from PySide.QtGui import QApplication
309 except:
310 print >> sys.stderr, "please install 'python-pyside' package!!"
311 sys.exit(-1)
312
313 StartHandler._prepareROSMaster(masteruri)
314 rospy.init_node(name, anonymous=anonymous, log_level=rospy.DEBUG)
315 setTerminalName(rospy.get_name())
316 setProcessName(rospy.get_name())
317
318
319 global app
320 app = QApplication(sys.argv)
321
322
323 import main_window, echo_dialog
324 global main_form
325 if len(args) >= 4 and args[1] == '-t':
326 show_hz_only = (len(args) > 4 and args[4] == '--hz')
327 main_form = echo_dialog.EchoDialog(args[2], args[3], show_hz_only)
328 else:
329
330 global _ssh_handler
331 global _screen_handler
332 global _start_handler
333 global _name_resolution
334 global _history
335 _ssh_handler = SSHhandler()
336 _screen_handler = ScreenHandler()
337 _start_handler = StartHandler()
338 _name_resolution = NameResolution()
339 _history = History()
340
341
342 __is_local('localhost')
343 __is_local(_name_resolution.getHostname(masteruri))
344 local_master = is_local(_name_resolution.getHostname(masteruri))
345
346
347 main_form = main_window.MainWindow(args, not local_master)
348
349 if not rospy.is_shutdown():
350 os.chdir(PACKAGE_DIR)
351 main_form.show()
352 exit_code = -1
353 rospy.on_shutdown(finish)
354 exit_code = app.exec_()
355
356
357
358
359