Ejemplo n.º 1
0
    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)
    def setup_group_frame(self, group):
        layout = QVBoxLayout()

        # grid for buttons for named targets
        grid = QGridLayout()
        grid.setSpacing(1)

        self.button_group = QButtonGroup(self)

        row = 0
        column = 0
        named_targets = self.get_named_targets(group)
        for target in named_targets:
            button = QPushButton(target)
            self.button_group.addButton(button)
            grid.addWidget(button, row, column)
            column += 1
            if column >= self.MAX_COLUMNS:
                row += 1
                column = 0

        self.button_group.buttonClicked.connect(self._handle_button_clicked)

        # grid for show joint value and move arm buttons/text field
        joint_values_grid = QGridLayout()
        joint_values_grid.setSpacing(1)

        button_show_joint_values = QPushButton('Current Joint Values')
        button_show_joint_values.clicked[bool].connect(
            self._handle_show_joint_values_clicked)

        line_edit = QLineEdit()
        self.text_joint_values.append(line_edit)

        button_move_to = QPushButton('Move to')
        button_move_to.clicked[bool].connect(self._handle_move_to_clicked)

        joint_values_grid.addWidget(button_show_joint_values, 0, 1)
        joint_values_grid.addWidget(line_edit, 0, 2)
        joint_values_grid.addWidget(button_move_to, 0, 3)

        layout.addLayout(grid)
        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        layout.addWidget(line)
        layout.addLayout(joint_values_grid)

        frame = QFrame()
        frame.setLayout(layout)
        return frame
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
    def __init__(self, context):
        super(SpectrogramPlugin, self).__init__(context)
        self.setObjectName('Spectrogram')

        sns.set(style="whitegrid", palette="bright", color_codes=True)

        self._widget = QWidget()
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        layout_ = QHBoxLayout()
        self.lbl_topic = QLabel('Topic:')
        layout_.addWidget(self.lbl_topic)
        self.le_topic = QLineEdit()
        layout_.addWidget(self.le_topic)
        self.apply_topic = QPushButton("Apply")
        self.apply_topic.clicked.connect(self.apply_clicked_topic)
        layout_.addWidget(self.apply_topic)
        layout.addLayout(layout_)

        layout_ = QHBoxLayout()
        self.lbl_lcf = QLabel('Low-cut Freq.[Hz]:')
        layout_.addWidget(self.lbl_lcf)
        self.spb_lcf = QSpinBox()
        self.spb_lcf.setRange(0, 50)
        self.spb_lcf.setValue(0)
        layout_.addWidget(self.spb_lcf)
        self.apply_lcf = QPushButton("Apply")
        self.apply_lcf.clicked.connect(self.apply_clicked_lcf)
        layout_.addWidget(self.apply_lcf)
        layout.addLayout(layout_)

        layout_ = QHBoxLayout()
        self.lbl_hcf = QLabel('High-cut Freq.[Hz]:')
        layout_.addWidget(self.lbl_hcf)
        self.spb_hcf = QSpinBox()
        self.spb_hcf.setRange(50, self.vib_freq / 2)
        self.spb_hcf.setValue(self.vib_freq / 2)
        layout_.addWidget(self.spb_hcf)
        self.apply_hcf = QPushButton("Apply")
        self.apply_hcf.clicked.connect(self.apply_clicked_hcf)
        layout_.addWidget(self.apply_hcf)
        layout.addLayout(layout_)

        #self.fig, self.axes = plt.subplots(2, 1, sharex=True)
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(1, 1, 1)
        self.canvas = FigureCanvas(self.fig)
        self.fig.tight_layout()
        layout.addWidget(self.canvas)

        context.add_widget(self._widget)

        self.update_signal.connect(self.update_spectrogram)
        self.subscriber_signal.connect(self.update_subscriber)
        self.subscriber_signal.emit('spectrum')
    def init_sliders(self):
        sliderbox = self._widget.findChild(QLayout, 'Sliders')

        graph_button = QPushButton()
        graph_button.setCheckable(True)
        graph_button.setText("Graph Off")
        graph_button.toggle()
        graph_button.clicked.connect(self.set_graph_state)
        self.graph_button = graph_button

        firstCol = QVBoxLayout()
        firstCol.addWidget(graph_button)

        sliderbox.addLayout(firstCol)

        self.sliders = []

        all_rows_layout = QVBoxLayout()
        chan_idx = 0
        for num_channels_row in self.settings['num_channels']:
            row_layout = QHBoxLayout()
            for i in range(num_channels_row):
                idx = chan_idx * 1

                slider_group = {
                    'slider_p': None,
                    'number_p': None,
                    'slider_v': None,
                    'number_v': None,
                    'on_off': None
                }

                layout_cluster = QVBoxLayout()
                slider_cluster = QHBoxLayout()
                label = QLabel()
                label.setText("Chan. %d" % (idx + 1))
                label.setAlignment(Qt.AlignCenter)
                layout_cluster.addWidget(label)
                for j in range(2):
                    layout = QVBoxLayout()
                    layout.setAlignment(Qt.AlignHCenter)

                    slider = QSlider(Qt.Vertical)
                    slider.setMinimum(0)
                    slider.setMaximum(255)
                    slider.setValue(
                        self.settings['valve_offsets'][chan_idx][j])
                    slider.setTickPosition(QSlider.TicksRight)
                    slider.setTickInterval(5)

                    spinbox = QSpinBox()
                    spinbox.setRange(0, 255)
                    spinbox.setValue(
                        self.settings['valve_offsets'][chan_idx][j])

                    slider.valueChanged.connect(spinbox.setValue)
                    spinbox.valueChanged.connect(slider.setValue)

                    cb_function_curr = lambda value, idx=idx: self.send_slider_value(
                        idx, value)
                    slider.valueChanged.connect(cb_function_curr)

                    label = QLabel()
                    label.setAlignment(Qt.AlignCenter)

                    if j == 0:
                        slider_group['slider_p'] = slider
                        slider_group['number_p'] = spinbox
                        label.setText("P")
                    else:
                        slider_group['slider_v'] = slider
                        slider_group['number_v'] = spinbox
                        label.setText("V")

                    labelmax = QLabel()
                    labelmax.setAlignment(Qt.AlignCenter)
                    labelmax.setText("255")

                    labelmin = QLabel()
                    labelmin.setAlignment(Qt.AlignCenter)
                    labelmin.setText("0")

                    layout.addWidget(label)
                    layout.addWidget(labelmax)
                    layout.addWidget(slider, Qt.AlignHCenter)
                    layout.addWidget(labelmin)
                    layout.addWidget(spinbox, Qt.AlignHCenter)
                    layout.setAlignment(slider, Qt.AlignHCenter)
                    layout.setAlignment(spinbox, Qt.AlignHCenter)

                    slider_cluster.addLayout(layout)

                on_button = QPushButton()
                on_button.setCheckable(True)
                on_button.setText("Off")

                if self.settings['channel_states'][chan_idx]:
                    on_button.toggle()
                    on_button.setText("On")

                on_button.clicked.connect(
                    lambda state, idx=idx: self.send_channel_state(idx, state))

                slider_group['on_off'] = on_button

                layout_cluster.addLayout(slider_cluster)
                layout_cluster.addWidget(on_button)

                row_layout.addLayout(layout_cluster)
                row_layout.addSpacing(20)

                self.sliders.append(slider_group)
                chan_idx += 1

            all_rows_layout.addLayout(row_layout)
        sliderbox.addLayout(all_rows_layout)
    def init_sliders(self):
        sliderbox = self._widget.findChild(QLayout, 'Sliders')

        firstCol = QVBoxLayout()
        graph_button = QPushButton()
        graph_button.setCheckable(True)
        graph_button.setText("Graph Off")
        graph_button.toggle()
        graph_button.clicked.connect(self.set_graph_state)

        reset_button = QPushButton()
        reset_button.setCheckable(False)
        reset_button.setText("Reset")
        reset_button.clicked.connect(self.set_reset)

        self.graph_button = graph_button
        self.reset_button = reset_button

        firstCol.addWidget(graph_button)
        firstCol.addWidget(reset_button)

        firstCol.setAlignment(graph_button, Qt.AlignVCenter)
        firstCol.setAlignment(reset_button, Qt.AlignVCenter)

        zero_button = QPushButton()
        zero_button.setCheckable(False)
        zero_button.setText("Set All Zero")
        zero_button.clicked.connect(self.set_pressure_zero)
        self.zero_button = zero_button
        firstCol.addWidget(zero_button)
        firstCol.setAlignment(zero_button, Qt.AlignVCenter)

        transition_box = QVBoxLayout()
        label = QLabel()
        label.setAlignment(Qt.AlignCenter)
        label.setText("Transition Time")

        spinbox = QDoubleSpinBox()
        spinbox.setMinimum(0)
        spinbox.setMaximum(10)
        spinbox.setValue(self.settings['transitions'])
        spinbox.setDecimals(1)
        spinbox.setSingleStep(0.1)
        spinbox.setSuffix(" sec")

        spinbox.valueChanged.connect(self.set_transition_value)

        transition_box.addWidget(label)
        transition_box.addWidget(spinbox)
        transition_box.setAlignment(label, Qt.AlignBottom)
        transition_box.setAlignment(spinbox, Qt.AlignTop)
        firstCol.addLayout(transition_box)

        self.sliders = []
        sliderbox.addLayout(firstCol)

        all_rows_layout = QVBoxLayout()

        chan_idx = 0
        for num_channels_row in self.settings['num_channels']:
            row_layout = QHBoxLayout()
            for i in range(num_channels_row):
                idx = chan_idx * 1

                slider_group = {'slider': None, 'number': None, 'on_off': None}
                layout_cluster = QVBoxLayout()

                layout = QVBoxLayout()
                layout.setAlignment(Qt.AlignHCenter)

                slider = QSlider(Qt.Vertical)
                slider.setMinimum(self.settings['min_pressure'][idx] * 10.0)
                slider.setMaximum(self.settings['max_pressure'][idx] * 10.0)
                slider.setValue(0)
                slider.setTickPosition(QSlider.TicksRight)
                slider.setTickInterval(20)

                spinbox = QDoubleSpinBox()
                spinbox.setMinimum(self.settings['min_pressure'][idx])
                spinbox.setMaximum(self.settings['max_pressure'][idx])
                spinbox.setValue(0)
                spinbox.setDecimals(1)
                spinbox.setSingleStep(0.1)

                cb_function_curr = lambda value, idx=idx, slider=False: self.send_slider_value(
                    idx, value, slider)
                cb_function_curr2 = lambda value, idx=idx, slider=True: self.send_slider_value(
                    idx, value, slider)
                slider.valueChanged.connect(cb_function_curr2)
                spinbox.valueChanged.connect(cb_function_curr)

                labelmax = QLabel()
                labelmax.setAlignment(Qt.AlignCenter)
                labelmax.setText("%0.1f" %
                                 (self.settings['max_pressure'][idx]))

                labelmin = QLabel()
                labelmin.setAlignment(Qt.AlignCenter)
                labelmin.setText("%0.1f" %
                                 (self.settings['min_pressure'][idx]))

                layout.addWidget(labelmax)
                layout.addWidget(slider)
                layout.addWidget(labelmin)
                layout.addWidget(spinbox)

                layout.setAlignment(slider, Qt.AlignHCenter)
                layout.setAlignment(spinbox, Qt.AlignHCenter)

                label = QLabel()
                label.setText("Chan. %d" % (chan_idx + 1))
                label.setAlignment(Qt.AlignCenter)
                layout_cluster.addWidget(label)
                layout_cluster.addLayout(layout)

                slider_group['slider'] = slider
                slider_group['number'] = spinbox

                on_button = QPushButton()
                on_button.setCheckable(True)
                on_button.setText("Off")

                if self.settings['channel_states'][idx]:
                    on_button.toggle()
                    on_button.setText("On")

                on_button.clicked.connect(
                    lambda state, idx=idx: self.send_channel_state(idx, state))

                slider_group['on_off'] = on_button

                layout_cluster.addWidget(on_button)

                row_layout.addLayout(layout_cluster)
                row_layout.addSpacing(20)

                self.sliders.append(slider_group)

                chan_idx += 1

            all_rows_layout.addLayout(row_layout)

        sliderbox.addLayout(all_rows_layout)
    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)
