Compare commits
13 Commits
pipeline-l
...
function_c
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d8412bcb6 | |||
| 43d69d5a99 | |||
|
|
3c03749edf | ||
|
|
e164148c5c | ||
|
|
b12339ff73 | ||
| 410d2e01e4 | |||
| 070e4f579d | |||
| dd066057b0 | |||
| 59c52f6b99 | |||
| bce9203e01 | |||
| 333fad40ac | |||
| 9538757047 | |||
| ffb9aee730 |
452
PIPELINE_GUIDE.md
Normal file
452
PIPELINE_GUIDE.md
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
# DronePlanning 处理 Pipeline 说明
|
||||||
|
|
||||||
|
本文档说明当前后端从自然语言输入到计划 JSON 输出的完整处理流程,以及可自定义修改点。
|
||||||
|
|
||||||
|
## 1. 总体流程
|
||||||
|
|
||||||
|
入口为 `POST /generate_plan`,主链路由 `GenerationOrchestrator` 编排:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
api[main.py /generate_plan] --> gen[py_tree_generator.generate]
|
||||||
|
gen --> orch[GenerationOrchestrator]
|
||||||
|
orch --> s1[Stage1 TaskUnderstanding]
|
||||||
|
orch --> s2[Stage2 ContextBinding]
|
||||||
|
orch --> s3[Stage3 BTPlanning]
|
||||||
|
orch --> s4[Stage4 ValidateAndPostprocess]
|
||||||
|
s4 --> out[返回 py_tree JSON]
|
||||||
|
```
|
||||||
|
|
||||||
|
对应代码:
|
||||||
|
|
||||||
|
- `backend_service/src/main.py`
|
||||||
|
- `backend_service/src/py_tree_generator.py`
|
||||||
|
- `backend_service/src/pipeline/orchestrator.py`
|
||||||
|
- `backend_service/src/pipeline/stages.py`
|
||||||
|
|
||||||
|
## 2. Stage1:任务理解(TaskUnderstanding)
|
||||||
|
|
||||||
|
功能:
|
||||||
|
|
||||||
|
- 场景分类:`simple / scene1 / scene4`
|
||||||
|
- 意图推断:`intent_type`
|
||||||
|
- 风险标记:`risk_flags`(例如是否需要人工确认、是否涉及相对方位)
|
||||||
|
|
||||||
|
核心代码:
|
||||||
|
|
||||||
|
- `backend_service/src/llm/gateway.py::classify_scene()`
|
||||||
|
- `backend_service/src/pipeline/stages.py::_infer_intent_type()`
|
||||||
|
- `backend_service/src/pipeline/stages.py::_extract_risk_flags()`
|
||||||
|
- 数据契约:`backend_service/src/pipeline/contracts.py::TaskUnderstanding`
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
- 分类模型可启用 thinking(由 `STAGE1_ENABLE_THINKING` 控制)。
|
||||||
|
- 该阶段不依赖节点字典,避免循环依赖。
|
||||||
|
|
||||||
|
### 2.1 输入格式
|
||||||
|
|
||||||
|
`stage1_task_understanding(user_prompt: str)` 仅接受原始用户指令字符串。
|
||||||
|
|
||||||
|
示例输入:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"user_prompt": "无人机当前在地面,到广场查找绿色公交车,找到后拍照。"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 输出格式(TaskUnderstanding)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scene_mode": "scene4",
|
||||||
|
"intent_type": "search_and_photo",
|
||||||
|
"requires_relative_target": false,
|
||||||
|
"entities": {
|
||||||
|
"raw_prompt": "无人机当前在地面,到广场查找绿色公交车,找到后拍照。"
|
||||||
|
},
|
||||||
|
"risk_flags": [],
|
||||||
|
"constraints": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
|
||||||
|
- `scene_mode`: `simple | scene1 | scene4`
|
||||||
|
- `intent_type`: 当前规则推导出的任务意图标签
|
||||||
|
- `requires_relative_target`: 是否检测到相对方位需求
|
||||||
|
- `entities`: 当前为轻量占位(最小包含 `raw_prompt`)
|
||||||
|
- `risk_flags`: 风险标记列表(如 `needs_manual_confirmation`)
|
||||||
|
- `constraints`: 约束占位(当前为空对象)
|
||||||
|
|
||||||
|
## 3. Stage2:上下文绑定(ContextBinding)
|
||||||
|
|
||||||
|
功能:
|
||||||
|
|
||||||
|
- 按场景动态决定检索范围(location/pattern/rules)
|
||||||
|
- 从多知识库并行检索并汇总
|
||||||
|
- 相对目标提取(`relative_refs`)
|
||||||
|
- 预计算航点(`precomputed_waypoints`,MVP)
|
||||||
|
- 基于意图与风险推导 `required_actions`
|
||||||
|
|
||||||
|
核心代码:
|
||||||
|
|
||||||
|
- `backend_service/src/retrieval/retriever.py::UnifiedRetriever`
|
||||||
|
- `backend_service/src/retrieval/adapters/chroma_adapter.py`
|
||||||
|
- `backend_service/src/llm/tool_runtime.py`
|
||||||
|
- `backend_service/src/pipeline/stages.py::stage2_context_binding()`
|
||||||
|
- 数据契约:`backend_service/src/pipeline/contracts.py::ContextBinding`
|
||||||
|
|
||||||
|
多知识库策略:
|
||||||
|
|
||||||
|
- 主集合:`location_kb`、`pattern_kb`、`rules_kb`
|
||||||
|
- 兼容集合:`drone_docs`
|
||||||
|
- 若主集合无结果,会尝试从 `drone_docs` + `kb_type` 过滤回退查询
|
||||||
|
|
||||||
|
### 3.1 输入格式
|
||||||
|
|
||||||
|
该阶段接收:
|
||||||
|
|
||||||
|
- `user_prompt: str`
|
||||||
|
- Stage1 输出 `TaskUnderstanding`
|
||||||
|
|
||||||
|
示例输入:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"user_prompt": "无人机当前在空中,去广场南边40米,持续监控5分钟,发现人就拍照。",
|
||||||
|
"understanding": {
|
||||||
|
"scene_mode": "scene4",
|
||||||
|
"intent_type": "patrol_or_monitor",
|
||||||
|
"requires_relative_target": false,
|
||||||
|
"risk_flags": [],
|
||||||
|
"entities": {"raw_prompt": "无人机当前在空中,去广场南边40米,持续监控5分钟,发现人就拍照。"},
|
||||||
|
"constraints": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 输出格式(ContextBinding)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"location_context": "地点:广场,坐标(x=120,y=30,z=0)...",
|
||||||
|
"pattern_context": "示例:先到达命名地点,再监控,再条件触发拍照...",
|
||||||
|
"rules_context": "",
|
||||||
|
"citations": {
|
||||||
|
"location": ["..."],
|
||||||
|
"pattern": ["..."],
|
||||||
|
"rules": []
|
||||||
|
},
|
||||||
|
"resolved_refs": {},
|
||||||
|
"precomputed_waypoints": [
|
||||||
|
{"x": 160.0, "y": 30.0, "z": 10.0}
|
||||||
|
],
|
||||||
|
"relative_refs": [],
|
||||||
|
"required_actions": [
|
||||||
|
"Sequence",
|
||||||
|
"fly_to_waypoint",
|
||||||
|
"loiter",
|
||||||
|
"object_detect",
|
||||||
|
"object_detected",
|
||||||
|
"take_photos"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
|
||||||
|
- `*_context`: 分知识域拼接后的文本上下文
|
||||||
|
- `citations`: 每个知识域的原始命中文档片段
|
||||||
|
- `precomputed_waypoints`: Stage2 静态可解析时的预计算坐标
|
||||||
|
- `relative_refs`: 相对目标结构化描述
|
||||||
|
- `required_actions`: 后续用于节点裁剪注入的动作白名单
|
||||||
|
|
||||||
|
## 4. Stage3:BT 生成(BTPlanning)
|
||||||
|
|
||||||
|
功能:
|
||||||
|
|
||||||
|
- 组装 prompt(骨架 + 节点裁剪 + 示例 + 规则 + 检索结果)
|
||||||
|
- 调用对应模型生成严格 JSON
|
||||||
|
- 解析模型响应(含 reasoning 提取)
|
||||||
|
|
||||||
|
核心代码:
|
||||||
|
|
||||||
|
- `backend_service/src/prompting/composer.py::PromptComposer`
|
||||||
|
- `backend_service/src/llm/gateway.py::generate_json()`
|
||||||
|
- `backend_service/src/llm/response_parser.py`
|
||||||
|
- `backend_service/src/pipeline/stages.py::stage3_bt_planning()`
|
||||||
|
- 数据契约:`backend_service/src/pipeline/contracts.py::BTDraft`
|
||||||
|
|
||||||
|
关键行为:
|
||||||
|
|
||||||
|
- simple 模式与复杂模式使用不同客户端/模型配置
|
||||||
|
- Stage3 强制关闭 thinking,强制 `response_format=json_object`
|
||||||
|
- 节点定义采用裁剪注入(非全量注入)
|
||||||
|
|
||||||
|
### 4.1 输入格式
|
||||||
|
|
||||||
|
该阶段接收:
|
||||||
|
|
||||||
|
- `user_prompt: str`
|
||||||
|
- `TaskUnderstanding`
|
||||||
|
- `ContextBinding`
|
||||||
|
|
||||||
|
核心输入(示例):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scene_mode": "scene4",
|
||||||
|
"intent_type": "search_and_photo",
|
||||||
|
"required_actions": ["Sequence", "fly_to_waypoint", "rotate_search", "object_detected", "take_photos"],
|
||||||
|
"risk_flags": [],
|
||||||
|
"context_blocks": {
|
||||||
|
"location": "地点:广场...",
|
||||||
|
"pattern": "示例:先到达再搜索...",
|
||||||
|
"rules": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 输出格式(BTDraft)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"system_prompt": "...(裁剪后的系统提示词)...",
|
||||||
|
"user_prompt": "原始指令 + 参考知识增强段",
|
||||||
|
"allowed_nodes": {
|
||||||
|
"actions": ["fly_to_waypoint", "rotate_search", "take_photos"],
|
||||||
|
"conditions": ["object_detected"]
|
||||||
|
},
|
||||||
|
"llm_raw_json": {
|
||||||
|
"root": {
|
||||||
|
"type": "Sequence",
|
||||||
|
"name": "Sequence",
|
||||||
|
"children": [
|
||||||
|
{"type": "action", "name": "fly_to_waypoint", "params": {"x": 120, "y": 30, "z": 10, "acceptance_radius": 2}},
|
||||||
|
{"type": "action", "name": "rotate_search", "params": {"target_class": "bus"}},
|
||||||
|
{"type": "condition", "name": "object_detected", "params": {"target_class": "bus"}},
|
||||||
|
{"type": "action", "name": "take_photos", "params": {"target_class": "bus", "track_time": 8}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reasoning_text": null,
|
||||||
|
"final_prompt": "=== System Prompt === ... === User Prompt === ..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
|
||||||
|
- `system_prompt/user_prompt`: 实际发给模型的提示词
|
||||||
|
- `allowed_nodes`: 节点裁剪结果(用于调试与复盘)
|
||||||
|
- `llm_raw_json`: 模型返回并解析后的原始计划 JSON
|
||||||
|
- `reasoning_text`: 可选推理文本(若模型返回)
|
||||||
|
- `final_prompt`: 完整组合记录(便于离线排查)
|
||||||
|
|
||||||
|
## 5. Stage4:校验与后处理(ValidateAndPostprocess)
|
||||||
|
|
||||||
|
功能:
|
||||||
|
|
||||||
|
- JSON Schema 校验(simple / complex)
|
||||||
|
- 注入 `plan_id`、`visualization_url`、`final_prompt`
|
||||||
|
- 保存推理链与历史记录
|
||||||
|
- 在复杂场景下注入 `context.relative_refs`(及可选 `context.resolved_refs`)
|
||||||
|
|
||||||
|
核心代码:
|
||||||
|
|
||||||
|
- `backend_service/src/validation/validator.py`
|
||||||
|
- `backend_service/src/validation/schema_provider.py`
|
||||||
|
- `backend_service/src/pipeline/stages.py::stage4_validate_and_postprocess()`
|
||||||
|
- `backend_service/src/py_tree_generator.py::render_visualization()`
|
||||||
|
- `backend_service/src/py_tree_generator.py::_save_history()`
|
||||||
|
|
||||||
|
### 5.1 输入格式
|
||||||
|
|
||||||
|
该阶段接收:
|
||||||
|
|
||||||
|
- `user_prompt: str`
|
||||||
|
- `TaskUnderstanding`
|
||||||
|
- `ContextBinding`
|
||||||
|
- `BTDraft`
|
||||||
|
|
||||||
|
其中主载荷来自 `BTDraft.llm_raw_json`。
|
||||||
|
|
||||||
|
### 5.2 输出格式(最终 API 返回)
|
||||||
|
|
||||||
|
复杂模式示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "Sequence",
|
||||||
|
"name": "Sequence",
|
||||||
|
"children": [
|
||||||
|
{"type": "action", "name": "fly_to_waypoint", "params": {"x": 120, "y": 30, "z": 10, "acceptance_radius": 2}},
|
||||||
|
{"type": "action", "name": "rotate_search", "params": {"target_class": "bus"}},
|
||||||
|
{"type": "condition", "name": "object_detected", "params": {"target_class": "bus"}},
|
||||||
|
{"type": "action", "name": "take_photos", "params": {"target_class": "bus", "track_time": 8}}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"relative_refs": [
|
||||||
|
{"anchor": "front_building", "relation": "left", "distance_m": 20.0}
|
||||||
|
],
|
||||||
|
"resolved_refs": {
|
||||||
|
"strategy": "backend_static_resolution",
|
||||||
|
"waypoints": [{"x": 120.0, "y": 30.0, "z": 10.0}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"plan_id": "6a924d0d-f1a7-4ef1-a9fa-31f73f3115ce",
|
||||||
|
"visualization_url": "/static/py_tree.png",
|
||||||
|
"final_prompt": "=== System Prompt === ... === User Prompt === ..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
simple 模式示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "action",
|
||||||
|
"name": "move_direction",
|
||||||
|
"params": {"direction": "north", "distance": 50}
|
||||||
|
},
|
||||||
|
"plan_id": "0f0e5e5f-b9a2-4e6f-95f5-c95e9e6280a5",
|
||||||
|
"visualization_url": "/static/py_tree.png",
|
||||||
|
"final_prompt": "=== System Prompt === ... === User Prompt === ..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
|
||||||
|
- `root`: 通过 schema 校验后的行为树根节点
|
||||||
|
- `context`: 仅在复杂模式且命中相对目标时追加
|
||||||
|
- `plan_id`: 每次生成唯一 ID
|
||||||
|
- `visualization_url`: 最新可视化图访问路径
|
||||||
|
- `final_prompt`: 生成时使用的完整提示词记录
|
||||||
|
|
||||||
|
## 6. 数据入库(RAG Ingestion)逻辑
|
||||||
|
|
||||||
|
入库脚本:
|
||||||
|
|
||||||
|
- `tools/rag/ingest.py`
|
||||||
|
|
||||||
|
行为:
|
||||||
|
|
||||||
|
- 扫描 `tools/rag/knowledge_base/`
|
||||||
|
- 根据子目录推断 `kb_type`(location/pattern/rules)
|
||||||
|
- 同时写入:
|
||||||
|
- `drone_docs`(兼容)
|
||||||
|
- `location_kb` / `pattern_kb` / `rules_kb`(新检索路径)
|
||||||
|
|
||||||
|
## 7. 可自定义修改点(推荐按优先级)
|
||||||
|
|
||||||
|
### 7.1 场景与意图逻辑
|
||||||
|
|
||||||
|
可改文件:
|
||||||
|
|
||||||
|
- `backend_service/src/pipeline/stages.py`
|
||||||
|
|
||||||
|
可改内容:
|
||||||
|
|
||||||
|
- `_infer_intent_type()`:扩展意图类别
|
||||||
|
- `_extract_risk_flags()`:新增风险规则
|
||||||
|
- `_derive_required_actions()`:调整规则推导的动作集合
|
||||||
|
|
||||||
|
### 7.2 Prompt 策略
|
||||||
|
|
||||||
|
可改文件:
|
||||||
|
|
||||||
|
- `backend_service/src/prompting/composer.py`
|
||||||
|
- `backend_service/src/prompts/prompt_manifest.yaml`
|
||||||
|
- `backend_service/src/prompts/partials/*`
|
||||||
|
|
||||||
|
可改内容:
|
||||||
|
|
||||||
|
- 骨架片段选择
|
||||||
|
- 节点裁剪规则(当前上限 30)
|
||||||
|
- 示例注入策略(何时注入 extra examples)
|
||||||
|
- 用户侧检索增强格式
|
||||||
|
|
||||||
|
### 7.3 模型路由与推理参数
|
||||||
|
|
||||||
|
可改文件:
|
||||||
|
|
||||||
|
- `backend_service/src/llm/gateway.py`
|
||||||
|
|
||||||
|
可改内容:
|
||||||
|
|
||||||
|
- 分类模型与生成模型分流策略
|
||||||
|
- `temperature`、`max_tokens`、重试次数
|
||||||
|
- thinking 开关策略(Stage1/Stage3)
|
||||||
|
|
||||||
|
### 7.4 检索策略
|
||||||
|
|
||||||
|
可改文件:
|
||||||
|
|
||||||
|
- `backend_service/src/retrieval/retriever.py`
|
||||||
|
- `backend_service/src/retrieval/adapters/chroma_adapter.py`
|
||||||
|
- `tools/rag/ingest.py`
|
||||||
|
|
||||||
|
可改内容:
|
||||||
|
|
||||||
|
- 检索并发策略与 `top_k`
|
||||||
|
- 回退策略(主集合与兼容集合)
|
||||||
|
- kb_type 划分方式
|
||||||
|
- 文档切分与 metadata 设计
|
||||||
|
|
||||||
|
### 7.5 相对目标解析
|
||||||
|
|
||||||
|
可改文件:
|
||||||
|
|
||||||
|
- `backend_service/src/pipeline/stages.py`
|
||||||
|
- `backend_service/src/llm/tool_runtime.py`
|
||||||
|
|
||||||
|
可改内容:
|
||||||
|
|
||||||
|
- `relative_refs` 抽取规则
|
||||||
|
- 静态解析能力(何时生成 `resolved_refs`)
|
||||||
|
- 与 UAV 端协议字段兼容策略
|
||||||
|
|
||||||
|
### 7.6 校验与输出协议
|
||||||
|
|
||||||
|
可改文件:
|
||||||
|
|
||||||
|
- `backend_service/src/validation/validator.py`
|
||||||
|
- `backend_service/src/validation/schema_provider.py`
|
||||||
|
- `backend_service/src/py_tree_generator.py`(schema 来源)
|
||||||
|
|
||||||
|
可改内容:
|
||||||
|
|
||||||
|
- simple/complex schema 约束强度
|
||||||
|
- 顶层 `context` 字段的可选校验
|
||||||
|
- 失败错误信息与恢复策略
|
||||||
|
|
||||||
|
## 8. 关键环境变量
|
||||||
|
|
||||||
|
- `ORIN_IP`
|
||||||
|
- `OPENAI_API_KEY`
|
||||||
|
- `CLASSIFIER_MODEL` / `SIMPLE_MODEL` / `COMPLEX_MODEL`
|
||||||
|
- `CLASSIFIER_BASE_URL` / `SIMPLE_BASE_URL` / `COMPLEX_BASE_URL`
|
||||||
|
- `STAGE1_ENABLE_THINKING`
|
||||||
|
- `ENABLE_REASONING_CAPTURE`
|
||||||
|
- `REASONING_PREVIEW_LINES`
|
||||||
|
|
||||||
|
## 9. 自定义改造建议(实践顺序)
|
||||||
|
|
||||||
|
1. 先改 Stage1 规则推导(低风险,收益快)
|
||||||
|
2. 再改 PromptComposer 的裁剪与注入(控制长度与稳定性)
|
||||||
|
3. 再改检索策略(top_k、回退、metadata)
|
||||||
|
4. 最后改 schema 与输出协议(需联动执行端)
|
||||||
|
|
||||||
|
## 10. 变更后最小回归清单
|
||||||
|
|
||||||
|
每次改造后至少验证:
|
||||||
|
|
||||||
|
1. simple 指令:返回 `root.action`,且无 children
|
||||||
|
2. scene4 指令:有复合树结构,JSON 可解析
|
||||||
|
3. relative 指令:复杂模式下出现 `context.relative_refs`
|
||||||
|
4. `/generate_plan` 不变更接口字段(兼容外部调用)
|
||||||
|
5. `python tools/rag/ingest.py` 可完成入库(或输出可定位错误)
|
||||||
|
|
||||||
545
README.md
545
README.md
@@ -1,454 +1,153 @@
|
|||||||
# 无人机自然语言控制项目
|
# 无人机自然语言控制项目 (DronePlanning)
|
||||||
|
|
||||||
本项目构建了一个完整的无人机自然语言控制系统,集成了检索增强生成(RAG)知识库、大型语言模型(LLM)、FastAPI后端服务和ROS2通信,最终实现通过自然语言指令控制无人机执行复杂任务。
|
本项目提供一个基于 `FastAPI + LLM + RAG` 的无人机任务规划后端。输入自然语言指令,输出严格 JSON 的行为树计划(`py_tree`)。
|
||||||
|
|
||||||
## 项目结构
|
> 当前版本已与 ROS2 解耦。
|
||||||
|
> 推荐直接使用 `start_all.sh` / `start_all_vllm.sh` 启动。
|
||||||
|
|
||||||
项目被清晰地划分为几个核心模块:
|
## 1. 当前代码结构
|
||||||
|
|
||||||
```
|
```text
|
||||||
.
|
backend_service/src/
|
||||||
├── backend_service/
|
├── main.py
|
||||||
│ ├── src/ # FastAPI应用核心代码
|
├── py_tree_generator.py
|
||||||
│ │ ├── __init__.py
|
├── models.py
|
||||||
│ │ ├── main.py # 应用主入口,提供Web API
|
├── websocket_manager.py
|
||||||
│ │ ├── py_tree_generator.py # RAG与LLM集成,生成py_tree
|
├── pipeline/ # 编排层(stage1~stage4)
|
||||||
│ │ ├── prompts/ # LLM 提示词
|
├── llm/ # 模型网关/响应解析/工具运行时
|
||||||
│ │ │ ├── system_prompt.txt # 复杂模式提示词(行为树与安全监控)
|
├── retrieval/ # 多知识库检索(Location/Pattern/Rules)
|
||||||
│ │ │ ├── simple_mode_prompt.txt # 简单模式提示词(单一原子动作JSON)
|
├── prompting/ # prompt manifest + 动态注入
|
||||||
│ │ │ └── classifier_prompt.txt # 指令简单/复杂分类提示词
|
├── validation/ # schema provider + validator
|
||||||
│ │ ├── ...
|
├── prompts/
|
||||||
│ ├── generated_visualizations/ # 存放最新生成的py_tree可视化图像
|
└── tools/
|
||||||
│ ├── generated_reasoning_content/ # 存放最新推理链Markdown(<plan_id>.md)
|
|
||||||
│ └── requirements.txt # 后端服务的Python依赖
|
|
||||||
│
|
|
||||||
├── tools/
|
|
||||||
│ ├── map/ # 【数据源】存放原始地图文件(如.world, .json)
|
|
||||||
│ ├── knowledge_base/ # 【处理后】存放build_knowledge_base.py生成的.ndjson文件
|
|
||||||
│ ├── vector_store/ # 【数据库】存放最终的ChromaDB向量数据库
|
|
||||||
│ ├── build_knowledge_base.py # 【步骤1】用于将原始数据转换为自然语言知识
|
|
||||||
│ ├── ingest.py # 【步骤2】用于将自然语言知识摄入向量数据库
|
|
||||||
│ └── test_llama_server.py # 直接调用本地8081端口llama-server,支持 --system / --system-file
|
|
||||||
│
|
|
||||||
├── / # ROS2接口定义 (保持不变)
|
|
||||||
└── docs/
|
|
||||||
└── README.md # 本说明文件
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 核心配置:Orin IP 地址
|
## 2. 环境准备(完整命令)
|
||||||
|
|
||||||
**重要提示:** 本项目的后端服务和知识库工具需要与在NVIDIA Jetson Orin设备上运行的服务进行通信(嵌入模型和LLM推理服务),**默认的IP地址为localhost**,所以使用电脑本地部署的模型服务同样可以,但是需要注意指定模型的端口。
|
在项目根目录执行:
|
||||||
|
|
||||||
在使用前,您必须配置正确的Orin设备IP地址。您可以通过以下两种方式之一进行设置:
|
|
||||||
|
|
||||||
1. **设置环境变量 (推荐)**:
|
|
||||||
在您的终端中设置一个名为 `ORIN_IP` 的环境变量。
|
|
||||||
```bash
|
|
||||||
export ORIN_IP="192.168.1.100" # 请替换为您的Orin设备的实际IP地址
|
|
||||||
```
|
|
||||||
脚本会优先使用这个环境变量。
|
|
||||||
|
|
||||||
2. **直接修改脚本**:
|
|
||||||
如果您不想设置环境变量,可以打开 `tools/ingest.py` 和 `backend_service/src/py_tree_generator.py` 文件,找到 `orin_ip = os.getenv("ORIN_IP", "...")` 这样的行,并将默认的IP地址修改为您的Orin设备的实际IP地址。
|
|
||||||
|
|
||||||
**在继续后续步骤之前,请务必完成此项配置。**
|
|
||||||
|
|
||||||
## 模型端口启动
|
|
||||||
|
|
||||||
本项目启动依赖于后端的模型推理服务,即`ORIN_IP`所指向的设备的模型服务端口,目前项目使用instruct模型与embedding模型实现流程,分别部署在8081端口与8090端口。
|
|
||||||
|
|
||||||
1. **推理模型部署**:
|
|
||||||
|
|
||||||
在`/llama.cpp/build/bin`路径下执行以下命令启动模型
|
|
||||||
```bash
|
|
||||||
./llama-server -m ~/models/gguf/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf --port 8081 --gpu-layers 36 --host 0.0.0.0 -c 8192
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Embedding模型部署**
|
|
||||||
|
|
||||||
在`/llama.cpp/build/bin`路径下执行以下命令启动模型
|
|
||||||
```bash
|
|
||||||
./llama-server -m ~/models/gguf/Qwen/Qwen3-embedding-4B/Qwen3-Embedding-4B-Q4_K_M.gguf --gpu-layers 36 --port 8090 --embeddings --pooling last --host 0.0.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 指令分类与分流
|
|
||||||
|
|
||||||
后端在生成任务前会先对用户指令进行“简单/复杂”分类,并分流到不同提示词与模型:
|
|
||||||
|
|
||||||
- 分类提示词:`backend_service/src/prompts/classifier_prompt.txt`
|
|
||||||
- 简单模式提示词:`backend_service/src/prompts/simple_mode_prompt.txt`
|
|
||||||
- 复杂模式提示词:`backend_service/src/prompts/system_prompt.txt`
|
|
||||||
|
|
||||||
分类仅输出如下JSON之一:`{"mode":"simple"}` 或 `{"mode":"complex"}`。两种模式都会执行检索增强(RAG),将参考知识拼接到用户指令后再进行推理。
|
|
||||||
|
|
||||||
当为简单模式时,LLM仅输出:
|
|
||||||
`{"mode":"simple","action":{"name":"<action>","params":{...}}}`。
|
|
||||||
后端不会再自动封装为复杂行为树;将直接返回简单JSON,并附加 `plan_id` 与 `visualization_url`(单动作可视化)。
|
|
||||||
|
|
||||||
### 环境变量(可选)
|
|
||||||
|
|
||||||
支持为“分类/简单/复杂”三类调用分别配置模型与Base URL(未设置时回退到默认本地配置):
|
|
||||||
|
|
||||||
- `CLASSIFIER_MODEL`, `CLASSIFIER_BASE_URL`
|
|
||||||
- `SIMPLE_MODEL`, `SIMPLE_BASE_URL`
|
|
||||||
- `COMPLEX_MODEL`, `COMPLEX_BASE_URL`
|
|
||||||
|
|
||||||
通用API Key:`OPENAI_API_KEY`
|
|
||||||
|
|
||||||
推理链捕获相关:
|
|
||||||
- `ENABLE_REASONING_CAPTURE`:是否允许模型返回含有 <think> 的原文以便捕获推理链;默认 true。
|
|
||||||
- `REASONING_PREVIEW_LINES`:在后端日志中打印推理链预览的行数;默认 20。
|
|
||||||
|
|
||||||
示例:
|
|
||||||
```bash
|
|
||||||
export CLASSIFIER_MODEL="qwen2.5-1.8b-instruct"
|
|
||||||
export SIMPLE_MODEL="qwen2.5-1.8b-instruct"
|
|
||||||
export COMPLEX_MODEL="qwen2.5-7b-instruct"
|
|
||||||
export CLASSIFIER_BASE_URL="http://$ORIN_IP:8081/v1"
|
|
||||||
export SIMPLE_BASE_URL="http://$ORIN_IP:8081/v1"
|
|
||||||
export COMPLEX_BASE_URL="http://$ORIN_IP:8081/v1"
|
|
||||||
export OPENAI_API_KEY="sk-no-key-required"
|
|
||||||
|
|
||||||
# 推理链捕获(可选)
|
|
||||||
export ENABLE_REASONING_CAPTURE=true # 默认已为true;如需关闭,设置为 false
|
|
||||||
export REASONING_PREVIEW_LINES=30 # 调整日志预览行数
|
|
||||||
```
|
|
||||||
|
|
||||||
### 测试简单模式
|
|
||||||
|
|
||||||
启动服务后,运行内置测试脚本:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd tools
|
cd /home/huangfukk/DronePlanning
|
||||||
python test_api.py
|
|
||||||
|
# 1) 创建并激活 venv
|
||||||
|
python3 -m venv backend_service/venv
|
||||||
|
source backend_service/venv/bin/activate
|
||||||
|
|
||||||
|
# 2) 安装依赖
|
||||||
|
pip install -r backend_service/requirements.txt
|
||||||
|
|
||||||
|
# 3) 可选:设置设备地址(本地默认 localhost)
|
||||||
|
export ORIN_IP="localhost"
|
||||||
```
|
```
|
||||||
|
|
||||||
示例输入:“简单模式,起飞” 或 “起飞到10米”。返回结果为简单JSON(无 `root`):包含 `mode`、`action`、`plan_id`、`visualization_url`。
|
## 3. 启动服务(推荐)
|
||||||
|
|
||||||
### 直接调用 llama-server(绕过后端)
|
### 3.1 llama.cpp 路线
|
||||||
|
|
||||||
当仅需测试本地 8081 端口的推理服务(OpenAI 兼容接口)时,可使用内置脚本:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
cd /home/huangfukk/DronePlanning
|
||||||
|
./start_all.sh start
|
||||||
|
```
|
||||||
|
|
||||||
|
常用命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./start_all.sh stop
|
||||||
|
./start_all.sh restart
|
||||||
|
./start_all.sh vl
|
||||||
|
./start_all.sh restart-vl
|
||||||
|
./start_all.sh status
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 vLLM 路线
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/huangfukk/DronePlanning
|
||||||
|
./start_all_vllm.sh start
|
||||||
|
```
|
||||||
|
|
||||||
|
常用命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./start_all_vllm.sh stop
|
||||||
|
./start_all_vllm.sh restart
|
||||||
|
./start_all_vllm.sh status
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 构建与入库(RAG)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/huangfukk/DronePlanning
|
||||||
|
source backend_service/venv/bin/activate
|
||||||
|
|
||||||
|
# 1) 从 map 生成知识文本(可选,已有知识可跳过)
|
||||||
|
python tools/rag/build_knowledge_base.py
|
||||||
|
|
||||||
|
# 2) 入库到 ChromaDB(Location/Pattern/Rules + 兼容集合)
|
||||||
|
python tools/rag/ingest.py
|
||||||
|
```
|
||||||
|
|
||||||
|
> 运行 `ingest.py` 前,请确保 embedding 服务(8090)已启动。
|
||||||
|
|
||||||
|
## 5. 快速接口验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/huangfukk/DronePlanning
|
||||||
|
|
||||||
|
# 健康检查
|
||||||
|
curl -s http://localhost:8000/docs >/dev/null && echo "fastapi ok"
|
||||||
|
curl -s http://localhost:8081/v1/models && echo "llm ok"
|
||||||
|
|
||||||
|
# 生成计划
|
||||||
|
curl -s http://localhost:8000/generate_plan \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"user_prompt":"无人机当前在地面,到广场查找绿色公交车,找到就拍照"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. 测试命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/huangfukk/DronePlanning
|
||||||
|
source backend_service/venv/bin/activate
|
||||||
|
|
||||||
|
# API 回归
|
||||||
|
python tools/test_api.py
|
||||||
|
|
||||||
|
# 直接测试 8081 的 OpenAI 兼容推理接口
|
||||||
python tools/test_llama_server.py \
|
python tools/test_llama_server.py \
|
||||||
--system-file backend_service/src/prompts/system_prompt.txt \
|
--system-file backend_service/src/prompts/system_prompt_vllm.txt \
|
||||||
--user "起飞到10米然后降落" \
|
--user "起飞到10米然后降落" \
|
||||||
--base-url "http://127.0.0.1:8081/v1" \
|
--base-url "http://127.0.0.1:8081/v1" \
|
||||||
--verbose
|
--verbose
|
||||||
|
|
||||||
|
# 交互式/批量验证
|
||||||
|
python tools/test_validate/run_tests.py
|
||||||
```
|
```
|
||||||
|
|
||||||
说明:
|
## 7. 关键 API
|
||||||
- 支持 `--system` 或 `--system-file` 自定义提示词文件;`--system-file` 优先。
|
|
||||||
- 默认解析 OpenAI 风格返回,若包含 `<think>` 推理内容会显示在输出中(具体取决于模型和服务配置)。
|
|
||||||
|
|
||||||
---
|
- `POST /generate_plan`
|
||||||
|
- `POST /execute_mission`(当前返回 execution_disabled)
|
||||||
|
- `WS /ws/status`
|
||||||
|
- `GET /static/py_tree.png`
|
||||||
|
|
||||||
## 工作流程
|
## 8. 日志与排障
|
||||||
|
|
||||||
整个系统的工作流程分为两个主要阶段:
|
|
||||||
|
|
||||||
1. **知识库构建(一次性设置)**: 将环境信息、无人机能力等知识加工并存入向量数据库。
|
|
||||||
2. **后端服务运行与交互**: 启动主服务,通过API接收指令、生成并执行任务。
|
|
||||||
|
|
||||||
### 阶段一:环境设置与编译
|
|
||||||
|
|
||||||
此阶段为项目准备好运行环境,仅需在初次配置或依赖变更时执行。一个稳定、隔离且兼容的环境是所有后续步骤成功的基础。
|
|
||||||
|
|
||||||
#### 1. 创建Conda环境 (关键步骤)
|
|
||||||
|
|
||||||
为了从根源上避免本地Python环境与系统ROS 2环境的库版本冲突(特别是Python版本和C++标准库),我们**必须**使用Conda创建一个干净、隔离且版本精确的虚拟环境。
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. 创建一个使用Python 3.10的新环境。
|
cd /home/huangfukk/DronePlanning
|
||||||
# --name backend: 指定环境名称。
|
|
||||||
# python=3.10: 指定Python版本,必须与ROS 2 Humble要求的版本一致。
|
|
||||||
# --channel conda-forge: 使用conda-forge社区源,其包通常有更好的兼容性。
|
|
||||||
# --no-default-packages: 关键!不安装Conda默认的包(如libgcc),避免与系统ROS 2的C++库冲突。
|
|
||||||
conda create --name backend --channel conda-forge --no-default-packages python=3.10
|
|
||||||
|
|
||||||
# 2. 激活新创建的环境
|
|
||||||
conda activate backend
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 安装所有Python依赖
|
|
||||||
|
|
||||||
在激活`backend`环境后,使用`pip`一次性安装所有依赖。`requirements.txt`已包含**运行时**(如fastapi, rclpy)和**编译时**(如empy, catkin-pkg, lark)所需的所有库。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 确保在项目根目录 (drone/) 下执行
|
|
||||||
pip install -r backend_service/requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. 编译ROS 2接口
|
|
||||||
|
|
||||||
为了让后端服务能够像导入普通Python包一样导入我们自定义的Action接口 (`drone_interfaces`),你需要先使用`colcon`对其进行编译。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 确保在项目根目录 (drone/) 下执行
|
|
||||||
colcon build
|
|
||||||
```
|
|
||||||
成功后,您会看到`build/`, `install/`, `log/`三个新目录。这一步会将`.action`文件转换为Python和C++代码。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 阶段二:数据处理流水线
|
|
||||||
|
|
||||||
此阶段为RAG系统准备数据,让LLM能够理解任务环境。
|
|
||||||
|
|
||||||
#### 1. 准备原始数据
|
|
||||||
|
|
||||||
将你的原始数据文件(例如,`.world`, `.json` 文件等)放入 `tools/map/` 目录中。
|
|
||||||
|
|
||||||
#### 2. 数据预处理
|
|
||||||
|
|
||||||
运行脚本将原始数据“翻译”成自然语言知识。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 确保在项目根目录 (drone/) 下,并已激活backend环境
|
|
||||||
cd tools
|
|
||||||
python build_knowledge_base.py
|
|
||||||
```
|
|
||||||
该脚本会扫描 `tools/map/` 目录,并在 `tools/knowledge_base/` 目录下生成对应的 `_knowledge.ndjson` 文件。
|
|
||||||
|
|
||||||
#### 3. 数据入库(Ingestion)
|
|
||||||
|
|
||||||
运行脚本将处理好的知识加载到向量数据库中。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 仍在tools/目录下执行
|
|
||||||
python ingest.py
|
|
||||||
```
|
|
||||||
该脚本会自动扫描 `tools/knowledge_base/` 目录,并将数据存入 `tools/vector_store/` 目录中。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 阶段三:服务启动与测试
|
|
||||||
|
|
||||||
完成前两个阶段后,即可启动并测试后端服务。
|
|
||||||
|
|
||||||
#### 1. 启动所有服务(推荐方式:一键启动脚本)
|
|
||||||
|
|
||||||
我们提供了一个一键启动脚本 `start_all.sh`,可以自动启动所有必需的服务:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 切换到项目根目录
|
|
||||||
cd /path/to/your/drone
|
|
||||||
|
|
||||||
# 2. 使用一键启动脚本(推荐)
|
|
||||||
./start_all.sh start
|
|
||||||
|
|
||||||
# 或者直接运行(start是默认命令)
|
|
||||||
./start_all.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
**脚本功能:**
|
|
||||||
- 自动启动推理模型服务(llama-server,端口8081)
|
|
||||||
- 自动启动Embedding模型服务(llama-server,端口8090)
|
|
||||||
- 自动启动FastAPI后端服务(端口8000)
|
|
||||||
- 自动检查端口占用、模型文件、环境配置等
|
|
||||||
- 自动等待服务就绪
|
|
||||||
- 统一管理日志文件(保存在 `logs/` 目录)
|
|
||||||
|
|
||||||
**环境变量配置(可选):**
|
|
||||||
|
|
||||||
在运行脚本前,可以通过环境变量自定义配置:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 设置llama-server路径(如果不在默认位置)
|
|
||||||
export LLAMA_SERVER_DIR="/path/to/llama.cpp/build/bin"
|
|
||||||
|
|
||||||
# 设置模型路径(如果不在默认位置)
|
|
||||||
export INFERENCE_MODEL="~/models/gguf/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf"
|
|
||||||
export EMBEDDING_MODEL="~/models/gguf/Qwen/Qwen3-embedding-4B/Qwen3-Embedding-4B-Q4_K_M.gguf"
|
|
||||||
|
|
||||||
# 设置Conda环境名称(如果使用不同的环境名)
|
|
||||||
export CONDA_ENV="backend"
|
|
||||||
|
|
||||||
# 然后运行脚本
|
|
||||||
./start_all.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
**脚本命令:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./start_all.sh start # 启动所有服务(默认)
|
|
||||||
./start_all.sh stop # 停止所有服务
|
|
||||||
./start_all.sh restart # 重启所有服务
|
|
||||||
./start_all.sh status # 查看服务状态
|
|
||||||
```
|
|
||||||
|
|
||||||
**日志查看:**
|
|
||||||
|
|
||||||
所有服务的日志都保存在 `logs/` 目录下:
|
|
||||||
```bash
|
|
||||||
# 查看所有日志
|
|
||||||
tail -f logs/*.log
|
tail -f logs/*.log
|
||||||
|
|
||||||
# 查看特定服务日志
|
|
||||||
tail -f logs/inference_model.log # 推理模型
|
|
||||||
tail -f logs/embedding_model.log # Embedding模型
|
|
||||||
tail -f logs/fastapi.log # FastAPI服务
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2. 手动启动服务(备选方式)
|
常见日志:
|
||||||
|
|
||||||
如果您需要手动控制每个服务的启动,可以按照以下步骤操作:
|
- `logs/inference_model.log`(llama.cpp 推理)
|
||||||
|
- `logs/vllm_inference_model.log`(vLLM 推理)
|
||||||
|
- `logs/embedding_model.log`
|
||||||
|
- `logs/fastapi.log`
|
||||||
|
|
||||||
**启动推理模型服务:**
|
如果 `tools/rag/ingest.py` 在 Chroma 初始化时报错,优先确认:
|
||||||
|
|
||||||
```bash
|
1. 是否使用项目 venv 运行
|
||||||
cd /llama.cpp/build/bin
|
2. `tools/rag/vector_store/` 是否损坏(可备份后重建)
|
||||||
./llama-server -m ~/models/gguf/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf --port 8081 --gpu-layers 36 --host 0.0.0.0 -c 8192
|
3. embedding 服务是否可访问(`http://localhost:8090/v1/embeddings`)
|
||||||
```
|
|
||||||
|
|
||||||
**启动Embedding模型服务:**
|
|
||||||
|
|
||||||
在另一个终端中:
|
|
||||||
```bash
|
|
||||||
cd /llama.cpp/build/bin
|
|
||||||
./llama-server -m ~/models/gguf/Qwen/Qwen3-embedding-4B/Qwen3-Embedding-4B-Q4_K_M.gguf --gpu-layers 36 --port 8090 --embeddings --pooling last --host 0.0.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
**启动FastAPI后端服务:**
|
|
||||||
|
|
||||||
在第三个终端中:
|
|
||||||
```bash
|
|
||||||
# 1. 切换到项目根目录
|
|
||||||
cd /path/to/your/drone
|
|
||||||
|
|
||||||
# 2. 激活ROS 2编译环境
|
|
||||||
# 作用:将我们编译好的`drone_interfaces`包的路径告知系统,否则Python会报`ModuleNotFoundError`。
|
|
||||||
# 注意:此命令必须在每次打开新终端时执行一次。
|
|
||||||
source install/setup.bash
|
|
||||||
|
|
||||||
# 3. 激活Conda Python环境
|
|
||||||
conda activate backend
|
|
||||||
|
|
||||||
# 4. 启动FastAPI服务
|
|
||||||
cd backend_service/
|
|
||||||
uvicorn src.main:app --host 0.0.0.0 --port 8000
|
|
||||||
```
|
|
||||||
|
|
||||||
当您看到日志中出现 `Uvicorn running on http://0.0.0.0:8000` 时,表示服务已成功启动。
|
|
||||||
|
|
||||||
#### 2. 运行API接口测试
|
|
||||||
|
|
||||||
我们提供了一个脚本来验证核心的“任务生成”功能。
|
|
||||||
|
|
||||||
**打开一个新的终端**,并执行以下命令:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 切换到项目根目录
|
|
||||||
cd /path/to/your/drone
|
|
||||||
|
|
||||||
# 2. 激活Conda环境
|
|
||||||
conda activate backend
|
|
||||||
|
|
||||||
# 3. 运行测试脚本
|
|
||||||
cd tools/
|
|
||||||
python test_api.py
|
|
||||||
```
|
|
||||||
如果一切正常,您将在终端看到一系列 `PASS` 信息,以及从服务器返回的Pytree JSON。
|
|
||||||
|
|
||||||
#### 3. API接口使用说明
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 故障排除 / 常见问题 (FAQ)
|
|
||||||
|
|
||||||
以下是在配置和运行此项目时可能遇到的一些常见问题及其解决方案。
|
|
||||||
|
|
||||||
#### **Q1: 启动服务时报错 `ModuleNotFoundError: No module named 'drone_interfaces'`**
|
|
||||||
|
|
||||||
- **原因**: 您当前的终端环境没有加载ROS 2工作空间的路径。仅仅激活Conda环境是不够的。
|
|
||||||
- **解决方案**: 严格遵循“启动后端服务”章节的说明,在激活Conda环境**之前**,必须先运行 `source install/setup.bash` 命令。
|
|
||||||
|
|
||||||
#### **Q2: `colcon build` 编译失败,提示 `ModuleNotFoundError: No module named 'em'`, `'catkin_pkg'`, 或 `'lark'`**
|
|
||||||
|
|
||||||
- **原因**: 您的Python环境中缺少ROS 2编译代码时所必需的依赖包。
|
|
||||||
- **解决方案**: 我们已将所有已知的编译时依赖(`empy`, `catkin-pkg`, `lark`等)添加到了`requirements.txt`中。请确保您已激活正确的Conda环境,然后运行 `pip install -r backend_service/requirements.txt` 来安装它们。
|
|
||||||
|
|
||||||
#### **Q3: 启动服务时报错 `ImportError: ... GLIBCXX_... not found` 或 `ModuleNotFoundError: No module named 'rclpy._rclpy_pybind11'`**
|
|
||||||
|
|
||||||
- **原因**: 您的Conda环境与系统ROS 2环境存在核心库冲突。最常见的原因是Python版本不匹配(例如,Conda是Python 3.11而ROS 2 Humble需要3.10),或者Conda自带的C++库与系统库冲突。
|
|
||||||
- **解决方案**: 这是最棘手的环境问题。最可靠的解决方法是彻底删除当前的Conda环境 (`conda env remove --name backend`),然后严格按照本文档「环境设置」章节的说明,用正确的命令 (`conda create --name backend --channel conda-forge --no-default-packages python=3.10`) 重建一个干净、兼容的环境。
|
|
||||||
|
|
||||||
#### **Q4: 服务启动时,日志显示正在从网络上下载模型(例如 `all-MiniLM-L6-v2`)**
|
|
||||||
|
|
||||||
- **原因**: 后端服务在连接向量数据库时,没有正确指定使用远程嵌入模型,导致ChromaDB退回到默认的、需要下载模型的本地嵌入函数。
|
|
||||||
- **解决方案**: 此问题在当前代码中**已被修复**。`backend_service/src/py_tree_generator.py`现在会正确地将远程嵌入函数实例传递给ChromaDB。如果您在自己的代码中遇到此问题,请检查您的`get_collection`调用。
|
|
||||||
|
|
||||||
#### **Q5: 服务启动时,日志停在 `waiting for action server...`,无法访问API**
|
|
||||||
|
|
||||||
- **原因**: 代码中存在阻塞式的`wait_for_server()`调用,它会一直等待直到无人机端的Action服务器上线,从而卡住了Web服务的启动流程。
|
|
||||||
- **解决方案**: 此问题在当前代码中**已被修复**。`backend_service/src/ros2_client.py`现在使用非阻塞的方式初始化,并在发送任务时检查服务器是否可用。
|
|
||||||
|
|
||||||
##### **A. 生成任务计划**
|
|
||||||
|
|
||||||
接收自然语言指令,返回生成的行为树(py_tree)JSON。
|
|
||||||
|
|
||||||
- **Endpoint**: `POST /generate_plan`
|
|
||||||
- **Request Body**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"user_prompt": "无人机起飞到10米,然后前往机库,最后降落。"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- **Success Response(复杂模式)**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"root": { ... },
|
|
||||||
"plan_id": "some-unique-id",
|
|
||||||
"visualization_url": "/static/py_tree.png"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- **Success Response(简单模式)**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mode": "simple",
|
|
||||||
"action": { "name": "takeoff", "params": { "altitude": 10.0 } },
|
|
||||||
"plan_id": "some-unique-id",
|
|
||||||
"visualization_url": "/static/py_tree.png"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### **B. 查看任务可视化**
|
|
||||||
|
|
||||||
获取最新生成的行为树的可视化图像。
|
|
||||||
|
|
||||||
- **Endpoint**: `GET /static/py_tree.png`
|
|
||||||
- **Usage**: 在浏览器中直接打开 `http://<服务器IP>:8000/static/py_tree.png` 即可查看。每次成功调用 `/generate_plan` 后,该图像都会被更新。
|
|
||||||
|
|
||||||
##### **C. 执行任务**
|
|
||||||
|
|
||||||
接收一个py_tree JSON,下发给无人机执行(当前为模拟执行)。
|
|
||||||
|
|
||||||
- **Endpoint**: `POST /execute_mission`
|
|
||||||
- **Request Body**: (使用 `/generate_plan` 返回的 `root` 对象)
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"py_tree": {
|
|
||||||
"root": { ... }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- **Response**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": "execution_started"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### **D. 接收实时状态**
|
|
||||||
|
|
||||||
通过WebSocket连接,实时接收无人机在执行任务时的状态反馈。
|
|
||||||
|
|
||||||
- **Endpoint**: `WS /ws/status`
|
|
||||||
- **Usage**: 使用任意WebSocket客户端连接到 `ws://<服务器IP>:8000/ws/status`。当任务执行时,服务器会主动推送JSON消息,例如:
|
|
||||||
```json
|
|
||||||
{"node_id": "takeoff_node_1", "status": 0} // 0: RUNNING
|
|
||||||
{"node_id": "takeoff_node_1", "status": 1} // 1: SUCCESS
|
|
||||||
```
|
|
||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 68 KiB |
75
backend_service/history/20260120_102200_plan.json
Normal file
75
backend_service/history/20260120_102200_plan.json
Normal file
File diff suppressed because one or more lines are too long
51
backend_service/history/20260120_102205_plan.json
Normal file
51
backend_service/history/20260120_102205_plan.json
Normal file
File diff suppressed because one or more lines are too long
63
backend_service/history/20260120_102211_plan.json
Normal file
63
backend_service/history/20260120_102211_plan.json
Normal file
File diff suppressed because one or more lines are too long
44
backend_service/history/20260120_102215_plan.json
Normal file
44
backend_service/history/20260120_102215_plan.json
Normal file
File diff suppressed because one or more lines are too long
75
backend_service/history/20260120_102222_plan.json
Normal file
75
backend_service/history/20260120_102222_plan.json
Normal file
File diff suppressed because one or more lines are too long
47
backend_service/history/20260120_102226_plan.json
Normal file
47
backend_service/history/20260120_102226_plan.json
Normal file
File diff suppressed because one or more lines are too long
64
backend_service/history/20260120_102232_plan.json
Normal file
64
backend_service/history/20260120_102232_plan.json
Normal file
File diff suppressed because one or more lines are too long
40
backend_service/history/20260120_102236_plan.json
Normal file
40
backend_service/history/20260120_102236_plan.json
Normal file
File diff suppressed because one or more lines are too long
75
backend_service/history/20260120_102742_plan.json
Normal file
75
backend_service/history/20260120_102742_plan.json
Normal file
File diff suppressed because one or more lines are too long
51
backend_service/history/20260120_102747_plan.json
Normal file
51
backend_service/history/20260120_102747_plan.json
Normal file
File diff suppressed because one or more lines are too long
63
backend_service/history/20260120_102755_plan.json
Normal file
63
backend_service/history/20260120_102755_plan.json
Normal file
File diff suppressed because one or more lines are too long
44
backend_service/history/20260120_102759_plan.json
Normal file
44
backend_service/history/20260120_102759_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_111034_plan.json
Normal file
56
backend_service/history/20260120_111034_plan.json
Normal file
File diff suppressed because one or more lines are too long
82
backend_service/history/20260120_111135_plan.json
Normal file
82
backend_service/history/20260120_111135_plan.json
Normal file
File diff suppressed because one or more lines are too long
82
backend_service/history/20260120_111754_plan.json
Normal file
82
backend_service/history/20260120_111754_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260120_111830_plan.json
Normal file
78
backend_service/history/20260120_111830_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260120_111903_plan.json
Normal file
78
backend_service/history/20260120_111903_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260120_115045_plan.json
Normal file
78
backend_service/history/20260120_115045_plan.json
Normal file
File diff suppressed because one or more lines are too long
82
backend_service/history/20260120_115356_plan.json
Normal file
82
backend_service/history/20260120_115356_plan.json
Normal file
File diff suppressed because one or more lines are too long
82
backend_service/history/20260120_115415_plan.json
Normal file
82
backend_service/history/20260120_115415_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260120_115816_plan.json
Normal file
78
backend_service/history/20260120_115816_plan.json
Normal file
File diff suppressed because one or more lines are too long
77
backend_service/history/20260120_115851_plan.json
Normal file
77
backend_service/history/20260120_115851_plan.json
Normal file
File diff suppressed because one or more lines are too long
50
backend_service/history/20260120_115900_plan.json
Normal file
50
backend_service/history/20260120_115900_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_115910_plan.json
Normal file
56
backend_service/history/20260120_115910_plan.json
Normal file
File diff suppressed because one or more lines are too long
64
backend_service/history/20260120_115921_plan.json
Normal file
64
backend_service/history/20260120_115921_plan.json
Normal file
File diff suppressed because one or more lines are too long
45
backend_service/history/20260120_115929_plan.json
Normal file
45
backend_service/history/20260120_115929_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260120_115942_plan.json
Normal file
78
backend_service/history/20260120_115942_plan.json
Normal file
File diff suppressed because one or more lines are too long
72
backend_service/history/20260120_115954_plan.json
Normal file
72
backend_service/history/20260120_115954_plan.json
Normal file
File diff suppressed because one or more lines are too long
45
backend_service/history/20260120_120002_plan.json
Normal file
45
backend_service/history/20260120_120002_plan.json
Normal file
File diff suppressed because one or more lines are too long
62
backend_service/history/20260120_120014_plan.json
Normal file
62
backend_service/history/20260120_120014_plan.json
Normal file
File diff suppressed because one or more lines are too long
40
backend_service/history/20260120_120022_plan.json
Normal file
40
backend_service/history/20260120_120022_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_120356_plan.json
Normal file
56
backend_service/history/20260120_120356_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_120657_plan.json
Normal file
56
backend_service/history/20260120_120657_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_122451_plan.json
Normal file
56
backend_service/history/20260120_122451_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_122519_plan.json
Normal file
56
backend_service/history/20260120_122519_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_122538_plan.json
Normal file
56
backend_service/history/20260120_122538_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123118_plan.json
Normal file
56
backend_service/history/20260120_123118_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123142_plan.json
Normal file
56
backend_service/history/20260120_123142_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123322_plan.json
Normal file
56
backend_service/history/20260120_123322_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123342_plan.json
Normal file
56
backend_service/history/20260120_123342_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123516_plan.json
Normal file
56
backend_service/history/20260120_123516_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123521_plan.json
Normal file
56
backend_service/history/20260120_123521_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123526_plan.json
Normal file
56
backend_service/history/20260120_123526_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123531_plan.json
Normal file
56
backend_service/history/20260120_123531_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123536_plan.json
Normal file
56
backend_service/history/20260120_123536_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123541_plan.json
Normal file
56
backend_service/history/20260120_123541_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123546_plan.json
Normal file
56
backend_service/history/20260120_123546_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123551_plan.json
Normal file
56
backend_service/history/20260120_123551_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123556_plan.json
Normal file
56
backend_service/history/20260120_123556_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123601_plan.json
Normal file
56
backend_service/history/20260120_123601_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_123801_plan.json
Normal file
56
backend_service/history/20260120_123801_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_125258_plan.json
Normal file
56
backend_service/history/20260120_125258_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260120_125315_plan.json
Normal file
56
backend_service/history/20260120_125315_plan.json
Normal file
File diff suppressed because one or more lines are too long
63
backend_service/history/20260121_202255_plan.json
Normal file
63
backend_service/history/20260121_202255_plan.json
Normal file
File diff suppressed because one or more lines are too long
79
backend_service/history/20260203_222653_plan.json
Normal file
79
backend_service/history/20260203_222653_plan.json
Normal file
File diff suppressed because one or more lines are too long
72
backend_service/history/20260203_222711_plan.json
Normal file
72
backend_service/history/20260203_222711_plan.json
Normal file
File diff suppressed because one or more lines are too long
53
backend_service/history/20260203_222720_plan.json
Normal file
53
backend_service/history/20260203_222720_plan.json
Normal file
File diff suppressed because one or more lines are too long
72
backend_service/history/20260203_222813_plan.json
Normal file
72
backend_service/history/20260203_222813_plan.json
Normal file
File diff suppressed because one or more lines are too long
49
backend_service/history/20260203_222823_plan.json
Normal file
49
backend_service/history/20260203_222823_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260203_222838_plan.json
Normal file
56
backend_service/history/20260203_222838_plan.json
Normal file
File diff suppressed because one or more lines are too long
18
backend_service/history/20260203_222840_plan.json
Normal file
18
backend_service/history/20260203_222840_plan.json
Normal file
File diff suppressed because one or more lines are too long
51
backend_service/history/20260203_222851_plan.json
Normal file
51
backend_service/history/20260203_222851_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260203_222907_plan.json
Normal file
78
backend_service/history/20260203_222907_plan.json
Normal file
File diff suppressed because one or more lines are too long
19
backend_service/history/20260203_222910_plan.json
Normal file
19
backend_service/history/20260203_222910_plan.json
Normal file
File diff suppressed because one or more lines are too long
62
backend_service/history/20260203_222943_plan.json
Normal file
62
backend_service/history/20260203_222943_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260203_222954_plan.json
Normal file
56
backend_service/history/20260203_222954_plan.json
Normal file
File diff suppressed because one or more lines are too long
72
backend_service/history/20260203_223851_plan.json
Normal file
72
backend_service/history/20260203_223851_plan.json
Normal file
File diff suppressed because one or more lines are too long
49
backend_service/history/20260203_223901_plan.json
Normal file
49
backend_service/history/20260203_223901_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260203_223912_plan.json
Normal file
56
backend_service/history/20260203_223912_plan.json
Normal file
File diff suppressed because one or more lines are too long
20
backend_service/history/20260203_223915_plan.json
Normal file
20
backend_service/history/20260203_223915_plan.json
Normal file
File diff suppressed because one or more lines are too long
51
backend_service/history/20260203_223925_plan.json
Normal file
51
backend_service/history/20260203_223925_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260203_223938_plan.json
Normal file
78
backend_service/history/20260203_223938_plan.json
Normal file
File diff suppressed because one or more lines are too long
19
backend_service/history/20260203_223941_plan.json
Normal file
19
backend_service/history/20260203_223941_plan.json
Normal file
File diff suppressed because one or more lines are too long
67
backend_service/history/20260203_224016_plan.json
Normal file
67
backend_service/history/20260203_224016_plan.json
Normal file
File diff suppressed because one or more lines are too long
40
backend_service/history/20260203_224025_plan.json
Normal file
40
backend_service/history/20260203_224025_plan.json
Normal file
File diff suppressed because one or more lines are too long
72
backend_service/history/20260203_224508_plan.json
Normal file
72
backend_service/history/20260203_224508_plan.json
Normal file
File diff suppressed because one or more lines are too long
49
backend_service/history/20260203_224518_plan.json
Normal file
49
backend_service/history/20260203_224518_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260203_224529_plan.json
Normal file
56
backend_service/history/20260203_224529_plan.json
Normal file
File diff suppressed because one or more lines are too long
20
backend_service/history/20260203_224532_plan.json
Normal file
20
backend_service/history/20260203_224532_plan.json
Normal file
File diff suppressed because one or more lines are too long
51
backend_service/history/20260203_224542_plan.json
Normal file
51
backend_service/history/20260203_224542_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260203_224557_plan.json
Normal file
78
backend_service/history/20260203_224557_plan.json
Normal file
File diff suppressed because one or more lines are too long
19
backend_service/history/20260203_224559_plan.json
Normal file
19
backend_service/history/20260203_224559_plan.json
Normal file
File diff suppressed because one or more lines are too long
72
backend_service/history/20260203_224642_plan.json
Normal file
72
backend_service/history/20260203_224642_plan.json
Normal file
File diff suppressed because one or more lines are too long
49
backend_service/history/20260203_224653_plan.json
Normal file
49
backend_service/history/20260203_224653_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260203_224705_plan.json
Normal file
56
backend_service/history/20260203_224705_plan.json
Normal file
File diff suppressed because one or more lines are too long
18
backend_service/history/20260203_224707_plan.json
Normal file
18
backend_service/history/20260203_224707_plan.json
Normal file
File diff suppressed because one or more lines are too long
51
backend_service/history/20260203_224718_plan.json
Normal file
51
backend_service/history/20260203_224718_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260203_224732_plan.json
Normal file
78
backend_service/history/20260203_224732_plan.json
Normal file
File diff suppressed because one or more lines are too long
19
backend_service/history/20260203_224736_plan.json
Normal file
19
backend_service/history/20260203_224736_plan.json
Normal file
File diff suppressed because one or more lines are too long
67
backend_service/history/20260203_224810_plan.json
Normal file
67
backend_service/history/20260203_224810_plan.json
Normal file
File diff suppressed because one or more lines are too long
40
backend_service/history/20260203_224818_plan.json
Normal file
40
backend_service/history/20260203_224818_plan.json
Normal file
File diff suppressed because one or more lines are too long
72
backend_service/history/20260203_225639_plan.json
Normal file
72
backend_service/history/20260203_225639_plan.json
Normal file
File diff suppressed because one or more lines are too long
49
backend_service/history/20260203_225648_plan.json
Normal file
49
backend_service/history/20260203_225648_plan.json
Normal file
File diff suppressed because one or more lines are too long
56
backend_service/history/20260203_225701_plan.json
Normal file
56
backend_service/history/20260203_225701_plan.json
Normal file
File diff suppressed because one or more lines are too long
63
backend_service/history/20260203_225712_plan.json
Normal file
63
backend_service/history/20260203_225712_plan.json
Normal file
File diff suppressed because one or more lines are too long
51
backend_service/history/20260203_225723_plan.json
Normal file
51
backend_service/history/20260203_225723_plan.json
Normal file
File diff suppressed because one or more lines are too long
78
backend_service/history/20260203_225737_plan.json
Normal file
78
backend_service/history/20260203_225737_plan.json
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user