1. tuned arrow mesh drawing

2. centralixzed arrow config in layout.py
3. seperate mesh render and display resolution to speed up (~40 fps)
This commit is contained in:
ykcheungab
2026-06-19 14:28:28 +08:00
parent 3fd9b839a9
commit 2e5c047d1e
19 changed files with 980 additions and 147 deletions
+24 -22
View File
@@ -66,6 +66,7 @@ class ForceChartWidget:
def _init_plot_buffer(self) -> None:
self.data = np.full((self.npoints, 2, 3), np.nan, dtype=np.float64)
self._plot_sample_count = 0
self._time_origin: float | None = None
self._y_range_smooth = [None, None, None]
def _create_plots(self) -> None:
@@ -134,6 +135,9 @@ class ForceChartWidget:
plot.setXRange(0, self._plot_window_sec, padding=0)
def update_frame(self, frame: FingerFrameView) -> None:
if self._time_origin is None:
self._time_origin = frame.timestamp
if self._plot_sample_count < self.npoints:
idx = self._plot_sample_count
self.data[idx, 0, :] = frame.timestamp
@@ -151,36 +155,36 @@ class ForceChartWidget:
self.data[-1, 1, 2] = frame.fsheary
n = self._plot_sample_count
if n == 0:
if n == 0 or self._time_origin is None:
return
layout = self._layout
data_plot = self.data[:n].copy()
times = data_plot[:, 0, 0] - float(data_plot[0, 0, 0])
data_plot = self.data[:n]
times = data_plot[:, 0, 0] - self._time_origin
x_end = float(times[-1])
if x_end < self._plot_window_sec:
x_start = 0.0
x_end = self._plot_window_sec
else:
x_start = x_end - self._plot_window_sec
for channel in range(3):
data_plot[:, 1, channel] = lowpass_filter(
data_plot[:, 1, channel],
y = lowpass_filter(
data_plot[:, 1, channel].copy(),
self.lowpass_cutoff_hz,
sample_rate_hz=self.sample_rate_hz,
)
x_end = float(times[-1])
x_start = max(0.0, x_end - self._plot_window_sec)
if x_end - x_start < self._plot_window_sec:
x_start = 0.0
x_end = max(self._plot_window_sec, x_end)
for i, curve in enumerate(self.curves):
y = data_plot[:, 1, i]
curve = self.curves[channel]
curve.setData(times, y)
finite = np.isfinite(y)
if not np.any(finite):
continue
ymin, ymax = float(np.min(y[finite])), float(np.max(y[finite]))
if self._y_range_smooth[i] is None:
self._y_range_smooth[i] = (ymin, ymax)
if self._y_range_smooth[channel] is None:
self._y_range_smooth[channel] = (ymin, ymax)
else:
prev_min, prev_max = self._y_range_smooth[i]
prev_min, prev_max = self._y_range_smooth[channel]
alpha = self._y_range_alpha
ymin = alpha * ymin + (1 - alpha) * prev_min
ymax = alpha * ymax + (1 - alpha) * prev_max
@@ -190,13 +194,11 @@ class ForceChartWidget:
half = layout.y_axis_min_span / 2
ymin = mid - half
ymax = mid + half
self._y_range_smooth[i] = (ymin, ymax)
self._y_range_smooth[channel] = (ymin, ymax)
pad = max((ymax - ymin) * 0.12, 0.01)
self.plots[i].setYRange(ymin - pad, ymax + pad)
last_x = times[-1:]
last_y = y[-1:]
self.dot_glows[i].setData(last_x, last_y)
self.dot_cores[i].setData(last_x, last_y)
self.plots[channel].setYRange(ymin - pad, ymax + pad)
self.dot_glows[channel].setData(times[-1:], y[-1:])
self.dot_cores[channel].setData(times[-1:], y[-1:])
for plot in self.plots:
plot.setXRange(x_start, x_end, padding=0)