class TopicSelection(QWidget):

    recordSettingsSelected = Signal(bool, list)

    def __init__(self):
        super(TopicSelection, self).__init__()
        master = rosgraph.Master('rqt_bag_recorder')
        self.setWindowTitle("Select the topics you want to record")
        self.resize(500, 700)

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

        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.from_nodes_button = QPushButton("From Nodes", self)
        self.from_nodes_button.clicked.connect(self.onFromNodesButtonClicked)

        self.main_vlayout = QVBoxLayout(self)
        self.main_vlayout.addWidget(self.area)
        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 = QCheckBox("All", self)
        self.item_monitor = QCheckBox("Monitor", self)
        self.item_monAge = QCheckBox("Monitor + Agents", self)
        self.item_all.stateChanged.connect(self.updateList)
        self.item_monitor.stateChanged.connect(lambda x: self.updateList(x, "Monitor"))
        self.item_monAge.stateChanged.connect(lambda x: self.updateList(x, "Monitor+"))
        self.selection_vlayout.addWidget(self.item_all)
        self.selection_vlayout.addWidget(self.item_monitor)
        self.selection_vlayout.addWidget(self.item_monAge)
        topic_data_list = master.getPublishedTopics('')
        topic_data_list.sort()
        for topic, datatype in topic_data_list:
            self.addCheckBox(topic)

        self.main_widget.setLayout(self.selection_vlayout)

        self.area.setWidget(self.main_widget)
        self.show()

    def addCheckBox(self, topic):
        self.topic_list.append(topic)
        item = QCheckBox(topic, self)
        item.stateChanged.connect(lambda x: self.updateList(x, topic))
        self.items_list.append(item)
        self.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)
        elif topic == "Monitor" or topic == "Monitor+":
            if state == Qt.Checked:
                self.item_monitor.setTristate(False)
                self.selected_topics.append("/world_model")
                self.selected_topics.append("/draws")
                self.selected_topics.append("/debugs")
                self.selected_topics.append("/referee")
                for item in self.items_list:
                    if item.text() == "/world_model" \
                            or item.text() == "/debugs" \
                            or item.text() == "/draws" \
                            or item.text() =="/referee":
                        item.setCheckState(Qt.Checked)
            elif state == Qt.Unchecked:
                self.item_all.setTristate(False)
                self.selected_topics.remove("/world_model")
                self.selected_topics.remove("/draws")
                self.selected_topics.remove("/debugs")
                self.selected_topics.remove("/referee")
                for item in self.items_list:
                    if item.text() == "/world_model" \
                            or item.text() =="/referee" \
                            or item.text() =="/debugs" \
                            or item.text()=="/draws":
                        item.setCheckState(Qt.Unchecked)

            if topic == "Monitor+":
                if state == Qt.Checked:
                    for item in self.items_list:
                        if item.text().find("agent") >-1:
                            self.selected_topics.append(item)
                            item.setCheckState(Qt.Checked)

                elif state == Qt.Unchecked:
                    for item in self.items_list:
                        if item.text().find("agent") >-1:
                            self.selected_topics.remove(item)
                            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 onButtonClicked(self):
        self.close()
        self.recordSettingsSelected.emit(
            self.item_all.checkState() == Qt.Checked, self.selected_topics)

    def onFromNodesButtonClicked(self):
        self.node_selection = NodeSelection(self)
