def __init__(self, map_topic='/map', paths=None, polygons=None):
        super(NavViewWidget, self).__init__()
        if paths is None:
            paths = [
                '/move_base/NavFn/plan',
                '/move_base/TrajectoryPlannerROS/local_plan'
            ]
        if polygons is None:
            polygons = ['/move_base/local_costmap/robot_footprint']

        self._layout = QVBoxLayout()
        self._button_layout = QHBoxLayout()

        self.setAcceptDrops(True)
        self.setWindowTitle('Navigation Viewer')

        self.paths = paths
        self.polygons = polygons
        self.map_topic = map_topic
        self._tf = tf.TransformListener()

        self._set_pose = QPushButton('Set Pose')
        self._set_goal = QPushButton('Set Goal')

        self._button_layout.addWidget(self._set_pose)
        self._button_layout.addWidget(self._set_goal)

        self._layout.addLayout(self._button_layout)

        self._nav_view = None

        self.setLayout(self._layout)
Exemple #2
0
    def __init__(self, parent=None):
        """Create a new, empty DataPlot

        This will raise a RuntimeError if none of the supported plotting
        backends can be found
        """
        super(DataPlot, self).__init__(parent)
        self._plot_index = 0
        self._color_index = 0
        self._markers_on = False
        self._autoscroll = True

        self._autoscale_x = True
        self._autoscale_y = DataPlot.SCALE_ALL

        # the backend widget that we're trying to hide/abstract
        self._data_plot_widget = None
        self._curves = {}
        self._vline = None
        self._redraw.connect(self._do_redraw)

        self._layout = QHBoxLayout()
        self.setLayout(self._layout)

        enabled_plot_types = [pt for pt in self.plot_types if pt['enabled']]
        if not enabled_plot_types:
            version_info = ' and PySide > 1.1.0' if QT_BINDING == 'pyside' else ''
            raise RuntimeError(
                'No usable plot type found. Install at least one of: PyQtGraph, MatPlotLib (at least 1.1.0%s) or Python-Qwt5.'
                % version_info)

        self._switch_data_plot_widget(self._plot_index)

        self.show()
    def __init__(self, reconf, node_name):
        """
        :type reconf: dynamic_reconfigure.client
        :type node_name: str
        """
        group_desc = reconf.get_group_descriptions()
        logging.debug('ParamClientWidget.group_desc=%s', group_desc)
        super(ParamClientWidget, self).__init__(ParamUpdater(reconf),
                                                group_desc, node_name)

        # Save and load buttons
        self.button_widget = QWidget(self)
        self.button_header = QHBoxLayout(self.button_widget)
        self.button_header.setContentsMargins(QMargins(0, 0, 0, 0))

        self.load_button = QPushButton()
        self.save_button = QPushButton()

        self.load_button.setIcon(QIcon.fromTheme('document-open'))
        self.save_button.setIcon(QIcon.fromTheme('document-save'))

        self.load_button.clicked[bool].connect(self._handle_load_clicked)
        self.save_button.clicked[bool].connect(self._handle_save_clicked)

        self.button_header.addWidget(self.save_button)
        self.button_header.addWidget(self.load_button)

        self.setMinimumWidth(150)

        self.reconf = reconf
        self.updater.start()
        self.reconf.config_callback = self.config_callback
        self._node_grn = node_name
    def __init__(self, aircraft_id):
        super(ChecklistWindow, self).__init__()
        # Set properties of the window
        self.setWindowTitle("BTO and BPO Checklist")
        self.resize(500, 700)
        self.move(200,100)
        self.checklist_state = 0

        # Relative path for the default BPO and BTO checklist
        BPO_checklist_file = os.path.join(rospkg.RosPack().get_path('yonah_rqt'), 'src/yonah_rqt', 'BPO_checklist.csv')
        BTO_checklist_file = os.path.join(rospkg.RosPack().get_path('yonah_rqt'), 'src/yonah_rqt', 'BTO_checklist.csv')
        
        # Check whether checklist is present, if not print a error message to terminal
        try:
            # If checklist is present, parse it and pass it to its respective variable
            self.BPO_checklist = self.excel_parser(BPO_checklist_file)
            self.BTO_checklist = self.excel_parser(BTO_checklist_file)
        except:
            rospy.logerr("Checklist files are missing or named wrongly. Please follow the original directory and naming")
            exit()
    
        # Create the layout
        self.main_layout = QVBoxLayout()
        self.buttons_layout = QHBoxLayout()
        self.tree_widget_layout = QHBoxLayout()
        
        # Create the widgets
        self.create_widget()
        self.has_message_opened = 0

        # Add the widgets into the layouts
        self.main_layout.addLayout(self.tree_widget_layout)
        self.main_layout.addLayout(self.buttons_layout)
        self.setLayout(self.main_layout)
Exemple #5
0
    def __init__(self, check_state_changed_callback, topic_name, parent=None, is_topic = False):
        super(TreeWidgetItem, self).__init__(parent)
        self._check_state_changed_callback = check_state_changed_callback
        self._topic_name = topic_name
        self.setCheckState(CHECK_COLUMN, Qt.Unchecked)
        self._is_topic = is_topic
        
        self._slider = QSlider(Qt.Horizontal)
        self._hbox = QHBoxLayout()
        self._min_label = QLabel("min")
        self._max_label = QLabel("max")
        self._hbox.addWidget(self._min_label)
        self._hbox.addWidget(self._slider)
        self._hbox.addWidget(self._max_label)

        tree = self.treeWidget()
        widget = QWidget()
        widget.setLayout(self._hbox)
        # tree.setItemWidget(self, 3, widget)        

        self.setTextAlignment(self._column_names.index("min"), Qt.AlignRight | Qt.AlignVCenter)
        self.setTextAlignment(self._column_names.index("max"), Qt.AlignLeft | Qt.AlignVCenter)
        self.setTextAlignment(self._column_names.index("value"), Qt.AlignHCenter | Qt.AlignVCenter)
        self.setTextAlignment(self._column_names.index("type"), Qt.AlignHCenter | Qt.AlignVCenter)

        self.setFlags(Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable )

        self._slider.valueChanged.connect(self.sliderValueChanged)
Exemple #6
0
    def __init__(self, map_topic='/map',
                 paths=['/move_base/NavFn/plan', '/move_base/TrajectoryPlannerROS/local_plan'],
                 polygons=['/move_base/local_costmap/robot_footprint']):
        super(NavViewWidget, self).__init__()
        self._layout = QVBoxLayout()
        self._button_layout = QHBoxLayout()

        self.setAcceptDrops(True)
        self.setWindowTitle('Navigation Viewer')

        self.paths = paths
        self.polygons = polygons
        self.map = map_topic
        self._tf = tf.TransformListener()

        self._nav_view = NavView(map_topic, paths, polygons, tf = self._tf, parent = self)

        self._set_pose = QPushButton('Set Pose')
        self._set_pose.clicked.connect(self._nav_view.pose_mode)
        self._set_goal = QPushButton('Set Goal')
        self._set_goal.clicked.connect(self._nav_view.goal_mode)

        self._button_layout.addWidget(self._set_pose)
        self._button_layout.addWidget(self._set_goal)

        self._layout.addLayout(self._button_layout)

        self._layout.addWidget(self._nav_view)

        self.setLayout(self._layout)
    def __init__(self, parent=None, current_values=None):
        super(BlacklistDialog, self).__init__(parent)
        self.setWindowTitle("Blacklist")
        vbox = QVBoxLayout()
        self.setLayout(vbox)

        self._blacklist = Blacklist()
        if isinstance(current_values, list):
            for val in current_values:
                self._blacklist.append(val)
        vbox.addWidget(self._blacklist)

        controls_layout = QHBoxLayout()
        add_button = QPushButton(icon=QIcon.fromTheme('list-add'))
        rem_button = QPushButton(icon=QIcon.fromTheme('list-remove'))
        ok_button = QPushButton("Ok")
        cancel_button = QPushButton("Cancel")
        add_button.clicked.connect(self._add_item)
        rem_button.clicked.connect(self._remove_item)
        ok_button.clicked.connect(self.accept)
        cancel_button.clicked.connect(self.reject)

        controls_layout.addWidget(add_button)
        controls_layout.addWidget(rem_button)
        controls_layout.addStretch(0)
        controls_layout.addWidget(ok_button)
        controls_layout.addWidget(cancel_button)
        vbox.addLayout(controls_layout)
Exemple #8
0
    def __init__(self):
        super(ServiceTabbedButtonGeneralWidget, self).__init__()
        self._tab_settings = None

        if rospy.has_param("~tabbed_layout"):
            tabbed_layout = rospy.get_param("~tabbed_layout")
            self._tab_list = []
            if not 'tab_list' in tabbed_layout:
                self.showError("Cannot find tab_list in %s" % (tabbed_layout))
                return
            tab_list = tabbed_layout['tab_list']
            for tb in tab_list:
                if tb in tabbed_layout:
                    param_settings = tabbed_layout[tb]
                    settings = {}
                    ##
                    if 'type' in param_settings:
                        settings['type'] = param_settings['type']
                    ##
                    if not 'name' in param_settings:
                        settings['name'] = tb
                    else:
                        settings['name'] = param_settings['name']
                    ##
                    if 'yaml_file' in param_settings:
                        settings['yaml_file'] = param_settings['yaml_file']
                    else:
                        self.showError("Cannot find yaml_file in %s" % (tb))
                        settings = None
                    ##
                    if 'namespace' in param_settings:
                        settings['namespace'] = param_settings['namespace']

                    if settings:
                        self._tab_list.append(settings)
                else:
                    self.showError("Cannot find key %s in %s" %
                                   (tb, tabbed_layout))
        else:
            self.showError("Cannot find rosparam ~tabbed_layout")
            return

        if len(self._tab_list) == 0:
            self.showError("there is no valid param in ~tabbed_layout")
            return

        qtab = QTabWidget()
        for tb in self._tab_list:
            wg = ServiceButtonGeneralWidget_in_tab(tb)
            qtab.addTab(wg, tb['name'])

        #self.setWindowTitle('Tab Layout')
        hbox = QHBoxLayout()
        hbox.addWidget(qtab)
        self.setLayout(hbox)
        self.show()
    def __init__(self, updater, config, nodename):
        """
        :param config:
        :type config: Dictionary? defined in dynamic_reconfigure.client.Client
        :type nodename: str
        """
        super(GroupWidget, self).__init__()
        self.state = config['state']
        self.param_name = config['name']
        self._toplevel_treenode_name = nodename

        # TODO: .ui file needs to be back into usage in later phase.
        #        ui_file = os.path.join(rp.get_path('rqt_reconfigure'),
        #                               'resource', 'singlenode_parameditor.ui')
        #        loadUi(ui_file, self)

        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(QMargins(0, 0, 0, 0))

        _widget_nodeheader = QWidget()
        _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader)
        _h_layout_nodeheader.setContentsMargins(QMargins(0, 0, 0, 0))

        self.nodename_qlabel = QLabel(self)
        font = QFont('Trebuchet MS, Bold')
        font.setUnderline(True)
        font.setBold(True)

        # Button to close a node.
        _icon_disable_node = QIcon.fromTheme('window-close')
        _bt_disable_node = QPushButton(_icon_disable_node, '', self)
        _bt_disable_node.setToolTip('Hide this node')
        _bt_disable_node_size = QSize(36, 24)
        _bt_disable_node.setFixedSize(_bt_disable_node_size)
        _bt_disable_node.pressed.connect(self._node_disable_bt_clicked)

        _h_layout_nodeheader.addWidget(self.nodename_qlabel)
        _h_layout_nodeheader.addWidget(_bt_disable_node)

        self.nodename_qlabel.setAlignment(Qt.AlignCenter)
        font.setPointSize(10)
        self.nodename_qlabel.setFont(font)
        grid_widget = QWidget(self)
        self.grid = QFormLayout(grid_widget)
        verticalLayout.addWidget(_widget_nodeheader)
        verticalLayout.addWidget(grid_widget, 1)
        # Again, these UI operation above needs to happen in .ui file.

        self.tab_bar = None  # Every group can have one tab bar
        self.tab_bar_shown = False

        self.updater = updater

        self.editor_widgets = []
        self._param_names = []

        self._create_node_widgets(config)

        logging.debug('Groups node name={}'.format(nodename))
        self.nodename_qlabel.setText(nodename)
    def __init__(self, active_aircrafts):
        super(WaypointWindow, self).__init__()
        self.setWindowTitle("Ground Control Station")
        self.adjustSize()
        self.move(200, 100)

        self.waypoint_plaintext_dict = {}
        self.main_layout = QHBoxLayout()
        self.progressbar_layout = QVBoxLayout()
        self.progressbar_layout.setAlignment(Qt.AlignTop)
        # Why we separate this is so that we can refresh the layout
        self.create_layout(active_aircrafts)

        self.main_layout.addLayout(self.progressbar_layout)
        self.setLayout(self.main_layout)
    def __init__(self, reconf, node_name):
        """
        :type reconf: dynamic_reconfigure.client
        :type node_name: str
        """

        group_desc = reconf.get_group_descriptions()
        rospy.logdebug('DynreconfClientWidget.group_desc=%s', group_desc)
        super(DynreconfClientWidget, self).__init__(ParamUpdater(reconf),
                                                    group_desc, node_name)

        # Save and load buttons
        self.button_widget = QWidget(self)
        self.button_header = QHBoxLayout(self.button_widget)
        self.button_header.setContentsMargins(QMargins(0, 0, 0, 0))

        self.load_button = QPushButton()
        self.save_button = QPushButton()

        self.load_button.setIcon(QIcon.fromTheme('document-open'))
        self.save_button.setIcon(QIcon.fromTheme('document-save'))

        self.load_button.clicked[bool].connect(self._handle_load_clicked)
        self.save_button.clicked[bool].connect(self._handle_save_clicked)

        self.button_header.addWidget(self.save_button)
        self.button_header.addWidget(self.load_button)

        self.setMinimumWidth(150)

        self.reconf = reconf
        self.updater.start()
        self.reconf.config_callback = self.config_callback
        self._node_grn = node_name
Exemple #12
0
    def __init__(self, map_topic='/map',
                 paths=['/move_base/NavFn/plan', '/move_base/TrajectoryPlannerROS/local_plan'],
                 polygons=['/move_base/local_costmap/robot_footprint']):
        super(NavViewWidget, self).__init__()
        self._layout = QVBoxLayout()
        self._button_layout = QHBoxLayout()

        self.setAcceptDrops(True)
        self.setWindowTitle('Navigation Viewer')

        self.paths = paths
        self.polygons = polygons
        self.map = map_topic
        self._tf = tf.TransformListener()

        self._nav_view = NavView(map_topic, paths, polygons, tf = self._tf, parent = self)

        self._set_pose = QPushButton('Set Pose')
        self._set_pose.clicked.connect(self._nav_view.pose_mode)
        self._set_goal = QPushButton('Set Goal')
        self._set_goal.clicked.connect(self._nav_view.goal_mode)

        self._button_layout.addWidget(self._set_pose)
        self._button_layout.addWidget(self._set_goal)

        self._layout.addLayout(self._button_layout)

        self._layout.addWidget(self._nav_view)

        self.setLayout(self._layout)