class JointStatePublisherGui(QWidget):
    sliderUpdateTrigger = Signal()

    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)

    @pyqtSlot(int)
    def onValueChanged(self, event):
        # A slider value was changed, but we need to change the joint_info metadata.
        for name, joint_info in self.joint_map.items():
            joint_info['slidervalue'] = joint_info['slider'].value()
            joint = joint_info['joint']
            joint['position'] = self.sliderToValue(joint_info['slidervalue'], joint)
            joint_info['display'].setText("%.2f" % joint['position'])

    @pyqtSlot()
    def updateSliders(self):
        self.update_sliders()

    def update_sliders(self):
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slidervalue'] = self.valueToSlider(joint['position'],
                                                           joint)
            joint_info['slider'].setValue(joint_info['slidervalue'])

    def center_event(self, event):
        self.center()

    def center(self):
        rospy.loginfo("Centering")
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slider'].setValue(self.valueToSlider(joint['zero'], joint))

    def reorggrid_event(self, event):
        self.reorganize_grid(event)

    def reorganize_grid(self, number_of_rows):
        self.num_rows = number_of_rows

        # Remove items from layout (won't destroy them!)
        items = []
        for pos in self.positions:
            item = self.gridlayout.itemAtPosition(*pos)
            items.append(item)
            self.gridlayout.removeItem(item)

        # Generate new positions for sliders and place them in their new spots
        self.positions = self.generate_grid_positions(len(items), self.num_rows)
        for item, pos in zip(items, self.positions):
            self.gridlayout.addLayout(item, *pos)

    def generate_grid_positions(self, num_items, num_rows):
        if num_rows==0:
          return []
        positions = [(y, x) for x in range(int((math.ceil(float(num_items) / num_rows)))) for y in range(num_rows)]
        positions = positions[:num_items]
        return positions

    def randomize_event(self, event):
        self.randomize()

    def randomize(self):
        rospy.loginfo("Randomizing")
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slider'].setValue(
                    self.valueToSlider(random.uniform(joint['min'], joint['max']), joint))

    def sliderUpdate(self, event):
        for name, joint_info in self.joint_map.items():
            joint_info['slidervalue'] = joint_info['slider'].value()
        self.update_sliders()

    def valueToSlider(self, value, joint):
        return (value - joint['min']) * float(RANGE) / (joint['max'] - joint['min'])

    def sliderToValue(self, slider, joint):
        pctvalue = slider / float(RANGE)
        return joint['min'] + (joint['max']-joint['min']) * pctvalue
