--- title: Movement Tracker emoji: 👋 colorFrom: red colorTo: blue sdk: static pinned: false short_description: Looks at whatever is moving tags: - reachy_mini - reachy_mini_python_app --- # Movement Tracker A Reachy Mini app that looks at whatever is moving. It uses OpenCV's MOG2 background subtractor to find pixels that differ from the learned background, groups them into blobs, and turns its head toward the largest one. After each move the background is relearned, since the robot's own motion changes the whole view. If nothing moves for a while, it scans: the head sweeps smoothly left and right while watching for motion. MOG2 needs a still camera, so scanning uses a second detector that cancels out the head's own motion: it tracks background features between frames, fits the homography that explains how they moved (a turning head is close to a pure rotation, which a homography models exactly), warps the older frame to line up with the newer one, and looks for what still differs. When it sees motion, the robot turns toward it and goes back to tracking. ## Motion Map The settings page at `http://:8042` shows a live motion map for checking detection: the camera view with the largest blob boxed (green if the robot will turn toward it, red if it is below the minimum blob size), the raw detector output (the background-subtraction mask while still, the aligned frame difference while scanning), and the cleaned mask used to pick the blob. Above it is what the robot is doing (learning the background, watching, tracking, or scanning). ## Tuning The settings page has sliders for the change thresholds (still and scanning) and the minimum blob size, so detection can be tuned live while watching the motion map. Changes last until the app restarts; the defaults are the constants at the top of `movement_tracker/motion.py`: | Constant | Meaning | |-------------------|-------------------------------------------------------------------| | `VAR_THRESHOLD` | MOG2 change threshold; raise it to ignore noise and flicker. | | `MIN_BLOB_FRAC` | Smallest blob, as a fraction of the image, that triggers a turn. | | `WARMUP` | Frames used to learn the background before reacting. | | `DIFF_THRESHOLD` | Change, after cancelling head motion, that counts while scanning. | | `FRAME_GAP` | Frames apart when comparing while scanning; higher sees slower. | Behavior constants live at the top of `movement_tracker/main.py`: | Constant | Meaning | |----------------|-----------------------------------------------------------| | `DEADBAND` | How far from the image center motion must be to turn. | | `IDLE_TIMEOUT` | Seconds without motion before scanning starts. | | `SCAN_RANGE` | How far the head sweeps each way, relative to body. | | `SCAN_SPEED` | Sweep speed; faster blurs frames and breaks alignment. | | `SCAN_CONFIRM` | Consecutive detections needed to stop a sweep. | ## Deployment The app is published as the private Hugging Face Space `blambert/movement-tracker`. To install it, log in to Hugging Face from the robot's dashboard and add the app from there. The Space is a git remote. Set it up once (this requires an SSH key added to your Hugging Face account): git remote add space git@hf.co:spaces/blambert/movement-tracker Then publish `main` to the Space: git push space main ## Development Run the tests (they cover only the detector, so the full `reachy-mini` install isn't needed): uv run --no-project --with pytest --with numpy --with opencv-python-headless pytest Check formatting: uvx black --check . uvx isort --check .