Gimbal Motion Detect

SkillDev tools

Use this skill when the user wants esp-claw to show the camera preview on the LCD and draw a bounding box around moving regions. The script opens the board camera, converts frames to RGB565, displays the same centered preview style used by gimbalcolordetect, and runs the standalone motiondetect Lua module.

Use Gimbal Motion Detect in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add Gimbal Motion Detect and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the Gimbal Motion Detect skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Gimbal Motion DetectStart free
About this skill

ESP-Claw Skills Lab

What this skill tells your AI

The instructions your AI receives, as published by espressif/esp-claw-skills-lab in skills/gimbal_motion_detect/SKILL.md and read by Ahel’s review.

Use this skill when the user wants esp-claw to show the camera preview on the LCD and draw a bounding box around moving regions. The script opens the board camera, converts frames to RGB565, displays the same centered preview style used by gimbal_color_detect, and runs the standalone motion_detect Lua module.

Preview display crops a centered 240x240 square from the board-default camera stream and draws it centered on the 284x240 LCD without additional flipping.

Default Hardware

  • Camera device: from board_manager.get_camera_paths()
  • Camera stream: board default mode from camera.open(dev_path)
  • LCD panel: from board_manager.get_display_lcd_params("display_lcd")
  • Runtime shape: a single async Lua job owns camera, LCD preview, and motion detection.
  • Display updates: full-frame double-buffered rendering when two framebuffers can be allocated; each preview frame uses clear = false, preserve = false, display.present_full(), and display.end_frame({ wait = false }) so the next frame can be prepared while panel DMA refresh is in flight. If only one framebuffer can be allocated, the display module falls back to single buffering.

If the board manager camera path cannot be opened, the script tries /dev/video0 through /dev/video7 before failing and reports every attempted path.

Start Script Args Schema

{
  "type": "object",
  "properties": {
    "run_seconds": {
      "type": "integer",
      "default": 0,
      "description": "0 means run until the async Lua job receives a cooperative stop request."
    },
    "capture_timeout_ms": {
      "type": "integer",
      "default": 500,
      "description": "Camera frame wait timeout. Keep this short enough that stop requests can reach cleanup quickly."
    },
    "frame_interval_ms": {
      "type": "integer",
      "default": 0,
      "description": "Extra delay after each frame. Keep 0 for maximum camera/display throughput."
    },
    "display_every_n": {
      "type": "integer",
      "default": 1
    },
    "perf_log_every_n": {
      "type": "integer",
      "default": 30,
      "description": "Print average get/convert/detect/display/loop timing every N frames. Set 0 to disable."
    },
    "display_crop_size": {
      "type": "integer",
      "default": 240,
      "description": "Centered square crop size before drawing to the LCD."
    },
    "pixel_diff_threshold": {
      "type": "integer",
      "default": 24,
      "description": "Per-pixel luma difference threshold."
    },
    "active_pixel_percent": {
      "type": "integer",
      "default": 5,
      "description": "Minimum active-pixel percentage inside the ROI required for raw motion."
    },
    "confirm_frames": {
      "type": "integer",
      "default": 2
    },
    "hold_frames": {
      "type": "integer",
      "default": 3
    },
    "block_size": {
      "type": "integer",
      "default": 4
    },
    "block_hit_pixels": {
      "type": "integer",
      "default": 15
    },
    "box_padding": {
      "type": "integer",
      "default": 2
    },
    "box_deadband": {
      "type": "integer",
      "default": 2
    },
    "box_snap_threshold": {
      "type": "integer",
      "default": 24
    }
  }
}

Tool Call Inputs

Start motion tracking:

{
  "path": "{CUR_SKILL_DIR}/scripts/start_gimbal_motion_detect.lua",
  "args": {},
  "timeout_ms": 0,
  "name": "gimbal_motion_detect",
  "exclusive": "gimbal_motion_detect",
  "replace": true
}

Stop motion tracking:

{
  "name": "gimbal_motion_detect",
  "wait_ms": 2000
}

Stop requests are handled by the Lua job executor. The script keeps the camera capture timeout short so stop can interrupt promptly, then runs camera, display, and detector cleanup from the script exit path.

Recommended Flow

  1. Activate gimbal_motion_detect.
  2. Run {CUR_SKILL_DIR}/scripts/start_gimbal_motion_detect.lua with lua_run_script_async.
  3. Use timeout_ms: 0, name: "gimbal_motion_detect", exclusive: "gimbal_motion_detect", and replace: true.
  4. Tune pixel_diff_threshold, active_pixel_percent, and block_hit_pixels for sensitivity.

Signals

GitHub stars
34
Forks
17
Last commit
Sep 2026
Advanced
Item type
skill
Key
gimbal-motion-detect
Source
github.com/espressif/esp-claw-skills-lab