Ejemplo n.º 10
0
    def init_sliders(self):
        sliderbox = self._widget.findChild(QLayout, 'Sliders')

        graph_button = QPushButton()
        graph_button.setCheckable(True)
        graph_button.setText("Graph Off")
        graph_button.toggle()
        graph_button.clicked.connect(self.set_graph_state)
        self.graph_button = graph_button

        firstCol = QVBoxLayout()
        firstCol.addWidget(graph_button)

        sliderbox.addLayout(firstCol)

        self.sliders = []

        all_rows_layout = QVBoxLayout()
        chan_idx = 0
        for num_channels_row in self.settings['num_channels']:
            row_layout = QHBoxLayout()
            for i in range(num_channels_row):
                idx = chan_idx * 1

                slider_group = {
                    'slider_p': None,
                    'number_p': None,
                    'slider_i': None,
                    'number_i': None,
                    'slider_d': None,
                    'number_d': None,
                    'on_off': None
                }

                layout_cluster = QVBoxLayout()
                slider_cluster = QHBoxLayout()
                label = QLabel()
                label.setText("Chan. %d" % (idx + 1))
                label.setAlignment(Qt.AlignCenter)
                layout_cluster.addWidget(label)
                for j in range(3):
                    layout = QVBoxLayout()
                    layout.setAlignment(Qt.AlignHCenter)

                    if j == 0:
                        maxrange = 1.0
                    elif j == 1:
                        maxrange = 10
                    elif j == 2:
                        maxrange = 10

                    slider = QSlider(Qt.Vertical)
                    slider.setMinimum(0)
                    slider.setMaximum(maxrange * 100)
                    slider.setValue(self.settings['pid_gains'][chan_idx][j] *
                                    100)
                    slider.setTickPosition(QSlider.TicksRight)
                    slider.setTickInterval(maxrange / 100.0)

                    spinbox = QDoubleSpinBox()
                    spinbox.setMinimum(0)
                    spinbox.setMaximum(maxrange)
                    spinbox.setValue(self.settings['pid_gains'][chan_idx][j])
                    spinbox.setDecimals(2)
                    spinbox.setSingleStep(maxrange / 100.0)

                    cb_function_number = lambda value, idx=idx, gain_idx=j, slider=False: self.send_slider_value(
                        idx, gain_idx, value, slider)
                    cb_function_slider = lambda value, idx=idx, gain_idx=j, slider=True: self.send_slider_value(
                        idx, gain_idx, value, slider)

                    slider.valueChanged.connect(cb_function_slider)
                    spinbox.valueChanged.connect(cb_function_number)

                    label = QLabel()
                    label.setAlignment(Qt.AlignCenter)

                    if j == 0:
                        slider_group['slider_p'] = slider
                        slider_group['number_p'] = spinbox
                        label.setText("P")
                    elif j == 1:
                        slider_group['slider_i'] = slider
                        slider_group['number_i'] = spinbox
                        label.setText("I")
                    elif j == 2:
                        slider_group['slider_d'] = slider
                        slider_group['number_d'] = spinbox
                        label.setText("D")

                    labelmax = QLabel()
                    labelmax.setAlignment(Qt.AlignCenter)
                    labelmax.setText("%0.1f" % (maxrange))

                    labelmin = QLabel()
                    labelmin.setAlignment(Qt.AlignCenter)
                    labelmin.setText("0")

                    layout.addWidget(label)
                    layout.addWidget(labelmax)
                    layout.addWidget(slider, Qt.AlignHCenter)
                    layout.addWidget(labelmin)
                    layout.addWidget(spinbox, Qt.AlignHCenter)
                    layout.setAlignment(slider, Qt.AlignHCenter)
                    layout.setAlignment(spinbox, Qt.AlignHCenter)

                    slider_cluster.addLayout(layout)

                on_button = QPushButton()
                on_button.setCheckable(True)
                on_button.setText("Off")

                if self.settings['channel_states'][chan_idx]:
                    on_button.toggle()
                    on_button.setText("On")

                on_button.clicked.connect(
                    lambda state, idx=idx: self.send_channel_state(idx, state))

                slider_group['on_off'] = on_button

                layout_cluster.addLayout(slider_cluster)
                layout_cluster.addWidget(on_button)

                row_layout.addLayout(layout_cluster)
                row_layout.addSpacing(20)

                self.sliders.append(slider_group)
                chan_idx += 1

            all_rows_layout.addLayout(row_layout)
        sliderbox.addLayout(all_rows_layout)
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
class ChecklistWindow(QWidget):
    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)

    # Create the main layout of widget
    def create_widget(self):
        # Create tree structure
        self.create_tree()

        # Declare buttons and connect each of them to a function
        self.load_button = QPushButton('Load')
        self.ok_button = QPushButton('OK')
        self.cancel_button = QPushButton('Cancel')
        self.load_button.pressed.connect(self.load_clicked)
        self.ok_button.pressed.connect(self.ok_clicked)
        self.cancel_button.pressed.connect(self.cancel_clicked)
        
        # Add buttons into the layout
        self.buttons_layout.addWidget(self.load_button)
        self.buttons_layout.addWidget(self.cancel_button)
        self.buttons_layout.addWidget(self.ok_button)
        self.tree_widget_layout.addWidget(self.tree_widget)

    # Create the tree layout of widget inside of the main layout
    def create_tree(self):
        # Set up the main tree widget
        self.tree_widget = QTreeWidget()
        self.tree_widget.setColumnCount(2)
        self.tree_widget.setColumnWidth(0, 250)
        self.tree_widget.setHeaderLabels(['Parts', 'Status'])
        self.item = QTreeWidgetItem()
        
        # Create the BPO section
        self.BPO_header = QTreeWidgetItem(self.tree_widget)
        self.BPO_header.setFlags(self.BPO_header.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        self.BPO_header.setText(0, 'BPO Checklist')
        self.BPO_header.setExpanded(True)
        self.create_item(self.BPO_header, self.BPO_checklist) # Adds the list of items into the section

        # Create the BTO section
        self.BTO_header = QTreeWidgetItem(self.tree_widget)
        self.BTO_header.setFlags(self.BTO_header.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        self.BTO_header.setText(0, 'BTO Checklist')
        self.BTO_header.setExpanded(True)
        self.create_item(self.BTO_header, self.BTO_checklist) # Adds the list of items into the section

    # Populate the tree layout with items
    def create_item(self, parent, list):
        section_header = [] # List of the section headers
        for i in range (len(list)):
            if (list[i][1] == '' and list[i][0] != ''):
                section_header.append(list[i][0])
        k = 0

        # Iterate through the different sections
        for j in range (len(section_header)):
            # Child refers to the sections (mechanical, avionics, etc)
            child = QTreeWidgetItem(parent)
            child.setFlags(child.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
            child.setText(0, section_header[j])

            while k < len(list):
                if list[k][0] in section_header:
                    # When the while loop encounters the first title, continue the loop
                    if (list[k][0] == section_header[0]):
                        k += 1
                        continue
                    # When the while loop encounters the next titles, break the loop so that the value of j increases
                    k += 1 
                    break
                # when the list contains empty cells, skip the cell and continue
                elif list[k][0] == '':
                    k += 1
                    continue
                # Add the list items to the treewidgetitem
                # Grandchild refers to the items under each section (wing nuts, tail nuts, etc)
                grandchild = QTreeWidgetItem(child)
                grandchild.setText(0, list[k][0])
                grandchild.setText(1, list[k][1])
                grandchild.setCheckState(0, Qt.Unchecked) # Set all checkbox to its unchecked state
                k += 1

    # Read the excel sheet and parse it as an array
    def excel_parser(self, file_name):
        with open(file_name, 'r') as file:
            checklist = []
            reader = csv.reader(file)
            for row in reader:
                checklist.append(row)
            return checklist            
    
    # Determines what happens when load button is clicked
    def load_clicked(self):
        # Use QFileDialog to open the system's file browser
        filenames = QFileDialog.getOpenFileNames(
            self, self.tr('Load from Files'), '.', self.tr('csv files {.csv} (*.csv)'))
        # Iterate through the file names selected
        for filename in filenames[0]:
            # If the file names has the word BPO or BTO in it, remove current widget, add the loaded one
            if (filename.find('BPO') != -1):
                self.BPO_checklist = self.excel_parser(filename)
                self.remove_widget()
                self.create_widget()
            elif (filename.find('BTO') != -1):
                self.BTO_checklist = self.excel_parser(filename)
                self.remove_widget()
                self.create_widget()
            else:
                rospy.logerr('rqt: Checklist name must contain BPO or BTO')
                self.close()
    
    # Close all the main_layout
    def remove_widget(self):
        self.main_layout.removeWidget(self.tree_widget)
        self.tree_widget.deleteLater()
        self.buttons_layout.removeWidget(self.ok_button)
        self.buttons_layout.removeWidget(self.cancel_button)
        self.buttons_layout.removeWidget(self.load_button)
        self.ok_button.deleteLater()
        self.cancel_button.deleteLater()
        self.load_button.deleteLater()
    
     # Declare what will happen when ok button is clicked
    def ok_clicked(self):
        if self.BPO_header.checkState(0) != 2 or self.BTO_header.checkState(0) != 2: # User clicks ok without checking all
            self.dialog_window("Some items in the checklist are still unchecked", "Do you still want to continue?", True)
        else:
            self.checklist_state = 1
            self.close()

    # Declare what will happen when cancel button is clicked
    def cancel_clicked(self):
        if self.BPO_header.checkState(0) != 0 or self.BTO_header.checkState(0) != 0: # User clicks cancel with some boxes checked
            self.dialog_window('Some of your items are checked. Cancelling will uncheck all your items', 'Do you still want to continue?', False)
        else:
            self.BTO_header.setCheckState(0, Qt.Unchecked)
            self.BPO_header.setCheckState(0, Qt.Unchecked)
            self.close()
    
    # Create a pop up window when user pre-emptively cancelled or clicked ok without completing the checklist
    def dialog_window(self, message, detail, check):
        self.message = QMessageBox()
        self.has_message_opened = 1
        self.message.setIcon(QMessageBox.Warning)
        self.message.setText(message)
        self.message.setInformativeText(detail)
        self.message.setWindowTitle("Items are unchecked")
        self.message.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        self.message.show()
        if check == True: # Check == True means it is from ok_clicked
            self.message.buttonClicked.connect(self.message_action)
        else:
            self.message.buttonClicked.connect(self.message_action_uncheck)
    
    # Determines what happens after dialog_window pops up from ok_button
    def message_action(self, i):
        if i.text() == '&Yes':
            self.checklist_state = 1
            self.close()
        else:
            self.message.close()

    # Determines what happens after dialog_window pops up from cancel_button
    def message_action_uncheck(self, i):
        self.response = i.text()
        if self.response == '&Yes':
            self.checklist_state = 1
            self.BTO_header.setCheckState(0, Qt.Unchecked)
            self.BPO_header.setCheckState(0, Qt.Unchecked)
            self.close()
        else:
            self.message.close()

    # Shutdown function
    def shutdown(self):
        self.close()
        if self.has_message_opened == 1:
            self.message.close()
Ejemplo n.º 13
0
class NavViewWidget(QWidget):
    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)

    def new_nav_view(self):
        if self._nav_view:
            self._nav_view.close()
        self._nav_view = NavView(self.map_topic,
                                 self.paths,
                                 self.polygons,
                                 tf_listener=self._tf,
                                 parent=self)
        self._set_pose.clicked.connect(self._nav_view.pose_mode)
        self._set_goal.clicked.connect(self._nav_view.goal_mode)
        self._layout.addWidget(self._nav_view)

    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 is None:
                qWarning(
                    'NavView.dragEnterEvent(): not hasattr(item, ros_topic_name_)'
                )
                return

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

        if accepted_topic(topic_name):
            e.acceptProposedAction()

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

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

                # Swap out the nav view for one with the new topics
                self.new_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):
        instance_settings.set_value("map_topic", self.map_topic)
        instance_settings.set_value("paths", self.paths)
        instance_settings.set_value("polygons", self.polygons)

    def restore_settings(self, plugin_settings, instance_settings):
        try:
            self.map_topic = instance_settings.value("map_topic", "/map")
        except Exception:
            pass

        try:
            self.paths = instance_settings.value("paths", [])
        except Exception:
            pass

        try:
            self.polygons = instance_settings.value("polygons", [])
        except Exception:
            pass

        self.new_nav_view()

    def trigger_configuration(self):
        """
        Callback when the configuration button is clicked
        """
        changed = False
        map_topics = sorted(rostopic.find_by_type('nav_msgs/OccupancyGrid'))
        try:
            index = map_topics.index(self.map_topic)
        except ValueError:
            index = 0
        map_topic, ok = QInputDialog.getItem(self, "Select map topic name",
                                             "Topic name", map_topics, index)
        if ok:
            if map_topic != self.map_topic:
                changed = True
            self.map_topic = map_topic

        # Paths
        path_topics = sorted(rostopic.find_by_type('nav_msgs/Path'))
        path_topics = [(topic, topic in self.paths) for topic in path_topics]
        dialog = ListDialog("Select path topic(s)", path_topics, self)
        paths, ok = dialog.exec_()

        if ok:
            if not paths:
                changed = True
            diff = set(paths).symmetric_difference(set(self.paths))
            if diff:
                self.paths = paths
                changed = True

        # Polygons
        polygon_topics = sorted(
            rostopic.find_by_type('geometry_msgs/PolygonStamped'))
        polygon_topics = [(topic, topic in self.polygons)
                          for topic in polygon_topics]
        dialog = ListDialog("Select polygon topic(s)", polygon_topics, self)
        polygons, ok = dialog.exec_()

        if ok:
            if not polygons:
                changed = True
            diff = set(polygons).symmetric_difference(set(self.polygons))
            if diff:
                self.polygons = polygons
                changed = True

        if changed:
            rospy.logdebug(
                "New configuration is different, creating a new nav_view")
            self.new_nav_view()
    def init_sliders(self):
        sliderbox = self._widget.findChild(QLayout,'Sliders')

        firstCol = QVBoxLayout()
        graph_button=QPushButton()
        graph_button.setCheckable(True)
        graph_button.setText("Graph Off")
        graph_button.toggle()
        graph_button.clicked.connect(self.set_graph_state)
        self.graph_button = graph_button

        reset_button=QPushButton()
        reset_button.setCheckable(False)
        reset_button.setText("Reset")
        reset_button.clicked.connect(self.set_reset)

        self.graph_button = graph_button
        self.reset_button = reset_button

        firstCol.addWidget(graph_button)
        firstCol.addWidget(reset_button)


        firstCol.addWidget(graph_button)
        firstCol.setAlignment(graph_button,Qt.AlignVCenter)

        zero_button=QPushButton()
        zero_button.setCheckable(False)
        zero_button.setText("Set All Zero")
        zero_button.clicked.connect(self.set_pressure_zero)
        self.zero_button = zero_button
        firstCol.addWidget(zero_button)
        firstCol.setAlignment(zero_button,Qt.AlignVCenter)



        transition_box = QVBoxLayout()
        label = QLabel()
        label.setAlignment(Qt.AlignCenter)
        label.setText("Transition Time")

        spinbox = QDoubleSpinBox()
        spinbox.setMinimum(0)
        spinbox.setMaximum(10)
        spinbox.setValue(self.settings['transitions'])
        spinbox.setDecimals(1)
        spinbox.setSingleStep(0.1)
        spinbox.setSuffix(" sec")

        spinbox.valueChanged.connect(self.set_transition_value)

        transition_box.addWidget(label)
        transition_box.addWidget(spinbox)
        transition_box.setAlignment(label,Qt.AlignBottom)
        transition_box.setAlignment(spinbox,Qt.AlignTop)
        firstCol.addLayout(transition_box)

        self.sliders = []
        sliderbox.addLayout(firstCol)

        all_rows_layout = QVBoxLayout()

        g_idx = 0

        for row in self.settings['gui_config']:
            num_groups_row = len(row)
            row_layout = QHBoxLayout()
            for gr_idx, s_group in enumerate(row): 
                g_channels = s_group['channels']
                g_layout = s_group['layout']

                if 'horiz' in g_layout:
                    group_layout = QHBoxLayout()
                else:
                    group_layout = QVBoxLayout()

                control_group = {'sliders': [], 'on_off': None}

                label = QLabel()
                label.setText("Group. %d"%(g_idx+1))
                label.setAlignment(Qt.AlignCenter)
                group_layout.addWidget(label)

                for c_idx, s_idx in enumerate(g_channels):
                    idx = s_idx*1
                    
                    slider_group={'slider':None, 'number':None}
                    
                    layout_cluster = QVBoxLayout()

                    labelfirst = QLabel()
                    labelfirst.setAlignment(Qt.AlignCenter)

                    labellast = QLabel()
                    labellast.setAlignment(Qt.AlignCenter)

                    layout = QVBoxLayout()

                    if 'diff' in g_layout and c_idx == 0:

                        sublayout=QHBoxLayout()

                        layout.setAlignment(Qt.AlignVCenter)

                        slider = QSlider(Qt.Horizontal)
                        slider.setMinimum(-100)
                        slider.setMaximum(100)
                        slider.setValue(0)
                        slider.setTickPosition(QSlider.TicksRight)
                        slider.setTickInterval(20)

                        spinbox = QDoubleSpinBox()
                        spinbox.setMinimum(-10)
                        spinbox.setMaximum(10)
                        spinbox.setValue(0)
                        spinbox.setDecimals(1)
                        spinbox.setSingleStep(0.1)

                        labellast.setText("%0.1f"%(10)) # These are flipped becasue of order
                        labelfirst.setText("%0.1f"%(-10))

                        max_label = labellast
                        min_label = labelfirst

                    else:
                        layout.setAlignment(Qt.AlignHCenter)

                        slider = QSlider(Qt.Vertical)
                        slider.setMinimum(self.settings['min_pressure'][idx]*10.0)
                        slider.setMaximum(self.settings['max_pressure'][idx]*10.0)
                        slider.setValue(0)
                        slider.setTickPosition(QSlider.TicksRight)
                        slider.setTickInterval(20)

                        spinbox = QDoubleSpinBox()
                        spinbox.setMinimum(self.settings['min_pressure'][idx])
                        spinbox.setMaximum(self.settings['max_pressure'][idx])
                        spinbox.setValue(0)
                        spinbox.setDecimals(1)
                        spinbox.setSingleStep(0.1)

                        labelfirst.setText("%0.1f"%(self.settings['max_pressure'][idx]))
                        labellast.setText("%0.1f"%(self.settings['min_pressure'][idx]))

                        max_label = labelfirst
                        min_label = labellast

                    
                    cb_function_number = lambda value, g_idx=g_idx, s_idx=c_idx, slider=False: self.send_slider_value(g_idx,s_idx,value,slider)
                    cb_function_slider = lambda value, g_idx=g_idx, s_idx=c_idx, slider=True: self.send_slider_value(g_idx,s_idx,value,slider)
                    slider.valueChanged.connect(cb_function_slider)
                    spinbox.valueChanged.connect(cb_function_number)
               

                    if 'diff' in g_layout and c_idx == 0:

                        sublayout.addWidget(labelfirst)
                        sublayout.addWidget(slider)
                        sublayout.addWidget(labellast)
                        layout.addWidget(spinbox)
                        layout.addLayout(sublayout)
                    else:
                        layout.addWidget(labelfirst)
                        layout.addWidget(slider)
                        layout.addWidget(labellast)
                        layout.addWidget(spinbox)

                    layout.setAlignment(slider, Qt.AlignHCenter)
                    layout.setAlignment(spinbox, Qt.AlignHCenter)

                    layout_cluster.addLayout(layout)

                    slider_group['slider'] = slider
                    slider_group['number'] = spinbox
                    slider_group['max_label'] = max_label
                    slider_group['min_label'] = min_label
                    control_group['sliders'].append(slider_group)

                    group_layout.addLayout(layout_cluster)

                on_button=QPushButton()
                on_button.setCheckable(True)
                on_button.setText("Off")

                if self.settings['channel_states'][idx]:
                    on_button.toggle()
                    on_button.setText("On")

                on_button.clicked.connect(lambda state, g_idx=g_idx: self.send_channel_state(g_idx,state))

                group_layout.addWidget(on_button)

                row_layout.addLayout(group_layout)
                row_layout.addSpacing(20)

                control_group['on_off'] = on_button
                self.sliders.append(control_group)

                g_idx+=1

            all_rows_layout.addLayout(row_layout)

        sliderbox.addLayout(all_rows_layout)
Ejemplo n.º 15
0
class SystemWidget(QWidget):
    """
    main class inherits from the ui window class.

    You can specify the topics that the topic pane.

    SystemWidget.start must be called in order to update topic pane.
    """

    _column_names = ['topic', 'type', 'bandwidth', 'rate', 'value']

    def __init__(self, plugin=None):
        """
        """
        super(SystemWidget, self).__init__()

        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_agent'), 'resource',
                               'SystemWidget.ui')
        loadUi(ui_file, self)

        self._plugin = plugin

        self._subsystems = {}

        self.all_subsystems = {}
        self._widgets = {}
        self.prev_subsystems = []
        self.levels_layouts = []

        self.structure_root = None
        self.structure_graph = None

        self.structure_changed = False

        self.scrollArea = QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.horizontalLayout.addWidget(self.scrollArea)
        self.mainWidget = QWidget()
        self.scrollArea.setWidget(self.mainWidget)
        self.verticalLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.verticalLayout)

        #        self._tree_items = {}
        #        self._column_index = {}
        #        for column_name in self._column_names:
        #            self._column_index[column_name] = len(self._column_index)

        # self.refresh_topics()

        # init and start update timer
        self._timer_refresh_topics = QTimer(self)
        self._timer_refresh_topics.timeout.connect(self.refresh_topics)

    def checkStructureChange(self):
        result = False

        for subsystem_name in self.prev_subsystems:
            if not subsystem_name in self._widgets:
                result = True
                break

        if result == False:
            for subsystem_name in self._widgets:
                if not subsystem_name in self.prev_subsystems:
                    result = True
                    break

        self.prev_subsystems = []
        for subsystem_name in self._widgets:
            self.prev_subsystems.append(subsystem_name)

        return result

    def start(self):
        """
        This method needs to be called to start updating topic pane.
        """
        self._timer_refresh_topics.start(100)

    def generateStructure(self):
        names = []
        for w1_name in self._widgets:
            names.append(w1_name)
            self._widgets[w1_name].resetBuffersLayout()

        for w1_name in self._widgets:
            w1 = self._widgets[w1_name]
            if not w1.isInitialized():
                continue
            for w2_name in self._widgets:
                w2 = self._widgets[w2_name]
                if not w2.isInitialized():
                    continue
                common_buffers = w1.getCommonBuffers(w2)
                if common_buffers != None:
                    w1.groupBuffers(common_buffers, w2.subsystem_name)
                    w2.groupBuffers(common_buffers, w1.subsystem_name)

        parents_dict = {}
        for w1_name in self._widgets:
            w1 = self._widgets[w1_name]
            if not w1.isInitialized():
                continue
            for w2_name in self._widgets:
                w2 = self._widgets[w2_name]
                if not w2.isInitialized():
                    continue
                rel_pose = w1.getLowerSubsystemPosition(w2.subsystem_name)
                if rel_pose != -1:
                    parents_dict[w2_name] = w1_name

#        print parents_dict

