diff options
| author | Christian Kolset <christian.kolset@gmail.com> | 2026-06-09 19:39:35 -0600 |
|---|---|---|
| committer | Christian Kolset <christian.kolset@gmail.com> | 2026-06-09 19:39:35 -0600 |
| commit | b776e70b4cd94c5d1f53dde39b2e46f6447cac3e (patch) | |
| tree | fade07a8ecd7a771c095a4d636fa5570e1f8ee7c /plugins/motion_capture/plugin.py | |
| parent | 51f04ada503b02c598c9940c96fdc444cf5da52a (diff) | |
Motion capture: profile support, FPS config, persistent tracking, window state
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 <noreply@anthropic.com>
Diffstat (limited to 'plugins/motion_capture/plugin.py')
| -rw-r--r-- | plugins/motion_capture/plugin.py | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/plugins/motion_capture/plugin.py b/plugins/motion_capture/plugin.py index 0b44cb4..9cf9557 100644 --- a/plugins/motion_capture/plugin.py +++ b/plugins/motion_capture/plugin.py @@ -49,12 +49,16 @@ class MotionCapturePlugin(LabPlugin): # ── Lifecycle ───────────────────────────────────────────────────────── def on_load(self, context: PluginContext) -> None: - self._ctx = context - self._btn = None # toolbar button reference - self._windows: dict = {} # device_id → MotionCaptureWindow + self._ctx = context + self._btn = None # toolbar button reference + self._windows: dict = {} # device_id → MotionCaptureWindow + self._window_state: dict = {} # device_id → {px_per_mm, camera_idx} from ui.add_device_dialog import _PANELS from camera_panel import CameraPanel _PANELS["Camera"] = (CameraPanel, "cam") + from core.profile import ProfileManager + from device import CameraDevice + ProfileManager.register_device_factory(CameraDevice.DEVICE_TYPE, CameraDevice) def on_unload(self) -> None: for win in list(self._windows.values()): @@ -62,6 +66,9 @@ class MotionCapturePlugin(LabPlugin): self._windows.clear() from ui.add_device_dialog import _PANELS _PANELS.pop("Camera", None) + from core.profile import ProfileManager + from device import CameraDevice + ProfileManager.unregister_device_factory(CameraDevice.DEVICE_TYPE) # ── Integration hooks ───────────────────────────────────────────────── @@ -133,11 +140,27 @@ class MotionCapturePlugin(LabPlugin): self._btn.setChecked(False) return win = MotionCaptureWindow(device._tracker) - win.closed.connect(lambda: self._close_window(dev_id)) + + # Restore mode/shape from live tracker state + win.restore_ui_state( + mode=device._tracker.track_mode, + shape=device._tracker.template_shape, + ) + # Restore px/mm and camera index from last session + if dev_id in self._window_state: + state = self._window_state[dev_id] + win.set_px_per_mm(state["px_per_mm"]) + win.set_camera_index(state["camera_idx"]) + + win.closed.connect(lambda d=dev_id, w=win: self._on_window_closed(d, w)) self._windows[dev_id] = win win.show() - def _close_window(self, dev_id: str) -> None: + def _on_window_closed(self, dev_id: str, win) -> None: + self._window_state[dev_id] = { + "px_per_mm": win.get_px_per_mm(), + "camera_idx": win.get_camera_index(), + } self._windows.pop(dev_id, None) if not self._windows and self._btn is not None: self._btn.setChecked(False) |
