Esempio n. 1
0
    def expand_item(self, path, path_id, clear_cache=False):
        '''
        Returns for the given item and path the file path if this is a file. Otherwise the
        folder will be expanded and None will be returned.

        :param str path: the real path of the item
        :param int path_id: the id of the path
        :param bool clear_cache: clear cache before reload
        :return: path of the launch file or None
        :rtype: str
        :raise Exception: if no path to given item was found
        '''
        if path_id in [PathItem.NOTHING]:
            return None
        has_shift_mod = Qt.ShiftModifier & QApplication.keyboardModifiers()
        if path_id in [
                PathItem.LAUNCH_FILE, PathItem.CFG_FILE, PathItem.PROFILE,
                PathItem.FILE, PathItem.RECENT_FILE, PathItem.LAUNCH_FILE
        ]:
            if not has_shift_mod:
                return path
        root = self.invisibleRootItem()
        while root.rowCount():
            root.removeRow(0)
        self.pyqt_workaround.clear()
        if has_shift_mod:
            if path_id in [
                    PathItem.LAUNCH_FILE, PathItem.CFG_FILE, PathItem.PROFILE,
                    PathItem.FILE, PathItem.RECENT_FILE, PathItem.LAUNCH_FILE
            ]:
                self._current_path = os.path.dirname(path)
            else:
                self._current_path = nmdurl.nmduri()
        else:
            if path_id in [PathItem.ROOT]:
                surl, spath = nmdurl.split(path, with_scheme=True)
                if self._is_root(path) or spath in ['', os.path.sep]:
                    self._current_path = nmdurl.nmduri()
                elif self._is_ros_root(path):
                    self._current_path = surl
                else:
                    dir_path = os.path.dirname(spath)
                    self._current_path = nmdurl.join(surl, dir_path)
            elif self._current_path != path:
                self._current_path = path
        self._add_path(self._current_path, PathItem.ROOT, 0, 0, 'loading...')
        nm.nmd().file.list_path_threaded(self._current_path, clear_cache)
        # TODO: add functionality to go deep automatically
        #         else:
        #             key_mod = QApplication.keyboardModifiers()
        #             onestep = False
        #             if key_mod & Qt.ControlModifier:
        #                 onestep = True
        #             root_path, items = self._moveDown(path, onestep)
        #        self._setNewList((root_path, items))
        return None
Esempio n. 2
0
 def get_packages(self, url=''):
     if url:
         grpc_url = nmdurl.nmduri(url)
         if grpc_url in self._cache_packages:
             return self._cache_packages[grpc_url]
         return {}
     return self._cache_packages
Esempio n. 3
0
 def __init__(self, parent=None, progress_queue=None, viewobj=None):
     '''
     Creates a new list model.
     '''
     QStandardItemModel.__init__(self, parent)
     self.viewobj = viewobj
     self.setColumnCount(len(LaunchListModel.header))
     self.setHorizontalHeaderLabels(
         [label for label, _width in LaunchListModel.header])
     self.pyqt_workaround = dict(
     )  # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass
     self.items = []
     self._roots = {}
     self._current_path = nmdurl.nmduri()
     self._current_master = masteruri_from_master()
     self._current_master_name = ''
     self.ros_root_paths = {}  # {url: [root pasth(str)]}
     self.ros_root_paths[self._current_path] = [
         os.path.normpath(p)
         for p in os.getenv("ROS_PACKAGE_PATH").split(':')
     ]
     self._progress_queue = progress_queue
     nm.nmd().file.listed_path.connect(self._listed_path)
     nm.nmd().file.packages_available.connect(self._on_new_packages)
     nm.nmd().file.error.connect(self._nmd_error)
Esempio n. 4
0
    def get_profile_file(self):
        '''
        Opens file manager dialog to save to select a new file for node manager profile.

        :return: path to profile file
        :rtype: str
        '''
        # save the profile
        (path, _) = QFileDialog.getSaveFileName(
            self, "New profile file",
            nm.settings().current_dialog_path,
            "node manager profile files (*.nmprofile);;All files (*)"
        )  # _:=filter
        if path:
            if not path.endswith('.nmprofile'):
                path = "%s.nmprofile" % path
            nm.settings().current_dialog_path = os.path.dirname(path)
            try:
                # we need a grpc url for local node manager daemon
                nmd_url = nmdurl.nmduri()
                (pkg, _) = package_name(
                    nmdurl.join(nmd_url, os.path.dirname(path)))  # _:=pkg_path
                if pkg is None:
                    ret = MessageBox.warning(
                        self,
                        "New File Error",
                        'The new file is not in a ROS package',
                        buttons=MessageBox.Ok | MessageBox.Cancel)
                    if ret == MessageBox.Cancel:
                        return None
                return path
            except EnvironmentError as e:
                MessageBox.warning(self, "New File Error",
                                   'Error while create a new file', utf8(e))
        return None