# get top-most subsystem (root)
        root = None
        if parents_dict:
            root = list(parents_dict.keys())[0]
            while root in parents_dict:
                root = parents_dict[root]

        levels = []
        if root == None:
            # there are no levels
            one_level = []
            for w_name in self._widgets:
                one_level.append(w_name)
            if len(one_level) > 0:
                levels.append(one_level)
        else:
            levels.append([root])
            while True:
                # expand all subsystems in the lowest level
                current_lowest = levels[-1]
                next_lower_level = []
                for s in current_lowest:
                    lower_list = self._widgets[s].getLowerSubsystems()
                    next_lower_level = next_lower_level + lower_list
                if len(next_lower_level) == 0:
                    break
                else:
                    levels.append(next_lower_level)

            # TODO: manage disjoint trees
            added_subsystems = []
            for l in levels:
                for s in l:
                    added_subsystems.append(s)
            for w_name in self._widgets:
                if not w_name in added_subsystems:
                    print "WARNING: subsystem %s is not in the main tree. This is not implemented." % (
                        w_name)

        print "levels:", levels
        return levels

    def layout_widgets(self, layout):
        return (layout.itemAt(i) for i in range(layout.count()))

    @Slot()
    def refresh_topics(self):
        """
        refresh tree view items
        """
        #
        # update the list of subsystems
        #
        topic_list = rospy.get_published_topics()
        if topic_list is None:
            rospy.logerr(
                'Not even a single published topic found. Check network configuration'
            )
            return

        # start new topic dict
        new_subsystems = {}

        for topic_name, topic_type in topic_list:
            name_split = topic_name.split('/')
            #            print name_split

            if (len(name_split) == 3) and (name_split[0] == '') and (
                    name_split[2]
                    == 'diag') and (topic_type
                                    == "diagnostic_msgs/DiagnosticArray"):
                subsystem_name = name_split[1]
                # if topic is new
                if subsystem_name not in self._subsystems:
                    # create new TopicInfo
                    topic_info = TopicInfo(topic_name, topic_type)
                    new_subsystems[subsystem_name] = topic_info
                    topic_info.start_monitoring()
                else:
                    # if topic has been seen before, copy it to new dict and
                    # remove it from the old one
                    new_subsystems[subsystem_name] = self._subsystems[
                        subsystem_name]
                    del self._subsystems[subsystem_name]

        # remove unused subsystems
        while True:
            repeat = False
            for s in self._subsystems:
                if not s in new_subsystems:
                    del self._subsystems[s]
                    repeat = True
                    break
            if not repeat:
                break

        # switch to new topic dict
        self._subsystems = new_subsystems

        #        print self._subsystems.keys()

        #
        # update each subsystem
        #
        new_widgets = {}
        for subsystem_name in self._subsystems:
            msg = self._subsystems[subsystem_name].last_message

            if (msg != None) and (len(msg.status) == 2) and \
              msg.status[0].name == 'components' and msg.status[1].name == 'diagnostics':
                name_split = subsystem_name.split('/')

                if not subsystem_name in self.all_subsystems:
                    self.all_subsystems[subsystem_name] = SubsystemWidget(
                        self._plugin, subsystem_name)

                if not subsystem_name in self._widgets:
                    new_widgets[subsystem_name] = self.all_subsystems[
                        subsystem_name]
#                    self.verticalLayout.addWidget(new_widgets[subsystem_name])
                else:
                    new_widgets[subsystem_name] = self._widgets[subsystem_name]
#                    del self._widgets[subsystem_name]

#                for value in msg.status[1].values:
#                    if value.key == 'master_component':
#                        new_widgets[subsystem_name].setStateName(value.value, '')
#                        break

# remove unused subsystems
#        while True:
#            repeat = False
#            for s in self._widgets:
#                if not s in new_widgets:
#                    del self._widgets[s]
#                    repeat = True
#                    break
#            if not repeat:
#                break

        self._widgets = new_widgets

        #        print self._widgets.keys()

        structure_changed = self.checkStructureChange()

        if structure_changed:
            self.structure_changed = True

        if self.structure_changed:
            allInitialized = True
            for subsystem_name in self._widgets:
                if not self._widgets[subsystem_name].isInitialized():
                    allInitialized = False
                    break
            if allInitialized:
                # remove all widgets from layouts
                # and remove all layouts
                for i in reversed(range(len(self.levels_layouts))):
                    layout = self.levels_layouts[i]
                    for i in reversed(range(layout.count())):
                        # The new widget is deleted when its parent is deleted.
                        layout.itemAt(i).widget().setParent(None)
                    self.verticalLayout.removeItem(layout)
                    del layout

                self.levels_layouts = []

                levels = self.generateStructure()
                for l in levels:
                    hbox = QHBoxLayout()
                    for w in l:
                        hbox.addWidget(self._widgets[w])
                        self._widgets[w].show()
                    self.levels_layouts.append(hbox)
                    self.verticalLayout.addLayout(hbox)
#                for
# TODO
                self.structure_changed = False

        while True:
            repeat = False
            for s in self.all_subsystems:
                if not s in self._widgets:
                    del self.all_subsystems[s]
                    repeat = True
                    break
            if not repeat:
                break

        for subsystem_name in self._widgets:
            self._widgets[subsystem_name].update_subsystem(
                self._subsystems[subsystem_name].last_message)

    def shutdown_plugin(self):
        for topic in self._topics.values():
            topic['info'].stop_monitoring()
        self._timer_refresh_topics.stop()

    def set_selected_topics(self, selected_topics):
        """
        @param selected_topics: list of tuple. [(topic_name, topic_type)]
        @type selected_topics: []
        """
        rospy.logdebug('set_selected_topics topics={}'.format(
            len(selected_topics)))
        self._selected_topics = selected_topics

    # TODO(Enhancement) Save/Restore tree expansion state
    def save_settings(self, plugin_settings, instance_settings):
        header_state = self.topics_tree_widget.header().saveState()
        instance_settings.set_value('tree_widget_header_state', header_state)

    def restore_settings(self, pluggin_settings, instance_settings):
        if instance_settings.contains('tree_widget_header_state'):
            header_state = instance_settings.value('tree_widget_header_state')
            if not self.topics_tree_widget.header().restoreState(header_state):
                rospy.logwarn("rqt_topic: Failed to restore header state.")
class block_pick_and_place(QWidget):
    def __init__(self, title="block_pick_and_place"):
        super(block_pick_and_place, self).__init__()

        # Initial
        self.br = tf.TransformBroadcaster()
        self.tf_listener = tf.TransformListener()
        self.ik = [0, 0, 0, 0]
        # Thread lock

        moveit_commander.roscpp_initialize(sys.argv)
        self.robot = moveit_commander.RobotCommander()
        self.scene = moveit_commander.PlanningSceneInterface()
        self.group = moveit_commander.MoveGroupCommander("arm")

        display_trajectory_publisher = rospy.Publisher(
            '/move_group/display_planned_path',
            moveit_msgs.msg.DisplayTrajectory,
            queue_size=1)
        self.gripper_cmd = rospy.Publisher('/gripper_joint/command',
                                           Float64,
                                           queue_size=1)

        # safe shutdown
        rospy.on_shutdown(self.onShutdown)

        # timer
        rospy.loginfo("[%s] Initialized " % (rospy.get_name()))
        self.group.allow_replanning(True)
        self.group.set_pose_reference_frame("base_link")

        self.group.set_goal_position_tolerance(0.005)
        self.group.set_goal_orientation_tolerance(0.05)

        self.home_pose()
        self.init_interactive_marker()

        self.arm_plan_state = False

        self.vlayout = QVBoxLayout(self)
        self.gridlayout = QGridLayout()
        self.vlayout.addLayout(self.gridlayout)

        # Buttons for randomizing and centering sliders and
        # Spinbox for on-the-fly selecting number of rows

        self.CWbutton = QPushButton('Start_to_plan', self)
        self.CWbutton.clicked.connect(self.start_event)
        self.vlayout.addWidget(self.CWbutton)
        self.SPbutton = QPushButton('Stop', self)
        self.SPbutton.clicked.connect(self.stop_event)
        self.vlayout.addWidget(self.SPbutton)

    def start_event(self, event):
        rospy.loginfo('ARM: START')
        self.arm_plan_state = True
        self.start_ik(self.ik[0], self.ik[1], self.ik[2], self.ik[3])

    def stop_event(self, event):
        rospy.loginfo('ARM: STOP ')

        self.arm_plan_state = False
        # print self.waypoints

    def init_interactive_marker(self):
        server = InteractiveMarkerServer("simple_marker")
        int_marker = InteractiveMarker()
        int_marker.header.frame_id = "/world"
        int_marker.name = "Object"
        int_marker.description = "Object Control"
        int_marker.scale = 0.1
        int_marker.pose.position.x = 0.3
        int_marker.pose.position.z = 0.01
        # create a grey box marker
        box_marker = Marker()
        box_marker.type = Marker.CUBE
        box_marker.scale.x = 0.02
        box_marker.scale.y = 0.02
        box_marker.scale.z = 0.02
        box_marker.color.r = 0.0
        box_marker.color.g = 0.5
        box_marker.color.b = 0.5
        box_marker.color.a = 1.0

        # create a non-interactive control which contains the box
        box_control = InteractiveMarkerControl()
        box_control.always_visible = True
        box_control.markers.append(box_marker)

        # add the control to the interactive marker
        int_marker.controls.append(box_control)

        # create a control which will move the box
        # this control does not contain any markers,
        # which will cause RViz to insert two arrows
        rotate_control = InteractiveMarkerControl()
        rotate_control.name = "move_3D"
        rotate_control.interaction_mode = InteractiveMarkerControl.MOVE_3D

        # add the control to the interactive marker
        int_marker.controls.append(rotate_control)

        # add the interactive marker to our collection &
        # tell the server to call processFeedback() when feedback arrives for it
        control = InteractiveMarkerControl()

        control = InteractiveMarkerControl()
        control.orientation.w = 1
        control.orientation.x = 1
        control.orientation.y = 0
        control.orientation.z = 0
        control.name = "move_x"
        control.interaction_mode = InteractiveMarkerControl.MOVE_AXIS

        int_marker.controls.append(control)

        control = InteractiveMarkerControl()
        control.orientation.w = 1
        control.orientation.x = 0
        control.orientation.y = 1
        control.orientation.z = 0
        control.name = "move_z"
        control.interaction_mode = InteractiveMarkerControl.MOVE_AXIS
        int_marker.controls.append(control)

        control = InteractiveMarkerControl()
        control.orientation.w = 1
        control.orientation.x = 0
        control.orientation.y = 0
        control.orientation.z = 1
        control.name = "move_y"
        control.interaction_mode = InteractiveMarkerControl.MOVE_AXIS
        int_marker.controls.append(control)

        server.insert(int_marker, self.processFeedback)

        # 'commit' changes and send to all clients
        server.applyChanges()

    def processFeedback(self, feedback):
        p = feedback.pose.position
        self.tf_listener.waitForTransform("/base_link", "/world",
                                          rospy.Time(0), rospy.Duration(1))
        pp = PointStamped()
        pp.point = p
        pp.header.frame_id = "/world"
        point_after = self.tf_listener.transformPoint("arm_base_link", pp)
        x = point_after.point.x  #+ random.uniform(0.005, -0.005)
        y = point_after.point.y  #+ random.uniform(0.005, -0.005)
        # print "x: ",x, "  y: ",y
        z = point_after.point.z
        ik_candidate = ik_solver(x, y, z, -90)
        # print ik_candidate
        if not np.isnan(ik_candidate.all()):
            for theta_1, theta_2, theta_3, theta_4 in ik_candidate:
                if abs(theta_2) < 2 and abs(theta_3) < 2 and abs(theta_4) < 2:
                    self.ik = [theta_1, theta_2, theta_3, theta_4]
                    break

        # print feedback.marker_name + " is now at " + str(p.x) + ", " + str(p.y) + ", " + str(p.z)

    def home_pose(self):
        joint_values = self.group.get_current_joint_values()

        joint_values[0] = 0
        joint_values[1] = -1.2417246372984723
        joint_values[2] = 1.7997449697893113
        joint_values[3] = 1.4184705050066115

        self.group.set_joint_value_target(joint_values)
        plan2 = self.group.plan()
        self.group.execute(plan2, wait=True)

    def start_ik(self, theta_1, theta_2, theta_3, theta_4):
        joint_values = self.group.get_current_joint_values()

        joint_values[0] = theta_1
        joint_values[1] = theta_2
        joint_values[2] = theta_3
        joint_values[3] = theta_4

        self.group.set_joint_value_target(joint_values)
        plan2 = self.group.plan()

        return plan2
        # self.group.execute(plan2,wait=True)

    def planCB(self, point_before, switch):
        # print msg

        self.tf_listener.waitForTransform("/base_link", "/world",
                                          rospy.Time(0), rospy.Duration(1))

        point_after = self.tf_listener.transformPoint("base_link",
                                                      point_before)
        x = point_after.point.x  #+ random.uniform(0.005, -0.005)
        y = point_after.point.y  #+ random.uniform(0.005, -0.005)
        # print "x: ",x, "  y: ",y
        z = point_after.point.z

        # print "x: ",x, "  y: ",y," z: ",z
        pose_target = Pose()
        pose_target.position.x = x
        pose_target.position.y = y
        pose_target.position.z = z
        r = math.atan(y / x)
        p = math.radians(90)
        y = 0
        if switch:
            self.rotation(r)

    # while (1):

    # q = tf.transformations.quaternion_from_euler(math.radians(msg.data[3]), math.radians(msg.data[4]), math.radians(msg.data[5]))
        q = tf.transformations.quaternion_from_euler(r, p, y)
        pose_target.orientation.x = q[0]
        pose_target.orientation.y = q[1]
        pose_target.orientation.z = q[2]
        pose_target.orientation.w = q[3]
        # print pose_target

        # self.group.set_goal_tolerance(0.1)
        self.group.set_pose_target(pose_target)
        # self.group.set_position_target((msg.data[0],msg.data[1],msg.data[2]))
        self.plan = self.group.plan()
        # print self.group.plan()
        ok = self.group.execute(self.plan, wait=True)
        print ok
        return ok
        # if ok:
        #   break
        # # print self.plan
        # p += 0.01
        # print p

    def onShutdown(self):
        rospy.loginfo("[%s] Shutting down..." % self.node_name)
        rospy.sleep(0.5)  #To make sure that it gets published.
        rospy.loginfo("[%s] Shutdown" % self.node_name)