Exemple #13
0
 def beginGui(self,obj):
     self.parent = QScrollArea()
     self.frame = QFrame(self.parent)
     if obj.layout == "vertical":
         self.tl = QVBoxLayout()
     else:
         self.tl = QHBoxLayout()
         
     self.__increase_nesting_level(self.frame,self.tl)
    def add_widgets(self):
        """
        Add groups of widgets to _main_widget. Supports group labels.

        This method can be reimplemented in order to customize appearances.
        """
        widgets = self.get_widgets()
        self._widgets = [
        ]  # stores widgets which may need to be shut down when done
        for group in widgets:
            # Check for group label
            if isinstance(group[0], str):
                grouplabel, v = group
                box = QGroupBox(grouplabel)
                box.setContentsMargins(0, 18, 0, 0)  # LTRB
                # Apply the center-label directive only for single-icon groups
                if len(group[1]) == 1:
                    box.setAlignment(Qt.AlignHCenter)
            else:
                box = QGroupBox()
                box.setContentsMargins(0, 0, 0, 0)  # LTRB
                v = group
            # Add widgets to QGroupBox
            layout = QHBoxLayout()
            layout.setSpacing(0)
            layout.setContentsMargins(0, 0, 0, 0)  # LTRB
            for i in v:
                try:
                    try:
                        i.setIconSize(
                            self.max_icon_size)  # without this, icons are tiny
                    except AttributeError as e:
                        # triggers with battery which uses a QLabel instead of a QToolButton-based widget
                        pass
                    layout.addWidget(i)
                    self._widgets.append(i)
                except:
                    raise Exception(
                        "All widgets must be a subclass of QWidget!")

            layout.activate()
            box.setLayout(layout)
            self._main_widget.addWidget(box)
            self._main_widget.addSeparator()
Exemple #15
0
 def beginGroup(self,obj):
     parent,layout = self.__get_immediate_parent()
     panel = QGroupBox(obj.name,parent)
     if obj.layout == "grid":
         l = QGridLayout()
     elif obj.layout == "vertical":
         l = QVBoxLayout()
     else:
         l = QHBoxLayout()
     
     self.__increase_nesting_level(panel, l)
Exemple #16
0
    def __init__(self, bagFiles, parent=None):
        super(CompareDataTab, self).__init__()
        self.parent = parent

        # attributes
        self.bagFiles = bagFiles
        self.plotData = ([], [], 0.0, 0.0)
        self.plotInfo = {
            'label': '',
            'y_label': '',
        }

        # widgets
        self.operationSelector = OperationSelectorWidget(self)
        self.thresholdSetter = ThresholdSetter(self)
        self.waitMessageBox = QMessageBox(self)
        self.waitMessageBox.setIcon(QMessageBox.Information)
        self.waitMessageBox.setWindowTitle('Computation')

        # layout:
        layout = QHBoxLayout()
        layout.addWidget(self.operationSelector)
        layout.addWidget(self.thresholdSetter)

        self.setLayout(layout)
    def __init__(self, parent=None):
        """Create a new, empty DataPlot
        """
        super(DataPlot, self).__init__(parent)

        # initialize miscellaneous class variables
        self._color_index = 0
        self._scrollwidth = 10
        self._dropwidth = 60  # drop data this much older than our window's lower bound

        # determine whether or not to scroll through the window (in X)
        self._autoscroll = True

        # initialize limits
        # @TODO move static Y values elsewhere? Kinda breaks modularity...
        self._x_limits = [0, 1.0]
        self._static_ylimits = [-0.5, 9.5]

        # initialize currently tracked data ({topic: {goal_id: [timestamp, id]}})
        self._curves = {}

        # initialize various input signals and their callbacks and widgets
        self._redraw.connect(self._do_redraw)
        self._layout = QHBoxLayout()
        self.setLayout(self._layout)

        # initialize backend data processor (based on matplotlib)
        self._data_plot_widget = MatDataPlot(self)
        self._data_plot_widget.limits_changed.connect(self.limits_changed)
        self._add_curve.connect(self._data_plot_widget.add_curve)
        self._layout.addWidget(self._data_plot_widget)

        # update axes
        self._data_plot_widget.set_xlim(self._x_limits)
        self._data_plot_widget.set_ylim(self._static_ylimits)
        self.redraw()

        # display current data
        self.show()
Exemple #18
0
    def _create_cell_push_button(self, text, clicked_cb, icon=None):
        widget = QWidget()

        button = QPushButton()
        button.setText(text)
        if icon:
            button.setIcon(icon)
        button.clicked[bool].connect(clicked_cb)

        hlayout = QHBoxLayout(widget)
        hlayout.addWidget(button)
        hlayout.setAlignment(Qt.AlignCenter)
        hlayout.setContentsMargins(0, 0, 0, 0)

        widget.setLayout(hlayout)
        return widget
Exemple #19
0
    def add_widgets(self):
        """
        Add groups of widgets to _main_widget. Supports group labels.

        This method can be reimplemented in order to customize appearances.
        """
        widgets = self.get_widgets()
        self._widgets = [] # stores widgets which may need to be shut down when done
        for group in widgets:
            # Check for group label
            if isinstance(group[0], str):
                grouplabel, v = group
                box = QGroupBox(grouplabel)
                box.setContentsMargins(0, 18, 0, 0) # LTRB
                # Apply the center-label directive only for single-icon groups
                if len(group[1]) == 1:
                    box.setAlignment(Qt.AlignHCenter)
            else:
                box = QGroupBox()
                box.setContentsMargins(0, 0, 0, 0) # LTRB
                v = group
            # Add widgets to QGroupBox
            layout = QHBoxLayout()
            layout.setSpacing(0)
            layout.setContentsMargins(0, 0, 0, 0) # LTRB
            for i in v:
                try:
                    try:
                        i.setIconSize(self.max_icon_size) # without this, icons are tiny
                    except AttributeError as e:
                        # triggers with battery which uses a QLabel instead of a QToolButton-based widget
                        pass
                    layout.addWidget(i)
                    self._widgets.append(i)
                except:
                    raise Exception("All widgets must be a subclass of QWidget!")

            layout.activate()
            box.setLayout(layout)
            self._main_widget.addWidget(box)
            self._main_widget.addSeparator()
Exemple #20
0
    def create_gait(self, name, gait, selections):
        gait_group_box = QGroupBox()
        gait_group_box.setObjectName('Gait')
        gait_group_box.setLayout(QHBoxLayout())

        gait_group_box.setTitle(name)
        image = QLabel()
        image.setStyleSheet(
            'background: url(' + gait['image'] + ') no-repeat center center 100px 100px;')
        image.setFixedSize(64, 80)
        gait_group_box.layout().addWidget(image)
        for subgait_name, subgait in gait['subgaits'].iteritems():
            subgait_group_box = self.create_subgait(subgait_name, subgait, selections)
            gait_group_box.layout().addWidget(subgait_group_box)

        return gait_group_box
    def __init__(self, parent=None):
        """Create a new, empty DataPlot

        This will raise a RuntimeError if none of the supported plotting
        backends can be found
        """
        super(DataPlot, self).__init__(parent)
        self._plot_index = 0
        self._color_index = 0
        self._markers_on = False
        self._autoscroll = True

        self._autoscale_x = True
        self._autoscale_y = DataPlot.SCALE_ALL

        # the backend widget that we're trying to hide/abstract
        self._data_plot_widget = None
        self._curves = {}
        self._vline = None
        self._redraw.connect(self._do_redraw)

        self._layout = QHBoxLayout()
        self.setLayout(self._layout)

        enabled_plot_types = [pt for pt in self.plot_types if pt["enabled"]]
        if not enabled_plot_types:
            if qVersion().startswith("4."):
                version_info = "1.1.0"
            else:
                # minimum matplotlib version for Qt 5
                version_info = "1.4.0"
            if QT_BINDING == "pyside":
                version_info += " and PySide %s" % ("> 1.1.0" if qVersion().startswith("4.") else ">= 2.0.0")
            raise RuntimeError(
                "No usable plot type found. Install at least one of: PyQtGraph, MatPlotLib (at least %s) or Python-Qwt5."
                % version_info
            )

        self._switch_data_plot_widget(self._plot_index)

        self.show()
    def create_progressbar(self, aircraft_no):
        waypoint_layout = QVBoxLayout()
        waypoint_layout.setContentsMargins(0, 10, 0, 10)
        waypoint_header_layout = QHBoxLayout(
        )  # waypoint_header_layout will be nested inside waypoint_layout with the progress bar beneath it

        aircraft_label = QLabel('Aircraft ' + str(aircraft_no))
        self.waypoint_plaintext_dict['aircraft' +
                                     str(aircraft_no)] = QPlainTextEdit()
        self.waypoint_plaintext_dict.get('aircraft' +
                                         str(aircraft_no)).setMaximumHeight(40)
        self.waypoint_plaintext_dict.get('aircraft' +
                                         str(aircraft_no)).setReadOnly(True)

        self.waypoint_plaintext_dict[
            'aircraftlink' + str(aircraft_no)] = QPlainTextEdit("Telegram")
        self.waypoint_plaintext_dict.get('aircraftlink' +
                                         str(aircraft_no)).setMaximumHeight(40)
        self.waypoint_plaintext_dict.get('aircraftlink' +
                                         str(aircraft_no)).setMaximumWidth(100)

        self.waypoint_plaintext_dict.get('aircraftlink' +
                                         str(aircraft_no)).setReadOnly(True)

        self.waypoint_plaintext_dict['progress_bar_aircraft' +
                                     str(aircraft_no)] = QProgressBar()

        waypoint_header_layout.addWidget(aircraft_label)
        waypoint_header_layout.addWidget(
            self.waypoint_plaintext_dict['aircraft' + str(aircraft_no)])
        waypoint_header_layout.addWidget(
            self.waypoint_plaintext_dict['aircraftlink' + str(aircraft_no)])
        waypoint_layout.addLayout(waypoint_header_layout)
        waypoint_layout.addWidget(
            self.waypoint_plaintext_dict['progress_bar_aircraft' +
                                         str(aircraft_no)])

        self.progressbar_layout.addLayout(waypoint_layout)
Exemple #23
0
    def __init__(self, bagFiles, parent=None):
        super(CompareDataTab, self).__init__()
        self.parent = parent

        # attributes
        self.bagFiles = bagFiles

        # widgets
        self.operationSelector = OperationSelectorWidget(self)
        self.thresholdSetter = ThresholdSetter(self)

        # layout:
        layout = QHBoxLayout()
        layout.addWidget(self.operationSelector)
        layout.addWidget(self.thresholdSetter)

        self.setLayout(layout)
    def __init__(self, btnText):
        super(BagSelector, self).__init__()

        # init the elements
        self.bagEdit = QLineEdit()
        self.bagBtn = QPushButton(btnText)

        # connect the signals to the slots
        self.bagEdit.textChanged.connect(self.pathChanged)
        self.bagBtn.clicked.connect(self.btnClicked)

        self.fileName = ""

        # layout
        layout = QHBoxLayout()
        layout.addWidget(self.bagEdit)
        layout.addWidget(self.bagBtn)
        self.setLayout(layout)
