Commit ·
a26fdbd
1
Parent(s): beb8e32
docs: Update PROJECT_PLAN.md - add face tracking, update Phase 14/17
Browse files- PROJECT_PLAN.md +68 -21
PROJECT_PLAN.md
CHANGED
|
@@ -16,10 +16,11 @@
|
|
| 16 |
2. **使用 Reachy Mini 原生硬件** - 使用机器人自带的麦克风和扬声器
|
| 17 |
3. **Home Assistant 集中管理** - 所有配置在 Home Assistant 端完成
|
| 18 |
4. **运动反馈** - 语音交互时提供头部运动和天线动画反馈
|
| 19 |
-
5. 整个项目需要严格遵循 [Reachy Mini SDK](reachy_mini) 的架构设计与约束
|
| 20 |
-
6. 严格遵循Python开发的标准,并做到代码风格一致,代码结构清晰,注释完整,文档完善,测试覆盖率高,代码质量高,代码可读性高,代码可维护性高,代码可扩展性高,代码可复用性高
|
| 21 |
-
7. 与home assistant的语音对话为最高优先级,任何其它的功能都是辅助功能,不能影响语音对
|
| 22 |
-
8. LED都被隐藏在了机器人内部,所有的LED控制全部都忽略,不要使用LED控制
|
|
|
|
| 23 |
|
| 24 |
## 技术架构
|
| 25 |
|
|
@@ -37,12 +38,18 @@
|
|
| 37 |
│ └─────────────┘ └─────────────┘ │
|
| 38 |
│ │
|
| 39 |
│ ┌─────────────────────────────────────────────────────┐ │
|
| 40 |
-
│ │
|
| 41 |
-
│ │ -
|
| 42 |
-
│ │ -
|
| 43 |
-
│ │ -
|
| 44 |
-
│
|
| 45 |
-
│
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
│ └─────────────────────────────────────────────────────┘ │
|
| 47 |
└─────────────────────────────────────────────────────────────┘
|
| 48 |
│
|
|
@@ -73,6 +80,8 @@
|
|
| 73 |
- [x] 头部运动控制(点头、摇头、注视)
|
| 74 |
- [x] 天线动画控制
|
| 75 |
- [x] 语音状态反馈动作
|
|
|
|
|
|
|
| 76 |
|
| 77 |
### 应用架构
|
| 78 |
- [x] 符合 Reachy Mini App 架构
|
|
@@ -86,12 +95,13 @@
|
|
| 86 |
reachy_mini_ha_voice/
|
| 87 |
├── reachy_mini_ha_voice/
|
| 88 |
│ ├── __init__.py # 包初始化
|
| 89 |
-
│ ├── __main__.py
|
| 90 |
│ ├── main.py # ReachyMiniApp 入口
|
| 91 |
│ ├── voice_assistant.py # 语音助手服务
|
| 92 |
│ ├── satellite.py # ESPHome 协议处理
|
| 93 |
│ ├── audio_player.py # 音频播放器
|
| 94 |
-
│ ├── camera_server.py # MJPEG 摄像头流服务
|
|
|
|
| 95 |
│ ├── motion.py # 运动控制 (高层 API)
|
| 96 |
│ ├── movement_manager.py # 统一运动管理器 (20Hz 控制循环,优化以防止 daemon 崩溃)
|
| 97 |
│ ├── models.py # 数据模型
|
|
@@ -407,19 +417,56 @@ automation:
|
|
| 407 |
option: "Happy"
|
| 408 |
```
|
| 409 |
|
| 410 |
-
### Phase 14 -
|
| 411 |
|
| 412 |
-
**目标**:
|
| 413 |
|
| 414 |
-
**
|
| 415 |
-
|
|
|
|
|
|
|
| 416 |
|
| 417 |
-
|
|
|
|
|
|
|
| 418 |
|------|------|---------|---------|
|
| 419 |
-
|
|
| 420 |
-
|
|
| 421 |
-
|
|
| 422 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 423 |
|
| 424 |
### Phase 15 - 卡通风格运动模式 (部分实现) 🟡
|
| 425 |
|
|
|
|
| 16 |
2. **使用 Reachy Mini 原生硬件** - 使用机器人自带的麦克风和扬声器
|
| 17 |
3. **Home Assistant 集中管理** - 所有配置在 Home Assistant 端完成
|
| 18 |
4. **运动反馈** - 语音交互时提供头部运动和天线动画反馈
|
| 19 |
+
5. **项目约束** - 整个项目需要严格遵循 [Reachy Mini SDK](reachy_mini) 的架构设计与约束
|
| 20 |
+
6. **代码质量** - 严格遵循Python开发的标准,并做到代码风格一致,代码结构清晰,注释完整,文档完善,测试覆盖率高,代码质量高,代码可读性高,代码可维护性高,代码可扩展性高,代码可复用性高
|
| 21 |
+
7. **功能优先级** - 与home assistant的语音对话为最高优先级,任何其它的功能都是辅助功能,不能影响语音对话的功能和响应速度
|
| 22 |
+
8. **不调用任何LED功能** - LED都被隐藏在了机器人内部,所有的LED控制全部都忽略,不要使用LED控制
|
| 23 |
+
9. **保留功能优先** - 任何代码修改都应该在保留已完成功能的前提下优化,不能以去除功能的方式来解决问题。当有问题发生时,应该充分参考案例之后以解决问题为优先级,而不是添加各种日志输出为优先级
|
| 24 |
|
| 25 |
## 技术架构
|
| 26 |
|
|
|
|
| 38 |
│ └─────────────┘ └─────────────┘ │
|
| 39 |
│ │
|
| 40 |
│ ┌─────────────────────────────────────────────────────┐ │
|
| 41 |
+
│ │ Camera + Face Tracking (YOLO) │ │
|
| 42 |
+
│ │ - 15Hz 人脸检测与追踪 │ │
|
| 43 |
+
│ │ - look_at_image() 计算目标姿态 │ │
|
| 44 |
+
│ │ - 人脸丢失后平滑回中性位置 │ │
|
| 45 |
+
│ └─────────────────────────────────────────────────────┘ │
|
| 46 |
+
│ │
|
| 47 |
+
│ ┌─────────────────────────────────────────────────────┐ │
|
| 48 |
+
│ │ Motion Controller (Head + Antennas) - 5Hz │ │
|
| 49 |
+
│ │ - Face tracking offsets (secondary pose) │ │
|
| 50 |
+
│ │ - Speech sway (语音驱动微动) │ │
|
| 51 |
+
│ │ - Breathing animation (空闲呼吸) │ │
|
| 52 |
+
│ │ - on_wakeup → on_listening → on_speaking → on_idle │ │
|
| 53 |
│ └─────────────────────────────────────────────────────┘ │
|
| 54 |
└─────────────────────────────────────────────────────────────┘
|
| 55 |
│
|
|
|
|
| 80 |
- [x] 头部运动控制(点头、摇头、注视)
|
| 81 |
- [x] 天线动画控制
|
| 82 |
- [x] 语音状态反馈动作
|
| 83 |
+
- [x] YOLO 人脸追踪(替代 DOA 声源定位)
|
| 84 |
+
- [x] 5Hz 统一运动控制循环
|
| 85 |
|
| 86 |
### 应用架构
|
| 87 |
- [x] 符合 Reachy Mini App 架构
|
|
|
|
| 95 |
reachy_mini_ha_voice/
|
| 96 |
├── reachy_mini_ha_voice/
|
| 97 |
│ ├── __init__.py # 包初始化
|
| 98 |
+
│ ├── __main__.py py # 命令行入口
|
| 99 |
│ ├── main.py # ReachyMiniApp 入口
|
| 100 |
│ ├── voice_assistant.py # 语音助手服务
|
| 101 |
│ ├── satellite.py # ESPHome 协议处理
|
| 102 |
│ ├── audio_player.py # 音频播放器
|
| 103 |
+
│ ├── camera_server.py # MJPEG 摄像头流服务器 + 人脸追踪
|
| 104 |
+
│ ├── head_tracker.py # YOLO 人脸检测器
|
| 105 |
│ ├── motion.py # 运动控制 (高层 API)
|
| 106 |
│ ├── movement_manager.py # 统一运动管理器 (20Hz 控制循环,优化以防止 daemon 崩溃)
|
| 107 |
│ ├── models.py # 数据模型
|
|
|
|
| 417 |
option: "Happy"
|
| 418 |
```
|
| 419 |
|
| 420 |
+
### Phase 14 - 人脸追踪(替代 DOA 声源追踪)✅ **已完成**
|
| 421 |
|
| 422 |
+
**目标**: 实现自然的人脸追踪,让机器人在对话时注视说话人。
|
| 423 |
|
| 424 |
+
**设计决策**:
|
| 425 |
+
- ❌ 原计划使用 DOA (Direction of Arrival) 声源追踪
|
| 426 |
+
- ✅ 改用 YOLO 人脸检测,更稳定、更准确
|
| 427 |
+
- 原因:DOA 在唤醒时判断不够准确,且频繁查询会导致 daemon 崩溃
|
| 428 |
|
| 429 |
+
**已实现功能**:
|
| 430 |
+
|
| 431 |
+
| 功能 | 说明 | 实现位置 | 实现状态 |
|
| 432 |
|------|------|---------|---------|
|
| 433 |
+
| YOLO 人脸检测 | 使用 `AdamCodd/YOLOv11n-face-detection` 模型 | `head_tracker.py` | ✅ 已实现 |
|
| 434 |
+
| 15Hz 人脸追踪 | 摄像头帧处理 + 人脸检测 | `camera_server.py` | ✅ 已实现 |
|
| 435 |
+
| look_at_image() | 根据人脸位置计算目标姿态 | `camera_server.py` | ✅ 已实现 |
|
| 436 |
+
| 平滑回中性位置 | 人脸丢失后 1 秒内平滑回归 | `camera_server.py` | ✅ 已实现 |
|
| 437 |
+
| face_tracking_offsets | 作为 secondary pose 叠加到运动控制 | `movement_manager.py` | ✅ 已实现 |
|
| 438 |
+
| 语音活动检测 | DOA 实体仍可用于检测语音 | `DoAInfo.speech_detected` | ✅ 已暴露为实体 |
|
| 439 |
+
|
| 440 |
+
**代码位置**:
|
| 441 |
+
- `head_tracker.py` - YOLO 人脸检测器 (`HeadTracker` 类)
|
| 442 |
+
- `camera_server.py:_face_tracking_loop()` - 15Hz 人脸追踪循环
|
| 443 |
+
- `movement_manager.py:set_face_tracking_offsets()` - 人脸追踪偏移量 API
|
| 444 |
+
|
| 445 |
+
**技术细节**:
|
| 446 |
+
```python
|
| 447 |
+
# head_tracker.py - YOLO 人脸检测
|
| 448 |
+
class HeadTracker:
|
| 449 |
+
def __init__(self):
|
| 450 |
+
self.model = YOLO("AdamCodd/YOLOv11n-face-detection")
|
| 451 |
+
|
| 452 |
+
def detect_faces(self, frame) -> list[FaceDetection]:
|
| 453 |
+
# 返回检测到的人脸列表,包含 bbox 和置信度
|
| 454 |
+
|
| 455 |
+
# camera_server.py - 人脸追踪循环
|
| 456 |
+
async def _face_tracking_loop(self):
|
| 457 |
+
while self._running:
|
| 458 |
+
frame = self._reachy_controller.get_camera_frame()
|
| 459 |
+
faces = self._head_tracker.detect_faces(frame)
|
| 460 |
+
if faces:
|
| 461 |
+
# 选择最大/最近的人脸
|
| 462 |
+
target_u, target_v = faces[0].center
|
| 463 |
+
pose = self._reachy_controller.look_at_image(target_u, target_v)
|
| 464 |
+
self._motion.set_face_tracking_offsets(pose)
|
| 465 |
+
else:
|
| 466 |
+
# 平滑回归中性位置
|
| 467 |
+
self._motion.clear_face_tracking_offsets()
|
| 468 |
+
await asyncio.sleep(1/15) # 15Hz
|
| 469 |
+
```
|
| 470 |
|
| 471 |
### Phase 15 - 卡通风格运动模式 (部分实现) 🟡
|
| 472 |
|