Ejemplo n.º 17
0
class WaypointWindow(QWidget):
    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 create_layout(self, active_aircrafts):
        for i in active_aircrafts:
            self.create_progressbar(i)

    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)

    def remove(self, layout):
        for i in reversed(range(layout.count())):
            child = layout.takeAt(0)
            if child.widget():
                child.widget().deleteLater()
            if child.layout():
                self.remove(child.layout())

    def shutdown(self):
        self.close()
Ejemplo n.º 18
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 JointStatePublisherGui(QWidget):
    sliderUpdateTrigger = Signal()

    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)

    @pyqtSlot(int)
    def onValueChanged(self, event):
        # A slider value was changed, but we need to change the joint_info metadata.
        for name, joint_info in self.joint_map.items():
            joint_info['slidervalue'] = joint_info['slider'].value()
            joint = joint_info['joint']
            joint['position'] = self.sliderToValue(joint_info['slidervalue'],
                                                   joint)
            joint_info['display'].setText("%.2f" % joint['position'])

    @pyqtSlot()
    def updateSliders(self):
        self.update_sliders()

    def update_sliders(self):
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slidervalue'] = self.valueToSlider(
                joint['position'], joint)
            joint_info['slider'].setValue(joint_info['slidervalue'])

    def center_event(self, event):
        self.center()

    def center(self):
        rospy.loginfo("Centering")
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slider'].setValue(
                self.valueToSlider(joint['zero'], joint))

    def reorggrid_event(self, event):
        self.reorganize_grid(event)

    def reorganize_grid(self, number_of_rows):
        self.num_rows = number_of_rows

        # Remove items from layout (won't destroy them!)
        items = []
        for pos in self.positions:
            item = self.gridlayout.itemAtPosition(*pos)
            items.append(item)
            self.gridlayout.removeItem(item)

        # Generate new positions for sliders and place them in their new spots
        self.positions = self.generate_grid_positions(len(items),
                                                      self.num_rows)
        for item, pos in zip(items, self.positions):
            self.gridlayout.addLayout(item, *pos)

    def generate_grid_positions(self, num_items, num_rows):
        if num_rows == 0:
            return []
        positions = [
            (y, x)
            for x in range(int((math.ceil(float(num_items) / num_rows))))
            for y in range(num_rows)
        ]
        positions = positions[:num_items]
        return positions

    def randomize_event(self, event):
        self.randomize()

    def randomize(self):
        rospy.loginfo("Randomizing")
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slider'].setValue(
                self.valueToSlider(random.uniform(joint['min'], joint['max']),
                                   joint))

    def sliderUpdate(self, event):
        for name, joint_info in self.joint_map.items():
            joint_info['slidervalue'] = joint_info['slider'].value()
        self.update_sliders()

    def valueToSlider(self, value, joint):
        return (value - joint['min']) * float(RANGE) / (joint['max'] -
                                                        joint['min'])

    def sliderToValue(self, slider, joint):
        pctvalue = slider / float(RANGE)
        return joint['min'] + (joint['max'] - joint['min']) * pctvalue
Ejemplo n.º 20
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")
Ejemplo n.º 21
0
class TopicSelection(QWidget):
    recordSettingsSelected = Signal(bool, list, dict)

    def __init__(self):
        super(TopicSelection, self).__init__()
        master = rosgraph.Master('rqt_bag_recorder')
        self.setWindowTitle("Record a Simulation")
        self.resize(650, 720)

        pre = TS.get_time_series_pre_feature_options()
        glob = TS.get_global_time_series_features_options()
        # print pre
        # print glob
        all_topics = S.get_topics_options()
        keys = all_topics.keys()
        # print all_topics.keys()[0]
        self.plp_filename = ""
        self.group_selected_items = dict()
        self.group_areas = dict()
        self.group_main_widget = dict()
        self.group_selection_vlayout = dict()
        self.group_item_all = dict()
        # self.main_vlayout = QVBoxLayout(self)
        self.main_vlayout = QVBoxLayout(self)

        self.group_label = dict()

        self.selected_topics = []
        self.items_list = []

        for group_name in all_topics:
            self.group_selected_items[group_name] = []
            self.group_areas[group_name] = QScrollArea(self)
            self.group_main_widget[group_name] = QWidget(
                self.group_areas[group_name])
            self.group_label[group_name] = QLabel(group_name, self)
            self.group_label[group_name].setAlignment(Qt.AlignCenter)
            self.main_vlayout.addWidget(self.group_label[group_name])
            self.main_vlayout.addWidget(self.group_areas[group_name])
            self.group_selection_vlayout[group_name] = QVBoxLayout(self)
            self.group_item_all[group_name] = MyQCheckBox(
                "All", self, self.group_selection_vlayout[group_name], None)
            self.MakeCheckBoxList(self.group_selection_vlayout[group_name],
                                  self.group_selected_items[group_name],
                                  all_topics[group_name],
                                  self.group_item_all[group_name])
            self.group_main_widget[group_name].setLayout(
                self.group_selection_vlayout[group_name])
            self.group_areas[group_name].setWidget(
                self.group_main_widget[group_name])

        self.label1 = QLabel("Scenarios", self)
        self.label1.setAlignment(Qt.AlignCenter)

        self.main_vlayout.addWidget(self.label1)

        scanarios = S.get_scenarios_options()
        self.scanarios_answer = scanarios
        self.map_answer = dict()
        # print scanarios
        keys1 = scanarios.keys()

        # print keys1[0]
        # print scanarios[keys1[0]]["name"]
        # print scanarios[keys1[0]]["params"]
        #
        # for item in scanarios[keys1[0]]["params"]:
        #     print item

        self.radio_items = dict()
        self.number_group = QButtonGroup(self)

        for id_radio in scanarios:
            self.radio_items[id_radio] = QRadioButton(
                scanarios[id_radio]["name"])
            self.number_group.addButton(self.radio_items[id_radio])
            self.main_vlayout.addWidget(self.radio_items[id_radio])
            self.radio_items[id_radio].setChecked(False)
            self.radio_items[id_radio].clicked.connect(
                partial(self.callConsult, scanarios[id_radio]["params"],
                        id_radio))

        self.select_path = QLineEdit()
        self.save_path = QLineEdit()

        self.select_path.setEnabled(False)
        self.save_path.setEnabled(False)

        self.plp_button = QPushButton("Select PLP Python File...", self)
        self.plp_button.clicked.connect(self.onPlpClicked)

        self.two_buttons1 = QHBoxLayout(self)

        self.two_buttons1.addWidget(self.plp_button)

        self.two_buttons1.addWidget(self.select_path)

        self.main_vlayout.addLayout(self.two_buttons1)

        # self.label = QLabel("live Topics", self)
        # self.label.setAlignment(Qt.AlignCenter)
        #
        # self.main_vlayout.addWidget(self.label)

        # self.area = QScrollArea(self)
        # self.main_widget = QWidget(self.area)

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

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

        self.choose_clear_buttons = QHBoxLayout(self)

        self.choose_clear_buttons.addWidget(self.choose_button)

        self.choose_clear_buttons.addWidget(self.clear_button)

        self.main_vlayout.addLayout(self.choose_clear_buttons)

        # self.main_vlayout.addRow(self.choose_button, self.clear_button)

        # self.from_nodes_button = QPushButton("From Nodes", self)
        # self.from_nodes_button.clicked.connect(self.onFromNodesButtonClicked)

        # self.main_vlayout.addWidget(self.area)
        # self.main_vlayout.addWidget(self.choose_button)
        self.main_vlayout.addWidget(self.ok_button)
        # self.main_vlayout.addWidget(self.from_nodes_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_list4 = map(lambda l: l[0], master.getPublishedTopics(''))
        # topic_data_list4.sort()
        # for topic in topic_data_list4:
        #     self.addCheckBox(topic, self.selection_vlayout, self.selected_topics)

        # self.main_widget.setLayout(self.selection_vlayout)

        # self.area.setWidget(self.main_widget)

        # print S.get_scenarios_options()

        self.show()

    def onClearClicked(self):
        self.clearTopicCheckState()

    def clearTopicCheckState(self):
        for item in self.items_list:
            item.setCheckState(False)
        for item in self.group_item_all.values():
            item.setCheckState(False)

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

    def callConsult(self, params, id_radio):
        self.input_dialog = inputDialog(params, id_radio)
        self.input_dialog.ParamsSelected.connect(self.params_answer)
        # item, ok = QInputDialog.getItem(self, "select parameter",
        #                                 "list of parameters", params, 0, False)
        # if ok and item:
        #     self.gettext(item)

    def params_answer(self, params, label_items, id_radio):
        if id_radio == 0:
            # print "------" + str(id_radio)
            self.number_group.setExclusive(False)
            # print self.radio_items
            for item in self.radio_items:
                # print self.radio_items[item]
                self.radio_items[item].setChecked(False)
            self.number_group.setExclusive(True)
            self.enable_record()
        else:
            # print id_radio
            # print params
            # print params.values()
            a = {}
            # print label_items
            for item, name in zip(params, label_items):
                # value = params[item].text()
                a[name] = item.text().encode("utf-8")
            # print a
            self.map_answer = {"id": id_radio, "params": a}
            self.enable_record()
            return self.map_answer

        # for item in params.values():
        #     print item.text()
        # pass

    # def gettext(self, item):
    #     text, ok = QInputDialog.getText(self, 'Text Input Dialog', item)
    #
    #     if ok:
    #        print self.multipleReplace(str(text), item)
    #
    #
    # def multipleReplace(self, text, item):
    #     for key in self.scanarios_answer:
    #         #
    #         print self.scanarios_answer[key]["params"]
    #         for id, par in enumerate(self.scanarios_answer[key]["params"]):
    #             if par == item:
    #                 self.scanarios_answer[key]["params"][id] = text
    #     for id_radio in self.radio_items.keys():
    #         if self.radio_items[id_radio].isChecked():
    #             self.map_answer = {"id" : id_radio, "params" : self.scanarios_answer[id_radio]["params"]}
    #     return self.map_answer

    def MakeCheckBoxList(self, selection_vlayout, selected, topics_Keys,
                         item_all):
        item_all.stateChanged.connect(
            lambda x: self.updateList(x, item_all, None))
        selection_vlayout.addWidget(item_all)
        topic_data_list = topics_Keys
        topic_data_list.sort()
        for topic in topic_data_list:
            self.addCheckBox(topic, selection_vlayout, selected)

    def get_item_by_name(self, item_name):
        for item in self.items_linputDialogist:
            if item.text() == item_name:
                return item
        return None

    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.append(item)
        selection_vlayout.addWidget(item)

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

    # def updateList(self, state, topic=None, force_update_state=False):
    #     if topic is None:  # The "All" checkbox was checked / unchecked
    #         if state == Qt.Checked:
    #             self.item_all.setTristate(False)
    #             for item in self.items_list:
    #                 if item.checkState() == Qt.Unchecked:
    #                     item.setCheckState(Qt.Checked)
    #         elif state == Qt.Unchecked:
    #             self.item_all.setTristate(False)
    #             for item in self.items_list:
    #                 if item.checkState() == Qt.Checked:
    #                     item.setCheckState(Qt.Unchecked)
    #     else:
    #         if state == Qt.Checked:
    #             self.selected_topics.append(topic)
    #         else:
    #             self.selected_topics.remove(topic)
    #             if self.item_all.checkState() == Qt.Checked:
    #                 self.item_all.setCheckState(Qt.PartiallyChecked)
    #
    #     if self.selected_topics == []:
    #         self.ok_button.setEnabled(False)
    #     else:
    #         self.ok_button.setEnabled(True)

    def updateList(self,
                   state,
                   item_clicked,
                   topic=None,
                   force_update_state=False):
        if type(item_clicked) is str:
            item_clicked = self.get_item_by_name(item_clicked)
            if item_clicked is None:
                return
        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:
                    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:
                    if item.checkState() == Qt.Checked and \
                            item.selection_vlayout == item_clicked.selection_vlayout:
                        item.setCheckState(Qt.Unchecked)
        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)

        self.enable_record()

    def enable_record(self):
        temp_selected_topics = []
        for item in self.group_selected_items.values():
            if item:
                for i in item:
                    temp_selected_topics.append(i)

        flag = False
        for item in self.radio_items:
            if self.radio_items[item].isChecked():
                flag = True
                break
            # print self.radio_items[item]

        # flag = reduce(lambda acc, curr: acc or , self.radio_items, False)
        # print "------+++++-" + str(flag)
        if len(temp_selected_topics) > 0 or len(self.selected_topics) > 0:
            self.ok_button.setEnabled(flag)
        else:
            self.ok_button.setEnabled(False)

    def onButtonClicked(self):
        # print self.group_selected_items
        for item in self.group_selected_items.values():
            if item:
                for i in item:
                    self.selected_topics.append(i)
        topics = self.selected_topics
        with open(get_path() + 'logger_topic.log', "w") as f:
            for topic in topics:
                f.write(topic + "\n")
        self.close()
        # TBD - runing plp on shell on itself
        # if self.plp_filename != "":
        #     from .plp import Plp
        #     Plp(self.plp_filename)
        self.recordSettingsSelected.emit(False, self.selected_topics,
                                         self.map_answer)

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

    def onPlpClicked(self):
        import inspect, os
        filepath = os.path.dirname(
            os.path.abspath(inspect.getfile(
                inspect.currentframe()))) + "/log/save_plp.log"
        current_directory = self.get_current_opened_directory(filepath)
        fd = QFileDialog(self)
        wc = "Csv files {.py} (*.py)"
        # print current_directory
        filename, filter = fd.getOpenFileNamesAndFilter(
            filter=wc, initialFilter=('*.py'), directory=current_directory)
        if len(filename):
            self.plp_filename = filename[0]
            with open(filepath, "w") as f:
                f.write(self.plp_filename)
            self.select_path.setText(self.plp_filename)
            # print self.plp_filename[0]

    def onFromNodesButtonClicked(self):
        self.node_selection = NodeSelection(self)

    def getTopicsByName(self, name):
        arr = S.get_topics_options()
        return arr[name]
