Exemplo n.º 1
0
    def __init__(self):
        super(ServiceTabbedButtonGeneralWidget, self).__init__()
        self._tab_settings = None

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

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

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

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

        #self.setWindowTitle('Tab Layout')
        hbox = QHBoxLayout()
        hbox.addWidget(qtab)
        self.setLayout(hbox)
        self.show()
Exemplo n.º 2
0
    def __init__(self, parent, updater, config):
        super(TabGroup, self).__init__(updater, config)
        self.parent = parent

        if not self.parent.tab_bar:
            self.parent.tab_bar = QTabWidget()

        parent.tab_bar.addTab(self, self.name)
Exemplo n.º 3
0
    def __init__(self, parent, updater, config, nodename):
        super(TabGroup, self).__init__(updater, config, nodename)
        self.parent = parent

        if not self.parent.tab_bar:
            self.parent.tab_bar = QTabWidget()

        self.wid = QWidget()
        self.wid.setLayout(self.grid)

        parent.tab_bar.addTab(self.wid, self.param_name)
Exemplo n.º 4
0
    def __init__(self, context):
        super(MoveitCommanderWidget, self).__init__()
        self.setObjectName('MoveitCommanderWidget')

        self.groups = self.get_groups()
        self.commanders = [
            moveit_commander.MoveGroupCommander(group) for group in self.groups
        ]

        # list of QLineEdit fields used to display joint values
        self.text_joint_values = []

        self.MAX_COLUMNS = 4

        self.tab_widget = QTabWidget()
        for g in self.groups:
            frame = self.setup_group_frame(g)
            self.tab_widget.addTab(frame, g)

        widget_layout = QVBoxLayout()
        widget_layout.addWidget(self.tab_widget)
        self.setLayout(widget_layout)
Exemplo n.º 5
0
class PlotDialogWidget(QDialog):
    newPlotData = QtCore.Signal(object, object)

    def __init__(self, bagFiles, parent=None):
        super(PlotDialogWidget, self).__init__()
        self.parent = parent
        self.bagFiles = bagFiles
        self.setWindowTitle("Add new Graph")
        self.layout = QVBoxLayout()
        self.resize(600, 400)

        # init the components
        self.tabWidget = QTabWidget()
        self.rawDataTab = RawDataTab(bagFiles, self)
        self.compareTab = CompareDataTab(bagFiles, self)
        self.diffTab = DiffTab(bagFiles, self)
        self.tabWidget.addTab(self.rawDataTab, "Raw Data Graphs")
        self.tabWidget.addTab(self.compareTab, "Evaluation Graphs")
        self.tabWidget.addTab(self.diffTab, "Difference Graphs")
        self.layout.addWidget(self.tabWidget)

        # init the start button
        startBtn = QPushButton("Start")
        startBtn.clicked.connect(self.startPressed)
        self.layout.addWidget(startBtn)

        self.setLayout(self.layout)

    def startPressed(self):
        '''
            is called when the start button is clicked
            calls the function to get the data to plot
            dependent on what tab is selected            
        '''
        currentTab = self.tabWidget.currentIndex()
        try:

            if currentTab == 0:  # rawDataTab is active
                plotData, plotInfo = self.rawDataTab.getPlotData()
            elif currentTab == 1:  #
                plotData, plotInfo = self.compareTab.getPlotData()
            elif currentTab == 2:
                plotData, plotInfo = self.diffTab.getPlotData()

            # emit signal with data
            self.newPlotData.emit(plotData, plotInfo)

            # close dialog
            self.close()

        except Exception as e:
            msg_box = QMessageBox(QMessageBox.Critical, 'Error', str(e))
            msg_box.exec_()
Exemplo n.º 6
0
    def __init__(self, parent, updater, config, nodename):
        super(TabGroup, self).__init__(updater, config, nodename)
        self.parent = parent

        if not self.parent.tab_bar:
            self.parent.tab_bar = QTabWidget()

            # Don't process wheel events when not focused
            self.parent.tab_bar.tabBar().installEventFilter(self)

        self.wid = QWidget()
        self.wid.setLayout(self.grid)

        parent.tab_bar.addTab(self.wid, self.param_name)