Exemple #25
0
class DataPlot(QWidget):
    """A widget for displaying a plot of data

    The DataPlot widget displays a plot, on one of several plotting backends,
    depending on which backend(s) are available at runtime. It currently
    supports PyQtGraph, MatPlot and QwtPlot backends.

    The DataPlot widget manages the plot backend internally, and can save
    and restore the internal state using `save_settings` and `restore_settings`
    functions.

    Currently, the user MUST call `restore_settings` before using the widget,
    to cause the creation of the enclosed plotting widget.
    """
    # plot types in order of priority
    plot_types = [
        {
            'title': 'PyQtGraph',
            'widget_class': PyQtGraphDataPlot,
            'description':
            'Based on PyQtGraph\n- installer: http://luke.campagnola.me/code/pyqtgraph\n',
            'enabled': PyQtGraphDataPlot is not None,
        },
        {
            'title':
            'MatPlot',
            'widget_class':
            MatDataPlot,
            'description':
            'Based on MatPlotLib\n- needs most CPU\n- needs matplotlib >= 1.1.0\n- if using '
            'PySide: PySide > 1.1.0\n',
            'enabled':
            MatDataPlot is not None,
        },
        {
            'title':
            'QwtPlot',
            'widget_class':
            QwtDataPlot,
            'description':
            'Based on QwtPlot\n- does not use timestamps\n- uses least CPU\n- needs Python '
            'Qwt bindings\n',
            'enabled':
            QwtDataPlot is not None,
        },
    ]

    # pre-defined colors:
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)

    SCALE_ALL = 1
    SCALE_VISIBLE = 2
    SCALE_EXTEND = 4

    _colors = [
        Qt.blue, Qt.red, Qt.cyan, Qt.magenta, Qt.green, Qt.darkYellow,
        Qt.black, Qt.darkCyan, Qt.darkRed, Qt.gray
    ]

    limits_changed = Signal()
    _redraw = Signal()
    _add_curve = Signal(str, str, 'QColor', bool, bool)

    def __init__(self, parent=None):
        """Create a new, empty DataPlot

        This will raise a RuntimeError if none of the supported plotting
        backends can be found
        """
        super(DataPlot, self).__init__(parent)
        self.x_width = 5.0

        self._plot_index = 0
        self._color_index = 0
        self._markers_on = False
        self._autoscroll = True

        self._autoscale_x = False
        self._autoscale_y = DataPlot.SCALE_ALL

        # the backend widget that we're trying to hide/abstract
        self._data_plot_widget = None
        self._curves = {}
        self._vline = None
        self._redraw.connect(self._do_redraw)

        self._layout = QHBoxLayout()
        self.setLayout(self._layout)

        enabled_plot_types = [pt for pt in self.plot_types if pt['enabled']]
        if not enabled_plot_types:
            if qVersion().startswith('4.'):
                version_info = '1.1.0'
            else:
                # minimum matplotlib version for Qt 5
                version_info = '1.4.0'
            if QT_BINDING == 'pyside':
                version_info += ' and PySide %s' % \
                    ('> 1.1.0' if qVersion().startswith('4.') else '>= 2.0.0')
            raise RuntimeError(
                'No usable plot type found. Install at least one of: PyQtGraph, MatPlotLib '
                '(at least %s) or Python-Qwt5.' % version_info)

        self._switch_data_plot_widget(self._plot_index)

        self.show()

    def set_x_width(self, width):
        self.x_width = width

    def _switch_data_plot_widget(self, plot_index, markers_on=False):
        """Internal method for activating a plotting backend by index"""
        # check if selected plot type is available
        if not self.plot_types[plot_index]['enabled']:
            # find other available plot type
            for index, plot_type in enumerate(self.plot_types):
                if plot_type['enabled']:
                    plot_index = index
                    break

        self._plot_index = plot_index
        self._markers_on = markers_on
        selected_plot = self.plot_types[plot_index]
        print("Selected plot: {}".format(selected_plot['title']))

        if self._data_plot_widget:
            x_limits = self.get_xlim()
            y_limits = self.get_ylim()

            self._layout.removeWidget(self._data_plot_widget)
            self._data_plot_widget.close()
            self._data_plot_widget = None
        else:
            x_limits = [0.0, 10.0]
            y_limits = [-0.001, 0.001]

        self._data_plot_widget = selected_plot['widget_class'](self)
        self._data_plot_widget.limits_changed.connect(self.limits_changed)
        self._add_curve.connect(self._data_plot_widget.add_curve)
        self._layout.addWidget(self._data_plot_widget)

        # restore old data
        for curve_id in self._curves:
            curve = self._curves[curve_id]
            self._data_plot_widget.add_curve(curve_id, curve['name'],
                                             curve['color'], markers_on)

        if self._vline:
            self.vline(*self._vline)

        self.set_xlim(x_limits)
        self.set_ylim(y_limits)
        self.redraw()

    def _switch_plot_markers(self, markers_on):
        self._markers_on = markers_on
        self._data_plot_widget._color_index = 0

        for curve_id in self._curves:
            self._data_plot_widget.remove_curve(curve_id)
            curve = self._curves[curve_id]
            self._data_plot_widget.add_curve(curve_id, curve['name'],
                                             curve['color'], markers_on,
                                             curve['dashed'])

        self.redraw()

    # interface out to the managing GUI component: get title, save, restore,
    # etc
    def getTitle(self):
        """get the title of the current plotting backend"""
        return self.plot_types[self._plot_index]['title']

    def save_settings(self, plugin_settings, instance_settings):
        """Save the settings associated with this widget

        Currently, this is just the plot type, but may include more useful
        data in the future"""
        instance_settings.set_value('plot_type', self._plot_index)
        xlim = self.get_xlim()
        ylim = self.get_ylim()
        # convert limits to normal arrays of floats; some backends return numpy
        # arrays
        xlim = [float(x) for x in xlim]
        ylim = [float(y) for y in ylim]
        instance_settings.set_value('x_limits', pack(xlim))
        instance_settings.set_value('y_limits', pack(ylim))

    def restore_settings(self, plugin_settings, instance_settings):
        """Restore the settings for this widget

        Currently, this just restores the plot type."""
        self._switch_data_plot_widget(
            int(instance_settings.value('plot_type', 0)))
        xlim = unpack(instance_settings.value('x_limits', []))
        ylim = unpack(instance_settings.value('y_limits', []))
        if xlim:
            # convert limits to an array of floats; they're often lists of
            # strings
            try:
                xlim = [float(x) for x in xlim]
                self.set_xlim(xlim)
            except:
                qWarning("Failed to restore X limits")
        if ylim:
            try:
                ylim = [float(y) for y in ylim]
                self.set_ylim(ylim)
            except:
                qWarning("Failed to restore Y limits")

    def doSettingsDialog(self):
        """Present the user with a dialog for choosing the plot backend

        This displays a SimpleSettingsDialog asking the user to choose a
        plot type, gets the result, and updates the plot type as necessary

        This method is blocking"""

        marker_settings = [{
            'title':
            'Show Plot Markers',
            'description':
            'Warning: Displaying markers in rqt_plot may cause\n \t high cpu load, '
            'especially using PyQtGraph\n',
            'enabled':
            True,
        }]
        if self._markers_on:
            selected_checkboxes = [0]
        else:
            selected_checkboxes = []

        dialog = SimpleSettingsDialog(title='Plot Options')
        dialog.add_exclusive_option_group(title='Plot Type',
                                          options=self.plot_types,
                                          selected_index=self._plot_index)
        dialog.add_checkbox_group(title='Plot Markers',
                                  options=marker_settings,
                                  selected_indexes=selected_checkboxes)
        [plot_type, checkboxes] = dialog.get_settings()
        if plot_type is not None and \
                plot_type['selected_index'] is not None and \
                self._plot_index != plot_type['selected_index']:
            self._switch_data_plot_widget(plot_type['selected_index'], 0
                                          in checkboxes['selected_indexes'])
        else:
            if checkboxes is not None and self._markers_on != (
                    0 in checkboxes['selected_indexes']):
                self._switch_plot_markers(0 in checkboxes['selected_indexes'])

    # interface out to the managing DATA component: load data, update data,
    # etc
    def autoscroll(self, enabled=True):
        """Enable or disable autoscrolling of the plot"""
        self._autoscroll = enabled

    def redraw(self):
        self._redraw.emit()

    def _do_redraw(self):
        """Redraw the underlying plot

        This causes the underlying plot to be redrawn. This is usually used
        after adding or updating the plot data"""
        if self._data_plot_widget:
            self._merged_autoscale()
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                try:
                    self._data_plot_widget.set_values(curve_id, curve['x'],
                                                      curve['y'])
                except KeyError:
                    # skip curve which has been removed in the mean time
                    pass
            self._data_plot_widget.redraw()

    def _get_curve(self, curve_id):
        if curve_id in self._curves:
            return self._curves[curve_id]
        else:
            raise DataPlotException("No curve named %s in this DataPlot" %
                                    (curve_id))

    def add_curve(self,
                  curve_id,
                  curve_name,
                  data_x,
                  data_y,
                  curve_color=None,
                  dashed=False):
        """Add a new, named curve to this plot

        Add a curve named `curve_name` to the plot, with initial data series
        `data_x` and `data_y`.

        Future references to this curve should use the provided `curve_id`

        Note that the plot is not redraw automatically; call `redraw()` to make
        any changes visible to the user.
        """
        if curve_color is None:
            curve_color = QColor(self._colors[self._color_index %
                                              len(self._colors)])
        self._color_index += 1

        self._curves[curve_id] = {
            'x': numpy.array(data_x),
            'y': numpy.array(data_y),
            'name': curve_name,
            'color': curve_color,
            'dashed': dashed
        }
        if self._data_plot_widget:
            self._add_curve.emit(curve_id, curve_name, curve_color,
                                 self._markers_on, dashed)

    def remove_curve(self, curve_id):
        """Remove the specified curve from this plot"""
        # TODO: do on UI thread with signals
        if curve_id in self._curves:
            del self._curves[curve_id]
        if self._data_plot_widget:
            self._data_plot_widget.remove_curve(curve_id)

    def update_values(self, curve_id, values_x, values_y, sort_data=True):
        """Append new data to an existing curve

        `values_x` and `values_y` will be appended to the existing data for
        `curve_id`

        Note that the plot is not redraw automatically; call `redraw()` to make
        any changes visible to the user.

        If `sort_data` is set to False, values won't be sorted by `values_x`
        order.
        """
        curve = self._get_curve(curve_id)
        curve['x'] = numpy.append(curve['x'], values_x)
        curve['y'] = numpy.append(curve['y'], values_y)

        if sort_data:
            # sort resulting data, so we can slice it later
            sort_order = curve['x'].argsort()
            curve['x'] = curve['x'][sort_order]
            curve['y'] = curve['y'][sort_order]

    def clear_values(self, curve_id=None):
        """Clear the values for the specified curve, or all curves

        This will erase the data series associaed with `curve_id`, or all
        curves if `curve_id` is not present or is None

        Note that the plot is not redraw automatically; call `redraw()` to make
        any changes visible to the user.
        """
        # clear internal curve representation
        if curve_id:
            curve = self._get_curve(curve_id)
            curve['x'] = numpy.array([])
            curve['y'] = numpy.array([])
        else:
            for curve_id in self._curves:
                self._curves[curve_id]['x'] = numpy.array([])
                self._curves[curve_id]['y'] = numpy.array([])

    def vline(self, x, color=RED):
        """Draw a vertical line on the plot

        Draw a line a position X, with the given color

        @param x: position of the vertical line to draw
        @param color: optional parameter specifying the color, as tuple of
                      RGB values from 0 to 255
        """
        self._vline = (x, color)
        if self._data_plot_widget:
            self._data_plot_widget.vline(x, color)

    # autoscaling methods
    def set_autoscale(self, x=None, y=None):
        """Change autoscaling of plot axes

        if a parameter is not passed, the autoscaling setting for that axis is
        not changed

        @param x: enable or disable autoscaling for X
        @param y: set autoscaling mode for Y
        """
        if x is not None:
            self._autoscale_x = x
        if y is not None:
            self._autoscale_y = y

    # autoscaling:  adjusting the plot bounds fit the data
    # autoscrollig: move the plot X window to show the most recent data
    #
    # what order do we do these adjustments in?
    #  * assuming the various stages are enabled:
    #  * autoscale X to bring all data into view
    #   * else, autoscale X to determine which data we're looking at
    #  * autoscale Y to fit the data we're viewing
    #
    # * autoscaling of Y might have several modes:
    #  * scale Y to fit the entire dataset
    #  * scale Y to fit the current view
    #  * increase the Y scale to fit the current view
    #
    # TODO: incrmenetal autoscaling: only update the autoscaling bounds
    #       when new data is added
    def _merged_autoscale(self):
        x_limit = [numpy.inf, -numpy.inf]
        if self._autoscale_x:
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                if len(curve['x']) > 0:
                    x_limit[0] = min(x_limit[0], curve['x'].min())
                    x_limit[1] = max(x_limit[1], curve['x'].max())
        elif self._autoscroll:
            # get current width of plot
            x_limit = self.get_xlim()
            # x_width = x_limit[1] - x_limit[0]
            x_width = self.x_width

            # reset the upper x_limit so that we ignore the previous position
            x_limit[1] = -numpy.inf

            # get largest X value
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                if len(curve['x']) > 0:
                    x_limit[1] = max(x_limit[1], curve['x'].max())

            # set lower limit based on width
            x_limit[0] = x_limit[1] - x_width
        else:
            # don't modify limit, or get it from plot
            x_limit = self.get_xlim()

        # set sane limits if our limits are infinite
        if numpy.isinf(x_limit[0]):
            x_limit[0] = 0.0
        if numpy.isinf(x_limit[1]):
            x_limit[1] = 1.0

        y_limit = [numpy.inf, -numpy.inf]
        if self._autoscale_y:
            # if we're extending the y limits, initialize them with the
            # current limits
            if self._autoscale_y & DataPlot.SCALE_EXTEND:
                y_limit = self.get_ylim()
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                start_index = 0
                end_index = len(curve['x'])

                # if we're scaling based on the visible window, find the
                # start and end indicies of our window
                if self._autoscale_y & DataPlot.SCALE_VISIBLE:
                    # indexof x_limit[0] in curves['x']
                    start_index = curve['x'].searchsorted(x_limit[0])
                    # indexof x_limit[1] in curves['x']
                    end_index = curve['x'].searchsorted(x_limit[1])

                # region here is cheap because it is a numpy view and not a
                # copy of the underlying data
                region = curve['y'][start_index:end_index]
                if len(region) > 0:
                    y_limit[0] = min(y_limit[0], region.min())
                    y_limit[1] = max(y_limit[1], region.max())

                # TODO: compute padding around new min and max values
                #       ONLY consider data for new values; not
                #       existing limits, or we'll add padding on top of old
                #       padding in SCALE_EXTEND mode
                #
                # pad the min/max
                # TODO: invert this padding in get_ylim
                # ymin = limits[0]
                # ymax = limits[1]
                # delta = ymax - ymin if ymax != ymin else 0.1
                # ymin -= .05 * delta
                # ymax += .05 * delta
        else:
            y_limit = self.get_ylim()

        # set sane limits if our limits are infinite
        if numpy.isinf(y_limit[0]):
            y_limit[0] = 0.0
        if numpy.isinf(y_limit[1]):
            y_limit[1] = 1.0

        self.set_xlim(x_limit)
        self.set_ylim(y_limit)

    def get_xlim(self):
        """get X limits"""
        if self._data_plot_widget:
            return self._data_plot_widget.get_xlim()
        else:
            qWarning("No plot widget; returning default X limits")
            return [0.0, 1.0]

    def set_xlim(self, limits):
        """set X limits"""
        if self._data_plot_widget:
            self._data_plot_widget.set_xlim(limits)
        else:
            qWarning("No plot widget; can't set X limits")

    def get_ylim(self):
        """get Y limits"""
        if self._data_plot_widget:
            return self._data_plot_widget.get_ylim()
        else:
            qWarning("No plot widget; returning default Y limits")
            return [0.0, 10.0]

    def set_ylim(self, limits):
        """set Y limits"""
        if self._data_plot_widget:
            self._data_plot_widget.set_ylim(limits)
        else:
            qWarning("No plot widget; can't set Y limits")
Exemple #26
0
    def __init__(self, parent=None):
        super(VisualizerWidget, self).__init__(parent)
        self.setWindowTitle('Graph Profiler Visualizer')
        vbox = QVBoxLayout()
        self.setLayout(vbox)

        toolbar_layout = QHBoxLayout()
        refresh_button = QPushButton()
        refresh_button.setIcon(QIcon.fromTheme('view-refresh'))
        auto_refresh_checkbox = QCheckBox("Auto Refresh")
        hide_disconnected_topics = QCheckBox("Hide Disconnected Topics")
        topic_blacklist_button = QPushButton("Topic Blacklist")
        node_blacklist_button = QPushButton("Node Blacklist")

        refresh_button.clicked.connect(self._refresh)
        topic_blacklist_button.clicked.connect(self._edit_topic_blacklist)
        node_blacklist_button.clicked.connect(self._edit_node_blacklist)
        auto_refresh_checkbox.setCheckState(2)
        auto_refresh_checkbox.stateChanged.connect(self._autorefresh_changed)
        hide_disconnected_topics.setCheckState(2)
        hide_disconnected_topics.stateChanged.connect(
            self._hidedisconnectedtopics_changed)

        toolbar_layout.addWidget(refresh_button)
        toolbar_layout.addWidget(auto_refresh_checkbox)
        toolbar_layout.addStretch(0)
        toolbar_layout.addWidget(hide_disconnected_topics)
        toolbar_layout.addWidget(topic_blacklist_button)
        toolbar_layout.addWidget(node_blacklist_button)
        vbox.addLayout(toolbar_layout)

        # Initialize the Visualizer
        self._view = qt_view.QtView()
        self._adapter = rosprofiler_adapter.ROSProfileAdapter(self._view)
        self._adapter.set_topic_quiet_list(TOPIC_BLACKLIST)
        self._adapter.set_node_quiet_list(NODE_BLACKLIST)
        vbox.addWidget(self._view)
