70 from rqt_bag
import MessageView
72 from python_qt_binding
import loadUi
73 from python_qt_binding.QtCore
import Qt, qWarning, Signal
74 from python_qt_binding.QtGui
import QDoubleValidator, QIcon
75 from python_qt_binding.QtWidgets
import QWidget, QPushButton, QTreeWidget, QTreeWidgetItem, QSizePolicy
91 super(PlotView, self).
__init__(timeline, topic)
101 _, msg, t = msg_details[:3]
106 self.plot_widget.message_tree.set_message(msg)
107 self.plot_widget.set_cursor((t - self.plot_widget.start_stamp).to_sec())
113 class PlotWidget(QWidget):
116 super(PlotWidget, self).
__init__(parent)
117 self.setObjectName(
'PlotWidget')
120 msg_type = self.timeline.get_datatype(topic)
129 rp = rospkg.RosPack()
130 ui_file = os.path.join(rp.get_path(
'rqt_bag_plugins'),
'resource',
'plot.ui')
131 loadUi(ui_file, self)
137 self.auto_res.stateChanged.connect(self.
autoChanged)
140 self.resolution.setValidator(QDoubleValidator(0.0, 1000.0, 6, self.resolution))
142 self.timeline.selected_region_changed.connect(self.
region_changed)
147 self.plot.set_autoscale(x=
False)
148 self.plot.set_autoscale(y=DataPlot.SCALE_VISIBLE)
149 self.plot.autoscroll(
False)
150 self.plot.set_xlim(self.
limits)
151 self.data_plot_layout.addWidget(self.
plot)
154 self._home_button.setToolTip(
"Reset View")
155 self._home_button.setIcon(QIcon.fromTheme(
'go-home'))
156 self._home_button.clicked.connect(self.
home)
160 self._config_button.clicked.connect(self.plot.doSettingsDialog)
172 bag, entry = self.timeline.get_entry(start_time, topic)
174 start_time = self.timeline.get_entry_after(start_time)[1].time
178 msg = bag._read_message(entry.position)
179 self.message_tree.set_message(msg[1])
187 self.plot.vline(position, color=DataPlot.RED)
198 self.plot.remove_curve(path)
199 self.paths_on.remove(path)
203 """get a generator for the specified time range on our bag""" 204 return self.bag.read_messages(self.
msgtopic,
212 self.resample_thread.join()
215 self.resample_fields.add(f)
222 self.resample_thread.setDaemon(
True)
223 self.resample_thread.start()
237 with self.timeline._bag_lock:
245 for entry
in msgdata:
258 for field
in path.split(
'.'):
260 if field.endswith(
']'):
262 field, _, index = field.rpartition(
'[')
263 y_value = getattr(y_value, field)
266 y_value = y_value[index]
267 y[path].append(y_value)
268 x[path].append((entry[2] - self.
start_stamp).to_sec())
282 qWarning(
"Resampling resulted in 0 data points for %s" % path)
285 self.plot.clear_values(path)
286 self.plot.update_values(path, x[path], y[path])
288 self.plot.add_curve(path, path, x[path], y[path])
289 self.paths_on.add(path)
293 self.resample_fields.clear()
300 if self.auto_res.isChecked():
301 timestep = round((limits[1] - limits[0]) / 200.0, 5)
303 timestep = float(self.resolution.text())
304 self.resolution.setText(str(timestep))
314 limits = [0.0, limits[1]]
321 self.plot.set_xlim(limits)
333 self.resolution.setDisabled(
True)
339 self.resolution.setDisabled(
False)
347 self.plot.set_xlim(self.
limits)
355 super(MessageTree, self).
__init__(parent)
356 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
357 self.setHeaderHidden(
True)
377 if item.isExpanded():
378 self._expanded_paths.add(path)
380 self._expanded_paths.remove(path)
381 if item.checkState(0) == Qt.Checked:
382 self._checked_states.add(path)
384 self._checked_states.remove(path)
398 item.setExpanded(
True)
400 item.setExpanded(
False)
405 return item.data(0, Qt.UserRole)[0].replace(
' ',
'')
410 root = self.invisibleRootItem()
418 for i
in range(root.childCount()):
419 child = root.child(i)
426 if hasattr(obj,
'__slots__'):
427 subobjs = [(slot, getattr(obj, slot))
for slot
in obj.__slots__]
428 elif type(obj)
in [list, tuple]:
433 w = int(math.ceil(math.log10(len_obj)))
434 subobjs = [(
'[%*d]' % (w, i), subobj)
for (i, subobj)
in enumerate(obj)]
439 if type(obj)
in [int, long, float]:
441 if type(obj) == float:
442 obj_repr =
'%.6f' % obj
446 if obj_repr[0] ==
'-':
447 label +=
': %s' % obj_repr
449 label +=
': %s' % obj_repr
451 elif type(obj)
in [str, bool, int, long, float, complex, rospy.Time]:
453 obj_repr = codecs.utf_8_decode(str(obj),
'ignore')[0]
456 if len(obj_repr) >= 50:
457 obj_repr = obj_repr[:50] +
'...' 459 label +=
': ' + obj_repr
460 item = QTreeWidgetItem([label])
463 elif path.find(
'.') == -1
and path.find(
'[') == -1:
464 self.addTopLevelItem(item)
466 parent.addChild(item)
469 item.setCheckState(0, Qt.Checked)
471 item.setCheckState(0, Qt.Unchecked)
472 item.setData(0, Qt.UserRole, (path, obj_type))
474 for subobj_name, subobj
in subobjs:
479 subpath = subobj_name
480 elif subobj_name.startswith(
'['):
481 subpath =
'%s%s' % (path, subobj_name)
483 subpath =
'%s.%s' % (path, subobj_name)
485 if hasattr(subobj,
'_type'):
486 subobj_type = subobj._type
488 subobj_type = type(subobj).__name__
493 if item.data(0, Qt.UserRole) ==
None:
497 if item.checkState(column) == Qt.Checked:
499 self.plot_list.add(path)
500 self.parent().parent().parent().add_plot(path)
501 if item.checkState(column) == Qt.Unchecked:
503 self.plot_list.remove(path)
504 self.parent().parent().parent().remove_plot(path)
def message_cleared(self)
def set_message(self, msg)
def get_item_path(self, item)
def __init__(self, msg_type, parent)
def traverse(self, root, function)
def _add_msg_object(self, parent, path, name, obj, obj_type)
def __init__(self, timeline, parent, topic)
def handleChanged(self, item, column)
def message_viewed(self, bag, msg_details)