Files
Docs/DevLogs/Day15.md
2025-12-31 16:18:28 +08:00

108 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Day 15: 性能优化 - 解决导航模式帧率问题
## 问题描述
导航模式下 FPS 从 10.0 降到 0.5-1.5,画面严重卡顿。
---
## 已完成优化
### 1. YOLO 帧间隔修复 ✅
`yolo_process_interval` 从 1 帧改为 5 帧。
### 2. 性能诊断日志 ✅
添加了 `[NAVIGATION DEBUG]` 日志用于监控状态。
### 3. 线程池化帧处理 ✅
使用 `ThreadPoolExecutor` 将 CPU 密集型处理移至后台线程。
### 4. 修复模型重复加载 BUG ✅
**根因**`audio_stream.py` 中的 `import app_main` 触发模块顶层代码再次执行。
**修复**:改为 `sys.modules['app_main']` 获取已加载的模块。
### 5. 跳帧机制 ✅
**根因**:虽然用了 `run_in_executor`,但 `await` 仍同步等待处理完成。
**修复**:实现非阻塞式帧处理:
- 后台任务处理帧,主循环不等待
- 使用最后一次成功的结果广播
- 新帧覆盖待处理队列(跳过中间帧)
### 6. 导航语音频率优化 ✅
**问题**FPS 恢复后导航指令触发过于频繁每1秒一次造成干扰。
**修复**:将 `audio_player.py` 中的 `_voice_cooldown` 从 1.0秒 调整为 3.0秒。
---
## 代码修改
### `audio_stream.py`
- `get_tts_websocket()`: 改用 `sys.modules` 避免触发模块重载
### `app_main.py`
- 添加跳帧机制全局变量:`_nav_processing_task`, `_nav_last_result_image`, `_nav_pending_frame`
- 修改 `ws_camera_esp` 中的帧处理为非阻塞式
### `audio_player.py`
- 调整 `_voice_cooldown` = 3.0 (原 1.0)
---
## 预期效果
| 场景 | 修改前 | 修改后 |
|------|--------|--------|
| CHAT 模式 | 10 FPS | 10 FPS |
| 导航模式 | 0.5-1.5 FPS | 8-10 FPS |
| Omni 对话 | 0.5 FPS | 8-10 FPS |
|
**真正的根因**
1. **同步帧处理阻塞事件循环** - `orchestrator.process_frame()` 在主 async 循环中同步执行
2. **Omni 对话阻塞** - TTS 音频流发送与帧处理串行竞争时间片
3. **双重 JPEG 编解码** - 每帧都解码+重编码
### 4. 线程池化帧处理 ✅
**方案**:将 CPU 密集型的帧处理移至 `ThreadPoolExecutor` 后台线程执行。
**修改**
- 添加 `concurrent.futures.ThreadPoolExecutor` 导入
- 创建全局 `frame_processing_executor`2 个 worker 线程)
- 使用 `await loop.run_in_executor()` 执行 `orchestrator.process_frame()`
- 使用 `await loop.run_in_executor()` 执行 `trafficlight_detection.process_single_frame()`
- 在 lifespan 关闭时调用 `executor.shutdown(wait=False)`
---
## 📝 代码变更汇总
| 文件 | 变更 |
|------|------|
| `workflow_blindpath.py` | YOLO 帧间隔检查 + 性能诊断计时 |
| `app_main.py` | 添加线程池 + `run_in_executor` 异步帧处理 |
| `audio_player.py` | 增加语音冷却时间至 3秒 |
---
## ⏭️ 下一步 (Day 16 计划)
### 1. 户外测试全流程配置
- [ ] **公网连接支持**:修改代码支持命令行指定 IP (避免硬编码) 或配置公网服务器地址。
- [ ] **开机自启动**:配置 `/etc/rc.local` 实现通电即运行。
- [ ] **程序固化**:将 `avaota_client` 部署到 `/usr/bin` 等非易失存储。
### 3. 程序部署与自启动 (已验证)
- [x] **解决存储空间不足问题**`/overlay` 空间不足 (316KB),改用 `/mnt/UDISK` (17MB)。
- [x] **部署命令**`adb push avaota_client /mnt/UDISK/`
- [x] **自启动配置**`/etc/rc.local` 添加启动脚本
```bash
sleep 15
/mnt/UDISK/avaota_client &
```
- [x] **连通性验证**:通过串口日志确认 WiFi 连接成功,程序成功收发数据。
### 2. 网络自动连接
- [ ] 配置 `wpa_supplicant.conf` 预存户外热点信息。
- [ ] 验证断电重启后的自动重连能力。