00001 from rqt_gui_py.plugin import Plugin 00002 import python_qt_binding.QtGui as QtGui 00003 from python_qt_binding.QtGui import (QAction, QIcon, QMenu, QWidget, 00004 QPainter, QColor, QFont, QBrush, 00005 QPen, QMessageBox, QSizePolicy, 00006 QLabel, QComboBox) 00007 from python_qt_binding.QtCore import Qt, QTimer, qWarning, Slot, QEvent, QSize 00008 from threading import Lock 00009 import rospy 00010 import python_qt_binding.QtCore as QtCore 00011 from std_msgs.msg import Bool, Time 00012 import math 00013 from resource_retriever import get_filename 00014 import yaml 00015 import os, sys 00016 00017 from std_msgs.msg import UInt8 00018 from image_view2_wrapper import ComboBoxDialog 00019 00020 class StatusLight(Plugin): 00021 """ 00022 rqt plugin to show light like ultra-man's light. 00023 It subscribes std_msgs/UInt8 topic and the value means: 00024 0 == Unknown (gray) 00025 1 == Success (green) 00026 2 == Warn (yellow) 00027 """ 00028 def __init__(self, context): 00029 super(StatusLight, self).__init__(context) 00030 self.setObjectName("StatusLight") 00031 self._widget = StatusLightWidget() 00032 context.add_widget(self._widget) 00033 def save_settings(self, plugin_settings, instance_settings): 00034 self._widget.save_settings(plugin_settings, instance_settings) 00035 def restore_settings(self, plugin_settings, instance_settings): 00036 self._widget.restore_settings(plugin_settings, instance_settings) 00037 def trigger_configuration(self): 00038 self._widget.trigger_configuration() 00039 00040 class StatusLightWidget(QWidget): 00041 _UNKNOWN_COLOR = QColor("#dddddd") 00042 _SUCCESS_COLOR = QColor("#18FFFF") 00043 _WARN_COLOR = QColor("#FFCA00") 00044 _ERROR_COLOR = QColor("#F44336") 00045 def __init__(self): 00046 super(StatusLightWidget, self).__init__() 00047 self.lock = Lock() 00048 self.status_sub = None 00049 self.status = 0 00050 self._status_topics = [] 00051 self._update_topic_timer = QTimer(self) 00052 self._update_topic_timer.timeout.connect(self.updateTopics) 00053 self._update_topic_timer.start(1000) 00054 self._active_topic = None 00055 self._dialog = ComboBoxDialog() 00056 self._update_plot_timer = QTimer(self) 00057 self._update_plot_timer.timeout.connect(self.redraw) 00058 self._update_plot_timer.start(1000 / 15) 00059 00060 def redraw(self): 00061 self.update() 00062 def paintEvent(self, event): 00063 with self.lock: 00064 if self.status == 1: 00065 color = self._SUCCESS_COLOR 00066 elif self.status == 2: 00067 color = self._WARN_COLOR 00068 else: 00069 color = self._UNKNOWN_COLOR 00070 rect = event.rect() 00071 qp = QPainter() 00072 qp.begin(self) 00073 radius = min(rect.width(), rect.height()) - 100 00074 qp.setFont(QFont('Helvetica', 100)) 00075 qp.setPen(QPen(QBrush(color), 50)) 00076 qp.setBrush(color) 00077 qp.drawEllipse((rect.width() - radius) / 2, (rect.height() - radius) / 2, 00078 radius, radius) 00079 qp.end() 00080 return 00081 00082 def trigger_configuration(self): 00083 self._dialog.exec_() 00084 self.setupSubscriber(self._status_topics[self._dialog.number]) 00085 def updateTopics(self): 00086 need_to_update = False 00087 for (topic, topic_type) in rospy.get_published_topics(): 00088 if topic_type == "std_msgs/UInt8": 00089 if not topic in self._status_topics: 00090 self._status_topics.append(topic) 00091 need_to_update = True 00092 if need_to_update: 00093 self._status_topics = sorted(self._status_topics) 00094 self._dialog.combo_box.clear() 00095 for topic in self._status_topics: 00096 self._dialog.combo_box.addItem(topic) 00097 if self._active_topic: 00098 if self._active_topic not in self._status_topics: 00099 self._status_topics.append(self._active_topic) 00100 self._dialog.combo_box.addItem(self._active_topic) 00101 self._dialog.combo_box.setCurrentIndex(self._status_topics.index(self._active_topic)) 00102 def setupSubscriber(self, topic): 00103 if self.status_sub: 00104 self.status_sub.unregister() 00105 self.status_sub = rospy.Subscriber(topic, UInt8, 00106 self.statusCallback) 00107 self._active_topic = topic 00108 def onActivated(self, number): 00109 self.setupSubscriber(self._status_topics[number]) 00110 def statusCallback(self, msg): 00111 self.status = msg.data 00112 def save_settings(self, plugin_settings, instance_settings): 00113 if self._active_topic: 00114 instance_settings.set_value("active_topic", self._active_topic) 00115 def restore_settings(self, plugin_settings, instance_settings): 00116 if instance_settings.value("active_topic"): 00117 topic = instance_settings.value("active_topic") 00118 self._dialog.combo_box.addItem(topic) 00119 self.setupSubscriber(topic)