Files
DronePlanning/tools/test_validate/api_test.log
2026-01-20 09:49:52 +08:00

682 lines
86 KiB
Plaintext
Raw 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.
[2026-01-02 14:09:56] ================================================================================
[2026-01-02 14:09:56] --- API Test: Scene 1: Search at Gate (Expected.csv Row 2) ---
[2026-01-02 14:09:56] URL: http://127.0.0.1:8000/generate_plan
[2026-01-02 14:09:56] Sending Prompt: "地面待命,去研究所正大门,搜索扎辫子女子并拍照。"
[2026-01-02 14:10:05] ✅ Received Response:
[2026-01-02 14:10:05]
📝 组织后的Prompt:
[2026-01-02 14:10:05] === System Prompt ===
任务根据用户任意任务指令生成结构化可执行的无人机行为树PytreeJSON。**仅输出单一JSON对象无任何自然语言、注释或额外内容**。
## 一、核心节点定义(格式不可修改,确保后端解析)
#### 1. 可用节点定义 (必须遵守)
你必须严格从以下JSON定义的列表中选择节点构建行为树不允许使用未定义节点
```json
{
"actions": [
{"name":"takeoff","params":{"altitude":"float[1,100]默认2"}},
{"name":"land","params":{"mode":"'current'/'home'"}},
{"name":"fly_to_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","acceptance_radius":"默认2.0"}},
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省持续移动"}},
{"name":"orbit_around_point","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
{"name":"orbit_around_target","params":{"target_class":"见object_detect列表","description":"可选,目标属性","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
{"name":"loiter","params":{"duration":"[1,600]秒/until_condition:可选"}},
{"name":"object_detect","params":{"target_class":"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush","description":"可选,","count":"默认1"}},
{"name":"strike_target","params":{"target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
{"name":"battle_damage_assessment","params":{"target_class":"同object_detect","assessment_time":"[5,60]默认15"}},
{"name":"search_pattern","params":{"pattern_type":"spiral/grid","center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
{"name":"track_object","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration'","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}},
{"name":"deliver_payload","params":{"payload_type":"string","release_altitude":"[2,100]默认5"}},
{"name":"preflight_checks","params":{"check_level":"basic/comprehensive"}},
{"name":"emergency_return","params":{"reason":"string"}},
{"name":"rotate_search","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,100]","speed_mps":"[0.5,10]","duration":"[10,600]秒"}},
{"name":"wait_for_confirmation","params":{"message":"string","timeout":"[10,600]秒"}}
],
"conditions": [
{"name":"battery_above","params":{"threshold":"[0.0,1.0],必传"}},
{"name":"at_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","tolerance":"默认3.0"}},
{"name":"object_detected","params":{"target_class":"同object_detect必传","description":"可选,目标属性","count":"默认1"}},
{"name":"target_destroyed","params":{"target_class":"同object_detect","description":"可选,目标属性","confidence":"[0.5,1.0]默认0.8"}},
{"name":"time_elapsed","params":{"duration":"[1,2700]秒"}},
{"name":"gps_status","params":{"min_satellites":"int[6,15]必传如8"}}
],
"control_flow": [
{"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"},
{"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"},
{"name":"Parallel","params":{"policy":"all_success"},"children":"子节点数组(同时执行,严禁用'one_success'"}
],
"decorators": [
{"name":"SuccessIsFailure","params":{},"child":"单个子节点(成功转失败,失败仍失败)"}
]
}
```
## 二、节点必填字段后端Schema强制要求缺一验证失败
每个节点必须包含以下字段,字段名/类型不可自定义:
1. **`type`**
- 动作节点→`"action"`,条件节点→`"condition"`,装饰器节点→`"decorator"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`(与`name`字段值完全一致);
2. **`name`**必须是上述JSON中`actions`/`conditions`/`control_flow`/`decorators`下的`name`值;
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;
4. **`children`**:仅控制流节点必含(子节点数组);
5. **`child`**:仅装饰器节点必含(单个子节点对象)。
## 三、行为树固定结构(通用不变)
根节点通常是 `Sequence` 或 `Selector`,直接包含任务逻辑。不再强制包含 `SafetyMonitor` 或 `Parallel` 根节点。
示例结构(简单顺序任务):
```json
{
"root": {
"type": "Sequence",
"name": "MainTask",
"params": {},
"children": [
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
{"type":"action","name":"fly_to_waypoint","params":{"x":200.0,"y":150.0,"z":10.0}},
{"type":"action","name":"land","params":{"mode":"home"}}
]
}
}
```
## 四、优先级排序任务通用示例
当用户指令中明确提出有多个待考察且具有优先级关系的物体时,节点描述须为优先级关系。比如当指令为已知有三个气球,危险级关系为红色气球大于蓝色气球大于绿色气球,要求优先跟踪最危险的气球时,节点的描述参考下表情形。
| 用户指令场景 | `target_class` | `description` | 核心节点示例search_pattern |
|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|
| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{"type":"action","name":"search_pattern","params":{"pattern_type":"grid","center_x":200,"center_y":150,"center_z":10,"radius":50,"target_class":"balloon","description":"(红>蓝>绿)"}}` |
| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{"type":"action","name":"object_detect","params":{"target_class":"truck","description":"(军用卡车>民用卡车>面包车)"}}` |
## 五、高频错误规避(确保验证通过)
1. 优先级排序不可修改`target_class`:如“民用卡车、面包车与军用卡车中,军用卡车优先”,`target_class`仍为`truck`,仅用`description`填排序规则;
2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;
3. `track_object`必传`track_time`:不可用`duration`替代如跟踪30秒填`"track_time":30.0`
4. `gps_status`的`min_satellites`必须在6-15之间如8不可缺省
5. 无自定义节点:“锁定高优先级目标”需通过`object_detect`+`object_detected`实现不可用“lock_high_risk_target”。
## 六、新场景模式指南 (New Scenarios)
### 1. 预期场景 (Expected Scenarios)
当用户指令包含“旋转搜索”、“人工确认”等特定词汇时,请使用以下对应关系:
- **"旋转搜索"** -> 使用 `rotate_search` 动作。
- **"人工确认"** -> 使用 `wait_for_confirmation` 动作(通常放在 `object_detect` 或 `object_detected` 之后)。
**示例:** "到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。"
```json
{
"type": "Sequence",
"name": "SearchAndConfirm",
"children": [
{"type":"action", "name":"fly_to_waypoint", "params":{"x":20, "y":150, "z":10}},
{"type":"action", "name":"rotate_search", "params":{"center_x":20, "y":150, "z":10, "radius":30, "duration":60}},
{"type":"action", "name":"wait_for_confirmation", "params":{"message":"Found yellow shirt male, confirm to photo?", "timeout":60}},
{"type":"action", "name":"strike_target", "params":{"target_class":"person", "description":"yellow shirt"}}
]
}
```
### 2. 环绕侦察 (Circular Reconnaissance with Interrupts)
当用户要求“环绕侦察”或“巡逻中发现目标即拍照”时,必须使用 `Selector` + `SuccessIsFailure` (Decorator) + `fly_to_waypoint` 的组合模式。
**逻辑解释:** 这是一个“顺路侦察”模式。无人机在飞往下一个航点的过程中Selector先尝试检测目标ReactiveWork。如果检测到目标并拍照成功`SuccessIsFailure` 会欺骗 Selector 说“失败了”,从而迫使 Selector 继续执行 `fly_to_waypoint`,确保无人机不会因为拍了照就停在半路,而是继续飞向终点。
**结构模板:**
```json
{
"name": "GoToWaypointX",
"type": "Selector",
"children": [
{"type": "condition", "name": "at_waypoint", "params": {"target_position": [x, y, z]}},
{
"name": "ReactiveWork",
"type": "Selector",
"children": [
{
"name": "SuccessIsFailure",
"type": "decorator",
"child": {
"name": "DetectHoverPhoto",
"type": "Sequence",
"children": [
{"name": "object_detect", "type": "action", "params": {"target_class": "person"}},
{"name": "loiter", "type": "action", "params": {"time": 2.0}}
]
}
},
{"name": "fly_to_waypoint", "type": "action", "params": {"x": x, "y": y, "z": z}}
]
}
]
}
```
## 七、输出要求
仅输出1个严格符合上述所有规则的JSON对象**确保1. 优先级排序逻辑正确填入`description`2. `target_class`匹配预定义列表3. 行为树结构不变4. 后端解析与Schema验证无错误**,无任何冗余内容。
【强制规则】仅生成包含root的复杂行为树JSON不得输出简单模式不得包含mode字段或仅有action节点
=== User Prompt ===
地面待命,去研究所正大门,搜索扎辫子女子并拍照。
[2026-01-02 14:10:05]
完整响应内容:
[2026-01-02 14:10:05] {
"root": {
"type": "Sequence",
"name": "MainTask",
"children": [
{
"type": "action",
"name": "preflight_checks",
"params": {
"check_level": "basic"
}
},
{
"type": "action",
"name": "fly_to_waypoint",
"params": {
"x": 200,
"y": 150,
"z": 10
}
},
{
"type": "action",
"name": "rotate_search",
"params": {
"center_x": 200,
"center_y": 150,
"center_z": 10,
"radius": 30,
"duration": 60
}
},
{
"type": "action",
"name": "wait_for_confirmation",
"params": {
"message": "Found woman with braid, confirm to photo?",
"timeout": 60
}
},
{
"type": "action",
"name": "object_detect",
"params": {
"target_class": "person",
"description": "(扎辫子女子)"
}
},
{
"type": "action",
"name": "strike_target",
"params": {
"target_class": "person",
"description": "扎辫子女子"
}
}
]
},
"plan_id": "06a44e45-153e-4f15-9c73-bcebd24e08cd",
"visualization_url": "/static/py_tree.png",
"final_prompt": "=== System Prompt ===\n任务根据用户任意任务指令生成结构化可执行的无人机行为树PytreeJSON。**仅输出单一JSON对象无任何自然语言、注释或额外内容**。\n\n## 一、核心节点定义(格式不可修改,确保后端解析)\n#### 1. 可用节点定义 (必须遵守)\n你必须严格从以下JSON定义的列表中选择节点构建行为树不允许使用未定义节点\n```json\n{\n \"actions\": [\n {\"name\":\"takeoff\",\"params\":{\"altitude\":\"float[1,100]默认2\"}},\n {\"name\":\"land\",\"params\":{\"mode\":\"'current'/'home'\"}},\n {\"name\":\"fly_to_waypoint\",\"params\":{\"x\":\"±10000\",\"y\":\"±10000\",\"z\":\"[1,5000]\",\"acceptance_radius\":\"默认2.0\"}},\n {\"name\":\"move_direction\",\"params\":{\"direction\":\"north/south/east/west/forward/backward/left/right\",\"distance\":\"[1,10000],缺省持续移动\"}},\n {\"name\":\"orbit_around_point\",\"params\":{\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,1000]\",\"laps\":\"[1,20]\",\"clockwise\":\"默认true\",\"speed_mps\":\"[0.5,15]\",\"gimbal_lock\":\"默认true\"}},\n {\"name\":\"orbit_around_target\",\"params\":{\"target_class\":\"见object_detect列表\",\"description\":\"可选,目标属性\",\"radius\":\"[5,1000]\",\"laps\":\"[1,20]\",\"clockwise\":\"默认true\",\"speed_mps\":\"[0.5,15]\",\"gimbal_lock\":\"默认true\"}},\n {\"name\":\"loiter\",\"params\":{\"duration\":\"[1,600]秒/until_condition:可选\"}},\n {\"name\":\"object_detect\",\"params\":{\"target_class\":\"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush\",\"description\":\"可选,\",\"count\":\"默认1\"}},\n {\"name\":\"strike_target\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"battle_damage_assessment\",\"params\":{\"target_class\":\"同object_detect\",\"assessment_time\":\"[5,60]默认15\"}},\n {\"name\":\"search_pattern\",\"params\":{\"pattern_type\":\"spiral/grid\",\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,1000]\",\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"track_object\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"track_time\":\"[1,600]秒(必传,不可用'duration'\",\"min_confidence\":\"[0.5,1.0]默认0.7\",\"safe_distance\":\"[2,50]默认10\"}},\n {\"name\":\"deliver_payload\",\"params\":{\"payload_type\":\"string\",\"release_altitude\":\"[2,100]默认5\"}},\n {\"name\":\"preflight_checks\",\"params\":{\"check_level\":\"basic/comprehensive\"}},\n {\"name\":\"emergency_return\",\"params\":{\"reason\":\"string\"}},\n {\"name\":\"rotate_search\",\"params\":{\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,100]\",\"speed_mps\":\"[0.5,10]\",\"duration\":\"[10,600]秒\"}},\n {\"name\":\"wait_for_confirmation\",\"params\":{\"message\":\"string\",\"timeout\":\"[10,600]秒\"}}\n ],\n \"conditions\": [\n {\"name\":\"battery_above\",\"params\":{\"threshold\":\"[0.0,1.0],必传\"}},\n {\"name\":\"at_waypoint\",\"params\":{\"x\":\"±10000\",\"y\":\"±10000\",\"z\":\"[1,5000]\",\"tolerance\":\"默认3.0\"}},\n {\"name\":\"object_detected\",\"params\":{\"target_class\":\"同object_detect必传\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"target_destroyed\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"confidence\":\"[0.5,1.0]默认0.8\"}},\n {\"name\":\"time_elapsed\",\"params\":{\"duration\":\"[1,2700]秒\"}},\n {\"name\":\"gps_status\",\"params\":{\"min_satellites\":\"int[6,15]必传如8\"}}\n ],\n \"control_flow\": [\n {\"name\":\"Sequence\",\"params\":{},\"children\":\"子节点数组(按序执行,全成功则成功)\"},\n {\"name\":\"Selector\",\"params\":{\"memory\":\"默认true\"},\"children\":\"子节点数组(执行到成功为止)\"},\n {\"name\":\"Parallel\",\"params\":{\"policy\":\"all_success\"},\"children\":\"子节点数组(同时执行,严禁用'one_success'\"}\n ],\n \"decorators\": [\n {\"name\":\"SuccessIsFailure\",\"params\":{},\"child\":\"单个子节点(成功转失败,失败仍失败)\"}\n ]\n}\n```\n\n\n## 二、节点必填字段后端Schema强制要求缺一验证失败\n每个节点必须包含以下字段字段名/类型不可自定义:\n1. **`type`** \n - 动作节点→`\"action\"`,条件节点→`\"condition\"`,装饰器节点→`\"decorator\"`,控制流节点→`\"Sequence\"`/`\"Selector\"`/`\"Parallel\"`(与`name`字段值完全一致);\n2. **`name`**必须是上述JSON中`actions`/`conditions`/`control_flow`/`decorators`下的`name`值;\n3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;\n4. **`children`**:仅控制流节点必含(子节点数组);\n5. **`child`**:仅装饰器节点必含(单个子节点对象)。\n\n\n## 三、行为树固定结构(通用不变)\n根节点通常是 `Sequence` 或 `Selector`,直接包含任务逻辑。不再强制包含 `SafetyMonitor` 或 `Parallel` 根节点。\n\n示例结构简单顺序任务\n```json\n{\n \"root\": {\n \"type\": \"Sequence\",\n \"name\": \"MainTask\",\n \"params\": {},\n \"children\": [\n {\"type\":\"action\",\"name\":\"takeoff\",\"params\":{\"altitude\":10.0}},\n {\"type\":\"action\",\"name\":\"fly_to_waypoint\",\"params\":{\"x\":200.0,\"y\":150.0,\"z\":10.0}},\n {\"type\":\"action\",\"name\":\"land\",\"params\":{\"mode\":\"home\"}}\n ]\n }\n}\n```\n\n\n## 四、优先级排序任务通用示例\n当用户指令中明确提出有多个待考察且具有优先级关系的物体时节点描述须为优先级关系。比如当指令为已知有三个气球危险级关系为红色气球大于蓝色气球大于绿色气球要求优先跟踪最危险的气球时节点的描述参考下表情形。\n| 用户指令场景 | `target_class` | `description` | 核心节点示例search_pattern |\n|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|\n| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{\"type\":\"action\",\"name\":\"search_pattern\",\"params\":{\"pattern_type\":\"grid\",\"center_x\":200,\"center_y\":150,\"center_z\":10,\"radius\":50,\"target_class\":\"balloon\",\"description\":\"(红>蓝>绿)\"}}` |\n| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{\"type\":\"action\",\"name\":\"object_detect\",\"params\":{\"target_class\":\"truck\",\"description\":\"(军用卡车>民用卡车>面包车)\"}}` |\n\n\n## 五、高频错误规避(确保验证通过)\n1. 优先级排序不可修改`target_class`:如“民用卡车、面包车与军用卡车中,军用卡车优先”,`target_class`仍为`truck`,仅用`description`填排序规则;\n2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;\n3. `track_object`必传`track_time`:不可用`duration`替代如跟踪30秒填`\"track_time\":30.0`\n4. `gps_status`的`min_satellites`必须在6-15之间如8不可缺省\n5. 无自定义节点:“锁定高优先级目标”需通过`object_detect`+`object_detected`实现不可用“lock_high_risk_target”。\n\n\n## 六、新场景模式指南 (New Scenarios)\n\n### 1. 预期场景 (Expected Scenarios)\n当用户指令包含“旋转搜索”、“人工确认”等特定词汇时请使用以下对应关系\n- **\"旋转搜索\"** -> 使用 `rotate_search` 动作。\n- **\"人工确认\"** -> 使用 `wait_for_confirmation` 动作(通常放在 `object_detect` 或 `object_detected` 之后)。\n\n**示例:** \"到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。\"\n```json\n{\n \"type\": \"Sequence\",\n \"name\": \"SearchAndConfirm\",\n \"children\": [\n {\"type\":\"action\", \"name\":\"fly_to_waypoint\", \"params\":{\"x\":20, \"y\":150, \"z\":10}},\n {\"type\":\"action\", \"name\":\"rotate_search\", \"params\":{\"center_x\":20, \"y\":150, \"z\":10, \"radius\":30, \"duration\":60}},\n {\"type\":\"action\", \"name\":\"wait_for_confirmation\", \"params\":{\"message\":\"Found yellow shirt male, confirm to photo?\", \"timeout\":60}},\n {\"type\":\"action\", \"name\":\"strike_target\", \"params\":{\"target_class\":\"person\", \"description\":\"yellow shirt\"}}\n ]\n}\n```\n\n### 2. 环绕侦察 (Circular Reconnaissance with Interrupts)\n当用户要求“环绕侦察”或“巡逻中发现目标即拍照”时必须使用 `Selector` + `SuccessIsFailure` (Decorator) + `fly_to_waypoint` 的组合模式。\n**逻辑解释:** 这是一个“顺路侦察”模式。无人机在飞往下一个航点的过程中Selector先尝试检测目标ReactiveWork。如果检测到目标并拍照成功`SuccessIsFailure` 会欺骗 Selector 说“失败了”,从而迫使 Selector 继续执行 `fly_to_waypoint`,确保无人机不会因为拍了照就停在半路,而是继续飞向终点。\n\n**结构模板:**\n```json\n{\n \"name\": \"GoToWaypointX\",\n \"type\": \"Selector\",\n \"children\": [\n {\"type\": \"condition\", \"name\": \"at_waypoint\", \"params\": {\"target_position\": [x, y, z]}},\n {\n \"name\": \"ReactiveWork\",\n \"type\": \"Selector\",\n \"children\": [\n {\n \"name\": \"SuccessIsFailure\",\n \"type\": \"decorator\",\n \"child\": {\n \"name\": \"DetectHoverPhoto\",\n \"type\": \"Sequence\",\n \"children\": [\n {\"name\": \"object_detect\", \"type\": \"action\", \"params\": {\"target_class\": \"person\"}},\n {\"name\": \"loiter\", \"type\": \"action\", \"params\": {\"time\": 2.0}}\n ]\n }\n },\n {\"name\": \"fly_to_waypoint\", \"type\": \"action\", \"params\": {\"x\": x, \"y\": y, \"z\": z}}\n ]\n }\n ]\n}\n```\n\n\n## 七、输出要求\n仅输出1个严格符合上述所有规则的JSON对象**确保1. 优先级排序逻辑正确填入`description`2. `target_class`匹配预定义列表3. 行为树结构不变4. 后端解析与Schema验证无错误**,无任何冗余内容。\n\n\n【强制规则】仅生成包含root的复杂行为树JSON不得输出简单模式不得包含mode字段或仅有action节点。\n\n=== User Prompt ===\n地面待命,去研究所正大门,搜索扎辫子女子并拍照。"
}
[2026-01-02 14:10:05]
--- Validation Checks ---
[2026-01-02 14:10:05] PASS: Response is a valid JSON object.
[2026-01-02 14:10:05] PASS: Response contains a valid 'root' key.
[2026-01-02 14:10:05] PASS: Response contains a valid 'visualization_url': /static/py_tree.png
[2026-01-02 14:10:05] ✅ Test completed successfully
[2026-01-02 14:10:05] ================================================================================
[2026-01-02 14:10:05]
[2026-01-02 14:10:05] ================================================================================
[2026-01-02 14:10:05] --- API Test: Scene 2: Search with Confirmation (Expected.csv Row 5) ---
[2026-01-02 14:10:05] URL: http://127.0.0.1:8000/generate_plan
[2026-01-02 14:10:05] Sending Prompt: "空中待命/任务中,到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。"
[2026-01-02 14:10:11] ✅ Received Response:
[2026-01-02 14:10:11]
📝 组织后的Prompt:
[2026-01-02 14:10:11] === System Prompt ===
任务根据用户任意任务指令生成结构化可执行的无人机行为树PytreeJSON。**仅输出单一JSON对象无任何自然语言、注释或额外内容**。
## 一、核心节点定义(格式不可修改,确保后端解析)
#### 1. 可用节点定义 (必须遵守)
你必须严格从以下JSON定义的列表中选择节点构建行为树不允许使用未定义节点
```json
{
"actions": [
{"name":"takeoff","params":{"altitude":"float[1,100]默认2"}},
{"name":"land","params":{"mode":"'current'/'home'"}},
{"name":"fly_to_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","acceptance_radius":"默认2.0"}},
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省持续移动"}},
{"name":"orbit_around_point","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
{"name":"orbit_around_target","params":{"target_class":"见object_detect列表","description":"可选,目标属性","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
{"name":"loiter","params":{"duration":"[1,600]秒/until_condition:可选"}},
{"name":"object_detect","params":{"target_class":"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush","description":"可选,","count":"默认1"}},
{"name":"strike_target","params":{"target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
{"name":"battle_damage_assessment","params":{"target_class":"同object_detect","assessment_time":"[5,60]默认15"}},
{"name":"search_pattern","params":{"pattern_type":"spiral/grid","center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
{"name":"track_object","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration'","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}},
{"name":"deliver_payload","params":{"payload_type":"string","release_altitude":"[2,100]默认5"}},
{"name":"preflight_checks","params":{"check_level":"basic/comprehensive"}},
{"name":"emergency_return","params":{"reason":"string"}},
{"name":"rotate_search","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,100]","speed_mps":"[0.5,10]","duration":"[10,600]秒"}},
{"name":"wait_for_confirmation","params":{"message":"string","timeout":"[10,600]秒"}}
],
"conditions": [
{"name":"battery_above","params":{"threshold":"[0.0,1.0],必传"}},
{"name":"at_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","tolerance":"默认3.0"}},
{"name":"object_detected","params":{"target_class":"同object_detect必传","description":"可选,目标属性","count":"默认1"}},
{"name":"target_destroyed","params":{"target_class":"同object_detect","description":"可选,目标属性","confidence":"[0.5,1.0]默认0.8"}},
{"name":"time_elapsed","params":{"duration":"[1,2700]秒"}},
{"name":"gps_status","params":{"min_satellites":"int[6,15]必传如8"}}
],
"control_flow": [
{"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"},
{"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"},
{"name":"Parallel","params":{"policy":"all_success"},"children":"子节点数组(同时执行,严禁用'one_success'"}
],
"decorators": [
{"name":"SuccessIsFailure","params":{},"child":"单个子节点(成功转失败,失败仍失败)"}
]
}
```
## 二、节点必填字段后端Schema强制要求缺一验证失败
每个节点必须包含以下字段,字段名/类型不可自定义:
1. **`type`**
- 动作节点→`"action"`,条件节点→`"condition"`,装饰器节点→`"decorator"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`(与`name`字段值完全一致);
2. **`name`**必须是上述JSON中`actions`/`conditions`/`control_flow`/`decorators`下的`name`值;
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;
4. **`children`**:仅控制流节点必含(子节点数组);
5. **`child`**:仅装饰器节点必含(单个子节点对象)。
## 三、行为树固定结构(通用不变)
根节点通常是 `Sequence` 或 `Selector`,直接包含任务逻辑。不再强制包含 `SafetyMonitor` 或 `Parallel` 根节点。
示例结构(简单顺序任务):
```json
{
"root": {
"type": "Sequence",
"name": "MainTask",
"params": {},
"children": [
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
{"type":"action","name":"fly_to_waypoint","params":{"x":200.0,"y":150.0,"z":10.0}},
{"type":"action","name":"land","params":{"mode":"home"}}
]
}
}
```
## 四、优先级排序任务通用示例
当用户指令中明确提出有多个待考察且具有优先级关系的物体时,节点描述须为优先级关系。比如当指令为已知有三个气球,危险级关系为红色气球大于蓝色气球大于绿色气球,要求优先跟踪最危险的气球时,节点的描述参考下表情形。
| 用户指令场景 | `target_class` | `description` | 核心节点示例search_pattern |
|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|
| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{"type":"action","name":"search_pattern","params":{"pattern_type":"grid","center_x":200,"center_y":150,"center_z":10,"radius":50,"target_class":"balloon","description":"(红>蓝>绿)"}}` |
| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{"type":"action","name":"object_detect","params":{"target_class":"truck","description":"(军用卡车>民用卡车>面包车)"}}` |
## 五、高频错误规避(确保验证通过)
1. 优先级排序不可修改`target_class`:如“民用卡车、面包车与军用卡车中,军用卡车优先”,`target_class`仍为`truck`,仅用`description`填排序规则;
2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;
3. `track_object`必传`track_time`:不可用`duration`替代如跟踪30秒填`"track_time":30.0`
4. `gps_status`的`min_satellites`必须在6-15之间如8不可缺省
5. 无自定义节点:“锁定高优先级目标”需通过`object_detect`+`object_detected`实现不可用“lock_high_risk_target”。
## 六、新场景模式指南 (New Scenarios)
### 1. 预期场景 (Expected Scenarios)
当用户指令包含“旋转搜索”、“人工确认”等特定词汇时,请使用以下对应关系:
- **"旋转搜索"** -> 使用 `rotate_search` 动作。
- **"人工确认"** -> 使用 `wait_for_confirmation` 动作(通常放在 `object_detect` 或 `object_detected` 之后)。
**示例:** "到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。"
```json
{
"type": "Sequence",
"name": "SearchAndConfirm",
"children": [
{"type":"action", "name":"fly_to_waypoint", "params":{"x":20, "y":150, "z":10}},
{"type":"action", "name":"rotate_search", "params":{"center_x":20, "y":150, "z":10, "radius":30, "duration":60}},
{"type":"action", "name":"wait_for_confirmation", "params":{"message":"Found yellow shirt male, confirm to photo?", "timeout":60}},
{"type":"action", "name":"strike_target", "params":{"target_class":"person", "description":"yellow shirt"}}
]
}
```
### 2. 环绕侦察 (Circular Reconnaissance with Interrupts)
当用户要求“环绕侦察”或“巡逻中发现目标即拍照”时,必须使用 `Selector` + `SuccessIsFailure` (Decorator) + `fly_to_waypoint` 的组合模式。
**逻辑解释:** 这是一个“顺路侦察”模式。无人机在飞往下一个航点的过程中Selector先尝试检测目标ReactiveWork。如果检测到目标并拍照成功`SuccessIsFailure` 会欺骗 Selector 说“失败了”,从而迫使 Selector 继续执行 `fly_to_waypoint`,确保无人机不会因为拍了照就停在半路,而是继续飞向终点。
**结构模板:**
```json
{
"name": "GoToWaypointX",
"type": "Selector",
"children": [
{"type": "condition", "name": "at_waypoint", "params": {"target_position": [x, y, z]}},
{
"name": "ReactiveWork",
"type": "Selector",
"children": [
{
"name": "SuccessIsFailure",
"type": "decorator",
"child": {
"name": "DetectHoverPhoto",
"type": "Sequence",
"children": [
{"name": "object_detect", "type": "action", "params": {"target_class": "person"}},
{"name": "loiter", "type": "action", "params": {"time": 2.0}}
]
}
},
{"name": "fly_to_waypoint", "type": "action", "params": {"x": x, "y": y, "z": z}}
]
}
]
}
```
## 七、输出要求
仅输出1个严格符合上述所有规则的JSON对象**确保1. 优先级排序逻辑正确填入`description`2. `target_class`匹配预定义列表3. 行为树结构不变4. 后端解析与Schema验证无错误**,无任何冗余内容。
【强制规则】仅生成包含root的复杂行为树JSON不得输出简单模式不得包含mode字段或仅有action节点
=== User Prompt ===
空中待命/任务中,到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。
[2026-01-02 14:10:11]
完整响应内容:
[2026-01-02 14:10:11] {
"root": {
"type": "Sequence",
"name": "SearchAndConfirm",
"children": [
{
"type": "action",
"name": "fly_to_waypoint",
"params": {
"x": 20,
"y": 150,
"z": 10
}
},
{
"type": "action",
"name": "rotate_search",
"params": {
"center_x": 20,
"y": 150,
"z": 10,
"radius": 30,
"duration": 60
}
},
{
"type": "action",
"name": "wait_for_confirmation",
"params": {
"message": "Found yellow shirt male, confirm to photo?",
"timeout": 60
}
},
{
"type": "action",
"name": "strike_target",
"params": {
"target_class": "person",
"description": "yellow shirt"
}
}
]
},
"plan_id": "6631de0c-b13d-4367-96c1-0109896291aa",
"visualization_url": "/static/py_tree.png",
"final_prompt": "=== System Prompt ===\n任务根据用户任意任务指令生成结构化可执行的无人机行为树PytreeJSON。**仅输出单一JSON对象无任何自然语言、注释或额外内容**。\n\n## 一、核心节点定义(格式不可修改,确保后端解析)\n#### 1. 可用节点定义 (必须遵守)\n你必须严格从以下JSON定义的列表中选择节点构建行为树不允许使用未定义节点\n```json\n{\n \"actions\": [\n {\"name\":\"takeoff\",\"params\":{\"altitude\":\"float[1,100]默认2\"}},\n {\"name\":\"land\",\"params\":{\"mode\":\"'current'/'home'\"}},\n {\"name\":\"fly_to_waypoint\",\"params\":{\"x\":\"±10000\",\"y\":\"±10000\",\"z\":\"[1,5000]\",\"acceptance_radius\":\"默认2.0\"}},\n {\"name\":\"move_direction\",\"params\":{\"direction\":\"north/south/east/west/forward/backward/left/right\",\"distance\":\"[1,10000],缺省持续移动\"}},\n {\"name\":\"orbit_around_point\",\"params\":{\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,1000]\",\"laps\":\"[1,20]\",\"clockwise\":\"默认true\",\"speed_mps\":\"[0.5,15]\",\"gimbal_lock\":\"默认true\"}},\n {\"name\":\"orbit_around_target\",\"params\":{\"target_class\":\"见object_detect列表\",\"description\":\"可选,目标属性\",\"radius\":\"[5,1000]\",\"laps\":\"[1,20]\",\"clockwise\":\"默认true\",\"speed_mps\":\"[0.5,15]\",\"gimbal_lock\":\"默认true\"}},\n {\"name\":\"loiter\",\"params\":{\"duration\":\"[1,600]秒/until_condition:可选\"}},\n {\"name\":\"object_detect\",\"params\":{\"target_class\":\"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush\",\"description\":\"可选,\",\"count\":\"默认1\"}},\n {\"name\":\"strike_target\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"battle_damage_assessment\",\"params\":{\"target_class\":\"同object_detect\",\"assessment_time\":\"[5,60]默认15\"}},\n {\"name\":\"search_pattern\",\"params\":{\"pattern_type\":\"spiral/grid\",\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,1000]\",\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"track_object\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"track_time\":\"[1,600]秒(必传,不可用'duration'\",\"min_confidence\":\"[0.5,1.0]默认0.7\",\"safe_distance\":\"[2,50]默认10\"}},\n {\"name\":\"deliver_payload\",\"params\":{\"payload_type\":\"string\",\"release_altitude\":\"[2,100]默认5\"}},\n {\"name\":\"preflight_checks\",\"params\":{\"check_level\":\"basic/comprehensive\"}},\n {\"name\":\"emergency_return\",\"params\":{\"reason\":\"string\"}},\n {\"name\":\"rotate_search\",\"params\":{\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,100]\",\"speed_mps\":\"[0.5,10]\",\"duration\":\"[10,600]秒\"}},\n {\"name\":\"wait_for_confirmation\",\"params\":{\"message\":\"string\",\"timeout\":\"[10,600]秒\"}}\n ],\n \"conditions\": [\n {\"name\":\"battery_above\",\"params\":{\"threshold\":\"[0.0,1.0],必传\"}},\n {\"name\":\"at_waypoint\",\"params\":{\"x\":\"±10000\",\"y\":\"±10000\",\"z\":\"[1,5000]\",\"tolerance\":\"默认3.0\"}},\n {\"name\":\"object_detected\",\"params\":{\"target_class\":\"同object_detect必传\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"target_destroyed\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"confidence\":\"[0.5,1.0]默认0.8\"}},\n {\"name\":\"time_elapsed\",\"params\":{\"duration\":\"[1,2700]秒\"}},\n {\"name\":\"gps_status\",\"params\":{\"min_satellites\":\"int[6,15]必传如8\"}}\n ],\n \"control_flow\": [\n {\"name\":\"Sequence\",\"params\":{},\"children\":\"子节点数组(按序执行,全成功则成功)\"},\n {\"name\":\"Selector\",\"params\":{\"memory\":\"默认true\"},\"children\":\"子节点数组(执行到成功为止)\"},\n {\"name\":\"Parallel\",\"params\":{\"policy\":\"all_success\"},\"children\":\"子节点数组(同时执行,严禁用'one_success'\"}\n ],\n \"decorators\": [\n {\"name\":\"SuccessIsFailure\",\"params\":{},\"child\":\"单个子节点(成功转失败,失败仍失败)\"}\n ]\n}\n```\n\n\n## 二、节点必填字段后端Schema强制要求缺一验证失败\n每个节点必须包含以下字段字段名/类型不可自定义:\n1. **`type`** \n - 动作节点→`\"action\"`,条件节点→`\"condition\"`,装饰器节点→`\"decorator\"`,控制流节点→`\"Sequence\"`/`\"Selector\"`/`\"Parallel\"`(与`name`字段值完全一致);\n2. **`name`**必须是上述JSON中`actions`/`conditions`/`control_flow`/`decorators`下的`name`值;\n3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;\n4. **`children`**:仅控制流节点必含(子节点数组);\n5. **`child`**:仅装饰器节点必含(单个子节点对象)。\n\n\n## 三、行为树固定结构(通用不变)\n根节点通常是 `Sequence` 或 `Selector`,直接包含任务逻辑。不再强制包含 `SafetyMonitor` 或 `Parallel` 根节点。\n\n示例结构简单顺序任务\n```json\n{\n \"root\": {\n \"type\": \"Sequence\",\n \"name\": \"MainTask\",\n \"params\": {},\n \"children\": [\n {\"type\":\"action\",\"name\":\"takeoff\",\"params\":{\"altitude\":10.0}},\n {\"type\":\"action\",\"name\":\"fly_to_waypoint\",\"params\":{\"x\":200.0,\"y\":150.0,\"z\":10.0}},\n {\"type\":\"action\",\"name\":\"land\",\"params\":{\"mode\":\"home\"}}\n ]\n }\n}\n```\n\n\n## 四、优先级排序任务通用示例\n当用户指令中明确提出有多个待考察且具有优先级关系的物体时节点描述须为优先级关系。比如当指令为已知有三个气球危险级关系为红色气球大于蓝色气球大于绿色气球要求优先跟踪最危险的气球时节点的描述参考下表情形。\n| 用户指令场景 | `target_class` | `description` | 核心节点示例search_pattern |\n|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|\n| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{\"type\":\"action\",\"name\":\"search_pattern\",\"params\":{\"pattern_type\":\"grid\",\"center_x\":200,\"center_y\":150,\"center_z\":10,\"radius\":50,\"target_class\":\"balloon\",\"description\":\"(红>蓝>绿)\"}}` |\n| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{\"type\":\"action\",\"name\":\"object_detect\",\"params\":{\"target_class\":\"truck\",\"description\":\"(军用卡车>民用卡车>面包车)\"}}` |\n\n\n## 五、高频错误规避(确保验证通过)\n1. 优先级排序不可修改`target_class`:如“民用卡车、面包车与军用卡车中,军用卡车优先”,`target_class`仍为`truck`,仅用`description`填排序规则;\n2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;\n3. `track_object`必传`track_time`:不可用`duration`替代如跟踪30秒填`\"track_time\":30.0`\n4. `gps_status`的`min_satellites`必须在6-15之间如8不可缺省\n5. 无自定义节点:“锁定高优先级目标”需通过`object_detect`+`object_detected`实现不可用“lock_high_risk_target”。\n\n\n## 六、新场景模式指南 (New Scenarios)\n\n### 1. 预期场景 (Expected Scenarios)\n当用户指令包含“旋转搜索”、“人工确认”等特定词汇时请使用以下对应关系\n- **\"旋转搜索\"** -> 使用 `rotate_search` 动作。\n- **\"人工确认\"** -> 使用 `wait_for_confirmation` 动作(通常放在 `object_detect` 或 `object_detected` 之后)。\n\n**示例:** \"到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。\"\n```json\n{\n \"type\": \"Sequence\",\n \"name\": \"SearchAndConfirm\",\n \"children\": [\n {\"type\":\"action\", \"name\":\"fly_to_waypoint\", \"params\":{\"x\":20, \"y\":150, \"z\":10}},\n {\"type\":\"action\", \"name\":\"rotate_search\", \"params\":{\"center_x\":20, \"y\":150, \"z\":10, \"radius\":30, \"duration\":60}},\n {\"type\":\"action\", \"name\":\"wait_for_confirmation\", \"params\":{\"message\":\"Found yellow shirt male, confirm to photo?\", \"timeout\":60}},\n {\"type\":\"action\", \"name\":\"strike_target\", \"params\":{\"target_class\":\"person\", \"description\":\"yellow shirt\"}}\n ]\n}\n```\n\n### 2. 环绕侦察 (Circular Reconnaissance with Interrupts)\n当用户要求“环绕侦察”或“巡逻中发现目标即拍照”时必须使用 `Selector` + `SuccessIsFailure` (Decorator) + `fly_to_waypoint` 的组合模式。\n**逻辑解释:** 这是一个“顺路侦察”模式。无人机在飞往下一个航点的过程中Selector先尝试检测目标ReactiveWork。如果检测到目标并拍照成功`SuccessIsFailure` 会欺骗 Selector 说“失败了”,从而迫使 Selector 继续执行 `fly_to_waypoint`,确保无人机不会因为拍了照就停在半路,而是继续飞向终点。\n\n**结构模板:**\n```json\n{\n \"name\": \"GoToWaypointX\",\n \"type\": \"Selector\",\n \"children\": [\n {\"type\": \"condition\", \"name\": \"at_waypoint\", \"params\": {\"target_position\": [x, y, z]}},\n {\n \"name\": \"ReactiveWork\",\n \"type\": \"Selector\",\n \"children\": [\n {\n \"name\": \"SuccessIsFailure\",\n \"type\": \"decorator\",\n \"child\": {\n \"name\": \"DetectHoverPhoto\",\n \"type\": \"Sequence\",\n \"children\": [\n {\"name\": \"object_detect\", \"type\": \"action\", \"params\": {\"target_class\": \"person\"}},\n {\"name\": \"loiter\", \"type\": \"action\", \"params\": {\"time\": 2.0}}\n ]\n }\n },\n {\"name\": \"fly_to_waypoint\", \"type\": \"action\", \"params\": {\"x\": x, \"y\": y, \"z\": z}}\n ]\n }\n ]\n}\n```\n\n\n## 七、输出要求\n仅输出1个严格符合上述所有规则的JSON对象**确保1. 优先级排序逻辑正确填入`description`2. `target_class`匹配预定义列表3. 行为树结构不变4. 后端解析与Schema验证无错误**,无任何冗余内容。\n\n\n【强制规则】仅生成包含root的复杂行为树JSON不得输出简单模式不得包含mode字段或仅有action节点。\n\n=== User Prompt ===\n空中待命/任务中,到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。"
}
[2026-01-02 14:10:11]
--- Validation Checks ---
[2026-01-02 14:10:11] PASS: Response is a valid JSON object.
[2026-01-02 14:10:11] PASS: Response contains a valid 'root' key.
[2026-01-02 14:10:11] PASS: Response contains a valid 'visualization_url': /static/py_tree.png
[2026-01-02 14:10:11] ✅ Test completed successfully
[2026-01-02 14:10:11] ================================================================================
[2026-01-02 14:10:11]
[2026-01-02 14:10:11] ================================================================================
[2026-01-02 14:10:11] --- API Test: Scene 3: Circular Reconnaissance (Selector Logic) ---
[2026-01-02 14:10:11] URL: http://127.0.0.1:8000/generate_plan
[2026-01-02 14:10:11] Sending Prompt: "执行环绕侦察任务,沿着研究所外围巡逻,如果发现人就悬停拍照。"
[2026-01-02 14:10:27] ✅ Received Response:
[2026-01-02 14:10:27]
📝 组织后的Prompt:
[2026-01-02 14:10:27] === System Prompt ===
任务根据用户任意任务指令生成结构化可执行的无人机行为树PytreeJSON。**仅输出单一JSON对象无任何自然语言、注释或额外内容**。
## 一、核心节点定义(格式不可修改,确保后端解析)
#### 1. 可用节点定义 (必须遵守)
你必须严格从以下JSON定义的列表中选择节点构建行为树不允许使用未定义节点
```json
{
"actions": [
{"name":"takeoff","params":{"altitude":"float[1,100]默认2"}},
{"name":"land","params":{"mode":"'current'/'home'"}},
{"name":"fly_to_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","acceptance_radius":"默认2.0"}},
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省持续移动"}},
{"name":"orbit_around_point","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
{"name":"orbit_around_target","params":{"target_class":"见object_detect列表","description":"可选,目标属性","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
{"name":"loiter","params":{"duration":"[1,600]秒/until_condition:可选"}},
{"name":"object_detect","params":{"target_class":"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush","description":"可选,","count":"默认1"}},
{"name":"strike_target","params":{"target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
{"name":"battle_damage_assessment","params":{"target_class":"同object_detect","assessment_time":"[5,60]默认15"}},
{"name":"search_pattern","params":{"pattern_type":"spiral/grid","center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
{"name":"track_object","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration'","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}},
{"name":"deliver_payload","params":{"payload_type":"string","release_altitude":"[2,100]默认5"}},
{"name":"preflight_checks","params":{"check_level":"basic/comprehensive"}},
{"name":"emergency_return","params":{"reason":"string"}},
{"name":"rotate_search","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,100]","speed_mps":"[0.5,10]","duration":"[10,600]秒"}},
{"name":"wait_for_confirmation","params":{"message":"string","timeout":"[10,600]秒"}}
],
"conditions": [
{"name":"battery_above","params":{"threshold":"[0.0,1.0],必传"}},
{"name":"at_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","tolerance":"默认3.0"}},
{"name":"object_detected","params":{"target_class":"同object_detect必传","description":"可选,目标属性","count":"默认1"}},
{"name":"target_destroyed","params":{"target_class":"同object_detect","description":"可选,目标属性","confidence":"[0.5,1.0]默认0.8"}},
{"name":"time_elapsed","params":{"duration":"[1,2700]秒"}},
{"name":"gps_status","params":{"min_satellites":"int[6,15]必传如8"}}
],
"control_flow": [
{"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"},
{"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"},
{"name":"Parallel","params":{"policy":"all_success"},"children":"子节点数组(同时执行,严禁用'one_success'"}
],
"decorators": [
{"name":"SuccessIsFailure","params":{},"child":"单个子节点(成功转失败,失败仍失败)"}
]
}
```
## 二、节点必填字段后端Schema强制要求缺一验证失败
每个节点必须包含以下字段,字段名/类型不可自定义:
1. **`type`**
- 动作节点→`"action"`,条件节点→`"condition"`,装饰器节点→`"decorator"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`(与`name`字段值完全一致);
2. **`name`**必须是上述JSON中`actions`/`conditions`/`control_flow`/`decorators`下的`name`值;
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;
4. **`children`**:仅控制流节点必含(子节点数组);
5. **`child`**:仅装饰器节点必含(单个子节点对象)。
## 三、行为树固定结构(通用不变)
根节点通常是 `Sequence` 或 `Selector`,直接包含任务逻辑。不再强制包含 `SafetyMonitor` 或 `Parallel` 根节点。
示例结构(简单顺序任务):
```json
{
"root": {
"type": "Sequence",
"name": "MainTask",
"params": {},
"children": [
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
{"type":"action","name":"fly_to_waypoint","params":{"x":200.0,"y":150.0,"z":10.0}},
{"type":"action","name":"land","params":{"mode":"home"}}
]
}
}
```
## 四、优先级排序任务通用示例
当用户指令中明确提出有多个待考察且具有优先级关系的物体时,节点描述须为优先级关系。比如当指令为已知有三个气球,危险级关系为红色气球大于蓝色气球大于绿色气球,要求优先跟踪最危险的气球时,节点的描述参考下表情形。
| 用户指令场景 | `target_class` | `description` | 核心节点示例search_pattern |
|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|
| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{"type":"action","name":"search_pattern","params":{"pattern_type":"grid","center_x":200,"center_y":150,"center_z":10,"radius":50,"target_class":"balloon","description":"(红>蓝>绿)"}}` |
| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{"type":"action","name":"object_detect","params":{"target_class":"truck","description":"(军用卡车>民用卡车>面包车)"}}` |
## 五、高频错误规避(确保验证通过)
1. 优先级排序不可修改`target_class`:如“民用卡车、面包车与军用卡车中,军用卡车优先”,`target_class`仍为`truck`,仅用`description`填排序规则;
2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;
3. `track_object`必传`track_time`:不可用`duration`替代如跟踪30秒填`"track_time":30.0`
4. `gps_status`的`min_satellites`必须在6-15之间如8不可缺省
5. 无自定义节点:“锁定高优先级目标”需通过`object_detect`+`object_detected`实现不可用“lock_high_risk_target”。
## 六、新场景模式指南 (New Scenarios)
### 1. 预期场景 (Expected Scenarios)
当用户指令包含“旋转搜索”、“人工确认”等特定词汇时,请使用以下对应关系:
- **"旋转搜索"** -> 使用 `rotate_search` 动作。
- **"人工确认"** -> 使用 `wait_for_confirmation` 动作(通常放在 `object_detect` 或 `object_detected` 之后)。
**示例:** "到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。"
```json
{
"type": "Sequence",
"name": "SearchAndConfirm",
"children": [
{"type":"action", "name":"fly_to_waypoint", "params":{"x":20, "y":150, "z":10}},
{"type":"action", "name":"rotate_search", "params":{"center_x":20, "y":150, "z":10, "radius":30, "duration":60}},
{"type":"action", "name":"wait_for_confirmation", "params":{"message":"Found yellow shirt male, confirm to photo?", "timeout":60}},
{"type":"action", "name":"strike_target", "params":{"target_class":"person", "description":"yellow shirt"}}
]
}
```
### 2. 环绕侦察 (Circular Reconnaissance with Interrupts)
当用户要求“环绕侦察”或“巡逻中发现目标即拍照”时,必须使用 `Selector` + `SuccessIsFailure` (Decorator) + `fly_to_waypoint` 的组合模式。
**逻辑解释:** 这是一个“顺路侦察”模式。无人机在飞往下一个航点的过程中Selector先尝试检测目标ReactiveWork。如果检测到目标并拍照成功`SuccessIsFailure` 会欺骗 Selector 说“失败了”,从而迫使 Selector 继续执行 `fly_to_waypoint`,确保无人机不会因为拍了照就停在半路,而是继续飞向终点。
**结构模板:**
```json
{
"name": "GoToWaypointX",
"type": "Selector",
"children": [
{"type": "condition", "name": "at_waypoint", "params": {"target_position": [x, y, z]}},
{
"name": "ReactiveWork",
"type": "Selector",
"children": [
{
"name": "SuccessIsFailure",
"type": "decorator",
"child": {
"name": "DetectHoverPhoto",
"type": "Sequence",
"children": [
{"name": "object_detect", "type": "action", "params": {"target_class": "person"}},
{"name": "loiter", "type": "action", "params": {"time": 2.0}}
]
}
},
{"name": "fly_to_waypoint", "type": "action", "params": {"x": x, "y": y, "z": z}}
]
}
]
}
```
## 七、输出要求
仅输出1个严格符合上述所有规则的JSON对象**确保1. 优先级排序逻辑正确填入`description`2. `target_class`匹配预定义列表3. 行为树结构不变4. 后端解析与Schema验证无错误**,无任何冗余内容。
【强制规则】仅生成包含root的复杂行为树JSON不得输出简单模式不得包含mode字段或仅有action节点
=== User Prompt ===
执行环绕侦察任务,沿着研究所外围巡逻,如果发现人就悬停拍照。
[2026-01-02 14:10:27]
完整响应内容:
[2026-01-02 14:10:27] {
"root": {
"type": "Selector",
"name": "CircumferentialReconnaissance",
"children": [
{
"type": "decorator",
"name": "SuccessIsFailure",
"child": {
"type": "Sequence",
"name": "DetectAndPhoto",
"children": [
{
"type": "action",
"name": "object_detect",
"params": {
"target_class": "person",
"description": "(优先级:人)"
}
},
{
"type": "action",
"name": "loiter",
"params": {
"time": 2.0
}
}
]
}
},
{
"type": "action",
"name": "orbit_around_point",
"params": {
"center_x": 200,
"center_y": 150,
"center_z": 10,
"radius": 50,
"laps": 2,
"clockwise": true,
"speed_mps": 5.0,
"gimbal_lock": true
}
}
]
},
"plan_id": "46a55010-9707-4972-8563-08d332917dbc",
"visualization_url": "/static/py_tree.png",
"final_prompt": "=== System Prompt ===\n任务根据用户任意任务指令生成结构化可执行的无人机行为树PytreeJSON。**仅输出单一JSON对象无任何自然语言、注释或额外内容**。\n\n## 一、核心节点定义(格式不可修改,确保后端解析)\n#### 1. 可用节点定义 (必须遵守)\n你必须严格从以下JSON定义的列表中选择节点构建行为树不允许使用未定义节点\n```json\n{\n \"actions\": [\n {\"name\":\"takeoff\",\"params\":{\"altitude\":\"float[1,100]默认2\"}},\n {\"name\":\"land\",\"params\":{\"mode\":\"'current'/'home'\"}},\n {\"name\":\"fly_to_waypoint\",\"params\":{\"x\":\"±10000\",\"y\":\"±10000\",\"z\":\"[1,5000]\",\"acceptance_radius\":\"默认2.0\"}},\n {\"name\":\"move_direction\",\"params\":{\"direction\":\"north/south/east/west/forward/backward/left/right\",\"distance\":\"[1,10000],缺省持续移动\"}},\n {\"name\":\"orbit_around_point\",\"params\":{\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,1000]\",\"laps\":\"[1,20]\",\"clockwise\":\"默认true\",\"speed_mps\":\"[0.5,15]\",\"gimbal_lock\":\"默认true\"}},\n {\"name\":\"orbit_around_target\",\"params\":{\"target_class\":\"见object_detect列表\",\"description\":\"可选,目标属性\",\"radius\":\"[5,1000]\",\"laps\":\"[1,20]\",\"clockwise\":\"默认true\",\"speed_mps\":\"[0.5,15]\",\"gimbal_lock\":\"默认true\"}},\n {\"name\":\"loiter\",\"params\":{\"duration\":\"[1,600]秒/until_condition:可选\"}},\n {\"name\":\"object_detect\",\"params\":{\"target_class\":\"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush\",\"description\":\"可选,\",\"count\":\"默认1\"}},\n {\"name\":\"strike_target\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"battle_damage_assessment\",\"params\":{\"target_class\":\"同object_detect\",\"assessment_time\":\"[5,60]默认15\"}},\n {\"name\":\"search_pattern\",\"params\":{\"pattern_type\":\"spiral/grid\",\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,1000]\",\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"track_object\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"track_time\":\"[1,600]秒(必传,不可用'duration'\",\"min_confidence\":\"[0.5,1.0]默认0.7\",\"safe_distance\":\"[2,50]默认10\"}},\n {\"name\":\"deliver_payload\",\"params\":{\"payload_type\":\"string\",\"release_altitude\":\"[2,100]默认5\"}},\n {\"name\":\"preflight_checks\",\"params\":{\"check_level\":\"basic/comprehensive\"}},\n {\"name\":\"emergency_return\",\"params\":{\"reason\":\"string\"}},\n {\"name\":\"rotate_search\",\"params\":{\"center_x\":\"±10000\",\"center_y\":\"±10000\",\"center_z\":\"[1,5000]\",\"radius\":\"[5,100]\",\"speed_mps\":\"[0.5,10]\",\"duration\":\"[10,600]秒\"}},\n {\"name\":\"wait_for_confirmation\",\"params\":{\"message\":\"string\",\"timeout\":\"[10,600]秒\"}}\n ],\n \"conditions\": [\n {\"name\":\"battery_above\",\"params\":{\"threshold\":\"[0.0,1.0],必传\"}},\n {\"name\":\"at_waypoint\",\"params\":{\"x\":\"±10000\",\"y\":\"±10000\",\"z\":\"[1,5000]\",\"tolerance\":\"默认3.0\"}},\n {\"name\":\"object_detected\",\"params\":{\"target_class\":\"同object_detect必传\",\"description\":\"可选,目标属性\",\"count\":\"默认1\"}},\n {\"name\":\"target_destroyed\",\"params\":{\"target_class\":\"同object_detect\",\"description\":\"可选,目标属性\",\"confidence\":\"[0.5,1.0]默认0.8\"}},\n {\"name\":\"time_elapsed\",\"params\":{\"duration\":\"[1,2700]秒\"}},\n {\"name\":\"gps_status\",\"params\":{\"min_satellites\":\"int[6,15]必传如8\"}}\n ],\n \"control_flow\": [\n {\"name\":\"Sequence\",\"params\":{},\"children\":\"子节点数组(按序执行,全成功则成功)\"},\n {\"name\":\"Selector\",\"params\":{\"memory\":\"默认true\"},\"children\":\"子节点数组(执行到成功为止)\"},\n {\"name\":\"Parallel\",\"params\":{\"policy\":\"all_success\"},\"children\":\"子节点数组(同时执行,严禁用'one_success'\"}\n ],\n \"decorators\": [\n {\"name\":\"SuccessIsFailure\",\"params\":{},\"child\":\"单个子节点(成功转失败,失败仍失败)\"}\n ]\n}\n```\n\n\n## 二、节点必填字段后端Schema强制要求缺一验证失败\n每个节点必须包含以下字段字段名/类型不可自定义:\n1. **`type`** \n - 动作节点→`\"action\"`,条件节点→`\"condition\"`,装饰器节点→`\"decorator\"`,控制流节点→`\"Sequence\"`/`\"Selector\"`/`\"Parallel\"`(与`name`字段值完全一致);\n2. **`name`**必须是上述JSON中`actions`/`conditions`/`control_flow`/`decorators`下的`name`值;\n3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;\n4. **`children`**:仅控制流节点必含(子节点数组);\n5. **`child`**:仅装饰器节点必含(单个子节点对象)。\n\n\n## 三、行为树固定结构(通用不变)\n根节点通常是 `Sequence` 或 `Selector`,直接包含任务逻辑。不再强制包含 `SafetyMonitor` 或 `Parallel` 根节点。\n\n示例结构简单顺序任务\n```json\n{\n \"root\": {\n \"type\": \"Sequence\",\n \"name\": \"MainTask\",\n \"params\": {},\n \"children\": [\n {\"type\":\"action\",\"name\":\"takeoff\",\"params\":{\"altitude\":10.0}},\n {\"type\":\"action\",\"name\":\"fly_to_waypoint\",\"params\":{\"x\":200.0,\"y\":150.0,\"z\":10.0}},\n {\"type\":\"action\",\"name\":\"land\",\"params\":{\"mode\":\"home\"}}\n ]\n }\n}\n```\n\n\n## 四、优先级排序任务通用示例\n当用户指令中明确提出有多个待考察且具有优先级关系的物体时节点描述须为优先级关系。比如当指令为已知有三个气球危险级关系为红色气球大于蓝色气球大于绿色气球要求优先跟踪最危险的气球时节点的描述参考下表情形。\n| 用户指令场景 | `target_class` | `description` | 核心节点示例search_pattern |\n|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|\n| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{\"type\":\"action\",\"name\":\"search_pattern\",\"params\":{\"pattern_type\":\"grid\",\"center_x\":200,\"center_y\":150,\"center_z\":10,\"radius\":50,\"target_class\":\"balloon\",\"description\":\"(红>蓝>绿)\"}}` |\n| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{\"type\":\"action\",\"name\":\"object_detect\",\"params\":{\"target_class\":\"truck\",\"description\":\"(军用卡车>民用卡车>面包车)\"}}` |\n\n\n## 五、高频错误规避(确保验证通过)\n1. 优先级排序不可修改`target_class`:如“民用卡车、面包车与军用卡车中,军用卡车优先”,`target_class`仍为`truck`,仅用`description`填排序规则;\n2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;\n3. `track_object`必传`track_time`:不可用`duration`替代如跟踪30秒填`\"track_time\":30.0`\n4. `gps_status`的`min_satellites`必须在6-15之间如8不可缺省\n5. 无自定义节点:“锁定高优先级目标”需通过`object_detect`+`object_detected`实现不可用“lock_high_risk_target”。\n\n\n## 六、新场景模式指南 (New Scenarios)\n\n### 1. 预期场景 (Expected Scenarios)\n当用户指令包含“旋转搜索”、“人工确认”等特定词汇时请使用以下对应关系\n- **\"旋转搜索\"** -> 使用 `rotate_search` 动作。\n- **\"人工确认\"** -> 使用 `wait_for_confirmation` 动作(通常放在 `object_detect` 或 `object_detected` 之后)。\n\n**示例:** \"到研究所广场,寻找黄色衣服男子,我确认后再对其拍照。\"\n```json\n{\n \"type\": \"Sequence\",\n \"name\": \"SearchAndConfirm\",\n \"children\": [\n {\"type\":\"action\", \"name\":\"fly_to_waypoint\", \"params\":{\"x\":20, \"y\":150, \"z\":10}},\n {\"type\":\"action\", \"name\":\"rotate_search\", \"params\":{\"center_x\":20, \"y\":150, \"z\":10, \"radius\":30, \"duration\":60}},\n {\"type\":\"action\", \"name\":\"wait_for_confirmation\", \"params\":{\"message\":\"Found yellow shirt male, confirm to photo?\", \"timeout\":60}},\n {\"type\":\"action\", \"name\":\"strike_target\", \"params\":{\"target_class\":\"person\", \"description\":\"yellow shirt\"}}\n ]\n}\n```\n\n### 2. 环绕侦察 (Circular Reconnaissance with Interrupts)\n当用户要求“环绕侦察”或“巡逻中发现目标即拍照”时必须使用 `Selector` + `SuccessIsFailure` (Decorator) + `fly_to_waypoint` 的组合模式。\n**逻辑解释:** 这是一个“顺路侦察”模式。无人机在飞往下一个航点的过程中Selector先尝试检测目标ReactiveWork。如果检测到目标并拍照成功`SuccessIsFailure` 会欺骗 Selector 说“失败了”,从而迫使 Selector 继续执行 `fly_to_waypoint`,确保无人机不会因为拍了照就停在半路,而是继续飞向终点。\n\n**结构模板:**\n```json\n{\n \"name\": \"GoToWaypointX\",\n \"type\": \"Selector\",\n \"children\": [\n {\"type\": \"condition\", \"name\": \"at_waypoint\", \"params\": {\"target_position\": [x, y, z]}},\n {\n \"name\": \"ReactiveWork\",\n \"type\": \"Selector\",\n \"children\": [\n {\n \"name\": \"SuccessIsFailure\",\n \"type\": \"decorator\",\n \"child\": {\n \"name\": \"DetectHoverPhoto\",\n \"type\": \"Sequence\",\n \"children\": [\n {\"name\": \"object_detect\", \"type\": \"action\", \"params\": {\"target_class\": \"person\"}},\n {\"name\": \"loiter\", \"type\": \"action\", \"params\": {\"time\": 2.0}}\n ]\n }\n },\n {\"name\": \"fly_to_waypoint\", \"type\": \"action\", \"params\": {\"x\": x, \"y\": y, \"z\": z}}\n ]\n }\n ]\n}\n```\n\n\n## 七、输出要求\n仅输出1个严格符合上述所有规则的JSON对象**确保1. 优先级排序逻辑正确填入`description`2. `target_class`匹配预定义列表3. 行为树结构不变4. 后端解析与Schema验证无错误**,无任何冗余内容。\n\n\n【强制规则】仅生成包含root的复杂行为树JSON不得输出简单模式不得包含mode字段或仅有action节点。\n\n=== User Prompt ===\n执行环绕侦察任务沿着研究所外围巡逻如果发现人就悬停拍照。"
}
[2026-01-02 14:10:27]
--- Validation Checks ---
[2026-01-02 14:10:27] PASS: Response is a valid JSON object.
[2026-01-02 14:10:27] PASS: Response contains a valid 'root' key.
[2026-01-02 14:10:27] PASS: Response contains a valid 'visualization_url': /static/py_tree.png
[2026-01-02 14:10:27] ✅ Test completed successfully
[2026-01-02 14:10:27] ================================================================================
[2026-01-02 14:10:27]