Esempio n. 2
0
class Top(Plugin):
    NODE_FIELDS = [
        'pid', 'get_cpu_percent', 'get_memory_percent', 'get_num_threads'
    ]
    OUT_FIELDS = [
        'node_name', 'pid', 'cpu_percent', 'memory_percent', 'num_threads'
    ]
    FORMAT_STRS = ['%s', '%s', '%0.2f', '%0.2f', '%s']
    NODE_LABELS = ['Node', 'PID', 'CPU %', 'Mem %', 'Num Threads']
    SORT_TYPE = [str, str, float, float, float]
    TOOLTIPS = {
        0: ('cmdline', lambda x: '\n'.join(textwrap.wrap(' '.join(x)))),
        3: ('memory_info', lambda x:
            ('Resident: %0.2f MiB, Virtual: %0.2f MiB' %
             (x[0] / 2**20, x[1] / 2**20)))
    }

    _node_info = NodeInfo()

    name_filter = re.compile('')

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

        # Process standalone plugin command-line arguments
        from argparse import ArgumentParser
        parser = ArgumentParser()
        # Add argument(s) to the parser.
        parser.add_argument("-q",
                            "--quiet",
                            action="store_true",
                            dest="quiet",
                            help="Put plugin in silent mode")
        args, unknowns = parser.parse_known_args(context.argv())
        # if not args.quiet:
        #     print 'arguments: ', args
        #     print 'unknowns: ', unknowns

        self._selected_node = ''
        self._selected_node_lock = RLock()

        # Setup the toolbar
        self._toolbar = QToolBar()
        self._filter_box = QLineEdit()
        self._regex_box = QCheckBox()
        self._regex_box.setText('regex')
        self._toolbar.addWidget(QLabel('Filter'))
        self._toolbar.addWidget(self._filter_box)
        self._toolbar.addWidget(self._regex_box)

        self._filter_box.returnPressed.connect(self.update_filter)
        self._regex_box.stateChanged.connect(self.update_filter)

        # Create a container widget and give it a layout
        self._container = QWidget()
        self._container.setWindowTitle('Process Monitor')
        self._layout = QVBoxLayout()
        self._container.setLayout(self._layout)

        self._layout.addWidget(self._toolbar)

        # Create the table widget
        self._table_widget = QTreeWidget()
        self._table_widget.setObjectName('TopTable')
        self._table_widget.setColumnCount(len(self.NODE_LABELS))
        self._table_widget.setHeaderLabels(self.NODE_LABELS)
        self._table_widget.itemClicked.connect(self._tableItemClicked)
        self._table_widget.setSortingEnabled(True)
        self._table_widget.setAlternatingRowColors(True)

        self._layout.addWidget(self._table_widget)
        context.add_widget(self._container)

        # Add a button for killing nodes
        self._kill_button = QPushButton('Kill Node')
        self._layout.addWidget(self._kill_button)
        self._kill_button.clicked.connect(self._kill_node)

        # Update twice since the first cpu% lookup will always return 0
        self.update_table()
        self.update_table()

        self._table_widget.resizeColumnToContents(0)

        # Start a timer to trigger updates
        self._update_timer = QTimer()
        self._update_timer.setInterval(1000)
        self._update_timer.timeout.connect(self.update_table)
        self._update_timer.start()

    def _tableItemClicked(self, item, column):
        with self._selected_node_lock:
            self._selected_node = item.text(0)

    def update_filter(self, *args):
        if self._regex_box.isChecked():
            expr = self._filter_box.text()
        else:
            expr = re.escape(self._filter_box.text())
        self.name_filter = re.compile(expr)
        self.update_table()

    def _kill_node(self):
        self._node_info.kill_node(self._selected_node)

    def update_one_item(self, row, info):
        twi = TopWidgetItem()
        for col, field in enumerate(self.OUT_FIELDS):
            val = info[field]
            twi.setText(col, self.FORMAT_STRS[col] % val)
        self._table_widget.insertTopLevelItem(row, twi)

        for col, (key, func) in self.TOOLTIPS.items():
            twi.setToolTip(col, func(info[key]))

        with self._selected_node_lock:
            if twi.text(0) == self._selected_node:
                twi.setSelected(True)

        twi.setHidden(len(self.name_filter.findall(info['node_name'])) == 0)

    def update_table(self):
        self._table_widget.clear()
        infos = self._node_info.get_all_node_fields(self.NODE_FIELDS)
        for nx, info in enumerate(infos):
            self.update_one_item(nx, info)

    def shutdown_plugin(self):
        self._update_timer.stop()

    def save_settings(self, plugin_settings, instance_settings):
        instance_settings.set_value('filter_text', self._filter_box.text())
        instance_settings.set_value('is_regex',
                                    int(self._regex_box.checkState()))

    def restore_settings(self, plugin_settings, instance_settings):
        self._filter_box.setText(instance_settings.value('filter_text'))
        is_regex_int = instance_settings.value('is_regex')
        if is_regex_int:
            self._regex_box.setCheckState(Qt.CheckState(is_regex_int))
        else:
            self._regex_box.setCheckState(Qt.CheckState(0))
        self.update_filter()
