Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
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)
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
  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)
Exemplo n.º 8
0
  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 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))
Exemplo n.º 11
0
    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])))
Exemplo n.º 12
0
    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))