Exemple #27
0
class NavViewWidget(QWidget):

    def __init__(self, map_topic='/map',
                 paths=['/move_base/NavFn/plan', '/move_base/TrajectoryPlannerROS/local_plan'],
                 polygons=['/move_base/local_costmap/robot_footprint']):
        super(NavViewWidget, self).__init__()
        self._layout = QVBoxLayout()
        self._button_layout = QHBoxLayout()

        self.setAcceptDrops(True)
        self.setWindowTitle('Navigation Viewer')

        self.paths = paths
        self.polygons = polygons
        self.map = map_topic
        self._tf = tf.TransformListener()

        self._nav_view = NavView(map_topic, paths, polygons, tf = self._tf, parent = self)

        self._set_pose = QPushButton('Set Pose')
        self._set_pose.clicked.connect(self._nav_view.pose_mode)
        self._set_goal = QPushButton('Set Goal')
        self._set_goal.clicked.connect(self._nav_view.goal_mode)

        self._button_layout.addWidget(self._set_pose)
        self._button_layout.addWidget(self._set_goal)

        self._layout.addLayout(self._button_layout)

        self._layout.addWidget(self._nav_view)

        self.setLayout(self._layout)

    def dragEnterEvent(self, e):
        if not e.mimeData().hasText():
            if not hasattr(e.source(), 'selectedItems') or len(e.source().selectedItems()) == 0:
                qWarning('NavView.dragEnterEvent(): not hasattr(event.source(), selectedItems) or len(event.source().selectedItems()) == 0')
                return
            item = e.source().selectedItems()[0]
            topic_name = item.data(0, Qt.UserRole)
            if topic_name == None:
                qWarning('NavView.dragEnterEvent(): not hasattr(item, ros_topic_name_)')
                return

        else:
            topic_name = str(e.mimeData().text())

        if accepted_topic(topic_name):
            e.accept()
            e.acceptProposedAction()

    def dropEvent(self, e):
        if e.mimeData().hasText():
            topic_name = str(e.mimeData().text())
        else:
            droped_item = e.source().selectedItems()[0]
            topic_name = str(droped_item.data(0, Qt.UserRole))

        topic_type, array = get_field_type(topic_name)
        if not array:
            if topic_type is OccupancyGrid:
                self.map = topic_name

                # Swap out the nav view for one with the new topics
                self._nav_view.close()
                self._nav_view = NavView(self.map, self.paths, self.polygons, self._tf, self)
                self._layout.addWidget(self._nav_view)
            elif topic_type is Path:
                self.paths.append(topic_name)
                self._nav_view.add_path(topic_name)
            elif topic_type is PolygonStamped:
                self.polygons.append(topic_name)
                self._nav_view.add_polygon(topic_name)

    def save_settings(self, plugin_settings, instance_settings):
        self._nav_view.save_settings(plugin_settings, instance_settings)

    def restore_settings(self, plugin_settings, instance_settings):
        self._nav_view.restore_settings(plugin_settings, instance_settings)
class ParamClientWidget(GroupWidget):
    """
    A wrapper of dynamic_reconfigure.client instance.

    Represents a widget where users can view and modify ROS params.
    """
    def __init__(self, reconf, node_name):
        """
        :type reconf: dynamic_reconfigure.client
        :type node_name: str
        """
        group_desc = reconf.get_group_descriptions()
        logging.debug('ParamClientWidget.group_desc=%s', group_desc)
        super(ParamClientWidget, self).__init__(ParamUpdater(reconf),
                                                group_desc, node_name)

        # Save and load buttons
        self.button_widget = QWidget(self)
        self.button_header = QHBoxLayout(self.button_widget)
        self.button_header.setContentsMargins(QMargins(0, 0, 0, 0))

        self.load_button = QPushButton()
        self.save_button = QPushButton()

        self.load_button.setIcon(QIcon.fromTheme('document-open'))
        self.save_button.setIcon(QIcon.fromTheme('document-save'))

        self.load_button.clicked[bool].connect(self._handle_load_clicked)
        self.save_button.clicked[bool].connect(self._handle_save_clicked)

        self.button_header.addWidget(self.save_button)
        self.button_header.addWidget(self.load_button)

        self.setMinimumWidth(150)

        self.reconf = reconf
        self.updater.start()
        self.reconf.config_callback = self.config_callback
        self._node_grn = node_name

    def get_node_grn(self):
        return self._node_grn

    def config_callback(self, config):

        # TODO: Think about replacing callback architecture with signals.

        if config:
            # TODO: should use config.keys but this method doesnt exist

            names = [name for name, v in config.items()]
            # v isn't used but necessary to get key and put it into dict.
            # logging.debug('config_callback name={} v={}'.format(name, v))

            for widget in self.editor_widgets:
                if isinstance(widget, EditorWidget):
                    if widget.param_name in names:
                        logging.debug('EDITOR widget.param_name=%s',
                                      widget.param_name)
                        widget.update_value(config[widget.param_name])
                elif isinstance(widget, GroupWidget):
                    cfg = find_cfg(config, widget.param_name)
                    logging.debug('GROUP widget.param_name=%s',
                                  widget.param_name)
                    widget.update_group(cfg)

    def _handle_load_clicked(self):
        filename = QFileDialog.getOpenFileName(
            self, self.tr('Load from File'), '.',
            self.tr('YAML file {.yaml} (*.yaml)'))
        if filename[0] != '':
            self.load_param(filename[0])

    def _handle_save_clicked(self):
        filename = QFileDialog.getSaveFileName(
            self, self.tr('Save parameters to file...'), '.',
            self.tr('YAML files {.yaml} (*.yaml)'))
        if filename[0] != '':
            self.save_param(filename[0])

    def save_param(self, filename):
        configuration = self.reconf.get_configuration()
        if configuration is not None:
            with open(filename, 'w') as f:
                yaml.dump(configuration, f)

    def load_param(self, filename):
        with open(filename, 'r') as f:
            configuration = {}
            for doc in yaml.load_all(f.read()):
                configuration.update(doc)

        try:
            self.reconf.update_configuration(configuration)
        except ServiceException as e:
            logging.warn(
                "Call for reconfiguration wasn't successful because: %s",
                e.message)
        except DynamicReconfigureParameterException as e:
            logging.warn("Reconfiguration wasn't successful because: %s",
                         e.message)
        except DynamicReconfigureCallbackException as e:
            logging.warn("Reconfiguration wasn't successful because: %s",
                         e.message)

    def close(self):
        self.reconf.close()
        self.updater.stop()

        for w in self.editor_widgets:
            w.close()

        self.deleteLater()

    def filter_param(self, filter_key):
        # TODO impl
        pass
Exemple #29
0
 def setupButtons(self, yaml_file):
     """
     Parse yaml file and setup Buttons. Format of the yaml file should be:
     - name: 'button name' (required)
       image: 'path to image for icon' (optional)
       image_size: 'width and height of icon' (optional)
       service: 'service' (required)
       column: 'column index' (optional, defaults to 0)
     """
     self.buttons = []
     with open(yaml_file) as f:
         yaml_data = yaml.load(f)
         # lookup colum direction
         direction = 'vertical'
         for d in yaml_data:
             if d.has_key('direction'):
                 if d['direction'] == 'horizontal':
                     direction = 'horizontal'
                 else:  # d['direction'] == 'vertical':
                     direction = 'vertical'
                 yaml_data.remove(d)
                 break
         # lookup column num
         column_indices = [d['column'] for d in yaml_data]
         max_column_index = max(*column_indices)
         if direction == 'vertical':
             self.layout = QHBoxLayout()
             self.layout_boxes = [
                 QVBoxLayout() for i in range(max_column_index + 1)
             ]
         else:  # direction == 'horizontal'
             self.layout = QVBoxLayout()
             self.layout_boxes = [
                 QHBoxLayout() for i in range(max_column_index + 1)
             ]
         self.button_groups = [
             QGroupBox() for i in range(max_column_index + 1)
         ]
         for button_data in yaml_data:
             # check if all the field is available
             if not button_data.has_key("name"):
                 self.showError("name field is missed in yaml")
                 raise Exception("name field is missed in yaml")
             if not button_data.has_key("service"):
                 self.showError("service field is missed in yaml")
                 raise Exception("service field is missed in yaml")
             if self.button_type == "push":
                 button = QToolButton()
             else:  # self.button_type == "radio":
                 button = QRadioButton()
             button.setSizePolicy(
                 QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred))
             if button_data.has_key("image"):
                 image_file = get_filename(
                     button_data["image"])[len("file://"):]
                 if os.path.exists(image_file):
                     icon = QtGui.QIcon(image_file)
                     button.setIcon(icon)
                     if button_data.has_key("image_size"):
                         button.setIconSize(
                             QSize(button_data["image_size"][0],
                                   button_data["image_size"][1]))
                     else:
                         button.setIconSize(QSize(100, 100))
             if button_data.has_key("name"):
                 name = button_data['name']
                 button.setText(name)
             if button_data.has_key('service_type'):
                 if button_data['service_type'] == 'Trigger':
                     service_type = Trigger
                 elif button_data['service_type'] == 'Empty':
                     service_type = Empty
                 elif button_data['service_type'] == 'SetBool':
                     service_type = SetBool
                 else:
                     raise Exception("Unsupported service type: {}".format(
                         button_data['service_type']))
             else:
                 service_type = Empty
             if service_type == SetBool:
                 button.setCheckable(True)
             button.clicked.connect(
                 self.buttonCallback(button_data['service'], service_type,
                                     button))
             if self.button_type == "push":
                 button.setToolButtonStyle(
                     QtCore.Qt.ToolButtonTextUnderIcon)
             if ((self.button_type == "radio" or service_type == SetBool)
                     and ("default_value" in button_data
                          and button_data['default_value'])):
                 button.setChecked(True)
             self.layout_boxes[button_data['column']].addWidget(button)
             self.buttons.append(button)
         for i in range(len(self.button_groups)):
             self.button_groups[i].setLayout(self.layout_boxes[i])
         for group in self.button_groups:
             self.layout.addWidget(group)
         self.setLayout(self.layout)
    def add_item_to_conversation_view(self, msg, type=0):
        label_msg = QLabel(msg)
        label_msg.setWordWrap(True)
        label_msg.setStyleSheet('font-size:10pt;')

        inner_text_layout = QHBoxLayout()
        horizonalSpacer1 = QSpacerItem(0, 0, QSizePolicy.MinimumExpanding,
                                       QSizePolicy.MinimumExpanding)
        if type == 0:
            inner_text_layout.addWidget(label_msg)
            inner_text_layout.addItem(horizonalSpacer1)
        elif type == 1:
            inner_text_layout.addItem(horizonalSpacer1)
            inner_text_layout.addWidget(label_msg)

        inner_layout = QVBoxLayout()
        time_msg = QLabel(str(time.asctime(time.localtime(time.time()))))
        time_msg.setStyleSheet('font-size:8pt;')

        inner_layout.addItem(inner_text_layout)
        inner_layout.addWidget(time_msg)
        inner_layout.setSizeConstraint(QLayout.SetFixedSize)

        outer_layout = QHBoxLayout()
        horizonalSpacer2 = QSpacerItem(0, 0, QSizePolicy.MinimumExpanding,
                                       QSizePolicy.MinimumExpanding)
        if type == 0:
            label_msg.setStyleSheet(
                'background: #e5e5ea; padding: 6px; border-radius: 8px;')
            time_msg.setAlignment(Qt.AlignLeft)
            outer_layout.addItem(inner_layout)
            outer_layout.addItem(horizonalSpacer2)
        elif type == 1:
            label_msg.setStyleSheet(
                'background: #1d86f4; padding: 6px; border-radius: 8px; color:#fff;'
            )
            time_msg.setAlignment(Qt.AlignRight)
            outer_layout.addItem(horizonalSpacer2)
            outer_layout.addItem(inner_layout)
        outer_layout.setSizeConstraint(QLayout.SetMinimumSize)

        widget = QWidget()
        widget.setLayout(outer_layout)
        widget.resize(widget.sizeHint())

        item = QListWidgetItem()
        item.setSizeHint(widget.sizeHint())

        self._widget.listWidget.addItem(item)
        self._widget.listWidget.setItemWidget(item, widget)
        self._widget.listWidget.scrollToBottom()
