Initial commit: 无人机行为规划后端系统
Made-with: Cursor
This commit is contained in:
265
# 无人机行为规划后端系统(重建版)需求说明.md
Normal file
265
# 无人机行为规划后端系统(重建版)需求说明.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# 无人机行为规划后端系统(重建版)需求说明
|
||||
|
||||
> 目标:基于端侧 Qwen3-4B(llama-server)和行为树,重建一个从自然语言到无人机行为树 JSON 的后端系统,支持未来扩展 RAG 和动态语义地图。
|
||||
|
||||
## 一、总体架构理念(务必遵守)
|
||||
|
||||
1. **大小脑解耦**
|
||||
- 大模型(4B,小模型) = 「大脑」:只做语义理解、意图拆解、行为树结构生成,不直接管起飞/降落/避障。
|
||||
- Python + py_trees + PX4/仿真 = 「小脑」:负责状态机管理、物理安全、控制执行(起飞、悬停、返航等)。
|
||||
|
||||
2. **四层流水线结构**
|
||||
|
||||
- 🔴 Layer 0:感知层(Perception & State)
|
||||
纯代码。维护一个全局状态黑板 `DroneStateBlackboard`,至少包含:
|
||||
- `is_in_air: bool`
|
||||
- `position: {x, y, z}`(ENU)
|
||||
- 后续可扩展电量、模式等。
|
||||
|
||||
- 🟡 Layer 1:意图路由层(Stage 1 Intent Router)
|
||||
调用 LLM 做**极简意图分类和实体抽取**,只输出:
|
||||
- `intents: list[str]`
|
||||
- `entities: dict`
|
||||
并实现 **Fast-Path 短路机制**:
|
||||
- 若指令是纯原子控制(如“起飞”、“降落”、“悬停”),直接由代码执行,不进入规划阶段。
|
||||
|
||||
- 🟢 Layer 2:动态组装与外部计算(Dynamic Composer & MCP/RAG)
|
||||
纯代码。
|
||||
- 根据 `intents` 和 `entities`,从本地 `node_schema.json` 裁剪出**最小必要的节点定义**(行为树节点)。
|
||||
- 使用工具(后续接 RAG)解析地点到坐标(ENU),大模型不做算术。
|
||||
- 生成发给 Stage 2 LLM 的 **精简 System Prompt**。
|
||||
|
||||
- 🔵 Layer 3:宏观行为规划(Stage 2 Macro Planner)
|
||||
调用 LLM(Qwen3-4B):
|
||||
- 输入:Layer 2 生成的 System Prompt + 用户原文(含 RAG 上下文)。
|
||||
- 输出:业务行为树 JSON(**不包含起飞/降落**)。
|
||||
|
||||
- 🟣 Layer 4:执行包装与安全逻辑(Execution Wrapper)
|
||||
纯代码 + py_trees:
|
||||
- 将业务树解析为 py_trees 对象。
|
||||
- 如果 `is_in_air == False`,自动在业务树前面**插入 `[SystemCheck -> Takeoff]` 子树**。
|
||||
- 提供 tick 循环和未来的中断(用户打断、动态重规划)预留。
|
||||
|
||||
---
|
||||
|
||||
## 二、节点定义(给 LLM 的行为树节点池)
|
||||
|
||||
请在 `config/node_schema.json` 定义一个简洁的行为节点池(LLM 可见的动作),结构类似:
|
||||
|
||||
```json
|
||||
{
|
||||
"_instruction": "作为行为树规划器,你只能使用以下定义的节点和参数。",
|
||||
"actions": {
|
||||
"fly_to_waypoint": { "desc": "...", "params": { "x": "float", "y": "float", "z": "float" } },
|
||||
"fly_sequence": { "desc": "...", "params": { "waypoints": "array of {x,y,z}" } },
|
||||
"move_direction": { "desc": "...", "params": { "direction": "front|back|left|right|up|down", "distance": "float" } },
|
||||
"search_pattern": { "desc": "...", "params": { "pattern_type": "spiral|grid", "radius": "float", "target_class": "string" } },
|
||||
"rotate_search": { "desc": "...", "params": { "target_class": "string" } },
|
||||
"track_object": { "desc": "...", "params": { "target_class": "string", "track_time": "float" } },
|
||||
"take_photos": { "desc": "...", "params": { "target_class": "string", "count": "int" } },
|
||||
"report_message": { "desc": "...", "params": { "message": "string" } },
|
||||
"manual_confirmation": { "desc": "...", "params": { "prompt_message": "string" } }
|
||||
},
|
||||
"conditions": {
|
||||
"object_detected": { "desc": "...", "params": { "target_class": "string" } }
|
||||
},
|
||||
"control_flow": {
|
||||
"Sequence": { "desc": "...", "params": {}, "requires_children": true },
|
||||
"Selector": { "desc": "...", "params": {}, "requires_children": true },
|
||||
"Parallel": { "desc": "...", "params": { "policy": "success_on_one|success_on_all" }, "requires_children": true }
|
||||
},
|
||||
"decorators": {
|
||||
"Timeout": { "desc": "...", "params": { "max_time": "float" }, "requires_child": true },
|
||||
"Repeat": { "desc": "...", "params": { "times": "int" }, "requires_child": true }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 注意:**起飞/降落等底层动作不要出现在这里**,由 Layer 4 包装硬编码处理。
|
||||
|
||||
---
|
||||
|
||||
## 三、Stage 1 Intent Router 的设计(重点)
|
||||
|
||||
### 1. LLM 提示词(Router System Prompt)
|
||||
|
||||
要求使用简洁、正交的 Intent 集合(避免同义词过多):
|
||||
|
||||
- 原子意图(Atomic Intents):仅用于 Fast-Path
|
||||
- `atomic_takeoff`
|
||||
- `atomic_land`
|
||||
- `atomic_hover`
|
||||
|
||||
- 业务意图(Business Intents)
|
||||
- `fly_task`:所有涉及空间移动/路径/巡逻
|
||||
- `search_task`:搜索/侦查
|
||||
- `track_task`:跟踪
|
||||
- `photo_task`:拍照
|
||||
- `interact_task`:上报/请求确认
|
||||
|
||||
**实体提取要求:**
|
||||
|
||||
- 地点实体统一用 `"locations"`,且必须为列表:
|
||||
- `{"locations": ["大门"]}`
|
||||
- `{"locations": ["大门", "广场"]}`(支持“先去A再去B”)
|
||||
|
||||
- 目标实体用 `"targets"` 列表:
|
||||
- `{"targets": ["汽车", "行人"]}`
|
||||
|
||||
- 其他参数如 `"direction"`, `"distance"` 直接提取。
|
||||
|
||||
### 2. Python 层的“硬编码冲突处理”逻辑
|
||||
|
||||
在 `pipeline/router.py` 中:
|
||||
|
||||
- 定义集合:
|
||||
|
||||
```python
|
||||
ATOMIC_INTENTS = {"atomic_takeoff", "atomic_land", "atomic_hover"}
|
||||
BUSINESS_INTENTS = {"fly_task", "search_task", "track_task", "photo_task", "interact_task"}
|
||||
```
|
||||
|
||||
- 处理流程:
|
||||
|
||||
- 若 `intents` 非空且 **全部属于 ATOMIC_INTENTS**:
|
||||
→ 允许 Fast-Path(直接执行原子命令)。
|
||||
|
||||
- 若 `intents` 同时包含 atomic 和 business(如 `["atomic_takeoff", "fly_task"]`):
|
||||
→ **删除所有 atomic**,仅保留 business,走正常规划(起飞由 Layer 4 自动包装)。
|
||||
|
||||
- 若 `intents` 为空或包含未识别标签(小模型幻觉):
|
||||
→ 兜底为 `["fly_task", "search_task"]`,保证系统不崩。
|
||||
|
||||
---
|
||||
|
||||
## 四、RAG 模块设计(Layer 2 可选扩展)
|
||||
|
||||
### 1. 目录结构
|
||||
|
||||
`src/drone_planning/rag/`:
|
||||
|
||||
- `embedding_client.py`:封装 Qwen Embedding(llama-server 8090)。
|
||||
- `vector_store.py`:ChromaDB 客户端,管理三个 Collection:
|
||||
- `map_db`
|
||||
- `rule_db`
|
||||
- `few_shot_db`
|
||||
- `retriever.py`:`RAGRetriever`:
|
||||
- `dynamic_memory`:热数据表占位(未来语义地图)。
|
||||
- `retrieve_context(intents, entities, user_text) -> dict`
|
||||
- `ingestion.py`:从 `data/knowledge/*.jsonl` 读 NDJSON 灌入 ChromaDB。
|
||||
- `schemas.py`(可选):约定 JSONL 字段结构。
|
||||
|
||||
### 2. JSONL 格式约定(统一用 `.jsonl`,一行一 JSON)
|
||||
|
||||
- `data/knowledge/map_db.jsonl`:
|
||||
|
||||
```json
|
||||
{"document": "喷泉在广场正中央,坐标 x=10, y=20", "location": "喷泉", "x": 10, "y": 20, "z": 0}
|
||||
{"document": "A区是禁飞区,不得进入", "location": "A区", "zone_type": "no_fly"}
|
||||
```
|
||||
|
||||
- `data/knowledge/rule_db.jsonl`:
|
||||
|
||||
```json
|
||||
{"document": "夜间巡逻必须开启热成像", "intent": "search_task", "scene": "night"}
|
||||
{"document": "起飞必须先做系统检查", "intent": "fly_task", "priority": "high"}
|
||||
```
|
||||
|
||||
- `data/knowledge/few_shot_db.jsonl`:
|
||||
|
||||
```json
|
||||
{"document": "飞到大门然后拍照", "intent": "fly_task", "tree_json": "{\"root\": {...}}"}
|
||||
```
|
||||
|
||||
### 3. 检索策略(在 `retriever.py`)
|
||||
|
||||
- 热数据优先(Dynamic Semantic Map):
|
||||
- `dynamic_memory = {"locations": {...}, "targets": {...}}`
|
||||
- 若某 location 在热内存中有坐标,直接返回,**不要查 ChromaDB**。
|
||||
|
||||
- 冷库次之(ChromaDB):
|
||||
- 根据 `entities["locations"]` 和 `intents` 用 metadata + 向量检索,从 `map_db` 和 `rule_db` 获取上下文。
|
||||
- 使用 `user_text` 在 `few_shot_db` 中查 1–2 个相似任务的行为树,作为 few-shot 示例。
|
||||
|
||||
RAG 返回统一结构:
|
||||
|
||||
```python
|
||||
{
|
||||
"map_context": "若干行文本或结构化信息",
|
||||
"rule_context": "规则文本汇总",
|
||||
"few_shot_examples": [
|
||||
{"instruction": "...", "tree_json": {...}},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 与 Composer 集成(`pipeline/composer.py`)
|
||||
|
||||
- 为 `build_system_prompt(...)` 增加参数 `rag_context: dict | None`。
|
||||
- 在 Prompt 中插入三个区块(若非空):
|
||||
- `## RAG 地图上下文`
|
||||
- `## RAG 规则约束`
|
||||
- `## RAG 示例行为树`
|
||||
|
||||
- 坐标解析优先级:
|
||||
1. 动态内存(语义地图,未来接入)。
|
||||
2. RAG 地图(map_db 的 x,y,z)。
|
||||
3. geo.py 的硬编码 `landmark_to_enu()`(兜底,不删除,作为最后一层 fallback)。
|
||||
|
||||
---
|
||||
|
||||
## 五、执行包装层(Layer 4,`execution`)
|
||||
|
||||
### 1. 行为节点实现(`execution/nodes.py`)
|
||||
|
||||
实现继承自 `py_trees.behaviour.Behaviour` 的 Mock 节点:
|
||||
|
||||
- `SystemCheckCondition`
|
||||
- `TakeoffAction`
|
||||
- `LandAction`
|
||||
- `FlyToWaypointAction`
|
||||
- `GenericAction`(兜底)
|
||||
|
||||
目前只打印日志并返回 `SUCCESS`,后续预留 ROS2/PX4 接口。
|
||||
|
||||
### 2. 树包装与 Tick 循环(`execution/tree_wrapper.py`)
|
||||
|
||||
- `parse_json_to_tree(node_dict)`:递归将 Planner 的 JSON 转换为 py_trees 树。
|
||||
- `wrap_and_build_tree(business_tree)`:
|
||||
- 读取 `DroneStateBlackboard.is_in_air`:
|
||||
- 若 `False`:创建 `Sequence("Safe_Execution")`,依次添加:
|
||||
- `SystemCheckCondition()`
|
||||
- `TakeoffAction()`
|
||||
- `business_tree`
|
||||
- 若 `True`:直接返回 `business_tree`。
|
||||
|
||||
---
|
||||
|
||||
## 六、API 接口与 Orchestrator
|
||||
|
||||
- 使用 FastAPI 暴露 `POST /api/plan`:
|
||||
- 输入:`{"text": "用户自然语言指令"}`。
|
||||
- 调用顺序:
|
||||
1. Layer 1 Router:若 Fast-Path,直接返回执行结果。
|
||||
2. 否则,调用 RAG → Composer → Planner → Tree Wrapper,返回行为树 JSON 和日志。
|
||||
|
||||
---
|
||||
|
||||
## 七、请 Cursor 的工作顺序建议
|
||||
|
||||
1. 生成项目目录和基础依赖(`requirements.txt`,`pyproject.toml`)。
|
||||
2. 实现:
|
||||
- `core/blackboard.py`
|
||||
- `llm_client/client.py`(指向 `http://localhost:8080/v1` for chat,`http://localhost:8090/v1` for embeddings 可在 embedding_client 中配置)
|
||||
3. 实现 `config/node_schema.json`。
|
||||
4. 实现 `pipeline/router.py`(含 intents/entities 提取与 Fast-Path 短路 + 冲突处理)。
|
||||
5. 实现 `tools/geo.py`(仅作为 fallback 静态坐标表)。
|
||||
6. 实现 `rag/*`(embedding_client, vector_store, ingestion, retriever)。
|
||||
7. 实现 `pipeline/composer.py` 和 `pipeline/planner.py`(加入 rag_context)。
|
||||
8. 实现 `execution/nodes.py` 和 `execution/tree_wrapper.py`。
|
||||
9. 实现 `api/routes.py` 和 `main.py`。
|
||||
10. 最后补充简单的 `tests/` 或手动 curl 示例。
|
||||
|
||||
请从目录结构 + 模块职责开始规划,确认后再逐步生成代码。
|
||||
```
|
||||
Reference in New Issue
Block a user