Example #1
0
    def __init__(self, updater, config):
        super(EnumEditor, self).__init__(updater, config)

        loadUi(ui_enum, self)

        try:
            enum = eval(config['edit_method'])['enum']
        except:  # noqa: E722
            logging.error('reconfig EnumEditor) Malformed enum')
            return

        # Setup the enum items
        self.names = [item['name'] for item in enum]
        self.values = [item['value'] for item in enum]

        items = [
            '%s (%s)' % (self.names[i], self.values[i])
            for i in range(0, len(self.names))
        ]

        # Add items to the combo box
        self._combobox.addItems(items)

        # Initialize to the default
        self._combobox.setCurrentIndex(self.values.index(config['default']))

        # Make selection update the param server
        self._combobox.currentIndexChanged['int'].connect(self.selected)

        # Make the param server update selection
        self._update_signal.connect(self._update_gui)

        # Bind the context menu
        self._combobox.contextMenuEvent = self.contextMenuEvent
    def __init__(self, *args):
        """
        :param args[0]: str (will become 1st arg of QStandardItem)
        :param args[1]: integer value that indicates whether this class
                               is node that has GRN (Graph Resource Names, see
                               http://www.ros.org/wiki/Names). This can be None
        """
        grn_current_treenode = args[0]
        self._raw_param_name = grn_current_treenode
        self._set_param_name(grn_current_treenode)
        super(TreenodeQstdItem, self).__init__(grn_current_treenode)

        # dynamic_reconfigure.client.Client
        self._param_client = None
        # ParamClientWidget
        self._param_client_widget = None

        self._is_rosnode = False

        self._lock = threading.Lock()
        self._paramserver_connect_thread = None

        try:
            if args[1]:
                self._is_rosnode = True
        except IndexError:  # tuple index out of range etc.
            logging.error('TreenodeQstdItem IndexError')
Example #3
0
 def selected(self, index):
     try:
         value = self.values[index]
     except IndexError:
         logging.error("Invalid selection '{}' for parameter '{}'".format(
             self._combobox.itemText(index), self.param_name))
     else:
         self._update_paramserver(value)
    def _update_nodetree_pernode(self):
        """
        """

        # TODO(Isaac): 11/25/2012 dynamic_reconfigure only returns params that
        #             are associated with nodes. In order to handle independent
        #             params, different approach needs taken.
        try:
            nodes = dyn_reconf.find_reconfigure_services()
        except rosservice.ROSServiceIOException as e:
            logging.error('Reconfigure GUI cannot connect to master.')
            raise e  # TODO Make sure 'raise' here returns or finalizes func.

        if not nodes == self._nodes_previous:
            i_node_curr = 1
            num_nodes = len(nodes)
            elapsedtime_overall = 0.0
            for node_name_grn in nodes:
                # Skip this grn if we already have it
                if node_name_grn in self._nodeitems:
                    i_node_curr += 1
                    continue

                time_siglenode_loop = time.time()

                # (Begin) For DEBUG ONLY; skip some dynreconf creation
                # if i_node_curr % 2 != 0:
                #     i_node_curr += 1
                #     continue
                # (End) For DEBUG ONLY. ####

                # Instantiate QStandardItem. Inside, dyn_reconf client will
                # be generated too.
                treenodeitem_toplevel = TreenodeQstdItem(
                    node_name_grn, TreenodeQstdItem.NODE_FULLPATH)
                _treenode_names = treenodeitem_toplevel.get_treenode_names()

                # Using OrderedDict here is a workaround for StdItemModel
                # not returning corresponding item to index.
                self._nodeitems[node_name_grn] = treenodeitem_toplevel

                self._add_children_treenode(treenodeitem_toplevel,
                                            self._rootitem, _treenode_names)

                time_siglenode_loop = time.time() - time_siglenode_loop
                elapsedtime_overall += time_siglenode_loop

                _str_progress = 'reconf ' + \
                    'loading #{}/{} {} / {}sec node={}'.format(
                        i_node_curr, num_nodes, round(time_siglenode_loop, 2),
                        round(elapsedtime_overall, 2), node_name_grn
                    )

                # NOT a debug print - please DO NOT remove. This print works
                # as progress notification when loading takes long time.
                logging.debug(_str_progress)
                i_node_curr += 1
    def _prune_nodetree_pernode(self):
        try:
            nodes = find_nodes_with_params(self._context.node)
        except Exception as e:
            logging.error('Reconfigure GUI cannot connect to master.')
            raise e  # TODO Make sure 'raise' here returns or finalizes func.

        for i in reversed(range(0, self._rootitem.rowCount())):
            candidate_for_removal = \
                self._rootitem.child(i).get_raw_param_name()
            if candidate_for_removal not in nodes:
                logging.debug(
                    'Removing {} because the server is no longer available.'.
                    format(candidate_for_removal))
                self._rootitem.removeRow(i)
                self._nodeitems.pop(candidate_for_removal).reset()
    def _selection_changed_slot(self, selected, deselected):
        """
        Send "open ROS Node box" signal.

        ONLY IF the selected treenode is the
        terminal treenode.
        Receives args from signal QItemSelectionModel.selectionChanged.

        :param selected: All indexs where selected (could be multiple)
        :type selected: QItemSelection
        :type deselected: QItemSelection
        """
        # Getting the index where user just selected. Should be single.
        if not selected.indexes() and not deselected.indexes():
            logging.error('Nothing selected? Not ideal to reach here')
            return

        index_current = None
        if selected.indexes():
            index_current = selected.indexes()[0]
        elif len(deselected.indexes()) == 1:
            # Setting length criteria as 1 is only a workaround, to avoid
            # Node boxes on right-hand side disappears when filter key doesn't
            # match them.
            # Indeed this workaround leaves another issue. Question for
            # permanent solution is asked here http://goo.gl/V4DT1
            index_current = deselected.indexes()[0]

        logging.debug('  - - - index_current={}'.format(index_current))

        rosnode_name_selected = RqtRosGraph.get_upper_grn(index_current, '')

        # If retrieved node name isn't in the list of all nodes.
        if rosnode_name_selected not in self._nodeitems.keys():
            # De-select the selected item.
            self.selectionModel.select(index_current,
                                       QItemSelectionModel.Deselect)
            return

        if selected.indexes():
            try:
                self._selection_selected(index_current, rosnode_name_selected)
            except Exception as e:
                # TODO: print to sysmsg pane
                err_msg = 'Connection to node={} failed:\n{}'.format(
                    rosnode_name_selected, e)
                import traceback
                traceback.print_exc()
                self._signal_msg.emit(err_msg)
                logging.error(err_msg)

        elif deselected.indexes():
            try:
                self._selection_deselected(index_current,
                                           rosnode_name_selected)
            except Exception as e:
                self._signal_msg.emit(e)
                logging.error(e)
    def connect_param_server(self):
        """
        Connect to parameter server using dynamic_reconfigure client.
        Behavior is delegated to a private method _connect_param_server, and
        its return value, client, is set to member variable.

        @return void
        @raise ROSException:
        """
        # If the treenode doesn't represent ROS Node, return None.
        with self._lock:
            if not self._is_rosnode:
                logging.error('connect_param_server failed due to missing '
                              'ROS Node. Return with nothing.')
                return

            if not self._param_client:
                if self._paramserver_connect_thread:
                    if self._paramserver_connect_thread.is_alive():
                        self._paramserver_connect_thread.join(1)
                self._paramserver_connect_thread = ParamserverConnectThread(
                    self, self._raw_param_name)
                self._paramserver_connect_thread.start()