class DataPlot(QWidget):
    """A widget for displaying a plot of data

    The DataPlot widget displays a plot, on one of several plotting backends,
    depending on which backend(s) are available at runtime. It currently 
    supports PyQtGraph, MatPlot and QwtPlot backends.

    The DataPlot widget manages the plot backend internally, and can save
    and restore the internal state using `save_settings` and `restore_settings`
    functions.

    Currently, the user MUST call `restore_settings` before using the widget,
    to cause the creation of the enclosed plotting widget.
    """
    # plot types in order of priority
    plot_types = [
        {
            'title': 'PyQtGraph',
            'widget_class': PyQtGraphDataPlot,
            'description': 'Based on PyQtGraph\n- installer: http://luke.campagnola.me/code/pyqtgraph\n',
            'enabled': PyQtGraphDataPlot is not None,
        },
        {
            'title': 'MatPlot',
            'widget_class': MatDataPlot,
            'description': 'Based on MatPlotLib\n- needs most CPU\n- needs matplotlib >= 1.1.0\n- if using PySide: PySide > 1.1.0\n',
            'enabled': MatDataPlot is not None,
        },
        {
            'title': 'QwtPlot',
            'widget_class': QwtDataPlot,
            'description': 'Based on QwtPlot\n- does not use timestamps\n- uses least CPU\n- needs Python Qwt bindings\n',
            'enabled': QwtDataPlot is not None,
        },
    ]

    # pre-defined colors:
    RED=(255, 0, 0)
    GREEN=(0, 255, 0)
    BLUE=(0, 0, 255)

    SCALE_ALL=1
    SCALE_VISIBLE=2
    SCALE_EXTEND=4

    _colors = [Qt.blue, Qt.red, Qt.cyan, Qt.magenta, Qt.green, Qt.darkYellow, Qt.black, Qt.darkCyan, Qt.darkRed, Qt.gray]

    limits_changed = Signal()
    _redraw = Signal()
    _add_curve = Signal(str, str, 'QColor', bool)

    def __init__(self, parent=None):
        """Create a new, empty DataPlot

        This will raise a RuntimeError if none of the supported plotting
        backends can be found
        """
        super(DataPlot, self).__init__(parent)
        self._plot_index = 0
        self._color_index = 0
        self._markers_on = False
        self._autoscroll = True

        self._autoscale_x = True
        self._autoscale_y = DataPlot.SCALE_ALL

        # the backend widget that we're trying to hide/abstract
        self._data_plot_widget = None
        self._curves = {}
        self._vline = None
        self._redraw.connect(self._do_redraw)

        self._layout = QHBoxLayout()
        self.setLayout(self._layout)

        enabled_plot_types = [pt for pt in self.plot_types if pt['enabled']]
        if not enabled_plot_types:
            if qVersion().startswith('4.'):
                version_info = '1.1.0'
            else:
                # minimum matplotlib version for Qt 5
                version_info = '1.4.0'
            if QT_BINDING == 'pyside':
                version_info += ' and PySide %s' % \
                    ('> 1.1.0' if qVersion().startswith('4.') else '>= 2.0.0')
            raise RuntimeError('No usable plot type found. Install at least one of: PyQtGraph, MatPlotLib (at least %s) or Python-Qwt5.' % version_info)

        self._switch_data_plot_widget(self._plot_index)

        self.show()

    def _switch_data_plot_widget(self, plot_index, markers_on=False):
        """Internal method for activating a plotting backend by index"""
        # check if selected plot type is available
        if not self.plot_types[plot_index]['enabled']:
            # find other available plot type
            for index, plot_type in enumerate(self.plot_types):
                if plot_type['enabled']:
                    plot_index = index
                    break

        self._plot_index = plot_index
        self._markers_on = markers_on
        selected_plot = self.plot_types[plot_index]

        if self._data_plot_widget:
            x_limits = self.get_xlim()
            y_limits = self.get_ylim()

            self._layout.removeWidget(self._data_plot_widget)
            self._data_plot_widget.close()
            self._data_plot_widget = None
        else:
            x_limits = [0.0, 10.0]
            y_limits = [-0.001, 0.001]

        self._data_plot_widget = selected_plot['widget_class'](self)
        self._data_plot_widget.limits_changed.connect(self.limits_changed)
        self._add_curve.connect(self._data_plot_widget.add_curve)
        self._layout.addWidget(self._data_plot_widget)

        # restore old data
        for curve_id in self._curves:
            curve = self._curves[curve_id]
            self._data_plot_widget.add_curve(curve_id, curve['name'], curve['color'], markers_on)

        if self._vline:
            self.vline(*self._vline)

        self.set_xlim(x_limits)
        self.set_ylim(y_limits)
        self.redraw()

    def _switch_plot_markers(self, markers_on):
        self._markers_on = markers_on
        self._data_plot_widget._color_index = 0

        for curve_id in self._curves:
            self._data_plot_widget.remove_curve(curve_id)
            curve = self._curves[curve_id]
            self._data_plot_widget.add_curve(curve_id, curve['name'], curve['color'], markers_on)

        self.redraw()

    # interface out to the managing GUI component: get title, save, restore, 
    # etc
    def getTitle(self):
        """get the title of the current plotting backend"""
        return self.plot_types[self._plot_index]['title']

    def save_settings(self, plugin_settings, instance_settings):
        """Save the settings associated with this widget

        Currently, this is just the plot type, but may include more useful
        data in the future"""
        instance_settings.set_value('plot_type', self._plot_index)
        xlim = self.get_xlim()
        ylim = self.get_ylim()
        # convert limits to normal arrays of floats; some backends return numpy
        # arrays
        xlim = [float(x) for x in xlim]
        ylim = [float(y) for y in ylim]
        instance_settings.set_value('x_limits', pack(xlim))
        instance_settings.set_value('y_limits', pack(ylim))

    def restore_settings(self, plugin_settings, instance_settings):
        """Restore the settings for this widget

        Currently, this just restores the plot type."""
        self._switch_data_plot_widget(int(instance_settings.value('plot_type', 0)))
        xlim = unpack(instance_settings.value('x_limits', []))
        ylim = unpack(instance_settings.value('y_limits', []))
        if xlim:
            # convert limits to an array of floats; they're often lists of
            # strings
            try:
                xlim = [float(x) for x in xlim]
                self.set_xlim(xlim)
            except:
                qWarning("Failed to restore X limits")
        if ylim:
            try:
                ylim = [float(y) for y in ylim]
                self.set_ylim(ylim)
            except:
                qWarning("Failed to restore Y limits")


    def doSettingsDialog(self):
        """Present the user with a dialog for choosing the plot backend

        This displays a SimpleSettingsDialog asking the user to choose a
        plot type, gets the result, and updates the plot type as necessary
        
        This method is blocking"""

        marker_settings = [
            {
                'title': 'Show Plot Markers',
                'description': 'Warning: Displaying markers in rqt_plot may cause\n \t high cpu load, especially using PyQtGraph\n',
                'enabled': True,
            }]
        if self._markers_on:
            selected_checkboxes = [0]
        else:
            selected_checkboxes = []

        dialog = SimpleSettingsDialog(title='Plot Options')
        dialog.add_exclusive_option_group(title='Plot Type', options=self.plot_types, selected_index=self._plot_index)
        dialog.add_checkbox_group(title='Plot Markers', options=marker_settings, selected_indexes=selected_checkboxes)
        [plot_type, checkboxes] = dialog.get_settings()
        if plot_type is not None and plot_type['selected_index'] is not None and self._plot_index != plot_type['selected_index']:
            self._switch_data_plot_widget(plot_type['selected_index'], 0 in checkboxes['selected_indexes'])
        else:
            if checkboxes is not None and self._markers_on != (0 in checkboxes['selected_indexes']):
                self._switch_plot_markers(0 in checkboxes['selected_indexes'])

    # interface out to the managing DATA component: load data, update data,
    # etc
    def autoscroll(self, enabled=True):
        """Enable or disable autoscrolling of the plot"""
        self._autoscroll = enabled

    def redraw(self):
        self._redraw.emit()

    def _do_redraw(self):
        """Redraw the underlying plot

        This causes the underlying plot to be redrawn. This is usually used
        after adding or updating the plot data"""
        if self._data_plot_widget:
            self._merged_autoscale()
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                self._data_plot_widget.set_values(curve_id, curve['x'], curve['y'])
            self._data_plot_widget.redraw()

    def _get_curve(self, curve_id):
        if curve_id in self._curves:
            return self._curves[curve_id]
        else:
            raise DataPlotException("No curve named %s in this DataPlot" %
                    ( curve_id) )

    def add_curve(self, curve_id, curve_name, data_x, data_y):
        """Add a new, named curve to this plot

        Add a curve named `curve_name` to the plot, with initial data series
        `data_x` and `data_y`.
        
        Future references to this curve should use the provided `curve_id`

        Note that the plot is not redraw automatically; call `redraw()` to make
        any changes visible to the user.
        """
        curve_color = QColor(self._colors[self._color_index % len(self._colors)])
        self._color_index += 1

        self._curves[curve_id] = { 'x': numpy.array(data_x),
                                   'y': numpy.array(data_y),
                                   'name': curve_name,
                                   'color': curve_color}
        if self._data_plot_widget:
            self._add_curve.emit(curve_id, curve_name, curve_color, self._markers_on)

    def remove_curve(self, curve_id):
        """Remove the specified curve from this plot"""
        # TODO: do on UI thread with signals
        if curve_id in self._curves:
            del self._curves[curve_id]
        if self._data_plot_widget:
            self._data_plot_widget.remove_curve(curve_id)

    def update_values(self, curve_id, values_x, values_y):
        """Append new data to an existing curve
        
        `values_x` and `values_y` will be appended to the existing data for
        `curve_id`

        Note that the plot is not redraw automatically; call `redraw()` to make
        any changes visible to the user.
        """
        curve = self._get_curve(curve_id)
        curve['x'] = numpy.append(curve['x'], values_x)
        curve['y'] = numpy.append(curve['y'], values_y)
        # sort resulting data, so we can slice it later
        sort_order = curve['x'].argsort()
        curve['x'] = curve['x'][sort_order]
        curve['y'] = curve['y'][sort_order]

    def clear_values(self, curve_id=None):
        """Clear the values for the specified curve, or all curves

        This will erase the data series associaed with `curve_id`, or all
        curves if `curve_id` is not present or is None

        Note that the plot is not redraw automatically; call `redraw()` to make
        any changes visible to the user.
        """
        # clear internal curve representation
        if curve_id:
            curve = self._get_curve(curve_id)
            curve['x'] = numpy.array([])
            curve['y'] = numpy.array([])
        else:
            for curve_id in self._curves:
                self._curves[curve_id]['x'] = numpy.array([])
                self._curves[curve_id]['y'] = numpy.array([])


    def vline(self, x, color=RED):
        """Draw a vertical line on the plot

        Draw a line a position X, with the given color
        
        @param x: position of the vertical line to draw
        @param color: optional parameter specifying the color, as tuple of
                      RGB values from 0 to 255
        """
        self._vline = (x, color)
        if self._data_plot_widget:
            self._data_plot_widget.vline(x, color)

    # autoscaling methods
    def set_autoscale(self, x=None, y=None):
        """Change autoscaling of plot axes

        if a parameter is not passed, the autoscaling setting for that axis is
        not changed

        @param x: enable or disable autoscaling for X
        @param y: set autoscaling mode for Y
        """
        if x is not None:
            self._autoscale_x = x
        if y is not None:
            self._autoscale_y = y

    # autoscaling:  adjusting the plot bounds fit the data
    # autoscrollig: move the plot X window to show the most recent data
    #
    # what order do we do these adjustments in?
    #  * assuming the various stages are enabled:
    #  * autoscale X to bring all data into view
    #   * else, autoscale X to determine which data we're looking at
    #  * autoscale Y to fit the data we're viewing
    #
    # * autoscaling of Y might have several modes:
    #  * scale Y to fit the entire dataset
    #  * scale Y to fit the current view
    #  * increase the Y scale to fit the current view
    #
    # TODO: incrmenetal autoscaling: only update the autoscaling bounds
    #       when new data is added
    def _merged_autoscale(self):
        x_limit = [numpy.inf, -numpy.inf]
        if self._autoscale_x:
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                if len(curve['x']) > 0:
                    x_limit[0] = min(x_limit[0], curve['x'].min())
                    x_limit[1] = max(x_limit[1], curve['x'].max())
        elif self._autoscroll:
            # get current width of plot
            x_limit = self.get_xlim()
            x_width = x_limit[1] - x_limit[0]

            # reset the upper x_limit so that we ignore the previous position
            x_limit[1] = -numpy.inf
            
            # get largest X value
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                if len(curve['x']) > 0:
                    x_limit[1] = max(x_limit[1], curve['x'].max())

            # set lower limit based on width
            x_limit[0] = x_limit[1] - x_width
        else:
            # don't modify limit, or get it from plot
            x_limit = self.get_xlim()

        # set sane limits if our limits are infinite
        if numpy.isinf(x_limit[0]):
            x_limit[0] = 0.0
        if numpy.isinf(x_limit[1]):
            x_limit[1] = 1.0


        y_limit = [numpy.inf, -numpy.inf]
        if self._autoscale_y:
            # if we're extending the y limits, initialize them with the
            # current limits
            if self._autoscale_y & DataPlot.SCALE_EXTEND:
                y_limit = self.get_ylim()
            for curve_id in self._curves:
                curve = self._curves[curve_id]
                start_index = 0
                end_index = len(curve['x'])

                # if we're scaling based on the visible window, find the
                # start and end indicies of our window
                if self._autoscale_y & DataPlot.SCALE_VISIBLE:
                    # indexof x_limit[0] in curves['x']
                    start_index = curve['x'].searchsorted(x_limit[0])
                    # indexof x_limit[1] in curves['x']
                    end_index = curve['x'].searchsorted(x_limit[1])

                # region here is cheap because it is a numpy view and not a
                # copy of the underlying data
                region = curve['y'][start_index:end_index]
                if len(region) > 0:
                    y_limit[0] = min(y_limit[0], region.min())
                    y_limit[1] = max(y_limit[1], region.max())

                # TODO: compute padding around new min and max values
                #       ONLY consider data for new values; not
                #       existing limits, or we'll add padding on top of old
                #       padding in SCALE_EXTEND mode
                # 
                # pad the min/max
                # TODO: invert this padding in get_ylim
                #ymin = limits[0]
                #ymax = limits[1]
                #delta = ymax - ymin if ymax != ymin else 0.1
                #ymin -= .05 * delta
                #ymax += .05 * delta
        else:
            y_limit = self.get_ylim()

        # set sane limits if our limits are infinite
        if numpy.isinf(y_limit[0]):
            y_limit[0] = 0.0
        if numpy.isinf(y_limit[1]):
            y_limit[1] = 1.0

        self.set_xlim(x_limit)
        self.set_ylim(y_limit)

    def get_xlim(self):
        """get X limits"""
        if self._data_plot_widget:
            return self._data_plot_widget.get_xlim()
        else:
            qWarning("No plot widget; returning default X limits")
            return [0.0, 1.0]

    def set_xlim(self, limits):
        """set X limits"""
        if self._data_plot_widget:
            self._data_plot_widget.set_xlim(limits)
        else:
            qWarning("No plot widget; can't set X limits")

    def get_ylim(self):
        """get Y limits"""
        if self._data_plot_widget:
            return self._data_plot_widget.get_ylim()
        else:
            qWarning("No plot widget; returning default Y limits")
            return [0.0, 10.0]

    def set_ylim(self, limits):
        """set Y limits"""
        if self._data_plot_widget:
            self._data_plot_widget.set_ylim(limits)
        else:
            qWarning("No plot widget; can't set Y limits")
