Initial commit: 无人机行为规划后端系统

Made-with: Cursor
This commit is contained in:
2026-03-17 10:51:32 +08:00
commit 3ddc2e1ff4
35 changed files with 3219 additions and 0 deletions

View File

@@ -0,0 +1,265 @@
# 无人机行为规划后端系统(重建版)需求说明
> 目标:基于端侧 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 示例。
请从目录结构 + 模块职责开始规划,确认后再逐步生成代码。
```