summaryrefslogtreecommitdiff
path: root/plugins/motion_capture/device.py
AgeCommit message (Collapse)Author
2026-09-19Redesign Signal/Channel naming and fix pin-remap breaking referencesChristian Kolset
Arduino analog Signal ids used to be the pin name itself, so fixing a wrong pin silently changed the id and orphaned any plot trace, control, or filter pipeline pointing at it. Analog Signal ids are now positional (ai0, ai1, ...) and decoupled from the underlying pin, matching how digital I/O already worked. More broadly, formalizes a Device -> Signal -> Channel -> Plot naming model (SignalConfig for physical device channels, Channel for derived/ computed ones) and adds core/reference_registry.py to propagate any Signal or Channel id rename through plot traces, controls, and filter pipelines instead of leaving them dangling. Signal ids are now editable in the Signals tab with the same propagation. .labui profile schema bumped to v2.0 with a transparent migration for old files, including remapping old pin-name Signal ids to the new positional ones. Removed six confirmed-dead files (two legacy device classes, four superseded top-level ui/ duplicates).
2026-08-17Fix motion capture UI freezes: throttling, async camera open/scan, stale pollChristian Kolset
Several compounding freeze sources in plugins/motion_capture/: - tracker.py: _run_real had no frame-rate cap independent of the camera's configured fps (up to 120fps/2560x1440 was possible), and no bound on consecutive failed reads — a camera that "opens" (cv2 isOpened() can lie, seen with Windows MSMF/obsensor) but never actually delivers frames would get hammered forever. Added a 20Hz processing cap, a real test-read before committing to a camera, and a give-up-after-30-failures fallback to simulation. - tracker.py/device.py: cv2.VideoCapture() opening a real camera is a slow, blocking call — CameraTracker.start() used to do this synchronously on the caller's thread, which froze the whole app when ProfileManager.apply() called it during profile load. Now runs on the background thread; status reporting (CameraDevice) moved to an on_result callback since the caller can no longer learn the outcome synchronously. - window.py: the Camera View preview ran a 30Hz GUI-thread timer doing a full-frame copy + QImage/QPixmap rebuild every tick unconditionally (no visibility check) — dropped to 10Hz and skips entirely when hidden. Camera enumeration (list_cameras(), up to 8 sequential cv2.VideoCapture probes) also ran inline in the window constructor, blocking it open the same way camera_panel.py's CameraScanThread already avoided for the Add Device dialog — moved to the same async pattern here. config_window.py: separately, ConfigWindow._dev_poll (device status label refresh) was stopped in closeEvent and never restarted, since MainWindow reuses the same ConfigWindow instance across opens — invisible before because connect() was synchronous, but with the above change a device can sit in CONNECTING for a while, and a stale poll made that look stuck forever after reopening the window. Restart it in showEvent. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29Add editable device display name, persist it across profile save/loadChristian Kolset
DeviceInfo.name existed but was hardcoded per device type and never operator-editable. Adds a Display Name field to Add Device and makes the Info-tab Name field in the device config dialog editable, and threads the name through get_save_config()/ProfileManager.apply() so a custom name survives a .labdaq save/reload instead of reverting to the type default. Name is applied post-construction rather than as a constructor kwarg, since no device factory declares a "name" param. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-06-09Motion capture: profile support, FPS config, persistent tracking, window stateChristian Kolset
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>
2026-06-09Upgrade motion capture: template matching, frame-freeze selection, resolutionChristian Kolset
Tracking: - Add "template" mode (default) using snapshot + shape-masked matchTemplate - Add "csrt" mode as alternative for texture-rich targets - set_roi_rect(x, y, w, h, frame_rgb) initialises from exact selection rect - set_roi() delegates to set_roi_rect (centred square, backwards-compat) - start() accepts resolution=(w, h) to set camera capture resolution Selection UX: - Replace QLabel feed with FrameSelector widget (custom QWidget) - "Click to Track" freezes frame; user scrolls to zoom (anchored to cursor), right-drags to pan, left-drags to draw rubber-band selection - Shape preview: rectangle or inscribed ellipse depending on mode - "Confirm Selection" extracts template from frozen frame and starts tracking - "Clear" cancels selection or clears active tracking Configuration: - CameraPanel adds Resolution combo (Default / 640×480 / 720p / 1080p / 1440p) - CameraDevice stores and forwards resolution to tracker.start() - Template Match listed first in Mode combo; shape combo hidden for CSRT Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04Redesign motion capture plugin as Camera device typeChristian Kolset
Plugin now registers a "Camera" option in the Add Device dialog on load (removes it on unload) instead of auto-creating a single device. - camera_panel.py (new): CameraPanel with CameraScanThread that probes OpenCV indices 0–5, lists found cameras with resolution, shows "No cameras detected" when none available, simulation checkbox. build_device() returns CameraDevice for the selected index. - device.py: rewrite MotionCaptureDevice → CameraDevice. Each instance owns its own CameraTracker created in connect(). Status is CONNECTED or SIMULATED based on tracker.simulated. get_config_widget() shows source/status and an "Open Camera View" button that launches the existing MotionCaptureWindow for that device's tracker. Backward-compat alias MotionCaptureDevice = CameraDevice kept for saved profiles. - plugin.py: simplified to on_load/_PANELS registration + pixel_to_mm filter. No auto-devices, no toolbar button, no settings widget. Camera data flows through the standard Device → Signal → Channel → Plot pipeline like any other device. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03Added Motion Capture pluginChristian Kolset
Tracks a user-selected point via webcam (OpenCV CSRT tracker) and streams x_pos / y_pos pixel coordinates as live channels into the acquisition pipeline. Falls back to a Lissajous figure simulation when opencv-python is not installed, so the plugin works immediately without hardware. - tracker.py: background thread, real camera + sim modes, thread-safe API - device.py: BaseDevice reading x/y from tracker, wires into engine - filter.py: custom pixel_to_mm filter (registered in FILTER_CLASSES) - window.py: floating tool window, live feed, click-to-track ROI selection - plugin.py: LabPlugin wiring all pieces together, toolbar button, settings widget, profile save/restore Also: PluginAction.button_ref_callback lets plugins store a ref to their toolbar button so they can uncheck it when their window closes. opencv-python install note added to requirements.txt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>