class TopicSelection(QWidget):

    recordSettingsSelected = Signal(bool, list)

    def __init__(self):
        super(TopicSelection, self).__init__()
        master = rosgraph.Master('rqt_bag_recorder')
        self.setWindowTitle("Select the topics you want to record")
        self.resize(500, 700)

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

        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.main_vlayout = QVBoxLayout(self)
        self.main_vlayout.addWidget(self.area)
        self.main_vlayout.addWidget(self.ok_button)
        self.setLayout(self.main_vlayout)

        self.selection_vlayout = QVBoxLayout(self)
        self.item_all = QCheckBox("All", self)
        self.item_all.stateChanged.connect(self.updateList)
        self.selection_vlayout.addWidget(self.item_all)
        topic_data_list = master.getPublishedTopics('')
        topic_data_list.sort()
        for topic, datatype in topic_data_list:
            self.addCheckBox(topic)

        self.main_widget.setLayout(self.selection_vlayout)

        self.area.setWidget(self.main_widget)
        self.show()

    def addCheckBox(self, topic):
        self.topic_list.append(topic)
        item = QCheckBox(topic, self)
        item.stateChanged.connect(lambda x: self.updateList(x,topic))
        self.items_list.append(item)
        self.selection_vlayout.addWidget(item)


    def updateList(self, state, topic = None):
        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 onButtonClicked(self):
        self.close()
        self.recordSettingsSelected.emit((self.item_all.checkState() == Qt.Checked), self.selected_topics)
