15 KiB
云端高层飞控意图 JSON 规范 v1(完整版)
定位:定义 WebSocket
dialog_result.flight_intent中的语义对象与伴飞侧执行约定,不是 MAVLink 二进制帧。
目标:
- 协议:客户端与云端可 100% 按字段表 strict 解析;禁止用自然语言或
summary驱动机控。- 桥(companion):按本文执行 有序
actions、校验、排队与安全门,再译为 PX4 可接受的模式 / 指令 / Offboard setpoint。- 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[] 通用形式
每个元素:
{ "type": "<ActionType>", "args": { ... } }
| 字段 | 类型 | 必填 |
|---|---|---|
type |
string |
是,取值限于 §3 枚举 |
args |
object |
是,允许为空对象 {};仅允许各小节表中列出的键 |
3. ActionType 与白名单 args
以下 type 仅允许小写。未列出的值在 v1 非法。
3.1 takeoff
| args 键 | 类型 | 必填 | 说明 |
|---|---|---|---|
relative_altitude_m |
number |
否 | 相对起飞点(或飞控定义的 TAKEOFF 参考)的目标高度,单位 米,须 > 0。省略则 完全由机端/飞控缺省参数 决定(与旧版「空 args」语义一致) |
{ "type": "takeoff", "args": {} }
{ "type": "takeoff", "args": { "relative_altitude_m": 5 } }
桥 / ROS 映射提示:PX4 TAKEOFF 模式、MAV_CMD_NAV_TAKEOFF;相对高度常与 MIS_TAKEOFF_ALT 或命令参数结合,以装机参数为准。
3.2 land
| args 键 | 类型 | 必填 | 说明 |
|---|---|---|---|
| — | — | — | v1 无参;降落行为由飞控 AUTO.LAND 等策略决定 |
{ "type": "land", "args": {} }
桥 / ROS 映射提示:AUTO.LAND、MAV_CMD_NAV_LAND;固定翼 / 多旋翼路径不同,由机端处理。
3.3 return_home
{ "type": "return_home", "args": {} }
语义:返航至 Home 并按飞控策略降落或盘旋(与 PX4 RTL 概义一致)。
3.4 hover 与 hold
二者在 v1 语义等价:在当前位置附近保持(多旋翼常见为位置保持;固定翼可能映射为 Loiter,由机端按机型解释)。
| args 键 | 类型 | 必填 | 说明 |
|---|---|---|---|
| — | — | — | 仅 {} 合法;表示进入保持,不隐含持续时间(时长用 §3.6 wait) |
{ "type": "hover", "args": {} }
{ "type": "hold", "args": {} }
约定:同一 actions 序列建议只选 hover 或 hold 一种命名;解析端可映射到同一 PX4 行为。
互操作(非规范首选):个别上游可能错误输出 "args": { "duration": 3 }(秒)。伴飞客户端(如本仓库 flight_intent.py)可在校验时将其折叠为:hover(无 duration)+ wait,与上表典型组合等价;新开发的上游仍应只产 wait。
典型组合(「悬停 3 秒后降落」):
[
{ "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 |
否 | 同上 |
{
"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 写极大值;产品可改小) |
{ "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 → 悬停
{
"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 秒 → 降落
{
"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 返航
{
"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 逻辑分层
- 接入:WebSocket 回调 → 解析
flight_intent;或订阅 ROS Topicflight_intent/json;或 TCP 接收与本文相同的 JSON。 - 校验:至少 L1–L3;有 px4 上下文时做 L4。
- 执行器:对
actions单线程顺序执行;内部每步调用 翻译器(见 §10.3)。 - 遥测与安全:每步前置检查(模式、解锁、定位、电量、围栏);执行中 watchdog;可打断队列。
- 回执(建议):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_intentJSON(保持云侧与机型解耦)。
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 对应。