Add voicellmcloud (cloud service) under voicellmcloud/
Made-with: Cursor
This commit is contained in:
parent
0f0ad1b968
commit
1650f046b6
46
voicellmcloud/.env.example
Normal file
46
voicellmcloud/.env.example
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# 云端无人机语音服务 - 环境配置示例
|
||||||
|
# 复制为 .env 并修改相应配置
|
||||||
|
|
||||||
|
# ==================== WebSocket 服务器 ====================
|
||||||
|
WS_HOST=0.0.0.0
|
||||||
|
WS_PORT=8765
|
||||||
|
|
||||||
|
# ==================== 鉴权 ====================
|
||||||
|
BEARER_TOKEN=drone-voice-cloud-token-2024
|
||||||
|
|
||||||
|
# ==================== 阿里云百炼 LLM ====================
|
||||||
|
DASHSCOPE_API_KEY=sk-8ac47bb8a1f7497a922c52d905dd11dc
|
||||||
|
# Fun-ASR 实时识别与 LLM 共用此 Key;北京域默认 WebSocket 如下(新加坡国际域见阿里云文档)
|
||||||
|
DASHSCOPE_WEBSOCKET_URL=wss://dashscope.aliyuncs.com/api-ws/v1/inference
|
||||||
|
DASHSCOPE_ASR_MODEL=fun-asr-realtime
|
||||||
|
ASR_AUDIO_SAMPLE_RATE=16000
|
||||||
|
ASR_SEMANTIC_PUNCTUATION_ENABLED=true
|
||||||
|
LLM_MODEL=qwen-plus
|
||||||
|
LLM_MAX_TOKENS=512
|
||||||
|
LLM_TEMPERATURE=0.3
|
||||||
|
LLM_TIMEOUT=30
|
||||||
|
LLM_CONTEXT_TURNS=4
|
||||||
|
|
||||||
|
# ==================== TTS 配置 ====================
|
||||||
|
TTS_PROVIDER=piper
|
||||||
|
TTS_MODEL_DIR=models
|
||||||
|
TTS_VOICE_NAME=zh_CN-huayan-medium
|
||||||
|
TTS_SAMPLE_RATE=24000
|
||||||
|
TTS_MAX_CHARS=800
|
||||||
|
# 闲聊首段 TTS:更快弱切(逗号等)与更短 soft_flush;可用环境变量覆盖代码默认
|
||||||
|
# TTS_STREAM_SOFT_FLUSH_LEN=28
|
||||||
|
# TTS_STREAM_EARLY_WEAK_CUT=true
|
||||||
|
# Kokoro:首 PCM 包时长(秒,默认 0.05);调试用整段 WAV 默认关,需则设 ROCKET_KOKORO_DEBUG_WAV=1
|
||||||
|
# ROCKET_KOKORO_FIRST_CHUNK_MS=0.05
|
||||||
|
|
||||||
|
# ==================== 飞控二次确认(仅 dialog v1 客户端声明 protocol 时生效)====================
|
||||||
|
FLIGHT_CONFIRM_REQUIRED=true
|
||||||
|
FLIGHT_CONFIRM_TIMEOUT_SEC=10
|
||||||
|
|
||||||
|
# ==================== 限流 ====================
|
||||||
|
MAX_CONCURRENT_SESSIONS=4
|
||||||
|
|
||||||
|
# ==================== 日志 ====================
|
||||||
|
LOG_LEVEL=INFO
|
||||||
|
LOG_TO_FILE=false
|
||||||
|
LOG_FILE=logs/server.log
|
||||||
52
voicellmcloud/.gitignore
vendored
Normal file
52
voicellmcloud/.gitignore
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
*.egg
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# 虚拟环境
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# 环境配置(敏感信息)
|
||||||
|
.env
|
||||||
|
|
||||||
|
# 调试文件
|
||||||
|
debug_*.wav
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# 模型文件(体积大,单独管理)
|
||||||
|
models/*.onnx
|
||||||
|
models/*.bin
|
||||||
|
models/*.ckpt
|
||||||
|
models/*.pth
|
||||||
|
models/*.gguf
|
||||||
|
models/*.data
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# 操作系统
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# 测试
|
||||||
|
.pytest_cache/
|
||||||
|
.coverage
|
||||||
|
htmlcov/
|
||||||
|
|
||||||
|
# 临时文件
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.pyc
|
||||||
94
voicellmcloud/Client/voice_drone_assistant/README.md
Normal file
94
voicellmcloud/Client/voice_drone_assistant/README.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# voice_drone_assistant
|
||||||
|
|
||||||
|
从原仓库抽离的**独立可运行**子工程:麦克风采集 → VAD 切段 → **SenseVoice STT** → **唤醒词** →(关键词起飞 / **Qwen + Kokoro 对话播报**)。
|
||||||
|
|
||||||
|
**部署与外场启动(推荐先读):[docs/DEPLOYMENT_AND_OPERATIONS.md](docs/DEPLOYMENT_AND_OPERATIONS.md)**
|
||||||
|
**日常配置索引:[docs/PROJECT_GUIDE.md](docs/PROJECT_GUIDE.md)** · 云端协议:[docs/llmcon.md](docs/llmcon.md)
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `main.py` | 启动入口 |
|
||||||
|
| `with_system_alsa.sh` | Conda 下建议包一层启动,修正 ALSA/PortAudio |
|
||||||
|
| `voice_drone/core/` | 音频、VAD、STT、TTS、预处理、唤醒、配置、识别器主流程 |
|
||||||
|
| `voice_drone/main_app.py` | 唤醒流程 + LLM 流式 + 起飞脚本联动(原 `rocket_drone_audio.py`) |
|
||||||
|
| `voice_drone/config/` | `system.yaml`、`wake_word.yaml`、`keywords.yaml`、`command_.yaml` |
|
||||||
|
| `voice_drone/logging_/` | 彩色日志 |
|
||||||
|
| `voice_drone/tools/` | YAML 加载等 |
|
||||||
|
| `scripts/` | PX4 offboard、`generate_wake_greeting_wav.py` |
|
||||||
|
| `assets/tts_cache/` | 唤醒问候 WAV 缓存 |
|
||||||
|
| `models/` | **需自备或软链**,见 `models/README.txt` |
|
||||||
|
|
||||||
|
## 环境准备
|
||||||
|
|
||||||
|
1. Python 3.10+(与原项目一致即可),安装依赖:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 模型:将 STT / TTS /(可选)Silero VAD 放到 `models/`,或按 `models/README.txt` 从原仓库 `src/models` 创建符号链接。
|
||||||
|
|
||||||
|
3. 大模型:默认查找 `cache/qwen25-1.5b-gguf/qwen2.5-1.5b-instruct-q4_k_m.gguf`,或通过环境变量 `ROCKET_LLM_GGUF` 指定 GGUF 路径。
|
||||||
|
|
||||||
|
## 运行
|
||||||
|
|
||||||
|
在 **`voice_drone_assistant` 根目录** 执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash with_system_alsa.sh python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
常用参数与环境变量与原 `rocket_drone_audio.py` 相同(如 `ROCKET_LLM_STREAM`、`ROCKET_INPUT_DEVICE_INDEX`、`--input-index`、`ROCKET_ENERGY_VAD` 等),说明见 `voice_drone/main_app.py` 文件头注释。
|
||||||
|
|
||||||
|
也可直接跑模块:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash with_system_alsa.sh python -m voice_drone.main_app
|
||||||
|
```
|
||||||
|
|
||||||
|
## 为什么不默认带上原仓库的 models?
|
||||||
|
|
||||||
|
- **ONNX / GGUF 体积大**(动辄数百 MB~数 GB),放进 Git 或重复拷贝会加重仓库和同步成本。
|
||||||
|
- 抽离时只保证 **代码与配置自给**;权重文件用 **本机拷贝 / U 盘 / 另一台预先 `bundle`** 更灵活。
|
||||||
|
|
||||||
|
若你本机仍摆着原仓库 `rocket_drone_audio`,且 `voice_drone_assistant` 在其子目录下,代码里有个**临时便利**:`models/...` 找不到时会尝试 **上一级 `src/models/...`**,所以在开发机上可以不改目录也能跑。
|
||||||
|
**这只在「子目录 + 上层仍有原仓库」时有效**,把 `voice_drone_assistant` **单独拷到另一台香橙派后,上层没有原仓库,必须在本目录自备 `models/`(和可选 `cache/`)**。
|
||||||
|
|
||||||
|
## 拷到另一台香橙派要做什么?
|
||||||
|
|
||||||
|
1. **整目录复制**(建议先在本机执行下面脚本打全模型,再打包 `voice_drone_assistant`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/voice_drone_assistant
|
||||||
|
bash scripts/bundle_for_device.sh /path/to/rocket_drone_audio
|
||||||
|
```
|
||||||
|
|
||||||
|
会把 `SenseVoiceSmall`、`Kokoro-82M-v1.1-zh-ONNX`(及存在的 `SileroVad`)复制到本目录 `models/`;可按提示选择是否复制 Qwen GGUF。
|
||||||
|
|
||||||
|
2. **新机器上 Python 依赖**:另一台是**全新系统**时,需要再装一次(或整体迁移同一个 conda/env):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd voice_drone_assistant
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
二进制/系统库层面若仍用 conda + PortAudio,建议继续 **`bash with_system_alsa.sh python main.py`**。
|
||||||
|
|
||||||
|
3. **大模型路径**:若未打包 `cache/`,在新机器设环境变量或放入默认路径,例如:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ROCKET_LLM_GGUF=/path/to/qwen2.5-1.5b-instruct-q4_k_m.gguf
|
||||||
|
```
|
||||||
|
|
||||||
|
综上:**工程可独立**,但必须带上 **`models/` + 已装依赖 +(可选)GGUF**;**`pip install` 每台新环境通常要做一次**,除非你把整个 conda env 目录一起迁移。
|
||||||
|
|
||||||
|
## 与原仓库关系
|
||||||
|
|
||||||
|
- 本目录为**代码与配置的复制 + 包名调整**(`src.*` → `voice_drone.*`),默认不把大体积 `models/`、`cache/` 放进版本库。
|
||||||
|
- 原仓库 `rocket_drone_audio` 仍可继续使用;开发阶段两者可并存,部署到单机时只带走 `voice_drone_assistant`(+ `bundle` 后的模型)即可。
|
||||||
|
|
||||||
|
## 未纳入本工程的模块
|
||||||
|
|
||||||
|
PX4 电机演示、独立录音脚本、Socket 试飞控协议服务端、ChatTTS 转换脚本等均留在原仓库,以减小篇幅;本工程仍通过 `SocketClient` 预留配置项(`TakeoffPrintRecognizer` 使用 `auto_connect_socket=False`,不依赖外置试飞控 Socket)。
|
||||||
Binary file not shown.
@ -0,0 +1,179 @@
|
|||||||
|
# 云端语音 · `dialog_result` 与飞控二次确认(v1)
|
||||||
|
|
||||||
|
供 **云端服务** 与 **机端 voice_drone_assistant** 同步实现。**尚无线上存量**:本文即 **`dialog_result` 的飞机位约定**,服务端可按 v1 直接改结构,无需迁就旧字段。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 目标
|
||||||
|
|
||||||
|
1. **`routing=chitchat`**:只走闲聊与对应 TTS,**不**下发可执行飞控负载。
|
||||||
|
2. **`routing=flight_intent`**:携 **`flight_intent`(v1)** + **`confirm`**;机端是否立刻执行仅由 **`confirm.required`** 决定,并支持 **确认 / 取消 / 超时** 交互。
|
||||||
|
3. **ASR**:飞控句是否改用云端识别见 **附录 A**;与 `confirm` 独立。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 术语
|
||||||
|
|
||||||
|
| 术语 | 含义 |
|
||||||
|
|------|------|
|
||||||
|
| **首轮** | 用户说一句;本轮 WS 收到 `dialog_result` 为止。 |
|
||||||
|
| **确认窗** | `confirm.required=true` 时,机端播完本轮 PCM 后 **仅收口令** 的时段,时长 **`confirm.timeout_sec`**。 |
|
||||||
|
| **`flight_intent`** | 见 `FLIGHT_INTENT_SCHEMA_v1.md`。 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. `dialog_result` 形状(云端 → 机端)
|
||||||
|
|
||||||
|
### 3.1 公共顶层(每轮必带)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `turn_id` | string | 是 | 与现有一致,关联本 turn。 |
|
||||||
|
| **`protocol`** | string | 是 | 固定 **`cloud_voice_dialog_v1`**,便于机端强校验、排障。 |
|
||||||
|
| `routing` | string | 是 | **`chitchat`** \| **`flight_intent`** |
|
||||||
|
| `user_input` | string | 建议 | 本回合用于生成回复的用户文本(可为云端 STT 结果)。 |
|
||||||
|
|
||||||
|
### 3.2 `routing=chitchat`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `chat_reply` | string | 是 | 闲聊文本(与 TTS 语义一致或由服务端定义)。 |
|
||||||
|
| `flight_intent` | — | **禁止** | 不得出现。 |
|
||||||
|
| `confirm` | — | **禁止** | 不得出现。 |
|
||||||
|
|
||||||
|
### 3.3 `routing=flight_intent`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `flight_intent` | object | 是 | v1:`is_flight_intent`、`version`、`actions`、`summary` 等。 |
|
||||||
|
| **`confirm`** | object | 是 | 见 §3.4;**每轮飞控必带**,机端拒收缺字段报文。 |
|
||||||
|
|
||||||
|
### 3.4 `confirm` 对象(`routing=flight_intent` 时必填)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| **`required`** | bool | 是 | `true`:进入确认窗,**首轮禁止**执行飞控;`false`:首轮允许按机端执行开关立即执行(调试/免确认策略)。 |
|
||||||
|
| **`timeout_sec`** | number | 是 | 确认窗秒数;建议默认 **10**。 |
|
||||||
|
| **`confirm_phrases`** | string[] | 是 | 非空;与口播一致,推荐 **`["确认"]`**。 |
|
||||||
|
| **`cancel_phrases`** | string[] | 是 | 非空;推荐 **`["取消"]`**。 |
|
||||||
|
| **`pending_id`** | string | 是 | 本轮待定意图 ID(建议 UUID);日志、可选第二轮遥测(附录 B)。 |
|
||||||
|
| **`summary_for_user`** | string | 建议 | 与口播语义一致,供日志/本地 TTS 兜底;**最终以本轮 PCM 为准**。 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 播报(理解与提示)
|
||||||
|
|
||||||
|
- **TTS**:仍用 **`tts_audio_chunk` + PCM**;内容示例:复述理解 + **「请回复确认或取消」**;服务端在 `confirm_*_phrases` 中与口播保持一致(推荐 **`确认` / `取消`**)。
|
||||||
|
- 机端 **须** 在 **本轮 PCM 播放结束**(或播放管线给出「可收听下一句」)后再进入确认窗,避免抢话。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 机端短语匹配(确认窗内)
|
||||||
|
|
||||||
|
对用户 **一句** STT 规范化后,与 `confirm_phrases` / `cancel_phrases` 比对(机端实现见 `match_phrase_list`):
|
||||||
|
|
||||||
|
1. **取消优先**:若命中 `cancel_phrases` 任一 → 取消本轮。
|
||||||
|
2. **确认**:否则若命中 `confirm_phrases` 任一 → 执行 **`flight_intent`**。
|
||||||
|
3. **规则要点**:**全等**(去尾标点)算命中;或对 **很短** 的句子(长度 ≤ 短语长+2)允许 **子串** 命中,以便「好的确认」类说法;**整句复述**云端长提示(如「请回复确认或取消」)不会因同时含「确认」「取消」子串而误匹配。
|
||||||
|
4. **未命中**:可静候超时(v1 建议确认窗内 **可多句** 直至超时,由机端实现决定)。
|
||||||
|
4. **超时 / 取消** 固定中文播报见下表(机端本地 TTS,降低时延):
|
||||||
|
|
||||||
|
| 事件 | 文案 |
|
||||||
|
|------|------|
|
||||||
|
| 超时 | `未收到确认指令,请重新下发指令` |
|
||||||
|
| 取消 | `已取消指令,请重新唤醒后下发指令` |
|
||||||
|
| 确认并执行 | `开始执行飞控指令` |
|
||||||
|
|
||||||
|
若产品强制云端音色,见 **附录 C**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 机端执行条件(归纳)
|
||||||
|
|
||||||
|
| 条件 | 行为 |
|
||||||
|
|------|------|
|
||||||
|
| `routing=chitchat` | 不执行飞控。 |
|
||||||
|
| `routing=flight_intent` 且 `confirm.required=false` 且机端已开执行开关 | 首轮校验通过后 **可立即** 执行。 |
|
||||||
|
| `routing=flight_intent` 且 `confirm.required=true` | **仅**在确认窗内命中确认短语后执行;**首轮绝不**执行。 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 机端状态机(摘要)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
stateDiagram-v2
|
||||||
|
[*] --> Idle
|
||||||
|
Idle --> Chitchat: routing=chitchat
|
||||||
|
Idle --> ExecNow: routing=flight_intent 且 confirm.required=false
|
||||||
|
Idle --> ConfirmWin: routing=flight_intent 且 confirm.required=true
|
||||||
|
|
||||||
|
ConfirmWin --> ExecIntent: 命中 confirm_phrases
|
||||||
|
ConfirmWin --> SayCancel: 命中 cancel_phrases
|
||||||
|
ConfirmWin --> SayTimeout: timeout_sec
|
||||||
|
|
||||||
|
ExecNow --> Idle
|
||||||
|
ExecIntent --> Idle
|
||||||
|
SayCancel --> Idle
|
||||||
|
SayTimeout --> Idle
|
||||||
|
Chitchat --> Idle
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 会话握手
|
||||||
|
|
||||||
|
**`session.start`**(或等价)的 `client` **须** 带:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"protocol": {
|
||||||
|
"dialog_result": "cloud_voice_dialog_v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
服务端仅对声明该协议的客户端下发 §3 结构;机端若未声明,服务端可拒绝或返显式错误码(由服务端定义)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 安全说明
|
||||||
|
|
||||||
|
二次确认减轻 **错词误飞**,不替代 **急停、遥控介入、场地规范**。
|
||||||
|
TTS 若为「请回复确认或取消」,服务端请在 `confirm_phrases` / `cancel_phrases` 中下发 **`确认`**、**`取消`**(与口播一致);**听与判均在机端**,云端无需再收一轮确认消息。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录 A:云端 ASR(可选)
|
||||||
|
|
||||||
|
服务端可将飞控相关 utterance 改为 **云端 STT** 结果填入 `user_input`,与 `flight_intent` 解析同源;**执行仍以 `flight_intent` + `confirm` 为准**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录 B:第二轮 `turn`(可选遥测)
|
||||||
|
|
||||||
|
用户确认后机端可再发一轮文本(ASR 原文),payload 可带 `pending_id`、`phase: confirm_ack`;**执行成功与否不依赖**该轮响应。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录 C:超时/取消走云端 TTS(可选)
|
||||||
|
|
||||||
|
若 `confirm.play_server_tts_on_timeout` 为真(服务端与机端扩展字段),则由云端推 PCM;**易增延迟**,v1 默认 **关**,以 §5 本地播报为准。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 文档关系
|
||||||
|
|
||||||
|
| 文档 | 关系 |
|
||||||
|
|------|------|
|
||||||
|
| `FLIGHT_INTENT_SCHEMA_v1.md` | `flight_intent` 体 |
|
||||||
|
| `DEPLOYMENT_AND_OPERATIONS.md` | 部署 |
|
||||||
|
|
||||||
|
**版本**:`cloud_voice_dialog_v1`(本文);后续 breaking 变更递增 `cloud_voice_dialog_v2` 等。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 机端实现状态(voice_drone_assistant)
|
||||||
|
|
||||||
|
- **`CloudVoiceClient`**:`session.start.client` 已带 `protocol.dialog_result: cloud_voice_dialog_v1`;`run_turn` 返回含 `protocol`、`confirm`。
|
||||||
|
- **`main_app.TakeoffPrintRecognizer`**:解析 `confirm`;`required=true` 且已开 `ROCKET_CLOUD_EXECUTE_FLIGHT` 时,播完本轮 PCM 后进入 **`FLIGHT_CONFIRM_LISTEN`**,本地匹配短语 / 超时文案见 **`voice_drone.core.cloud_dialog_v1`**。
|
||||||
|
- **服务端未升级前**:若缺 `protocol` 或 `confirm`,机端 **不执行** 飞控(仍播 TTS)。
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
# PCM ASR 上行协议 v1(机端实现摘要)
|
||||||
|
|
||||||
|
与 `CloudVoiceClient`(`voice_drone/core/cloud_voice_client.py`)及 voicellmcloud 的 `pcm_asr_uplink` **session.start.transport_profile** 对齐。
|
||||||
|
|
||||||
|
## 上行:仅文本 WebSocket 帧
|
||||||
|
|
||||||
|
**禁止**用 WebSocket **binary** 发送用户 PCM。对端(Starlette)`receive_text()` 与 `receive_bytes()` 分流;binary 上发会导致对端异常,客户端可能表现为空文本等异常。
|
||||||
|
|
||||||
|
用户音频只出现在 **`turn.audio.chunk` 的 JSON 字段 `pcm_base64`** 中(标准 Base64,内容为 little-endian **pcm_s16le** 原始字节)。
|
||||||
|
|
||||||
|
## session.start
|
||||||
|
|
||||||
|
- `transport_profile`: **`pcm_asr_uplink`**
|
||||||
|
- 其余与会话通用字段相同(`client`、`auth_token`、`session_id` 等)。
|
||||||
|
|
||||||
|
## 单轮上行(一个 `turn_id`)
|
||||||
|
|
||||||
|
1. **文本 JSON**:`turn.audio.start`
|
||||||
|
- `type`: `"turn.audio.start"`
|
||||||
|
- `proto_version`: `"1.0"`
|
||||||
|
- `transport_profile`: `"pcm_asr_uplink"`
|
||||||
|
- `turn_id`: UUID 字符串
|
||||||
|
- `sample_rate_hz`: 整数(机端一般为 **16000**,与采集一致)
|
||||||
|
- `codec`: `"pcm_s16le"`
|
||||||
|
- `channels`: **1**
|
||||||
|
|
||||||
|
2. **文本 JSON**(可多条):`turn.audio.chunk`
|
||||||
|
- `type`: `"turn.audio.chunk"`
|
||||||
|
- `proto_version`、`transport_profile`、`turn_id` 与 start 一致
|
||||||
|
- `pcm_base64`: 本段 PCM 原始字节的 Base64(不传 WebSocket binary)
|
||||||
|
|
||||||
|
每段原始字节长度由环境变量 **`ROCKET_CLOUD_AUDIO_CHUNK_BYTES`** 控制(默认 8192,对 **解码前** 的 PCM 字节数做钳制)。
|
||||||
|
|
||||||
|
3. **文本 JSON**:`turn.audio.end`
|
||||||
|
- `type`: `"turn.audio.end"`
|
||||||
|
- `proto_version`、`transport_profile`、`turn_id` 与 start 一致。
|
||||||
|
|
||||||
|
**并发**:同一 WebSocket 会话内,**勿**在收到上一轮的 `turn.complete` 之前再发新一轮 `turn.audio.start`。
|
||||||
|
|
||||||
|
## 下行(与 turn.text 同形态)
|
||||||
|
|
||||||
|
- 可选:`asr.partial` — 机端仅日志/UI,**不参与状态机**。
|
||||||
|
- `llm.text_delta`(可选)
|
||||||
|
- `tts_audio_chunk`(JSON)后随 **binary PCM**(TTS 下行仍可为 binary,与上行约定无关)
|
||||||
|
- `dialog_result`
|
||||||
|
- `turn.complete`
|
||||||
|
|
||||||
|
机端对 **空文本帧** 会忽略并继续读(与云端「空文本忽略」一致)。
|
||||||
|
|
||||||
|
机端须 **收齐 `turn.complete` 且按序拼完该轮 TTS 二进制** 后再视为播报结束,再按产品规则分支(闲聊再滴声 / 飞控确认窗等)。
|
||||||
|
|
||||||
|
## 参考
|
||||||
|
|
||||||
|
- 会话产品流:[`CLOUD_VOICE_SESSION_SCHEME_v1.md`](./CLOUD_VOICE_SESSION_SCHEME_v1.md)
|
||||||
|
- 飞控确认:`CLOUD_VOICE_FLIGHT_CONFIRM_v1.md`
|
||||||
@ -0,0 +1,163 @@
|
|||||||
|
# 语音助手会话方案 v1(服务端 + 机端对齐)
|
||||||
|
|
||||||
|
本文档描述 **「唤醒 → 问候 → 滴声开录 → 断句上云 → 提示音 → 云端理解与 TTS → 分支循环/待机」** 的端到端方案,供 **服务端(voicellmcloud)** 与 **机端(本仓库 voice_drone_assistant)** 分工落地。
|
||||||
|
|
||||||
|
**v1 明确不做**:播报中途 **抢话 / 打断 TTS(barge-in)**;播放 TTS 时机端 **关麦或不处理用户语音**。
|
||||||
|
|
||||||
|
**关联协议**:
|
||||||
|
|
||||||
|
- 音频上行与 Fun-ASR:[CLOUD_VOICE_PROTOCOL_pcm_asr_uplink_v1.md](./CLOUD_VOICE_PROTOCOL_pcm_asr_uplink_v1.md)
|
||||||
|
- 未唤醒不上云:由服务端/产品文档 `CLOUD_VOICE_CLIENT_WAKE_GATE_v1` 约定(机端须本地门禁后再建联上云)
|
||||||
|
- 总接口:以 voicellmcloud 仓库 `API_SPECIFICATION` 为准
|
||||||
|
- 飞控确认窗:[CLOUD_VOICE_FLIGHT_CONFIRM_v1.md](./CLOUD_VOICE_FLIGHT_CONFIRM_v1.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 产品流程(用户视角)
|
||||||
|
|
||||||
|
1. 用户说唤醒词(如「无人机」,由机端配置),**仅本地处理,不上云 ASR**。
|
||||||
|
2. 机端播放问候语(如「你好,有什么事儿吗」)— 可用本地 TTS 或 `tts.synthesize`。
|
||||||
|
3. 机端 **滴一声**,表示 **开始收音**;同时启动 **5 秒静默超时** 计时(见 §4)。
|
||||||
|
4. 用户说话;机端 **VAD/端点检测** 得到 **一整句** 后:
|
||||||
|
- 播放 **极短断句提示音**(表示「已截句、将上云」);
|
||||||
|
- **提示音播放期间闭麦或做回声隔离**,提示音结束后 **短消抖**(建议 **150~300 ms**)再恢复采集逻辑,避免把提示音当成用户语音。
|
||||||
|
5. 将该句 **PCM** 以 `turn.audio.*` 发云端;云端 **Fun-ASR → LLM → `dialog_result` → TTS**;机端播完 **全部** `tts_audio_chunk` 及收到 **`turn.complete`** 后,视为本轮播报结束(见 §3 服务端)。
|
||||||
|
6. **分支**:
|
||||||
|
- **`routing === flight_intent`**:进入 **飞控子状态机**(口头确认/取消/超时),**不使用** §4 的「闲聊滴声后 5s」规则覆盖确认窗;超时以 **`dialog_result.confirm.timeout_sec`** 及 [CLOUD_VOICE_FLIGHT_CONFIRM_v1.md](./CLOUD_VOICE_FLIGHT_CONFIRM_v1.md) 为准。
|
||||||
|
- **`routing === chitchat`**:本轮结束后 **再滴一声**,进入下一轮 **步骤 4**(同一 WebSocket 会话内 **新 `turn_id`** 再起一轮 `turn.audio.*`)。
|
||||||
|
7. 若在 **步骤 3 的滴声之后** 连续 **5 s** 内未检测到有效语音(见 §4),机端播 **超时提示音**,**不再收音**,回到 **待机**(仅唤醒)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 机端状态机(规范性)
|
||||||
|
|
||||||
|
| 状态 | 含义 | 开麦 | 上云 ASR | 备注 |
|
||||||
|
|------|------|------|----------|------|
|
||||||
|
| `STANDBY` | 仅监听唤醒 | 按现网 VAD | **禁止** `turn.audio.*` | 本地 STT + 唤醒词 |
|
||||||
|
| `GREETING` | 播问候 | 可关麦或忽略输入 | 否 | 避免问候进识别 |
|
||||||
|
| `PROMPT_LISTEN` | 已滴「开始录」,等用户一句 | 开 | 否 | **5s 超时**在此状态监控 |
|
||||||
|
| `SEGMENT_END` | 已断句,播短提示音 | **闭麦/屏蔽** | 否 | 消抖后再转 `UPLOADING` |
|
||||||
|
| `UPLOADING` | 发送 `turn.audio.*` | 否 | **是** | 一轮一个 `turn_id` |
|
||||||
|
| `PLAYING_CLOUD_TTS` | 播云端 TTS | **关麦**(v1 无抢话) | 否 | 至 `turn.complete` + PCM 播完 |
|
||||||
|
| `FLIGHT_CONFIRM` | 飞控确认窗 | 按飞控文档 | **可** `turn.text` 或按产品另定 | **独立超时**,不共用 5s |
|
||||||
|
| `CHITCHAT_TAIL` | 闲聊结束,将再滴一声 | — | 否 | 回到 `PROMPT_LISTEN` |
|
||||||
|
|
||||||
|
**并发**:同一时刻仅允许 **一路** `turn.audio.start`~`end`;须等 `turn.complete` 后再开下一轮(与现有 `pipeline_lock` 一致)。
|
||||||
|
|
||||||
|
**唤醒前**:须满足未唤醒不上云的产品/协议约定。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 服务端(voicellmcloud)职责 — v1 **无新消息类型**
|
||||||
|
|
||||||
|
### 3.1 单轮行为(不变)
|
||||||
|
|
||||||
|
对每个完整 `turn.audio.*` 或 `turn.text`:
|
||||||
|
|
||||||
|
1. Fun-ASR(仅 `pcm_asr_uplink` + 音频轮)→ 文本
|
||||||
|
2. LLM 流式 → `dialog_result`(`routing` / `flight_intent` / `chat_reply` 等)
|
||||||
|
3. `tts_audio_chunk*` → `turn.complete`
|
||||||
|
|
||||||
|
服务端 **不** 下发「请再滴一声」「进入待机」类机端 UX 信令;这些由机端根据 **`routing` + `turn.complete`** **固定规则** 驱动。
|
||||||
|
|
||||||
|
### 3.2 机端判定「播报完成」
|
||||||
|
|
||||||
|
须同时满足:
|
||||||
|
|
||||||
|
- 收到该轮 **`turn.complete`**
|
||||||
|
- 已按序播完该轮关联的 **binary PCM**(`tts_audio_chunk` 与现实现一致)
|
||||||
|
|
||||||
|
然后机端再执行 §1 步骤 6 的分支。
|
||||||
|
|
||||||
|
### 3.3 可选下行
|
||||||
|
|
||||||
|
- **`asr.partial`**:机端 **不得** 用于驱动状态跳转;仅可 UI 展示。
|
||||||
|
- **错误**:`error` / `ASR_FAILED` 等 → 机端播简短失败提示后,建议 **回 `STANDBY` 或回到 `PROMPT_LISTEN`**(产品定)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 5 秒静默超时(闲聊路径)
|
||||||
|
|
||||||
|
| 项 | 约定 |
|
||||||
|
|----|------|
|
||||||
|
| **起算点** | 「**开始收音**」的 **滴声播放结束** 时刻(或滴声后固定 **50~100 ms** 偏移,避免与滴声能量重叠)。 |
|
||||||
|
| **「无说话」** | 麦克 **RMS / VAD** 低于阈值,持续累计 ≥ **5 s**(建议可配置,默认 5)。 |
|
||||||
|
| **期间若开始说话** | 清零超时;**断句上云**后本超时在下一轮「滴声」后重新起算。 |
|
||||||
|
| **触发动作** | 播 **超时提示音** → 进入 **`STANDBY`**(不再滴声、不上云)。 |
|
||||||
|
| **不适用** | **`FLIGHT_CONFIRM`** 整段;确认窗用 **服务端给的 `timeout_sec`**。 |
|
||||||
|
|
||||||
|
**机端配置**(`system.yaml` `cloud_voice`):`listen_silence_timeout_sec`、`post_cue_mic_mute_ms`、`segment_cue_duration_ms`;环境变量见 `main_app.py` 头部说明。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 断句后提示音(工程)
|
||||||
|
|
||||||
|
| 项 | 约定 |
|
||||||
|
|----|------|
|
||||||
|
| 目的 | 用户感知「已截句,可等待播报」 |
|
||||||
|
| 实现 | 机端本地短 WAV / 蜂鸣;时长建议 **≤ 200 ms** |
|
||||||
|
| 回声 | **SEGMENT_END** 阶段闭麦或硬件 AEC;结束后 **≥ 150 ms** 再进入 `UPLOADING` |
|
||||||
|
| 与云端 | **无需** 上传该提示音 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 时序简图(闲聊多轮)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant U as 用户
|
||||||
|
participant D as 机端
|
||||||
|
participant S as 服务端
|
||||||
|
|
||||||
|
U->>D: 唤醒词(本地)
|
||||||
|
D->>D: GREETING 播问候
|
||||||
|
D->>D: 滴声 → PROMPT_LISTEN(起 5s 定时)
|
||||||
|
U->>D: 一句语音
|
||||||
|
D->>D: VAD 断句 → 短提示音 → UPLOADING
|
||||||
|
D->>S: turn.audio.start/chunk/end
|
||||||
|
S->>D: asr.partial(可选)
|
||||||
|
S->>D: dialog_result + TTS + turn.complete
|
||||||
|
D->>D: PLAYING_CLOUD_TTS(关麦)
|
||||||
|
alt chitchat
|
||||||
|
D->>D: 再滴声 → PROMPT_LISTEN
|
||||||
|
else flight_intent
|
||||||
|
D->>D: FLIGHT_CONFIRM(独立超时)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 配置建议(机端)
|
||||||
|
|
||||||
|
| 键 | 默认值 | 说明 |
|
||||||
|
|----|--------|------|
|
||||||
|
| `listen_silence_timeout_sec` | `5` | 滴声后起算 |
|
||||||
|
| `post_cue_mic_mute_ms` | `150`~`300` | 断句提示音后再采集 |
|
||||||
|
| `cue_tone_duration_ms` / `segment_cue_duration_ms` | `≤200` | 断句提示 |
|
||||||
|
| `flight_confirm_handling` | 遵循飞控文档 | 禁用闲聊 5s 覆盖 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 机端开发自检
|
||||||
|
|
||||||
|
- [ ] `STANDBY` 下无 `turn.audio.start`。
|
||||||
|
- [ ] `PLAYING_CLOUD_TTS` 与 `SEGMENT_END` 提示音阶段 **不开麦**(v1)。
|
||||||
|
- [ ] 每轮新 `turn_id`;不并行两轮音频上行。
|
||||||
|
- [ ] `flight_intent` 后进入 `FLIGHT_CONFIRM`,**不**误用 5s 闲聊超时。
|
||||||
|
- [ ] `chitchat` 在 TTS 完成后 **再滴** 再 `PROMPT_LISTEN`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 非目标(v1)
|
||||||
|
|
||||||
|
- 播报中抢话、打断 TTS、实时 re-prompt。
|
||||||
|
- 服务端驱动「滴声/待机」(均由机端规则实现)。
|
||||||
|
- 连续免唤醒「直接说指令」跨多轮(若需另开 v2)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 修订记录
|
||||||
|
|
||||||
|
| 版本 | 日期 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| v1 | 2026-04-07 | 首版:小爱类会话 + 双端分工;不含 barge-in |
|
||||||
@ -0,0 +1,288 @@
|
|||||||
|
# 部署与运维手册(项目总结)
|
||||||
|
|
||||||
|
本文面向 **生产/外场部署**:说明 **voice_drone_assistant** 是什么、与 **云端** / **ROS 伴飞桥** / **PX4** 如何衔接,以及 **推荐启动顺序**、**环境变量**与**常见问题**。
|
||||||
|
协议细节见 [`llmcon.md`](llmcon.md),通用配置索引见 [`PROJECT_GUIDE.md`](PROJECT_GUIDE.md),伴飞桥行为见 [`FLIGHT_BRIDGE_ROS1.md`](FLIGHT_BRIDGE_ROS1.md),`flight_intent` 字段见 [`FLIGHT_INTENT_SCHEMA_v1.md`](FLIGHT_INTENT_SCHEMA_v1.md)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 项目总结
|
||||||
|
|
||||||
|
### 1.1 定位
|
||||||
|
|
||||||
|
**voice_drone_assistant** 是板端 **语音无人机助手**:麦克风 → 降噪/VAD → **SenseVoice STT** → **唤醒词** → 用户一句指令 → **云端 WebSocket**(LLM + TTS)或 **本地 Qwen + Kokoro** → 若服务端返回 **`flight_intent`**,可在本机 **校验后执行**(TCP Socket 旧路径,或 **ROS 伴飞桥** 推荐路径)。
|
||||||
|
|
||||||
|
### 1.2 推荐数据流(方案一:云 → 语音程序 → ROS 桥)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph cloud [云端]
|
||||||
|
WS[WebSocket LLM+TTS]
|
||||||
|
end
|
||||||
|
subgraph board [机载 香橙派等]
|
||||||
|
MIC[麦克风]
|
||||||
|
MAIN[main.py TakeoffPrintRecognizer]
|
||||||
|
ROSPUB[子进程 publish JSON]
|
||||||
|
BRIDGE[flight_bridge ros1_node]
|
||||||
|
MAV[MAVROS]
|
||||||
|
end
|
||||||
|
FCU[PX4 飞控]
|
||||||
|
|
||||||
|
MIC --> MAIN
|
||||||
|
MAIN <-->|WSS pcm_asr_uplink + flight_intent| WS
|
||||||
|
MAIN -->|ROCKET_FLIGHT_INTENT_ROS_BRIDGE| ROSPUB
|
||||||
|
ROSPUB -->|std_msgs/String /input| BRIDGE
|
||||||
|
BRIDGE --> MAV --> FCU
|
||||||
|
```
|
||||||
|
|
||||||
|
- **不**把 ROS 直接暴露给公网:云端只连板子的 **WSS/WS**;飞控由 **本机 MAVROS + 伴飞桥** 执行。
|
||||||
|
- **TCP Socket**(`system.yaml` → `socket_server`)是另一条试飞控通道,与云端 **无关**;未起 Socket 服务端时仅会重连日志,不影响 ROS 方案。
|
||||||
|
|
||||||
|
### 1.3 目录与核心入口(仓库根 = `voice_drone_assistant/`)
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `main.py` | 语音助手入口 |
|
||||||
|
| `with_system_alsa.sh` | 建议包装启动,修正 Conda 与系统 ALSA |
|
||||||
|
| `voice_drone/main_app.py` | 唤醒、云端/本地 LLM、TTS、`flight_intent` 执行策略 |
|
||||||
|
| `voice_drone/flight_bridge/ros1_node.py` | ROS1 订阅 `/input`,执行 `flight_intent` |
|
||||||
|
| `voice_drone/flight_bridge/ros1_mavros_executor.py` | MAVROS:offboard / AUTO.LAND / RTL |
|
||||||
|
| `voice_drone/tools/publish_flight_intent_ros_once.py` | 单次向 ROS 发布 JSON(主程序 ROS 桥会子进程调用) |
|
||||||
|
| `scripts/run_flight_bridge_with_mavros.sh` | 一键:roscore(可选)+ MAVROS + 伴飞桥 |
|
||||||
|
| `scripts/run_flight_intent_bridge_ros1.sh` | 仅伴飞桥(须已有 roscore + MAVROS) |
|
||||||
|
| `voice_drone/config/system.yaml` | 音频、STT、TTS、云端、`assistant` 等 |
|
||||||
|
| `requirements.txt` | Python 依赖;**rospy** 来自 `apt` 的 ROS Noetic,见文件内注释 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 环境与依赖
|
||||||
|
|
||||||
|
### 2.1 硬件与系统(典型)
|
||||||
|
|
||||||
|
- ARM64 板卡(如 RK3588)、ES8388 等音频编解码器、USB/内置麦克风。
|
||||||
|
- Ubuntu 20.04 + **ROS Noetic**(伴飞桥 / MAVROS 路径);同机运行语音进程与 `ros1_node`。
|
||||||
|
- 飞控串口(如 `/dev/ttyACM0`)与 MAVROS `fcu_url` 一致。
|
||||||
|
|
||||||
|
### 2.2 Python
|
||||||
|
|
||||||
|
- Python 3.10+(与原仓库一致即可)。
|
||||||
|
- 在 **`voice_drone_assistant`** 根目录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 ROS / MAVROS(伴飞桥方案必选)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install ros-noetic-ros-base ros-noetic-mavros ros-noetic-mavros-extras
|
||||||
|
# 按官方文档执行 mavros 地理库安装(如有)
|
||||||
|
```
|
||||||
|
|
||||||
|
- 语音主程序的 **ROS 桥**子进程会 `source /opt/ros/noetic/setup.bash` 并 **prepend** `PYTHONPATH`,**不要**在未 source ROS 的 shell 里把 `PYTHONPATH` 设成「只有工程根」,否则会找不到 `rospy`(参见 `main_app` 中 `_publish_flight_intent_to_ros_bridge`)。
|
||||||
|
|
||||||
|
### 2.4 模型与权重
|
||||||
|
|
||||||
|
- STT / TTS /(可选)VAD 放入 `models/`,或 `bash scripts/bundle_for_device.sh` 从原仓库打包。
|
||||||
|
- 本地 LLM:GGUF 默认路径或 `ROCKET_LLM_GGUF`;**纯云端对话**时可弱化本地模型,但回退/混合模式仍需。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 部署拓扑
|
||||||
|
|
||||||
|
### 3.1 单机一体化(常见)
|
||||||
|
|
||||||
|
同一台香橙派上同时运行:
|
||||||
|
|
||||||
|
1. **roscore**(若尚无 master,由 `run_flight_bridge_with_mavros.sh` 拉起)。
|
||||||
|
2. **MAVROS**(`px4.launch`,串口连 PX4)。
|
||||||
|
3. **伴飞桥** `python3 -m voice_drone.flight_bridge.ros1_node`(订阅 **`/input`**)。
|
||||||
|
4. **语音** `bash with_system_alsa.sh python main.py`。
|
||||||
|
|
||||||
|
`ROS_MASTER_URI` / `ROS_HOSTNAME`:一键脚本内默认 `http://127.0.0.1:11311` 与 `127.0.0.1`;**新开调试终端** 执行 `rostopic`/`rosservice` 前须自行 `source /opt/ros/noetic/setup.bash` 并 export **同一** `ROS_MASTER_URI`(见下文「常见问题」)。
|
||||||
|
|
||||||
|
### 3.2 网络
|
||||||
|
|
||||||
|
- 板子能访问 **云端 WebSocket**(`ROCKET_CLOUD_WS_URL`)。
|
||||||
|
- PX4 + 遥控 + 安全开关等按外场规范配置;本文不替代安全检校清单。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 启动顺序(推荐)
|
||||||
|
|
||||||
|
### 4.1 终端 A:飞控栈 + 伴飞桥
|
||||||
|
|
||||||
|
在 **`voice_drone_assistant`** 根目录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/voice_drone_assistant
|
||||||
|
bash scripts/run_flight_bridge_with_mavros.sh /dev/ttyACM0 921600
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本会:
|
||||||
|
|
||||||
|
- 设置 `ROS_MASTER_URI`、`ROS_HOSTNAME`(未预设时默认为本机 master);
|
||||||
|
- 如无 master 则启动 **roscore**;
|
||||||
|
- 启动 **MAVROS** 并等待 `/mavros/state` **connected**;
|
||||||
|
- 前台启动伴飞桥,日志中应出现:`flight_intent_bridge 就绪:订阅 /input`。
|
||||||
|
|
||||||
|
**仅桥(已有 MAVROS 时)**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source /opt/ros/noetic/setup.bash
|
||||||
|
export ROS_MASTER_URI="${ROS_MASTER_URI:-http://127.0.0.1:11311}"
|
||||||
|
export ROS_HOSTNAME="${ROS_HOSTNAME:-127.0.0.1}"
|
||||||
|
bash scripts/run_flight_intent_bridge_ros1.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 终端 B:语音助手 + 云端 + 执行飞控
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/voice_drone_assistant
|
||||||
|
|
||||||
|
export ROCKET_CLOUD_VOICE=1
|
||||||
|
export ROCKET_CLOUD_WS_URL='ws://<云主机>:8766/v1/voice/session'
|
||||||
|
export ROCKET_CLOUD_AUTH_TOKEN='<token>'
|
||||||
|
export ROCKET_CLOUD_DEVICE_ID='drone-001' # 可选
|
||||||
|
|
||||||
|
# 云端返回 flight_intent 时是否在机端执行
|
||||||
|
export ROCKET_CLOUD_EXECUTE_FLIGHT=1
|
||||||
|
# 走 ROS 伴飞桥(与 Socket/offboard 序列互斥,勿双开重复执行)
|
||||||
|
export ROCKET_FLIGHT_INTENT_ROS_BRIDGE=1
|
||||||
|
# 可选:ROCKET_FLIGHT_BRIDGE_TOPIC=/input ROCKET_FLIGHT_BRIDGE_WAIT_SUB=2
|
||||||
|
|
||||||
|
# 默认关闭本地「起飞演示」口令直起 offboard;需要时再设为 1
|
||||||
|
# export ROCKET_LOCAL_KEYWORD_TAKEOFF=1
|
||||||
|
|
||||||
|
bash with_system_alsa.sh python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
成功时日志类似:`[飞控-ROS桥] 已发布至 /input`;伴飞桥端出现 `执行 flight_intent:steps=...`。
|
||||||
|
|
||||||
|
### 4.3 配置写进 YAML(可选)
|
||||||
|
|
||||||
|
- 云端:`system.yaml` → `cloud_voice`(`enabled`、`server_url`、`auth_token` 等)。
|
||||||
|
- 本地口令起飞:`assistant.local_keyword_takeoff_enabled`(默认 `false`);环境变量 `ROCKET_LOCAL_KEYWORD_TAKEOFF` **非空时优先生效**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 环境变量速查(飞控与云端)
|
||||||
|
|
||||||
|
| 变量 | 含义 |
|
||||||
|
|------|------|
|
||||||
|
| `ROCKET_CLOUD_VOICE` | `1`:对话走云端 WebSocket |
|
||||||
|
| `ROCKET_CLOUD_WS_URL` | 云端会话地址 |
|
||||||
|
| `ROCKET_CLOUD_AUTH_TOKEN` | WS 鉴权 |
|
||||||
|
| `ROCKET_CLOUD_DEVICE_ID` | 设备 ID(可选) |
|
||||||
|
| `ROCKET_CLOUD_EXECUTE_FLIGHT` | `1`:云端 `flight_intent` 在机端执行 |
|
||||||
|
| `ROCKET_FLIGHT_INTENT_ROS_BRIDGE` | `1`:执行方式为 **发布到 ROS `/input`**,不跑机内 Socket+offboard 序列 |
|
||||||
|
| `ROCKET_FLIGHT_BRIDGE_TOPIC` | 默认 `/input` |
|
||||||
|
| `ROCKET_FLIGHT_BRIDGE_SETUP` | 子进程内 source ROS 的命令,默认 `source /opt/ros/noetic/setup.bash` |
|
||||||
|
| `ROCKET_FLIGHT_BRIDGE_WAIT_SUB` | 发布前等待订阅者的秒数,默认 `2`;`0` 即尽可能快发 |
|
||||||
|
| `ROCKET_LOCAL_KEYWORD_TAKEOFF` | 非空时:`1/true/yes` 开启 **`keywords.yaml` takeoff → 本地 offboard** |
|
||||||
|
| `ROCKET_CLOUD_PX4_CONTEXT_FILE` | 覆盖 `cloud_voice.px4_context_file`,合并进 session.start |
|
||||||
|
|
||||||
|
更多调试变量见 **`voice_drone/main_app.py` 文件头注释** 与 [`PROJECT_GUIDE.md`](PROJECT_GUIDE.md) 第 5 节。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 联调与自测
|
||||||
|
|
||||||
|
### 6.1 仅测 ROS 链(无语音)
|
||||||
|
|
||||||
|
终端已 `source /opt/ros/noetic/setup.bash` 且与 master 一致:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rostopic pub -1 /input std_msgs/String \
|
||||||
|
"data: '{\"is_flight_intent\":true,\"version\":1,\"actions\":[{\"type\":\"land\",\"args\":{}}],\"summary\":\"测\"}'"
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:`std_msgs/String` 在命令行里只能写 **`data: '...json...'`**,不能把 JSON 放在消息顶层。
|
||||||
|
|
||||||
|
### 6.2 确认话题与 master
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source /opt/ros/noetic/setup.bash
|
||||||
|
export ROS_MASTER_URI=http://127.0.0.1:11311
|
||||||
|
rosnode list
|
||||||
|
rostopic info /input
|
||||||
|
rosservice list | grep set_mode
|
||||||
|
```
|
||||||
|
|
||||||
|
若 `Unable to communicate with master!`:当前 shell 未连上正在运行的 **roscore**(或未 export 正确 `ROS_MASTER_URI`)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 常见问题(摘录)
|
||||||
|
|
||||||
|
| 现象 | 可能原因 | 处理 |
|
||||||
|
|------|----------|------|
|
||||||
|
| `ModuleNotFoundError: rospy` | 子进程未继承 ROS 的 `PYTHONPATH` | 已修复为 `PYTHONPATH=<根>:$PYTHONPATH`;确保 `ROCKET_FLIGHT_BRIDGE_SETUP` 能 source Noetic |
|
||||||
|
| 语音端「已发布」但桥无日志 | 曾用相对 `input`,与全局 `/input` 不一致 | 伴飞桥默认已改为订阅 **`/input`**;重启桥 |
|
||||||
|
| `set_mode unavailable` / land 失败 | OFFBOARD 断流、MAVROS 异常等 | 伴飞桥降落逻辑已带持续 setpoint + 重连 proxy;仍失败则查 `rosservice`、`/mavros/state`、链路 |
|
||||||
|
| takeoff 超时 | 未进 OFFBOARD、未解锁、定位未就绪 | 查地面站、`/mavros/state`、适当增大 `~takeoff_timeout_sec`(ROS 私有参数) |
|
||||||
|
| ALSA underrun | 播放与采集竞争 | 板端常见;可调缓冲区/设备或 `recognizer.ack_pause_mic_for_playback` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 安全与运维建议
|
||||||
|
|
||||||
|
- 外场前在 **SITL 或系留** 环境验证完整 **`flight_intent`** 序列。
|
||||||
|
- 云端 token、WS URL 勿提交到公开仓库;用环境变量或本机 **overlay** 配置注入。
|
||||||
|
- 升级伴飞桥或 MAVROS 后清日志重试一遍 **`/input`** 手发 JSON。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 迁移到另一台香橙派:是否只拷贝 `voice_drone_assistant` 即可?
|
||||||
|
|
||||||
|
**结论:目录是「代码 + 配置」的核心载体,但仅靠「整文件夹 scp 过去」通常不够;新板必须再装系统级依赖、模型与(可选)ROS,并按现场改配置。**
|
||||||
|
|
||||||
|
### 9.1 拷贝目录本身会带上什么
|
||||||
|
|
||||||
|
| 已包含 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| 全部 Python 源码、`voice_drone/config/*.yaml` 默认配置 | 可直接改 YAML / 环境变量适配新环境 |
|
||||||
|
| `scripts/`、`with_system_alsa.sh`、`docs/` | 启动与说明在包内 |
|
||||||
|
|
||||||
|
### 9.2 新板必须单独准备(不随目录自动存在)
|
||||||
|
|
||||||
|
| 项 | 说明 |
|
||||||
|
|----|------|
|
||||||
|
| **Ubuntu + 音频/ALSA** | 与当前开发板同代或自行适配;录音设备索引可能变化,需重选或设 `ROCKET_INPUT_DEVICE_INDEX` |
|
||||||
|
| **`pip install -r requirements.txt`** | 每台新 Python 环境执行一次(或整体迁移同一 conda 目录) |
|
||||||
|
| **`models/`** | STT/TTS/VAD 体积大,**务必**在本机先 `bash scripts/bundle_for_device.sh /path/to/rocket_drone_audio` 或手工拷入,见 `models/README.txt` |
|
||||||
|
| **`cache/` GGUF** | 纯云端可不强依赖;若需本地 Qwen 回退,拷贝或设 `ROCKET_LLM_GGUF` |
|
||||||
|
| **ROS Noetic + MAVROS** | **apt** 安装;伴飞桥方案 **必选**;`rospy` **不要**指望只靠 pip |
|
||||||
|
| **云端连通** | 新板 IP/防火墙能访问 `ROCKET_CLOUD_WS_URL`;token 用环境变量注入 |
|
||||||
|
| **`dialout` 等权限** | 访问 `/dev/ttyACM0` 的用户加入 `dialout`,否则 MAVROS 无串口 |
|
||||||
|
| **`system.yaml` 现场差异** | `socket_server` IP、可选 `tts.output_device`、若麦索引固定可写 `audio.input_device_index` |
|
||||||
|
|
||||||
|
### 9.3 推荐迁移流程(简表)
|
||||||
|
|
||||||
|
1. 在旧机或 CI:**bundle 模型** → 打包整个 `voice_drone_assistant`(含 `models/`,按需含 `cache/`)。
|
||||||
|
2. 新香橙派:解压到任意路径,安装 **`requirements.txt`**、**ROS+MAVROS**、系统音频工具。
|
||||||
|
3. 用 **`with_system_alsa.sh python main.py`** 试麦与 STT;再按本文 **§4** 双终端起 **桥 + 语音**。
|
||||||
|
4. 首次外场前做一次 **`rostopic pub /input`** 手发 JSON(见 **§6**)。
|
||||||
|
|
||||||
|
### 9.4 常见误区
|
||||||
|
|
||||||
|
- **只拉 Git、不拷 `models/`**:STT/TTS 启动即失败。
|
||||||
|
- **新板 Noetic 未装却开 `ROCKET_FLIGHT_INTENT_ROS_BRIDGE`**:发布子进程仍可能报错。
|
||||||
|
- **假设麦克风设备号一定相同**:Orange Pi 刷机或换内核后常变,以首次启动日志为准。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 文档索引
|
||||||
|
|
||||||
|
| 文档 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| [`README.md`](../README.md) | 仓库简介、模型、`bundle` |
|
||||||
|
| [`PROJECT_GUIDE.md`](PROJECT_GUIDE.md) | 配置项与日常用法索引 |
|
||||||
|
| **本文** | 部署拓扑、启动顺序、环境变量、联调、**§9 迁移清单** |
|
||||||
|
| [`FLIGHT_BRIDGE_ROS1.md`](FLIGHT_BRIDGE_ROS1.md) | 伴飞桥参数、PX4 行为、`rostopic pub` 注意 |
|
||||||
|
| [`FLIGHT_INTENT_SCHEMA_v1.md`](FLIGHT_INTENT_SCHEMA_v1.md) | JSON 协议 |
|
||||||
|
| [`llmcon.md`](llmcon.md) | 云端协议 |
|
||||||
|
| [`CLOUD_VOICE_FLIGHT_CONFIRM_v1.md`](CLOUD_VOICE_FLIGHT_CONFIRM_v1.md) | **飞控口头二次确认**(闲聊不变、确认/取消/超时)云端与机端字段约定 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档版本与仓库同步;若行为与代码不一致,以当前 `main_app.py`、`flight_bridge/*.py` 为准。*
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
# Flight Intent 伴飞桥(ROS 1 + MAVROS)
|
||||||
|
|
||||||
|
本目录代码与语音助手 **`main.py` 独立进程**:在 **MAVROS 已连接 PX4** 的前提下,订阅一条 JSON,按 **`FLIGHT_INTENT_SCHEMA_v1.md`** 顺序执行。
|
||||||
|
|
||||||
|
## 依赖
|
||||||
|
|
||||||
|
- Ubuntu / 设备上已装 **ROS Noetic**、`mavros`(与 `scripts/run_px4_offboard_one_terminal.sh` 一致)
|
||||||
|
- Python 能 import:`rospy`、`std_msgs`、`geometry_msgs`、`mavros_msgs`
|
||||||
|
- 本仓库根目录 **`voice_drone_assistant`** 需在 `PYTHONPATH`(启动脚本已设置)
|
||||||
|
|
||||||
|
## 启动
|
||||||
|
|
||||||
|
**推荐(不会单独敲 roslaunch 时用)**:一键拉起 roscore(若尚无)→ MAVROS → 伴飞桥:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd voice_drone_assistant
|
||||||
|
bash scripts/run_flight_bridge_with_mavros.sh
|
||||||
|
bash scripts/run_flight_bridge_with_mavros.sh /dev/ttyACM0 921600
|
||||||
|
```
|
||||||
|
|
||||||
|
**已有 MAVROS 时**只启桥:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd voice_drone_assistant
|
||||||
|
bash scripts/run_flight_intent_bridge_ros1.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
默认节点名(含 anonymous 后缀):`/flight_intent_mavros_bridge_<...>`,默认订阅 **全局 `/input`**(`std_msgs/String`,内容为 JSON)。私有参数 `~input_topic` 可改(例如专用名时填入完整话题)。桥启动日志会打印实际订阅名。
|
||||||
|
|
||||||
|
## JSON 格式
|
||||||
|
|
||||||
|
- **完整** `flight_intent`(与云端相同顶层字段),或
|
||||||
|
- **最小**:`{"actions":[...], "summary":"任意非空"}`(节点内会补 `is_flight_intent/version`)
|
||||||
|
|
||||||
|
校验失败会打 `rospy.logerr`,不执行。
|
||||||
|
|
||||||
|
## 行为映射(首版)
|
||||||
|
|
||||||
|
| `type` | 行为(简述) |
|
||||||
|
|--------|----------------|
|
||||||
|
| `takeoff` | Offboard 位姿:当前点预热 setpoint → `OFFBOARD` + arm → `z0 + Δz`(Δz 来自 `relative_altitude_m` 或参数 `~default_takeoff_relative_m`,与 `px4_ctrl_offboard_demo` 同号约定) |
|
||||||
|
| `hover` / `hold` | 当前位姿 hold 约 1s(持续发 setpoint) |
|
||||||
|
| `wait` | `rospy.Duration`,Offboard 时顺带维持当前点 setpoint |
|
||||||
|
| `goto` | `local_ned` / `body_ned` 增量 → 目标 NED 点,到位容差见 `~goto_position_tolerance` |
|
||||||
|
| `land` | `AUTO.LAND` |
|
||||||
|
| `return_home` | `AUTO.RTL` |
|
||||||
|
|
||||||
|
**注意**:真机前请 SITL 验证;不同 PX4/机型的 `custom_mode` 字符串若不一致需在 `ros1_mavros_executor.py` 中调整。
|
||||||
|
|
||||||
|
## 参数(私有命名空间)
|
||||||
|
|
||||||
|
| 参数 | 默认 | 含义 |
|
||||||
|
|------|------|------|
|
||||||
|
| `~input_topic` | `/input` | 订阅话题(建议绝对路径;勿再用相对名 `input`,否则与 `/input` 对不上) |
|
||||||
|
| `~default_takeoff_relative_m` | `0.5` | `takeoff` 无 `relative_altitude_m` 时 |
|
||||||
|
| `~takeoff_timeout_sec` | `15` | |
|
||||||
|
| `~goto_position_tolerance` | `0.15` | m |
|
||||||
|
| `~goto_timeout_sec` | `60` | |
|
||||||
|
| `~land_timeout_sec` | `45` | land/rtl 等待 disarm 超时 |
|
||||||
|
| `~offboard_pre_stream_count` | `80` | 与 demo 类似 |
|
||||||
|
|
||||||
|
## 与语音程序的关系
|
||||||
|
|
||||||
|
- **`main.py`**:仍可用 Socket / 本地 offboard **演示脚本**(产品过渡期)。
|
||||||
|
- **桥**:适合作为 **长期** MAVROS 执行端;后续可把语音侧改为 **向本节点 `input` 发布 JSON**(`rospy` 或 `roslibpy` 等),而不再直接起 bash demo。
|
||||||
|
|
||||||
|
## 与语音侧联调:`rostopic pub`(注意 `data:`)
|
||||||
|
|
||||||
|
`std_msgs/String` 的 YAML 只有字段 **`data`**,JSON 必须写在 **`data: '...'`** 里;不能把 JSON 直接当消息顶层(否则会 `ERROR: No field name [is_flight_intent]` / `Args are: [data]`)。
|
||||||
|
|
||||||
|
终端 A:已跑 `run_flight_bridge_with_mavros.sh`(或 MAVROS + 桥)。
|
||||||
|
终端 B:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source /opt/ros/noetic/setup.bash
|
||||||
|
# 订阅名以桥日志为准,常见为全局 /input
|
||||||
|
rostopic pub -1 /input std_msgs/String \
|
||||||
|
"data: '{\"is_flight_intent\":true,\"version\":1,\"actions\":[{\"type\":\"land\",\"args\":{}}],\"summary\":\"联调降落\"}'"
|
||||||
|
```
|
||||||
|
|
||||||
|
**悬停 2 秒再降**(须已在空中时再试):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rostopic pub -1 /input std_msgs/String \
|
||||||
|
"data: '{\"is_flight_intent\":true,\"version\":1,\"actions\":[{\"type\":\"hover\",\"args\":{}},{\"type\":\"wait\",\"args\":{\"seconds\":2}},{\"type\":\"land\",\"args\":{}}],\"summary\":\"测\"}'"
|
||||||
|
```
|
||||||
|
|
||||||
|
在语音进程内集成时,建议 **不要在 asyncio 里直接调 rospy**,用 **独立桥进程 + topic** 或 **UNIX socket 转发到桥**。
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
# Flight Intent v1 + 伴飞桥 — 实施计划
|
||||||
|
|
||||||
|
本文档与 [`FLIGHT_INTENT_SCHEMA_v1.md`](FLIGHT_INTENT_SCHEMA_v1.md) 配套,描述从协议闭环到 ROS/PX4 可控的**分阶段交付**。顺序建议按阶段 0→4;各阶段内任务可并行处已标注。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目标与验收标准
|
||||||
|
|
||||||
|
| 维度 | 验收标准 |
|
||||||
|
|------|-----------|
|
||||||
|
| **协议** | 云端下发的 `flight_intent` 满足 v1:含 `wait`、`takeoff` 可选高度、`trace_id`;L1–L3 校验可自动化 |
|
||||||
|
| **语音客户端** | 能解析并记录完整 `actions`;在 `ROCKET_CLOUD_EXECUTE_FLIGHT=1` 时通过 Socket/桥 执行或与桥约定本地执行 `wait` |
|
||||||
|
| **桥** | 顺序执行 `actions`,每步有超时/失败策略;可对接 MAVROS(或既定 ROS 2 栈)驱动 PX4 |
|
||||||
|
| **安全** | 执行前 L4 门禁、执行中可中断、急停路径明确 |
|
||||||
|
| **回归** | SITL 或台架可重复跑通「起飞 → 悬停 → wait → 降落」等示例 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 0:对齐与基线(约 0.5~1 天)
|
||||||
|
|
||||||
|
- [ ] 全员精读 `FLIGHT_INTENT_SCHEMA_v1.md`,冻结 **v1 白名单**(`type` / `args` 键)。
|
||||||
|
- [ ] 确认伴飞侧技术选型:**ROS 2 + MAVROS**(或 `px4_ros_com`)与默认 **AUTO vs Offboard** 策略(写入桥 YAML,不写进 JSON)。
|
||||||
|
- [ ] 盘点现有 **Socket 服务**:是否即「桥」或仅转发;是否需新进程 `flight_intent_bridge`。
|
||||||
|
- [ ] 建立 **trace_id** 在日志中的格式(云端 / 语音 / 桥统一)。
|
||||||
|
|
||||||
|
**产出**:架构一页纸(谁消费 WebSocket、谁连 PX4)、桥配置模板路径约定。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 1:协议与云端(可与阶段 2 并行,约 2~4 天)
|
||||||
|
|
||||||
|
- [ ] **Schema 校验**:服务端对 `flight_intent` 做 L1–L3(必要时 L4 占位);非法则 `routing=error` 或产品协议兜底。
|
||||||
|
- [ ] **LLM 提示词**:只允许 §3.7 中 `type` 与允许键;强调 **时长必须用 `wait`**,禁止用 `summary` 控机。
|
||||||
|
- [ ] **示例与回归用例**:固定 JSON golden(§7.1~§7.3 + 边界:首步 `wait`、`seconds` 超界、多余 `args` 键)。
|
||||||
|
- [ ] **可选 `trace_id`**:服务端生成或在 bundle 层透传。
|
||||||
|
|
||||||
|
**产出**:校验测试集、提示词 MR、发布说明(对客户端可见的字段变更)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 2:语音客户端(`voice_drone_assistant`)(约 3~5 天)
|
||||||
|
|
||||||
|
可与阶段 1、3 部分并行。
|
||||||
|
|
||||||
|
- [x] **Pydantic**:`voice_drone/core/flight_intent.py`(v2)按 v1 文档收紧动作与 `args`。
|
||||||
|
- [x] **`parse_flight_intent_dict`**:等价 L1–L3 + 首步禁止 `wait`;白名单、`goto.frame`、`wait.seconds`、`takeoff.relative_altitude_m`。
|
||||||
|
- [x] **`main_app`**:`ROCKET_CLOUD_EXECUTE_FLIGHT=1` 时在后台线程 **`_run_cloud_flight_intent_sequence`** 顺序执行;`wait` 用 `time.sleep`;`goto` **单轴** 映射 Socket `Command`;`return_home` 已入 `Command`;**含 `takeoff` 的序列**在 offboard 完成后继续后续步(不再丢失)。
|
||||||
|
- [x] **日志**:序列开始时打印 `trace_id`;`takeoff` 打相对高度提示(offboard 是否消费须自行接参数)。
|
||||||
|
- [x] **单测**:`tests/test_flight_intent.py`(无完整依赖时 goto 用例自动 skip)。
|
||||||
|
|
||||||
|
**产出**:MR 合并后,本地无 PX4 也能跑通解析与 mock 执行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 3:伴飞桥 + ROS/PX4(约 5~10 天,视现网复用程度)
|
||||||
|
|
||||||
|
- [x] **进程边界(首版)**:独立 ROS1 节点,订阅 `std_msgs/String` JSON;见 **`docs/FLIGHT_BRIDGE_ROS1.md`**、`scripts/run_flight_intent_bridge_ros1.sh`。
|
||||||
|
- [x] **执行器(首版)**:`voice_drone/flight_bridge/ros1_mavros_executor.py` 单线程顺序执行;`takeoff/goto` 带超时;`land/rtl` 等待 disarm 超时。
|
||||||
|
- [x] **翻译实现(首版 / MAVROS)**:
|
||||||
|
- `takeoff` / `hover` / `wait` / `goto`:`/mavros/setpoint_raw/local`(Offboard)+ `set_mode` / `arming`。
|
||||||
|
- `land` / `return_home`:`AUTO.LAND` / `AUTO.RTL`。
|
||||||
|
- [ ] **安全**:L4(电量、围栏、急停 topic);`wait` 中异常策略。
|
||||||
|
- [ ] **回执**:result topic / 与 `main.py` 的 topic 串联。
|
||||||
|
- [ ] **ROS2 / 仅 TCP 无 ROS**:按需另起接口。
|
||||||
|
|
||||||
|
**产出(当前)**:ROS1 桥可 `rostopic pub` 联调;**待** launch、与语音侧发布 JSON、SITL CI。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 4:联调、硬化与发布(约 3~7 天)
|
||||||
|
|
||||||
|
- [ ] **端到端**:真机或 SITL:语音 → 云 → 客户端 → 桥 → PX4,带 `trace_id` 串 log。
|
||||||
|
- [ ] **压测与失败注入**:断 WebSocket、桥崩溃重启、Offboard 丢失等(预期行为写进运维文档)。
|
||||||
|
- [ ] **配置与门禁**:默认关闭实飞执行;仅生产镜像打开;参数与围栏双人复核。
|
||||||
|
- [ ] **文档**:更新 `PROJECT_GUIDE.md` 中「飞控路径」链接到本文与 SCHEMA。
|
||||||
|
|
||||||
|
**产出**:发布 checklist、已知限制列表(如某机型仅支持 AUTO 等)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 依赖与风险
|
||||||
|
|
||||||
|
| 风险 | 缓解 |
|
||||||
|
|------|------|
|
||||||
|
| Socket 协议与 `Command` 无法表达多步 | **推荐**由桥消费**完整** `flight_intent` JSON,客户端只负责下发一份;少步经 Socket 逐条 |
|
||||||
|
| Offboard 与 AUTO 混用冲突 | 桥配置单一「主策略」;`goto` 仅在 Offboard 就绪时接受 |
|
||||||
|
| LLM 仍产出非法 JSON | L2 硬拒绝 + 提示词回归 + golden 测试 |
|
||||||
|
| 排期膨胀 | 先交付 **AUTO 模式族 + wait + land**,再迭代复杂 `goto` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 建议里程碑(日历为估算)
|
||||||
|
|
||||||
|
| 里程碑 | 内容 |
|
||||||
|
|--------|------|
|
||||||
|
| **M1** | 阶段 0–1 完成:云校验 + 提示词 + golden |
|
||||||
|
| **M2** | 阶段 2 完成:客户端 strict 模型 + `wait` + 执行路径单一数据源 |
|
||||||
|
| **M3** | 阶段 3 完成:桥 + SITL 跑通 §7.2 |
|
||||||
|
| **M4** | 阶段 4:联调签字 + 生产策略 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 文档索引
|
||||||
|
|
||||||
|
| 文档 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| [`FLIGHT_INTENT_SCHEMA_v1.md`](FLIGHT_INTENT_SCHEMA_v1.md) | 字段、校验、桥分层、ROS 参考 |
|
||||||
|
| [`PROJECT_GUIDE.md`](PROJECT_GUIDE.md) | 仓库总览与运行方式 |
|
||||||
|
| 本文 | 任务拆解、顺序、验收 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**版本**:2026-04-07;随 SCHEMA v1 修订同步更新本计划中的阶段勾选与工期估算。
|
||||||
@ -0,0 +1,372 @@
|
|||||||
|
# 云端高层飞控意图 JSON 规范 v1(完整版)
|
||||||
|
|
||||||
|
> **定位**:定义 WebSocket `dialog_result.flight_intent` 中的**语义对象**与**伴飞侧执行约定**,不是 MAVLink 二进制帧。
|
||||||
|
> **目标**:
|
||||||
|
>
|
||||||
|
> 1. **协议**:客户端与云端可 **100% 按字段表 strict 解析**;**禁止**用自然语言或 `summary` 驱动机控。
|
||||||
|
> 2. **桥(companion)**:按本文执行 **有序 `actions`**、校验、排队与安全门,再译为 PX4 可接受的模式 / 指令 / Offboard setpoint。
|
||||||
|
> 3. **ROS**:为 MAVROS(或等价 ROS 2 封装)提供**参考映射表**;具体 topic/service 名称以装机软件栈为准。
|
||||||
|
|
||||||
|
**协议(bundle)**:`proto_version: "1.0"`,会话 `transport_profile: "pcm_asr_uplink"`(与机端 CloudVoiceClient 一致)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 顶层对象 `flight_intent`
|
||||||
|
|
||||||
|
当 `routing === "flight_intent"` 时,`flight_intent` **必须非 null**,且为下表 JSON 对象(键顺序任意)。
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `is_flight_intent` | `boolean` | 是 | **必须为 `true`** |
|
||||||
|
| `version` | `integer` | 是 | **Schema 版本,本文档固定为 `1`** |
|
||||||
|
| `actions` | `array` | 是 | **有序**动作列表,按**时间先后**执行(见 §5、§10) |
|
||||||
|
| `summary` | `string` | 是 | 一句人类可读中文摘要(播报/日志);**不参与机控解析** |
|
||||||
|
| `trace_id` | `string` | 否 | **端到端追踪 ID**(建议 UUID 或雪花 ID);用于桥、ROS 节点与日志关联;长度建议 ≤ 128 |
|
||||||
|
|
||||||
|
**禁止字段**:除上表外,顶层不得出现其它键(便于 `strict` 解析)。扩展须 **递增 `version`**(见 §8)。
|
||||||
|
|
||||||
|
**字符编码**:UTF-8。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. `actions[]` 通用形式
|
||||||
|
|
||||||
|
每个元素:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "<ActionType>", "args": { ... } }
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 |
|
||||||
|
|------|------|------|
|
||||||
|
| `type` | `string` | 是,取值限于 §3 枚举 |
|
||||||
|
| `args` | `object` | 是,允许为空对象 `{}`;**仅允许**各小节表中列出的键 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. `ActionType` 与白名单 `args`
|
||||||
|
|
||||||
|
以下 **`type` 仅允许小写**。未列出的值在 v1 **非法**。
|
||||||
|
|
||||||
|
### 3.1 `takeoff`
|
||||||
|
|
||||||
|
| args 键 | 类型 | 必填 | 说明 |
|
||||||
|
|---------|------|------|------|
|
||||||
|
| `relative_altitude_m` | `number` | 否 | 相对起飞点(或飞控定义的 TAKEOFF 参考)的**目标高度**,单位 **米**,须 **> 0**。省略则 **完全由机端/飞控缺省参数** 决定(与旧版「空 args」语义一致) |
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "takeoff", "args": {} }
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "takeoff", "args": { "relative_altitude_m": 5 } }
|
||||||
|
```
|
||||||
|
|
||||||
|
**桥 / ROS 映射提示**:PX4 `TAKEOFF` 模式、`MAV_CMD_NAV_TAKEOFF`;相对高度常与 `MIS_TAKEOFF_ALT` 或命令参数结合,**以装机参数为准**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 `land`
|
||||||
|
|
||||||
|
| args 键 | 类型 | 必填 | 说明 |
|
||||||
|
|---------|------|------|------|
|
||||||
|
| — | — | — | v1 无参;降落行为由飞控 `AUTO.LAND` 等策略决定 |
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "land", "args": {} }
|
||||||
|
```
|
||||||
|
|
||||||
|
**桥 / ROS 映射提示**:`AUTO.LAND`、`MAV_CMD_NAV_LAND`;固定翼 / 多旋翼路径不同,由机端处理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 `return_home`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "return_home", "args": {} }
|
||||||
|
```
|
||||||
|
|
||||||
|
语义:**返航至 Home 并按飞控策略降落或盘旋**(与 PX4 **RTL** 概义一致)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.4 `hover` 与 `hold`
|
||||||
|
|
||||||
|
二者在 v1 **语义等价**:**在当前位置附近保持**(多旋翼常见为位置保持;固定翼可能映射为 Loiter,由机端按机型解释)。
|
||||||
|
|
||||||
|
| args 键 | 类型 | 必填 | 说明 |
|
||||||
|
|---------|------|------|------|
|
||||||
|
| — | — | — | 仅 `{}` 合法;表示进入保持,**不隐含**持续时间(时长用 §3.6 `wait`) |
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "hover", "args": {} }
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "hold", "args": {} }
|
||||||
|
```
|
||||||
|
|
||||||
|
**约定**:同一 `actions` 序列建议只选 `hover` 或 `hold` 一种命名;解析端可映射到同一 PX4 行为。
|
||||||
|
|
||||||
|
**互操作(非规范首选)**:个别上游可能错误输出 `"args": { "duration": 3 }`(秒)。**伴飞客户端**(如本仓库 `flight_intent.py`)可在校验时将其**折叠**为:`hover`(无 `duration`)+ `wait`,与上表典型组合等价;**新开发的上游仍应只产 `wait`**。
|
||||||
|
|
||||||
|
**典型组合**(「悬停 3 秒后降落」):
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{ "type": "takeoff", "args": {} },
|
||||||
|
{ "type": "hover", "args": {} },
|
||||||
|
{ "type": "wait", "args": { "seconds": 3 } },
|
||||||
|
{ "type": "land", "args": {} }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.5 `goto` — 相对/局部位移
|
||||||
|
|
||||||
|
| args 键 | 类型 | 必填 | 说明 |
|
||||||
|
|---------|------|------|------|
|
||||||
|
| `frame` | `string` | 是 | 坐标系,取值见 §4 |
|
||||||
|
| `x` | `number` \| `null` | 否 | **米**;`null` 或 **省略** 表示该轴**无位移意图**(机端保持) |
|
||||||
|
| `y` | `number` \| `null` | 否 | 同上 |
|
||||||
|
| `z` | `number` \| `null` | 否 | 同上 |
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "goto",
|
||||||
|
"args": {
|
||||||
|
"frame": "local_ned",
|
||||||
|
"x": 100,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**语义**:在 `frame` 下相对当前位置的**增量**。v1 **不**定义绝对经纬度航点;若未来需要,应 **v2** 增加 `goto_global` / `waypoint`。
|
||||||
|
|
||||||
|
**口语映射示例**:「向前飞 10 米」可建模为 `frame: "body_ned"`, `x: 10`(前为 x+,与 §4 一致)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.6 `wait` — 纯时间等待
|
||||||
|
|
||||||
|
**不包含**模式切换;桥在**本地计时**后继续下一步。用于「悬停多久」「停顿再执行」等。
|
||||||
|
|
||||||
|
| args 键 | 类型 | 必填 | 说明 |
|
||||||
|
|---------|------|------|------|
|
||||||
|
| `seconds` | `number` | 是 | 等待秒数,须满足 **0 < seconds ≤ 3600**(上限可防止 LLM 写极大值;产品可改小) |
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "type": "wait", "args": { "seconds": 3 } }
|
||||||
|
```
|
||||||
|
|
||||||
|
**安全**:等待期间桥须持续监测遥测(失联、低电量、姿态异常等),**可中断**序列并转入 `RTL` / `LAND` / `HOLD`(策略见 §10.4)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.7 v1 动作类型一览
|
||||||
|
|
||||||
|
| `type` | 必填 `args` 键 | 备注 |
|
||||||
|
|--------|----------------|------|
|
||||||
|
| `takeoff` | 无 | 可选 `relative_altitude_m` |
|
||||||
|
| `land` | 无 | |
|
||||||
|
| `return_home` | 无 | |
|
||||||
|
| `hover` | 无 | |
|
||||||
|
| `hold` | 无 | 与 `hover` 等价 |
|
||||||
|
| `goto` | `frame` | 可选 x/y/z |
|
||||||
|
| `wait` | `seconds` | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. `frame`(仅 `goto`)
|
||||||
|
|
||||||
|
| 取值 | 含义 |
|
||||||
|
|------|------|
|
||||||
|
| `local_ned` | **局部 NED**:北(x)-东(y)-地(z),单位 m;**向下为 z 正**(与 PX4 `LOCAL_NED` 常见用法一致) |
|
||||||
|
| `body_ned` | **机体系**:**前(x)-右(y)-下(z)**,单位 m;桥或 ROS 侧需转换到 NED / setpoint |
|
||||||
|
|
||||||
|
**v1 仅此两值**;其它字符串 **L2 非法**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 序列语义与组合规则
|
||||||
|
|
||||||
|
- **`actions` 有序**:严格对应口语**时间顺序**(先执行索引 0,再 1,…)。
|
||||||
|
- **空列表**:**不允许**(至少 1 个元素)。
|
||||||
|
- **`wait`**:不改变飞控模式;若需「边悬停边等」,应先 `hover`/`hold` 再 `wait`(或在上一步已进入位置模式的假定下仅 `wait`,由机端策略定义;**推荐**显式 `hover` 再 `wait`)。
|
||||||
|
- **首步**:首元素为 `wait` **不推荐**(飞机未起飞则等待无控飞意义);服务端可做 **L4 警告或拒绝**。
|
||||||
|
- **`takeoff` 后出现 `goto`**:桥应确保已有位置估计/GPS 等前置条件,否则拒绝并回报原因。
|
||||||
|
- **重复动作**:不禁止连续多个 `goto` / `wait`;机端可合并或排队。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 校验分级(服务端 + 桥建议共用)
|
||||||
|
|
||||||
|
| 级别 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| **L1 结构** | JSON 可解析;`is_flight_intent===true`;`version===1`;`actions` 为非空数组;`summary` 为非空字符串;`trace_id` 若存在则为 string。 |
|
||||||
|
| **L2 枚举** | 每个 `action.type` ∈ §3.7;`goto` 含合法 `frame`;各 `args` **仅含**该 `type` 允许的键(无多余键)。 |
|
||||||
|
| **L3 数值** | `relative_altitude_m` 若存在则 **> 0** 且建议 capped(如 ≤ 500);`wait.seconds` 在 **(0, 3600]**;`goto` 的 x/y/z 为有限 number 或 null;位移模长可设上限(如 10e3 m)。 |
|
||||||
|
| **L4 语义** | 结合 `session.start.client.px4`(机型、是否支持 Offboard、地理围栏等);禁止不合法序列(如无定位时 `goto`);不通过则 `error` 或带工程约定 `warnings`(v2 可标准化 `warnings` 数组)。 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 完整示例
|
||||||
|
|
||||||
|
### 7.1 起飞 → 北飞 100m → 悬停
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"is_flight_intent": true,
|
||||||
|
"version": 1,
|
||||||
|
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"actions": [
|
||||||
|
{ "type": "takeoff", "args": {} },
|
||||||
|
{
|
||||||
|
"type": "goto",
|
||||||
|
"args": { "frame": "local_ned", "x": 100, "y": 0, "z": 0 }
|
||||||
|
},
|
||||||
|
{ "type": "hover", "args": {} }
|
||||||
|
],
|
||||||
|
"summary": "起飞后向北飞约100米并悬停"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 起飞 → 悬停 3 秒 → 降落
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"is_flight_intent": true,
|
||||||
|
"version": 1,
|
||||||
|
"actions": [
|
||||||
|
{ "type": "takeoff", "args": { "relative_altitude_m": 3 } },
|
||||||
|
{ "type": "hover", "args": {} },
|
||||||
|
{ "type": "wait", "args": { "seconds": 3 } },
|
||||||
|
{ "type": "land", "args": {} }
|
||||||
|
],
|
||||||
|
"summary": "起飞至约3米高,悬停3秒后降落"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 返航
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"is_flight_intent": true,
|
||||||
|
"version": 1,
|
||||||
|
"actions": [
|
||||||
|
{ "type": "return_home", "args": {} }
|
||||||
|
],
|
||||||
|
"summary": "返航至 Home"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 演进与扩展
|
||||||
|
|
||||||
|
- **新增 `type`、新 `frame`、顶层字段**:须 **递增 `version`**(如 `2`)并附迁移说明。
|
||||||
|
- **严禁**:在 `flight_intent` 内增加自由文本字段用于机动解释(仅 `summary` 可读)。
|
||||||
|
- **调试**:可在外层 bundle(非 `flight_intent` 体内)附加 `schema: "cloud_voice.flight_intent@1"`,由工程约定。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. JSON → PX4 责任边界(摘要)
|
||||||
|
|
||||||
|
| JSON `type` | 机端典型职责(PX4 侧,非规范强制) |
|
||||||
|
|-------------|--------------------------------------|
|
||||||
|
| `return_home` | RTL / `MAV_CMD_NAV_RETURN_TO_LAUNCH` 等 |
|
||||||
|
| `takeoff` | TAKEOFF / `MAV_CMD_NAV_TAKEOFF`,高度来自 args 或参数 |
|
||||||
|
| `land` | LAND 模式 / `MAV_CMD_NAV_LAND` |
|
||||||
|
| `goto` | Offboard 轨迹、外部跟踪或 Mission 航点(**桥根据策略选一**) |
|
||||||
|
| `hover` / `hold` | LOITER / HOLD / 位置保持 setpoint |
|
||||||
|
| `wait` | 仅伴飞计时;**不发**模式切换 MAV 命令(除非实现为「保持当前模式下的阻塞」) |
|
||||||
|
|
||||||
|
**不重样规定**:MAVLink messageId、发送频率、Offboard 心跳、EKF 就绪条件由 **companion + PX4 装机** 保证。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 伴飞桥(Bridge)设计要点
|
||||||
|
|
||||||
|
本节约定:**桥** = 运行在伴飞计算机上的进程(可与语音同源或独立),负责消费 `flight_intent`(或等价 JSON),**绝不**把原始 LLM 文本直接发给 PX4。
|
||||||
|
|
||||||
|
### 10.1 逻辑分层
|
||||||
|
|
||||||
|
1. **接入**:WebSocket 回调 → 解析 `flight_intent`;或订阅 ROS Topic `flight_intent/json`;或 TCP 接收与本文相同的 JSON。
|
||||||
|
2. **校验**:至少 L1–L3;有 px4 上下文时做 L4。
|
||||||
|
3. **执行器**:对 `actions` **单线程顺序**执行;内部每步调用 **翻译器**(见 §10.3)。
|
||||||
|
4. **遥测与安全**:每步前置检查(模式、解锁、定位、电量、围栏);执行中 watchdog;可打断队列。
|
||||||
|
5. **回执(建议)**:ROS 发布 `flight_intent/result` 或写日志/Socket:success / rejected / aborted + `trace_id` + 步号 + 原因码。
|
||||||
|
|
||||||
|
### 10.2 与语音客户端的关系(本仓库)
|
||||||
|
|
||||||
|
- 语音侧可将 **`flight_intent` 映射** 为现有 `Command`(`command` + `params` + `sequence_id` + `timestamp`)经 **Socket** 发到桥;或由桥 **直接订阅云端结果**(二选一,避免双源)。
|
||||||
|
- **`wait`**:若 Socket 协议暂无对应 `Command`,桥在本地对「已解析的 `actions` 列表」执行 `wait`,**不必**经 Socket 转发计时。
|
||||||
|
- **扩展 `Command`**:若希望所有步骤可经 Socket 观测,可增加 `command: "noop"` + `params.duration` 仅作日志,但 **推荐** 桥本地处理 `wait`。
|
||||||
|
|
||||||
|
### 10.3 翻译器(`type` → 行为)
|
||||||
|
|
||||||
|
实现为代码表 + 机型分支,示例:
|
||||||
|
|
||||||
|
| `type` | 桥内典型步骤(抽象) |
|
||||||
|
|--------|----------------------|
|
||||||
|
| `takeoff` | 检查 arming 策略 → 发送起飞命令/切 TAKEOFF → 等待「达到 hover 可接受高度」或超时 |
|
||||||
|
| `land` | 切 LAND 或发 NAV_LAND → 监测直到 disarm 或超时 |
|
||||||
|
| `return_home` | 切 RTL |
|
||||||
|
| `hover`/`hold` | 切 AUTO.LOITER 或发位置保持 setpoint(Offboard 路径则发零速/当前位 setpoint) |
|
||||||
|
| `goto` | 按 `frame` 解算目标 → Offboard 轨迹或上传迷你 mission → 等待到达容差或超时 |
|
||||||
|
| `wait` | `sleep(seconds)` + 可中断环形检查遥测 |
|
||||||
|
|
||||||
|
每步应定义 **超时** 与 **失败策略**(中止整段序列 / 仅跳过一步)。
|
||||||
|
|
||||||
|
### 10.4 安全与中断
|
||||||
|
|
||||||
|
- **急停 / 人机优先级**:本地硬件或 ROS `/emergency_hold` 等应能 **清空队列** 并进入安全模式。
|
||||||
|
- **云断连**:不要求中断已在执行的序列(产品可配置「断连即 RTL」)。
|
||||||
|
- **`wait` 期间**:持续判据;触发阈值则 **中止等待** 并执行安全动作。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. ROS / MAVROS 实施参考
|
||||||
|
|
||||||
|
以下为方便对接 **ROS 2 + MAVROS**(或 `px4_ros_com`)的**参考映射**;实际包名、话题名、QoS 以你方 `mavros` 版本与 launch 为准。
|
||||||
|
|
||||||
|
### 11.1 常用接口类型
|
||||||
|
|
||||||
|
| 目的 | 常见 ROS 2 形态 | 说明 |
|
||||||
|
|------|------------------|------|
|
||||||
|
| 模式切换 | `mavros_msgs/srv/VehicleCmd` 或 SetMode 等价服务 | 切 `AUTO.TAKEOFF`, `AUTO.LAND`, `AUTO.LOITER`, `AUTO.RTL` 等 |
|
||||||
|
| 解锁/上锁 | `cmd/arming` 服务或 VehicleCommand | 桥策略决定是否自动 arm |
|
||||||
|
| Offboard 轨迹 | `trajectory_setpoint`、`offboard_control_mode`(PX4 官方 ROS 2 示例) | 用于 `goto` / `hover` 的 setpoint 路径 |
|
||||||
|
| 状态反馈 | `vehicle_status`、`local_position`、电池 topic | L4 与每步完成判定 |
|
||||||
|
| 长航指令 | `Mission`、`CMD` 接口 | 复杂航迹可选用 mission 上传 |
|
||||||
|
|
||||||
|
### 11.2 JSON → ROS 责任划分建议
|
||||||
|
|
||||||
|
- **桥节点**订阅或接收 `flight_intent`,执行 §10.3,并调用 **MAVROS / px4_ros_com** 客户端。
|
||||||
|
- **飞控仿真**:同一套 `flight_intent` 可在 SITL 上回放,便于 CI。
|
||||||
|
- **单飞控单 writer**:同一时刻建议只有一个节点向 Offboard 端口写 setpoint,避免竞争。
|
||||||
|
|
||||||
|
### 11.3 与 PX4 模式的关系(概念)
|
||||||
|
|
||||||
|
- **AUTO 模式族**(TAKEOFF / LAND / LOITER / RTL):适合 `takeoff`、`land`、`return_home`、部分 `hover`。
|
||||||
|
- **Offboard**:适合连续 `goto`、精细悬停;桥需负责 **先切 Offboard 再发 setpoint**,并满足 PX4 Offboard 丢包监测。
|
||||||
|
- 具体选 AUTO 还是 Offboard 由 **桥配置**(YAML)决定,**不写入** `flight_intent` JSON(保持云侧与机型解耦)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 与当前仓库实现的对齐清单
|
||||||
|
|
||||||
|
| 项 | 建议 |
|
||||||
|
|----|------|
|
||||||
|
| Pydantic | `FlightIntentPayload` / `FlightIntentAction`:收紧 `type` Literal;`args` 按 §3 分类型或 discriminated union |
|
||||||
|
| 云端校验 | `_validate_flight_intent`:L2 白名单 + `goto.frame` + `wait.seconds` + `takeoff.relative_altitude_m` |
|
||||||
|
| LLM 提示词 | 仅允许 §3.7 中 `type` 与各 `args` 键;**必须**用 `wait` 表达明确停顿时长 |
|
||||||
|
| `main_app` | `land`/`hover` 已有 Socket 映射;`goto`/`return_home`/`takeoff`/`wait` 需在桥或 Socket 侧补全 |
|
||||||
|
| `Command` | 可扩展 `Literal` 与 `CommandParams`,或与桥约定「语音只发 Socket,复杂序列由桥执行」 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档版本**:2026-04-07(修订:增加 `wait`、`takeoff` 可选高度、`trace_id`、桥与 ROS 章节)。与 **`flight_intent.version === 1`** 对应。
|
||||||
148
voicellmcloud/Client/voice_drone_assistant/docs/PROJECT_GUIDE.md
Normal file
148
voicellmcloud/Client/voice_drone_assistant/docs/PROJECT_GUIDE.md
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# voice_drone_assistant — 项目说明与配置指南
|
||||||
|
|
||||||
|
面向部署与二次开发:**目录结构**、**配置文件用法**、**启动与日常操作**、**与云端/飞控的关系**。**外场统一部署与双终端启动顺序**见 **`docs/DEPLOYMENT_AND_OPERATIONS.md`**;协议细节以 `docs/llmcon.md` 为准。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 项目做什么
|
||||||
|
|
||||||
|
- **麦克风** → 预处理(降噪/AGC)→ **VAD 切段** → **SenseVoice STT** → **唤醒词**
|
||||||
|
- **关键词起飞(offboard 演示,默认关闭)**:`system.yaml` → **`assistant.local_keyword_takeoff_enabled`** 或 **`ROCKET_LOCAL_KEYWORD_TAKEOFF=1`** 开启后,`keywords.yaml` 里 **`takeoff` 词表**(如「起飞演示」)→ 提示音 + offboard 脚本;飞控主路径推荐 **云端 `flight_intent` + ROS 伴飞桥**
|
||||||
|
- **其它语音**:本地 **Qwen + Kokoro**,或 **云端 WebSocket**(LLM + TTS 上云,见 `cloud_voice`)
|
||||||
|
- 可选通过 **TCP Socket** 下发结构化飞控命令(`VoiceCommandRecognizer` 路径;`TakeoffPrintRecognizer` 默认不在启动时连 Socket,飞控多为云端 JSON + 可选 `ROCKET_CLOUD_EXECUTE_FLIGHT`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 目录结构(仓库根 = `voice_drone_assistant/`)
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `main.py` | 程序入口(会 `chdir` 到本目录并跑 `voice_drone.main_app`) |
|
||||||
|
| `with_system_alsa.sh` | 在 Conda/残缺 ALSA 环境下修正 `LD_LIBRARY_PATH`,建议始终包一层启动 |
|
||||||
|
| `requirements.txt` | Python 依赖(含 `websocket-client` 等) |
|
||||||
|
| **`voice_drone/main_app.py`** | 主流程:唤醒、问候/快路径、关麦、LLM/云端、TTS、offboard |
|
||||||
|
| **`voice_drone/core/`** | 音频采集、预处理、VAD、STT、TTS、Socket、云端 WS、唤醒、命令、文本预处理、配置加载 |
|
||||||
|
| **`voice_drone/flight_bridge/`** | 伴飞桥(ROS1+MAVROS):`flight_intent` → 飞控;说明见 **`docs/FLIGHT_BRIDGE_ROS1.md`** |
|
||||||
|
| **`voice_drone/config/`** | 各类 YAML,见下文「配置文件」 |
|
||||||
|
| **`voice_drone/logging_/`** | 日志与彩色输出 |
|
||||||
|
| **`voice_drone/tools/`** | `config_loader` 等工具 |
|
||||||
|
| **`docs/`** | `PROJECT_GUIDE.md`(本文)、`llmcon.md`(云端协议)、`clientguide.md`(联调与示例) |
|
||||||
|
| **`scripts/`** | `run_px4_offboard_one_terminal.sh`;**伴飞桥** `run_flight_bridge_with_mavros.sh`(含 MAVROS)、`run_flight_intent_bridge_ros1.sh`(仅桥);另有 `generate_wake_greeting_wav.py`、`bundle_for_device.sh` |
|
||||||
|
| **`assets/tts_cache/`** | 唤醒问候等预生成 WAV(可自动生成) |
|
||||||
|
| **`models/`** | STT/TTS/VAD ONNX 等(需自备或 bundle,见 `models/README.txt`) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 配置文件一览
|
||||||
|
|
||||||
|
配置由 `voice_drone/core/configuration.py` 在进程启动时读入;主文件为 **`voice_drone/config/system.yaml`**(路径相对 **`voice_drone_assistant` 根目录**)。
|
||||||
|
|
||||||
|
| 文件 | 作用 |
|
||||||
|
|------|------|
|
||||||
|
| **`system.yaml`** | **总控**:`audio`(采样、设备、AGC、降噪)、`vad`、`stt`、`tts`、`cloud_voice`、`socket_server`、`text_preprocessor`、`recognizer`(VAD 能量门槛、尾静音、问候/TTS 关麦等) |
|
||||||
|
| **`wake_word.yaml`** | 唤醒词主词、变体、模糊/部分匹配策略 |
|
||||||
|
| **`keywords.yaml`** | 命令关键词与同义词(供文本预处理映射到 `Command`) |
|
||||||
|
| **`command_.yaml`** | 各飞行动作默认 `distance/speed/duration`(与 `Command` 联动) |
|
||||||
|
| **`cloud_voice_px4_context.yaml`** | 云端 **`session.start.client` 扩展**:`vehicle_class`、`mav_type`、`default_setpoint_frame`、`extras` 等,供服务端 LLM 生成 PX4 相关指令;路径在 `system.yaml` → `cloud_voice.px4_context_file`,也可用环境变量 **`ROCKET_CLOUD_PX4_CONTEXT_FILE`** 覆盖 |
|
||||||
|
|
||||||
|
修改 YAML 后需**重启** `main.py` 生效(`SYSTEM_CLOUD_VOICE_PX4_CONTEXT` 等在 import 时加载一次)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. `system.yaml` 常用区块(索引)
|
||||||
|
|
||||||
|
- **`audio`**:采样率、`frame_size`、`input_device_index`(`null` 则枚举设备)、`prefer_stereo_capture`(ES8388 等)、`noise_reduce`、`agc*`、`agc_release_alpha`
|
||||||
|
- **`vad`**:Silero 用阈值、`end_frame` 等(能量 VAD 时部分由 `recognizer` 覆盖)
|
||||||
|
- **`stt`**:SenseVoice 模型路径、ORT 线程等
|
||||||
|
- **`tts`**:Kokoro 目录、音色 `voice`、`speed`、`output_device`、`playback_*`
|
||||||
|
- **`cloud_voice`**:`enabled`、`server_url`、`auth_token`、`device_id`、`timeout`、`fallback_to_local`、`px4_context_file`
|
||||||
|
- **`socket_server`**:试飞控 TCP 地址、`reconnect_interval`、`max_retries`(`-1` 为断线持续重连直至成功)
|
||||||
|
- **`recognizer`**:`trailing_silence_seconds`、`vad_backend`(`energy`/`silero`)、`energy_vad_*`、`energy_vad_utt_peak_decay`、`energy_vad_end_peak_ratio`、`pre_speech_max_seconds`、`ack_pause_mic_for_playback`、应答 TTS 等
|
||||||
|
|
||||||
|
更细的参数含义以各 YAML 内注释为准。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 系统使用方式
|
||||||
|
|
||||||
|
### 5.1 推荐启动命令
|
||||||
|
|
||||||
|
在 **`voice_drone_assistant` 根目录**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash with_system_alsa.sh python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
或使用模块方式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash with_system_alsa.sh python -m voice_drone.main_app
|
||||||
|
```
|
||||||
|
|
||||||
|
录音设备:**首次**可交互选择;非交互时可设 `ROCKET_INPUT_DEVICE_INDEX` 或使用 `main.py --input-index N` / `--non-interactive`(详见 `main_app` 内 `argparse` 与文件头注释)。
|
||||||
|
|
||||||
|
### 5.2 典型工作流(默认 `TakeoffPrintRecognizer`)
|
||||||
|
|
||||||
|
1. 说唤醒词(如「无人机」);若**同句带指令**,会**跳过问候与滴声**,直接关麦处理:命中 `keywords.yaml` 的 **takeoff** 则 offboard,否则走 LLM/云端。
|
||||||
|
2. 若**只唤醒**,则问候(或缓存 WAV)+ 可选滴声 → 再说**一句**指令。
|
||||||
|
3. 云端模式:指令以文本上云,TTS 多为服务端 PCM;本地模式:Qwen 推理 + Kokoro 播报。
|
||||||
|
|
||||||
|
### 5.3 云端语音(可选)
|
||||||
|
|
||||||
|
- `system.yaml` 里 `cloud_voice.enabled: true`,或环境变量 **`ROCKET_CLOUD_VOICE=1`**
|
||||||
|
- **`ROCKET_CLOUD_WS_URL`**、`ROCKET_CLOUD_AUTH_TOKEN`、可选 **`ROCKET_CLOUD_DEVICE_ID`**(可覆盖 yaml)
|
||||||
|
- PX4 语境:见 `cloud_voice_px4_context.yaml` / **`ROCKET_CLOUD_PX4_CONTEXT_FILE`**
|
||||||
|
- 协议与消息类型: **`docs/llmcon.md`**
|
||||||
|
- 飞控 JSON 是否机端执行: **`ROCKET_CLOUD_EXECUTE_FLIGHT=1`**;走 ROS 伴飞桥时再设 **`ROCKET_FLIGHT_INTENT_ROS_BRIDGE=1`**(详见 **`docs/DEPLOYMENT_AND_OPERATIONS.md`**)
|
||||||
|
|
||||||
|
### 5.4 本地大模型与 TTS
|
||||||
|
|
||||||
|
- GGUF:`cache/` 默认路径或 **`ROCKET_LLM_GGUF`**
|
||||||
|
- 关闭对话:**`ROCKET_LLM_DISABLE=1`**
|
||||||
|
- 流式输出:**`ROCKET_LLM_STREAM=0`** 可改为整段生成后再播(调试)
|
||||||
|
- 详细列表见 **`voice_drone/main_app.py` 文件头部注释**。
|
||||||
|
|
||||||
|
### 5.5 其它实用环境变量(摘录)
|
||||||
|
|
||||||
|
| 变量 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `ROCKET_ENERGY_VAD` | `1` 时使用能量 VAD(板载麦常见) |
|
||||||
|
| `ROCKET_PRINT_STT` / `ROCKET_PRINT_VAD` | 终端打印 STT/VAD 诊断 |
|
||||||
|
| `ROCKET_CLOUD_TURN_RETRIES` | 云端 WS 单轮失败重连重试次数(默认 3) |
|
||||||
|
| `ROCKET_PRINT_LLM_STREAM` | 云端流式字 `llm.text_delta` 打印到终端 |
|
||||||
|
| `ROCKET_WAKE_PROMPT_BEEP` | `0` 关闭问候后滴声 |
|
||||||
|
| `ROCKET_MIC_RESTART_SETTLE_MS` | 播完 TTS 恢复麦克风后的等待毫秒 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 相关文档与代码入口
|
||||||
|
|
||||||
|
| 文档 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| **`README.md`** | 简版说明、bundle 到香橙派、与原仓库关系 |
|
||||||
|
| **`docs/DEPLOYMENT_AND_OPERATIONS.md`** | **部署与外场启动**:拓扑、`ROS_MASTER_URI`、双终端启动顺序、环境变量速查、联调 |
|
||||||
|
| **`docs/PROJECT_GUIDE.md`** | 本文:目录、配置、使用方式总览 |
|
||||||
|
| **`docs/FLIGHT_BRIDGE_ROS1.md`** | ROS1 伴飞桥、MAVROS、`/input`、`rostopic pub` |
|
||||||
|
| **`docs/llmcon.md`** | 云端 WebSocket 消息类型与客户端约定 |
|
||||||
|
| **`docs/CLOUD_VOICE_FLIGHT_CONFIRM_v1.md`** | 云端 **`dialog_result` v1**(`protocol=cloud_voice_dialog_v1`,闲聊/飞控分流 + `confirm`) |
|
||||||
|
|
||||||
|
| 能力 | 主要代码 |
|
||||||
|
|------|-----------|
|
||||||
|
| 音频采集/AGC | `voice_drone/core/audio.py` |
|
||||||
|
| 能量/Silero VAD | `voice_drone/core/recognizer.py`、`voice_drone/core/vad.py` |
|
||||||
|
| STT | `voice_drone/core/stt.py` |
|
||||||
|
| 本地 LLM 提示词 | `voice_drone/core/qwen_intent_chat.py`(`FLIGHT_INTENT_CHAT_SYSTEM`) |
|
||||||
|
| 云端会话 | `voice_drone/core/cloud_voice_client.py` |
|
||||||
|
| 主流程 | `voice_drone/main_app.py` |
|
||||||
|
| 配置聚合 | `voice_drone/core/configuration.py` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 版本与维护
|
||||||
|
|
||||||
|
- 配置项会随功能迭代增加;若与运行日志或 `llmcon` 不一致,以**当前仓库 YAML + 代码**为准。
|
||||||
|
- 新增仅与云端相关的字段时,请同时通知服务端解析 **`session.start.client`**(含 PX4 扩展块)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档版本:与仓库同步维护;更新日期见 Git 提交。*
|
||||||
29
voicellmcloud/Client/voice_drone_assistant/main.py
Normal file
29
voicellmcloud/Client/voice_drone_assistant/main.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""入口:请在工程根目录 voice_drone_assistant 下运行。
|
||||||
|
|
||||||
|
bash with_system_alsa.sh python main.py
|
||||||
|
|
||||||
|
或使用包方式:python -m voice_drone.main_app(需先 cd 到本目录)。"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parent
|
||||||
|
if str(ROOT) not in sys.path:
|
||||||
|
sys.path.insert(0, str(ROOT))
|
||||||
|
try:
|
||||||
|
os.chdir(ROOT)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
from voice_drone.core.portaudio_env import fix_ld_path_for_portaudio
|
||||||
|
|
||||||
|
fix_ld_path_for_portaudio()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from voice_drone.main_app import main
|
||||||
|
|
||||||
|
main()
|
||||||
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
Revision:master,CreatedAt:1751839966
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
license: apache-2.0
|
||||||
|
library_name: transformers.js
|
||||||
|
language:
|
||||||
|
- en
|
||||||
|
- zh
|
||||||
|
base_model:
|
||||||
|
- hexgrad/Kokoro-82M-v1.1-zh
|
||||||
|
pipeline_tag: text-to-speech
|
||||||
|
---
|
||||||
|
|
||||||
|
# Kokoro TTS
|
||||||
|
|
||||||
|
Kokoro is a frontier TTS model for its size of 82 million parameters (text in/audio out).
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"model_type": "style_text_to_speech_2"
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"framework": "pytorch", "task": "others", "allow_remote": true}
|
||||||
@ -0,0 +1,232 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0",
|
||||||
|
"truncation": null,
|
||||||
|
"padding": null,
|
||||||
|
"added_tokens": [],
|
||||||
|
"normalizer": {
|
||||||
|
"type": "Replace",
|
||||||
|
"pattern": {
|
||||||
|
"Regex": "[^ !\"(),./12345:;?AIOQRSTWYabcdefhijklmnopqrstuvwxyz\u00e6\u00e7\u00f0\u00f8\u014b\u0153\u0250\u0251\u0252\u0254\u0255\u0256\u0259\u025b\u025c\u025f\u0261\u0263\u0268\u026a\u026f\u0270\u0272\u0273\u0274\u0278\u0279\u027d\u027e\u0281\u0282\u0283\u0288\u028a\u028b\u028c\u028e\u0292\u0294\u029d\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02b0\u02b2\u02c8\u02cc\u02d0\u0303\u03b2\u03b8\u03c7\u1d4a\u1d5d\u1d7b\u2014\u201c\u201d\u2026\u3105\u3106\u3107\u3108\u3109\u310a\u310b\u310c\u310d\u310e\u310f\u3110\u3111\u3112\u3113\u3114\u3115\u3116\u3117\u3118\u3119\u311a\u311b\u311c\u311d\u311e\u311f\u3120\u3121\u3122\u3123\u3124\u3125\u3126\u3127\u3128\u3129\u312d\u4e07\u4e2d\u4e3a\u4e91\u5143\u5341\u538b\u53c8\u5916\u5e94\u6211\u6587\u6708\u738b\u74ee\u7528\u7a75\u8981\u8a00\u9633\u9634]"
|
||||||
|
},
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"pre_tokenizer": {
|
||||||
|
"type": "Split",
|
||||||
|
"pattern": {
|
||||||
|
"Regex": ""
|
||||||
|
},
|
||||||
|
"behavior": "Isolated",
|
||||||
|
"invert": false
|
||||||
|
},
|
||||||
|
"post_processor": {
|
||||||
|
"type": "TemplateProcessing",
|
||||||
|
"single": [
|
||||||
|
{
|
||||||
|
"SpecialToken": {
|
||||||
|
"id": "$",
|
||||||
|
"type_id": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Sequence": {
|
||||||
|
"id": "A",
|
||||||
|
"type_id": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SpecialToken": {
|
||||||
|
"id": "$",
|
||||||
|
"type_id": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"special_tokens": {
|
||||||
|
"$": {
|
||||||
|
"id": "$",
|
||||||
|
"ids": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"tokens": [
|
||||||
|
"$"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"decoder": null,
|
||||||
|
"model": {
|
||||||
|
"vocab": {
|
||||||
|
"$": 0,
|
||||||
|
";": 1,
|
||||||
|
":": 2,
|
||||||
|
",": 3,
|
||||||
|
".": 4,
|
||||||
|
"!": 5,
|
||||||
|
"?": 6,
|
||||||
|
"/": 7,
|
||||||
|
"\u2014": 9,
|
||||||
|
"\u2026": 10,
|
||||||
|
"\"": 11,
|
||||||
|
"(": 12,
|
||||||
|
")": 13,
|
||||||
|
"\u201c": 14,
|
||||||
|
"\u201d": 15,
|
||||||
|
" ": 16,
|
||||||
|
"\u0303": 17,
|
||||||
|
"\u02a3": 18,
|
||||||
|
"\u02a5": 19,
|
||||||
|
"\u02a6": 20,
|
||||||
|
"\u02a8": 21,
|
||||||
|
"\u1d5d": 22,
|
||||||
|
"\u3113": 23,
|
||||||
|
"A": 24,
|
||||||
|
"I": 25,
|
||||||
|
"\u3105": 30,
|
||||||
|
"O": 31,
|
||||||
|
"\u3106": 32,
|
||||||
|
"Q": 33,
|
||||||
|
"R": 34,
|
||||||
|
"S": 35,
|
||||||
|
"T": 36,
|
||||||
|
"\u3107": 37,
|
||||||
|
"\u3108": 38,
|
||||||
|
"W": 39,
|
||||||
|
"\u3109": 40,
|
||||||
|
"Y": 41,
|
||||||
|
"\u1d4a": 42,
|
||||||
|
"a": 43,
|
||||||
|
"b": 44,
|
||||||
|
"c": 45,
|
||||||
|
"d": 46,
|
||||||
|
"e": 47,
|
||||||
|
"f": 48,
|
||||||
|
"\u310a": 49,
|
||||||
|
"h": 50,
|
||||||
|
"i": 51,
|
||||||
|
"j": 52,
|
||||||
|
"k": 53,
|
||||||
|
"l": 54,
|
||||||
|
"m": 55,
|
||||||
|
"n": 56,
|
||||||
|
"o": 57,
|
||||||
|
"p": 58,
|
||||||
|
"q": 59,
|
||||||
|
"r": 60,
|
||||||
|
"s": 61,
|
||||||
|
"t": 62,
|
||||||
|
"u": 63,
|
||||||
|
"v": 64,
|
||||||
|
"w": 65,
|
||||||
|
"x": 66,
|
||||||
|
"y": 67,
|
||||||
|
"z": 68,
|
||||||
|
"\u0251": 69,
|
||||||
|
"\u0250": 70,
|
||||||
|
"\u0252": 71,
|
||||||
|
"\u00e6": 72,
|
||||||
|
"\u310b": 73,
|
||||||
|
"\u310c": 74,
|
||||||
|
"\u03b2": 75,
|
||||||
|
"\u0254": 76,
|
||||||
|
"\u0255": 77,
|
||||||
|
"\u00e7": 78,
|
||||||
|
"\u310d": 79,
|
||||||
|
"\u0256": 80,
|
||||||
|
"\u00f0": 81,
|
||||||
|
"\u02a4": 82,
|
||||||
|
"\u0259": 83,
|
||||||
|
"\u310e": 84,
|
||||||
|
"\u3126": 85,
|
||||||
|
"\u025b": 86,
|
||||||
|
"\u025c": 87,
|
||||||
|
"\u310f": 88,
|
||||||
|
"\u3110": 89,
|
||||||
|
"\u025f": 90,
|
||||||
|
"\u3111": 91,
|
||||||
|
"\u0261": 92,
|
||||||
|
"\u3112": 93,
|
||||||
|
"\u3114": 94,
|
||||||
|
"\u3115": 95,
|
||||||
|
"\u3117": 96,
|
||||||
|
"\u3118": 97,
|
||||||
|
"\u3119": 98,
|
||||||
|
"\u6708": 99,
|
||||||
|
"\u311a": 100,
|
||||||
|
"\u0268": 101,
|
||||||
|
"\u026a": 102,
|
||||||
|
"\u029d": 103,
|
||||||
|
"\u311b": 104,
|
||||||
|
"\u311d": 105,
|
||||||
|
"\u311e": 106,
|
||||||
|
"\u311f": 107,
|
||||||
|
"\u3120": 108,
|
||||||
|
"\u3121": 109,
|
||||||
|
"\u026f": 110,
|
||||||
|
"\u0270": 111,
|
||||||
|
"\u014b": 112,
|
||||||
|
"\u0273": 113,
|
||||||
|
"\u0272": 114,
|
||||||
|
"\u0274": 115,
|
||||||
|
"\u00f8": 116,
|
||||||
|
"\u3122": 117,
|
||||||
|
"\u0278": 118,
|
||||||
|
"\u03b8": 119,
|
||||||
|
"\u0153": 120,
|
||||||
|
"\u3123": 121,
|
||||||
|
"\u3124": 122,
|
||||||
|
"\u0279": 123,
|
||||||
|
"\u3125": 124,
|
||||||
|
"\u027e": 125,
|
||||||
|
"\u3116": 126,
|
||||||
|
"\u3127": 127,
|
||||||
|
"\u0281": 128,
|
||||||
|
"\u027d": 129,
|
||||||
|
"\u0282": 130,
|
||||||
|
"\u0283": 131,
|
||||||
|
"\u0288": 132,
|
||||||
|
"\u02a7": 133,
|
||||||
|
"\u3128": 134,
|
||||||
|
"\u028a": 135,
|
||||||
|
"\u028b": 136,
|
||||||
|
"\u3129": 137,
|
||||||
|
"\u028c": 138,
|
||||||
|
"\u0263": 139,
|
||||||
|
"\u311c": 140,
|
||||||
|
"\u312d": 141,
|
||||||
|
"\u03c7": 142,
|
||||||
|
"\u028e": 143,
|
||||||
|
"\u5341": 144,
|
||||||
|
"\u538b": 145,
|
||||||
|
"\u8a00": 146,
|
||||||
|
"\u0292": 147,
|
||||||
|
"\u0294": 148,
|
||||||
|
"\u9633": 149,
|
||||||
|
"\u8981": 150,
|
||||||
|
"\u9634": 151,
|
||||||
|
"\u5e94": 152,
|
||||||
|
"\u7528": 153,
|
||||||
|
"\u53c8": 154,
|
||||||
|
"\u4e2d": 155,
|
||||||
|
"\u02c8": 156,
|
||||||
|
"\u02cc": 157,
|
||||||
|
"\u02d0": 158,
|
||||||
|
"\u7a75": 159,
|
||||||
|
"\u5916": 160,
|
||||||
|
"\u4e07": 161,
|
||||||
|
"\u02b0": 162,
|
||||||
|
"\u738b": 163,
|
||||||
|
"\u02b2": 164,
|
||||||
|
"\u4e3a": 165,
|
||||||
|
"\u6587": 166,
|
||||||
|
"\u74ee": 167,
|
||||||
|
"\u6211": 168,
|
||||||
|
"3": 169,
|
||||||
|
"5": 170,
|
||||||
|
"1": 171,
|
||||||
|
"2": 172,
|
||||||
|
"4": 173,
|
||||||
|
"\u5143": 175,
|
||||||
|
"\u4e91": 176,
|
||||||
|
"\u1d7b": 177
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"model_max_length": 512,
|
||||||
|
"pad_token": "$",
|
||||||
|
"tokenizer_class": "PreTrainedTokenizer",
|
||||||
|
"unk_token": "$"
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user