Exemple #32
0
class BagParser(QWidget):
    def __init__(self, bag_files, listtopics, duration):
        super(BagParser, self).__init__()

        # window title
        self.setWindowTitle("Making csv file")
        # size of window
        self.resize(960, 720)
        #self.showFullScreen()
        #self.setWindowState(Qt.WindowMaximized)

        # print listtopics
        # print E.get_general_features_options()
        # print E.get_specific_features_options()

        self.topics_items = dict()
        self.topics_items["0"] = listtopics
        self.topics_items["1"] = E.get_general_features_options()
        self.topics_items["2"] = E.get_specific_features_options()

        print self.topics_items

        #path to bag file
        self.bag_files = bag_files

        self.selected_bag_topics = []
        self.selected_specific_features = []
        self.selected_general_features = []

        self.items_list_topics = []

        self.area = QScrollArea(self)
        self.areagen = QScrollArea(self)
        self.areaspec = QScrollArea(self)
        self.main_widget = QWidget(self.area)
        self.main_widget1 = QWidget(self.areagen)
        self.main_widget2 = QWidget(self.areaspec)
        self.ok_button = QPushButton("Export To CSV", self)
        #self.ok_button.setFixedSize(150, 30)
        self.ok_button.clicked.connect(self.onButtonClicked)

        self.clear_button = QPushButton("Clear Selection", self)
        # self.clear_button.resize(self.clear_button.sizeHint())
        self.clear_button.clicked.connect(self.onClearClicked)

        self.choose_button = QPushButton("Get Last Export Choose", self)
        self.choose_button.clicked.connect(self.onButtonChooseCliked)
        self.ok_button.setEnabled(False)

        self.label1 = QLabel("Select topic from bag(s)", self)
        self.label1.setAlignment(Qt.AlignCenter)

        self.label2 = QLabel("Statistics Features", self)
        self.label2.setAlignment(Qt.AlignCenter)

        self.label3 = QLabel("Specific Features", self)
        self.label3.setAlignment(Qt.AlignCenter)

        self.duration = duration

        self.label5 = QLabel("Duration Time: " + str("%.1f" % duration), self)
        self.label5.setAlignment(Qt.AlignCenter)

        self.main_vlayout = QVBoxLayout(self)
        # self.main_vlayout = QGridLayout(self)
        self.main_vlayout.addWidget(self.label1)
        self.main_vlayout.addWidget(self.area)
        self.main_vlayout.addWidget(self.label2)
        self.main_vlayout.addWidget(self.areagen)
        self.main_vlayout.addWidget(self.label3)
        self.main_vlayout.addWidget(self.areaspec)

        self.label4 = QLabel("Window time", self)
        self.label4.setAlignment(Qt.AlignCenter)

        # self.main_vlayout.addWidget(self.label4)

        self.window = QLineEdit(self)
        # self.main_vlayout.addWidget(self.window)
        self.window.setText("1")

        self.windows_time_3 = QHBoxLayout(self)

        self.windows_time_3.addWidget(self.label4)

        self.windows_time_3.addWidget(self.window)

        self.windows_time_3.addWidget(self.label5)

        self.main_vlayout.addLayout(self.windows_time_3)

        # self.window = QLineEdit(self)
        # self.window.setText("1")

        # self.box = QVBoxLayout()
        # self.box.addStretch(1)
        # self.box.addWidget(self.clear_button)
        # self.box.addWidget(self.choose_button)
        # self.box.addWidget(self.label4)
        # self.box.addWidget(self.window)
        # self.box.addWidget(self.label5)
        # self.box.addWidget(self.ok_button)

        #self.main_vlayout.addWidget(self.from_nodes_button)

        # self.main_vlayout.addLayout(self.box)

        self.two_buttons = QHBoxLayout(self)

        self.two_buttons.addWidget(self.choose_button)

        self.two_buttons.addWidget(self.clear_button)

        self.main_vlayout.addLayout(self.two_buttons)

        self.main_vlayout.addWidget(self.ok_button)

        self.setLayout(self.main_vlayout)

        self.selection_vlayout = QVBoxLayout(self)
        self.item_all = MyQCheckBox("All", self, self.selection_vlayout, None)
        self.item_all.stateChanged.connect(
            lambda x: self.updateList(x, self.item_all, None))
        self.selection_vlayout.addWidget(self.item_all)
        topic_data_list = listtopics
        topic_data_list.sort()
        for topic in topic_data_list:
            self.addCheckBox(topic, self.selection_vlayout,
                             self.selected_bag_topics)

        self.selection_vlayout1 = QVBoxLayout(self)
        self.item_all1 = MyQCheckBox("All", self, self.selection_vlayout1,
                                     None)
        self.item_all1.stateChanged.connect(
            lambda x: self.updateList(x, self.item_all1, None))
        self.selection_vlayout1.addWidget(self.item_all1)
        topic_data_list1 = E.get_general_features_options()
        topic_data_list1.sort()
        for topic in topic_data_list1:
            self.addCheckBox(topic, self.selection_vlayout1,
                             self.selected_general_features)

        self.selection_vlayout2 = QVBoxLayout(self)
        self.item_all2 = MyQCheckBox("All", self, self.selection_vlayout2,
                                     None)
        self.item_all2.stateChanged.connect(
            lambda x: self.updateList(x, self.item_all2, None))
        self.selection_vlayout2.addWidget(self.item_all2)
        topic_data_list2 = E.get_specific_features_options()
        topic_data_list2.sort()
        for topic in topic_data_list2:
            self.addCheckBox(topic, self.selection_vlayout2,
                             self.selected_specific_features)

        self.main_widget.setLayout(self.selection_vlayout)
        self.main_widget1.setLayout(self.selection_vlayout1)
        self.main_widget2.setLayout(self.selection_vlayout2)

        self.area.setWidget(self.main_widget)
        self.areagen.setWidget(self.main_widget1)
        self.areaspec.setWidget(self.main_widget2)
        self.show()

    def onClearClicked(self):
        self.clearTopicCheckState()

    def clearTopicCheckState(self):
        for item in self.items_list_topics:
            item.setCheckState(False)
        self.item_all.setCheckState(False)
        self.item_all1.setCheckState(False)
        self.item_all2.setCheckState(False)

    def addCheckBox(self, topic, selection_vlayout, selected_list):
        item = MyQCheckBox(topic, self, selection_vlayout, selected_list)
        item.stateChanged.connect(lambda x: self.updateList(x, item, topic))
        self.items_list_topics.append(item)
        selection_vlayout.addWidget(item)

    def changeTopicCheckState(self, topic, state):
        for item in self.items_list_topics:
            if item.text() == topic:
                item.setCheckState(state)
                return

    def updateList(self,
                   state,
                   item_clicked,
                   topic=None,
                   force_update_state=False):
        if topic is None:  # The "All" checkbox was checked / unchecked
            # print "if topic is None"
            if state == Qt.Checked:
                self.item_all.setTristate(False)
                for item in self.items_list_topics:
                    if item.checkState() == Qt.Unchecked and \
                            item.selection_vlayout == item_clicked.selection_vlayout:
                        item.setCheckState(Qt.Checked)
            elif state == Qt.Unchecked:
                self.item_all.setTristate(False)
                for item in self.items_list_topics:
                    if item.checkState() == Qt.Checked and \
                            item.selection_vlayout == item_clicked.selection_vlayout:
                        item.setCheckState(Qt.Unchecked)
        else:
            # print "else:"
            if state == Qt.Checked:
                item_clicked.selected_list.append(topic)
                print item_clicked.selected_list
            else:
                item_clicked.selected_list.remove(topic)
                #if self.item_all.checkState() == Qt.Checked:
                #    self.item_all.setCheckState(Qt.PartiallyChecked)

        if self.selected_specific_features != []:
            if self.selected_general_features != [] and self.selected_bag_topics != []:
                self.ok_button.setEnabled(True)
            elif self.selected_general_features == [] and self.selected_bag_topics == []:
                self.ok_button.setEnabled(True)
            else:
                self.ok_button.setEnabled(False)
        else:
            if self.selected_general_features != [] and self.selected_bag_topics != []:
                self.ok_button.setEnabled(True)
            else:
                self.ok_button.setEnabled(False)

        # if self.selected_bag_topics != []:
        #     if self.selected_specific_features == [] and self.selected_general_features == []:
        #         self.ok_button.setEnabled(False)
        #     else:
        #         self.ok_button.setEnabled(True)
        #     # elif self.selected_specific_features != [] and self.selected_general_features == []:
        #     #     self.ok_button.setEnabled(True)
        #     # elif self.selected_specific_features == [] and self.selected_general_features != []:
        #     #     self.ok_button.setEnabled(True)
        # else:
        #     self.ok_button.setEnabled(False)

        # if self.selected_specific_features != []:
        #     if self.selected_bag_topics == [] and self.selected_general_features == []:
        #         self.ok_button.setEnabled(True)
        #     elif self.selected_bag_topics != [] and self.selected_general_features != []:
        #         self.ok_button.setEnabled(True)
        #     else:
        #         self.ok_button.setEnabled(False)
        # else:
        #     if self.selected_bag_topics == [] or self.selected_general_features == []:
        #         self.ok_button.setEnabled(False)
        #     else:
        #         self.ok_button.setEnabled(True)

    def onButtonChooseCliked(self):
        for checkbox in self.items_list_topics:
            checkbox.setCheckState(Qt.Unchecked)
        with open(get_path() + "logger.log", 'r') as f:
            topics = f.read().splitlines()
        for checkbox in self.items_list_topics:
            if checkbox.text() in topics:
                checkbox.setCheckState(Qt.Checked)

    def get_current_opened_directory(self, filepath):
        import os
        direc = "/"
        if os.path.isfile(filepath):
            with open(filepath, 'r') as f:
                direc = f.read()
        return direc

    def onButtonClicked(self):
        import inspect, os
        filepath = os.path.dirname(
            os.path.abspath(inspect.getfile(
                inspect.currentframe()))) + "/log/save_csv.log"
        current_directory = self.get_current_opened_directory(filepath)
        window = self.window.text()
        try:
            val = float(window)
        except ValueError:
            QMessageBox.about(self, "Error in Window Time",
                              "That's not a number!")
            return
        if val >= self.duration:
            QMessageBox.about(
                self, "Error in Window Time",
                "time need to be smaller than: " + str(self.duration))
            return
        # filename = QFileDialog.getSaveFileName(self, self.tr('csv File'), current_directory, self.tr('csv (*.csv)'))
        saved_dir = str(
            QFileDialog.getExistingDirectory(self, "Select Directory",
                                             current_directory))
        # if filename[0] != '':
        #     with open(filepath, "w") as f:
        #         f.write(filename[0])
        if saved_dir != '':
            with open(filepath, "w") as f:
                f.write(saved_dir)
            topics = self.selected_bag_topics
            specific_features_selection = self.selected_specific_features
            general_features_selection = self.selected_general_features
            with open(get_path() + 'logger.log', "w") as f:
                for topic in topics:
                    f.write(topic + "\n")
                for topic1 in specific_features_selection:
                    f.write(topic1 + "\n")
                for topic2 in general_features_selection:
                    f.write(topic2 + "\n")
            ef = E.ExtractFeatures(topics, float(window),
                                   specific_features_selection,
                                   general_features_selection)
            counter = 0
            for bag_file in self.bag_files:
                df = ef.generate_features(bag_file)
                if len(self.bag_files) == 1:
                    counter = -1
                # temp = filename + "/" +
                # temp = get_corrent_file_name(filename[0], ".csv", counter)
                csv_path = generate_csv_from_bag(saved_dir, bag_file)
                # temp = "%s_%s%s" % (filename[0],counter,".csv")
                E.write_to_csv(csv_path, df)
                counter = counter + 1
            QMessageBox.about(self, "csv export",
                              "csv was exported successfuly")
Exemple #33
0
    def __init__(self, title, jsp, num_rows=0):
        super(JointStatePublisherGui, self).__init__()
        font = QFont("Helvetica", 9, QFont.Bold)
        self.hlayout = QHBoxLayout(self)
        vlayout = QVBoxLayout()
        glayout = QGridLayout()
        right_l_lauout = QVBoxLayout()
        self.listVeiw = QListWidget()
        self.checkbox = []
        self.value_line_edit = []
        self.sliders = []
        self.positions = []
        self.progressbars = []

        self.value_last = []

        speed_max = enviromnt_conf['joint_speed']
        slider_max = speed_max * 1000

        position_max = enviromnt_conf['joint_max_position']
        progress_max = position_max * 1000

        #create joints widget
        for i in range(0, num_rows):
            if config[i][0]:
                g_in_g = QGridLayout()
                checkbox = QCheckBox(config[i][1])
                checkbox.setFont(font)

                self.checkbox.append(checkbox)

                value_line_edit = QLineEdit()
                value_line_edit.setFont(font)
                value_line_edit.setText("0.0")

                self.value_line_edit.append(value_line_edit)

                display_lable = QLabel()
                display_lable.setFont(font)
                display_lable.setText("Position:")

                position_label = QLabel()
                position_label.setFont(font)
                position_label.setText("0.0")

                self.positions.append(position_label)

                position_progress_bar = QProgressBar()
                position_progress_bar.setMaximum(progress_max)
                position_progress_bar.setMinimum(-progress_max)
                position_progress_bar.setValue(0)

                self.progressbars.append(position_progress_bar)

                slider = QSlider()
                slider.setMaximum(slider_max)
                slider.setMinimum(-slider_max)
                slider.setOrientation(Qt.Horizontal)
                slider.valueChanged.connect(self.slider_value_changed)
                self.sliders.append(slider)

                g_in_g.addWidget(checkbox, 0, 0)
                g_in_g.addWidget(value_line_edit, 0, 1)
                g_in_g.addWidget(display_lable, 0, 2)
                g_in_g.addWidget(position_label, 0, 3)
                g_in_g.addWidget(slider, 1, 0, 1, 2)
                g_in_g.addWidget(position_progress_bar, 1, 2, 1, 2)

                glayout.addLayout(g_in_g, i, 0)

        #create v layout
        self.import_Btn = QPushButton('Import')
        self.import_Btn.setFont(font)
        self.import_Btn.clicked.connect(self.import_Btn_clecked)

        self.export_Btn = QPushButton('Export')
        self.export_Btn.setFont(font)
        self.export_Btn.clicked.connect(self.export_Btn_clicked)

        self.start_Btn = QPushButton("Start")
        self.start_Btn.setFont(font)
        self.start_Btn.clicked.connect(self.start_Btn_clicked)

        self.reset_Btn = QPushButton('Reset')
        self.reset_Btn.setFont(font)
        self.reset_Btn.clicked.connect(self.reset_Btn_clicked)

        self.record_Btn = QPushButton('Record')
        self.record_Btn.setFont(font)
        self.record_Btn.clicked.connect(self.record_Btn_clicked)

        self.replay_Btn = QPushButton('Repaly')
        self.replay_Btn.setFont(font)
        self.replay_Btn.clicked.connect(self.replay_Btn_clicked)

        self.delete_Btn = QPushButton("Delete")
        self.delete_Btn.setFont(font)
        self.delete_Btn.clicked.connect(self.delete_Btn_clicked)

        self.debug_Btn = QPushButton("Debug")
        self.debug_Btn.setFont(font)
        self.debug_Btn.clicked.connect(self.debug_Btn_clicked)

        vlayout.addWidget(self.import_Btn)
        vlayout.addWidget(self.export_Btn)
        vlayout.addWidget(self.start_Btn)
        vlayout.addWidget(self.reset_Btn)
        vlayout.addWidget(self.record_Btn)
        vlayout.addWidget(self.delete_Btn)
        vlayout.addWidget(self.replay_Btn)
        vlayout.addWidget(self.debug_Btn)

        self.master_url = QLineEdit("http://192.168.0.91:11311")
        self.master_url.setFont(font)

        self.master_ip = QLineEdit("192.168.0.91")
        self.master_ip.setFont(font)

        self.listVeiw.clicked.connect(self.listVeiw_clicked)
        self.listVeiw.currentRowChanged.connect(
            self.listVeiw_itemSelectionChanged)

        self.description = QTextEdit("")
        self.description.setFont(font)

        #self.description.setGeometry(0,100,100,500)

        right_l_lauout.addWidget(self.master_url)
        right_l_lauout.addWidget(self.master_ip)
        right_l_lauout.addWidget(self.listVeiw)
        right_l_lauout.addWidget(self.description)

        right_l_lauout.setStretch(0, 1)
        right_l_lauout.setStretch(1, 1)
        right_l_lauout.setStretch(2, 3)
        right_l_lauout.setStretch(3, 1)

        self.num_rows = len(self.checkbox)
        self.hlayout.addLayout(glayout)
        self.hlayout.addLayout(vlayout)
        self.hlayout.addLayout(right_l_lauout)
        self.setLayout(self.hlayout)

        self.callback_start = None
        self.callback_pause = None
        self.callback_record = None
        self.callback_reset = None
        self.callback_replay = None
        self.callback_replay_stop = None
        self.callback_delete = None
        self.callback_debug = None
        self.callback_import = None
        self.callback_export = None
        self.callback_list_clicked = None

        self.listVeiw_isClicked = False
        self.listVeiw_current_item = 0
        self.listVeiw_len = 0
        self.f = QFileDialog()