Ejemplo n.º 22
0
class QuestionDialogPlugin(Plugin):

    timeout_sig = pyqtSignal()
    update_sig = pyqtSignal()

    def __init__(self, context):
        super(QuestionDialogPlugin, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('QuestionDialogPlugin')

        font_size = rospy.get_param("~font_size", 40)

        # Create QWidget
        self._widget = QWidget()
        self._widget.setFont(QFont("Times", font_size, QFont.Bold))
        self._layout = QVBoxLayout(self._widget)
        self._text_browser = QTextBrowser(self._widget)
        self._layout.addWidget(self._text_browser)
        self._button_layout = QGridLayout()
        self._layout.addLayout(self._button_layout)

        # layout = QVBoxLayout(self._widget)
        # layout.addWidget(self.button)
        self._widget.setObjectName('QuestionDialogPluginUI')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))
        context.add_widget(self._widget)

        # Setup service provider
        self.service = rospy.Service('question_dialog', QuestionDialog,
                                     self.service_callback)
        self.request = None
        self.response_ready = False
        self.response = None
        self.buttons = []
        self.text_label = None
        self.text_input = None

        self.update_sig.connect(self.update)
        self.timeout_sig.connect(self.timeout)

    def shutdown_plugin(self):
        self.service.shutdown()

    def service_callback(self, req):
        self.response_ready = False
        self.request = req
        self.update_sig.emit()
        # Start timer against wall clock here instead of the ros clock.
        start_time = time.time()
        while not self.response_ready:
            if self.request != req:
                # The request got preempted by a new request.
                return QuestionDialogResponse(QuestionDialogRequest.PREEMPTED, "")
            if req.timeout != QuestionDialogRequest.NO_TIMEOUT:
                current_time = time.time()
                if current_time - start_time > req.timeout:
                    self.timeout_sig.emit()
                    return QuestionDialogResponse(
                            QuestionDialogRequest.TIMED_OUT, "")
            time.sleep(0.2)
        return self.response

    def update(self):
        self.clean()
        if not self.request:
            rospy.logwarn('question dialog: no request, update ignored')
            return
        req = self.request
        self._text_browser.setText(req.message)
        if req.type == QuestionDialogRequest.DISPLAY:
            # All done, nothing more too see here.
            self.response = QuestionDialogResponse(
                    QuestionDialogRequest.NO_RESPONSE, "")
            self.response_ready = True
        elif req.type == QuestionDialogRequest.CHOICE_QUESTION:
            for index, options in enumerate(req.options):
                button = QPushButton(options, self._widget)
                button.clicked.connect(partial(self.handle_button, index))
                row = index / 3
                col = index % 3
                self._button_layout.addWidget(button, row, col)
                self.buttons.append(button)
        elif req.type == QuestionDialogRequest.TEXT_QUESTION:
            self.text_label = QLabel("Enter here: ", self._widget)
            self._button_layout.addWidget(self.text_label, 0, 0)
            self.text_input = QLineEdit(self._widget)
            self.text_input.editingFinished.connect(self.handle_text)
            self._button_layout.addWidget(self.text_input, 0, 1)

    def timeout(self):
        self._text_browser.setText("Oh no! The request timed out.")
        self.clean()

    def clean(self):
        while self._button_layout.count():
            item = self._button_layout.takeAt(0)
            item.widget().deleteLater()
        self.buttons = []
        self.text_input = None
        self.text_label = None

    def handle_button(self, index):
        self.response = QuestionDialogResponse(index, "")
        self.clean()
        self.response_ready = True

    def handle_text(self):
        self.response = QuestionDialogResponse(
            QuestionDialogRequest.TEXT_RESPONSE,
            self.text_input.text())
        self.clean()
        self.response_ready = True

    def save_settings(self, plugin_settings, instance_settings):
        # TODO save intrinsic configuration, usually using:
        # instance_settings.set_value(k, v)
        pass

    def restore_settings(self, plugin_settings, instance_settings):
        # TODO restore intrinsic configuration, usually using:
        # v = instance_settings.value(k)
        pass
Ejemplo n.º 23
0
class HistorySelection(QWidget):
    def __init__(self):
        super(HistorySelection, self).__init__()
        self.setWindowTitle("Extracting Window Features")
        self.resize(550, 440)

        per_title, pre = TS.get_time_series_pre_feature_options()
        glob_title, glob = TS.get_global_time_series_features_options()

        self.history_items = dict()
        self.history_items[per_title] = pre
        self.history_items[glob_title] = glob

        self.saved_dir = []

        self.group_selected_items = dict()
        self.group_areas = dict()
        self.group_main_widget = dict()
        self.group_selection_vlayout = dict()
        self.group_item_all = dict()
        self.main_vlayout = QVBoxLayout(self)
        self.group_label = dict()

        self.items_list = []
        self.selected_topics = []
        self.files = []

        # layout = QFormLayout()

        self.select_path = QLineEdit()
        self.save_path = QLineEdit()

        self.select_path.setEnabled(False)
        self.save_path.setEnabled(False)

        self.ok_button = QPushButton("Select CSV...", self)
        self.ok_button.clicked.connect(self.onButtonClicked)

        self.two_buttons1 = QHBoxLayout(self)

        self.two_buttons1.addWidget(self.ok_button)

        self.two_buttons1.addWidget(self.select_path)

        self.main_vlayout.addLayout(self.two_buttons1)

        # self.main_vlayout.addRow(self.ok_button, self.client_answers)

        # self.main_vlayout.addWidget(self.ok_button)

        # self.main_vlayout.addWidget(self.ok_button)

        for group_name in self.history_items:
            self.group_selected_items[group_name] = []
            self.group_areas[group_name] = QScrollArea(self)
            self.group_main_widget[group_name] = QWidget(
                self.group_areas[group_name])
            self.group_label[group_name] = QLabel(group_name, self)
            self.group_label[group_name].setAlignment(Qt.AlignCenter)
            self.main_vlayout.addWidget(self.group_label[group_name])
            self.main_vlayout.addWidget(self.group_areas[group_name])
            self.group_selection_vlayout[group_name] = QVBoxLayout(self)
            self.group_item_all[group_name] = MyQCheckBox(
                "All", self, self.group_selection_vlayout[group_name], None)
            self.MakeCheckBoxList(self.group_selection_vlayout[group_name],
                                  self.group_selected_items[group_name],
                                  self.history_items[group_name],
                                  self.group_item_all[group_name])
            self.group_main_widget[group_name].setLayout(
                self.group_selection_vlayout[group_name])
            self.group_areas[group_name].setWidget(
                self.group_main_widget[group_name])

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

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

        # self.main_vlayout.addWidget(self.choose_button)

        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("3")

        self.label5 = QLabel("Duration Time:", self)
        self.label5.setAlignment(Qt.AlignCenter)

        self.label6 = QLabel("Step:", self)
        self.label6.setAlignment(Qt.AlignCenter)

        self.step = QLineEdit(self)
        self.step.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.step_2 = QHBoxLayout(self)

        self.step_2.addWidget(self.label6)

        self.step_2.addWidget(self.step)

        self.main_vlayout.addLayout(self.step_2)

        # self.main_vlayout.addRow(self.label4, self.window)

        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.addRow(self.clear_button, self.choose_button)

        # self.label5 = QLabel("Load CSV", self)
        # self.label5.setAlignment(Qt.AlignCenter)
        #
        # self.main_vlayout.addWidget(self.label5)

        # self.label6 = QLabel("output", self)
        # self.label6.setAlignment(Qt.AlignCenter)
        #
        # self.main_vlayout.addWidget(self.label6)

        self.save_button = QPushButton("Save CSV...", self)
        self.save_button.clicked.connect(self.onSaveClicked)

        self.submit_button = QPushButton("Sumbit", self)
        self.submit_button.clicked.connect(self.onSumbitClicked)

        # self.main_vlayout.addWidget(self.save_button)

        self.two_buttons2 = QHBoxLayout(self)

        self.two_buttons2.addWidget(self.save_button)

        self.two_buttons2.addWidget(self.save_path)

        self.main_vlayout.addLayout(self.two_buttons2)

        # self.main_vlayout.addRow(self.save_button, self.client_answers1)

        self.main_vlayout.addWidget(self.submit_button)

        self.show()

    def get_min_rows_csv(self, csv_files):
        import pandas as pd
        dfs = map(lambda x: pd.read_csv(x, header=0), csv_files)
        number = dfs[0].shape[0]
        number = reduce(lambda acc, curr: min(acc, curr.shape[0]), dfs, number)
        self.label5.setText("Duration Time: %s" % number)

    def onClearClicked(self):
        self.clearTopicCheckState()

    def clearTopicCheckState(self):
        for item in self.items_list:
            item.setCheckState(False)
        for item in self.group_item_all.values():
            item.setCheckState(False)

    def MakeCheckBoxList(self, selection_vlayout, selected, topics_Keys,
                         item_all):
        item_all.stateChanged.connect(
            lambda x: self.updateList(x, item_all, None))
        selection_vlayout.addWidget(item_all)
        topic_data_list = topics_Keys
        topic_data_list.sort()
        for topic in topic_data_list:
            self.addCheckBox(topic, selection_vlayout, selected)

    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.append(item)
        selection_vlayout.addWidget(item)

    def updateList(self,
                   state,
                   item_clicked,
                   topic=None,
                   force_update_state=False):
        if type(item_clicked) is str:
            item_clicked = self.get_item_by_name(item_clicked)
            if item_clicked is None:
                return
        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:
                    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:
                    if item.checkState() == Qt.Checked and \
                                    item.selection_vlayout == item_clicked.selection_vlayout:
                        item.setCheckState(Qt.Unchecked)
        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)

    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/select_history.log"
        fd = QFileDialog(self)
        wc = "Csv files {.csv} (*.csv)"
        self.files = []
        current_directory = self.get_current_opened_directory(filepath)
        tmp_pathes, filter = fd.getOpenFileNamesAndFilter(
            filter=wc, initialFilter=('*.csv'), directory=current_directory)
        for path in tmp_pathes:
            self.files.append(path.encode("utf-8"))
        # print self.files
        if len(self.files) != 0:
            self.get_min_rows_csv(tmp_pathes)
            self.select_path.setText(self.files[0])
            with open(filepath, "w") as f:
                f.write(self.files[0])

                # handler = logging.FileHandler(filepath, mode='w')
                # logger_topic.addHandler(handler)
                # logger_topic.info(self.files[0])
        else:
            self.select_path.setText("")

    def check_int(self, number, condition, title, message_body):
        try:
            # print type(number)
            val = int(number)
            if val <= condition:
                QMessageBox.about(self, title,
                                  "The number should > %s" % condition)
                return False
        except ValueError:
            QMessageBox.about(self, title, message_body)
            return False
        return True

    def check_choose(self):
        flag = True
        temp = []
        for item in self.group_selected_items.values():
            if item:
                for i in item:
                    temp.append(i)
        if len(temp) == 0:
            QMessageBox.about(self, "Features",
                              "One feature at least should be chosen")
            flag = False
        return flag

    def check_files_amount(self):
        flag = True
        if len(self.files) <= 0:
            QMessageBox.about(self, "Load CSV",
                              "One file at least should be chosen")
            flag = False
        return flag

    def check_validation(self):
        flag = self.check_files_amount()
        flag = flag & self.check_choose()
        flag = flag & self.check_int(self.window.text(), 2,
                                     "Error in Window Time",
                                     "That's not a number!")
        flag = flag & self.check_int(self.step.text(), 0, "Error in Step",
                                     "That's not a integer!")
        # TODO selected topic not empty

        if self.saved_dir == []:
            QMessageBox.about(self, "Save CSV", "Select path for saving")
            flag = False
        return flag

    def onSumbitClicked(self):
        if not self.check_validation():
            return
        self.selected_topics = []
        for item in self.group_selected_items.values():
            if item:
                for i in item:
                    self.selected_topics.append(i)
        # Defined Logging
        # handler = logging.FileHandler('/var/tmp/logger_history.log', mode='a')
        # logger_topic.addHandler(handler)
        topics = self.selected_topics
        with open(get_path() + 'logger_history.log', "w") as f:
            for topic in topics:
                f.write(topic + "\n")
        self.createTimeSeriesFeatures(self.files, self.saved_dir,
                                      int(self.window.text()),
                                      self.group_selected_items,
                                      int(self.step.text()))

    def onSaveClicked(self):
        import inspect, os
        filepath = os.path.dirname(
            os.path.abspath(inspect.getfile(
                inspect.currentframe()))) + "/log/save_history.log"
        # print self.files
        # print self.window.text()
        # print self.group_selected_items.values()

        # print self.group_selected_items
        current_directory = self.get_current_opened_directory(filepath)
        # print current_directory
        # self._to_save_filename = QFileDialog.getSaveFileName(self, self.tr('csv File'), current_directory,
        #                                                      self.tr('csv (*.csv)'))
        self.saved_dir = str(
            QFileDialog.getExistingDirectory(self, "Select Directory",
                                             current_directory))
        # if self._to_save_filename[0] != "":
        #     with open(filepath, "w") as f:
        #         f.write(self._to_save_filename[0])
        if self.saved_dir != "":
            with open(filepath, "w") as f:
                f.write(self.saved_dir)

                # handler = logging.FileHandler(filepath, mode='w')
                # logger_topic.addHandler(handler)
                # print self._to_save_filename[0]
                # logger_topic.info()
        # self.save_path.setText(get_corrent_file_name(self._to_save_filename[0], ".csv"))
        self.save_path.setText(self.saved_dir)

    def createTimeSeriesFeatures(self, files, saved_dir, window,
                                 group_selected_items, step):
        import TimeSeriesFeatures as TS
        # saved_dir = saved_dir[0].encode('utf-8')
        for input_path in files:
            output_path = generate_csv_from_bag(saved_dir, input_path)
            print "++++++++++++++++++++++++++ ", output_path
            print "in = %s out = %s " % (input_path, output_path)
            print "step = %s" % step
            ts = TS.TimeSeries(input_path, output_path, window,
                               group_selected_items, step)
            ts.generate_time_series_features()
        QMessageBox.about(self, "csv save", "csv was saved successfuly")

    def onButtonChooseCliked(self):
        for checkbox in self.items_list:
            checkbox.setCheckState(Qt.Unchecked)
        with open(get_path() + "logger_history.log", 'r') as f:
            topics = f.read().splitlines()
        for checkbox in self.items_list:
            if checkbox.text() in topics:
                checkbox.setCheckState(Qt.Checked)
