def openLog(cls, nodename, host): ''' 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()} ''' title_opt = ' '.join(['"LOG', nodename, 'on', host, '"']) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.terminal_cmd([nm.LESS, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) subprocess.Popen(shlex.split(cmd)) found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.terminal_cmd([nm.LESS, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) subprocess.Popen(shlex.split(cmd)) found = True return found else: nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_screen_log', nodename], title_opt) nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG')) return False
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 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'", str(nodename), str(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 openLog(cls, nodename, host, user=None): ''' 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'", str(nodename), str(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), id="Open log", description="Open log for '%s' on '%s'"%(str(nodename), str(host))) found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): 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), id="Open log", description="Open log for '%s' on '%s'"%(str(nodename), str(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) 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 copylogPath2Clipboards(self, host, nodes=[], auto_pw_request=True, 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: output, error, ok = nm.ssh().ssh_exec( host, [nm.STARTER_SCRIPT, '--ros_log_path', request], user, pw, auto_pw_request) if ok: return output else: raise StartException( str(''.join([ 'Get log path from "', host, '" failed:\n', error ]))) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError( e, cls.deleteLog, (nodename, host, auto_pw_request))
def deleteLog(cls, nodename, host): ''' 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()} ''' 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: (stdin, stdout, stderr), ok = nm.ssh().ssh_exec( host, [nm.STARTER_SCRIPT, '--delete_logs', nodename]) if ok: stdin.close()
def openLog(cls, nodename, host): ''' 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'", str(nodename), str(host)) title_opt = ' '.join(['"LOG', nodename, 'on', host, '"']) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.terminal_cmd([nm.LESS, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.terminal_cmd([nm.LESS, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True return found else: ps = nm.ssh().ssh_x11_exec( host, [nm.STARTER_SCRIPT, '--show_screen_log', nodename], title_opt) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() ps = nm.ssh().ssh_x11_exec( host, [nm.STARTER_SCRIPT, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG')) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() return False
def openLog(cls, nodename, host, user=None): ''' 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'", str(nodename), str(host)) title_opt = ' '.join(['"LOG', nodename, 'on', host, '"']) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.terminal_cmd([nm.LESS, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.terminal_cmd([nm.LESS, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True return found else: ps = nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_screen_log', nodename], title_opt, user) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() ps = nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG'), user) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() return False
def openLog(cls, nodename, host, user=None): ''' 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'", str(nodename), str(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), id="Open log", description="Open log for '%s' on '%s'" % (str(nodename), str(host))) found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): 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), id="Open log", description="Open log for '%s' on '%s'" % (str(nodename), str(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) 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 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: iface = f.write(self.textedit.toPlainText()) from master_sync_fkie.common import read_interface read_interface(tmp_file) if not self._new_iface and self._interfaces_files.has_key(self.interface_field.currentText()): fileName = self._interfaces_files[self.interface_field.currentText()] else: fileName, selectedFilter = QtGui.QFileDialog.getSaveFileName(self, 'Save sync interface', '/home', "Sync Files (*.sync)") if fileName: with open(fileName, 'w+') as f: iface = f.write(self.textedit.toPlainText()) if self._new_iface: self.interface_field.clear() self._interfaces_files = None self._on_select_interface_clicked() # QtGui.QDialog.accept(self) # self.resetView() except Exception as e: WarningMessageBox(QtGui.QMessageBox.Warning, "Create sync interface", "Error while create interface", str(e)).exec_() elif self.interface_field.isVisible(): interface = self.interface_field.currentText() if self._interfaces_files and self._interfaces_files.has_key(interface): self._sync_args = [] self._sync_args.append(''.join(['_interface_url:=', interface])) QtGui.QDialog.accept(self) self.resetView() else: QtGui.QDialog.accept(self) self.resetView()
def copylogPath2Clipboards(self, host, nodes=[], auto_pw_request=True, 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: output, error, ok = nm.ssh().ssh_exec(host, [nm.STARTER_SCRIPT, '--ros_log_path', request], user, pw, auto_pw_request) if ok: return output else: raise StartException(str(''.join(['Get log path from "', host, '" failed:\n', error]))) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.deleteLog, (nodename, host, auto_pw_request))
def copylogPath2Clipboards(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) output, error, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--ros_log_path', request], user, pw, auto_pw_request) if ok: return output else: raise StartException(str(''.join(['Get log path from "', host, '" failed:\n', error]))) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.copylogPath2Clipboards, (host, nodes, auto_pw_request)) 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 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(str(''.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 deleteLog(cls, nodename, host): ''' 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()} ''' 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: (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, [nm.STARTER_SCRIPT, '--delete_logs', nodename]) if ok: stdin.close()
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._interfaces_files.has_key( self.interface_field.currentText()): fileName = self._interfaces_files[ self.interface_field.currentText()] else: fileName, _ = QtGui.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() # QtGui.QDialog.accept(self) # self.resetView() except Exception as e: WarningMessageBox(QtGui.QMessageBox.Warning, "Create sync interface", "Error while create interface", str(e)).exec_() elif self.interface_field.isVisible(): interface = self.interface_field.currentText() if self._interfaces_files and self._interfaces_files.has_key( interface): self._interface_filename = self._interfaces_files[interface] self._sync_args = [] self._sync_args.append(''.join(['_interface_url:=', interface])) QtGui.QDialog.accept(self) self.resetView() else: QtGui.QDialog.accept(self) self.resetView()
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 runNodeWithoutConfig(cls, host, package, binary, name, args=[], masteruri=None, auto_pw_request=False, user=None, pw=None): ''' Start a node with using a launch configuration. @param host: the host or ip to run the node @type host: C{str} @param package: the ROS package containing the binary @type package: C{str} @param binary: the binary of the node to execute @type binary: C{str} @param name: the ROS name of the node (with name space) @type name: C{str} @param args: the list with arguments passed to the binary @type args: C{[str, ...]} @param auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread @type auto_pw_request: bool @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' # create the name with namespace args2 = list(args) fullname = roslib.names.ns_join(roslib.names.SEP, name) namespace = '' for a in args: if a.startswith('__ns:='): namespace = a.replace('__ns:=', '') fullname = roslib.names.ns_join(namespace, name) args2.append(''.join(['__name:=', name])) # run on local host if nm.is_local(host, wait=True): try: cmd = roslib.packages.find_node(package, binary) except roslib.packages.ROSPkgException as e: # multiple nodes, invalid package raise StartException(utf8(e)) # handle different result types str or array of string # import types 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!' % (binary, package)) if len(cmd) > 1: # Open selection for executables err = [''.join(['Multiple executables with same name in package [', package, '] found:'])] err.extend(cmd) raise StartException('\n'.join(err)) else: cmd_type = cmd[0] cmd_str = utf8(' '.join([nm.screen().getSceenCmd(fullname), cmd_type, ' '.join(args2)])) rospy.loginfo("Run without config: %s", cmd_str) new_env = dict(os.environ) if namespace: new_env['ROS_NAMESPACE'] = namespace if masteruri is not None: cls._prepareROSMaster(masteruri) new_env['ROS_MASTER_URI'] = masteruri ros_hostname = NameResolution.get_ros_hostname(masteruri) if ros_hostname: new_env['ROS_HOSTNAME'] = ros_hostname SupervisedPopen(shlex.split(cmd_str), env=new_env, object_id="Run without config", description="Run without config [%s]%s" % (utf8(package), utf8(binary))) else: # run on a remote machine startcmd = [nm.settings().start_remote_script, '--package', utf8(package), '--node_type', utf8(binary), '--node_name', utf8(fullname)] startcmd[len(startcmd):] = args2 if masteruri is not None: startcmd.append('--masteruri') startcmd.append(masteruri) rospy.loginfo("Run remote on %s: %s", host, ' '.join(startcmd)) try: _, stdout, stderr, ok = nm.ssh().ssh_exec(host, startcmd, user, pw, auto_pw_request, close_stdin=True) if ok: output = stdout.read() error = stderr.read() stdout.close() stderr.close() if error: rospy.logwarn("ERROR while start '%s': %s", name, error) raise StartException(''.join(['The host "', host, '" reports:\n', error])) if output: rospy.logdebug("STDOUT while start '%s': %s", name, output) else: if error: rospy.logwarn("ERROR while start '%s': %s", name, error) raise StartException(''.join(['The host "', host, '" reports:\n', error])) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.runNodeWithoutConfig, (host, package, binary, name, args, masteruri, auto_pw_request))
def runNode(cls, node, launch_config, force2host=None, masteruri=None): ''' Start the node with given name from the given configuration. @param node: the name of the node (with name space) @type node: C{str} @param launch_config: the configuration containing the node @type launch_config: L{LaunchConfig} @param force2host: start the node on given host. @type force2host: L{str} @param masteruri: force the masteruri. @type masteruri: L{str} @raise StartException: if the screen is not available on host. @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' n = launch_config.getNode(node) if n is None: raise StartException(''.join(["Node '", node, "' not found!"])) env = list(n.env_args) prefix = n.launch_prefix if not n.launch_prefix is None else '' if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1: rospy.loginfo("SCREEN prefix removed before start!") prefix = '' args = [''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name])] if not (n.cwd is None): args.append(''.join(['__cwd:=', n.cwd])) # add remaps for remap in n.remap_args: args.append(''.join([remap[0], ':=', remap[1]])) # get host of the node host = launch_config.hostname env_loader = '' if n.machine_name: machine = launch_config.Roscfg.machines[n.machine_name] host = machine.address #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 not force2host is None: host = force2host if masteruri is None: masteruri = nm.nameres().masteruri(n.machine_name) # set the ROS_MASTER_URI if masteruri is None: masteruri = nm.masteruri_from_ros() env.append(('ROS_MASTER_URI', masteruri)) abs_paths = list() # tuples of (parameter name, old value, new value) not_found_packages = list() # package names # set the global parameter if not masteruri is None and not masteruri in launch_config.global_param_done: global_node_names = cls.getGlobalParams(launch_config.Roscfg) rospy.loginfo("Register global parameter:\n%s", '\n'.join(global_node_names)) abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(masteruri, global_node_names, []) launch_config.global_param_done.append(masteruri) # add params if not masteruri is None: nodens = ''.join([n.namespace, n.name, '/']) params = dict() for param, value in launch_config.Roscfg.params.items(): if param.startswith(nodens): params[param] = value clear_params = [] for cparam in launch_config.Roscfg.clear_params: if cparam.startswith(nodens): clear_params.append(param) rospy.loginfo("Register parameter:\n%s", '\n'.join(params)) abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(masteruri, params, clear_params) if nm.is_local(host): nm.screen().testScreen() try: cmd = roslib.packages.find_node(n.package, n.type) except (Exception, roslib.packages.ROSPkgException) as e: # multiple nodes, invalid package raise StartException(''.join(["Can't find resource: ", str(e)])) # handle diferent result types str or array of string import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise nm.StartException(' '.join([n.type, 'in package [', n.package, '] not found!\n\nThe package was created?\nIs the binary executable?\n'])) if len(cmd) > 1: # Open selection for executables try: from PySide import QtGui item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', n.type, 'in', n.package]), 'Select an executable', cmd, 0, False) if result: #open the selected screen cmd_type = item else: return except: raise nm.StartException('Multiple executables with same name in package found!') else: cmd_type = cmd[0] # determine the current working path, Default: the package of the node cwd = nm.get_ros_home() if not (n.cwd is None): if n.cwd == 'ROS_HOME': cwd = nm.get_ros_home() elif n.cwd == 'node': cwd = os.path.dirname(cmd_type) # else: # cwd = LaunchConfig.packageName(os.path.dirname(cmd_type)) cls._prepareROSMaster(masteruri) node_cmd = [nm.RESPAWN_SCRIPT if n.respawn else '', prefix, cmd_type] cmd_args = [nm.screen().getSceenCmd(node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(str(n.args)) cmd_args[len(cmd_args):] = args rospy.loginfo("RUN: %s", ' '.join(cmd_args)) if not masteruri is None: new_env=dict(os.environ) new_env['ROS_MASTER_URI'] = masteruri ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))), cwd=cwd, env=new_env) else: ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))), cwd=cwd) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() else: # start remote if launch_config.PackageName is None: raise StartException(''.join(["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 nm.StartException("env_loader in machine tag currently not supported") if env: env_command = "env "+' '.join(["%s=%s"%(k,v) for (k, v) in env]) startcmd = [env_command, nm.STARTER_SCRIPT, '--package', str(n.package), '--node_type', str(n.type), '--node_name', str(node), '--node_respawn true' if n.respawn else ''] if not masteruri is None: startcmd.append('--masteruri') startcmd.append(masteruri) if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] #rename the absolute paths in the args of the node node_args = [] for a in n.args.split(): a_value, is_abs_path, found, package = cls._resolve_abs_paths(a, host) 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, str(' '.join(startcmd))) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() # stderr.close() # stdout.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", node, error) raise nm.StartException(str(''.join(['The host "', host, '" reports:\n', error]))) output = stdout.read() if output: rospy.loginfo("STDOUT while start '%s': %s", node, output) # inform about absolute paths in parameter value if len(abs_paths) > 0: rospy.loginfo("Absolute paths found while start:\n%s", str('\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 nm.StartException(str('\n'.join(['Some absolute paths are not renamed because following packages are not found on remote host:', packages])))
def runNodeWithoutConfig(cls, host, package, type, name, args=[], masteruri=None): ''' Start a node with using a launch configuration. @param host: the host or ip to run the node @type host: C{str} @param package: the ROS package containing the binary @type package: C{str} @param type: the binary of the node to execute @type type: C{str} @param name: the ROS name of the node (with name space) @type name: C{str} @param args: the list with arguments passed to the binary @type args: C{[str, ...]} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' # create the name with namespace args2 = list(args) fullname = roslib.names.ns_join(roslib.names.SEP, name) for a in args: if a.startswith('__ns:='): fullname = roslib.names.ns_join(a.replace('__ns:=', ''), name) args2.append(''.join(['__name:=', name])) # run on local host if nm.is_local(host): try: cmd = roslib.packages.find_node(package, type) except roslib.packages.ROSPkgException as e: # multiple nodes, invalid package raise StartException(str(e)) # handle diferent result types str or array of string import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise nm.StartException(' '.join([type, 'in package [', package, '] not found!'])) if len(cmd) > 1: # Open selection for executables try: from PySide import QtGui item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', type, 'in', package]), 'Select an executable', cmd, 0, False) if result: #open the selected screen cmd_type = item else: return except: raise nm.StartException('Multiple executables with same name in package found!') else: cmd_type = cmd[0] cmd_str = str(' '.join([nm.screen().getSceenCmd(fullname), cmd_type, ' '.join(args2)])) rospy.loginfo("Run without config: %s", cmd_str) ps = None if not masteruri is None: cls._prepareROSMaster(masteruri) new_env=dict(os.environ) new_env['ROS_MASTER_URI'] = masteruri ps = subprocess.Popen(shlex.split(cmd_str), env=new_env) else: ps = subprocess.Popen(shlex.split(cmd_str)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() else: # run on a remote machine startcmd = [nm.STARTER_SCRIPT, '--package', str(package), '--node_type', str(type), '--node_name', str(fullname)] startcmd[len(startcmd):] = args2 if not masteruri is None: startcmd.append('--masteruri') startcmd.append(masteruri) rospy.loginfo("Run remote on %s: %s", host, ' '.join(startcmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", name, error) from PySide import QtGui QtGui.QMessageBox.warning(None, 'Error while remote start %s'%str(name), str(''.join(['The host "', host, '" reports:\n', error])), QtGui.QMessageBox.Ok) output = stdout.read() if output: rospy.logdebug("STDOUT while start '%s': %s", name, output) else: if stderr: rospy.logwarn("ERROR while start '%s': %s", name, stderr) from PySide import QtGui QtGui.QMessageBox.warning(None, 'Error while remote start %s'%str(name), str(''.join(['The host "', host, '" reports:\n', stderr])), QtGui.QMessageBox.Ok)
def runNode(cls, node, launch_config, force2host=None, masteruri=None, auto_pw_request=False, user=None, pw=None): ''' Start the node with given name from the given configuration. @param node: the name of the node (with name space) @type node: C{str} @param launch_config: the configuration containing the node @type launch_config: L{LaunchConfig} @param force2host: start the node on given host. @type force2host: L{str} @param masteruri: force the masteruri. @type masteruri: L{str} @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 = launch_config.getNode(node) if n is None: raise StartException(''.join(["Node '", node, "' not found!"])) env = list(n.env_args) prefix = n.launch_prefix if not n.launch_prefix is None else '' if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1: rospy.loginfo("SCREEN prefix removed before start!") prefix = '' args = [ ''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name]) ] if not (n.cwd is None): args.append(''.join(['__cwd:=', n.cwd])) # add remaps for remap in n.remap_args: args.append(''.join([remap[0], ':=', remap[1]])) # get host of the node host = launch_config.hostname env_loader = '' if n.machine_name: machine = launch_config.Roscfg.machines[n.machine_name] host = machine.address #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 not force2host is None: host = force2host if masteruri is None: masteruri = nm.nameres().masteruri(n.machine_name) # set the ROS_MASTER_URI if masteruri is None: masteruri = nm.masteruri_from_ros() env.append(('ROS_MASTER_URI', masteruri)) abs_paths = list() # tuples of (parameter name, old value, new value) not_found_packages = list() # package names # set the global parameter if not masteruri is None and not masteruri in launch_config.global_param_done: global_node_names = cls.getGlobalParams(launch_config.Roscfg) rospy.loginfo("Register global parameter:\n%s", '\n'.join(global_node_names)) abs_paths[len(abs_paths):], not_found_packages[ len(not_found_packages):] = cls._load_parameters( masteruri, global_node_names, []) launch_config.global_param_done.append(masteruri) # add params if not masteruri is None: nodens = ''.join([n.namespace, n.name, '/']) params = dict() for param, value in launch_config.Roscfg.params.items(): if param.startswith(nodens): params[param] = value clear_params = [] for cparam in launch_config.Roscfg.clear_params: if cparam.startswith(nodens): clear_params.append(param) rospy.loginfo("Register parameter:\n%s", '\n'.join(params)) abs_paths[len(abs_paths):], not_found_packages[ len(not_found_packages):] = cls._load_parameters( masteruri, params, clear_params) #'print "RUN prepared", node, time.time() if nm.is_local(host): nm.screen().testScreen() try: cmd = roslib.packages.find_node(n.package, n.type) except (Exception, roslib.packages.ROSPkgException) as e: # multiple nodes, invalid package raise StartException(''.join(["Can't find resource: ", str(e)])) # handle diferent result types str or array of string import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise StartException(' '.join([ n.type, 'in package [', n.package, '] not found!\n\nThe package was created?\nIs the binary executable?\n' ])) if len(cmd) > 1: # Open selection for executables try: from PySide import QtGui item, result = QtGui.QInputDialog.getItem( None, ' '.join( ['Multiple executables', n.type, 'in', 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: cmd_type = cmd[0] # determine the current working path, Default: the package of the node cwd = nm.get_ros_home() if not (n.cwd is None): if n.cwd == 'ROS_HOME': cwd = nm.get_ros_home() elif n.cwd == 'node': cwd = os.path.dirname(cmd_type) # else: # cwd = LaunchConfig.packageName(os.path.dirname(cmd_type)) cls._prepareROSMaster(masteruri) node_cmd = [ nm.RESPAWN_SCRIPT if n.respawn else '', prefix, cmd_type ] cmd_args = [nm.screen().getSceenCmd(node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(str(n.args)) cmd_args[len(cmd_args):] = args rospy.loginfo("RUN: %s", ' '.join(cmd_args)) if not masteruri is None: new_env = dict(os.environ) new_env['ROS_MASTER_URI'] = masteruri ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))), cwd=cwd, env=new_env) else: ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))), cwd=cwd) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() else: #'print "RUN REMOTE", node, time.time() # start remote if launch_config.PackageName is None: raise StartException(''.join( ["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: env_command = "env " + ' '.join( ["%s=%s" % (k, v) for (k, v) in env]) startcmd = [ env_command, nm.STARTER_SCRIPT, '--package', str(n.package), '--node_type', str(n.type), '--node_name', str(node), '--node_respawn true' if n.respawn else '' ] if not masteruri is None: startcmd.append('--masteruri') startcmd.append(masteruri) if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] #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) 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, str(' '.join(startcmd))) #'print "RUN CALL", node, time.time() output, error, ok = nm.ssh().ssh_exec(host, startcmd, user, pw, auto_pw_request) #'print "RUN CALLOK", node, time.time() except nm.AuthenticationRequest as e: raise nm.InteractionNeededError( e, cls.runNode, (node, launch_config, force2host, masteruri, auto_pw_request)) if ok: if error: rospy.logwarn("ERROR while start '%s': %s", node, error) raise StartException( str(''.join( ['The host "', host, '" reports:\n', error]))) if output: rospy.loginfo("STDOUT while start '%s': %s", node, output) # inform about absolute paths in parameter value if len(abs_paths) > 0: rospy.loginfo( "Absolute paths found while start:\n%s", str('\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( str('\n'.join([ 'Some absolute paths are not renamed because following packages are not found on remote host:', packages ])))
def runNode(cls, node, launch_config): ''' Start the node with given name from the given configuration. @param node: the name of the node (with name space) @type node: C{str} @param launch_config: the configuration containing the node @type launch_config: L{LaunchConfig} @raise StartException: if the screen is not available on host. @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' n = launch_config.getNode(node) if n is None: raise StartException(''.join(["Node '", node, "' not found!"])) env = list(n.env_args) prefix = n.launch_prefix if not n.launch_prefix is None else '' # thus the parameters while the transfer are not separated if prefix: prefix = ''.join(['"', prefix, '"']) args = [''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name])] if not (n.cwd is None): args.append(''.join(['__cwd:=', n.cwd])) # add remaps for remap in n.remap_args: args.append(''.join([remap[0], ':=', remap[1]])) # get host of the node host = launch_config.hostname env_loader = '' if n.machine_name: machine = launch_config.Roscfg.machines[n.machine_name] host = machine.address #TODO: env-loader support? # if hasattr(machine, "env_loader") and machine.env_loader: # env_loader = machine.env_loader masteruri = nm.nameres().getUri(host=host) # set the ROS_MASTER_URI if masteruri is None: env.append(('ROS_MASTER_URI', nm.masteruri_from_ros())) # set the global parameter if not masteruri is None and not masteruri in launch_config.global_param_done: global_node_names = cls.getGlobalParams(launch_config.Roscfg) rospy.loginfo("Register global parameter:\n%s", '\n'.join(global_node_names)) cls._load_parameters(masteruri, global_node_names, []) launch_config.global_param_done.append(masteruri) # add params if not masteruri is None: nodens = ''.join([n.namespace, n.name, '/']) params = dict() for param, value in launch_config.Roscfg.params.items(): if param.startswith(nodens): params[param] = value clear_params = [] for cparam in launch_config.Roscfg.clear_params: if cparam.startswith(nodens): clear_params.append(param) rospy.loginfo("Register parameter:\n%s", '\n'.join(params)) cls._load_parameters(masteruri, params, clear_params) if nm.is_local(host): nm.screen().testScreen() try: cmd = roslib.packages.find_node(n.package, n.type) except (Exception, roslib.packages.ROSPkgException) as e: # multiple nodes, invalid package raise StartException(''.join(["Can't find resource: ", str(e)])) # handle diferent result types str or array of string import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise nm.StartException(' '.join([n.type, 'in package [', n.package, '] not found!\n\nThe package was created?\nIs the binary executable?\n'])) if len(cmd) > 1: # Open selection for executables try: from PySide import QtGui item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', n.type, 'in', n.package]), 'Select an executable', cmd, 0, False) if result: #open the selected screen cmd_type = item else: return except: raise nm.StartException('Multiple executables with same name in package found!') else: cmd_type = cmd[0] node_cmd = [prefix, cmd_type] cmd_args = [nm.screen().getSceenCmd(node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(n.args) cmd_args[len(cmd_args):] = args rospy.loginfo("RUN: %s", ' '.join(cmd_args)) subprocess.Popen(shlex.split(str(' '.join(cmd_args)))) else: # start remote if launch_config.PackageName is None: raise StartException(''.join(["Can't run remote without a valid package name!"])) # setup environment env_command = '' if env_loader: rospy.logwarn("env_loader in machine tag currently not supported") raise nm.StartException("env_loader in machine tag currently not supported") if env: env_command = "env "+' '.join(["%s=%s"%(k,v) for (k, v) in env]) startcmd = [env_command, nm.STARTER_SCRIPT, '--package', str(n.package), '--node_type', str(n.type), '--node_name', str(node)] if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] startcmd[len(startcmd):] = n.args startcmd[len(startcmd):] = args rospy.loginfo("Run remote: %s", ' '.join(startcmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() # stderr.close() # stdout.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", node, error) raise nm.StartException(str(''.join(['The host "', host, '" reports:\n', error]))) output = stdout.read() if output: rospy.logdebug("STDOUT while start '%s': %s", node, output)
def runNodeWithoutConfig(cls, host, package, binary, name, args=[], masteruri=None, auto_pw_request=False, user=None, pw=None): ''' Start a node with using a launch configuration. @param host: the host or ip to run the node @type host: C{str} @param package: the ROS package containing the binary @type package: C{str} @param binary: the binary of the node to execute @type binary: C{str} @param name: the ROS name of the node (with name space) @type name: C{str} @param args: the list with arguments passed to the binary @type args: C{[str, ...]} @param auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread @type auto_pw_request: bool @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' # create the name with namespace args2 = list(args) fullname = roslib.names.ns_join(roslib.names.SEP, name) namespace = '' for a in args: if a.startswith('__ns:='): namespace = a.replace('__ns:=', '') fullname = roslib.names.ns_join(namespace, name) args2.append(''.join(['__name:=', name])) # run on local host if nm.is_local(host): try: cmd = roslib.packages.find_node(package, binary) except roslib.packages.ROSPkgException as e: # multiple nodes, invalid package raise StartException(str(e)) # handle different result types str or array of string # import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise StartException(' '.join( [binary, 'in package [', package, '] not found!'])) if len(cmd) > 1: # Open selection for executables # try: # from python_qt_binding import QtGui # item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', type, 'in', package]), # 'Select an executable', # cmd, 0, False) # if result: # #open the selected screen # cmd_type = item # else: # return # except: err = [ ''.join([ 'Multiple executables with same name in package [', package, '] found:' ]) ] err.extend(cmd) raise StartException('\n'.join(err)) else: cmd_type = cmd[0] cmd_str = str(' '.join( [nm.screen().getSceenCmd(fullname), cmd_type, ' '.join(args2)])) rospy.loginfo("Run without config: %s", cmd_str) ps = None new_env = dict(os.environ) if namespace: new_env['ROS_NAMESPACE'] = namespace if not masteruri is None: cls._prepareROSMaster(masteruri) new_env['ROS_MASTER_URI'] = masteruri SupervisedPopen(shlex.split(cmd_str), env=new_env, id="Run without config", description="Run without config [%s]%s" % (str(package), str(binary))) else: # run on a remote machine startcmd = [ nm.settings().start_remote_script, '--package', str(package), '--node_type', str(binary), '--node_name', str(fullname) ] startcmd[len(startcmd):] = args2 if not masteruri is None: startcmd.append('--masteruri') startcmd.append(masteruri) rospy.loginfo("Run remote on %s: %s", host, ' '.join(startcmd)) try: _, stdout, stderr, ok = nm.ssh().ssh_exec(host, startcmd, user, pw, auto_pw_request, close_stdin=True) if ok: output = stdout.read() error = stderr.read() stdout.close() stderr.close() if error: rospy.logwarn("ERROR while start '%s': %s", name, error) raise StartException(''.join( ['The host "', host, '" reports:\n', error])) # from python_qt_binding import QtGui # QtGui.QMessageBox.warning(None, 'Error while remote start %s'%str(name), # str(''.join(['The host "', host, '" reports:\n', error])), # QtGui.QMessageBox.Ok) if output: rospy.logdebug("STDOUT while start '%s': %s", name, output) else: if error: rospy.logwarn("ERROR while start '%s': %s", name, error) raise StartException(''.join( ['The host "', host, '" reports:\n', error])) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError( e, cls.runNodeWithoutConfig, (host, package, binary, name, args, masteruri, auto_pw_request))
def runNodeWithoutConfig(cls, host, package, type, name, args=[], masteruri=None, auto_pw_request=True, user=None, pw=None): ''' Start a node with using a launch configuration. @param host: the host or ip to run the node @type host: C{str} @param package: the ROS package containing the binary @type package: C{str} @param type: the binary of the node to execute @type type: C{str} @param name: the ROS name of the node (with name space) @type name: C{str} @param args: the list with arguments passed to the binary @type args: C{[str, ...]} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' # create the name with namespace args2 = list(args) fullname = roslib.names.ns_join(roslib.names.SEP, name) for a in args: if a.startswith('__ns:='): fullname = roslib.names.ns_join(a.replace('__ns:=', ''), name) args2.append(''.join(['__name:=', name])) # run on local host if nm.is_local(host): try: cmd = roslib.packages.find_node(package, type) except roslib.packages.ROSPkgException as e: # multiple nodes, invalid package raise StartException(str(e)) # handle different result types str or array of string import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise StartException(' '.join( [type, 'in package [', package, '] not found!'])) if len(cmd) > 1: # Open selection for executables # try: # from PySide import QtGui # item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', type, 'in', package]), # 'Select an executable', # cmd, 0, False) # if result: # #open the selected screen # cmd_type = item # else: # return # except: err = [ ''.join([ 'Multiple executables with same name in package [', package, '] found:' ]) ] err.extend(cmd) raise StartException('\n'.join(err)) else: cmd_type = cmd[0] cmd_str = str(' '.join( [nm.screen().getSceenCmd(fullname), cmd_type, ' '.join(args2)])) rospy.loginfo("Run without config: %s", cmd_str) ps = None if not masteruri is None: cls._prepareROSMaster(masteruri) new_env = dict(os.environ) new_env['ROS_MASTER_URI'] = masteruri ps = subprocess.Popen(shlex.split(cmd_str), env=new_env) else: ps = subprocess.Popen(shlex.split(cmd_str)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() else: # run on a remote machine startcmd = [ nm.STARTER_SCRIPT, '--package', str(package), '--node_type', str(type), '--node_name', str(fullname) ] startcmd[len(startcmd):] = args2 if not masteruri is None: startcmd.append('--masteruri') startcmd.append(masteruri) rospy.loginfo("Run remote on %s: %s", host, ' '.join(startcmd)) try: output, error, ok = nm.ssh().ssh_exec(host, startcmd, user, pw, auto_pw_request) if ok: if error: rospy.logwarn("ERROR while start '%s': %s", name, error) raise StartException(''.join( ['The host "', host, '" reports:\n', error])) # from PySide import QtGui # QtGui.QMessageBox.warning(None, 'Error while remote start %s'%str(name), # str(''.join(['The host "', host, '" reports:\n', error])), # QtGui.QMessageBox.Ok) if output: rospy.logdebug("STDOUT while start '%s': %s", name, output) else: if error: rospy.logwarn("ERROR while start '%s': %s", name, error) raise StartException(''.join( ['The host "', host, '" reports:\n', error])) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError( e, cls.runNodeWithoutConfig, (host, package, type, name, args, masteruri, auto_pw_request))
def runNode(cls, node, launch_config, force2host=None, masteruri=None, auto_pw_request=False, user=None, pw=None, item=None): ''' Start the node with given name from the given configuration. @param node: the name of the node (with name space) @type node: C{str} @param launch_config: the configuration containing the node @type launch_config: L{LaunchConfig} @param force2host: start the node on given host. @type force2host: L{str} @param masteruri: force the masteruri. @type masteruri: L{str} @param auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread @type auto_pw_request: bool @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 = launch_config.getNode(node) if n is None: raise StartException(''.join(["Node '", node, "' not found!"])) env = list(n.env_args) if n.respawn: # set the respawn environment variables respawn_params = cls._get_respawn_params( rospy.names.ns_join(n.namespace, n.name), launch_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 not n.launch_prefix is None else '' if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1: rospy.loginfo("SCREEN prefix removed before start!") prefix = '' args = [ ''.join(['__ns:=', n.namespace.rstrip(rospy.names.SEP)]), ''.join(['__name:=', n.name]) ] if not (n.cwd is None): args.append(''.join(['__cwd:=', n.cwd])) # add remaps for remap in n.remap_args: args.append(''.join([remap[0], ':=', remap[1]])) # get host of the node host = launch_config.hostname env_loader = '' if n.machine_name: machine = launch_config.Roscfg.machines[n.machine_name] if not machine.address in ['localhost', '127.0.0.1']: host = machine.address if masteruri is None: 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 not force2host is None: host = force2host # set the ROS_MASTER_URI if masteruri is None: masteruri = masteruri_from_ros() env.append(('ROS_MASTER_URI', masteruri)) abs_paths = list() # tuples of (parameter name, old value, new value) not_found_packages = list() # package names # set the global parameter if not masteruri is None and not masteruri in launch_config.global_param_done: global_node_names = cls.getGlobalParams(launch_config.Roscfg) rospy.loginfo( "Register global parameter:\n %s", '\n '.join( "%s%s" % (str(v)[:80], '...' if len(str(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( masteruri, global_node_names, [], user, pw, auto_pw_request) launch_config.global_param_done.append(masteruri) # add params if not masteruri is None: nodens = ''.join([n.namespace, n.name, rospy.names.SEP]) params = dict() for param, value in launch_config.Roscfg.params.items(): if param.startswith(nodens): params[param] = value clear_params = [] for cparam in launch_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" % (str(v)[:80], '...' if len(str(v)) > 80 else '') for v in params.values())) abs_paths[len(abs_paths):], not_found_packages[ len(not_found_packages):] = cls._load_parameters( masteruri, params, clear_params, user, pw, auto_pw_request) #'print "RUN prepared", node, time.time() if nm.is_local(host): nm.screen().testScreen() if item: cmd_type = item else: try: cmd = roslib.packages.find_node(n.package, n.type) except (Exception, roslib.packages.ROSPkgException) as e: # multiple nodes, invalid package raise StartException(''.join( ["Can't find resource: ", str(e)])) # 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(' '.join([ n.type, 'in package [', n.package, '] not found!\n\nThe package was created?\nIs the binary executable?\n' ])) if len(cmd) > 1: if auto_pw_request: # Open selection for executables, only if the method is called from the main GUI thread try: from python_qt_binding import QtGui item, result = QtGui.QInputDialog.getItem( None, ' '.join([ 'Multiple executables', n.type, 'in', 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, (node, launch_config, force2host, masteruri, auto_pw_request, user, pw)) 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(masteruri) node_cmd = [ nm.settings().respawn_script if n.respawn else '', prefix, cmd_type ] cmd_args = [nm.screen().getSceenCmd(node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(str(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'] = masteruri # add the namespace environment parameter to handle some cases, e.g. rqt_cpp plugins if n.namespace: new_env['ROS_NAMESPACE'] = n.namespace for k, v in env: new_env[k] = v SupervisedPopen(shlex.split(str(' '.join(cmd_args))), cwd=cwd, env=new_env, id="Run node", description="Run node [%s]%s" % (str(n.package), str(n.type))) else: #'print "RUN REMOTE", node, time.time() # start remote if launch_config.PackageName is None: raise StartException(''.join( ["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, user, pw, 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, (node, launch_config, force2host, masteruri, auto_pw_request)) startcmd = [ env_command, nm.settings().start_remote_script, '--package', str(n.package), '--node_type', str(n.type), '--node_name', str(node), '--node_respawn true' if n.respawn else '' ] if not masteruri is None: startcmd.append('--masteruri') startcmd.append(masteruri) if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] #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, user, pw, 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, str(' '.join(startcmd))) #'print "RUN CALL", node, time.time() _, stdout, stderr, ok = nm.ssh().ssh_exec(host, startcmd, user, pw, 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, (node, launch_config, force2host, masteruri, auto_pw_request)) if ok: if error: rospy.logwarn("ERROR while start '%s': %s", node, error) raise StartException( str(''.join( ['The host "', host, '" reports:\n', error]))) if output: rospy.loginfo("STDOUT while start '%s': %s", node, output) # inform about absolute paths in parameter value if len(abs_paths) > 0: rospy.loginfo( "Absolute paths found while start:\n%s", str('\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( str('\n'.join([ 'Some absolute paths are not renamed because following packages are not found on remote host:', packages ])))
def runNodeWithoutConfig(cls, host, package, type, name, args=[]): ''' Start a node with using a launch configuration. @param host: the host or ip to run the node @type host: C{str} @param package: the ROS package containing the binary @type package: C{str} @param type: the binary of the node to execute @type type: C{str} @param name: the ROS name of the node (with name space) @type name: C{str} @param args: the list with arguments passed to the binary @type args: C{[str, ...]} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' # create the name with namespace fullname = ''.join(['/', name]) for a in args: if a.startswith('__ns:='): fullname = ''.join( ['/', a.replace('__ns:=', '').strip('/ '), fullname]) fullname = fullname.replace('//', '/') args2 = list(args) args2.append(''.join(['__name:=', name])) # run on local host if nm.is_local(host): try: cmd = roslib.packages.find_node(package, type) except roslib.packages.ROSPkgException as e: # multiple nodes, invalid package raise StartException(str(e)) # handle diferent result types str or array of string import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise nm.StartException(' '.join( [type, 'in package [', package, '] not found!'])) if len(cmd) > 1: # Open selection for executables try: from PySide import QtGui item, result = QtGui.QInputDialog.getItem( None, ' '.join(['Multiple executables', type, 'in', package]), 'Select an executable', cmd, 0, False) if result: #open the selected screen cmd_type = item else: return except: raise nm.StartException( 'Multiple executables with same name in package found!' ) else: cmd_type = cmd[0] cmd_str = str(' '.join( [nm.screen().getSceenCmd(fullname), cmd_type, ' '.join(args2)])) rospy.loginfo("Run without config: %s", cmd_str) subprocess.Popen(shlex.split(cmd_str)) else: # run on a remote machine startcmd = [ nm.STARTER_SCRIPT, '--package', str(package), '--node_type', str(type), '--node_name', str(fullname) ] startcmd[len(startcmd):] = args2 rospy.loginfo("Run remote: %s", ' '.join(startcmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", name, error) from PySide import QtGui QtGui.QMessageBox.warning( None, 'Error while remote start %s' % str(name), str(''.join( ['The host "', host, '" reports:\n', error])), QtGui.QMessageBox.Ok) output = stdout.read() if output: rospy.logdebug("STDOUT while start '%s': %s", name, output)
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])))
def runNode(cls, node, launch_config): ''' Start the node with given name from the given configuration. @param node: the name of the node (with name space) @type node: C{str} @param launch_config: the configuration containing the node @type launch_config: L{LaunchConfig} @raise StartException: if the screen is not available on host. @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' n = launch_config.getNode(node) if n is None: raise StartException(''.join(["Node '", node, "' not found!"])) env = list(n.env_args) prefix = n.launch_prefix if not n.launch_prefix is None else '' # thus the parameters while the transfer are not separated if prefix: prefix = ''.join(['"', prefix, '"']) args = [ ''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name]) ] if not (n.cwd is None): args.append(''.join(['__cwd:=', n.cwd])) # add remaps for remap in n.remap_args: args.append(''.join([remap[0], ':=', remap[1]])) # get host of the node host = launch_config.hostname env_loader = '' if n.machine_name: machine = launch_config.Roscfg.machines[n.machine_name] host = machine.address #TODO: env-loader support? # if hasattr(machine, "env_loader") and machine.env_loader: # env_loader = machine.env_loader masteruri = nm.nameres().getUri(host=host) # set the ROS_MASTER_URI if masteruri is None: env.append(('ROS_MASTER_URI', nm.masteruri_from_ros())) # set the global parameter if not masteruri is None and not masteruri in launch_config.global_param_done: global_node_names = cls.getGlobalParams(launch_config.Roscfg) rospy.loginfo("Register global parameter:\n%s", '\n'.join(global_node_names)) cls._load_parameters(masteruri, global_node_names, []) launch_config.global_param_done.append(masteruri) # add params if not masteruri is None: nodens = ''.join([n.namespace, n.name, '/']) params = dict() for param, value in launch_config.Roscfg.params.items(): if param.startswith(nodens): params[param] = value clear_params = [] for cparam in launch_config.Roscfg.clear_params: if cparam.startswith(nodens): clear_params.append(param) rospy.loginfo("Register parameter:\n%s", '\n'.join(params)) cls._load_parameters(masteruri, params, clear_params) if nm.is_local(host): nm.screen().testScreen() try: cmd = roslib.packages.find_node(n.package, n.type) except (Exception, roslib.packages.ROSPkgException) as e: # multiple nodes, invalid package raise StartException(''.join(["Can't find resource: ", str(e)])) # handle diferent result types str or array of string import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise nm.StartException(' '.join([ n.type, 'in package [', n.package, '] not found!\n\nThe package was created?\nIs the binary executable?\n' ])) if len(cmd) > 1: # Open selection for executables try: from PySide import QtGui item, result = QtGui.QInputDialog.getItem( None, ' '.join( ['Multiple executables', n.type, 'in', n.package]), 'Select an executable', cmd, 0, False) if result: #open the selected screen cmd_type = item else: return except: raise nm.StartException( 'Multiple executables with same name in package found!' ) else: cmd_type = cmd[0] node_cmd = [prefix, cmd_type] cmd_args = [nm.screen().getSceenCmd(node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(n.args) cmd_args[len(cmd_args):] = args rospy.loginfo("RUN: %s", ' '.join(cmd_args)) subprocess.Popen(shlex.split(str(' '.join(cmd_args)))) else: # start remote if launch_config.PackageName is None: raise StartException(''.join( ["Can't run remote without a valid package name!"])) # setup environment env_command = '' if env_loader: rospy.logwarn( "env_loader in machine tag currently not supported") raise nm.StartException( "env_loader in machine tag currently not supported") if env: env_command = "env " + ' '.join( ["%s=%s" % (k, v) for (k, v) in env]) startcmd = [ env_command, nm.STARTER_SCRIPT, '--package', str(n.package), '--node_type', str(n.type), '--node_name', str(node) ] if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] startcmd[len(startcmd):] = n.args startcmd[len(startcmd):] = args rospy.loginfo("Run remote: %s", ' '.join(startcmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() # stderr.close() # stdout.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", node, error) raise nm.StartException( str(''.join( ['The host "', host, '" reports:\n', error]))) output = stdout.read() if output: rospy.logdebug("STDOUT while start '%s': %s", node, output)