Exemple #34
0
class JointStatePublisherGui(QWidget):
    def __init__(self, title, jsp, num_rows=0):
        super(JointStatePublisherGui, self).__init__()
        font = QFont("Helvetica", 9, QFont.Bold)
        self.hlayout = QHBoxLayout(self)
        vlayout = QVBoxLayout()
        glayout = QGridLayout()
        right_l_lauout = QVBoxLayout()
        self.listVeiw = QListWidget()
        self.checkbox = []
        self.value_line_edit = []
        self.sliders = []
        self.positions = []
        self.progressbars = []

        self.value_last = []

        speed_max = enviromnt_conf['joint_speed']
        slider_max = speed_max * 1000

        position_max = enviromnt_conf['joint_max_position']
        progress_max = position_max * 1000

        #create joints widget
        for i in range(0, num_rows):
            if config[i][0]:
                g_in_g = QGridLayout()
                checkbox = QCheckBox(config[i][1])
                checkbox.setFont(font)

                self.checkbox.append(checkbox)

                value_line_edit = QLineEdit()
                value_line_edit.setFont(font)
                value_line_edit.setText("0.0")

                self.value_line_edit.append(value_line_edit)

                display_lable = QLabel()
                display_lable.setFont(font)
                display_lable.setText("Position:")

                position_label = QLabel()
                position_label.setFont(font)
                position_label.setText("0.0")

                self.positions.append(position_label)

                position_progress_bar = QProgressBar()
                position_progress_bar.setMaximum(progress_max)
                position_progress_bar.setMinimum(-progress_max)
                position_progress_bar.setValue(0)

                self.progressbars.append(position_progress_bar)

                slider = QSlider()
                slider.setMaximum(slider_max)
                slider.setMinimum(-slider_max)
                slider.setOrientation(Qt.Horizontal)
                slider.valueChanged.connect(self.slider_value_changed)
                self.sliders.append(slider)

                g_in_g.addWidget(checkbox, 0, 0)
                g_in_g.addWidget(value_line_edit, 0, 1)
                g_in_g.addWidget(display_lable, 0, 2)
                g_in_g.addWidget(position_label, 0, 3)
                g_in_g.addWidget(slider, 1, 0, 1, 2)
                g_in_g.addWidget(position_progress_bar, 1, 2, 1, 2)

                glayout.addLayout(g_in_g, i, 0)

        #create v layout
        self.import_Btn = QPushButton('Import')
        self.import_Btn.setFont(font)
        self.import_Btn.clicked.connect(self.import_Btn_clecked)

        self.export_Btn = QPushButton('Export')
        self.export_Btn.setFont(font)
        self.export_Btn.clicked.connect(self.export_Btn_clicked)

        self.start_Btn = QPushButton("Start")
        self.start_Btn.setFont(font)
        self.start_Btn.clicked.connect(self.start_Btn_clicked)

        self.reset_Btn = QPushButton('Reset')
        self.reset_Btn.setFont(font)
        self.reset_Btn.clicked.connect(self.reset_Btn_clicked)

        self.record_Btn = QPushButton('Record')
        self.record_Btn.setFont(font)
        self.record_Btn.clicked.connect(self.record_Btn_clicked)

        self.replay_Btn = QPushButton('Repaly')
        self.replay_Btn.setFont(font)
        self.replay_Btn.clicked.connect(self.replay_Btn_clicked)

        self.delete_Btn = QPushButton("Delete")
        self.delete_Btn.setFont(font)
        self.delete_Btn.clicked.connect(self.delete_Btn_clicked)

        self.debug_Btn = QPushButton("Debug")
        self.debug_Btn.setFont(font)
        self.debug_Btn.clicked.connect(self.debug_Btn_clicked)

        vlayout.addWidget(self.import_Btn)
        vlayout.addWidget(self.export_Btn)
        vlayout.addWidget(self.start_Btn)
        vlayout.addWidget(self.reset_Btn)
        vlayout.addWidget(self.record_Btn)
        vlayout.addWidget(self.delete_Btn)
        vlayout.addWidget(self.replay_Btn)
        vlayout.addWidget(self.debug_Btn)

        self.master_url = QLineEdit("http://192.168.0.91:11311")
        self.master_url.setFont(font)

        self.master_ip = QLineEdit("192.168.0.91")
        self.master_ip.setFont(font)

        self.listVeiw.clicked.connect(self.listVeiw_clicked)
        self.listVeiw.currentRowChanged.connect(
            self.listVeiw_itemSelectionChanged)

        self.description = QTextEdit("")
        self.description.setFont(font)

        #self.description.setGeometry(0,100,100,500)

        right_l_lauout.addWidget(self.master_url)
        right_l_lauout.addWidget(self.master_ip)
        right_l_lauout.addWidget(self.listVeiw)
        right_l_lauout.addWidget(self.description)

        right_l_lauout.setStretch(0, 1)
        right_l_lauout.setStretch(1, 1)
        right_l_lauout.setStretch(2, 3)
        right_l_lauout.setStretch(3, 1)

        self.num_rows = len(self.checkbox)
        self.hlayout.addLayout(glayout)
        self.hlayout.addLayout(vlayout)
        self.hlayout.addLayout(right_l_lauout)
        self.setLayout(self.hlayout)

        self.callback_start = None
        self.callback_pause = None
        self.callback_record = None
        self.callback_reset = None
        self.callback_replay = None
        self.callback_replay_stop = None
        self.callback_delete = None
        self.callback_debug = None
        self.callback_import = None
        self.callback_export = None
        self.callback_list_clicked = None

        self.listVeiw_isClicked = False
        self.listVeiw_current_item = 0
        self.listVeiw_len = 0
        self.f = QFileDialog()

    def who_data_changed(self):
        for i in range(0, self.num_rows):
            value_last = self.value_line_edit[i].text()
            value_last = float(value_last) * 1000
            value = self.sliders[i].value()
            if value != value_last:
                return i

    def change_line_edit(self, change_index):
        value = self.sliders[change_index].value()
        value = float(value) / 1000
        value = str(value)
        self.value_line_edit[change_index].setText(value)

    def change_position_edit(self, change_index):
        value = self.progressbars[change_index].value()
        value += self.sliders[change_index].value()
        self.progressbars[change_index].setValue(value)

        self.positions[change_index].setText(str(float(value) / 1000))

    def reset_speed(self, change_index):
        self.sliders[change_index].setValue(0)

    def reset_speed_all(self):
        for i in range(0, self.num_rows):
            self.reset_speed(i)

    def set_speed(self, index, data):
        self.sliders[index].setValue(data)

    def import_Btn_clecked(self):
        self.file_path = self.f.getOpenFileName(caption='Import excel data',
                                                directory='',
                                                filter='*.xlsx',
                                                initialFilter='')
        self.file_path = self.file_path[0]
        if self.callback_import:
            self.callback_import()
        pass

    def export_Btn_clicked(self):
        self.file_path = self.f.getSaveFileName(caption='Save as excel data',
                                                directory='',
                                                filter='*.xlsx',
                                                initialFilter='')
        self.file_path = self.file_path[0]
        if self.callback_export:
            self.callback_export()
        pass

    def set_callback_start(self, func):
        self.callback_start = func

    def start_Btn_clicked(self):
        if self.start_Btn.text() == "Start":
            if self.callback_start:
                self.callback_start()
            self.start_Btn.setText("Pause")
        else:
            if self.callback_pause:
                self.callback_pause()
            self.start_Btn.setText("Start")

    def reset_Btn_clicked(self):
        self.reset_speed_all()
        self.reset_postion_all()

        if self.callback_reset:
            self.callback_reset()

    def replay_Btn_clicked(self):
        if self.replay_Btn.text() == "Replay":
            self.replay_Btn.setText("Stop")
            if self.callback_replay:
                self.callback_replay()
        else:
            self.replay_Btn.setText("Replay")
            if self.callback_replay_stop:
                self.callback_replay_stop()

    def debug_Btn_clicked(self):
        if self.callback_debug:
            self.callback_debug()

    def record_Btn_clicked(self):
        self.set_postion()
        self.listVeiw_len += 1
        if self.callback_record:
            self.callback_record()
        self.reset_speed_all()

    def listVeiw_itemSelectionChanged(self, index):
        self.listVeiw_isClicked = True
        self.listVeiw_current_item = index
        if self.callback_list_clicked:
            self.callback_list_clicked()

    def listVeiw_clicked(self, index):
        #print "index", index.row()
        if self.listVeiw_current_item != index.row():
            description_text = self.description.toPlainText()
            #self.listVeiw.item(self.listVeiw_current_item).setData(1,"123")
            #print self.listVeiw.item(self.listVeiw_current_item).data
        self.listVeiw_isClicked = True
        self.listVeiw_current_item = index.row()
        if self.callback_list_clicked:
            self.callback_list_clicked()

    def update_listView(self):
        print "update", self.listVeiw_len
        for i in range(0, self.listVeiw_len):
            view = self.listVeiw.item(i)
            view.setText(str(i))

    def get_listVeiw_current_item(self):
        return self.listVeiw_current_item

    def delete_Btn_clicked(self):
        if self.listVeiw_isClicked:
            print self.listVeiw_current_item
            self.listVeiw.removeItemWidget(
                self.listVeiw.takeItem(self.listVeiw_current_item))
            self.listVeiw_len -= 1
            if self.listVeiw_current_item != self.listVeiw_len:
                self.update_listView()
            if self.callback_delete:
                self.callback_delete()
            if self.listVeiw_current_item == 0:
                self.listVeiw_current_item = 0
            else:
                self.listVeiw_current_item -= 1

            self.listVeiw.setCurrentRow(self.listVeiw_current_item)
            if self.listVeiw_len == 0:
                self.listVeiw_isClicked = False

    def listView_add_item(self, index):
        self.listVeiw.addItem(str(index))

    def listView_inset_item(self, index, label):
        self.listVeiw.insertItem(index, str(label))

    def slider_value_changed(self, data):
        change_index = self.who_data_changed()
        self.change_line_edit(change_index)

    def get_speed(self):
        speed = []
        for i in range(0, self.num_rows):
            value = self.sliders[i].value()
            value = float(value) / 1000
            speed.append(value)
        return speed

    def get_position(self):
        position = []
        for i in range(0, self.num_rows):
            value = self.progressbars[i].value()
            value += self.sliders[i].value()
            value = float(value) / 1000
            position.append(value)
        return position

    def set_postion(self):
        for i in range(0, self.num_rows):
            self.change_position_edit(i)

    def set_positions(self, data):
        print len(data)
        for i in range(0, len(data)):
            self.progressbars[i].setValue(data[i] * 1000)
            self.positions[i].setText(str(data[i]))

    def reset_position(self, change_index):
        value = 0
        self.progressbars[change_index].setValue(value)

        self.positions[change_index].setText(str(float(value) / 1000))

    def reset_postion_all(self):
        for i in range(0, self.num_rows):
            self.reset_position(i)
    def __init__(self, updater, config, nodename):
        '''
        :param config:
        :type config: Dictionary? defined in dynamic_reconfigure.client.Client
        :type nodename: str
        '''

        super(GroupWidget, self).__init__()
        self.state = config['state']
        self.param_name = config['name']
        self._toplevel_treenode_name = nodename

        # TODO: .ui file needs to be back into usage in later phase.
#        ui_file = os.path.join(rp.get_path('rqt_reconfigure'),
#                               'resource', 'singlenode_parameditor.ui')
#        loadUi(ui_file, self)

        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(QMargins(0, 0, 0, 0))

        _widget_nodeheader = QWidget()
        _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader)
        _h_layout_nodeheader.setContentsMargins(QMargins(0, 0, 0, 0))

        self.nodename_qlabel = QLabel(self)
        font = QFont('Trebuchet MS, Bold')
        font.setUnderline(True)
        font.setBold(True)

        # Button to close a node.
        _icon_disable_node = QIcon.fromTheme('window-close')
        _bt_disable_node = QPushButton(_icon_disable_node, '', self)
        _bt_disable_node.setToolTip('Hide this node')
        _bt_disable_node_size = QSize(36, 24)
        _bt_disable_node.setFixedSize(_bt_disable_node_size)
        _bt_disable_node.pressed.connect(self._node_disable_bt_clicked)

        _h_layout_nodeheader.addWidget(self.nodename_qlabel)
        _h_layout_nodeheader.addWidget(_bt_disable_node)

        self.nodename_qlabel.setAlignment(Qt.AlignCenter)
        font.setPointSize(10)
        self.nodename_qlabel.setFont(font)
        grid_widget = QWidget(self)
        self.grid = QFormLayout(grid_widget)
        verticalLayout.addWidget(_widget_nodeheader)
        verticalLayout.addWidget(grid_widget, 1)
        # Again, these UI operation above needs to happen in .ui file.

        self.tab_bar = None  # Every group can have one tab bar
        self.tab_bar_shown = False

        self.updater = updater

        self.editor_widgets = []
        self._param_names = []

        self._create_node_widgets(config)

        rospy.logdebug('Groups node name={}'.format(nodename))
        self.nodename_qlabel.setText(nodename)
    def __init__(self, title, jsp, num_rows=0):
        super(JointStatePublisherGui, self).__init__()
        self.jsp = jsp
        self.joint_map = {}
        self.vlayout = QVBoxLayout(self)
        self.gridlayout = QGridLayout()
        font = QFont("Helvetica", 9, QFont.Bold)

        ### Generate sliders ###
        sliders = []
        for name in self.jsp.joint_list:
            if name not in self.jsp.free_joints:
                continue
            joint = self.jsp.free_joints[name]

            if joint['min'] == joint['max']:
                continue

            joint_layout = QVBoxLayout()
            row_layout = QHBoxLayout()

            label = QLabel(name)
            label.setFont(font)
            row_layout.addWidget(label)
            display = QLineEdit("0.00")
            display.setAlignment(Qt.AlignRight)
            display.setFont(font)
            display.setReadOnly(True)
            row_layout.addWidget(display)

            joint_layout.addLayout(row_layout)

            slider = QSlider(Qt.Horizontal)

            slider.setFont(font)
            slider.setRange(0, RANGE)
            slider.setValue(RANGE/2)

            joint_layout.addWidget(slider)

            self.joint_map[name] = {'slidervalue': 0, 'display': display,
                                    'slider': slider, 'joint': joint}
            # Connect to the signal provided by QSignal
            slider.valueChanged.connect(self.onValueChanged)
            sliders.append(joint_layout)

        # Determine number of rows to be used in grid
        self.num_rows = num_rows
        # if desired num of rows wasn't set, default behaviour is a vertical layout
        if self.num_rows == 0:
            self.num_rows = len(sliders)  # equals VBoxLayout
        # Generate positions in grid and place sliders there
        self.positions = self.generate_grid_positions(len(sliders), self.num_rows)
        for item, pos in zip(sliders, self.positions):
            self.gridlayout.addLayout(item, *pos)

        # Set zero positions read from parameters
        self.center()

        # Synchronize slider and displayed value
        self.sliderUpdate(None)

        # Set up a signal for updating the sliders based on external joint info
        self.sliderUpdateTrigger.connect(self.updateSliders)

        self.vlayout.addLayout(self.gridlayout)

        # Buttons for randomizing and centering sliders and
        # Spinbox for on-the-fly selecting number of rows
        self.randbutton = QPushButton('Randomize', self)
        self.randbutton.clicked.connect(self.randomize_event)
        self.vlayout.addWidget(self.randbutton)
        self.ctrbutton = QPushButton('Center', self)
        self.ctrbutton.clicked.connect(self.center_event)
        self.vlayout.addWidget(self.ctrbutton)
        self.maxrowsupdown = QSpinBox()
        self.maxrowsupdown.setMinimum(1)
        self.maxrowsupdown.setMaximum(len(sliders))
        self.maxrowsupdown.setValue(self.num_rows)
        self.maxrowsupdown.lineEdit().setReadOnly(True)  # don't edit it by hand to avoid weird resizing of window
        self.maxrowsupdown.valueChanged.connect(self.reorggrid_event)
        self.vlayout.addWidget(self.maxrowsupdown)
