summaryrefslogtreecommitdiff
path: root/plugins/motion_capture/device.py
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/motion_capture/device.py')
-rw-r--r--plugins/motion_capture/device.py85
1 files changed, 85 insertions, 0 deletions
diff --git a/plugins/motion_capture/device.py b/plugins/motion_capture/device.py
new file mode 100644
index 0000000..f0d082c
--- /dev/null
+++ b/plugins/motion_capture/device.py
@@ -0,0 +1,85 @@
+"""
+motion_capture/device.py
+
+BaseDevice that reads x/y position from CameraTracker.
+
+Channels:
+ x_pos — horizontal position [px] (left=0, right=frame_width)
+ y_pos — vertical position [px] (top=0, bottom=frame_height)
+
+Apply the pixel_to_mm filter in Signals → Channels to convert to mm.
+"""
+
+from __future__ import annotations
+
+import threading
+from typing import Any, Dict
+
+from devices.base_device import (
+ BaseDevice, ChannelConfig, DeviceInfo, DeviceStatus,
+)
+
+
+class MotionCaptureDevice(BaseDevice):
+
+ def __init__(self, tracker, device_id: str = "motion_capture"):
+ super().__init__(DeviceInfo(
+ device_id = device_id,
+ name = "Motion Capture",
+ device_type = "virtual",
+ description = "Camera point-tracking — x/y position in pixels.",
+ icon = "🎥",
+ channels = [
+ ChannelConfig(
+ channel_id = "x_pos",
+ name = "X Position",
+ unit = "px",
+ min_value = 0.0,
+ max_value = 1920.0,
+ color = "#00d4ff",
+ ),
+ ChannelConfig(
+ channel_id = "y_pos",
+ name = "Y Position",
+ unit = "px",
+ min_value = 0.0,
+ max_value = 1080.0,
+ color = "#f72585",
+ ),
+ ],
+ ))
+ self._tracker = tracker
+ self._lock = threading.Lock()
+ self._last = (0.0, 0.0)
+
+ # ── BaseDevice interface ──────────────────────────────────────────────
+
+ def connect(self) -> bool:
+ self.status = DeviceStatus.SIMULATED
+ return True
+
+ def disconnect(self) -> None:
+ self.status = DeviceStatus.DISCONNECTED
+
+ def read_channels(self) -> Dict[str, float]:
+ pos = self._tracker.get_position()
+ if pos is not None:
+ with self._lock:
+ self._last = pos
+ with self._lock:
+ x, y = self._last
+ return {"x_pos": x, "y_pos": y}
+
+ def write_channel(self, channel_id: str, value: Any) -> bool:
+ return False
+
+ def get_config_widget(self):
+ from PyQt6.QtWidgets import QLabel
+ lbl = QLabel(
+ "Configure via the Motion Capture toolbar window.\n\n"
+ "Apply 'pixel_to_mm' filter in Signals → Channels\n"
+ "to convert pixel coordinates to millimetres."
+ )
+ lbl.setObjectName("traceSource")
+ lbl.setWordWrap(True)
+ return lbl