Esempio n. 5
0
 def _add_history(self):
     for hitem in nm.settings().launch_history:
         if not hitem.startswith(os.path.sep):
             hitem_uri, _ = nmdurl.split(hitem, with_scheme=True)
             current_uri = nmdurl.nmduri(self._current_path)
             if nmdurl.equal_uri(hitem_uri, current_uri):
                 self._add_path(hitem, PathItem.RECENT_FILE, 0, 0,
                                os.path.basename(hitem))
Esempio n. 6
0
 def set_current_master(self, masteruri, mastername):
     self._current_master = masteruri.rstrip(os.path.sep)
     self._current_master_name = mastername
     if self._is_root(self._current_path):
         nm.nmd().file.list_path_threaded(self._current_path)
         if nmdurl.equal_uri(self._current_path, masteruri_from_master()):
             self._add_path(nmdurl.nmduri(self._current_master),
                            PathItem.REMOTE_DAEMON, 0, 0,
                            get_hostname(self._current_master_name))
Esempio n. 7
0
 def clear_package_cache(self, url):
     if url:
         grpc_url = nmdurl.nmduri(url)
         try:
             del self._cache_packages[grpc_url]
             rospy.logdebug("cache for packages from '%s' removed",
                            grpc_url)
         except KeyError:
             pass
Esempio n. 8
0
 def run(self):
     '''
     '''
     if self._grpc_url:
         try:
             self._result = nm.nmd().file.get_package_binaries(
                 self._package, nmdurl.nmduri(self._grpc_url))
             if not self._canceled:
                 self.binaries_signal.emit(self._package, self._result)
         except Exception:
             import traceback
             print(traceback.format_exc())
Esempio n. 9
0
 def _listed_path(self, url, path, result):
     if not self.is_current_nmd(url):
         return
     root = self.invisibleRootItem()
     while root.rowCount():
         root.removeRow(0)
     self.pyqt_workaround.clear()
     # test for ROS root paths and add these if it is in ROS_PACKAGE_PATH
     isroot = path in ['', os.path.sep]
     if isroot:
         self.ros_root_paths[url] = []
     # append path items to the list model
     result_list = []
     for path_item in result:
         if isroot and path_item.type in [FileItem.DIR, FileItem.PACKAGE]:
             self.ros_root_paths[url].append(path_item.path)
         item = os.path.normpath(os.path.join(path, path_item.path))
         gpath = nmdurl.join(url, item)
         path_id = PathItem.NOT_FOUND
         if FileItem.FILE == path_item.type:
             _, ext = os.path.splitext(path_item.path)
             if ext in nm.settings(
             ).launch_view_file_ext or path_item.path.find('.launch.') > 0:
                 path_id = PathItem.FILE
         elif FileItem.DIR == path_item.type:
             path_id = PathItem.FOLDER
         elif FileItem.SYMLINK == path_item.type:
             pass
         elif FileItem.PACKAGE == path_item.type:
             path_id = PathItem.PACKAGE
         if path_id != PathItem.NOT_FOUND and not os.path.basename(
                 path_item.path).startswith('.'):
             # TODO: create filter for files
             result_list.append(
                 (gpath, path_id, path_item.mtime, path_item.size,
                  os.path.basename(path_item.path)))
     root_path = nmdurl.join(url, path)
     self._set_new_list(root_path, result_list)
     isroot = self._is_root(self._current_path)
     if isroot and not nmdurl.equal_uri(self._current_master,
                                        masteruri_from_master()):
         self._add_path(nmdurl.nmduri(self._current_master),
                        PathItem.REMOTE_DAEMON, 0, 0,
                        get_hostname(self._current_master_name))
     self.pathlist_handled.emit(root_path)
Esempio n. 10
0
 def on_package_selected(self, package):
     getnew = False
     if self._request_bin_thread is None:
         getnew = True
     else:
         if self._request_bin_thread.pkgname != package:
             self._request_bin_thread.cancel()
             getnew = True
     if self._request_bin_thread is not None and self._request_bin_thread.pkgname == package:
         # use already got data
         self._request_bin_thread.reemit()
     elif getnew:
         self.binary_field.clear()
         if self.packages and package in self.packages:
             self.binary_field.setEnabled(True)
             self._request_bin_thread = RequestBinariesThread(
                 package, nmdurl.nmduri(self.masteruri))
             self._request_bin_thread.binaries_signal.connect(
                 self._on_new_binaries)
             self._request_bin_thread.start()
