DroneMind/docs/FLIGHT_INTENT_SCHEMA_v1.md
2026-04-14 09:54:26 +08:00

373 lines
15 KiB
Markdown
Raw 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.

# 云端高层飞控意图 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. **校验**:至少 L1L3有 px4 上下文时做 L4。
3. **执行器**:对 `actions` **单线程顺序**执行;内部每步调用 **翻译器**(见 §10.3)。
4. **遥测与安全**:每步前置检查(模式、解锁、定位、电量、围栏);执行中 watchdog可打断队列。
5. **回执(建议)**ROS 发布 `flight_intent/result` 或写日志/Socketsuccess / 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 或发位置保持 setpointOffboard 路径则发零速/当前位 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`** 对应。