186 lines
5.1 KiB
Markdown
186 lines
5.1 KiB
Markdown
# Day 17 - 室外测试与盲道导航语音修复
|
||
|
||
**日期**: 2025-12-17
|
||
**主题**: 室外实地测试、盲道导航语音播报问题修复、IMU 采样率优化
|
||
|
||
---
|
||
|
||
## 室外实地测试
|
||
|
||
### 测试环境
|
||
- **网络连接**: 开发板通过 iPhone 手机热点连接公网服务器
|
||
- **服务器地址**: `8.148.25.142:8081`(通过 frp 内网穿透)
|
||
|
||
### 测试结果
|
||
|
||
| 功能 | 状态 | 说明 |
|
||
|------|------|------|
|
||
| 摄像头采集 | ✅ 正常 | 视频流传输稳定 |
|
||
| 过马路导航语音 | ✅ 正常 | 语音播报正常工作 |
|
||
| 盲道导航语音 | ❌ 异常 | **无语音播报** |
|
||
| IMU 数据上传 | ❌ 异常 | 公网环境下无法接收 |
|
||
| 扬声器杂音 | ⚠️ 存在 | IMU 工作和手靠近电线时有杂音 |
|
||
|
||
---
|
||
|
||
## 问题 1:IMU 数据无法通过公网上传
|
||
|
||
### 现象
|
||
- 将服务器地址从本地 IP 改为公网 IP `8.148.25.142` 后
|
||
- IMU 数据无法被服务器接收
|
||
|
||
### 根因分析
|
||
`frpc.toml` 只配置了 **TCP 8081**(WebSocket),未配置 **UDP 12345**(IMU):
|
||
|
||
```toml
|
||
# 原配置只有 TCP
|
||
[[proxies]]
|
||
name = "avaota_server"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 8081
|
||
remotePort = 8081
|
||
```
|
||
|
||
### 解决方案
|
||
|
||
**1. 修改 `frpc.toml`,增加 UDP 代理**:
|
||
```toml
|
||
[[proxies]]
|
||
name = "avaota_imu_udp"
|
||
type = "udp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 12345
|
||
remotePort = 12345
|
||
```
|
||
|
||
**2. 公网服务器防火墙开放 UDP 12345**:
|
||
- 阿里云/腾讯云安全组添加入站规则
|
||
- 或使用 `iptables -A INPUT -p udp --dport 12345 -j ACCEPT`
|
||
|
||
**3. 重启 frpc 服务**使配置生效
|
||
|
||
---
|
||
|
||
## 问题 2:盲道导航无语音播报
|
||
|
||
### 现象
|
||
- 过马路导航正常有语音播报
|
||
- 盲道导航没有语音播报
|
||
|
||
### 根因分析
|
||
|
||
#### 调用链差异
|
||
|
||
**过马路模块** (`workflow_crossstreet.py`):
|
||
```
|
||
process_frame() 返回 guidance_text
|
||
↓
|
||
navigation_master._say() 节流
|
||
↓
|
||
app_main.py play_voice_text() ← 在主事件循环中执行 ✅
|
||
```
|
||
|
||
**盲道模块** (`workflow_blindpath.py`):
|
||
```
|
||
process_frame() 内部直接调用 play_voice_text() ← 在线程池中执行 ❌
|
||
↓
|
||
play_voice_text() 调用 async broadcast_pcm16_realtime()
|
||
↓
|
||
在线程池中无法运行 asyncio 协程 → 失败
|
||
```
|
||
|
||
#### 核心问题
|
||
盲道模块在 `process_frame()` 内部直接调用 `play_voice_text()`,但该函数是在 `frame_processing_executor` 线程池中执行的,无法正确运行 asyncio 协程。
|
||
|
||
### 修复方案
|
||
|
||
修改 `workflow_blindpath.py`,与过马路模块保持一致:
|
||
|
||
1. **移除内部播放**(第 17 行):
|
||
```python
|
||
# 【移除】从这里播放音频会导致线程池中asyncio无法工作
|
||
# from audio_player import play_voice_text
|
||
# 语音由 app_main.py 统一处理
|
||
```
|
||
|
||
2. **移除 play_voice_text 调用**(第 759-765 行):
|
||
```python
|
||
# 【移除】play_voice_text() - 由app_main统一处理
|
||
logger.info(f"[语音待播] 优先级{selected_voice['priority']}: {final_guidance_text}")
|
||
```
|
||
|
||
3. **返回正确的文本**(第 793 行):
|
||
```python
|
||
# 【修改】返回 final_guidance_text(经过节流的),由 app_main 统一播放
|
||
return ProcessingResult(
|
||
guidance_text=final_guidance_text, # 改为返回节流后的文本
|
||
...
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## 问题 3:扬声器有杂音
|
||
|
||
### 现象
|
||
- IMU 工作时扬声器有杂音
|
||
- 手靠近电线时扬声器也有杂音
|
||
|
||
### 分析
|
||
|
||
#### IMU 干扰源
|
||
- GPIO 模拟 SPI 通信(500kHz)
|
||
- 每秒约 5600 次 GPIO 翻转(50Hz × 14字节 × 8位)
|
||
- 可能产生电磁干扰
|
||
|
||
#### 优化措施
|
||
降低 IMU 采样率从 50Hz 到 10Hz:
|
||
|
||
```cpp
|
||
// main.cpp 第 311 行
|
||
usleep(100000); // 10 Hz (100ms) - 降低采样率减少对音频的干扰
|
||
```
|
||
|
||
#### 硬件层面原因
|
||
- 人体静电感应
|
||
- 信号线屏蔽不足
|
||
- 接地不良
|
||
|
||
### 结论
|
||
- 软件优化可减少干扰但无法完全消除
|
||
- 彻底解决需要硬件层面改进(加磁环、重新布线等)
|
||
- 当前暂时保持现状
|
||
|
||
---
|
||
|
||
## 语音播报系统统一状态
|
||
|
||
| 模块 | 状态 | 说明 |
|
||
|------|------|------|
|
||
| `workflow_blindpath.py` | ✅ 已修复 | 移除内部播放,由 app_main 统一处理 |
|
||
| `workflow_crossstreet.py` | ✅ 正常 | 早已移除内部播放 |
|
||
| `navigation_master.py` | ✅ 正常 | 只做节流,不播放语音 |
|
||
| `trafficlight_detection.py` | ✅ 正常 | 导入但未调用 |
|
||
| `app_main.py` | ✅ 正常 | 统一语音播放入口 |
|
||
|
||
---
|
||
|
||
## 修改文件列表
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|----------|
|
||
| `frpc.toml` | 新增 UDP 12345 代理配置(IMU 数据转发) |
|
||
| `OpenAIglasses_for_Navigation/workflow_blindpath.py` | 移除内部语音播放,改为返回文本给 app_main |
|
||
| `AvaotaF1/avaota_app_demo/src/main.cpp` | IMU 采样率从 50Hz 降低到 10Hz |
|
||
|
||
---
|
||
|
||
## 待解决问题
|
||
|
||
- [x] IMU 数据公网传输(已通过 frpc UDP 代理解决)
|
||
- [x] 盲道导航语音播报(已修复代码)
|
||
- [ ] 扬声器杂音(需硬件层面解决)
|
||
- [ ] 验证盲道导航语音播报是否正常工作(需重新室外测试)
|
||
|