Esempio n. 4
0
class RobotTab(QWidget):
    signalRobotNameChanged = pyqtSignal(int)

    def __init__(self, num_robots, robots):
        super(RobotTab, self).__init__()

        # Available robots from gui_config.yaml
        self.robots = robots
        # Set robot type by default to ground
        self.agent_type = 'ground'

        # Number of robots
        self.num_robots = num_robots

        # Set the robot name by default
        self.robot_name = 'robot' + str(self.num_robots)

        # Set layout for tab
        self.layout = QVBoxLayout()

        # Robot tab title
        self.robot_label_name = QLabel(('Robot ' + str(self.num_robots)))
        font = QFont()
        font.setPointSize(14)
        font.setBold(True)
        self.robot_label_name.setFont(font)
        self.layout.addWidget(self.robot_label_name)

        # Robot name label and input line
        self.robot_label = QLabel('Robot name')
        self.layout.addWidget(self.robot_label)
        self.robot_name_input = QLineEdit('robot' + str(self.num_robots))
        #self.robot_name_input.editingFinished.connect(self.robot_name_changed)
        self.layout.addWidget(self.robot_name_input)

        # Robot model label and comboBox
        self.robot_model_label = QLabel('Robot model')
        self.layout.addWidget(self.robot_model_label)
        self.robot_comboBox = CustomComboBox(self.num_robots - 1)
        self.robot_comboBox.addItems(self.robots['Models'].keys())
        self.layout.addWidget(self.robot_comboBox)
        self.robot_comboBox.signalIndexChanged.connect(self.set_agent_type)

        # Initial pose
        self.robot_label_init = QLabel('Initial pose')
        self.layout.addWidget(self.robot_label_init)
        self.robot_comboBox_init = CustomComboBox(self.num_robots)
        self.layout.addWidget(self.robot_comboBox_init)

        # Add initial pose text item to graphic
        initial_pose_textItem = QGraphicsTextItem(
            'start_' + str(self.num_robots).zfill(2))
        self.initial_pose = {
            'start_' + str(self.num_robots).zfill(2): {
                'label': 'r01',
                'text_item': initial_pose_textItem
            }
        }

        # Use Qualisys
        self.robot_localization_label = QLabel('Localization')
        self.layout.addWidget(self.robot_localization_label)
        self.robot_localization_checkBox = QCheckBox('Use Qualisys')
        self.layout.addWidget(self.robot_localization_checkBox)

        # Task specifications
        self.robot_label_task_title = QLabel('Task robot ' +
                                             str(self.num_robots))
        self.robot_label_task_title.setFont(font)
        self.layout.addWidget(self.robot_label_task_title)
        self.robot_label_hard_task = QLabel('Hard tasks')
        self.layout.addWidget(self.robot_label_hard_task)
        self.robot_hard_task_input = QLineEdit('([]<> r01) && ([]<> r02)')
        self.layout.addWidget(self.robot_hard_task_input)
        self.robot_label_soft_task = QLabel('Soft tasks')
        self.layout.addWidget(self.robot_label_soft_task)
        self.robot_soft_task_input = QLineEdit()
        self.layout.addWidget(self.robot_soft_task_input)

        # Plan display
        self.robot_label_prefix = QLabel('Planner prefix robot ' +
                                         str(self.num_robots))
        self.layout.addWidget(self.robot_label_prefix)
        self.robot_prefix_textbox = QTextBrowser()
        self.layout.addWidget(self.robot_prefix_textbox)
        self.robot_label_sufix = QLabel('Planner sufix robot ' +
                                        str(self.num_robots))
        self.layout.addWidget(self.robot_label_sufix)
        self.robot_sufix_textbox = QTextBrowser()
        self.layout.addWidget(self.robot_sufix_textbox)

        # Current goal display
        self.robot_label_current_goal = QLabel('Current goal robot ' +
                                               str(self.num_robots))
        self.layout.addWidget(self.robot_label_current_goal)
        self.robot_current_goal_textbox = QTextBrowser()
        self.layout.addWidget(self.robot_current_goal_textbox)

        # Clear costmap button
        self.robot_resend_goal_button = QPushButton('Clear costmap')
        self.layout.addWidget(self.robot_resend_goal_button)

        # Temporary task button
        self.robot_temporary_task_button = QPushButton('Temporary task')
        self.layout.addWidget(self.robot_temporary_task_button)
        self.robot_temporary_task_button.clicked.connect(
            self.temporary_task_button_pressed)

        self.setLayout(self.layout)

        # Messages for publishing pose, soft-task, hard-task and clear_costmap
        self.init_pose_msg = Pose()
        self.soft_task_msg = String()
        self.hard_task_msg = String()

        self.prefix_string = ''
        self.sufix_string = ''

        # Marker displaying robots name
        self.label_marker_msg = Marker()
        self.label_marker_msg.pose = self.init_pose_msg
        self.label_marker_msg.pose.position.z = 1.0
        self.label_marker_msg.text = self.robot_name
        self.label_marker_msg.type = self.label_marker_msg.TEXT_VIEW_FACING
        self.label_marker_msg.id = self.num_robots
        self.label_marker_msg.action = self.label_marker_msg.ADD
        self.label_marker_msg.scale.z = 0.5
        self.label_marker_msg.color.a = 1.0
        self.label_marker_msg.color.r = 0.0
        self.label_marker_msg.color.g = 0.0
        self.label_marker_msg.color.b = 0.0
        self.label_marker_msg.header.frame_id = '/map'

        # Pose msg published for planner
        self.pose_msg = PoseWithCovarianceStamped()

        # Init pose msg for planner
        self.pose_msg.pose.pose = self.init_pose_msg

        # Clear costmap and resend current goal
        self.robot_resend_goal_button.clicked.connect(
            self.call_clear_costmap_srvs)
        self.robot_current_goal = MoveBaseActionGoal()

        # Start all publisher and Subscriber
        #self.start_publisher_and_subscriber()

    # AMCL pose callback
    def current_pose_amcl_callback(self, msg):
        if self.robot_localization_checkBox.checkState() != 2:
            self.pose_msg.pose.pose = deepcopy(msg.pose.pose)
            self.pose_msg.header = deepcopy(msg.header)
            self.pose_msg.header.stamp = rospy.Time.now()

            if self.agent_type == 'ground':
                self.label_marker_msg.header = msg.header
                self.label_marker_msg.pose = deepcopy(msg.pose.pose)
                self.label_marker_msg.pose.position.z = deepcopy(
                    msg.pose.pose.position.z) + 1

    # Localization with Qualisys
    def current_pose_qualisys_callback(self, msg):
        if self.robot_localization_checkBox.checkState() == 2:
            self.pose_msg.header = deepcopy(msg.header)
            self.pose_msg.pose.pose = deepcopy(msg.pose)
            self.pose_msg.header.stamp = rospy.Time.now()

            if self.agent_type == 'ground':
                self.label_marker_msg.header = msg.header
                self.label_marker_msg.pose = msg.pose
                self.label_marker_msg.pose.position.z = deepcopy(
                    msg.pose.position.z) + 1

    # Localization with Gazebo ground truth
    def current_pose_gazebo_ground_truth_callback(self, msg):
        if self.agent_type == 'aerial':
            self.label_marker_msg.header = msg.header
            self.label_marker_msg.pose = msg.pose.pose
            self.label_marker_msg.pose.position.z = deepcopy(
                msg.pose.pose.position.z) + 1.0

    # Sends topic to planner to clear costmap manual
    @Slot(bool)
    def call_clear_costmap_srvs(self):
        if self.agent_type == 'ground':
            bool = Bool()
            bool.data = True
            self.clear_costmap_publisher.publish(bool)

    # Opens dialog for temporary task
    @Slot(bool)
    def temporary_task_button_pressed(self):
        temporary_task_dialog = TemporaryTask_dialog()
        temporary_task_dialog.exec_()
        if temporary_task_dialog.atomic_propositions:
            temporary_task_msg = TemporaryTask()
            temporary_task_msg.header.stamp = rospy.Time.now()
            for i in range(0, len(temporary_task_dialog.atomic_propositions)):
                string_msg = String()
                string_msg.data = temporary_task_dialog.atomic_propositions[i]
                temporary_task_msg.task.append(string_msg)
            temporary_task_msg.T_des.data = temporary_task_dialog.T_des
            self.temporary_task_publisher.publish(temporary_task_msg)

    # If robot name in tab has changed the subscriber and publisher topics are updated
    def robot_name_changed(self):
        self.remove_publisher_and_subscriber()
        self.robot_name = self.robot_name_input.text()
        self.start_publisher_and_subscriber()
        self.label_marker_msg.text = self.robot_name
        self.signalRobotNameChanged.emit(self.num_robots)

    # Start all publisher and subscriber from robot tab
    def start_publisher_and_subscriber(self):
        self.robot_name = self.robot_name_input.text()
        self.ros_publisher = ROS_Publisher()
        self.ros_publisher.add_publisher('/' + self.robot_name + '/init_pose',
                                         Pose, 1.0, self.init_pose_msg)
        self.ros_publisher.add_publisher('/' + self.robot_name + '/soft_task',
                                         String, 1.0, self.soft_task_msg)
        self.ros_publisher.add_publisher('/' + self.robot_name + '/hard_task',
                                         String, 1.0, self.hard_task_msg)
        self.ros_publisher.add_publisher(
            '/' + self.robot_name + '/label_marker', Marker, 5.0,
            self.label_marker_msg)
        self.temporary_task_publisher = rospy.Publisher('/' + self.robot_name +
                                                        '/temporary_task',
                                                        TemporaryTask,
                                                        queue_size=1)
        self.clear_costmap_publisher = rospy.Publisher('/' + self.robot_name +
                                                       '/clear_costmap',
                                                       Bool,
                                                       queue_size=1)
        self.current_pose_amcl_subscriber = rospy.Subscriber(
            '/' + self.robot_name + '/amcl_pose', PoseWithCovarianceStamped,
            self.current_pose_amcl_callback)
        self.current_pose_qualisys_subscriber = rospy.Subscriber(
            '/' + self.robot_name + '/qualisys_pose_map', PoseStamped,
            self.current_pose_qualisys_callback)
        self.current_pose_gazebo_ground_truth_subscriber = rospy.Subscriber(
            '/' + self.robot_name + '/ground_truth/pose_with_covariance',
            PoseWithCovarianceStamped,
            self.current_pose_gazebo_ground_truth_callback)
        self.ros_publisher.add_publisher('/' + self.robot_name + '/pose_gui',
                                         PoseWithCovarianceStamped, 15.0,
                                         self.pose_msg)

        self.label_marker_msg.text = self.robot_name

    # Remove all publisher and subcriber from robot tab
    def remove_publisher_and_subscriber(self):
        del self.ros_publisher
        del self.clear_costmap_publisher
        del self.temporary_task_publisher
        del self.current_pose_amcl_subscriber
        del self.current_pose_qualisys_subscriber
        del self.current_pose_gazebo_ground_truth_subscriber

    # ADD FUNCTION THAT JUST CHANGES SOFT AND HARD TASK!!!!
    # DELETE OLD ONE, AND ADD NEW ONE! pass as argument the planner or previous class such that I call it here

    # Updates robot type if model checkbox was changed
    def set_agent_type(self):
        if self.robot_comboBox.currentText(
        ) in self.robots['robot_types']['aerial']:
            self.agent_type = 'aerial'
        else:
            self.agent_type = 'ground'

    def build_init_pose_msg(self, id):
        self.init_pose_msg.position.x = self.initial_pose[
            'start_' + str(id).zfill(2)]['pose']['position'][0]
        self.init_pose_msg.position.y = self.initial_pose[
            'start_' + str(id).zfill(2)]['pose']['position'][1]
        self.init_pose_msg.position.z = self.initial_pose[
            'start_' + str(id).zfill(2)]['pose']['position'][2]
        self.init_pose_msg.orientation.w = self.initial_pose[
            'start_' + str(id).zfill(2)]['pose']['orientation'][0]
        self.init_pose_msg.orientation.x = self.initial_pose[
            'start_' + str(id).zfill(2)]['pose']['orientation'][1]
        self.init_pose_msg.orientation.y = self.initial_pose[
            'start_' + str(id).zfill(2)]['pose']['orientation'][2]
        self.init_pose_msg.orientation.z = self.initial_pose[
            'start_' + str(id).zfill(2)]['pose']['orientation'][3]