Ejemplo n.º 24
0
class SliderPublisher(QWidget):
    def __init__(self, content):
        super(SliderPublisher, self).__init__()

        content = content.replace('\t', '    ')

        # get message types
        self.publishers = {}
        self.values = {}
        pkgs = []

        # to keep track of key ordering in the yaml file
        order = []
        old = []

        for topic, info in yaml.load(content).items():
            pkg, msg = info['type'].split('/')
            pkgs.append(__import__(pkg, globals(), locals(), ['msg']))
            self.publishers[topic] = Publisher(topic,
                                               getattr(pkgs[-1].msg,
                                                       msg), info)
            order.append((topic, []))
            for key in info:
                self.values[key] = info[key]
                order[-1][1].append((content.find(' ' + key + ':'), key))
                old.append((content.find(' ' + key + ':'), key))
                for bound in ['min', 'max']:
                    self.values[key][bound] = float(self.values[key][bound])
                self.values[key]['val'] = 0
            order[-1][1].sort()
        order.sort(key=lambda x: x[1][0][0])
        # build sliders - thanks joint_state_publisher
        sliderUpdateTrigger = Signal()
        self.vlayout = QVBoxLayout(self)
        self.gridlayout = QGridLayout()
        font = QFont("Helvetica", 9, QFont.Bold)
        topic_font = QFont("Helvetica", 10, QFont.Bold)

        sliders = []
        self.key_map = {}
        y = 0
        for topic, keys in order:
            topic_layout = QVBoxLayout()
            label = QLabel(topic)
            label.setFont(topic_font)
            topic_layout.addWidget(label)
            self.gridlayout.addLayout(topic_layout, *(y, 0))
            y += 1
            for idx, key in keys:
                key_layout = QVBoxLayout()
                row_layout = QHBoxLayout()
                label = QLabel(key)
                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)
                key_layout.addLayout(row_layout)

                slider = QSlider(Qt.Horizontal)
                slider.setFont(font)
                slider.setRange(0, RANGE)
                slider.setValue(RANGE / 2)

                key_layout.addWidget(slider)

                self.key_map[key] = {
                    'slidervalue': 0,
                    'display': display,
                    'slider': slider
                }
                slider.valueChanged.connect(self.onValueChanged)
                self.gridlayout.addLayout(key_layout, *(y, 0))
                y += 1
                #sliders.append(key_layout)

            # Generate positions in grid and place sliders there
            #self.positions = [(y,0) for y in range(len(sliders))]
            #for item, pos in zip(sliders, self.positions):
            #    self.gridlayout.addLayout(item, *pos)

        self.vlayout.addLayout(self.gridlayout)

        self.ctrbutton = QPushButton('Center', self)
        self.ctrbutton.clicked.connect(self.center)
        self.vlayout.addWidget(self.ctrbutton)

        self.center(1)

    def sliderToValue(self, slider, key):
        val = self.values[key]
        return val['min'] + slider * (val['max'] - val['min']) / RANGE

    @pyqtSlot(int)
    def onValueChanged(self, event):
        # A slider value was changed, but we need to change the joint_info metadata.
        for key, key_info in self.key_map.items():
            key_info['slidervalue'] = key_info['slider'].value()
            # build corresponding value
            self.values[key]['val'] = self.sliderToValue(
                key_info['slidervalue'], key)
            key_info['display'].setText("%.2f" % self.values[key]['val'])

    def center(self, event):
        for key, key_info in self.key_map.items():
            key_info['slider'].setValue(RANGE / 2)
        self.onValueChanged(event)

    def loop(self):
        rate = rospy.Rate(10)
        while not rospy.is_shutdown():
            for pub in self.publishers:
                self.publishers[pub].update(self.values)
            rate.sleep()
Ejemplo n.º 25
0
    def __init__(self, content):
        super(SliderPublisher, self).__init__()

        content = content.replace('\t', '    ')

        # get message types
        self.publishers = {}
        self.values = {}
        pkgs = []

        # to keep track of key ordering in the yaml file
        order = []
        old = []

        for topic, info in yaml.load(content).items():
            pkg, msg = info['type'].split('/')
            pkgs.append(__import__(pkg, globals(), locals(), ['msg']))
            self.publishers[topic] = Publisher(topic,
                                               getattr(pkgs[-1].msg,
                                                       msg), info)
            order.append((topic, []))
            for key in info:
                self.values[key] = info[key]
                order[-1][1].append((content.find(' ' + key + ':'), key))
                old.append((content.find(' ' + key + ':'), key))
                for bound in ['min', 'max']:
                    self.values[key][bound] = float(self.values[key][bound])
                self.values[key]['val'] = 0
            order[-1][1].sort()
        order.sort(key=lambda x: x[1][0][0])
        # build sliders - thanks joint_state_publisher
        sliderUpdateTrigger = Signal()
        self.vlayout = QVBoxLayout(self)
        self.gridlayout = QGridLayout()
        font = QFont("Helvetica", 9, QFont.Bold)
        topic_font = QFont("Helvetica", 10, QFont.Bold)

        sliders = []
        self.key_map = {}
        y = 0
        for topic, keys in order:
            topic_layout = QVBoxLayout()
            label = QLabel(topic)
            label.setFont(topic_font)
            topic_layout.addWidget(label)
            self.gridlayout.addLayout(topic_layout, *(y, 0))
            y += 1
            for idx, key in keys:
                key_layout = QVBoxLayout()
                row_layout = QHBoxLayout()
                label = QLabel(key)
                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)
                key_layout.addLayout(row_layout)

                slider = QSlider(Qt.Horizontal)
                slider.setFont(font)
                slider.setRange(0, RANGE)
                slider.setValue(RANGE / 2)

                key_layout.addWidget(slider)

                self.key_map[key] = {
                    'slidervalue': 0,
                    'display': display,
                    'slider': slider
                }
                slider.valueChanged.connect(self.onValueChanged)
                self.gridlayout.addLayout(key_layout, *(y, 0))
                y += 1
                #sliders.append(key_layout)

            # Generate positions in grid and place sliders there
            #self.positions = [(y,0) for y in range(len(sliders))]
            #for item, pos in zip(sliders, self.positions):
            #    self.gridlayout.addLayout(item, *pos)

        self.vlayout.addLayout(self.gridlayout)

        self.ctrbutton = QPushButton('Center', self)
        self.ctrbutton.clicked.connect(self.center)
        self.vlayout.addWidget(self.ctrbutton)

        self.center(1)