Esempio n. 11
0
 def _is_root(self, grpc_path):
     return grpc_path == nmdurl.nmduri()
    def runNodeWithoutConfig(cls,
                             host,
                             package,
                             binary,
                             name,
                             args=[],
                             masteruri=None,
                             use_nmd=True,
                             auto_pw_request=False,
                             user=None,
                             pw=None,
                             path=''):
        '''
        Start a node with using a launch configuration.

        :param str hosturi: the host or ip to run the node
        :param str package: the ROS package containing the binary
        :param str binary: the binary of the node to execute
        :param str name: the ROS name of the node (with name space)
        :param args: the list with arguments passed to the binary
        :type args: [str]
        :param bool use_nmd: start the node using node manager daemon
        :param bool auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.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):
            if not use_nmd:
                if path:
                    cmd = [path]
                else:
                    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
                    if isstring(cmd):
                        cmd = [cmd]
                cmd_type = ''
                if cmd is None or len(cmd) == 0:
                    raise StartException('%s in package [%s] not found!' %
                                         (binary, package))
                # compatibility for python scripts installed with catkin_install_python()
                # avoid ask for select a binary
                cmd = cls._remove_src_binary(cmd)
                if len(cmd) > 1:
                    # Open selection for executables
                    err = 'Multiple executables with same name in package [%s] found' % package
                    bsel = nm.BinarySelectionRequest(cmd, err)
                    raise nm.InteractionNeededError(
                        bsel, cls.runNodeWithoutConfig, {
                            'host': host,
                            'package': package,
                            'binary': binary,
                            'name': name,
                            'args': args,
                            'masteruri': masteruri,
                            'use_nmd': use_nmd,
                            'auto_pw_request': auto_pw_request,
                            'user': user,
                            'pw': pw,
                            'path': path
                        })
                else:
                    cmd_type = cmd[0]
            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
                if 'ROS_HOSTNAME' in os.environ:
                    # set ROS_HOSTNAME only if node_manager has also one
                    ros_hostname = nmdhost.get_ros_hostname(masteruri, host)
                    if ros_hostname:
                        new_env['ROS_HOSTNAME'] = ros_hostname
            if use_nmd:
                nm.nmd().launch.start_standalone_node(nmdurl.nmduri(), package,
                                                      binary, name, namespace,
                                                      args, new_env, masteruri,
                                                      host)
            else:
                local_env = dict(os.environ)
                local_env.update(new_env)
                cmd_str = utf8(' '.join([
                    screen.get_cmd(fullname, local_env), cmd_type,
                    ' '.join(args2)
                ]))
                rospy.loginfo("Run without config: %s",
                              fullname if use_nmd else cmd_str)
                SupervisedPopen(shlex.split(cmd_str),
                                env=local_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:
                        if output.find("dn't") != -1:
                            rospy.logwarn("Warning while start '%s': %s", name,
                                          output)
                        else:
                            rospy.loginfo("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': host,
                        'package': package,
                        'binary': binary,
                        'name': name,
                        'args': args,
                        'masteruri': masteruri,
                        'use_nmd': use_nmd,
                        'auto_pw_request': auto_pw_request,
                        'user': user,
                        'pw': pw,
                        'path': path
                    })
Esempio n. 13
0
    def __init__(self, masteruri, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None
        self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri
        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
        self.binary_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''
        self._request_bin_thread = None

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
        # fill the input fields
        self.packages = {
            name: path
            for path, name in nm.nmd().file.get_packages(
                nmdurl.nmduri(masteruri)).items()
        }
        packages = self.packages.keys()
        packages.sort()
        self.package_field.clear()
        self.package_field.clearEditText()
        self.package_field.addItems(packages)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(
                self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)
Esempio n. 14
0
    def on_load_profile_file(self, grpc_url):
        '''
        Load the profile file.

        :param str grpc_url: the path of the profile file.
        '''
        _url, path = nmdurl.split(grpc_url)
        rospy.loginfo("Load profile %s" % path)
        self.progressBar.setValue(0)
        self.setVisible(True)
        self.setWindowTitle("%s profile started" %
                            os.path.basename(path).rstrip('.nmprofile'))
        hasstart = False
        if path:
            try:
                with open(path, 'r') as f:
                    content = ruamel.yaml.load(f.read(),
                                               Loader=ruamel.yaml.Loader)
                    if not isinstance(content, dict):
                        raise Exception("Mailformed profile: %s" %
                                        os.path.basename(path))
                    for muri, master_dict in content.items():
                        local_hostname = get_hostname(
                            self._main_window.getMasteruri())
                        rmuri = muri.replace('$LOCAL$', local_hostname)
                        master = self._main_window.getMaster(rmuri)
                        running_nodes = master.get_nodes_runningIfLocal()
                        usr = None
                        self._current_profile[rmuri] = set()
                        if 'user' in master_dict:
                            usr = master_dict['user']
                        if master_dict['mastername'] and master_dict[
                                'mastername']:
                            nm.nameres().add_master_entry(
                                master.masteruri, master_dict['mastername'],
                                master_dict['address'])
                        hostname = master_dict['address'].replace(
                            '$LOCAL$', local_hostname)
                        if 'master_discovery' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_master_discovery',
                                'master_discovery',
                                usr,
                                cfg=master_dict['master_discovery'])
                            self._current_profile[rmuri].add(
                                '/master_discovery')
                        if 'master_sync' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_master_sync',
                                'master_sync',
                                usr,
                                cfg=master_dict['master_sync'])
                            self._current_profile[rmuri].add('/master_sync')
                        if 'zeroconf' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_master_discovery',
                                'zeroconf',
                                usr,
                                cfg=master_dict['zeroconf'])
                            self._current_profile[rmuri].add('/zeroconf')
                        if 'node_manager_daemon' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_node_manager_daemon',
                                'node_manager_daemon',
                                usr,
                                cfg=master_dict['node_manager_daemon'])
                            self._current_profile[rmuri].add(
                                '/node_manager_daemon')
                        try:
                            do_start = []
                            do_not_stop = {
                                '/rosout',
                                rospy.get_name(), '/node_manager',
                                '/master_discovery', '/master_sync',
                                '*default_cfg', '/zeroconf',
                                '/node_manager_daemon'
                            }
                            configs = master_dict['configs']
                            conf_set = set()
                            for cfg_name, cmdict in configs.items():
                                cfg_name = cfg_name.replace(
                                    '$LOCAL$', local_hostname)
                                if cfg_name.startswith("pkg://"):
                                    cfg_name = resolve_pkg(
                                        cfg_name, nmdurl.nmduri(rmuri))
                                conf_set.add(cfg_name)
                                reload_launch = True
                                args = {}
                                if 'args' in cmdict:
                                    if 'args' in cmdict:
                                        args = cmdict['args']
                                    # do we need to load to load/reload launch file
                                    if cfg_name in master.launchfiles:
                                        reload_launch = set(
                                            master.launchfiles[cfg_name].args.
                                            itervalues()) != set(
                                                args.itervalues())
                                if reload_launch:
                                    self._main_window.launch_dock.load_file(
                                        cfg_name, args, master.masteruri)
                                if 'nodes' in cmdict:
                                    self._current_profile[rmuri].update(
                                        cmdict['nodes'])
                                    force_start = True
                                    cfg = cfg_name
                                    if not reload_launch:
                                        force_start = False
                                        do_not_stop.update(set(
                                            cmdict['nodes']))
                                        do_start.append(
                                            (reload_launch, cfg,
                                             cmdict['nodes'], force_start))
                                    else:
                                        do_start.append(
                                            (reload_launch, cfg,
                                             cmdict['nodes'], force_start))
                            # close unused configurations
                            for lfile in set(
                                    master.launchfiles.keys()) - conf_set:
                                master._close_cfg(lfile)
                            master.stop_nodes_by_name(running_nodes.keys(),
                                                      True, do_not_stop)
                            for reload_launch, cfg, nodes, force_start in do_start:
                                if nodes:
                                    hasstart = True
                                if reload_launch:
                                    master.start_nodes_after_load_cfg(
                                        cfg, list(nodes), force_start)
                                else:
                                    master.start_nodes_by_name(
                                        list(nodes), cfg, force_start)
                        except Exception as ml:
                            import traceback
                            print(utf8(traceback.format_exc(1)))
                            rospy.logwarn(
                                "Can not load launch file for %s: %s" %
                                (muri, utf8(ml)))
            except Exception as e:
                import traceback
                print(traceback.format_exc(1))
                MessageBox.warning(self, "Load profile error",
                                   'Error while load profile', utf8(e))
            if not hasstart:
                self.update_progress()
            else:
                QTimer.singleShot(1000, self.update_progress)