Files
Docs/DevLogs/Day26.md
2026-01-05 09:14:42 +08:00

174 lines
7.4 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 26 开发日志
**日期**2026-01-04
**主题**:室内导盲模型服务器集成
---
## 🔧 室内导盲服务器集成
### 1. 状态机扩展 (NavigationMaster)
`NavigationMaster` 中添加了 `INDOOR_NAV` 状态,支持复用 `BlindPathNavigator` 进行室内导航。
```python
# 新增状态常量
INDOOR_NAV = "INDOOR_NAV"
# 室内导航处理逻辑
if self.state == INDOOR_NAV:
# 优先使用室内导航器fallback 到盲道导航器
nav = self.indoor if self.indoor else self.blind
bres = nav.process_frame(bgr)
```
### 2. 模型加载与初始化
`app_main.py` 中实现了 `load_indoor_model()` 函数,支持加载 TensorRT 优化的室内分割模型 `yolo11l-seg-indoor14.engine`
在系统启动时,如果检测到室内模型,会自动初始化 `indoor_navigator` 并注入到 `NavigationMaster`
### 3. 语音命令支持
扩展了 `start_ai_with_text_custom``asr_core.py` 白名单,支持以下命令:
- **"室内导航" / "室内导盲"**: 启动室内导航模式
- **"停止导航" / "结束导航"**: 停止当前导航(适用于所有模式)
### 4. 互斥逻辑
实现了室内导航与室外盲道导航、红绿灯检测的互斥逻辑。无论当前处于何种导航模式,新的导航命令都会正确切换状态或停止当前任务。
---
## ✅ 验证结果
- **模型加载**: 系统启动时成功加载 `yolo11l-seg-indoor14.engine` (TensorRT FP16)
- **语音控制**: 语音命令正确触发 `start_indoor_navigation()`
- **状态切换**: UI 正确显示 `[系统] 室内导航已启动`
### 5. 动态语音合成 (EdgeTTS Fallback)
**功能**:室内导航检测到未预录的物体(如"前方有吸尘器")时,系统不再静默。
**实现**
- 修改 `audio_player.play_voice_text`,当本地语音包缺失时,自动调用 `EdgeTTS`
- 采用 `asyncio.create_task` 异步合成,不阻塞导航主线程。
- 增加了运行时内存缓存,相同语句只需合成一次。
---
## 🔧 客户端优化 (NaviGlassClient)
### 1. 内存碎片修复 (camera.cpp)
**问题**原代码每帧画面30fps都执行 `new/delete`在嵌入式设备V821上导致严重的内存碎片。
**修复**
- 实现了**静态双缓冲池** (`m_frame_buffers[2]`)。
- 启动时分配两次,运行期间零 `malloc`
**结果**:✅ 彻底消除了运行时堆内存分配,防止 OOM。
### 2. 依赖移除 (ws_client.cpp)
**问题**:仅为了 WebSocket 握手时的 Base64 编码而引入了完整的 OpenSSL 库,增加了二进制体积和编译复杂度。
**修复**
- 移除了所有 OpenSSL 头文件和链接库 (`-lssl -lcrypto`)。
- 内置了一个轻量级的 Base64 编码器。
**结果**:✅ 减少了二进制体积,简化了交叉编译流程。
---
## 🔧 服务器重构与优化 (NaviGlassServer)
### 1. 全局状态重构 (ServerContext)
**问题**`app_main.py` 包含 30+ 个分散的全局变量,导致状态管理混乱且容易产生竞态条件。
**解决方案**
- 创建 `ServerContext` 单例 (`ctx`) 统一管理所有状态WebSocket 连接、导航标志、模型实例)。
- 提供了 `ctx.reset_navigation_state()` 以安全地重置所有业务状态。
### 2. 结构化日志
**问题**:大量使用 `print()` 导致日志难以追踪且无法轮转。
**修复**
- 引入 `logging` 模块,配置了 `TimedRotatingFileHandler`(每日轮转)。
- 关键错误使用 `logger.error(..., exc_info=True)` 记录堆栈信息。
### 3. 动态导入与容错
**修复**
-`trafficlight_detection``hand_landmarker` 等可选/重型模块移至顶层,并包裹在 `try-except` 中。
- 业务逻辑中增加了 `if module:` 检查,确保模块加载失败时系统不崩溃。
### 4. 鲁棒性增强 (Retry Logic)
**修复**
- **EdgeTTS**: `text_to_speech` 函数增加了指数退避重试,防止网络抖动导致语音缺失。
- **GLM Client**: `chat_stream` 增加了对 API 429 (Rate Limit) 的自动重试。
---
---
## 🐛 Bug Fixes & Optimization
### 1. 语音命令与模式互斥修复
**问题**: "停止室内导航" 命令被错误识别为启动命令;室内模式下仍触发室外斑马线检测。
**修复**:
- **命令优先级**: 在 `app_main.py` 中,将停止命令的判断移至启动命令之前。
- **检测互斥**: 在 `workflow_blindpath.py` 中引入 `enable_crosswalk_detection` 标志。室内模式初始化时禁用斑马线检测。
### 2. 服务器启动日志净化
**目标**: 消除启动时的冗余警告和刷屏日志,提供干净的专业级控制台输出。
**优化内容**:
- **音频压缩日志**: 屏蔽了 `audio_compressor.py` 中 100+ 行的详细压缩比率日志 (`[INFO] [压缩] ...`)。
- **HandLandmarker**: 注释了旧 AI 管道未使用的 `hand_landmarker` 导入,消除 ImportError 警告。
- **TensorRT 警告**: 修复了 `model.to(device)` 错误调用导致的警告TRT 引擎不需要移至 GPU
- **YOLO Task**: 显式指定 `YOLO(..., task='detect')`,消除任务自动猜测警告。
- **结果**: 启动日志行数减少 80%,关键信息一目了然。
### 3. EdgeTTS 磁盘缓存 (代码审查优化)
**问题**: EdgeTTS 动态合成的语音只在运行时缓存,重启后需重新合成。
**修复**:
-`audio_player.py` 中添加磁盘缓存目录 `voice/tts_cache/`
- 使用 MD5 哈希作为文件名,首次合成后自动保存
- 重启后优先从磁盘加载,减少网络延迟
### 4. 可配置日志采样间隔
**目标**: 调试时可临时增加日志输出,生产环境减少刷屏。
**实现**:
- 新增环境变量 `AIGLASS_LOG_INTERVAL`(默认 30 帧)
-`workflow_blindpath.py` 中替换硬编码的 `% 30`
### 5. API Key 管理规范化
- `GLM_API_KEY``glm_client.py` 硬编码移至 `.env`
- `DASHSCOPE_API_KEY` 标记为可选(旧管道)
### 6. 项目文件清理
**清理内容**:
- `mobileclip_blt.ts` (571MB) - 无引用残留模型
- `recordings/` (~600MB) - 测试录音文件
- `test/` (~580MB) - 测试视频文件
- `compile/` - ESP32 残留代码
- `.env.performance` - 重复配置
**释放空间**: ~1.75GB
### 7. 启动日志优化
- **pygame 欢迎信息**: 设置 `PYGAME_HIDE_SUPPORT_PROMPT=1` 抑制
- **CROSS_STREET .to() 警告**: 改用 `is_tensorrt_engine()` 静默处理
### 8. 室内导航工作流 (IndoorNavigator)
**问题**: 室内模式使用 `BlindPathNavigator`,但类别 ID 不匹配(期望 `blind_path` ID=1实际是 `corridor`)。
**解决方案**: 创建专用 `workflow_indoor.py`
```python
# 室内类别映射 (14 classes from MIT Indoor)
WALKABLE_CLASSES = {0, 1, 2} # floor, corridor, sidewalk
OBSTACLE_CLASSES = {3, 4, 5, 11, 12} # chair, table, sofa_bed, cabinet, trash_can
POI_CLASSES = {6, 7, 8} # door, elevator, stairs
```
**实现内容**:
- `IndoorNavigator` 类 (~400行)
- 可行走区域检测: 合并 floor + corridor + sidewalk
- 障碍物避障: 前方区域 chair/table/person 检测
- 兴趣点提示: door/elevator/stairs 语音播报
- 方向引导: 基于可行走区域左中右分布计算
**修改文件**:
- `app_main.py`: 室内导航器改用 `IndoorNavigator`
- `navigation_master.py`: 兼容 `IndoorResult` 类型
## 📋 下一步
- [ ] 室内导航实际测试
- [ ] 根据用户反馈微调语音引导策略