Exemplo n.º 7
0
    def __init__(self, bagFiles, parent=None):
        super(PlotDialogWidget, self).__init__()
        self.parent = parent
        self.bagFiles = bagFiles
        self.setWindowTitle("Add new Graph")
        self.layout = QVBoxLayout()
        self.resize(600, 400)

        # init the components
        self.tabWidget = QTabWidget()
        self.rawDataTab = RawDataTab(bagFiles, self)
        self.compareTab = CompareDataTab(bagFiles, self)
        self.diffTab = DiffTab(bagFiles, self)
        self.tabWidget.addTab(self.rawDataTab, "Raw Data Graphs")
        self.tabWidget.addTab(self.compareTab, "Evaluation Graphs")
        self.tabWidget.addTab(self.diffTab, "Difference Graphs")
        self.layout.addWidget(self.tabWidget)

        # init the start button
        startBtn = QPushButton("Start")
        startBtn.clicked.connect(self.startPressed)
        self.layout.addWidget(startBtn)

        self.setLayout(self.layout)
class MoveitCommanderWidget(QWidget):
    """
    Provides a UI for Moveit Commander
    - parses rosparam 'robot_description_semantic' to get content of robot srdf
    - there are tabs for each move_group group
    - for each group, there is a set of buttons with the named targets
    - for each group, there is a button to get current joint values and a button to move to specific joint values
    """
    def __init__(self, context):
        super(MoveitCommanderWidget, self).__init__()
        self.setObjectName('MoveitCommanderWidget')

        self.robot = SRDF.from_parameter_server()
        self.groups = self.get_groups()
        self.commanders = [
            moveit_commander.MoveGroupCommander(group) for group in self.groups
        ]

        # list of QLineEdit fields used to display joint values
        self.text_joint_values = []

        self.MAX_COLUMNS = 4

        self.tab_widget = QTabWidget()
        for g in self.groups:
            frame = self.setup_group_frame(g)
            self.tab_widget.addTab(frame, g)

        widget_layout = QVBoxLayout()
        widget_layout.addWidget(self.tab_widget)
        self.setLayout(widget_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

    def _handle_button_clicked(self, button):
        commander = self.commanders[self.tab_widget.currentIndex()]
        rospy.loginfo('Moving ' + commander.get_name() + ' to: ' +
                      button.text())
        try:
            commander.set_named_target(str(button.text()))
        except Exception as e:
            rospy.logerr('Unable to set target: %s' % (str(e)))
            return

        error_code = commander.go(wait=True)
        if error_code == moveit_msgs.msg.MoveItErrorCodes.SUCCESS:
            rospy.loginfo("Succeeded")
        else:
            rospy.logerr("Movement failed with error code: %d", error_code)

    def _handle_show_joint_values_clicked(self, checked):
        commander = self.commanders[self.tab_widget.currentIndex()]
        l = commander.get_current_joint_values()
        l = [round(ll, 6) for ll in l]
        self.text_joint_values[self.tab_widget.currentIndex()].setText(str(l))

    def _handle_move_to_clicked(self, checked):
        commander = self.commanders[self.tab_widget.currentIndex()]
        # parse string as list
        l = ast.literal_eval(
            str(self.text_joint_values[self.tab_widget.currentIndex()].text()))

        if all(isinstance(x, float) for x in l):
            try:
                commander.set_joint_value_target(l)
            except Exception as e:
                rospy.logerr('Unable to set target position: %s' % (str(e)))
                return
            error_code = commander.go(wait=True)
            if error_code == moveit_msgs.msg.MoveItErrorCodes.SUCCESS:
                rospy.loginfo("Succeeded")
            else:
                rospy.logerr("Movement failed with error code: %d", error_code)

        else:
            rospy.logerr("Malformed joint angle list")

    def get_named_targets(self, group_name):
        '''
        Return list of group states associated with `group_name`
        '''
        group_states = self.robot.group_state_map.keys()
        named_targets = []
        for group_state in group_states:
            if self.robot.group_state_map[group_state].group == group_name:
                named_targets.append(group_state)
        return named_targets

    def get_groups(self):
        '''
        Return list of joint group names
        '''
        return self.robot.group_map.keys()
Exemplo n.º 9
0
    def __init__(self, context):
        """
        Create Qt GUI using the event file
        """
        super(EventTransmissionGUI, self).__init__(context)
        self.setObjectName('ManualEventTriggerGUI')
        parser = ArgumentParser()

        # Add argument(s) to the parser.
        args = self._parse_args(context.argv())

        ## Create Event trigger
        self.event_trigger = RosEventTrigger(args.event_file)

        ## Parent container to store buttons, textboxes
        self._container = QTabWidget()
        ## Tab to display robot system, state machine status
        ## and command buttons without any arguments
        self._status_tab = QWidget()
        ## Tab to display positionyaw and velocityyaw commands
        ## and sliders for them
        self._additional_commands_tab = QWidget()
        # Set title of the parent container window
        self._status_tab.setWindowTitle(self.event_trigger.event_manager_name)
        ## Layout for status tab
        self._layout = QVBoxLayout()
        self._status_tab.setLayout(self._layout)

        # Create Textboxes and add to Layout
        self._layout.addWidget(QLabel('State Machine State'))
        ## Textbox to show sytem status
        self.system_status_textbox = QTextEdit()
        self.system_status_textbox.setReadOnly(True)
        self._layout.addWidget(self.system_status_textbox)

        # Define and connect buttons
        self._layout.addWidget(QLabel('Event Triggers'))
        ## Continer to store event triggering buttons
        self.button_container = QWidget()
        ## List of push buttons to trigger events
        self.push_buttons = list()
        ## Layout for the push buttons
        self.button_layout = QGridLayout()
        self.button_container.setLayout(self.button_layout)
        button_index = 0
        for event_name in self.event_trigger.event_names_list:
            self.push_buttons.append(QPushButton(event_name))
            partial_fun = partial(self.event_trigger.triggerEvent,
                                  event_name=event_name)
            self.push_buttons[-1].clicked.connect(partial_fun)
            row, col = self.get_row_col(button_index, args.grid_cols)
            self.button_layout.addWidget(self.push_buttons[-1], row, col)
            button_index += 1
        self._layout.addWidget(self.button_container)

        ## Layout for additional commands tab
        self._additional_commands_layout = QVBoxLayout()
        self._additional_commands_tab.setLayout(
            self._additional_commands_layout)
        # Create height slider
        self._additional_commands_layout.addWidget(
            QLabel('Pose Command Height (m)'))
        ## Height slider to adjust z coordinate for pose command
        ## \todo Matt: Load slider settings from param file
        self.height_slider = self.createSlider(1.0, 20.0, 2.0, 1.0)
        self._additional_commands_layout.addWidget(self.height_slider)
        ## Add button for triggering pose command
        ## Container for pose event related objects: slide etc
        ## \todo Matt: Reset slider value based on current quad height
        self.pose_command_container = QWidget()
        ## Pose command layout
        self.pose_command_layout = QGridLayout()
        self.pose_command_container.setLayout(self.pose_command_layout)
        ## x pose label to display position command from rviz to user
        self.pose_x = QLabel('x: -')
        ## y pose label to display position command from rviz to user
        self.pose_y = QLabel('y: -')
        ## z pose label to display position command from rviz to user
        self.pose_z = QLabel("z: {0:.2f}".format(self.height_slider.value()))
        self.height_slider.valueChanged.connect(
            partial(self.updateLabel,
                    header="z",
                    label=self.pose_z,
                    slider=self.height_slider))
        self.pose_command_layout.addWidget(self.pose_x, 0, 0)
        self.pose_command_layout.addWidget(self.pose_y, 0, 1)
        self.pose_command_layout.addWidget(self.pose_z, 0, 2)
        ## Button to send the pose command to state machine as poseyaw event
        self.send_pose_command_button = QPushButton("Send Pose Command")
        self.send_pose_command_button.clicked.connect(
            self.poseCommandButtonCallback)
        self.pose_command_layout.addWidget(self.send_pose_command_button, 0, 3)
        self._additional_commands_layout.addWidget(self.pose_command_container)
        ## Pose command container to store pose from Rviz and send to state
        ## machine
        self.pose_command = None
        ## Sliders for setting vx,vy,vz, yaw
        self.velocity_sliders = []
        ## Labels vx,vy,vz,yaw as an array
        self.velocity_command_labels = []
        self._additional_commands_layout.addWidget(
            QLabel('Velocity Command (m/s), Yaw (deg)'))
        for i in range(3):
            self.velocity_sliders.append(
                self.createSlider(-20.0, 20.0, 0.0, 1.0))
            self._additional_commands_layout.addWidget(
                self.velocity_sliders[i])
        # Slider for yaw
        self.velocity_sliders.append(
            self.createSlider(-180.0, 180.0, 0.0, 10.0))
        self._additional_commands_layout.addWidget(self.velocity_sliders[-1])
        ## Add button for triggering velocity yaw
        self.velocity_command_container = QWidget()
        ## Velocity command layout
        self.velocity_command_layout = QGridLayout()
        self.velocity_command_container.setLayout(self.velocity_command_layout)
        for i, axis_label in enumerate(['x', 'y', 'z']):
            # label to display velocity command from rviz to user
            self.velocity_command_labels.append(
                QLabel("v{0}: {1:.2f}".format(
                    axis_label, self.velocity_sliders[i].value() / 10.0)))
            self.velocity_sliders[i].valueChanged.connect(
                partial(self.updateLabel,
                        header="v" + str(i),
                        label=self.velocity_command_labels[i],
                        slider=self.velocity_sliders[i],
                        scale=10.0))
            self.velocity_command_layout.addWidget(
                self.velocity_command_labels[i], 0, i)
        # Label for yaw
        self.velocity_command_labels.append(
            QLabel("Yaw: {0:.2f}".format(self.velocity_sliders[-1].value())))
        self.velocity_sliders[-1].valueChanged.connect(
            partial(self.updateLabel,
                    header="Yaw",
                    label=self.velocity_command_labels[-1],
                    slider=self.velocity_sliders[-1]))
        self.velocity_command_layout.addWidget(
            self.velocity_command_labels[-1], 0, 3)
        ## Button to send the pose command to state machine as poseyaw event
        self.send_velocity_command_button = QPushButton(
            "Send Velocity Command")
        self.send_velocity_command_button.clicked.connect(
            self.velocityCommandButtonCallback)
        self.velocity_command_layout.addWidget(
            self.send_velocity_command_button, 0, 4)
        self._additional_commands_layout.addWidget(
            self.velocity_command_container)
        self._additional_commands_layout.addStretch()

        self._container.addTab(self._status_tab, "StatusBasicCommands")
        self._container.addTab(self._additional_commands_tab,
                               "AdditionalCommands")
        context.add_widget(self._container)

        # Add textboxes to update hooks from eventTrigger class
        # Define Partial callbacks
        systemStatusCallback = partial(self.updateStatus,
                                       text_box=self.system_status_textbox)
        # Connect Event Triggers
        self.event_trigger.status_signal.connect(systemStatusCallback)
        self.event_trigger.pose_command_signal.connect(
            self.poseCommandCallback)
Exemplo n.º 10
0
class EventTransmissionGUI(Plugin):
    """
    GUI to send events from User to logic state machine
    """
    def __init__(self, context):
        """
        Create Qt GUI using the event file
        """
        super(EventTransmissionGUI, self).__init__(context)
        self.setObjectName('ManualEventTriggerGUI')
        parser = ArgumentParser()

        # Add argument(s) to the parser.
        args = self._parse_args(context.argv())

        ## Create Event trigger
        self.event_trigger = RosEventTrigger(args.event_file)

        ## Parent container to store buttons, textboxes
        self._container = QTabWidget()
        ## Tab to display robot system, state machine status
        ## and command buttons without any arguments
        self._status_tab = QWidget()
        ## Tab to display positionyaw and velocityyaw commands
        ## and sliders for them
        self._additional_commands_tab = QWidget()
        # Set title of the parent container window
        self._status_tab.setWindowTitle(self.event_trigger.event_manager_name)
        ## Layout for status tab
        self._layout = QVBoxLayout()
        self._status_tab.setLayout(self._layout)

        # Create Textboxes and add to Layout
        self._layout.addWidget(QLabel('State Machine State'))
        ## Textbox to show sytem status
        self.system_status_textbox = QTextEdit()
        self.system_status_textbox.setReadOnly(True)
        self._layout.addWidget(self.system_status_textbox)

        # Define and connect buttons
        self._layout.addWidget(QLabel('Event Triggers'))
        ## Continer to store event triggering buttons
        self.button_container = QWidget()
        ## List of push buttons to trigger events
        self.push_buttons = list()
        ## Layout for the push buttons
        self.button_layout = QGridLayout()
        self.button_container.setLayout(self.button_layout)
        button_index = 0
        for event_name in self.event_trigger.event_names_list:
            self.push_buttons.append(QPushButton(event_name))
            partial_fun = partial(self.event_trigger.triggerEvent,
                                  event_name=event_name)
            self.push_buttons[-1].clicked.connect(partial_fun)
            row, col = self.get_row_col(button_index, args.grid_cols)
            self.button_layout.addWidget(self.push_buttons[-1], row, col)
            button_index += 1
        self._layout.addWidget(self.button_container)

        ## Layout for additional commands tab
        self._additional_commands_layout = QVBoxLayout()
        self._additional_commands_tab.setLayout(
            self._additional_commands_layout)
        # Create height slider
        self._additional_commands_layout.addWidget(
            QLabel('Pose Command Height (m)'))
        ## Height slider to adjust z coordinate for pose command
        ## \todo Matt: Load slider settings from param file
        self.height_slider = self.createSlider(1.0, 20.0, 2.0, 1.0)
        self._additional_commands_layout.addWidget(self.height_slider)
        ## Add button for triggering pose command
        ## Container for pose event related objects: slide etc
        ## \todo Matt: Reset slider value based on current quad height
        self.pose_command_container = QWidget()
        ## Pose command layout
        self.pose_command_layout = QGridLayout()
        self.pose_command_container.setLayout(self.pose_command_layout)
        ## x pose label to display position command from rviz to user
        self.pose_x = QLabel('x: -')
        ## y pose label to display position command from rviz to user
        self.pose_y = QLabel('y: -')
        ## z pose label to display position command from rviz to user
        self.pose_z = QLabel("z: {0:.2f}".format(self.height_slider.value()))
        self.height_slider.valueChanged.connect(
            partial(self.updateLabel,
                    header="z",
                    label=self.pose_z,
                    slider=self.height_slider))
        self.pose_command_layout.addWidget(self.pose_x, 0, 0)
        self.pose_command_layout.addWidget(self.pose_y, 0, 1)
        self.pose_command_layout.addWidget(self.pose_z, 0, 2)
        ## Button to send the pose command to state machine as poseyaw event
        self.send_pose_command_button = QPushButton("Send Pose Command")
        self.send_pose_command_button.clicked.connect(
            self.poseCommandButtonCallback)
        self.pose_command_layout.addWidget(self.send_pose_command_button, 0, 3)
        self._additional_commands_layout.addWidget(self.pose_command_container)
        ## Pose command container to store pose from Rviz and send to state
        ## machine
        self.pose_command = None
        ## Sliders for setting vx,vy,vz, yaw
        self.velocity_sliders = []
        ## Labels vx,vy,vz,yaw as an array
        self.velocity_command_labels = []
        self._additional_commands_layout.addWidget(
            QLabel('Velocity Command (m/s), Yaw (deg)'))
        for i in range(3):
            self.velocity_sliders.append(
                self.createSlider(-20.0, 20.0, 0.0, 1.0))
            self._additional_commands_layout.addWidget(
                self.velocity_sliders[i])
        # Slider for yaw
        self.velocity_sliders.append(
            self.createSlider(-180.0, 180.0, 0.0, 10.0))
        self._additional_commands_layout.addWidget(self.velocity_sliders[-1])
        ## Add button for triggering velocity yaw
        self.velocity_command_container = QWidget()
        ## Velocity command layout
        self.velocity_command_layout = QGridLayout()
        self.velocity_command_container.setLayout(self.velocity_command_layout)
        for i, axis_label in enumerate(['x', 'y', 'z']):
            # label to display velocity command from rviz to user
            self.velocity_command_labels.append(
                QLabel("v{0}: {1:.2f}".format(
                    axis_label, self.velocity_sliders[i].value() / 10.0)))
            self.velocity_sliders[i].valueChanged.connect(
                partial(self.updateLabel,
                        header="v" + str(i),
                        label=self.velocity_command_labels[i],
                        slider=self.velocity_sliders[i],
                        scale=10.0))
            self.velocity_command_layout.addWidget(
                self.velocity_command_labels[i], 0, i)
        # Label for yaw
        self.velocity_command_labels.append(
            QLabel("Yaw: {0:.2f}".format(self.velocity_sliders[-1].value())))
        self.velocity_sliders[-1].valueChanged.connect(
            partial(self.updateLabel,
                    header="Yaw",
                    label=self.velocity_command_labels[-1],
                    slider=self.velocity_sliders[-1]))
        self.velocity_command_layout.addWidget(
            self.velocity_command_labels[-1], 0, 3)
        ## Button to send the pose command to state machine as poseyaw event
        self.send_velocity_command_button = QPushButton(
            "Send Velocity Command")
        self.send_velocity_command_button.clicked.connect(
            self.velocityCommandButtonCallback)
        self.velocity_command_layout.addWidget(
            self.send_velocity_command_button, 0, 4)
        self._additional_commands_layout.addWidget(
            self.velocity_command_container)
        self._additional_commands_layout.addStretch()

        self._container.addTab(self._status_tab, "StatusBasicCommands")
        self._container.addTab(self._additional_commands_tab,
                               "AdditionalCommands")
        context.add_widget(self._container)

        # Add textboxes to update hooks from eventTrigger class
        # Define Partial callbacks
        systemStatusCallback = partial(self.updateStatus,
                                       text_box=self.system_status_textbox)
        # Connect Event Triggers
        self.event_trigger.status_signal.connect(systemStatusCallback)
        self.event_trigger.pose_command_signal.connect(
            self.poseCommandCallback)

    def createSlider(self, minimum, maximum, default_value, tick_interval):
        """
        Create a QtSlider with specified properties

        Parameters:
        @param minimum Minimum value for slider
        @param maximum Maximum value for slider
        @param default_value Initial value the slider is set to
        @param tick_inverval Integer value specifying difference between
                        successive ticks
        @return Slider value
        """
        slider = QSlider(Qt.Horizontal)
        slider.setMinimum(minimum)
        slider.setMaximum(maximum)
        slider.setValue(default_value)
        slider.setTickPosition(QSlider.TicksBelow)
        slider.setTickInterval(tick_interval)
        return slider

    def _parse_args(self, argv):
        """
        Parse extra arguments when plugin is deployed in standalone mode
        """
        parser = argparse.ArgumentParser(prog='aerial_autonomy',
                                         add_help=False)
        EventTransmissionGUI.add_arguments(parser)
        return parser.parse_args(argv)

    @staticmethod
    def add_arguments(parser):
        """
        Notify rqt_gui that this plugin can parse these extra arguments
        """
        group = parser.add_argument_group(
            'Options for aerial autonomy gui plugin')
        group.add_argument("-e",
                           "--event_file",
                           type=str,
                           default='',
                           help="Event file")
        group.add_argument("-c",
                           "--grid_cols",
                           type=int,
                           default=3,
                           help="Number of columns in grid")

    def get_row_col(self, button_index, ncols):
        """
        Automatically find the row and col to add the button
        to in a grid based on index of the button
        """
        col_index = button_index % ncols
        row_index = int((button_index - col_index) / ncols)
        return (row_index, col_index)

    def poseCommandCallback(self, pose):
        """
        Saves pose command and updates command display
        """
        self.pose_command = pose
        self.pose_x.setText("x: {0:.2f}".format(
            self.pose_command.pose.position.x))
        self.pose_y.setText("y: {0:.2f}".format(
            self.pose_command.pose.position.y))

    def poseCommandButtonCallback(self):
        """
        Publishes stored pose command after setting height from slider
        """
        if self.pose_command:
            self.pose_command.pose.position.z = self.height_slider.value()
            self.event_trigger.triggerPoseCommand(self.pose_command)
            # Reset pose command to avoid accidental triggering
            self.pose_command = None
            self.pose_x.setText('x: -')
            self.pose_y.setText('y: -')
        else:
            print "No pose command to trigger"

    def velocityCommandButtonCallback(self):
        """
        Publishes stored velocity command
        """
        velocity_command = VelocityYaw()
        velocity_command.vx = self.velocity_sliders[0].value() / 10.0
        velocity_command.vy = self.velocity_sliders[1].value() / 10.0
        velocity_command.vz = self.velocity_sliders[2].value() / 10.0
        velocity_command.yaw = self.velocity_sliders[3].value() * np.pi / 180.0
        self.event_trigger.triggerVelocityCommand(velocity_command)

    def updateLabel(self, header, label, slider, scale=1):
        """
        Updates height label based on slider value
        """
        label.setText(header + ": {0:.2f}".format(slider.value() / scale))

    def updateStatus(self, status, text_box):
        """
        Generic placeholder function to update text box
        """
        if not sip.isdeleted(text_box):
            text_box.setHtml(status)
            doc_size = text_box.document().size()
            text_box.setFixedHeight(doc_size.height() + 10)