实现 ESP32-S3 上单摄像头人脸追踪的核心代码骨架,替代 Grove Vision AI V2
模块,通过 UART 发送人脸坐标驱动 RP2040 控制的眼球/YAW 舵机。
## 规划文档(docs/phase-01-face-tracking/)
- GOAL.md Phase 目标与 5 大成功标准
- RESEARCH.md esp-dl v3.2/3.3 + human_face_detect 0.4.1 技术调研
- PLAN.md 15 个原子任务的执行计划(T01-T15)
- PLAN_CHECK.md 计划审查报告(PASS_WITH_NOTES)
- PROGRESS.md 执行进度追踪(批次 1-3 已完成)
## 批次 1:依赖与开关(T01-T03)
- main/idf_component.yml
新增 esp-dl ~3.3.0 + human_face_detect 0.4.1(仅 S3/P4)
esp-sr 从 ~2.2.0 升级到 ~2.3.1,解决 esp-dsp 1.6/1.7 版本冲突
- main/Kconfig.projbuild
新增 CONFIG_XIAOZHI_ENABLE_FACE_TRACKING 开关(默认 y,depends on S3)
新增 CONFIG_XIAOZHI_FACE_TRACKING_FPS_CHOICE(5/10/15)
- main/boards/common/esp32_camera.{h,cc}
新增 ProbeFrameCapture() 最小 V4L2 DQBUF/QBUF 探针(T01)
- main/application.cc
Start() 末尾调用 probe 验证摄像头硬件链路
## 批次 2:人脸检测核心(T04-T06)
- main/boards/common/esp32_camera.{h,cc}
新增 FrameRef 结构体 + CaptureForDetection/ReleaseDetectionFrame
双超时 mutex 策略:face_tracker 10ms timeout 跳帧,Capture() RAII guard
- main/face_tracker.{h,cc}(新建)
Core 0 / 优先级 2 / 栈 8KB 独立任务
集成 esp-dl HumanFaceDetect 推理
坐标归一化 cx*224/W-112,匹配 RP2040 pixel_centre=112
多人脸遍历挑 score 最高,避免多脸时眼球摇摆
三重保护:Kconfig depends on S3 + 源文件 #if 守卫 + CMake 条件排除
- main/CMakeLists.txt
非 S3 目标从 SOURCES 移除 face_tracker.cc
## 批次 3:UART 协议扩展(T07)
- main/uart_component.{h,cc}
新增 uart_send_face(x,y) 发送 face:x,y\r\n 协议
extern "C" 链接名配合 face_tracker 的弱符号声明
全局 TX mutex 保护所有 UART 写入,防并发帧交织
uart_send_string 同步加锁保持一致性
## 编译验证
idf.py build 通过,固件 2.51MB / 剩余 1.46MB (36% free)
当前 face_tracker 未被 application 激活(留到 T11),
UART/摄像头现有功能零影响。
## 未完成(下次继续)
- T01 硬件 probe 实机验证
- T08-T10 RP2040 端 parse_face + facetrack 双数据源改造
- T11-T15 application 接入 + 端到端联调 + 性能调优 + 最终验收
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.9 KiB
3.9 KiB
Phase 1: 单摄像头人脸追踪
目标
将 ESP32-S3 上的 OV3660 摄像头用作人脸追踪数据源,替代 Grove Vision AI V2 模块,驱动 RP2040 控制的眼球(EYL/EYR)和身体(YAW)舵机追踪人脸移动。
硬件环境
- ESP32 模组: ESP32-S3-WROOM-1-N16R8(16MB Flash + 8MB PSRAM)
- 摄像头: OV3660 DVP 接口(已完成 3 根飞线:GPIO 35→14, 36→41, 37→42)
- RP2040: Raspberry Pi Pico(直接焊在 CogNog V1.0 PCB 上)
- 舵机: 9 个 180° 标准舵机(KPower M0090 / MG90S 180°)
- 无 Grove Vision AI V2: 本 Phase 的核心目的是省去此模块
当前架构(改造前)
OV3660 → ESP32-S3(仅显示/视觉辅助功能)
Grove Vision AI V2 → UART 921600 → RP2040 的 GP0/GP1
↓
facetrack() 解析 boxes
↓
驱动 EYL/EYR/PIT/YAW
目标架构(改造后)
OV3660 → ESP32-S3
├── 视觉辅助功能(保留)
└── 人脸检测推理(新增)
↓
提取人脸中心 (x, y) 偏移
↓
UART 115200 → RP2040 的 GP4/GP5
↓
coms.py 识别 face: 协议,注入 facetrack()
↓
驱动 EYL/EYR/PIT/YAW(复用现有逻辑)
成功标准(Success Criteria)
必须同时满足:
-
性能指标
- ESP32 摄像头帧率 ≥ 5 FPS(QVGA 320×240 或更低分辨率)
- 人脸检测延迟 ≤ 200ms
- 坐标传输延迟 ≤ 50ms
-
功能正确性
- 检测到人脸时,ESP32 通过 UART 发送格式化坐标到 RP2040
- RP2040 接收坐标后眼球和身体正确追踪人脸方向
- 人脸偏离摄像头中心时,眼球先转动,YAW 延迟跟随(保留现有逻辑)
- 无人脸时,3 秒后
grove_active标志自动置为 False,回退到随机动画
-
不破坏现有功能
- 语音对话(WebSocket + Opus 音频编解码)无卡顿、无断连
- 唤醒词检测正常工作
- LCD 显示(如有)正常刷新
- 现有 UART 状态指令(
"idle","listening","speaking"等)继续工作
-
代码质量
- ESP32 端人脸检测任务运行在 Core 0,与音频/WiFi 隔离
- PSRAM 合理使用,不出现 OOM
- UART 协议向后兼容(不影响 RP2040 现有状态指令解析)
- 所有新增代码有清晰的中文注释
-
可维护性
- 支持无 Grove 和有 Grove 两种模式自动切换(复用已有的
grove_active机制) - ESP32 侧面能通过 menuconfig 或宏定义开关人脸检测功能
- 支持无 Grove 和有 Grove 两种模式自动切换(复用已有的
涉及的代码库
- ESP32 端:
/Users/rdzleo/Desktop/CogletESP-camera-version(当前目录) - RP2040 端:
/Users/rdzleo/Desktop/CogletESP-CogletESP/RP2040(另一个本地目录)
注意:RP2040 侧的
coms.py和main.py已经做过一次增强动画改造(2026-04-17)。本 Phase 需要在此基础上继续增加 ESP32 人脸坐标协议支持。
非目标(Out of Scope)
- 不做人脸识别(谁的脸),只做人脸检测(有没有脸 + 在哪里)
- 不做多人追踪(只追踪第一张检测到的脸)
- 不实现 180° 全景追踪(保持原 Grove 方案的追踪范围)
- 不改变眼球/YAW 的追踪算法(复用
main.py facetrack()中的现有逻辑)
风险与限制
- 性能风险: ESP32-S3 同时运行 WiFi + WebSocket + Opus + AI 对话 + LVGL + 摄像头 + 人脸检测,CPU 和内存压力大
- 音频干扰风险: 人脸检测占用的 Core 0 可能与音频共享,导致对话卡顿
- 跨项目协调: ESP32 和 RP2040 属于不同代码库,需协调 UART 协议
- 模型精度: esp-dl 的人脸检测模型精度低于 Grove Vision AI V2,追踪流畅度可能下降