Exemple #37
0
    def __init__(self, bag_files, listtopics, duration):
        super(BagParser, self).__init__()

        # window title
        self.setWindowTitle("Making csv file")
        # size of window
        self.resize(960, 720)
        #self.showFullScreen()
        #self.setWindowState(Qt.WindowMaximized)

        # print listtopics
        # print E.get_general_features_options()
        # print E.get_specific_features_options()

        self.topics_items = dict()
        self.topics_items["0"] = listtopics
        self.topics_items["1"] = E.get_general_features_options()
        self.topics_items["2"] = E.get_specific_features_options()

        print self.topics_items

        #path to bag file
        self.bag_files = bag_files

        self.selected_bag_topics = []
        self.selected_specific_features = []
        self.selected_general_features = []

        self.items_list_topics = []

        self.area = QScrollArea(self)
        self.areagen = QScrollArea(self)
        self.areaspec = QScrollArea(self)
        self.main_widget = QWidget(self.area)
        self.main_widget1 = QWidget(self.areagen)
        self.main_widget2 = QWidget(self.areaspec)
        self.ok_button = QPushButton("Export To CSV", self)
        #self.ok_button.setFixedSize(150, 30)
        self.ok_button.clicked.connect(self.onButtonClicked)

        self.clear_button = QPushButton("Clear Selection", self)
        # self.clear_button.resize(self.clear_button.sizeHint())
        self.clear_button.clicked.connect(self.onClearClicked)

        self.choose_button = QPushButton("Get Last Export Choose", self)
        self.choose_button.clicked.connect(self.onButtonChooseCliked)
        self.ok_button.setEnabled(False)

        self.label1 = QLabel("Select topic from bag(s)", self)
        self.label1.setAlignment(Qt.AlignCenter)

        self.label2 = QLabel("Statistics Features", self)
        self.label2.setAlignment(Qt.AlignCenter)

        self.label3 = QLabel("Specific Features", self)
        self.label3.setAlignment(Qt.AlignCenter)

        self.duration = duration

        self.label5 = QLabel("Duration Time: " + str("%.1f" % duration), self)
        self.label5.setAlignment(Qt.AlignCenter)

        self.main_vlayout = QVBoxLayout(self)
        # self.main_vlayout = QGridLayout(self)
        self.main_vlayout.addWidget(self.label1)
        self.main_vlayout.addWidget(self.area)
        self.main_vlayout.addWidget(self.label2)
        self.main_vlayout.addWidget(self.areagen)
        self.main_vlayout.addWidget(self.label3)
        self.main_vlayout.addWidget(self.areaspec)

        self.label4 = QLabel("Window time", self)
        self.label4.setAlignment(Qt.AlignCenter)

        # self.main_vlayout.addWidget(self.label4)

        self.window = QLineEdit(self)
        # self.main_vlayout.addWidget(self.window)
        self.window.setText("1")

        self.windows_time_3 = QHBoxLayout(self)

        self.windows_time_3.addWidget(self.label4)

        self.windows_time_3.addWidget(self.window)

        self.windows_time_3.addWidget(self.label5)

        self.main_vlayout.addLayout(self.windows_time_3)

        # self.window = QLineEdit(self)
        # self.window.setText("1")

        # self.box = QVBoxLayout()
        # self.box.addStretch(1)
        # self.box.addWidget(self.clear_button)
        # self.box.addWidget(self.choose_button)
        # self.box.addWidget(self.label4)
        # self.box.addWidget(self.window)
        # self.box.addWidget(self.label5)
        # self.box.addWidget(self.ok_button)

        #self.main_vlayout.addWidget(self.from_nodes_button)

        # self.main_vlayout.addLayout(self.box)

        self.two_buttons = QHBoxLayout(self)

        self.two_buttons.addWidget(self.choose_button)

        self.two_buttons.addWidget(self.clear_button)

        self.main_vlayout.addLayout(self.two_buttons)

        self.main_vlayout.addWidget(self.ok_button)

        self.setLayout(self.main_vlayout)

        self.selection_vlayout = QVBoxLayout(self)
        self.item_all = MyQCheckBox("All", self, self.selection_vlayout, None)
        self.item_all.stateChanged.connect(
            lambda x: self.updateList(x, self.item_all, None))
        self.selection_vlayout.addWidget(self.item_all)
        topic_data_list = listtopics
        topic_data_list.sort()
        for topic in topic_data_list:
            self.addCheckBox(topic, self.selection_vlayout,
                             self.selected_bag_topics)

        self.selection_vlayout1 = QVBoxLayout(self)
        self.item_all1 = MyQCheckBox("All", self, self.selection_vlayout1,
                                     None)
        self.item_all1.stateChanged.connect(
            lambda x: self.updateList(x, self.item_all1, None))
        self.selection_vlayout1.addWidget(self.item_all1)
        topic_data_list1 = E.get_general_features_options()
        topic_data_list1.sort()
        for topic in topic_data_list1:
            self.addCheckBox(topic, self.selection_vlayout1,
                             self.selected_general_features)

        self.selection_vlayout2 = QVBoxLayout(self)
        self.item_all2 = MyQCheckBox("All", self, self.selection_vlayout2,
                                     None)
        self.item_all2.stateChanged.connect(
            lambda x: self.updateList(x, self.item_all2, None))
        self.selection_vlayout2.addWidget(self.item_all2)
        topic_data_list2 = E.get_specific_features_options()
        topic_data_list2.sort()
        for topic in topic_data_list2:
            self.addCheckBox(topic, self.selection_vlayout2,
                             self.selected_specific_features)

        self.main_widget.setLayout(self.selection_vlayout)
        self.main_widget1.setLayout(self.selection_vlayout1)
        self.main_widget2.setLayout(self.selection_vlayout2)

        self.area.setWidget(self.main_widget)
        self.areagen.setWidget(self.main_widget1)
        self.areaspec.setWidget(self.main_widget2)
        self.show()
    def __init__(self, context, node=None):
        """
        This class is intended to be called by rqt plugin framework class.
        Currently (12/12/2012) the whole widget is splitted into 2 panes:
        one on left allows you to choose the node(s) you work on. Right side
        pane lets you work with the parameters associated with the node(s) you
        select on the left.

        (12/27/2012) Despite the pkg name is changed to rqt_reconfigure to
        reflect the available functionality, file & class names remain
        'param', expecting all the parameters will become handle-able.
        """

        super(ParamWidget, self).__init__()
        self.setObjectName(self._TITLE_PLUGIN)
        self.setWindowTitle(self._TITLE_PLUGIN)

        rp = rospkg.RosPack()

        #TODO: .ui file needs to replace the GUI components declaration
        #            below. For unknown reason, referring to another .ui files
        #            from a .ui that is used in this class failed. So for now,
        #            I decided not use .ui in this class.
        #            If someone can tackle this I'd appreciate.
        _hlayout_top = QHBoxLayout(self)
        _hlayout_top.setContentsMargins(QMargins(0, 0, 0, 0))
        self._splitter = QSplitter(self)
        _hlayout_top.addWidget(self._splitter)

        _vlayout_nodesel_widget = QWidget()
        _vlayout_nodesel_side = QVBoxLayout()
        _hlayout_filter_widget = QWidget(self)
        _hlayout_filter = QHBoxLayout()
        self._text_filter = TextFilter()
        self.filter_lineedit = TextFilterWidget(self._text_filter, rp)
        self.filterkey_label = QLabel("&Filter key:")
        self.filterkey_label.setBuddy(self.filter_lineedit)
        _hlayout_filter.addWidget(self.filterkey_label)
        _hlayout_filter.addWidget(self.filter_lineedit)
        _hlayout_filter_widget.setLayout(_hlayout_filter)
        self._nodesel_widget = NodeSelectorWidget(self, rp, self.sig_sysmsg)
        _vlayout_nodesel_side.addWidget(_hlayout_filter_widget)
        _vlayout_nodesel_side.addWidget(self._nodesel_widget)
        _vlayout_nodesel_side.setSpacing(1)
        _vlayout_nodesel_widget.setLayout(_vlayout_nodesel_side)

        reconf_widget = ParameditWidget(rp)

        self._splitter.insertWidget(0, _vlayout_nodesel_widget)
        self._splitter.insertWidget(1, reconf_widget)
        # 1st column, _vlayout_nodesel_widget, to minimize width.
        # 2nd col to keep the possible max width.
        self._splitter.setStretchFactor(0, 0)
        self._splitter.setStretchFactor(1, 1)

        # Signal from paramedit widget to node selector widget.
        reconf_widget.sig_node_disabled_selected.connect(
                                       self._nodesel_widget.node_deselected)
        # Pass name of node to editor widget
        self._nodesel_widget.sig_node_selected.connect(
                                                     reconf_widget.show_reconf)

        if not node:
            title = self._TITLE_PLUGIN
        else:
            title = self._TITLE_PLUGIN + ' %s' % node
        self.setObjectName(title)

        #Connect filter signal-slots.
        self._text_filter.filter_changed_signal.connect(
                                            self._filter_key_changed)

        # Open any clients indicated from command line
        self.sig_selected.connect(self._nodesel_widget.node_selected)
        for rn in [rospy.resolve_name(c) for c in context.argv()]:
            if rn in self._nodesel_widget.get_paramitems():
                self.sig_selected.emit(rn)
            else:
                rospy.logwarn('Could not find a dynamic reconfigure client named \'%s\'', str(rn))
Exemple #39
0
    def __init__(self, title, jsp, num_rows=0):
        super(JointStatePublisherGui, self).__init__()
        self.jsp = jsp
        self.joint_map = {}
        self.vlayout = QVBoxLayout(self)
        self.scrollable = QWidget()
        self.gridlayout = QGridLayout()
        self.scroll = QScrollArea()
        self.scroll.setWidgetResizable(True)

        font = QFont("Helvetica", 9, QFont.Bold)

        ### Generate sliders ###
        sliders = []
        for name in self.jsp.joint_list:
            if name not in self.jsp.free_joints:
                continue
            joint = self.jsp.free_joints[name]

            if joint['min'] == joint['max']:
                continue

            joint_layout = QVBoxLayout()
            row_layout = QHBoxLayout()

            label = QLabel(name)
            label.setFont(font)
            row_layout.addWidget(label)
            display = QLineEdit("0.00")
            display.setAlignment(Qt.AlignRight)
            display.setFont(font)
            display.setReadOnly(True)
            row_layout.addWidget(display)

            joint_layout.addLayout(row_layout)

            slider = QSlider(Qt.Horizontal)

            slider.setFont(font)
            slider.setRange(0, RANGE)
            slider.setValue(RANGE / 2)

            joint_layout.addWidget(slider)

            self.joint_map[name] = {
                'slidervalue': 0,
                'display': display,
                'slider': slider,
                'joint': joint
            }
            # Connect to the signal provided by QSignal
            slider.valueChanged.connect(
                lambda event, name=name: self.onValueChangedOne(name))

            sliders.append(joint_layout)

        # Determine number of rows to be used in grid
        self.num_rows = num_rows
        # if desired num of rows wasn't set, default behaviour is a vertical layout
        if self.num_rows == 0:
            self.num_rows = len(sliders)  # equals VBoxLayout
        # Generate positions in grid and place sliders there
        self.positions = self.generate_grid_positions(len(sliders),
                                                      self.num_rows)
        for item, pos in zip(sliders, self.positions):
            self.gridlayout.addLayout(item, *pos)

        # Set zero positions read from parameters
        self.center()

        # Synchronize slider and displayed value
        self.sliderUpdate(None)

        # Set up a signal for updating the sliders based on external joint info
        self.sliderUpdateTrigger.connect(self.updateSliders)

        self.scrollable.setLayout(self.gridlayout)
        self.scroll.setWidget(self.scrollable)
        self.vlayout.addWidget(self.scroll)

        # Buttons for randomizing and centering sliders and
        # Spinbox for on-the-fly selecting number of rows
        self.randbutton = QPushButton('Randomize', self)
        self.randbutton.clicked.connect(self.randomize_event)
        self.vlayout.addWidget(self.randbutton)
        self.ctrbutton = QPushButton('Center', self)
        self.ctrbutton.clicked.connect(self.center_event)
        self.vlayout.addWidget(self.ctrbutton)
        self.maxrowsupdown = QSpinBox()
        self.maxrowsupdown.setMinimum(1)
        self.maxrowsupdown.setMaximum(len(sliders))
        self.maxrowsupdown.setValue(self.num_rows)
        self.maxrowsupdown.valueChanged.connect(self.reorggrid_event)
        self.vlayout.addWidget(self.maxrowsupdown)
        self.setLayout(self.vlayout)
class DynreconfClientWidget(GroupWidget):
    """
    A wrapper of dynamic_reconfigure.client instance.
    Represents a widget where users can view and modify ROS params.
    """

    def __init__(self, reconf, node_name):
        """
        :type reconf: dynamic_reconfigure.client
        :type node_name: str
        """

        group_desc = reconf.get_group_descriptions()
        rospy.logdebug('DynreconfClientWidget.group_desc=%s', group_desc)
        super(DynreconfClientWidget, self).__init__(ParamUpdater(reconf),
                                                    group_desc, node_name)

        # Save and load buttons
        self.button_widget = QWidget(self)
        self.button_header = QHBoxLayout(self.button_widget)
        self.button_header.setContentsMargins(QMargins(0, 0, 0, 0))

        self.load_button = QPushButton()
        self.save_button = QPushButton()

        self.load_button.setIcon(QIcon.fromTheme('document-open'))
        self.save_button.setIcon(QIcon.fromTheme('document-save'))

        self.load_button.clicked[bool].connect(self._handle_load_clicked)
        self.save_button.clicked[bool].connect(self._handle_save_clicked)

        self.button_header.addWidget(self.save_button)
        self.button_header.addWidget(self.load_button)

        self.setMinimumWidth(150)

        self.reconf = reconf
        self.updater.start()
        self.reconf.config_callback = self.config_callback
        self._node_grn = node_name

    def get_node_grn(self):

        return self._node_grn

    def config_callback(self, config):

        #TODO: Think about replacing callback architecture with signals.

        if config:
            # TODO: should use config.keys but this method doesnt exist

            names = [name for name, v in config.items()]
            # v isn't used but necessary to get key and put it into dict.
            rospy.logdebug('config_callback name={} v={}'.format(name, v))

            for widget in self.editor_widgets:
                if isinstance(widget, EditorWidget):
                    if widget.param_name in names:
                        rospy.logdebug('EDITOR widget.param_name=%s',
                                       widget.param_name)
                        widget.update_value(config[widget.param_name])
                elif isinstance(widget, GroupWidget):
                    cfg = find_cfg(config, widget.param_name)
                    rospy.logdebug('GROUP widget.param_name=%s',
                                   widget.param_name)
                    widget.update_group(cfg)

    def _handle_load_clicked(self):
        filename = QFileDialog.getOpenFileName(
                self, self.tr('Load from File'), '.',
                self.tr('YAML file {.yaml} (*.yaml)'))
        if filename[0] != '':
            self.load_param(filename[0])

    def _handle_save_clicked(self):
        filename = QFileDialog.getSaveFileName(
                self, self.tr('Save parameters to file...'), '.',
                self.tr('YAML files {.yaml} (*.yaml)'))
        if filename[0] != '':
            self.save_param(filename[0])

    def save_param(self, filename):
        configuration = self.reconf.get_configuration()
        if configuration is not None:
            with file(filename, 'w') as f:
                yaml.dump(configuration, f)

    def load_param(self, filename):
        with file(filename, 'r') as f:
            configuration = {}
            for doc in yaml.load_all(f.read()):
                configuration.update(doc)
        self.reconf.update_configuration(configuration)

    def close(self):
        self.reconf.close()
        self.updater.stop()

        for w in self.editor_widgets:
            w.close()

        self.deleteLater()

    def filter_param(self, filter_key):
        #TODO impl
        pass