class Dashboard(QWidget): _scan_button_led = Signal(bool) _cancel_button_led = Signal(bool) def __init__(self): super(Dashboard, self).__init__() not_latched = False # latched = True self.publishers = py_trees_ros.utilities.Publishers([ ('scan', "~scan", std_msgs.Empty, not_latched, 1), ('cancel', "~cancel", std_msgs.Empty, not_latched, 1), ]) self.scan_push_button = QPushButton("Scan") self.scan_push_button.setStyleSheet("QPushButton { font-size: 30pt; }") self.scan_push_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.scan_push_button.pressed.connect( functools.partial(self.publish_button_message, self.publishers.scan)) self.cancel_push_button = QPushButton("Cancel") self.cancel_push_button.setStyleSheet( "QPushButton { font-size: 30pt; }") self.cancel_push_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.cancel_push_button.pressed.connect( functools.partial(self.publish_button_message, self.publishers.cancel)) self.led_strip_flashing = False self.led_strip_on_count = 1 self.led_strip_colour = "grey" self.led_strip_lock = threading.Lock() self.led_strip_timer = QTimer() self.led_strip_timer.timeout.connect(self.led_strip_timer_callback) self.led_strip_label = QLabel("LED Strip") self.led_strip_label.setAlignment(Qt.AlignCenter) self.led_strip_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.led_strip_label.setStyleSheet( "background-color: %s; font-size: 30pt;" % self.led_strip_colour) self.hbox_layout = QGridLayout(self) self.hbox_layout.addWidget(self.scan_push_button) self.hbox_layout.addWidget(self.cancel_push_button) self.hbox_layout.addWidget(self.led_strip_label) self.subscribers = py_trees_ros.utilities.Subscribers([ ("report", "/tree/report", std_msgs.String, self.reality_report_callback), ("led_strip", "/led_strip/display", std_msgs.String, self.led_strip_display_callback) ]) self.led_strip_timer.start(500) # ms def publish_button_message(self, publisher): publisher.publish(std_msgs.Empty()) def reality_report_callback(self, msg): if msg.data == "cancelling": self.set_scanning_colour(False) self.set_cancelling_colour(True) self.cancel_push_button.setEnabled(True) elif msg.data == "scanning": self.set_scanning_colour(True) self.set_cancelling_colour(False) self.cancel_push_button.setEnabled(True) else: self.set_scanning_colour(False) self.set_cancelling_colour(False) self.cancel_push_button.setEnabled(False) def set_cancelling_colour(self, val): if val: self.cancel_push_button.setStyleSheet( "QPushButton { font-size: 30pt; background-color: red}") else: self.cancel_push_button.setStyleSheet( "QPushButton { font-size: 30pt; }") def set_scanning_colour(self, val): if val: self.scan_push_button.setStyleSheet( "QPushButton { font-size: 30pt; background-color: green}") else: self.scan_push_button.setStyleSheet( "QPushButton { font-size: 30pt; }") def led_strip_display_callback(self, msg): with self.led_strip_lock: if not msg.data: self.led_strip_colour = "grey" self.led_strip_flashing = False else: self.led_strip_flashing = True self.led_strip_colour = None for colour in ["blue", "red", "green"]: if colour in msg.data: self.led_strip_colour = colour break if not self.led_strip_colour: self.led_strip_colour = "pink" rospy.loginfo( "Dashboard: received unknown LED colour {0}, setting 'pink'" .format(msg.data)) @Slot() def led_strip_timer_callback(self): with self.led_strip_lock: if self.led_strip_flashing: if self.led_strip_on_count > 0: self.led_strip_on_count = 0 self.led_strip_label.setStyleSheet( "background-color: none; font-size: 30pt;") else: self.led_strip_on_count += 1 self.led_strip_label.setStyleSheet( "background-color: %s; font-size: 30pt;" % self.led_strip_colour) else: # solid self.led_strip_on_count = 1 self.led_strip_label.setStyleSheet( "background-color: %s; font-size: 30pt;" % self.led_strip_colour)
class StringLabelWidget(QWidget): def __init__(self): super(StringLabelWidget, self).__init__() self.lock = Lock() vbox = QVBoxLayout(self) self.label = QLabel() self.label.setAlignment(Qt.AlignLeft) self.label.setSizePolicy( QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)) font = QFont("Helvetica", 14) self.label.setFont(font) self.label.setWordWrap(True) vbox.addWidget(self.label) self.string_sub = None self._string_topics = [] self._update_topic_timer = QTimer(self) self._update_topic_timer.timeout.connect(self.updateTopics) self._update_topic_timer.start(1000) self._active_topic = None # to update label visualization self._dialog = LineEditDialog() self._rosdata = None self._start_time = rospy.get_time() self._update_label_timer = QTimer(self) self._update_label_timer.timeout.connect(self.updateLabel) self._update_label_timer.start(40) def trigger_configuration(self): self._dialog.exec_() self.setupSubscriber(self._dialog.value) def updateLabel(self): if not self._rosdata: return try: _, data_y = self._rosdata.next() except rqt_plot.rosplot.RosPlotException as e: self._rosdata = None return if len(data_y) == 0: return latest = data_y[-1] # get latest data # supports std_msgs/String as well as string data nested in rosmsg if type(latest) == String: self.string = latest.data else: self.string = latest try: self.label.setText(self.string) except TypeError as e: rospy.logwarn(e) def updateTopics(self): need_to_update = False for (topic, topic_type) in rospy.get_published_topics(): msg = roslib.message.get_message_class(topic_type) field_names = get_slot_type_field_names(msg, slot_type='string') for field in field_names: string_topic = topic + field if string_topic not in self._string_topics: self._string_topics.append(string_topic) need_to_update = True if need_to_update: self._string_topics = sorted(self._string_topics) self._dialog.combo_box.clear() for topic in self._string_topics: self._dialog.combo_box.addItem(topic) if self._active_topic: if self._active_topic not in self._string_topics: self._string_topics.append(self._active_topic) self._dialog.combo_box.addItem(self._active_topic) self._dialog.combo_box.setCurrentIndex( self._string_topics.index(self._active_topic)) def setupSubscriber(self, topic): if not self._rosdata: self._rosdata = ROSData(topic, self._start_time) else: if self._rosdata != topic: self._rosdata.close() self._rosdata = ROSData(topic, self._start_time) else: rospy.logwarn("%s is already subscribed", topic) self._active_topic = topic def onActivated(self, number): self.setupSubscriber(self._string_topics[number]) def save_settings(self, plugin_settings, instance_settings): if self._active_topic: instance_settings.set_value("active_topic", self._active_topic) def restore_settings(self, plugin_settings, instance_settings): if instance_settings.value("active_topic"): topic = instance_settings.value("active_topic") self._dialog.combo_box.addItem(topic) self.setupSubscriber(topic)