Ejemplo n.º 26
0
class HandEyeCalibration(Plugin):
    PLUGIN_TITLE = ' Intel OTC Robotics: Hand-Eye Calibration'

    def __init__(self, context):
        super(HandEyeCalibration, self).__init__(context)
        self.context = context
        self.node = context.node
        self.widget = QWidget()
        self.widget.setObjectName(self.PLUGIN_TITLE)
        self.widget.setWindowTitle(self.PLUGIN_TITLE)

        # Data
        self.Tsamples = []

        # Toolbar
        _, path_pkg = get_resource('packages', 'handeye_dashboard')
        print("{}".format(path_pkg))

        self.snapshot_action = QAction(QIcon.fromTheme('camera-photo'),
                                       'Take a snapshot', self.widget)
        path = path_pkg + '/share/handeye_dashboard/images/capture.png'
        self.calibrate_action = QAction(QIcon(QPixmap.fromImage(QImage(path))),
                                        'Get the camera/robot transform',
                                        self.widget)
        self.clear_action = QAction(QIcon.fromTheme('edit-clear'),
                                    'Clear the record data.', self.widget)
        path = path_pkg + '/share/handeye_dashboard/images/UR5.png'
        self.execut_action = QAction(QIcon(QPixmap.fromImage(QImage(path))),
                                     'EStart the publishing the TF.',
                                     self.widget)
        self.toolbar = QToolBar()
        self.toolbar.addAction(self.snapshot_action)
        self.toolbar.addAction(self.calibrate_action)
        self.toolbar.addAction(self.clear_action)
        self.toolbar.addAction(self.execut_action)

        # Toolbar0
        self.l0 = QLabel(self.widget)
        self.l0.setText("Camera-Mount-Type: ")
        self.l0.setFixedWidth(150)
        self.l0.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.combobox = QComboBox(self.widget)
        self.combobox.addItem('attached on robot')
        self.combobox.addItem('fixed beside robot')
        self.toolbar0 = QToolBar()
        self.toolbar0.addWidget(self.l0)
        self.toolbar0.addWidget(self.combobox)

        # Toolbar1
        self.l1 = QLabel(self.widget)
        self.l1.setText("Camera-Frame: ")
        self.l1.setFixedWidth(150)
        self.l1.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.camera_frame = QLineEdit(self.widget)
        self.camera_frame.setText("camera_link")
        self.toolbar1 = QToolBar()
        self.toolbar1.addWidget(self.l1)
        self.toolbar1.addWidget(self.camera_frame)

        # Toolbar2
        self.l2 = QLabel(self.widget)
        self.l2.setText("Object-Frame: ")
        self.l2.setFixedWidth(150)
        self.l2.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.object_frame = QLineEdit(self.widget)
        self.object_frame.setText("calib_board")
        self.toolbar2 = QToolBar()
        self.toolbar2.addWidget(self.l2)
        self.toolbar2.addWidget(self.object_frame)

        # Toolbar3
        self.l3 = QLabel(self.widget)
        self.l3.setText("Robot-Base-Frame: ")
        self.l3.setFixedWidth(150)
        self.l3.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.base_frame = QLineEdit(self.widget)
        self.base_frame.setText("base")
        self.toolbar3 = QToolBar()
        self.toolbar3.addWidget(self.l3)
        self.toolbar3.addWidget(self.base_frame)

        # Toolbar4
        self.l4 = QLabel(self.widget)
        self.l4.setText("End-Effector-Frame: ")
        self.l4.setFixedWidth(150)
        self.l4.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.endeffector_frame = QLineEdit(self.widget)
        self.endeffector_frame.setText("tool0")
        self.toolbar4 = QToolBar()
        self.toolbar4.addWidget(self.l4)
        self.toolbar4.addWidget(self.endeffector_frame)

        # Toolbar5
        self.l5 = QLabel(self.widget)
        self.l5.setText("Sample-Number: ")
        self.l5.setFixedWidth(150)
        self.l5.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.le5 = QLineEdit(self.widget)
        self.le5.setValidator(QIntValidator())
        self.le5.setText('10')
        self.le5.setReadOnly(True)
        self.toolbar5 = QToolBar()
        self.toolbar5.addWidget(self.l5)
        self.toolbar5.addWidget(self.le5)

        # TreeView
        self.treeview = QTreeView()
        self.treeview.setAlternatingRowColors(True)
        self.model = QStandardItemModel(self.treeview)
        self.treeview.setModel(self.model)
        self.treeview.setHeaderHidden(True)

        # TextEdit
        self.textedit = QTextEdit(self.widget)
        self.textedit.setReadOnly(True)

        # Layout
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.toolbar0)
        self.layout.addWidget(self.toolbar1)
        self.layout.addWidget(self.toolbar2)
        self.layout.addWidget(self.toolbar3)
        self.layout.addWidget(self.toolbar4)
        self.layout.addWidget(self.toolbar5)
        self.layout.addWidget(self.toolbar)
        self.layoutH = QHBoxLayout()
        self.layoutH.addWidget(self.treeview)
        self.layoutH.addWidget(self.textedit)
        self.layout.addLayout(self.layoutH)
        self.widget.setLayout(self.layout)
        # Add the widget to the user interface
        if context.serial_number() > 1:
            self.widget.setWindowTitle(self.widget.windowTitle() +
                                       (' (%d)' % context.serial_number()))
        context.add_widget(self.widget)
        # Make the connections
        self.snapshot_action.triggered.connect(self.take_snapshot)
        self.calibrate_action.triggered.connect(self.calibration)
        self.clear_action.triggered.connect(self.clear)
        self.execut_action.triggered.connect(self.execution)

        # Package path
        self.path_pkg = path_pkg

        # Set up TF
        self.cli = self.node.create_client(HandeyeTF, 'handeye_tf_service')
        while not self.cli.wait_for_service(timeout_sec=1.0):
            self.node.get_logger().info(
                'service not available, waiting again...')
        self.req = HandeyeTF.Request()

    def clear(self):
        # >>> Clear the recorded samples
        self.textedit.append('Clearing the recorded data ...')
        self.textedit.clear()
        self.Tsamples = []
        self.model.clear()

    def get_tf_transform(self, frame_id, child_frame_id):
        self.req.transform.header.frame_id = frame_id
        self.req.transform.child_frame_id = child_frame_id
        self.req.publish.data = False

        future = self.cli.call_async(self.req)
        rclpy.spin_until_future_complete(self.node, future)

        transform = TransformStamped()

        try:
            result = future.result()
        except Exception as e:
            self.node.get_logger().info('Service call failed %r' % (e, ))
        else:
            transform = result.tf_lookup_result

        return transform

    def publish_tf_transform(self, transform_to_publish):
        self.req.publish.data = True
        self.req.transform = transform_to_publish

        future = self.cli.call_async(self.req)
        rclpy.spin_until_future_complete(self.node, future)

        try:
            future.result()
        except Exception as e:
            self.node.get_logger().info('Service call failed %r' % (e, ))
        else:
            self.node.get_logger().info(
                'Send the camera-robot transform :\n\tfrom `{}` to `{}`.'.
                format(self.req.transform.header.frame_id,
                       self.req.transform.child_frame_id))

    def take_snapshot(self):
        # >>> Take the snapshot
        self.textedit.append('Taking snapshot ...')

        # Get the transform from `tool0` to `base_link`
        T = self.get_tf_transform(self.base_frame.text(),
                                  self.endeffector_frame.text())
        bTe = np.zeros((4, 4))
        q = [
            T.transform.rotation.w, T.transform.rotation.x,
            T.transform.rotation.y, T.transform.rotation.z
        ]
        bTe = br.quaternion.to_transform(q)
        bTe[:3, 3] = np.array([
            T.transform.translation.x, T.transform.translation.y,
            T.transform.translation.z
        ])
        self.textedit.append('Lookup transform: from `{}` to `{}`.'.format(
            self.base_frame.text(), self.endeffector_frame.text()))
        self.node.get_logger().info(bcolors.OKGREEN + 'bTe:' + bcolors.ENDC +
                                    '\n{}'.format(bTe))

        # Get the transform from `calib_board` to `camera_link`
        T = self.get_tf_transform(self.camera_frame.text(),
                                  self.object_frame.text())
        cTo = np.zeros((4, 4))
        q = [
            T.transform.rotation.w, T.transform.rotation.x,
            T.transform.rotation.y, T.transform.rotation.z
        ]
        cTo = br.quaternion.to_transform(q)
        cTo[:3, 3] = np.array([
            T.transform.translation.x, T.transform.translation.y,
            T.transform.translation.z
        ])
        self.textedit.append('Lookup transform: from `{}` to `{}`.'.format(
            self.camera_frame.text(), self.object_frame.text()))
        self.node.get_logger().info(bcolors.OKGREEN + 'cTo:' + bcolors.ENDC +
                                    '\n{}'.format(cTo))

        parent = QStandardItem('Snapshot {}'.format(len(self.Tsamples)))
        child_1 = QStandardItem('bTe:\n{}\n{}\n{}\n{}'.format(
            bTe[0, :], bTe[1, :], bTe[2, :], bTe[3, :]))
        child_2 = QStandardItem('cTo:\n{}\n{}\n{}\n{}'.format(
            cTo[0, :], cTo[1, :], cTo[2, :], cTo[3, :]))
        parent.appendRow(child_1)
        parent.appendRow(child_2)
        self.model.appendRow(parent)
        self.Tsamples.append((bTe, cTo))
        self.le5.setText(str(len(self.Tsamples)))

    def calibration(self):
        # >>> Compute the calibration
        self.textedit.append('Making the calibration ...')
        if len(self.Tsamples) == 0:
            self.textedit.append(
                'No transform recorded, please take snapshots.')
            return
        # save samples to `dataset.json` file
        save_samples_to_file(self.Tsamples)
        import handeye
        if self.combobox.currentIndex() == 0:
            solver_cri = handeye.calibrator.HandEyeCalibrator(setup='Moving')
        if self.combobox.currentIndex() == 1:
            solver_cri = handeye.calibrator.HandEyeCalibrator(setup='Fixed')
        for sample in self.Tsamples:
            solver_cri.add_sample(sample[0], sample[1])
        try:
            bTc = solver_cri.solve(method=handeye.solver.Daniilidis1999)
            # save the calibration result to 'camera-robot.json' file
            file_output = '/tmp/' + 'camera-robot.json'
            with open(file_output, 'w') as f:
                json.dump(bTc.tolist(), f)
        except Exception:
            self.textedit.append("Failed to solve the hand-eye calibration.")

    def execution(self):
        # >>> Publish the camera-robot transform
        self.textedit.append('Publishing the camera TF ...')
        file_input = '/tmp/' + 'camera-robot.json'
        with open(file_input, 'r') as f:
            datastore = json.load(f)

        to_frame = self.camera_frame.text()
        if self.combobox.currentIndex() == 0:
            from_frame = self.endeffector_frame.text()
        if self.combobox.currentIndex() == 1:
            from_frame = self.base_frame.text()

        bTc = np.array(datastore)
        static_transformStamped = TransformStamped()
        static_transformStamped.header.stamp = ROSClock().now().to_msg()
        static_transformStamped.header.frame_id = from_frame
        static_transformStamped.child_frame_id = to_frame

        static_transformStamped.transform.translation.x = bTc[0, 3]
        static_transformStamped.transform.translation.y = bTc[1, 3]
        static_transformStamped.transform.translation.z = bTc[2, 3]

        q = br.transform.to_quaternion(bTc)
        static_transformStamped.transform.rotation.x = q[1]
        static_transformStamped.transform.rotation.y = q[2]
        static_transformStamped.transform.rotation.z = q[3]
        static_transformStamped.transform.rotation.w = q[0]

        self.publish_tf_transform(static_transformStamped)

        output_string = "camera-robot pose:\n"
        output_string += "  Translation: [{}, {}, {}]\n".format(
            bTc[0, 3], bTc[1, 3], bTc[2, 3])
        output_string += "  Rotation: in Quaternion [{}, {}, {}, {}]".format(
            q[0], q[1], q[2], q[3])
        file_path = '/tmp/' + 'camera-robot.txt'
        with open(file_path, 'w') as f:
            f.write(output_string)

    def shutdown_plugin(self):
        """
    Unregister subscribers when the plugin shutdown
    """
        pass

    def save_settings(self, plugin_settings, instance_settings):
        # Nothing to be done here
        pass

    def restore_settings(self, plugin_settings, instance_settings):
        # Nothing to be done here
        pass
Ejemplo n.º 27
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)
Ejemplo n.º 28
0
    def setup(self):
        layout = QGridLayout()

        # Sidebar
        self.benchmark_combo_box = QComboBox()
        for key in self.config['benchmarks'].keys():
            self.benchmark_combo_box.addItem(
                self.config['benchmarks'][key]['name'])
        self.benchmark_combo_box.currentIndexChanged.connect(
            self._handle_benchmark_selected)
        self.benchmark_combo_box.setMaximumWidth(SIDEBAR_WIDTH)
        self.set_current_benchmark()

        self.team_combo_box = QComboBox()
        for key in self.config['teams']:
            self.team_combo_box.addItem(key)
        self.team_combo_box.setMaximumWidth(SIDEBAR_WIDTH)
        self.test_communication_button = QPushButton('Test communication')
        self.test_communication_button.clicked.connect(self._handle_test_comm)

        self.trial_list_widget = QListWidget()
        self.trial_list_widget.currentItemChanged.connect(
            self._handle_trial_change)
        self.trial_list_widget.setMaximumWidth(SIDEBAR_WIDTH)

        sidebar_layout = QVBoxLayout()
        sidebar_layout.addWidget(QLabel("Team"))
        sidebar_layout.addWidget(self.team_combo_box)
        sidebar_layout.addWidget(self.test_communication_button)
        sidebar_layout.addWidget(QLabel("Benchmark"))
        sidebar_layout.addWidget(self.benchmark_combo_box)
        sidebar_layout.addWidget(QLabel("Trial"))
        sidebar_layout.addWidget(self.trial_list_widget)

        self.generate_button = QPushButton('Generate')
        self.generate_button.clicked.connect(self._handle_generate)

        self.delete_button = QPushButton('Delete')
        self.delete_button.clicked.connect(self._handle_delete)

        self.save_trials_button = QPushButton('Save')
        self.save_trials_button.clicked.connect(self._handle_save_trial_config)

        self.lock_button = QPushButton('Lock')
        if self.config_locked:
            self.lock_button.setText('Unlock')
        self.lock_button.clicked.connect(self._handle_lock)

        sidebar_button_layout = QGridLayout()
        sidebar_button_layout.addWidget(self.generate_button, 0, 0)
        sidebar_button_layout.addWidget(self.delete_button, 0, 1)
        sidebar_button_layout.addWidget(self.save_trials_button, 1, 0)
        sidebar_button_layout.addWidget(self.lock_button, 1, 1)
        sidebar_layout.addLayout(sidebar_button_layout)

        layout.addLayout(sidebar_layout, 0, 0)

        # Status box
        self.status = QPlainTextEdit()
        self.status.setReadOnly(True)
        self.status.setMaximumHeight(200)

        # row 1, col 0, rowspan 1, colspan 2
        layout.addWidget(self.status, 1, 0, 1, 2)

        # trial config and results
        trial_layout = QVBoxLayout()
        self.trial_config_layout = QHBoxLayout()
        self.trial_results_layout = QVBoxLayout()
        self.setup_trial_config()

        # benchmark trial controls
        benchmark_controls_group_box = QGroupBox('Controls')
        benchmark_controls_layout = QHBoxLayout()
        self.start_trial_button = QPushButton('Start')
        self.start_trial_button.clicked.connect(self._handle_start_trial)
        self.stop_trial_button = QPushButton('Stop')
        self.stop_trial_button.clicked.connect(self._handle_stop_trial)
        self.prev_trial_button = QPushButton('Previous')
        self.prev_trial_button.clicked.connect(self._handle_prev_trial)
        self.next_trial_button = QPushButton('Next')
        self.next_trial_button.clicked.connect(self._handle_next_trial)
        self.start_continuous_recording_button = QPushButton(
            'Start continuous recording')
        self.start_continuous_recording_button.clicked.connect(
            self._handle_continuous_recording)

        self.timer_field = QLabel()
        font = QFont("Arial", 20, QFont.Bold)
        self.timer_field.setFont(font)
        self.timer_field.setAutoFillBackground(True)
        benchmark_controls_layout.addWidget(self.start_trial_button)
        benchmark_controls_layout.addWidget(self.stop_trial_button)
        benchmark_controls_layout.addWidget(self.prev_trial_button)
        benchmark_controls_layout.addWidget(self.next_trial_button)
        benchmark_controls_layout.addWidget(
            self.start_continuous_recording_button)
        benchmark_controls_layout.addWidget(self.timer_field)
        benchmark_controls_group_box.setLayout(benchmark_controls_layout)

        trial_layout.addLayout(self.trial_config_layout)
        trial_layout.addWidget(benchmark_controls_group_box)
        trial_layout.addLayout(self.trial_results_layout)
        self.save_results_button = QPushButton('Save results')
        self.save_results_button.clicked.connect(self._handle_save_result)
        trial_layout.addWidget(self.save_results_button)

        layout.addLayout(trial_layout, 0, 1)

        self.setLayout(layout)
        self.show()

        self.show_env_var('ROS_MASTER_URI')
        self.show_env_var('ROS_IP')
        self.show_env_var('ROS_HOSTNAME')