diff --git a/backend_service/src/prompts/scene1_prompt.txt b/backend_service/src/prompts/scene1_prompt.txt new file mode 100644 index 00000000..cbd4d991 --- /dev/null +++ b/backend_service/src/prompts/scene1_prompt.txt @@ -0,0 +1,519 @@ +任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(Pytree)JSON。**仅输出单一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","desc":"仅当指令提及具体地点(如'去广场'、'去大门')或需计算明确坐标时使用"}}, + {"name":"fly_sequence","params":{"waypoints":"list[dict] (e.g. [{'x':10,'y':20,'depth':5}, ...];depth可选,不填则保持当前高度)","coordinate_frame":"'global'/'local_enu'(global:经纬度, local_enu:以起飞点为原点的东南天坐标系)","speed":"float,可选"}}, + {"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省则持续移动","speed":"float,可选","desc":"当指令仅包含'往东/西...飞xx米'且无具体地点名词时,必须使用此节点"}}, + {"name":"approach_target","params":{"target_class":"string,要趋近的目标类别","description":"string,可选,目标属性描述","stop_distance":"float,期望的最终停止距离","speed":"float,可选,期望的逼近速度"}}, + {"name":"rotate","params":{"angle":"float,无人机自身旋转角度(正数逆时针,负数顺时针)","angular_velocity":"rad/s,旋转角速度"}}, + {"name":"rotate_search","params":{"target_class":"同object_detect","description":"string,可选,目标属性描述","step_angle":"float,可选,每一步旋转的角度","total_rotation":"float,可选,总共旋转搜索的角度"}}, + {"name":"manual_confirmation","params":{}}, + {"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,garbage","description":"可选,","count":"默认1"}}, + {"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":"system_checks","params":{"check_level":"basic/comprehensive,只能在起飞takeoff节点前使用,空中无需使用该节点"}}, + {"name":"return_emergency","params":{"reason":"string,此节点仅用于【无明确目的地】的立即返航(默认回起飞点)。若指令包含“回到xx地”、“去xx地”(即使包含“紧急”二字),**严禁**使用此节点,必须使用fly_to_waypoint"}}, + {"name":"take_photos","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}} + ], + "conditions": [ + {"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"}} + ], + "control_flow": [ + {"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"}, + {"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"}, + {"name":"Parallel","params":{"policy":"all_success/success_on_one"},"children":"子节点数组(同时执行,默认all_success)"} + ], + "decorators": [ + {"name":"SuccessIsFailure","params":{},"child":"单一子节点(将子节点的成功结果反转为失败)"} + ] +} +``` + + +## 二、节点必填字段(后端Schema强制要求,缺一验证失败) +每个节点必须包含以下字段,字段名/类型不可自定义: +1. **`type`**: + - 动作节点→`"action"`,条件节点→`"condition"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`,装饰器节点→`"decorator"`; +2. **`name`**:必须是上述JSON中定义的`name`值; +3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数; +4. **`children`**:仅控制流节点必含(子节点数组); +5. **`child`**:仅装饰器节点必含(单一子节点对象,非数组)。 + + +## 三、标准任务结构模板(单次起降流程) +当无人机在地面时,大多数任务应遵循“起飞 -> 移动 -> 条件判断 -> 执行 -> 返航/降落”的单次闭环流程,参考结构如下: +```json +{ + "root": { + "type": "Sequence", + "name": "MainTask", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + {"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}}, // 接近目标区域 + // --- 核心任务区 (根据指令替换) --- + // 默认不需要降落节点,除非用户明确要求 + ] + } +} +``` +而当无人机在空中时,则无需system_checks与takeoff环节,直接执行用户任务即可 + +## 四、场景示例 + +#### 场景 1:地面到12米绕外围查看打开的窗户(Sequence) +**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "FlyPerimeterAndPhotoWindows", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetectWindows", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 289.8, "depth": 12.0}, + {"x": -24.0, "y": 292.8, "depth": 12.0}, + {"x": -24.0, "y": 241.8, "depth": 12.0} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectOpenWindowsWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"window","description":"打开的窗户"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"window","description":"打开的窗户"}}, + {"type":"action","name":"take_photos","params":{"target_class":"window","description":"打开的窗户","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 2:地面到12米沿外围查找打开的窗户(Sequence) +**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "FlyPerimeterAndPhotoOpenWindows", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetectOpenWindows", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 289.8, "depth": 12.0}, + {"x": -24.0, "y": 292.8, "depth": 12.0}, + {"x": -24.0, "y": 241.8, "depth": 12.0} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectAllOpenWindowsWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"window","description":"打开的窗户"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"window","description":"打开的窗户"}}, + {"type":"action","name":"take_photos","params":{"target_class":"window","description":"打开的窗户","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 3:空中上升后绕外围侦察打开窗户(Sequence) +**指令**:“无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "RiseAndDetectOpenWindows", + "children": [ + {"type":"action","name":"move_direction","params":{"direction":"up","distance":3.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetectOpenWindows", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8}, + {"x": -108.5, "y": 241.8}, + {"x": -108.5, "y": 289.8}, + {"x": -24.0, "y": 292.8}, + {"x": -24.0, "y": 241.8} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectOpenWindowsWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"window","description":"打开的窗户"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"window","description":"打开的窗户"}}, + {"type":"action","name":"take_photos","params":{"target_class":"window","description":"打开的窗户","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 4:地面到12米绕外围巡视杂物堆积(Sequence) +**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "FlyPerimeterAndPhotoGarbageObserve", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetectGarbageObserve", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 289.8, "depth": 12.0}, + {"x": -24.0, "y": 292.8, "depth": 12.0}, + {"x": -24.0, "y": 241.8, "depth": 12.0} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectGarbageWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"garbage","description":"杂物堆积"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"garbage","description":"杂物堆积"}}, + {"type":"action","name":"take_photos","params":{"target_class":"garbage","description":"杂物堆积","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 5:地面到12米沿外围查找杂物堆积(Sequence) +**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "FlyPerimeterAndPhotoGarbage", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetectGarbage", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 289.8, "depth": 12.0}, + {"x": -24.0, "y": 292.8, "depth": 12.0}, + {"x": -24.0, "y": 241.8, "depth": 12.0} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectGarbageWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"garbage","description":"杂物堆积"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"garbage","description":"杂物堆积"}}, + {"type":"action","name":"take_photos","params":{"target_class":"garbage","description":"杂物堆积","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 6:空中下降后绕外围侦察杂物堆积(Sequence) +**指令**:“无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "DescendAndDetectGarbage", + "children": [ + {"type":"action","name":"move_direction","params":{"direction":"down","distance":3.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetectGarbage", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8}, + {"x": -108.5, "y": 241.8}, + {"x": -108.5, "y": 289.8}, + {"x": -24.0, "y": 292.8}, + {"x": -24.0, "y": 241.8} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectGarbageWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"garbage","description":"杂物堆积"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"garbage","description":"杂物堆积"}}, + {"type":"action","name":"take_photos","params":{"target_class":"garbage","description":"杂物堆积","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 7:地面到12米绕外围查看是否有人(Sequence) +**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "FlyPerimeterAndPhotoPerson", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetectPerson", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 241.8, "depth": 12.0}, + {"x": -108.5, "y": 289.8, "depth": 12.0}, + {"x": -24.0, "y": 292.8, "depth": 12.0}, + {"x": -24.0, "y": 241.8, "depth": 12.0} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectPersonWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"person","description":"人员"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"person","description":"人员"}}, + {"type":"action","name":"take_photos","params":{"target_class":"person","description":"人员","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 8:地面到12米沿外围逆时针查找人员(Sequence) +**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围逆时针查找所有的人并拍照。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "FlyPerimeterCounterClockwiseAndPhotoPerson", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + { + "type": "Parallel", + "name": "PatrolCCWAndDetectPerson", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8, "depth": 12.0}, + {"x": -24.0, "y": 292.8, "depth": 12.0}, + {"x": -108.5, "y": 289.8, "depth": 12.0}, + {"x": -108.5, "y": 241.8, "depth": 12.0}, + {"x": -24.0, "y": 241.8, "depth": 12.0} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectPersonWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"person","description":"人员"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"person","description":"人员"}}, + {"type":"action","name":"take_photos","params":{"target_class":"person","description":"人员","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` + +#### 场景 9:空中上升后沿建筑外围侦察人员(Sequence) +**指令**:“无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。” +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "RiseAndPatrolPerimeter", + "children": [ + {"type":"action","name":"move_direction","params":{"direction":"up","distance":3.0}}, + { + "type": "Parallel", + "name": "PatrolAndDetect", + "params": {"policy": "success_on_one"}, + "children": [ + { + "type": "action", + "name": "fly_sequence", + "params": { + "waypoints": [ + {"x": -24.0, "y": 241.8}, + {"x": -108.5, "y": 241.8}, + {"x": -108.5, "y": 289.8}, + {"x": -24.0, "y": 292.8}, + {"x": -24.0, "y": 241.8} + ], + "coordinate_frame": "local_enu" + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "DetectAndPhotoWhileFlying", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"person","description":"建筑外围人员"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"person","description":"建筑外围人员"}}, + {"type":"action","name":"take_photos","params":{"target_class":"person","description":"建筑外围人员","track_time":10.0}} + ] + } + } + ] + } + ] + } +} +``` diff --git a/backend_service/src/prompts/scene4_prompt.txt b/backend_service/src/prompts/scene4_prompt.txt new file mode 100644 index 00000000..87479e8c --- /dev/null +++ b/backend_service/src/prompts/scene4_prompt.txt @@ -0,0 +1,311 @@ +任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(Pytree)JSON。**仅输出单一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","desc":"仅当指令提及具体地点(如'去广场'、'去大门')或需计算明确坐标时使用"}}, + {"name":"fly_sequence","params":{"waypoints":"list[dict] (e.g. [{'x':10,'y':20,'depth':5}, ...];depth可选,不填则保持当前高度)","coordinate_frame":"'global'/'local_enu'(global:经纬度, local_enu:以起飞点为原点的东南天坐标系)","speed":"float,可选"}}, + {"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省则持续移动","speed":"float,可选","desc":"当指令仅包含'往东/西...飞xx米'且无具体地点名词时,必须使用此节点"}}, + {"name":"approach_target","params":{"target_class":"string,要趋近的目标类别","description":"string,可选,目标属性描述","stop_distance":"float,期望的最终停止距离","speed":"float,可选,期望的逼近速度"}}, + {"name":"rotate","params":{"angle":"float,无人机自身旋转角度(正数逆时针,负数顺时针)","angular_velocity":"rad/s,旋转角速度"}}, + {"name":"rotate_search","params":{"target_class":"同object_detect","description":"string,可选,目标属性描述","step_angle":"float,可选,每一步旋转的角度","total_rotation":"float,可选,总共旋转搜索的角度"}}, + {"name":"manual_confirmation","params":{}}, + {"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,garbage","description":"可选,","count":"默认1"}}, + {"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":"system_checks","params":{"check_level":"basic/comprehensive,只能在起飞takeoff节点前使用,空中无需使用该节点"}}, + {"name":"return_emergency","params":{"reason":"string,此节点仅用于【无明确目的地】的立即返航(默认回起飞点)。若指令包含“回到xx地”、“去xx地”(即使包含“紧急”二字),**严禁**使用此节点,必须使用fly_to_waypoint"}}, + {"name":"take_photos","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}} + ], + "conditions": [ + {"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"}} + ], + "control_flow": [ + {"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"}, + {"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"}, + {"name":"Parallel","params":{"policy":"all_success/success_on_one"},"children":"子节点数组(同时执行,默认all_success)"} + ], + "decorators": [ + {"name":"SuccessIsFailure","params":{},"child":"单一子节点(将子节点的成功结果反转为失败)"} + ] +} +``` + + +## 二、节点必填字段(后端Schema强制要求,缺一验证失败) +每个节点必须包含以下字段,字段名/类型不可自定义: +1. **`type`**: + - 动作节点→`"action"`,条件节点→`"condition"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`,装饰器节点→`"decorator"`; +2. **`name`**:必须是上述JSON中定义的`name`值; +3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数; +4. **`children`**:仅控制流节点必含(子节点数组); +5. **`child`**:仅装饰器节点必含(单一子节点对象,非数组)。 + + +## 三、标准任务结构模板(单次起降流程) +当无人机在地面时,大多数任务应遵循“起飞 -> 移动 -> 条件判断 -> 执行 -> 返航/降落”的单次闭环流程,参考结构如下: +```json +{ + "root": { + "type": "Sequence", + "name": "MainTask", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + {"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}}, // 接近目标区域 + // --- 核心任务区 (根据指令替换) --- + // 默认不需要降落节点,除非用户明确要求 + ] + } +} +``` +而当无人机在空中时,则无需system_checks与takeoff环节,直接执行用户任务即可 + +## 四、场景示例(请灵活参考) + +#### 场景 1:线性搜索任务(Sequence + Selector) +**指令**:“无人机当前在地面,去研究所正大门,搜索扎辫子女子,找到后拍照。” +**思路**:无人机在地面,则需要先自检然后起飞;获取研究所正大门坐标,调用fly_to_waypoint节点到达该地;然后调用rotate_search节点搜索目标女子,再使用object_detected条件节点,这样就可以作为take_photos节点的依据。 +**结构**:Sequence (按顺序执行) +```json +{ + "root": { + "type": "Sequence", + "name": "MainSearchTask", + "children": [ + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + {"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}}, + {"type":"action","name":"rotate_search","params":{"target_class":"person","description":"扎辫子女子"}}, + { + "type": "Selector", + "name": "CheckAndPhoto", + "children": [ + { + "type": "Sequence", + "name": "PhotoIfFound", + "children": [ + {"type":"condition","name":"object_detected","params":{"target_class":"person","description":"扎辫子女子"}}, + {"type":"action","name":"take_photos","params":{"target_class":"person","description":"扎辫子女子","track_time":10.0}} + ] + }, + {"type":"action","name":"loiter","params":{"duration":5.0}} // 未发现时的备选动作 + ] + } + ] + } +} +``` + +#### 场景 2:带中断逻辑的巡逻(Selector 示例) +**指令**:“无人机当前在地面,飞往航点A。如果途中发现可疑人员,则悬停。” +**参考知识**:航点A的坐标(x:100.0,y:50.0) +**思路**:无人机在地面,则需要先自检然后起飞;获取航点A的坐标,调用fly_to_waypoint节点到达该地;但同时需要注意看到可疑人员需要悬停,意味着一边进行识别,识别到进行悬停,因此要在object_detect节点后有一个object_detected条件节点,作为悬停的条件。 +**结构**: +```json +{ + "root": { + "type": "Sequence", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"basic"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + { + "type": "Selector", + "name": "FlyOrDetect", + "children": [ + { + "type": "Sequence", + "name": "InterruptionLogic", + "children": [ + {"type":"action","name":"object_detect","params":{"target_class":"person"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"person"}}, + {"type":"action","name":"loiter","params":{"duration":5.0}} + ] + }, + {"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}} + ] + } + ] + } +} +``` + +#### 场景 3:长期监控任务(Parallel 示例) +**指令**:“无人机当前在空中,往广场西边飞200米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。” +**参考知识**:广场西边200米的坐标(x:50.0,y:50.0,z:10.0) +**思路**:无人机在空中,直接前往目标点;到达后需要并行执行两件事:1. 倒计时5分钟(主控时间);2. 持续检测人并拍照(从属任务)。 +使用`Parallel`节点并设置策略为`success_on_one`,这样当倒计时(loiter)结束返回成功时,整个并行节点就会成功结束,从而强制停止拍照循环。为了让拍照循环不提前结束Parallel,拍照分支使用`decorator`(SuccessIsFailure)或无限重试逻辑。 +**结构**: +```json +{ + "root": { + "type": "Sequence", + "name": "MainTask", + "children": [ + { + "type": "action", + "name": "fly_to_waypoint", + "params": { + "x": 50.0, + "y": 50.0, + "z": 10.0 + } + }, + { + "type": "Parallel", + "name": "MonitorAndPhoto", + "params": { + "policy": "success_on_one" + }, + "children": [ + { + "type": "action", + "name": "loiter", + "params": { + "time": 300 + } + }, + { + "type": "decorator", + "name": "SuccessIsFailure", + "child": { + "type": "Sequence", + "name": "CheckAndPhoto", + "children": [ + { + "type": "action", + "name": "object_detect", + "params": { + "target_class": "person" + } + }, + { + "type": "condition", + "name": "object_detected", + "params": { + "target_class": "person" + } + }, + { + "type": "action", + "name": "take_photos", + "params": { + "target_class": "person" + } + } + ] + } + } + ] + }, + { + "type": "action", + "name": "return_emergency", + "params": { + "reason": "任务完成" + } + } + ] + } +} +``` + +#### 场景 4:交互式确认任务(Sequence + Manual Confirmation) +**指令**:“无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。” +**思路**:无人机已在空中,无需起飞,直接进行搜索。首先使用`rotate_search`主动搜索目标,配合`object_detected`条件节点确认目标是否被检测到。检测到后,执行`manual_confirmation`节点等待用户确认。只有用户确认通过(返回Success),才会继续执行后续的`take_photos`动作。 +**结构**:Sequence +```json +{ + "root": { + "type": "Sequence", + "name": "SearchConfirmPhoto", + "children": [ + {"type":"action","name":"rotate_search","params":{"target_class":"car","description":"小汽车"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"car","description":"小汽车"}}, + {"type":"action","name":"manual_confirmation","params":{}}, + {"type":"action","name":"take_photos","params":{"target_class":"car","description":"小汽车"}} + ] + } +} +``` + +#### 场景 5:后置确认任务(Sequence + Manual Confirmation) +**指令**:“无人机当前在地面,搜索小汽车,搜索到了拍张照,我确认后再决定要不要返航” +**思路**:无人机在地面,需起飞。搜索小汽车(`rotate_search` + `object_detected`)。搜索到后,先执行拍照(`take_photos`)。之后执行人工确认(`manual_confirmation`),确认通过后才执行返航(`return_emergency`)。 +**结构**:Sequence +```json +{ + "root": { + "type": "Sequence", + "name": "SearchPhotoConfirmReturn", + "children": [ + {"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}, + {"type":"action","name":"takeoff","params":{"altitude":10.0}}, + {"type":"action","name":"rotate_search","params":{"target_class":"car","description":"小汽车"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"car","description":"小汽车"}}, + {"type":"action","name":"take_photos","params":{"target_class":"car","description":"小汽车"}}, + {"type":"action","name":"manual_confirmation","params":{}}, + {"type":"action","name":"return_emergency","params":{"reason":"确认后返航"}} + ] + } +} +``` + +#### 场景 6:移动后条件降落(Sequence) +**指令**:“无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。” +**参考知识**:广场坐标(x:0.0, y:0.0, z:10.0) +**思路**:无人机在空中,无需起飞。首先飞往广场(`fly_to_waypoint`),严禁使用`return_emergency`。到达后,为了满足“看见红绿灯”的条件,必须先执行主动搜索(`rotate_search`)。一旦检测到红绿灯(`object_detected`),即执行降落(`land`)。 +**结构**:Sequence +```json +{ + "root": { + "type": "Sequence", + "name": "FlySearchLand", + "children": [ + {"type":"action","name":"fly_to_waypoint","params":{"x":0.0,"y":0.0,"z":10.0}}, + {"type":"action","name":"rotate_search","params":{"target_class":"traffic_light","description":"红绿灯"}}, + {"type":"condition","name":"object_detected","params":{"target_class":"traffic_light","description":"红绿灯"}}, + {"type":"action","name":"land","params":{"mode":"current"}} + ] + } +} +``` + +## 六、高频错误规避 +1. 控制流节点的 `type` 必须是 `"Sequence"`, `"Selector"` 或 `"Parallel"` +2. **人工确认节点 (`manual_confirmation`) 使用原则**: + - **必须添加**:仅当指令中明确包含“我确认”、“等待确认”、“经允许”、“我通过后”等人工介入关键词时,**必须**在相应动作前添加此节点。 + - **严禁添加**:若指令未提及上述关键词,**严禁**主动添加此节点(即使是拍照、返航或降落等动作,只要用户没说要确认,就直接执行)。 +3. 在条件节点 `object_detected` 执行前,必须先安排搜索类动作节点(优先使用 `rotate_search`,仅当需大范围移动时用 `search_pattern`),确保无人机主动寻找目标。 +4. 当使用rotate_search或者object_detect节点时,必须有object_detected节点 +5. 用户指令中要求在当前位置执行任务时,无需fly_to_waypoint节点 +6. **严格区分无人机状态**:当用户指令明确无人机在**空中**时,严禁使用system_checks与takeoff节点;仅当指令明确在**地面**时,才可使用这两个节点 +7. **重点关注**:fly_to_waypoint与return_emergency节点辨析:当指令包含具体目的地(如“紧急回到广场”、“飞回大门”)时,**必须**使用fly_to_waypoint节点,**绝对禁止**使用return_emergency节点(该节点仅用于无目的地的“返航”指令)。 +8. 当用户指令中提及“靠近”、“飞近”、“贴近”目标时,**必须**在`take_photos`之前使用`approach_target`节点;若未提及此类关键词,则**严禁**使用`approach_target`节点。 +9. **方向移动优先原则**:当指令为“快速去往东边100米”,直接使用 `move_direction` 节点+距离参数,严禁使用fly_to_waypoint + +## 七、坐标计算规则(东南天坐标系 ENU) +本系统统一使用东南天(ENU)坐标系: +- **X轴**:正方向为**东** (East),负方向为**西** (West) +- **Y轴**:正方向为**南** (South)向为**北** (North) +- **Z轴**:正方向为**天** (Up),负方向为**地** (Down) + +**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:** + +当指令包含“具体地点 + 方向 + 距离”的偏移(如“广场西边200米”)时,**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数: +- `base`: 参考地点的ENU坐标(含x/y/z) +- `direction`: east/west/north/south/up/down +- `distance`: 偏移距离(米) + +当指令只有“方向 + 距离”且**没有具体地点名词**时,**禁止**调用`calc_offset_enu`,必须使用`move_direction`。 +当指令描述“附近/边上/区域内”等模糊位置且**无方向+距离**时,视为到该地点本身,不做偏移计算。 + +## 八、输出要求 +仅输出1个严格符合上述所有规则的JSON对象。 diff --git a/backend_service/src/prompts/scene_classifier_prompt.txt b/backend_service/src/prompts/scene_classifier_prompt.txt new file mode 100644 index 00000000..f989a754 --- /dev/null +++ b/backend_service/src/prompts/scene_classifier_prompt.txt @@ -0,0 +1,46 @@ +你是一个严格的指令场景分类器。只输出一个JSON对象,不要输出解释或多余文本。 +根据用户指令与下述场景定义,判断其属于“simple / scene1 / scene4”之一。 + +输出格式(严格遵守): +{"mode":"simple"} 或 {"mode":"scene1"} 或 {"mode":"scene4"} + +判定规则(严格遵守): +1. 若指令符合 scene1 或 scene4 的特征,必须输出对应模式; +2. 若指令不符合 scene1 与 scene4,输出 simple; +3. 仅允许以上三种取值,禁止输出其他字段或文本。 + +—— 场景定义 —— +scene1(大楼外围巡查类): +- 关键词特征:面前大楼/这栋楼、外围/沿着外围/绕着外围、12米高处、逆时针等; +- 任务类型:绕楼外围巡查、搜索窗户/杂物堆积/人员等并拍照; +- 包含上下/下降移动(上升3米/下降3米)后绕楼侦察的也属于 scene1。 + +scene4(广场相关复合任务类): +- 关键词特征:广场、广场边上、广场南边、施工区域、紧急回到广场、回到广场; +- 任务类型:在广场搜索/拍照/监控/返航/降落/靠近拍照等; +- 可能包含“确认后拍照/返航”、“持续监控5分钟”、“挟持”等描述。 + +—— 场景指令样例 —— +scene1 示例: +- 无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。 +- 无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。 +- 无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。 +- 无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。 +- 无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。 +- 无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。 +- 无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。 +- 无人机当前在地面,去面前大楼的12米高处,沿着外围逆时针查找所有的人并拍照。 +- 无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。 + +scene4 示例: +- 无人机当前在地面,到广场查找穿红色衣服的人,找到后近距离拍照。 +- 无人机当前在空中,回到广场,对戴帽子的人进行拍照。 +- 无人机当前在空中,去广场南边40米,对过往的公交车拍张照,然后返航。 +- 无人机当前在地面,到广场查找绿色公交车,看见了拍个照片。 +- 无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。 +- 无人机当前在空中,搜索小汽车,搜索到了拍张照,我确认后再决定要不要返航。 +- 无人机当前在空中,往广场南边飞40米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。 +- 无人机当前在地面,到广场边上的施工区域内,发现有没带安全帽的飞近后拍照。 +- 无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。 +- 无人机当前在地面,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。 +- 无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。 diff --git a/backend_service/src/py_tree_generator.py b/backend_service/src/py_tree_generator.py index 5b2c147c..eb104dc4 100644 --- a/backend_service/src/py_tree_generator.py +++ b/backend_service/src/py_tree_generator.py @@ -594,10 +594,13 @@ class PyTreeGenerator: self.reasoning_preview_lines = int(os.getenv("REASONING_PREVIEW_LINES", "20")) except Exception: self.reasoning_preview_lines = 20 - # 加载提示词:复杂模式复用现有 system_prompt.txt;简单模式与分类器独立提示词 + # 加载提示词:复杂模式复用现有 system_prompt.txt;场景1/4与分类器独立提示词 self.complex_prompt = self._load_prompt("system_prompt.txt") + self.scene1_prompt = self._load_prompt("scene1_prompt.txt") + self.scene4_prompt = self._load_prompt("scene4_prompt.txt") self.simple_prompt = self._load_prompt("simple_mode_prompt.txt") self.classifier_prompt = self._load_prompt("classifier_prompt.txt") + self.scene_classifier_prompt = self._load_prompt("scene_classifier_prompt.txt") # 兼容旧变量名 self.system_prompt = self.complex_prompt @@ -812,13 +815,13 @@ class PyTreeGenerator: """ logging.info(f"接收到用户请求: {user_prompt}") - # 第一步:分类(简单/复杂) - mode = "complex" + # 第一步:场景分类(simple/scene1/scene4) + scene_mode = "scene1" try: classifier_resp = self.classifier_client.chat.completions.create( model=self.classifier_model, messages=[ - {"role": "system", "content": self.classifier_prompt or "你是一个分类器,只输出JSON。"}, + {"role": "system", "content": self.scene_classifier_prompt or "你是一个分类器,只输出JSON。"}, {"role": "user", "content": user_prompt} ], temperature=0.0, @@ -830,18 +833,25 @@ class PyTreeGenerator: ) class_str = classifier_resp.choices[0].message.content class_obj = json.loads(class_str) - if isinstance(class_obj, dict) and class_obj.get("mode") in ("simple", "complex"): - mode = class_obj.get("mode") - logging.info(f"分类结果: {mode}") + if isinstance(class_obj, dict) and class_obj.get("mode") in ("simple", "scene1", "scene4"): + scene_mode = class_obj.get("mode") + logging.info(f"场景分类结果: {scene_mode}") except Exception as e: - logging.warning(f"分类失败,默认按复杂指令处理: {e}") + logging.warning(f"场景分类失败,默认按scene1处理: {e}") # 第二步:根据模式准备提示词与上下文(简单与复杂都执行检索增强) - # 基于模式选择提示词;复杂模式追加一条强制规则,避免模型误输出简单结构 - use_prompt = self.simple_prompt if mode == "simple" else ( - (self.complex_prompt or "") + - "\n\n【强制规则】仅生成包含root的复杂行为树JSON,不得输出简单模式(不得包含mode字段或仅有action节点)。" - ) + # 基于场景选择提示词;非simple时追加强制规则,避免模型误输出简单结构 + if scene_mode == "simple": + use_prompt = self.simple_prompt + elif scene_mode == "scene4": + use_prompt = self.scene4_prompt + else: + use_prompt = self.scene1_prompt + if scene_mode != "simple": + use_prompt = ( + (use_prompt or self.complex_prompt or "") + + "\n\n【强制规则】仅生成包含root的复杂行为树JSON,不得输出简单模式(不得包含mode字段或仅有action节点)。" + ) final_user_prompt = user_prompt retrieved_context = self._retrieve_context(user_prompt) if retrieved_context: @@ -866,8 +876,9 @@ class PyTreeGenerator: logging.info(f"--- 第 {attempt + 1}/3 次尝试生成Pytree ---") try: # 简单/复杂分流到不同模型与提示词 - client = self.simple_llm_client if mode == "simple" else self.complex_llm_client - model_name = self.simple_model if mode == "simple" else self.complex_model + is_simple = scene_mode == "simple" + client = self.simple_llm_client if is_simple else self.complex_llm_client + model_name = self.simple_model if is_simple else self.complex_model messages = [ {"role": "system", "content": use_prompt}, {"role": "user", "content": final_user_prompt} @@ -876,7 +887,7 @@ class PyTreeGenerator: response_kwargs = { "model": model_name, "messages": messages, - "temperature": 0.1 if mode == "complex" else 0.0, + "temperature": 0.0 if is_simple else 0.1, "response_format": {"type": "json_object"}, # 始终强制JSON输出,禁用思考功能 "extra_body": {"chat_template_kwargs": {"enable_thinking": False}} } @@ -884,7 +895,7 @@ class PyTreeGenerator: response_kwargs["tools"] = self._get_tool_definitions() response_kwargs["tool_choice"] = "auto" # 基于模式设定最大输出token数(直接在代码中配置) - response_kwargs["max_tokens"] = self.simple_max_tokens if mode == "simple" else self.complex_max_tokens + response_kwargs["max_tokens"] = self.simple_max_tokens if is_simple else self.complex_max_tokens response = client.chat.completions.create(**response_kwargs) # 工具调用处理:执行工具并回填后,强制模型输出JSON @@ -1008,7 +1019,7 @@ class PyTreeGenerator: continue # 简单/复杂分别验证与返回 - if mode == "simple": + if scene_mode == "simple": try: jsonschema.validate(instance=pytree_dict, schema=self.simple_schema) # 手动检查:简单模式的root节点不能有children(或children必须是空数组) diff --git a/tools/test_validate/instructions/scene1.txt b/tools/test_validate/instructions/scene1.txt index 749df098..5b6dc3d2 100644 --- a/tools/test_validate/instructions/scene1.txt +++ b/tools/test_validate/instructions/scene1.txt @@ -1,2 +1,9 @@ -无人机当前在地面,到广场查找穿黄色衣服的男子,找到后近距离拍照。 -无人机当前在空中,回到广场,对长发可疑男子进行拍照。 \ No newline at end of file +无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。 +无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。 +无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。 +无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。 +无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。 +无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。 +无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。 +无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的人并拍照。 +无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。 \ No newline at end of file diff --git a/tools/test_validate/instructions/scene4.txt b/tools/test_validate/instructions/scene4.txt new file mode 100644 index 00000000..cf77a61d --- /dev/null +++ b/tools/test_validate/instructions/scene4.txt @@ -0,0 +1,11 @@ +无人机当前在地面,到广场查找穿红色衣服的人,找到后近距离拍照。 +无人机当前在空中,回到广场,对戴帽子的人进行拍照。 +无人机当前在空中,去广场南边40米,对过往的公交车拍张照,然后返航。 +无人机当前在地面,到广场查找绿色公交车,看见了拍个照片。 +无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。 +无人机当前在空中,搜索小汽车,搜索到了拍张照,我确认后再决定要不要返航。 +无人机当前在空中,往广场南边飞40米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。 +无人机当前在地面,到广场边上的施工区域内,发现有没带安全帽的飞近后拍照。 +无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。 +无人机当前在地面,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。 +无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。 \ No newline at end of file diff --git a/tools/test_validate/instructions/scene4_1.txt b/tools/test_validate/instructions/scene4_1.txt new file mode 100644 index 00000000..3053a196 --- /dev/null +++ b/tools/test_validate/instructions/scene4_1.txt @@ -0,0 +1,8 @@ +无人机当前在空中,往广场南边飞40米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。 +无人机当前在空中,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。 +无人机当前在地面,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。 +无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。 +无人机当前在空中,返航。 +无人机当前在空中,飞往广场。 +无人机当前在地面,飞往广场。 +无人机当前再空中,向上移动10米。 diff --git a/tools/test_validate/instructions/validate_instructions.txt b/tools/test_validate/instructions/validate_instructions.txt index 2aa7af22..7060251c 100644 --- a/tools/test_validate/instructions/validate_instructions.txt +++ b/tools/test_validate/instructions/validate_instructions.txt @@ -4,7 +4,7 @@ 无人机当前在地面,到广场查找绿色公交车,看见了拍个照片。 无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。 无人机当前在空中,往广场西边飞200米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。 -无人机当前在地面,到广场边上的施工区域内,发现有没带安全帽的飞近后拍照。 +无人机当前在地面,到广场边上的施工区域内,发现未戴安全帽的飞近后拍照。 无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。 -无人机当前在地面,快速去往东边100米,有身穿黑色衣服,头戴帽子的男子在挟持他人,对其进行拍照。 +无人机当前在地面,快速去往东边60米,对身穿白色衣服,头戴帽子正在挟持他人的人进行拍照。 无人机当前在空中,离黑色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。 \ No newline at end of file