Esempio n. 5
0
class TopicSelection(QWidget):

    recordSettingsSelected = Signal(bool, list)

    def __init__(self):
        super(TopicSelection, self).__init__()
        master = rosgraph.Master('rqt_bag_recorder')
        self.setWindowTitle("Select the topics you want to record")
        self.resize(500, 700)

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

        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.main_vlayout = QVBoxLayout(self)
        self.main_vlayout.addWidget(self.area)
        self.main_vlayout.addWidget(self.ok_button)
        self.setLayout(self.main_vlayout)

        self.selection_vlayout = QVBoxLayout(self)
        self.item_all = QCheckBox("All", self)
        self.item_all.stateChanged.connect(self.updateList)
        self.selection_vlayout.addWidget(self.item_all)
        topic_data_list = master.getPublishedTopics('')
        topic_data_list.sort()
        for topic, datatype in topic_data_list:
            self.addCheckBox(topic)

        self.main_widget.setLayout(self.selection_vlayout)

        self.area.setWidget(self.main_widget)
        self.show()

    def addCheckBox(self, topic):
        self.topic_list.append(topic)
        item = QCheckBox(topic, self)
        item.stateChanged.connect(lambda x: self.updateList(x, topic))
        self.items_list.append(item)
        self.selection_vlayout.addWidget(item)

    def updateList(self, state, topic=None):
        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 onButtonClicked(self):
        self.close()
        self.recordSettingsSelected.emit(
            (self.item_all.checkState() == Qt.Checked), self.selected_topics)
