From b776e70b4cd94c5d1f53dde39b2e46f6447cac3e Mon Sep 17 00:00:00 2001 From: Christian Kolset Date: Tue, 9 Jun 2026 19:39:35 -0600 Subject: Motion capture: profile support, FPS config, persistent tracking, window state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Profile integration: - CameraDevice.get_save_config() serialises camera_index, simulate, resolution, fps — cameras now persist in .labdaq profiles - ProfileManager.register/unregister_device_factory() lets plugins register their device classes for profile restoration without core → plugin dependency - MotionCapturePlugin registers CameraDevice factory on load/unload Camera configuration: - Add Frame Rate combo to CameraPanel (Default/15/24/30/60/120 fps) defaults to 30 fps; flows through to CAP_PROP_FPS on connect - tracker.start() accepts fps param alongside existing resolution Tracking persistence: - CameraTracker.is_running() — checks thread alive state - MotionCaptureWindow initialises _connected from tracker.is_running() so reopening the window resumes the live feed without restarting the camera or losing the active tracking state Window state: - Plugin saves px_per_mm + camera_idx when window closes - Reopened window restores saved values and syncs mode/shape UI from tracker state via restore_ui_state() (signals blocked to avoid resetting tracker) - Window type changed to Qt.WindowType.Window for independent close button on all Linux WMs Co-Authored-By: Claude Sonnet 4.6 --- plugins/motion_capture/device.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'plugins/motion_capture/device.py') diff --git a/plugins/motion_capture/device.py b/plugins/motion_capture/device.py index 8eb1591..58f89ce 100644 --- a/plugins/motion_capture/device.py +++ b/plugins/motion_capture/device.py @@ -24,10 +24,13 @@ from devices.base_device import ( class CameraDevice(BaseDevice): + DEVICE_TYPE = "camera" + def __init__(self, device_id: str = "cam_0", camera_index: int = 0, simulate: bool = False, - resolution=None): + resolution=None, + fps=None): name = "Camera (Sim)" if simulate else f"Camera {camera_index}" super().__init__(DeviceInfo( device_id = device_id, @@ -57,6 +60,7 @@ class CameraDevice(BaseDevice): self._camera_index = camera_index self._simulate = simulate self._resolution = resolution + self._fps = fps self._tracker: Optional[Any] = None self._tracking_win = None @@ -68,6 +72,7 @@ class CameraDevice(BaseDevice): self._tracker.start( -1 if self._simulate else self._camera_index, resolution=self._resolution, + fps=self._fps, ) if self._tracker.simulated: self.status = DeviceStatus.SIMULATED @@ -93,6 +98,16 @@ class CameraDevice(BaseDevice): x, y = pos return {"x_pos": float(x), "y_pos": float(y)} + def get_save_config(self) -> dict: + return { + "device_type": self.DEVICE_TYPE, + "device_id": self.info.device_id, + "camera_index": self._camera_index, + "simulate": self._simulate, + "resolution": list(self._resolution) if self._resolution else None, + "fps": self._fps, + } + def write_channel(self, channel_id: str, value: Any) -> bool: return False -- cgit v1.2.3