Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 import roslib
00034 roslib.load_manifest('rqt_plot')
00035
00036 from python_qt_binding import QT_BINDING
00037 from python_qt_binding.QtCore import qDebug
00038 from qt_gui_py_common.simple_settings_dialog import SimpleSettingsDialog
00039 from rqt_gui_py.plugin import Plugin
00040
00041 from .plot_widget import PlotWidget
00042
00043 try:
00044 qDebug('rqt_plot.plot: importing PyQtGraphDataPlot')
00045 from pyqtgraph_data_plot import PyQtGraphDataPlot
00046 except ImportError:
00047 qDebug('rqt_plot.plot: import of PyQtGraphDataPlot failed')
00048 PyQtGraphDataPlot = None
00049
00050 try:
00051 qDebug('rqt_plot.plot: importing MatDataPlot')
00052 from mat_data_plot import MatDataPlot
00053 except ImportError:
00054 qDebug('rqt_plot.plot: import of MatDataPlot failed')
00055 MatDataPlot = None
00056
00057 try:
00058 qDebug('rqt_plot.plot: importing QwtDataPlot')
00059 from qwt_data_plot import QwtDataPlot
00060 except ImportError:
00061 qDebug('rqt_plot.plot: import of QwtDataPlot failed')
00062 QwtDataPlot = None
00063
00064
00065 class Plot(Plugin):
00066
00067 plot_types = [
00068 {
00069 'title': 'PyQtGraph',
00070 'widget_class': PyQtGraphDataPlot,
00071 'description': 'Based on PyQtGraph\n- installer: http://luke.campagnola.me/code/pyqtgraph',
00072 'enabled': PyQtGraphDataPlot is not None,
00073 },
00074 {
00075 'title': 'MatPlot',
00076 'widget_class': MatDataPlot,
00077 'description': 'Based on MatPlotLib\n- needs most CPU\n- needs matplotlib >= 1.1.0\n- if using PySide: PySide > 1.1.0',
00078 'enabled': MatDataPlot is not None,
00079 },
00080 {
00081 'title': 'QwtPlot',
00082 'widget_class': QwtDataPlot,
00083 'description': 'Based on QwtPlot\n- does not use timestamps\n- uses least CPU\n- needs Python Qwt bindings',
00084 'enabled': QwtDataPlot is not None,
00085 },
00086 ]
00087
00088 def __init__(self, context):
00089 super(Plot, self).__init__(context)
00090 self.setObjectName('Plot')
00091
00092 enabled_plot_types = [pt for pt in self.plot_types if pt['enabled']]
00093 if not enabled_plot_types:
00094 version_info = ' and PySide > 1.1.0' if QT_BINDING == 'pyside' else ''
00095 raise RuntimeError('No usable plot type found. Install at least one of: PyQtGraph, MatPlotLib (at least 1.1.0%s) or Python-Qwt5.' % version_info)
00096
00097 self._plot_type_index = 0
00098 self._context = context
00099
00100 args, topics = self._process_arguments(context.argv())
00101 self._widget = PlotWidget(args, topics)
00102 if context.serial_number() > 1:
00103 self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))
00104 context.add_widget(self._widget)
00105
00106 def _process_arguments(self, argv):
00107 from argparse import ArgumentParser
00108 parser = ArgumentParser()
00109
00110
00111 parser.add_argument("-P", "--pause", action="store_true",
00112 dest="start_paused",
00113 help="start in paused state")
00114
00115 args, topics = parser.parse_known_args(argv)
00116
00117
00118 topic_list = []
00119 for t in topics:
00120
00121 c_topics = []
00122
00123 for sub_t in [x for x in t.split(',') if x]:
00124
00125 if ':' in sub_t:
00126 base = sub_t[:sub_t.find(':')]
00127
00128 c_topics.append(base)
00129 if not '/' in base:
00130 parser.error("%s must contain a topic and field name" % sub_t)
00131 base = base[:base.rfind('/')]
00132
00133
00134 fields = sub_t.split(':')[1:]
00135 c_topics.extend(["%s/%s" % (base, f) for f in fields if f])
00136 else:
00137 c_topics.append(sub_t)
00138
00139 import rosgraph
00140 c_topics = [rosgraph.names.script_resolve_name('rqt_plot', n) for n in c_topics]
00141 if type(c_topics) == list:
00142 topic_list.extend(c_topics)
00143 else:
00144 topic_list.append(c_topics)
00145
00146
00147 print_topic_list = []
00148 for l in topic_list:
00149 if type(l) == list:
00150 print_topic_list.extend(l)
00151 else:
00152 print_topic_list.append(l)
00153
00154 print "plotting topics", ', '.join(print_topic_list)
00155
00156 return (args, topic_list)
00157
00158 def _switch_data_plot_widget(self, plot_type_index):
00159
00160 if not self.plot_types[plot_type_index]['enabled']:
00161
00162 for index, plot_type in enumerate(self.plot_types):
00163 if plot_type['enabled']:
00164 plot_type_index = index
00165 break
00166
00167 self._plot_type_index = plot_type_index
00168 selected_plot = self.plot_types[plot_type_index]
00169
00170 self._widget.switch_data_plot_widget(selected_plot['widget_class'](self._widget))
00171 self._widget.setWindowTitle(selected_plot['title'])
00172 if self._context.serial_number() > 1:
00173 self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % self._context.serial_number()))
00174
00175 def save_settings(self, plugin_settings, instance_settings):
00176 instance_settings.set_value('plot_type', self._plot_type_index)
00177
00178 def restore_settings(self, plugin_settings, instance_settings):
00179 self._switch_data_plot_widget(int(instance_settings.value('plot_type', 0)))
00180
00181 def trigger_configuration(self):
00182 dialog = SimpleSettingsDialog(title='Plot Options')
00183 dialog.add_exclusive_option_group(title='Plot Type', options=self.plot_types, selected_index=self._plot_type_index)
00184 plot_type = dialog.get_settings()[0]
00185 if plot_type is not None and plot_type['selected_index'] is not None and self._plot_type_index != plot_type['selected_index']:
00186 self._switch_data_plot_widget(plot_type['selected_index'])
00187
00188 def shutdown_plugin(self):
00189 self._widget.clean_up_subscribers()