def main(name): ''' Start the NodeManager or EchoDialog. :param name: the name propagated to the rospy.init_node() :type name: str ''' try: from python_qt_binding.QtGui import QApplication except: try: from python_qt_binding.QtWidgets import QApplication except: print >> sys.stderr, "please install 'python_qt_binding' package!!" sys.exit(-1) init_settings() detect_version() parser = init_arg_parser() args = rospy.myargv(argv=sys.argv) parsed_args = parser.parse_args(args[1:]) if parsed_args.muri: masteruri = parsed_args.muri[0] hostname = NameResolution.get_ros_hostname(masteruri) os.environ['ROS_MASTER_URI'] = masteruri if hostname: os.environ['ROS_HOSTNAME'] = hostname masteruri = settings().masteruri() # Initialize Qt global _QAPP _QAPP = QApplication(sys.argv) # decide to show main or echo dialog global _MAIN_FORM try: if parsed_args.echo: _MAIN_FORM = init_echo_dialog(name, masteruri, parsed_args.echo[0], parsed_args.echo[1], parsed_args.hz, parsed_args.ssh) else: _MAIN_FORM = init_main_window(name, masteruri, parsed_args.file) except Exception as err: sys.exit("%s" % err) exit_code = 0 # resize and show the qt window if not rospy.is_shutdown(): # change path for access to the images of descriptions os.chdir(settings().PACKAGE_DIR) # _MAIN_FORM.resize(1024, 720) screen_size = QApplication.desktop().availableGeometry() if (_MAIN_FORM.size().width() >= screen_size.width() or _MAIN_FORM.size().height() >= screen_size.height() - 24): _MAIN_FORM.showMaximized() else: _MAIN_FORM.show() exit_code = -1 rospy.on_shutdown(finish) exit_code = _QAPP.exec_() return exit_code
def main(name): ''' Start the NodeManager or EchoDialog. :param name: the name propagated to the rospy.init_node() :type name: str ''' try: from python_qt_binding.QtGui import QApplication except: try: from python_qt_binding.QtWidgets import QApplication except: print >> sys.stderr, "please install 'python_qt_binding' package!!" sys.exit(-1) init_settings() parser = init_arg_parser() args = rospy.myargv(argv=sys.argv) parsed_args = parser.parse_args(args[1:]) if parsed_args.muri: masteruri = parsed_args.muri[0] hostname = NameResolution.get_ros_hostname(masteruri) os.environ['ROS_MASTER_URI'] = masteruri if hostname: os.environ['ROS_HOSTNAME'] = hostname masteruri = settings().masteruri() # Initialize Qt global _QAPP _QAPP = QApplication(sys.argv) # decide to show main or echo dialog global _MAIN_FORM try: if parsed_args.echo: _MAIN_FORM = init_echo_dialog(name, masteruri, parsed_args.echo[0], parsed_args.echo[1], parsed_args.hz, parsed_args.ssh) else: _MAIN_FORM = init_main_window(name, masteruri, parsed_args.file) except Exception as err: sys.exit("%s" % err) exit_code = 0 # resize and show the qt window if not rospy.is_shutdown(): # change path for access to the images of descriptions os.chdir(settings().PACKAGE_DIR) # _MAIN_FORM.resize(1024, 720) screen_size = QApplication.desktop().availableGeometry() if (_MAIN_FORM.size().width() >= screen_size.width() or _MAIN_FORM.size().height() >= screen_size.height() - 24): _MAIN_FORM.showMaximized() else: _MAIN_FORM.show() exit_code = -1 rospy.on_shutdown(finish) exit_code = _QAPP.exec_() return exit_code
def get_ros_hostname(url): ''' Returns the host name used in a url, if it is a name. If it is an IP an empty string will be returned. @return: host or '' if url is an IP or invalid @rtype: C{str} ''' return NameResolution.get_ros_hostname(url)
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 _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: # socket.setdefaulttimeout(None) # import traceback # print traceback.format_exc(3) # run a roscore from urlparse import urlparse master_host = urlparse(masteruri).hostname if nm.is_local(master_host, True): master_port = urlparse(masteruri).port 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) try: SupervisedPopen(shlex.split(cmd_args), env=new_env, object_id="ROSCORE", description="Start roscore") # 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 except: time.sleep(1) count += 1 if count >= 11: raise StartException('Cannot connect to the ROS-Master: '+ str(masteruri)) except Exception as e: import sys print >> sys.stderr, e raise else: raise Exception("ROS master '%s' is not reachable"%masteruri) finally: socket.setdefaulttimeout(None)
def _prepareROSMaster(cls, masteruri): if not masteruri: masteruri = masteruri_from_ros() #start roscore, if needed try: if not os.path.isdir(ScreenHandler.LOG_PATH): os.makedirs(ScreenHandler.LOG_PATH) socket.setdefaulttimeout(3) master = xmlrpclib.ServerProxy(masteruri) master.getUri(rospy.get_name()) except: # socket.setdefaulttimeout(None) # import traceback # print traceback.format_exc(1) # run a roscore from urlparse import urlparse master_host = urlparse(masteruri).hostname if cls.is_local(master_host, True): print "Start ROS-Master with", masteruri, "..." master_port = urlparse(masteruri).port 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'%(ScreenHandler.getSceenCmd('/roscore--%d'%master_port), master_port) print " %s"%cmd_args try: subprocess.Popen(shlex.split(cmd_args), env=new_env) # wait for roscore to avoid connection problems while init_node result = -1 count = 1 while result == -1 and count < 11: try: print " retry connect to ROS master", count, '/', 10 master = xmlrpclib.ServerProxy(masteruri) result, _, _ = master.getUri(rospy.get_name())#_:=uri, msg except: time.sleep(1) count += 1 if count >= 11: raise StartException('Cannot connect to the ROS-Master: '+ str(masteruri)) except Exception as e: import sys print >> sys.stderr, e raise else: raise Exception("ROS master '%s' is not reachable"%masteruri) finally: socket.setdefaulttimeout(None)
def init_globals(masteruri): ''' :return: True if the masteruri referred to localhost :rtype: bool ''' # initialize the global handler global _SSH_HANDLER global _SCREEN_HANDLER global _START_HANDLER global _NAME_RESOLUTION global _HISTORY global _FILE_WATCHER global _FILE_WATCHER_PARAM _SSH_HANDLER = SSHhandler() _SCREEN_HANDLER = ScreenHandler() _START_HANDLER = StartHandler() _NAME_RESOLUTION = NameResolution() _HISTORY = History() _FILE_WATCHER = FileWatcher() _FILE_WATCHER_PARAM = FileWatcher() # test where the roscore is running (local or remote) __is_local('localhost') ## fill cache return __is_local(_NAME_RESOLUTION.getHostname(masteruri)) # # fill cache
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 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, 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" % (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(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" % (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(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(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'] = 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(str(' '.join(cmd_args))), cwd=cwd, env=new_env, object_id="Run node", description="Run node " "[%s]%s" % (str(n.package), str(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', str(n.package), '--node_type', str(n.type), '--node_name', str(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, str(' '.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(str(''.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", 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, 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(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('%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 = str(' '.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" % (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 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])) # 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))