def deleteLog(cls, nodename, host, auto_pw_request=False, user=None, pw=None): ''' Deletes the log file associated with the given node. @param nodename: the name of the node (with name space) @type nodename: C{str} @param host: the host name or ip where the log file are to delete @type host: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("delete log for '%s' on '%s'", utf8(nodename), utf8(host)) if nm.is_local(host): screenLog = nm.screen().getScreenLogFile(node=nodename) pidFile = nm.screen().getScreenPidFile(node=nodename) roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(screenLog): os.remove(screenLog) if os.path.isfile(pidFile): os.remove(pidFile) if os.path.isfile(roslog): os.remove(roslog) else: try: # output ignored: output, error, ok nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--delete_logs', nodename], user, pw, auto_pw_request, close_stdin=True, close_stdout=True, close_stderr=True) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.deleteLog, (nodename, host, auto_pw_request))
def data(self, role): if role == self.NAME_ROLE: return self.topic.name elif role == self.NODENAMES_ROLE: return utf8(self.topic.publisherNodes) + utf8(self.topic.subscriberNodes) else: return QStandardItem.data(self, role)
def storeCache(self, history_file, cache, history_len): ''' Stores the cache to a file. @param history_file: the name of the history file @type history_file: C{str} @param cache: the dictionary with values @type cache: C{dict} @param history_len: the maximal count of value for a key @type history_len: C{int} ''' ignored = dict() with codecs.open(os.path.join(nm.settings().cfg_path, history_file), 'w', encoding='utf-8') as f: for key in cache.keys(): count = 0 for value in cache[key]: if count < history_len: try: f.write(''.join([key, ':=', utf8(value), '\n'])) except UnicodeEncodeError, e: ignored[key] = (value, utf8(e)) except: import traceback rospy.logwarn("Storing history aborted: %s", traceback.format_exc(3)) count += 1
def run(self): ''' ''' try: if self._target is not None: if 'pqid' in self._target.func_code.co_varnames: self._target(*self._args, pqid=self._id) else: self._target(*self._args) self.finished_signal.emit(self._id) else: self.error_signal.emit(self._id, 'No target specified') except InteractionNeededError as ine: self.request_interact_signal.emit(self._id, self.descr, ine) except DetailedError as err: self.error_signal.emit(self._id, err.title, err.value, err.detailed_text) except Exception: import traceback # print traceback.print_exc() formatted_lines = traceback.format_exc(1).splitlines() last_line = formatted_lines[-1] index = 1 while not last_line and len(formatted_lines) > index: index += 1 last_line = formatted_lines[-index] self.error_signal.emit(self._id, 'Progress Job Error', "%s failed:\n%s" % (utf8(self.descr), utf8(last_line)), utf8(traceback.format_exc(4))) rospy.logwarn("%s failed:\n\t%s", utf8(self.descr), utf8(last_line))
def deleteLog(cls, nodename, host, auto_pw_request=False, user=None, pw=None): ''' Deletes the log file associated with the given node. @param nodename: the name of the node (with name space) @type nodename: C{str} @param host: the host name or ip where the log file are to delete @type host: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("delete log for '%s' on '%s'", utf8(nodename), utf8(host)) if nm.is_local(host): screenLog = nm.screen().getScreenLogFile(node=nodename) pidFile = nm.screen().getScreenPidFile(node=nodename) roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(screenLog): os.remove(screenLog) if os.path.isfile(pidFile): os.remove(pidFile) if os.path.isfile(roslog): os.remove(roslog) else: try: # output ignored: output, error, ok _, stdout, _, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--delete_logs', nodename], user, pw, auto_pw_request, close_stdin=True, close_stdout=False, close_stderr=True) if ok: stdout.readlines() stdout.close() except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.deleteLog, (nodename, host, auto_pw_request))
def run(self): ''' ''' if self._masteruri: service_names = interface_finder.get_refresh_service( self._masteruri, self._wait) err_msg = '' for service_name in service_names: rospy.logdebug("service 'refresh' found on %s as %s", self._masteruri, service_name) if self._wait: rospy.wait_for_service(service_name) socket.setdefaulttimeout(3) refreshMasters = rospy.ServiceProxy(service_name, std_srvs.srv.Empty) try: _ = refreshMasters() self.ok_signal.emit(self._masteruri) except rospy.ServiceException, e: rospy.logwarn("ERROR Service call 'refresh' failed: %s", utf8(e)) self.err_signal.emit( self._masteruri, "ERROR Service call 'refresh' failed: %s" % utf8(err_msg), True) finally: socket.setdefaulttimeout(None)
def loadCache(self, history_file): ''' Loads the content of the given file and return it as cache. @param history_file: the name of the history file @type history_file: C{str} @return: the dictionary with arguments @rtype: C{dict(str(name):[str(value), ...], ...)} ''' result = {} historyFile = os.path.join(nm.settings().cfg_path, history_file) if os.path.isfile(historyFile): with codecs.open(historyFile, 'r', encoding='utf-8') as f: line = utf8(f.readline()) while line: if line: line = line.strip() if line: key, sep, value = line.partition(':=') if sep: if key not in result.keys(): result[key] = [value] elif len(result[key]) <= nm.settings( ).param_history_length: result[key].append(value) line = utf8(f.readline()) return result
def data(self, role): if role == self.NAME_ROLE: return self.service.name elif role == self.TYPE_ROLE: return utf8(self.service.get_service_class(False)) elif role == self.NODENAMES_ROLE: return utf8(self.service.serviceProvider) else: return QStandardItem.data(self, role)
def __eq__(self, item): ''' Compares the value of parameter. ''' if isinstance(item, str) or isinstance(item, unicode): return utf8(self.value) == utf8(item) elif not (item is None): return utf8(self.value) == utf8(item.value) return False
def data(self, role): if role == self.NAME_ROLE: return self.name elif role == self.VALUE_ROLE: return utf8(self.value) elif role == self.TYPE_ROLE: return utf8(type(self.value).replace('<type \'').replace('\'>')) else: return QStandardItem.data(self, role)
def killScreens(cls, node, host, auto_ok_request=True, user=None, pw=None): ''' Searches for the screen associated with the given node and kill this screens. @param node: the name of the node those screen output to show @type node: C{str} @param host: the host name or ip where the screen is running @type host: C{str} ''' if node is None or len(node) == 0: return False try: # get the available screens screens = cls._getActiveScreens(host, cls.createSessionName(node), auto_ok_request, user=user, pwd=pw) # user=user, pwd=pwd if screens: do_kill = True if auto_ok_request: from node_manager_fkie.detailed_msg_box import MessageBox result = MessageBox.question(None, "Kill SCREENs?", '\n'.join(screens), buttons=MessageBox.Ok | MessageBox.Cancel) if result == MessageBox.Ok: do_kill = True if do_kill: for s in screens: pid, _, _ = s.partition('.') if pid: try: nm.starter()._kill_wo(host, int(pid), auto_ok_request, user, pw) except: import traceback rospy.logwarn( "Error while kill screen (PID: %s) on host '%s': %s", utf8(pid), utf8(host), traceback.format_exc(1)) if nm.is_local(host): SupervisedPopen( [cls.SCREEN, '-wipe'], object_id='screen -wipe', description="screen: clean up the socket with -wipe" ) else: nm.ssh().ssh_exec(host, [cls.SCREEN, '-wipe'], close_stdin=True, close_stdout=True, close_stderr=True) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.killScreens, (node, host, auto_ok_request))
def __init__(self, context): super(NodeManager, self).__init__(context) # Give QObjects reasonable names self.setObjectName('NodeManagerFKIE') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns node_manager_fkie.init_settings() masteruri = node_manager_fkie.settings().masteruri() node_manager_fkie.init_globals(masteruri) # Create QWidget try: self._widget = MainWindow() # self._widget.read_view_history() except Exception, e: MessageBox.critical(self, "Node Manager", utf8(e)) raise
def service_type_str(self): stype = '' try: stype = utf8(self.service.get_service_class(False)) except Exception: pass return stype
def interpret_path(path): ''' Tries to determine the path of the included file. The statement of C{$(find 'package')} will be resolved. @param path: the sting which contains the included path @type path: C{str} @return: C{$(find 'package')} will be resolved. The prefixes `file:///`, `package://` or `pkg://` are also resolved. Otherwise the parameter itself normalized by `os.path.normpath` will be returned. @rtype: C{str} ''' path = path.strip() index = path.find('$') if index > -1: startIndex = path.find('(', index) if startIndex > -1: endIndex = path.find(')', startIndex + 1) script = path[startIndex + 1:endIndex].split() if len(script) == 2 and (script[0] == 'find'): try: pkg = roslib.packages.get_pkg_dir(script[1]) return os.path.normpath('%s/%s' % (pkg, path[endIndex + 1:])) except Exception as e: rospy.logwarn(utf8(e)) else: try: return resolve_url(path) except ValueError, e: pass
def __init__(self, filenames, search_text='', parent=None): ''' @param filenames: a list with filenames. The last one will be activated. @type filenames: C{[str, ...]} @param search_text: if not empty, searches in new document for first occurrence of the given text @type search_text: C{str} (Default: C{Empty String}) ''' QMainWindow.__init__(self, parent) self.setObjectName('Editor - %s' % utf8(filenames)) self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowFlags(Qt.Window) self.mIcon = QIcon(":/icons/crystal_clear_edit_launch.png") self._error_icon = QIcon(":/icons/crystal_clear_warning.png") self._empty_icon = QIcon() self.setWindowIcon(self.mIcon) window_title = "ROSLaunch Editor" if filenames: window_title = self.__getTabName(filenames[0]) self.setWindowTitle(window_title) self.init_filenames = list(filenames) self._search_thread = None # list with all open files self.files = [] # create tabs for files self.main_widget = QWidget(self) self.verticalLayout = QVBoxLayout(self.main_widget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName("verticalLayout") self.tabWidget = EditorTabWidget(self) self.tabWidget.setTabPosition(QTabWidget.North) self.tabWidget.setDocumentMode(True) self.tabWidget.setTabsClosable(True) self.tabWidget.setMovable(False) self.tabWidget.setObjectName("tabWidget") self.tabWidget.tabCloseRequested.connect(self.on_close_tab) self.tabWidget.currentChanged.connect(self.on_tab_changed) self.verticalLayout.addWidget(self.tabWidget) self.buttons = self._create_buttons() self.verticalLayout.addWidget(self.buttons) self.setCentralWidget(self.main_widget) self.find_dialog = TextSearchFrame(self.tabWidget, self) self.find_dialog.search_result_signal.connect(self.on_search_result) self.find_dialog.replace_signal.connect(self.on_replace) self.addDockWidget(Qt.RightDockWidgetArea, self.find_dialog) self.graph_view = GraphViewWidget(self.tabWidget, self) self.graph_view.load_signal.connect(self.on_graph_load_file) self.graph_view.goto_signal.connect(self.on_graph_goto) self.addDockWidget(Qt.RightDockWidgetArea, self.graph_view) # open the files for f in filenames: if f: self.on_load_request(os.path.normpath(f), search_text) self.readSettings() self.find_dialog.setVisible(False) self.graph_view.setVisible(False)
def run(self): ''' ''' if self._masteruri: found = False service_names = interface_finder.get_listmaster_service(self._masteruri, self._wait) err_msg = '' for service_name in service_names: rospy.logdebug("service 'list_masters' found on %s as %s", self._masteruri, service_name) if self._wait: rospy.wait_for_service(service_name) socket.setdefaulttimeout(3) discoverMasters = rospy.ServiceProxy(service_name, DiscoverMasters) try: resp = discoverMasters() except rospy.ServiceException, e: err_msg = "Service call 'list_masters' failed: %s" % utf8(e) rospy.logwarn(err_msg) self.err_signal.emit(self._masteruri, "Service call '%s' failed: %s" % (service_name, err_msg), False) else: if resp.masters: self.master_list_signal.emit(self._masteruri, service_name, resp.masters) found = True else: self.err_signal.emit(self._masteruri, "local 'master_discovery' reports empty master list, it seems he has a problem", False) finally: socket.setdefaulttimeout(None)
def on_heartbeat_received(self, msg, address, is_multicast): force_update = False with self.mutex: try: hostname = self._hosts[address[0]] except: self.status_text_signal.emit("resolve %s" % address[0]) hostname = nm.nameres().hostname(utf8(address[0]), resolve=True) self._hosts[address[0]] = hostname try: (_version, _msg_tuple) = Discoverer.msg2masterState(msg, address) index = address[1] - self.default_port if index not in self._discovered: self._discovered[index] = dict() self._discovered[index][address] = (hostname, time.time()) if hostname not in self._msg_counts: self._msg_counts[hostname] = 0 self._msg_counts[hostname] += 1 self._received_msgs += 1 force_update = True except: print traceback.format_exc(1) if force_update: self._updateDisplay()
def stop(self): ''' Deletes all queued tasks and wait 3 seconds for the end of current running thread. ''' try: val = self._progress_bar.value() if val < len(self.__progress_queue): print " Stop progress queue '%s'..." % self._name thread = self.__progress_queue[val] self.__progress_queue = [] if thread.is_alive(): thread.join(3) print " Progress queue '%s' stopped!" % self._name except Exception: import traceback print utf8(traceback.format_exc())
def __init__(self, name, value, parent=None): ''' Initialize the item object. @param name: the name of the parameter @type name: C{str} @param value: the value of the parameter @type value: C{str} ''' QStandardItem.__init__( self, utf8(value) if not isinstance(value, Binary) else utf8(value)) self._name = name '''@ivar: the name of parameter ''' self._value = value '''@ivar: the value of the parameter ''' if isinstance(value, (str, unicode)) and value.find('\n') > -1: self.setSizeHint(QSize(-1, 45))
def _on_progress_canceled(self): try: if self.__progress_queue: try: pthread = self.__progress_queue[self._progress_bar.value()] pthread.finished_signal.disconnect(self._progress_thread_finished) pthread.error_signal.disconnect(self._progress_thread_error) pthread.request_interact_signal.disconnect(self._on_request_interact) # self.__progress_queue[self._progress_bar.value()].terminate() except: pass self.__progress_queue = [] self._progress_frame.setVisible(False) self.__running = False except: import traceback print utf8(traceback.format_exc(1))
def data(self, role): if role == self.NAME_ROLE: return self.service.name elif role == self.TYPE_ROLE: return self.service_type_str elif role == self.NODENAMES_ROLE: return utf8(self.service.serviceProvider) else: return QStandardItem.data(self, role)
def _kill_wo(self, host, pid, auto_pw_request=False, user=None, pw=None): rospy.loginfo("kill %s on %s", utf8(pid), host) if nm.is_local(host): os.kill(pid, signal.SIGKILL) rospy.loginfo("kill: %s", utf8(pid)) else: # kill on a remote machine cmd = ['kill -9', str(pid)] _, stdout, stderr, ok = nm.ssh().ssh_exec(host, cmd, user, pw, False, close_stdin=True) if ok: output = stdout.read() error = stderr.read() stdout.close() stderr.close() if error: rospy.logwarn("ERROR while kill %s: %s", utf8(pid), error) raise StartException(utf8(''.join(['The host "', host, '" reports:\n', error]))) if output: rospy.logdebug("STDOUT while kill %s on %s: %s", utf8(pid), host, output)
def _updateDisplay(self): self.display_clear_signal.emit() text = '<div style="font-family:Fixedsys,Courier,monospace; padding:10px;">\n' for index, addr_dict in self._discovered.items(): text = ''.join([ text, 'Network <b>', utf8(index), '</b>: <a href="', utf8(index), '">join</a><dl>' ]) for addr, (hostname, ts) in addr_dict.items(): text = ''.join([ text, '<dt>', self._getTsStr(ts), ' <b><u>', utf8(hostname), '</u></b> ', utf8(addr), ', received messages: ', str(self._msg_counts[hostname]), '</dt>\n' ]) text = ''.join([text, '</dl><br>']) text = ''.join([text, '</div>']) self.display_append_signal.emit(text)
def __init__(self, default_mcast_group, default_port, networks_count, parent=None): ''' Creates an input dialog. @param default_port: the default discovery port @type default_port: C{int} @param networks_count: the count of discovering ports @type networks_count: C{int} ''' QDialog.__init__(self, parent=parent) threading.Thread.__init__(self) self.default_port = default_port self.setObjectName('NetworkDiscoveryDialog') self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowFlags(Qt.Window) self.setWindowTitle('Network Discovery') self.resize(728, 512) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.display = QTextBrowser(self) self.display.setReadOnly(True) self.verticalLayout.addWidget(self.display) self.display_clear_signal.connect(self.display.clear) self.display_append_signal.connect(self.display.append) self.display.anchorClicked.connect(self.on_anchorClicked) self.status_label = QLabel('0 messages', self) self.verticalLayout.addWidget(self.status_label) self.status_text_signal.connect(self.status_label.setText) self._msg_counts = dict() self._networks_count = networks_count self._running = True self._received_msgs = 0 self._discovered = dict() self._hosts = dict() # resolution for hostname and address self.mutex = threading.RLock() self.sockets = [] with self.mutex: try: for p in range(networks_count): msock = DiscoverSocket(default_port + p, default_mcast_group) self.sockets.append(msock) msock.settimeout(self.TIMEOUT) except Exception as e: self.display.setText(utf8(e)) self.setDaemon(True) self.start()
def _removeFromCache(self, cache, key, value): uvalue = utf8(value) if key and uvalue: if key in cache: value_list = cache[key] try: value_list.remove(uvalue) except: pass if len(value_list) == 0: del cache[key]
def _prepareROSMaster(cls, masteruri): if masteruri is None: masteruri = masteruri_from_ros() # start roscore, if needed try: if not os.path.isdir(nm.ScreenHandler.LOG_PATH): os.makedirs(nm.ScreenHandler.LOG_PATH) socket.setdefaulttimeout(3) master = xmlrpclib.ServerProxy(masteruri) master.getUri(rospy.get_name()) # restart ROSCORE on different masteruri?, not now... # master_uri = master.getUri(rospy.get_name()) # if masteruri != master_uri[2]: # # kill the local roscore... # raise except: # run a roscore master_host = get_hostname(masteruri) if nm.is_local(master_host, True): master_port = get_port(masteruri) new_env = dict(os.environ) new_env['ROS_MASTER_URI'] = masteruri ros_hostname = NameResolution.get_ros_hostname(masteruri) if ros_hostname: new_env['ROS_HOSTNAME'] = ros_hostname cmd_args = '%s roscore --port %d' % (nm.ScreenHandler.getSceenCmd('/roscore--%d' % master_port), master_port) for n in [1, 2, 3, 4]: try: if n == 1: print("Launch ROS Master in screen ...") SupervisedPopen(shlex.split(cmd_args), env=new_env, object_id="ROSCORE", description="Start roscore") elif n == 2: print("ROS Master takes too long for start, wait for next 10 sec ...") elif n == 3: print("A really slow start, wait for last 10 sec ...") # wait for roscore to avoid connection problems while init_node result = -1 count = 1 while result == -1 and count < 11: try: master = xmlrpclib.ServerProxy(masteruri) result, _, _ = master.getUri(rospy.get_name()) # _:=uri, msg return except Exception: time.sleep(1) count += 1 if n == 4 and count >= 11: raise StartException('Cannot connect to ROS-Master: %s\n--> please run "roscore" manually!' % utf8(masteruri)) except Exception as e: raise Exception("Error while call '%s': %s" % (cmd_args, utf8(e))) else: raise Exception("ROS master '%s' is not reachable" % masteruri) finally: socket.setdefaulttimeout(None)
def _add2Cache(self, cache, key, value): uvalue = utf8(value) if key and uvalue: if key not in cache: cache[key] = [uvalue] elif uvalue not in cache[key]: cache[key].insert(0, uvalue) if len(cache[key]) >= nm.settings().param_history_length: cache[key].pop() else: cache[key].remove(uvalue) cache[key].insert(0, uvalue)
def str2list(self, l): if isinstance(l, list): return l try: l = l.strip('[]') l = l.replace('u"', '') l = l.replace('"', '') l = l.replace("'", '') l = l.replace(",", ' ') return [utf8(i).strip() for i in l.split(' ') if i] except: return []
def _getSSH(self, host, user, pw=None, do_connect=True, auto_pw_request=False): ''' @return: the paramiko ssh client @rtype: U{paramiko.SSHClient<http://docs.paramiko.org/en/1.10/api/client.html>} @raise BadHostKeyException: - if the server's host key could not be verified @raise AuthenticationException: - if authentication failed @raise SSHException: - if there was any other error connecting or establishing an SSH session @raise socket.error: - if a socket error occurred while connecting ''' session = SSHhandler.SSH_SESSIONS.get(host, paramiko.SSHClient()) if session is None or (not session.get_transport() is None and (not session.get_transport().is_active() or session._transport.get_username() != user)): t = SSHhandler.SSH_SESSIONS.pop(host) del t if host in self.SSH_AUTH: del self.SSH_AUTH[host] session = SSHhandler.SSH_SESSIONS.get(host, paramiko.SSHClient()) if session._transport is None: session.set_missing_host_key_policy(paramiko.AutoAddPolicy()) while (session.get_transport() is None or not session.get_transport().authenticated) and do_connect: try: session.connect(host, username=user, password=pw, timeout=3, compress=True) self.SSH_AUTH[host] = user except Exception, e: if utf8(e) in ['Authentication failed.', 'No authentication methods available', 'Private key file is encrypted']: if auto_pw_request: # 'print "REQUEST PW-AUTO" res, user, pw = self._requestPW(user, host) if not res: return None self.SSH_AUTH[host] = user else: raise AuthenticationRequest(user, host, utf8(e)) else: rospy.logwarn("ssh connection to %s failed: %s", host, utf8(e)) raise Exception(' '.join(["ssh connection to", host, "failed:", utf8(e)])) else: SSHhandler.SSH_SESSIONS[host] = session if not session.get_transport() is None: session.get_transport().set_keepalive(10)
def mastermonitor_loop(self): ''' The method test periodically the state of the ROS master. The new state will be published as 'state_signal'. ''' import os current_check_hz = OwnMasterMonitoring.ROSMASTER_HZ while (not rospy.is_shutdown() and not self._do_finish): try: if not self._do_pause: cputimes = os.times() cputime_init = cputimes[0] + cputimes[1] if self._master_monitor.checkState(): mon_state = self._master_monitor.getCurrentState() # publish the new state state = MasterState( MasterState.STATE_CHANGED, ROSMaster( utf8(self._local_addr), utf8(self._masteruri), mon_state.timestamp, mon_state.timestamp_local, True, rospy.get_name(), ''.join([ 'http://localhost:', utf8(self._master_monitor.rpcport) ]))) self.state_signal.emit(state) # adapt the check rate to the CPU usage time cputimes = os.times() cputime = cputimes[0] + cputimes[1] - cputime_init if current_check_hz * cputime > 0.20: current_check_hz = float(current_check_hz) / 2.0 elif current_check_hz * cputime < 0.10 and current_check_hz < OwnMasterMonitoring.ROSMASTER_HZ: current_check_hz = float(current_check_hz) * 2.0 except MasterConnectionException, mce: self._handle_exception( "MasterConnectionException while master check loop", mce) except RuntimeError, ree: # will thrown on exit of the app while try to emit the signal self._handle_exception("RuntimeError while master check loop", ree)
def run(self): ''' ''' if self._service and self._service_uri: try: if self._delay_exec > 0: time.sleep(self._delay_exec) _, resp = nm.starter().callService(self._service_uri, self._service, ListNodes) self.update_signal.emit(self._service_uri, self._service, resp.nodes) except: import traceback lines = traceback.format_exc(1).splitlines() rospy.logwarn("Error while retrieve the node list from %s[%s]: %s", utf8(self._service), utf8(self._service_uri), utf8(lines[-1])) self.err_signal.emit(self._service_uri, self._service, lines[-1])
def createSessionName(cls, node=None): ''' Creates a name for the screen session. All slash separators are replaced by L{SLASH_SEP} @param node: the name of the node @type node: C{str} @return: name for the screen session. @rtype: C{str} ''' # package_name = utf8(package) if not package is None else '' # lanchfile_name = utf8(launchfile).replace('.launch', '') if not launchfile is None else '' node_name = utf8(node).replace('/', cls.SLASH_SEP) if node is not None else '' # result = ''.join([node_name, '.', package_name, '.', lanchfile_name]) return node_name
def ssh_x11_exec(self, host, cmd, title=None, user=None): ''' Executes a command on remote host using a terminal with X11 forwarding. @todo: establish connection using paramiko SSH library. @param host: the host @type host: C{str} @param cmd: the list with command and arguments @type cmd: C{[str,...]} @param title: the title of the new opened terminal, if it is None, no new terminal will be created @type title: C{str} or C{None} @param user: user name @return: the result of C{subprocess.Popen(command)} @see: U{http://docs.python.org/library/subprocess.html?highlight=subproces#subprocess} ''' with self.mutex: try: # workaround: use ssh in a terminal with X11 forward user = nm.settings().host_user(host) if user is None else user if host in self.SSH_AUTH: user = self.SSH_AUTH[host] # generate string for SSH command ssh_str = ' '.join(['/usr/bin/ssh', '-aqtx', '-oClearAllForwardings=yes', '-oConnectTimeout=5', '-oStrictHostKeyChecking=no', '-oVerifyHostKeyDNS=no', '-oCheckHostIP=no', ''.join([user, '@', host])]) if title is not None: cmd_str = nm.settings().terminal_cmd([ssh_str, ' '.join(cmd)], title) else: cmd_str = utf8(' '.join([ssh_str, ' '.join(cmd)])) rospy.loginfo("REMOTE x11 execute on %s: %s", host, cmd_str) return SupervisedPopen(shlex.split(cmd_str), object_id=utf8(title), description="REMOTE x11 execute on %s: %s" % (host, cmd_str)) except: raise
def openLog(cls, nodename, host, user=None, only_screen=False): ''' Opens the log file associated with the given node in a new terminal. @param nodename: the name of the node (with name space) @type nodename: C{str} @param host: the host name or ip where the log file are @type host: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("show log for '%s' on '%s'", utf8(nodename), utf8(host)) title_opt = 'LOG %s on %s' % (nodename, host) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.settings().terminal_cmd([nm.settings().log_viewer, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) SupervisedPopen(shlex.split(cmd), object_id="Open log", description="Open log for '%s' on '%s'" % (utf8(nodename), utf8(host))) found = True # open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog) and not only_screen: title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.settings().terminal_cmd([nm.settings().log_viewer, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) SupervisedPopen(shlex.split(cmd), object_id="Open log", description="Open log for '%s' on '%s'" % (utf8(nodename), utf8(host))) found = True return found else: ps = nm.ssh().ssh_x11_exec(host, [nm.settings().start_remote_script, '--show_screen_log', nodename], title_opt, user) if not only_screen: ps = nm.ssh().ssh_x11_exec(host, [nm.settings().start_remote_script, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG'), user) return False
def mastermonitor_loop(self): ''' The method test periodically the state of the ROS master. The new state will be published as 'state_signal'. ''' import os current_check_hz = OwnMasterMonitoring.ROSMASTER_HZ while (not rospy.is_shutdown() and not self._do_finish): try: if not self._do_pause: cputimes = os.times() cputime_init = cputimes[0] + cputimes[1] if self._master_monitor.checkState(): mon_state = self._master_monitor.getCurrentState() # publish the new state state = MasterState(MasterState.STATE_CHANGED, ROSMaster(utf8(self._local_addr), utf8(self._masteruri), mon_state.timestamp, mon_state.timestamp_local, True, rospy.get_name(), ''.join(['http://localhost:', utf8(self._master_monitor.rpcport)]))) self.state_signal.emit(state) # adapt the check rate to the CPU usage time cputimes = os.times() cputime = cputimes[0] + cputimes[1] - cputime_init if current_check_hz * cputime > 0.20: current_check_hz = float(current_check_hz) / 2.0 elif current_check_hz * cputime < 0.10 and current_check_hz < OwnMasterMonitoring.ROSMASTER_HZ: current_check_hz = float(current_check_hz) * 2.0 except MasterConnectionException, mce: self._handle_exception("MasterConnectionException while master check loop", mce) except RuntimeError, ree: # will thrown on exit of the app while try to emit the signal self._handle_exception("RuntimeError while master check loop", ree)
def _on_edit_interface_clicked(self): self._new_iface = False self.interface_field.setVisible(False) self.toolButton_CreateInterface.setVisible(False) self.toolButton_EditInterface.setVisible(False) self.textedit.setVisible(True) if self.interface_field.currentText() in self._interfaces_files: try: with open(self._interfaces_files[self.interface_field.currentText()], 'rw') as f: iface = f.read() self.textedit.setText(iface) except Exception as e: MessageBox.warning(self, "Edit sync interface", "Error while open interface", utf8(e)) self.resize(350, 300)
def run(self): ''' ''' if self._masteruri: service_names = interface_finder.get_refresh_service(self._masteruri, self._wait) err_msg = '' for service_name in service_names: rospy.logdebug("service 'refresh' found on %s as %s", self._masteruri, service_name) if self._wait: rospy.wait_for_service(service_name) socket.setdefaulttimeout(3) refreshMasters = rospy.ServiceProxy(service_name, std_srvs.srv.Empty) try: _ = refreshMasters() self.ok_signal.emit(self._masteruri) except rospy.ServiceException, e: rospy.logwarn("ERROR Service call 'refresh' failed: %s", utf8(e)) self.err_signal.emit(self._masteruri, "ERROR Service call 'refresh' failed: %s" % utf8(err_msg), True) finally: socket.setdefaulttimeout(None)
def get_log_path(cls, host, nodes=[], auto_pw_request=False, user=None, pw=None): if nm.is_local(host): if len(nodes) == 1: return nm.screen().getScreenLogFile(node=nodes[0]) else: return nm.screen().LOG_PATH else: request = '[]' if len(nodes) != 1 else nodes[0] try: socket.setdefaulttimeout(3) _, stdout, _, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--ros_log_path', request], user, pw, auto_pw_request, close_stdin=True, close_stderr=True) if ok: output = stdout.read() stdout.close() return output.strip() else: raise StartException(utf8(''.join(['Get log path from "', host, '" failed']))) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.get_log_path, (host, nodes, auto_pw_request)) finally: socket.setdefaulttimeout(None)
def transfer_files(cls, host, path, auto_pw_request=False, user=None, pw=None): ''' Copies the given file to the remote host. Uses caching of remote paths. ''' # get package of the file if nm.is_local(host): # it's local -> no copy needed return (pkg_name, pkg_path) = package_name(os.path.dirname(path)) if pkg_name is not None: # get the subpath of the file subfile_path = path.replace(pkg_path, '') # get the path of the package on the remote machine try: output = '' error = '' ok = True if host in CACHED_PKG_PATH and pkg_name in CACHED_PKG_PATH[host]: output = CACHED_PKG_PATH[host][pkg_name] else: if host not in CACHED_PKG_PATH: CACHED_PKG_PATH[host] = dict() _, stdout, stderr, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--package', pkg_name], user, pw, auto_pw_request, close_stdin=True) output = stdout.read() error = stderr.read() stdout.close() stderr.close() if ok: if error: rospy.logwarn("ERROR while transfer %s to %s: %s", path, host, error) raise StartException(utf8(''.join(['The host "', host, '" reports:\n', error]))) if output: CACHED_PKG_PATH[host][pkg_name] = output nm.ssh().transfer(host, path, os.path.join(output.strip(), subfile_path.strip(os.sep)), user) else: raise StartException("Remote host no returned any answer. Is there the new version of node_manager installed?") else: raise StartException("Can't get path from remote host. Is there the new version of node_manager installed?") except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.transfer_files, (host, path, auto_pw_request))
def ntpdate(cls, host, cmd, user=None, pw=None): ''' Opens the log file associated with the given node in a new terminal. @param host: the host name or ip where the log file are @type host: C{str} @param cmd: command to set the time @type cmd: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' mesg = "synchronize time on '%s' using '%s'" % (utf8(host), cmd) rospy.loginfo(mesg) title_opt = "ntpdate on %s" % str(host) # '%s on %s' % (cmd, host) if nm.is_local(host): cmd = nm.settings().terminal_cmd([cmd], title_opt, noclose=True) rospy.loginfo("EXEC: %s" % cmd) ps = SupervisedPopen(shlex.split(cmd), object_id=cmd, description=mesg) else: ps = nm.ssh().ssh_x11_exec(host, [cmd, ';echo "";echo "this terminal will be closed in 10 sec...";sleep 10'], title_opt, user) return False
def ssh_exec(self, host, cmd, user=None, pw=None, auto_pw_request=False, get_pty=False, close_stdin=False, close_stdout=False, close_stderr=False): ''' Executes a command on remote host. Returns the output channels with execution result or None. The connection will be established using paramiko SSH library. @param host: the host @type host: C{str} @param cmd: the list with command and arguments @type cmd: C{[str,...]} @param user: user name @param pw: the password @return: the 4-tuple stdin, stdout, stderr and boolean of the executing command @rtype: C{tuple(ChannelFile, ChannelFile, ChannelFile, boolean)} @see: U{http://www.lag.net/paramiko/docs/paramiko.SSHClient-class.html#exec_command} ''' with self.mutex: try: ssh = self._getSSH(host, nm.settings().host_user(host) if user is None else user, pw, True, auto_pw_request) if ssh is not None: cmd_str = utf8(' '.join(cmd)) rospy.loginfo("REMOTE execute on %s@%s: %s", ssh._transport.get_username(), host, cmd_str) (stdin, stdout, stderr) = (None, None, None) if get_pty: (stdin, stdout, stderr) = ssh.exec_command(cmd_str, get_pty=get_pty) else: (stdin, stdout, stderr) = ssh.exec_command(cmd_str) if close_stdin: stdin.close() if close_stdout: stdout.close() if close_stderr: stderr.close() return stdin, stdout, stderr, True except AuthenticationRequest as e: raise except Exception as e: raise raise Exception('Cannot login @%s' % host)
def accept(self): if self.textedit.isVisible(): try: tmp_file = os.path.join(nm.screen().LOG_PATH, 'tmp_sync_interface.sync') with open(tmp_file, 'w+') as f: f.write(self.textedit.toPlainText()) from master_discovery_fkie.common import read_interface read_interface(tmp_file) if not self._new_iface and self.interface_field.currentText() in self._interfaces_files: fileName = self._interfaces_files[self.interface_field.currentText()] else: fileName, _ = QFileDialog.getSaveFileName(self, 'Save sync interface', '/home', "Sync Files (*.sync)") if fileName: with open(fileName, 'w+') as f: self._interface_filename = fileName f.write(self.textedit.toPlainText()) if self._new_iface: self.interface_field.clear() self._interfaces_files = None self._on_select_interface_clicked() # QDialog.accept(self) # self.resetView() except Exception as e: MessageBox.warning(self, "Create sync interface", "Error while create interface", utf8(e)) elif self.interface_field.isVisible(): interface = self.interface_field.currentText() if self._interfaces_files and interface in self._interfaces_files: self._interface_filename = self._interfaces_files[interface] self._sync_args = [] self._sync_args.append(''.join(['_interface_url:=', interface])) QDialog.accept(self) self.resetView() else: QDialog.accept(self) self.resetView()
def _requestPW(self, user, host): ''' Open the dialog to input the user name and password to open an SSH connection. ''' from python_qt_binding.QtCore import Qt from python_qt_binding import loadUi try: from python_qt_binding.QtGui import QDialog except: from python_qt_binding.QtWidgets import QDialog result = False pw = None pwInput = QDialog() ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'PasswordInput.ui') loadUi(ui_file, pwInput) pwInput.setWindowTitle(''.join(['Enter the password for user ', user, ' on ', host])) pwInput.userLine.setText(utf8(user)) pwInput.pwLine.setText("") pwInput.pwLine.setFocus(Qt.OtherFocusReason) if pwInput.exec_(): result = True user = pwInput.userLine.text() pw = pwInput.pwLine.text() return result, user, pw
def mouseReleaseEvent(self, event): ''' Opens the new editor, if the user clicked on the included file and sets the default cursor. ''' if event.modifiers() == Qt.ControlModifier or event.modifiers() == Qt.ShiftModifier: cursor = self.cursorForPosition(event.pos()) inc_files = LaunchConfig.included_files(cursor.block().text(), recursive=False) if inc_files: try: qf = QFile(inc_files[0]) if not qf.exists(): # create a new file, if it does not exists result = MessageBox.question(self, "File not found", '\n\n'.join(["Create a new file?", qf.fileName()]), buttons=MessageBox.Yes | MessageBox.No) if result == MessageBox.Yes: d = os.path.dirname(qf.fileName()) if not os.path.exists(d): os.makedirs(d) with open(qf.fileName(), 'w') as f: if qf.fileName().endswith('.launch'): f.write('<launch>\n\n</launch>') event.setAccepted(True) self.load_request_signal.emit(qf.fileName()) else: event.setAccepted(True) self.load_request_signal.emit(qf.fileName()) except Exception, e: MessageBox.critical(self, "Error", "File not found %s" % inc_files[0], detailed_text=utf8(e))
def callService(self, service_uri, service, service_type, service_args=[]): ''' Calls the service and return the response. To call the service the ServiceProxy can't be used, because it uses environment variables to determine the URI of the running service. In our case this service can be running using another ROS master. The changes on the environment variables is not thread safe. So the source code of the rospy.SerivceProxy (tcpros_service.py) was modified. @param service_uri: the URI of the service @type service_uri: C{str} @param service: full service name (with name space) @type service: C{str} @param service_type: service class @type service_type: ServiceDefinition: service class @param service_args: arguments @return: the tuple of request and response. @rtype: C{(request object, response object)} @raise StartException: on error @see: U{rospy.SerivceProxy<http://docs.ros.org/kinetic/api/rospy/html/rospy.impl.tcpros_service.ServiceProxy-class.html>} ''' service = str(service) rospy.loginfo("Call service %s[%s]: %s, %s", utf8(service), utf8(service_uri), utf8(service_type), utf8(service_args)) from rospy.core import parse_rosrpc_uri, is_shutdown # from rospy.msg import args_kwds_to_message from rospy.exceptions import TransportInitError, TransportException from rospy.impl.tcpros_base import TCPROSTransport, DEFAULT_BUFF_SIZE # ,TCPROSTransportProtocol from rospy.impl.tcpros_service import TCPROSServiceClient from rospy.service import ServiceException request = service_type._request_class() import genpy try: now = rospy.get_rostime() import std_msgs.msg keys = {'now': now, 'auto': std_msgs.msg.Header(stamp=now)} genpy.message.fill_message_args(request, service_args, keys) except genpy.MessageException as e: def argsummary(args): if type(args) in [tuple, list]: return '\n'.join([' * %s (type %s)' % (a, type(a).__name__) for a in args]) else: return ' * %s (type %s)' % (args, type(args).__name__) raise StartException("Incompatible arguments to call service:\n%s\nProvided arguments are:\n%s\n\nService arguments are: [%s]" % (e, argsummary(service_args), genpy.message.get_printable_message_args(request))) # request = args_kwds_to_message(type._request_class, args, kwds) protocol = TCPROSServiceClient(service, service_type, headers={}) transport = TCPROSTransport(protocol, service) # initialize transport dest_addr, dest_port = parse_rosrpc_uri(service_uri) # connect to service transport.buff_size = DEFAULT_BUFF_SIZE try: transport.connect(dest_addr, dest_port, service_uri, timeout=5) except TransportInitError as e: # can be a connection or md5sum mismatch raise StartException(''.join(["unable to connect to service: ", utf8(e)])) transport.send_message(request, 0) try: responses = transport.receive_once() if len(responses) == 0: raise StartException("service [%s] returned no response" % service) elif len(responses) > 1: raise StartException("service [%s] returned multiple responses: %s" % (service, len(responses))) except TransportException as e: # convert lower-level exception to exposed type if is_shutdown(): raise StartException("node shutdown interrupted service call") else: raise StartException("transport error completing service call: %s" % (utf8(e))) except ServiceException, e: raise StartException("Service error: %s" % (utf8(e)))
import rospy from master_discovery_fkie.master_monitor import MasterMonitor, MasterConnectionException import master_discovery_fkie.interface_finder as interface_finder from node_manager_fkie.common import utf8 try: import std_srvs.srv from multimaster_msgs_fkie.msg import LinkStatesStamped, MasterState, ROSMaster # , LinkState, SyncMasterInfo, SyncTopicInfo from multimaster_msgs_fkie.srv import DiscoverMasters # , GetSyncInfo except ImportError, e: import sys print >> sys.stderr, "Can't import messages and services of multimaster_msgs_fkie. Is multimaster_msgs_fkie package compiled?" raise ImportError(utf8(e)) class MasterListService(QObject): ''' A class to retrieve the ROS master list from a ROS service. The service will be determine using U{master_discovery_fkie.interface_finder.get_listmaster_service()<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#interface-finder-module>} ''' masterlist_signal = Signal(str, str, list) '''@ivar: a signal with a list of the masters retrieved from the master_discovery service 'list_masters'. ParameterB{:} C{masteruri}, C{service name}, C{[U{master_discovery_fkie.msg.ROSMaster<http://docs.ros.org/api/multimaster_msgs_fkie/html/msg/ROSMaster.html>}, ...]}''' masterlist_err_signal = Signal(str, str) '''@ivar: this signal is emitted if an error while calling #list_masters' service of master_discovery is failed. ParameterB{:} C{masteruri}, C{error}'''
def runNode(cls, runcfg): ''' Start the node with given name from the given configuration. @param runcfg: the configuration containing the start parameter @type runcfg: AdvRunCfg @raise StartException: if the screen is not available on host. @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' # 'print "RUN node", node, time.time() n = runcfg.roslaunch_config.getNode(runcfg.node) if n is None: raise StartException(''.join(["Node '", runcfg.node, "' not found!"])) env = list(n.env_args) # set logging options if runcfg.logging is not None: if not runcfg.logging.is_default('console_format'): env.append(('ROSCONSOLE_FORMAT', '%s' % runcfg.logging.console_format)) if n.respawn: # set the respawn environment variables respawn_params = cls._get_respawn_params(rospy.names.ns_join(n.namespace, n.name), runcfg.roslaunch_config.Roscfg.params) if respawn_params['max'] > 0: env.append(('RESPAWN_MAX', '%d' % respawn_params['max'])) if respawn_params['min_runtime'] > 0: env.append(('RESPAWN_MIN_RUNTIME', '%d' % respawn_params['min_runtime'])) if respawn_params['delay'] > 0: env.append(('RESPAWN_DELAY', '%d' % respawn_params['delay'])) prefix = n.launch_prefix if n.launch_prefix is not None else '' if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1: rospy.loginfo("SCREEN prefix removed before start!") prefix = '' args = ['__ns:=%s' % n.namespace.rstrip(rospy.names.SEP), '__name:=%s' % n.name] if n.cwd is not None: args.append('__cwd:=%s' % n.cwd) # add remaps for remap in n.remap_args: args.append(''.join([remap[0], ':=', remap[1]])) # get host of the node host = runcfg.roslaunch_config.hostname env_loader = '' if n.machine_name: machine = runcfg.roslaunch_config.Roscfg.machines[n.machine_name] if machine.address not in ['localhost', '127.0.0.1']: host = machine.address if runcfg.masteruri is None: runcfg.masteruri = nm.nameres().masteruri(n.machine_name) # TODO: env-loader support? # if hasattr(machine, "env_loader") and machine.env_loader: # env_loader = machine.env_loader # set the host to the given host if runcfg.force2host is not None: host = runcfg.force2host # set the ROS_MASTER_URI if runcfg.masteruri is None: runcfg.masteruri = masteruri_from_ros() env.append(('ROS_MASTER_URI', runcfg.masteruri)) ros_hostname = NameResolution.get_ros_hostname(runcfg.masteruri) if ros_hostname: env.append(('ROS_HOSTNAME', ros_hostname)) abs_paths = list() # tuples of (parameter name, old value, new value) not_found_packages = list() # package names # set the global parameter if runcfg.masteruri is not None and runcfg.masteruri not in runcfg.roslaunch_config.global_param_done: global_node_names = cls.getGlobalParams(runcfg.roslaunch_config.Roscfg) rospy.loginfo("Register global parameter:\n %s", '\n '.join("%s%s" % (utf8(v)[:80], '...' if len(utf8(v)) > 80 else'') for v in global_node_names.values())) abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(runcfg.masteruri, global_node_names, [], runcfg.user, runcfg.pw, runcfg.auto_pw_request) runcfg.roslaunch_config.global_param_done.append(runcfg.masteruri) # add params if runcfg.masteruri is not None: nodens = ''.join([n.namespace, n.name, rospy.names.SEP]) params = dict() for param, value in runcfg.roslaunch_config.Roscfg.params.items(): if param.startswith(nodens): params[param] = value clear_params = [] for cparam in runcfg.roslaunch_config.Roscfg.clear_params: if cparam.startswith(nodens): clear_params.append(cparam) rospy.loginfo("Delete parameter:\n %s", '\n '.join(clear_params)) rospy.loginfo("Register parameter:\n %s", '\n '.join("%s%s" % (utf8(v)[:80], '...' if len(utf8(v)) > 80 else'') for v in params.values())) abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(runcfg.masteruri, params, clear_params, runcfg.user, runcfg.pw, runcfg.auto_pw_request) # 'print "RUN prepared", node, time.time() if nm.is_local(host, wait=True): nm.screen().testScreen() if runcfg.executable: cmd_type = runcfg.executable else: try: cmd = roslib.packages.find_node(n.package, n.type) except (Exception, roslib.packages.ROSPkgException) as starterr: # multiple nodes, invalid package raise StartException("Can't find resource: %s" % starterr) # handle diferent result types str or array of string if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise StartException("%s in package [%s] not found!\n\nThe package " "was created?\nIs the binary executable?\n" % (n.type, n.package)) if len(cmd) > 1: if runcfg.auto_pw_request: # Open selection for executables, only if the method is called from the main GUI thread try: try: from python_qt_binding.QtGui import QInputDialog except: from python_qt_binding.QtWidgets import QInputDialog item, result = QInputDialog.getItem(None, 'Multiple executables %s in %s' % (n.type, n.package), 'Select an executable', cmd, 0, False) if result: # open the selected screen cmd_type = item else: return except: raise StartException('Multiple executables with same name in package found!') else: err = BinarySelectionRequest(cmd, 'Multiple executables') raise nm.InteractionNeededError(err, cls.runNode, (runcfg,)) else: cmd_type = cmd[0] # determine the current working path, Default: the package of the node cwd = get_ros_home() if not (n.cwd is None): if n.cwd == 'ROS_HOME': cwd = get_ros_home() elif n.cwd == 'node': cwd = os.path.dirname(cmd_type) cls._prepareROSMaster(runcfg.masteruri) node_cmd = [nm.settings().respawn_script if n.respawn else '', prefix, cmd_type] cmd_args = [nm.screen().getSceenCmd(runcfg.node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(utf8(n.args)) cmd_args[len(cmd_args):] = args rospy.loginfo("RUN: %s", ' '.join(cmd_args)) new_env = dict(os.environ) new_env['ROS_MASTER_URI'] = runcfg.masteruri ros_hostname = NameResolution.get_ros_hostname(runcfg.masteruri) if ros_hostname: new_env['ROS_HOSTNAME'] = ros_hostname # add the namespace environment parameter to handle some cases, # e.g. rqt_cpp plugins if n.namespace: new_env['ROS_NAMESPACE'] = n.namespace # set logging options if runcfg.logging is not None: if not runcfg.logging.is_default('loglevel'): env.append(('ROSCONSOLE_CONFIG_FILE', nm.settings().rosconsole_cfg_file(n.package))) for key, value in env: new_env[key] = value SupervisedPopen(shlex.split(utf8(' '.join(cmd_args))), cwd=cwd, env=new_env, object_id="Run node", description="Run node " "[%s]%s" % (utf8(n.package), utf8(n.type))) nm.filewatcher().add_binary(cmd_type, runcfg.node, runcfg.masteruri, runcfg.roslaunch_config.Filename) else: # 'print "RUN REMOTE", node, time.time() # start remote if runcfg.roslaunch_config.PackageName is None: raise StartException("Can't run remote without a valid package name!") # thus the prefix parameters while the transfer are not separated if prefix: prefix = ''.join(['"', prefix, '"']) # setup environment env_command = '' if env_loader: rospy.logwarn("env_loader in machine tag currently not supported") raise StartException("env_loader in machine tag currently not supported") if env: new_env = dict() try: for (k, v) in env: v_value, is_abs_path, found, package = cls._resolve_abs_paths(v, host, runcfg.user, runcfg.pw, runcfg.auto_pw_request) new_env[k] = v_value if is_abs_path: abs_paths.append(('ENV', "%s=%s" % (k, v), "%s=%s" % (k, v_value))) if not found and package: not_found_packages.append(package) env_command = "env " + ' '.join(["%s=\'%s\'" % (k, v) for (k, v) in new_env.items()]) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.runNode, (runcfg,)) startcmd = [env_command, nm.settings().start_remote_script, '--package', utf8(n.package), '--node_type', utf8(n.type), '--node_name', utf8(runcfg.node), '--node_respawn true' if n.respawn else ''] if runcfg.masteruri is not None: startcmd.append('--masteruri') startcmd.append(runcfg.masteruri) if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] if runcfg.logging is not None: if not runcfg.logging.is_default('loglevel'): startcmd.append('--loglevel') startcmd.append(nm.settings().logging.loglevel) # rename the absolute paths in the args of the node node_args = [] try: for a in n.args.split(): a_value, is_abs_path, found, package = cls._resolve_abs_paths(a, host, runcfg.user, runcfg.pw, runcfg.auto_pw_request) node_args.append(a_value) if is_abs_path: abs_paths.append(('ARGS', a, a_value)) if not found and package: not_found_packages.append(package) startcmd[len(startcmd):] = node_args startcmd[len(startcmd):] = args rospy.loginfo("Run remote on %s: %s", host, utf8(' '.join(startcmd))) # 'print "RUN CALL", node, time.time() _, stdout, stderr, ok = nm.ssh().ssh_exec(host, startcmd, runcfg.user, runcfg.pw, runcfg.auto_pw_request, close_stdin=True) output = stdout.read() error = stderr.read() stdout.close() stderr.close() # 'print "RUN CALLOK", node, time.time() except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.runNode, (runcfg,)) if ok: if error: rospy.logwarn("ERROR while start '%s': %s", runcfg.node, error) raise StartException(utf8(''.join(['The host "', host, '" reports:\n', error]))) if output: rospy.loginfo("STDOUT while start '%s': %s", runcfg.node, output) # inform about absolute paths in parameter value if len(abs_paths) > 0: rospy.loginfo("Absolute paths found while start:\n%s", utf8('\n'.join([''.join([p, '\n OLD: ', ov, '\n NEW: ', nv]) for p, ov, nv in abs_paths]))) if len(not_found_packages) > 0: packages = '\n'.join(not_found_packages) raise StartException(utf8('\n'.join(['Some absolute paths are not renamed because following packages are not found on remote host:', packages])))