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, PathCollection, LineCollection
00013 import matplotlib
00014 
00015 import rospkg
00016 import rospy
00017 
00018 import os, sys
00019 import argparse
00020 
00021 try:
00022     from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
00023 except ImportError:
00024     # work around bug in dateutil
00025     import sys
00026     import thread
00027     sys.modules['_thread'] = thread
00028     from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
00029 from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
00030 from matplotlib.figure import Figure
00031 
00032 import numpy as np
00033 import matplotlib.pyplot as plt
00034 
00035 class ROSData(_ROSData):
00036     def _get_data(self, msg):
00037         val = msg
00038         try:
00039             if not self.field_evals:
00040                 return val
00041             for f in self.field_evals:
00042                 val = f(val)
00043             return val
00044         except IndexError:
00045             self.error = RosPlotException("[%s] index error for: %s" % (self.name, str(val).replace('\n', ', ')))
00046         except TypeError:
00047             self.error = RosPlotException("[%s] value was not numeric: %s" % (self.name, val))
00048 
00049 
00050 
00051 class HistogramPlot(Plugin):
00052     def __init__(self, context):
00053         super(HistogramPlot, self).__init__(context)
00054         self.setObjectName('HistogramPlot')
00055         self._args = self._parse_args(context.argv())
00056         self._widget = HistogramPlotWidget(self._args.topics)
00057         context.add_widget(self._widget)
00058     def _parse_args(self, argv):
00059         parser = argparse.ArgumentParser(prog='rqt_histogram_plot', add_help=False)
00060         HistogramPlot.add_arguments(parser)
00061         args = parser.parse_args(argv)
00062         return args
00063     @staticmethod
00064     def add_arguments(parser):
00065         group = parser.add_argument_group('Options for rqt_histogram plugin')
00066         # group.add_argument('-P', '--pause', action='store_true', dest='start_paused',
00067         #     help='Start in paused state')
00068         # group.add_argument('-L', '--line', action='store_true', dest='show_line',
00069         #     help='Show lines rather than polygon representation')
00070         # group.add_argument('--no-legend', action='store_true', dest='no_legend',
00071         #     help='do not show legend')
00072         # group.add_argument('-B', '--buffer', dest='buffer', action="store",
00073         #     help='the length of the buffer', default=100, type=int)
00074         group.add_argument('topics', nargs='?', default=[], help='Topics to plot')
00075         
00076 class HistogramPlotWidget(QWidget):
00077     _redraw_interval = 40
00078     def __init__(self, topics):
00079         super(HistogramPlotWidget, self).__init__()
00080         self.setObjectName('HistogramPlotWidget')
00081         rp = rospkg.RosPack()
00082         ui_file = os.path.join(rp.get_path('jsk_rqt_plugins'), 
00083                                'resource', 'plot_histogram.ui')
00084         loadUi(ui_file, self)
00085         self.subscribe_topic_button.setIcon(QIcon.fromTheme('add'))
00086         self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause'))
00087         self.clear_button.setIcon(QIcon.fromTheme('edit-clear'))
00088         self.data_plot = MatHistogramPlot(self)
00089         self.data_plot_layout.addWidget(self.data_plot)
00090         self._topic_completer = TopicCompleter(self.topic_edit)
00091         self._topic_completer.update_topics()
00092         self.topic_edit.setCompleter(self._topic_completer)
00093         self.data_plot.dropEvent = self.dropEvent
00094         self.data_plot.dragEnterEvent = self.dragEnterEvent
00095         self._start_time = rospy.get_time()
00096         self._rosdata = None
00097         if len(topics) != 0:
00098             self.subscribe_topic(topics)
00099         self._update_plot_timer = QTimer(self)
00100         self._update_plot_timer.timeout.connect(self.update_plot)
00101         self._update_plot_timer.start(self._redraw_interval)
00102     @Slot('QDropEvent*')
00103     def dropEvent(self, event):
00104         print "hello"
00105         if event.mimeData().hasText():
00106             topic_name = str(event.mimeData().text())
00107         else:
00108             droped_item = event.source().selectedItems()[0]
00109             topic_name = str(droped_item.data(0, Qt.UserRole))
00110         self.subscribe_topic(topic_name)
00111     @Slot()
00112     def on_topic_edit_returnPressed(self):
00113         if self.subscribe_topic_button.isEnabled():
00114             self.subscribe_topic(str(self.topic_edit.text()))
00115     @Slot()
00116     def on_subscribe_topic_button_clicked(self):
00117         self.subscribe_topic(str(self.topic_edit.text()))
00118 
00119     def subscribe_topic(self, topic_name):
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         if len(data_y) == 0:
00148             return
00149         xs = data_y[-1]
00150         axes = self.data_plot._canvas.axes
00151         axes.cla()
00152         axes.set_xlim(xmin=0, xmax=len(xs))
00153         pos = np.arange(len(xs))
00154         #axes.xticks(range(5))
00155         for p, x in zip(pos, xs):
00156             axes.bar(p, x, color='r', align='center')
00157         self.data_plot._canvas.draw()
00158         
00159 class MatHistogramPlot(QWidget):
00160     class Canvas(FigureCanvas):
00161         def __init__(self, parent=None):
00162             super(MatHistogramPlot.Canvas, self).__init__(Figure())
00163             self.axes = self.figure.add_subplot(111)
00164             self.figure.tight_layout()
00165             self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
00166             self.updateGeometry()
00167         def resizeEvent(self, event):
00168             super(MatHistogramPlot.Canvas, self).resizeEvent(event)
00169             self.figure.tight_layout()
00170     def __init__(self, parent=None):
00171         super(MatHistogramPlot, self).__init__(parent)
00172         self._canvas = MatHistogramPlot.Canvas()
00173         self._toolbar = NavigationToolbar(self._canvas, self._canvas)
00174         vbox = QVBoxLayout()
00175         vbox.addWidget(self._toolbar)
00176         vbox.addWidget(self._canvas)
00177         self.setLayout(vbox)
00178     def redraw(self):
00179         pass
00180     def clear(self):
00181         self._canvas.axes.cla()
00182         self._canvas.draw()


jsk_rqt_plugins
Author(s):
autogenerated on Mon Oct 6 2014 01:20:19