Esempio n. 6
0
class Top(Plugin):

    NODE_FIELDS   = [             'pid', 'get_cpu_percent', 'get_memory_percent', 'get_num_threads']
    OUT_FIELDS    = ['node_name', 'pid', 'cpu_percent',     'memory_percent',     'num_threads'    ]
    FORMAT_STRS   = ['%s',        '%s',  '%0.2f',           '%0.2f',              '%s'             ]
    NODE_LABELS   = ['Node',      'PID', 'CPU %',           'Mem %',              'Num Threads'    ]
    SORT_TYPE     = [str,         str,   float,             float,                float            ]
    TOOLTIPS      = {
        0: ('cmdline', lambda x: '\n'.join(textwrap.wrap(' '.join(x)))),
        3: ('memory_info', lambda x: ('Resident: %0.2f MiB, Virtual: %0.2f MiB' % (x[0]/2**20, x[1]/2**20)))
    }

    _node_info = NodeInfo()

    name_filter = re.compile('')

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

        # Process standalone plugin command-line arguments
        from argparse import ArgumentParser
        parser = ArgumentParser()
        # Add argument(s) to the parser.
        parser.add_argument("-q", "--quiet", action="store_true",
                      dest="quiet",
                      help="Put plugin in silent mode")
        args, unknowns = parser.parse_known_args(context.argv())
        # if not args.quiet:
        #     print 'arguments: ', args
        #     print 'unknowns: ', unknowns

        self._selected_node = ''
        self._selected_node_lock = RLock()

        # Setup the toolbar
        self._toolbar = QToolBar()
        self._filter_box = QLineEdit()
        self._regex_box  = QCheckBox()
        self._regex_box.setText('regex')
        self._toolbar.addWidget(QLabel('Filter'))
        self._toolbar.addWidget(self._filter_box)
        self._toolbar.addWidget(self._regex_box)

        self._filter_box.returnPressed.connect(self.update_filter)
        self._regex_box.stateChanged.connect(self.update_filter)

        # Create a container widget and give it a layout
        self._container = QWidget()
        self._container.setWindowTitle('Process Monitor')
        self._layout    = QVBoxLayout()
        self._container.setLayout(self._layout)

        self._layout.addWidget(self._toolbar)

        # Create the table widget
        self._table_widget = QTreeWidget()
        self._table_widget.setObjectName('TopTable')
        self._table_widget.setColumnCount(len(self.NODE_LABELS))
        self._table_widget.setHeaderLabels(self.NODE_LABELS)
        self._table_widget.itemClicked.connect(self._tableItemClicked)
        self._table_widget.setSortingEnabled(True)
        self._table_widget.setAlternatingRowColors(True)

        self._layout.addWidget(self._table_widget)
        context.add_widget(self._container)

        # Add a button for killing nodes
        self._kill_button = QPushButton('Kill Node')
        self._layout.addWidget(self._kill_button)
        self._kill_button.clicked.connect(self._kill_node)

        # Update twice since the first cpu% lookup will always return 0
        self.update_table()
        self.update_table()

        self._table_widget.resizeColumnToContents(0)

        # Start a timer to trigger updates
        self._update_timer = QTimer()
        self._update_timer.setInterval(1000)
        self._update_timer.timeout.connect(self.update_table)
        self._update_timer.start()

    def _tableItemClicked(self, item, column):
        with self._selected_node_lock:
            self._selected_node = item.text(0)

    def update_filter(self, *args):
        if self._regex_box.isChecked():
            expr = self._filter_box.text()
        else:
            expr = re.escape(self._filter_box.text())
        self.name_filter = re.compile(expr)
        self.update_table()

    def _kill_node(self):
        self._node_info.kill_node(self._selected_node)

    def update_one_item(self, row, info):
        twi = TopWidgetItem()
        for col, field in enumerate(self.OUT_FIELDS):
            val = info[field]
            twi.setText(col, self.FORMAT_STRS[col] % val)
        self._table_widget.insertTopLevelItem(row, twi)

        for col, (key, func) in self.TOOLTIPS.items():
            twi.setToolTip(col, func(info[key]))

        with self._selected_node_lock:
            if twi.text(0) == self._selected_node:
                twi.setSelected(True)

        twi.setHidden(len(self.name_filter.findall(info['node_name'])) == 0)

    def update_table(self):
        self._table_widget.clear()
        infos = self._node_info.get_all_node_fields(self.NODE_FIELDS)
        for nx, info in enumerate(infos):
            self.update_one_item(nx, info)

    def shutdown_plugin(self):
        self._update_timer.stop()

    def save_settings(self, plugin_settings, instance_settings):        
        instance_settings.set_value('filter_text', self._filter_box.text())
        instance_settings.set_value('is_regex', int(self._regex_box.checkState()))

    def restore_settings(self, plugin_settings, instance_settings):
        self._filter_box.setText(instance_settings.value('filter_text'))
        is_regex_int = instance_settings.value('is_regex')
        if is_regex_int:
            self._regex_box.setCheckState(Qt.CheckState(is_regex_int))
        else:
            self._regex_box.setCheckState(Qt.CheckState(0))
        self.update_filter()