hist.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 from rqt_gui_py.plugin import Plugin
00003 from python_qt_binding import loadUi
00004 from python_qt_binding.QtCore import Qt, QTimer, qWarning, Slot
00005 from python_qt_binding.QtGui import QAction, QIcon, QMenu, QWidget
00006 from python_qt_binding.QtGui import QWidget, QVBoxLayout, QSizePolicy, QColor
00007 from rqt_py_common.topic_completer import TopicCompleter
00008 from matplotlib.colors import colorConverter
00009 from rqt_py_common.topic_helpers import is_slot_numeric
00010 from rqt_plot.rosplot import ROSData as _ROSData
00011 from rqt_plot.rosplot import RosPlotException
00012 from matplotlib.collections import (PolyCollection, 
00013                                     PathCollection, LineCollection)
00014 import matplotlib
00015 import matplotlib.patches as mpatches
00016 import rospkg
00017 import rospy
00018 from cStringIO import StringIO
00019 import cv2
00020 from cv_bridge import CvBridge
00021 from sensor_msgs.msg import Image
00022 from jsk_recognition_msgs.msg import HistogramWithRange, HistogramWithRangeBin
00023 
00024 import os, sys
00025 import argparse
00026 
00027 try:
00028     from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
00029 except ImportError:
00030     # work around bug in dateutil
00031     import sys
00032     import thread
00033     sys.modules['_thread'] = thread
00034     from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
00035 from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
00036 from matplotlib.figure import Figure
00037 
00038 import numpy as np
00039 import matplotlib.pyplot as plt
00040 
00041 class ROSData(_ROSData):
00042     def _get_data(self, msg):
00043         val = msg
00044         try:
00045             if not self.field_evals:
00046                 return val
00047             for f in self.field_evals:
00048                 val = f(val)
00049             return val
00050         except IndexError:
00051             self.error = RosPlotException("[%s] index error for: %s" % (self.name, str(val).replace('\n', ', ')))
00052         except TypeError:
00053             self.error = RosPlotException("[%s] value was not numeric: %s" % (self.name, val))
00054 
00055 
00056 
00057 class HistogramPlot(Plugin):
00058     def __init__(self, context):
00059         super(HistogramPlot, self).__init__(context)
00060         self.setObjectName('HistogramPlot')
00061         self._args = self._parse_args(context.argv())
00062         self._widget = HistogramPlotWidget(self._args.topics)
00063         context.add_widget(self._widget)
00064     def _parse_args(self, argv):
00065         parser = argparse.ArgumentParser(prog='rqt_histogram_plot', add_help=False)
00066         HistogramPlot.add_arguments(parser)
00067         args = parser.parse_args(argv)
00068         return args
00069     @staticmethod
00070     def add_arguments(parser):
00071         group = parser.add_argument_group('Options for rqt_histogram plugin')
00072         group.add_argument('topics', nargs='?', default=[], help='Topics to plot')
00073         
00074 class HistogramPlotWidget(QWidget):
00075     _redraw_interval = 40
00076     def __init__(self, topics):
00077         super(HistogramPlotWidget, self).__init__()
00078         self.setObjectName('HistogramPlotWidget')
00079         rp = rospkg.RosPack()
00080         ui_file = os.path.join(rp.get_path('jsk_rqt_plugins'), 
00081                                'resource', 'plot_histogram.ui')
00082         loadUi(ui_file, self)
00083         self.cv_bridge = CvBridge()
00084         self.subscribe_topic_button.setIcon(QIcon.fromTheme('add'))
00085         self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause'))
00086         self.clear_button.setIcon(QIcon.fromTheme('edit-clear'))
00087         self.data_plot = MatHistogramPlot(self)
00088         self.data_plot_layout.addWidget(self.data_plot)
00089         self._topic_completer = TopicCompleter(self.topic_edit)
00090         self._topic_completer.update_topics()
00091         self.topic_edit.setCompleter(self._topic_completer)
00092         self.data_plot.dropEvent = self.dropEvent
00093         self.data_plot.dragEnterEvent = self.dragEnterEvent
00094         self._start_time = rospy.get_time()
00095         self._rosdata = None
00096         if len(topics) != 0:
00097             self.subscribe_topic(topics)
00098         self._update_plot_timer = QTimer(self)
00099         self._update_plot_timer.timeout.connect(self.update_plot)
00100         self._update_plot_timer.start(self._redraw_interval)
00101     @Slot('QDropEvent*')
00102     def dropEvent(self, event):
00103         if event.mimeData().hasText():
00104             topic_name = str(event.mimeData().text())
00105         else:
00106             droped_item = event.source().selectedItems()[0]
00107             topic_name = str(droped_item.data(0, Qt.UserRole))
00108         self.subscribe_topic(topic_name)
00109     @Slot()
00110     def on_topic_edit_returnPressed(self):
00111         if self.subscribe_topic_button.isEnabled():
00112             self.subscribe_topic(str(self.topic_edit.text()))
00113     @Slot()
00114     def on_subscribe_topic_button_clicked(self):
00115         self.subscribe_topic(str(self.topic_edit.text()))
00116 
00117     def subscribe_topic(self, topic_name):
00118         self.topic_with_field_name = topic_name
00119         self.pub_image = rospy.Publisher(topic_name + "/histogram_image", Image)
00120         if not self._rosdata:
00121             self._rosdata = ROSData(topic_name, self._start_time)
00122         else:
00123             if self._rosdata != topic_name:
00124                 self._rosdata.close()
00125                 self.data_plot.clear()
00126                 self._rosdata = ROSData(topic_name, self._start_time)
00127             else:
00128                 rospy.logwarn("%s is already subscribed", topic_name)
00129         
00130     def enable_timer(self, enabled=True):
00131         if enabled:
00132             self._update_plot_timer.start(self._redraw_interval)
00133         else:
00134             self._update_plot_timer.stop()
00135     @Slot()
00136     def on_clear_button_clicked(self):
00137         self.data_plot.clear()
00138     
00139     @Slot(bool)
00140     def on_pause_button_clicked(self, checked):
00141         self.enable_timer(not checked)
00142     
00143     def update_plot(self):
00144         if not self._rosdata:
00145             return
00146         data_x, data_y = self._rosdata.next()
00147 
00148         if len(data_y) == 0:
00149             return
00150         axes = self.data_plot._canvas.axes
00151         axes.cla()
00152         if self._rosdata.sub.data_class is HistogramWithRange:
00153             xs = [y.count for y in data_y[-1].bins]
00154             pos = [y.min_value for y in data_y[-1].bins]
00155             widths = [y.max_value - y.min_value for y in data_y[-1].bins]
00156             axes.set_xlim(xmin=pos[0], xmax=pos[-1] + widths[-1])
00157         else:
00158             xs = data_y[-1]
00159             pos = np.arange(len(xs))
00160             widths = [1] * len(xs)
00161             axes.set_xlim(xmin=0, xmax=len(xs))
00162         #axes.xticks(range(5))
00163         for p, x, w in zip(pos, xs, widths):
00164             axes.bar(p, x, color='r', align='center', width=w)
00165         axes.legend([self.topic_with_field_name], prop={'size': '8'})
00166         self.data_plot._canvas.draw()
00167         buffer = StringIO()
00168         self.data_plot._canvas.figure.savefig(buffer, format="png")
00169         buffer.seek(0)
00170         img_array = np.asarray(bytearray(buffer.read()), dtype=np.uint8)
00171         img = cv2.imdecode(img_array, cv2.CV_LOAD_IMAGE_COLOR)
00172         self.pub_image.publish(self.cv_bridge.cv2_to_imgmsg(img, "bgr8"))
00173 class MatHistogramPlot(QWidget):
00174     class Canvas(FigureCanvas):
00175         def __init__(self, parent=None):
00176             super(MatHistogramPlot.Canvas, self).__init__(Figure())
00177             self.axes = self.figure.add_subplot(111)
00178             self.figure.tight_layout()
00179             self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
00180             self.updateGeometry()
00181         def resizeEvent(self, event):
00182             super(MatHistogramPlot.Canvas, self).resizeEvent(event)
00183             self.figure.tight_layout()
00184     def __init__(self, parent=None):
00185         super(MatHistogramPlot, self).__init__(parent)
00186         self._canvas = MatHistogramPlot.Canvas()
00187         self._toolbar = NavigationToolbar(self._canvas, self._canvas)
00188         vbox = QVBoxLayout()
00189         vbox.addWidget(self._toolbar)
00190         vbox.addWidget(self._canvas)
00191         self.setLayout(vbox)
00192     def redraw(self):
00193         pass
00194     def clear(self):
00195         self._canvas.axes.cla()
00196         self._canvas.draw()


jsk_rqt_plugins
Author(s):
autogenerated on Sun Sep 13 2015 22:29:48