Files
DronePlanningV2/# 无人机行为规划后端系统(重建版)需求说明.md
2026-03-17 10:51:32 +08:00

265 lines
10 KiB
Markdown
Raw Permalink 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.
# 无人机行为规划后端系统(重建版)需求说明
> 目标:基于端侧 Qwen3-4Bllama-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
调用 LLMQwen3-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 Embeddingllama-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` 中查 12 个相似任务的行为树,作为 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 示例。
请从目录结构 + 模块职责开始规划,确认后再逐步生成代码。
```