split example visualizaiton pipeline
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""PyQtGraph real-time force chart window for examples."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def _require_pyqtgraph():
|
||||
try:
|
||||
import pyqtgraph as pg
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"PyQtGraph is not installed. Install with: pip install pyqt5 pyqtgraph"
|
||||
) from exc
|
||||
return pg
|
||||
|
||||
|
||||
class ForceChartWindow:
|
||||
"""Rolling normal/shear force charts backed by PyQtGraph."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
npoints: int = 100,
|
||||
sample_rate_hz: float = 30.0,
|
||||
title: str = "Orisys 实时力曲线",
|
||||
app_name: str = "Orisys Plot Example",
|
||||
) -> None:
|
||||
pg = _require_pyqtgraph()
|
||||
pg.setConfigOption("background", "w")
|
||||
pg.setConfigOption("foreground", "k")
|
||||
|
||||
self._pg = pg
|
||||
self.npoints = npoints
|
||||
self.sample_rate_hz = sample_rate_hz
|
||||
self.app = pg.mkQApp(app_name)
|
||||
self.win = pg.GraphicsLayoutWidget(show=True, title=title)
|
||||
self.win.setWindowTitle(title)
|
||||
|
||||
self.data = np.zeros((npoints, 2, 3), dtype=np.float64)
|
||||
for channel in range(3):
|
||||
self.data[:, 0, channel] = np.linspace(-npoints, 0, npoints) / sample_rate_hz
|
||||
|
||||
p1 = self.win.addPlot(title="法向力")
|
||||
p1.setLabel("bottom", "时间", units="s")
|
||||
self.win.nextRow()
|
||||
p2 = self.win.addPlot(title="切向力 X")
|
||||
p2.setLabel("bottom", "时间", units="s")
|
||||
self.win.nextRow()
|
||||
p3 = self.win.addPlot(title="切向力 Y")
|
||||
p3.setLabel("bottom", "时间", units="s")
|
||||
|
||||
self._plots = (p1, p2, p3)
|
||||
self._curves = (p1.plot(pen="k"), p2.plot(pen="k"), p3.plot(pen="k"))
|
||||
|
||||
def push(self, timestamp: float, fn: float, fx: float, fy: float) -> None:
|
||||
for channel in range(3):
|
||||
self.data[:-1, 0, channel] = self.data[1:, 0, channel]
|
||||
self.data[:-1, 1, channel] = self.data[1:, 1, channel]
|
||||
self.data[-1, 0, :] = timestamp
|
||||
self.data[-1, 1, 0] = fn
|
||||
self.data[-1, 1, 1] = fx
|
||||
self.data[-1, 1, 2] = fy
|
||||
|
||||
def refresh(self, display_data: np.ndarray | None = None) -> None:
|
||||
plot_data = self.data if display_data is None else display_data
|
||||
for channel, (plot, curve) in enumerate(zip(self._plots, self._curves)):
|
||||
curve.setData(plot_data[:, :, channel])
|
||||
plot.setYRange(float(plot_data[:, 1, channel].min()), float(plot_data[:, 1, channel].max()))
|
||||
Reference in New Issue
Block a user