# 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` 预存户外热点信息。 - [ ] 验证断电重启后的自动重连能力。