流程节点完善
@@ -1,3 +1,3 @@
|
||||
{"property": "location", "information": {"name": "飞行场地", "coordinates": {"x": 0, "y": 0, "z": 0}}}
|
||||
{"property": "rules", "information": {"name": "紧急返航", "description": "当指令中要求紧急返航到某地时,必须使用fly_to_waypoint节点,严禁使用return_emergency节点。"}}
|
||||
{"property": "location", "information": {"name": "大楼外围四个点东南天坐标系坐标", "coordinates": {"A": {"x": -24.00, "y": 241.80, "z": 0}, "B": {"x": -108.50, "y": 241.80, "z": 0}, "C": {"x": -108.50, "y": 289.80, "z": 0}, "D": {"x": -24.00, "y": 292.80, "z": 0}}}}
|
||||
{"property": "location", "information": {"name": "广场", "coordinates": {"x": 100, "y": 260, "z": 0}}}
|
||||
@@ -1,6 +1,6 @@
|
||||
{"scene_id":"scene1_perimeter_window_ground","intent_type":"patrol_or_monitor","trigger_terms":["面前大楼","12米","外围","窗户"],"text":"地面起飞后到面前大楼约12米高度,沿外围巡查打开窗户;如发现窗户则拍照回传。","pattern_json":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},{"type":"action","name":"takeoff","params":{"altitude":12}},{"type":"action","name":"rotate_search","params":{"target_class":"window"}},{"type":"condition","name":"object_detected","params":{"target_class":"window"}},{"type":"action","name":"take_photos","params":{"target_class":"window","track_time":10}}]}}}
|
||||
{"scene_id":"scene1_perimeter_person_air","intent_type":"patrol_or_monitor","trigger_terms":["这栋楼","空中","外围","人"],"text":"无人机已在空中,先调整高度后沿建筑外围巡查人员,发现目标后拍照。","pattern_json":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"move_direction","params":{"direction":"up","distance":3}},{"type":"action","name":"rotate_search","params":{"target_class":"person"}},{"type":"condition","name":"object_detected","params":{"target_class":"person"}},{"type":"action","name":"take_photos","params":{"target_class":"person","track_time":10}}]}}}
|
||||
{"scene_id":"scene1_perimeter_trash_ground","intent_type":"patrol_or_monitor","trigger_terms":["面前大楼","杂物","外围"],"text":"地面起飞至指定高度后沿楼体外围侦察杂物堆积并拍照。","pattern_json":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"takeoff","params":{"altitude":12}},{"type":"action","name":"rotate_search","params":{"target_class":"garbage"}},{"type":"condition","name":"object_detected","params":{"target_class":"garbage"}},{"type":"action","name":"take_photos","params":{"target_class":"garbage","track_time":8}}]}}}
|
||||
{"scene_id":"scene4_named_place_search_photo","intent_type":"search_and_photo","trigger_terms":["广场","查找","拍照"],"text":"前往命名地点后搜索目标并拍照。","pattern_json":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"fly_to_waypoint","params":{"x":0,"y":0,"z":10,"acceptance_radius":2}},{"type":"action","name":"rotate_search","params":{"target_class":"person"}},{"type":"condition","name":"object_detected","params":{"target_class":"person"}},{"type":"action","name":"take_photos","params":{"target_class":"person","track_time":8}}]}}}
|
||||
{"scene_id":"scene4_named_place_monitor_return","intent_type":"return_or_land","trigger_terms":["广场南边","监控","返航"],"text":"先到达命名地点偏移区域执行监控,到时后返航。","pattern_json":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"fly_to_waypoint","params":{"x":40,"y":80,"z":15,"acceptance_radius":2}},{"type":"action","name":"loiter","params":{"duration":300}},{"type":"action","name":"return_emergency","params":{"reason":"mission_complete"}}]}}}
|
||||
{"scene_id":"scene4_named_place_confirm_then_action","intent_type":"search_and_photo","trigger_terms":["确认后","拍照","返航"],"text":"在命名区域发现目标后等待人工确认,再执行拍照或返航。","pattern_json":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"fly_to_waypoint","params":{"x":10,"y":10,"z":10,"acceptance_radius":2}},{"type":"action","name":"rotate_search","params":{"target_class":"car"}},{"type":"condition","name":"object_detected","params":{"target_class":"car"}},{"type":"action","name":"manual_confirmation","params":{}},{"type":"action","name":"take_photos","params":{"target_class":"car","track_time":8}}]}}}
|
||||
{"scene_id":"scene1_perimeter_window_ground","intent_type":"patrol_or_monitor","trigger_terms":["面前大楼","12米","外围","窗户"],"text":"地面起飞后到面前大楼约12米高度,沿外围巡查打开窗户;如发现窗户则拍照回传。","reasoning_path":"无人机在地面,需先自检并起飞到指定高度;到达高度后,由于是沿外围巡查并识别,应使用 Parallel 节点并设置 policy 为 success_on_one,让基于航点队列的飞行(fly_sequence)与查找物体分支并行执行;查找分支应循环或按序执行目标检测(object_detect)与条件判定(object_detected),发现后执行拍照(take_photos)。","parameter_requests":[{"node":"takeoff","intent":"起飞到12米","extracted_entities":{"altitude":"12米"}},{"node":"fly_sequence","intent":"沿面前大楼外围飞行","extracted_entities":{"landmark":"面前大楼外围"}},{"node":"object_detect","intent":"检测打开的窗户","extracted_entities":{"target":"打开的窗户"}},{"node":"object_detected","intent":"判定是否发现打开的窗户","extracted_entities":{"target":"打开的窗户"}},{"node":"take_photos","intent":"对打开的窗户拍照","extracted_entities":{"target":"打开的窗户"}}],"macro_tree":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"system_checks"},{"type":"action","name":"takeoff"},{"type":"Parallel","name":"PatrolAndDetectWindows","children":[{"type":"action","name":"fly_sequence"},{"type":"decorator","name":"SuccessIsFailure","child":{"type":"Sequence","name":"DetectOpenWindowsWhileFlying","children":[{"type":"action","name":"object_detect"},{"type":"condition","name":"object_detected"},{"type":"action","name":"take_photos"}]}}]}]}}}
|
||||
{"scene_id":"scene1_perimeter_person_air","intent_type":"patrol_or_monitor","trigger_terms":["这栋楼","空中","外围","人"],"text":"无人机已在空中,先往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。","reasoning_path":"无人机已在空中,禁止自检与起飞;需先执行方向移动(move_direction)上升;然后使用 Parallel 节点(success_on_one)让外围绕飞(fly_sequence)与识别人员分支并行执行;识别分支需先检测物体(object_detect),满足检测条件(object_detected)后触发拍照(take_photos)。","parameter_requests":[{"node":"move_direction","intent":"往上飞3米","extracted_entities":{"direction":"上","distance":"3米"}},{"node":"fly_sequence","intent":"绕这栋楼外围飞行","extracted_entities":{"landmark":"这栋楼外围"}},{"node":"object_detect","intent":"检测人","extracted_entities":{"target":"人"}},{"node":"object_detected","intent":"判定是否发现人","extracted_entities":{"target":"人"}},{"node":"take_photos","intent":"对人拍照","extracted_entities":{"target":"人"}}],"macro_tree":{"root":{"type":"Sequence","name":"RiseAndDetectOpenWindows","children":[{"type":"action","name":"move_direction"},{"type":"Parallel","name":"PatrolAndDetectOpenWindows","children":[{"type":"action","name":"fly_sequence"},{"type":"decorator","name":"SuccessIsFailure","child":{"type":"Sequence","name":"DetectOpenWindowsWhileFlying","children":[{"type":"action","name":"object_detect"},{"type":"condition","name":"object_detected"},{"type":"action","name":"take_photos"}]}}]}]}}}
|
||||
{"scene_id":"scene4_named_place_search_photo","intent_type":"search_and_photo","trigger_terms":["正大门","搜索","拍照"],"text":"无人机当前在地面,去研究所正大门,搜索扎辫子女子,找到后拍照。","reasoning_path":"无人机在地面,需先自检并起飞;到达指定目标点需使用坐标飞行(fly_to_waypoint);到达后因为不知道目标具体方位,需旋转搜索(rotate_search);搜索过程可能有结果也可能无结果,采用 Selector 节点进行判断:优先分支检测目标(object_detected)并拍照(take_photos),若未检测到,退至备选的悬停(loiter)动作。","parameter_requests":[{"node":"fly_to_waypoint","intent":"前往研究所正大门","extracted_entities":{"landmark":"研究所正大门"}},{"node":"rotate_search","intent":"搜索扎辫子女子","extracted_entities":{"target":"扎辫子女子"}},{"node":"object_detected","intent":"判定是否发现扎辫子女子","extracted_entities":{"target":"扎辫子女子"}},{"node":"take_photos","intent":"对扎辫子女子拍照","extracted_entities":{"target":"扎辫子女子"}}],"macro_tree":{"root":{"type":"Sequence","name":"MainSearchTask","children":[{"type":"action","name":"system_checks"},{"type":"action","name":"takeoff"},{"type":"action","name":"fly_to_waypoint"},{"type":"action","name":"rotate_search"},{"type":"Selector","name":"CheckAndPhoto","children":[{"type":"Sequence","name":"PhotoIfFound","children":[{"type":"condition","name":"object_detected"},{"type":"action","name":"take_photos"}]},{"type":"action","name":"loiter"}]}]}}}
|
||||
{"scene_id":"scene4_named_place_monitor_return","intent_type":"return_or_land","trigger_terms":["广场西边","监控","返航"],"text":"无人机当前在空中,往广场西边飞200米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。","reasoning_path":"无人机在空中,直接前往目标点(fly_to_waypoint);到达后需长期监控,使用 Parallel 节点并设 policy 为 success_on_one。主控分支为时长控制的悬停(loiter),监控分支循环检测人(object_detect),检测到(object_detected)即拍照(take_photos);由于并行节点只要有一个完成(loiter时间到)便成功,整个监控段结束后最后执行紧急返航(return_emergency)。","parameter_requests":[{"node":"fly_to_waypoint","intent":"去广场西边200米","extracted_entities":{"landmark":"广场","direction":"西边","distance":"200米"}},{"node":"loiter","intent":"持续监控5分钟","extracted_entities":{"time":"5分钟"}},{"node":"object_detect","intent":"检测人","extracted_entities":{"target":"人"}},{"node":"object_detected","intent":"判定是否发现人","extracted_entities":{"target":"人"}},{"node":"take_photos","intent":"对人拍照","extracted_entities":{"target":"人"}}],"macro_tree":{"root":{"type":"Sequence","name":"MainTask","children":[{"type":"action","name":"fly_to_waypoint"},{"type":"Parallel","name":"MonitorAndPhoto","children":[{"type":"action","name":"loiter"},{"type":"decorator","name":"SuccessIsFailure","child":{"type":"Sequence","name":"CheckAndPhoto","children":[{"type":"action","name":"object_detect"},{"type":"condition","name":"object_detected"},{"type":"action","name":"take_photos"}]}}]},{"type":"action","name":"return_emergency"}]}}}
|
||||
{"scene_id":"scene4_named_place_confirm_then_action","intent_type":"search_and_photo","trigger_terms":["确认后","拍照","返航"],"text":"无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。","reasoning_path":"无人机在空中,直接开始任务。首先执行原地旋转搜索(rotate_search);紧接着使用条件节点确认是否检测到目标(object_detected);确认检测到后,需插入人工确认交互节点(manual_confirmation);若人工放行,最后执行拍照(take_photos)。","parameter_requests":[{"node":"rotate_search","intent":"搜索小汽车","extracted_entities":{"target":"小汽车"}},{"node":"object_detected","intent":"判定是否发现小汽车","extracted_entities":{"target":"小汽车"}},{"node":"take_photos","intent":"对小汽车拍照","extracted_entities":{"target":"小汽车"}}],"macro_tree":{"root":{"type":"Sequence","name":"SearchConfirmPhoto","children":[{"type":"action","name":"rotate_search"},{"type":"condition","name":"object_detected"},{"type":"action","name":"manual_confirmation"},{"type":"action","name":"take_photos"}]}}}
|
||||
{"scene_id":"scene4_interruption_logic","intent_type":"generic_mission","trigger_terms":["如果途中","发现可疑人员","悬停"],"text":"无人机当前在地面,飞往航点A。如果途中发现可疑人员,则悬停。","reasoning_path":"无人机在地面需起飞。因为要在飞行途中中断,采用 Selector 控制。优先分支为检测异常:包含主动检测(object_detect)、条件判定(object_detected)与发现后的悬停应对(loiter)。若优先分支未能连续达成(即途中未发现目标),Selector 退回备选分支:正常向航点飞行(fly_to_waypoint)。","parameter_requests":[{"node":"object_detect","intent":"检测可疑人员","extracted_entities":{"target":"可疑人员"}},{"node":"object_detected","intent":"判定是否发现可疑人员","extracted_entities":{"target":"可疑人员"}},{"node":"fly_to_waypoint","intent":"飞往航点A","extracted_entities":{"landmark":"航点A"}}],"macro_tree":{"root":{"type":"Sequence","name":"Sequence","children":[{"type":"action","name":"system_checks"},{"type":"action","name":"takeoff"},{"type":"Selector","name":"FlyOrDetect","children":[{"type":"Sequence","name":"InterruptionLogic","children":[{"type":"action","name":"object_detect"},{"type":"condition","name":"object_detected"},{"type":"action","name":"loiter"}]},{"type":"action","name":"fly_to_waypoint"}]}]}}}
|
||||
@@ -7,7 +7,62 @@ class APIClient:
|
||||
self.base_url = base_url
|
||||
self.endpoint = "/generate_plan"
|
||||
|
||||
def send_request(self, prompt, timeout=60):
|
||||
def send_debug_stage(
|
||||
self, prompt: str, drone_state: str = "on_ground", target_stage: int = 1, timeout=120
|
||||
):
|
||||
"""
|
||||
Stage 分阶段调试请求。
|
||||
target_stage: 1-6
|
||||
Returns: 同 send_request 结构,data 为 debug 端返回的 {target_stage, stage_name, output}
|
||||
"""
|
||||
url = f"{self.base_url}/debug_stage"
|
||||
payload = {
|
||||
"user_prompt": prompt,
|
||||
"drone_state": drone_state,
|
||||
"target_stage": target_stage,
|
||||
}
|
||||
headers = {"Content-Type": "application/json"}
|
||||
start_time = time.time()
|
||||
try:
|
||||
response = requests.post(url, json=payload, headers=headers, timeout=timeout)
|
||||
latency = time.time() - start_time
|
||||
response.raise_for_status()
|
||||
try:
|
||||
data = response.json()
|
||||
if "error" in data and len(data) == 1:
|
||||
return {
|
||||
"success": False,
|
||||
"data": data,
|
||||
"latency": latency,
|
||||
"error": data["error"],
|
||||
"http_status": response.status_code,
|
||||
}
|
||||
return {
|
||||
"success": True,
|
||||
"data": data,
|
||||
"latency": latency,
|
||||
"error": None,
|
||||
"http_status": response.status_code,
|
||||
}
|
||||
except json.JSONDecodeError:
|
||||
return {
|
||||
"success": False,
|
||||
"data": None,
|
||||
"latency": latency,
|
||||
"error": f"Invalid JSON: {response.text[:200]}",
|
||||
"http_status": response.status_code,
|
||||
}
|
||||
except requests.exceptions.RequestException as e:
|
||||
latency = time.time() - start_time
|
||||
return {
|
||||
"success": False,
|
||||
"data": None,
|
||||
"latency": latency,
|
||||
"error": str(e),
|
||||
"http_status": getattr(e.response, "status_code", None) if hasattr(e, "response") and e.response is not None else None,
|
||||
}
|
||||
|
||||
def send_request(self, prompt, drone_state="on_ground", timeout=60):
|
||||
"""
|
||||
Sends a request to the API and returns a structured result.
|
||||
Returns:
|
||||
@@ -20,7 +75,7 @@ class APIClient:
|
||||
}
|
||||
"""
|
||||
url = f"{self.base_url}{self.endpoint}"
|
||||
payload = {"user_prompt": prompt}
|
||||
payload = {"user_prompt": prompt, "drone_state": drone_state}
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
259
tools/test_validate/modules/stage_debugger.py
Normal file
@@ -0,0 +1,259 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Stage 分阶段调试模块:支持单条指令调试与批量指令调试。
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import csv
|
||||
import time
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from .api_client import APIClient
|
||||
from .visualizer import generate_visualization, sanitize_filename
|
||||
|
||||
# Stage 名称映射
|
||||
STAGE_NAMES = {
|
||||
1: "Stage1 任务理解 (TaskUnderstanding)",
|
||||
2: "Stage2 上下文绑定 (ContextBinding)",
|
||||
3: "Stage3 宏观规划 (BTDraft)",
|
||||
4: "Stage4 中间层解析 (MiddlewareResolution)",
|
||||
5: "Stage5 微观填参 (MicroFilling)",
|
||||
6: "Stage6 校验与后处理 (ValidateAndPostprocess)",
|
||||
}
|
||||
|
||||
|
||||
def _select_stage():
|
||||
"""交互式选择调试 stage"""
|
||||
print("\n可选 Stage:")
|
||||
for k, v in STAGE_NAMES.items():
|
||||
print(f" {k}. {v}")
|
||||
while True:
|
||||
try:
|
||||
choice = int(input("请选择 Stage [1-6]: ").strip())
|
||||
if 1 <= choice <= 6:
|
||||
return choice
|
||||
except ValueError:
|
||||
pass
|
||||
print("❌ 请输入 1-6 之间的数字")
|
||||
|
||||
|
||||
def _infer_drone_state_from_prompt(prompt: str) -> str:
|
||||
"""从指令中简单推断 drone_state(批量模式下若未单独指定则用此)"""
|
||||
if "在空中" in prompt or "已起飞" in prompt:
|
||||
return "in_air"
|
||||
return "on_ground"
|
||||
|
||||
|
||||
def run_stage_debug_single():
|
||||
"""单条指令 Stage 调试"""
|
||||
client = APIClient()
|
||||
print("\n🚀 进入 Stage 分阶段调试 - 单条模式 (输入 'exit' 或 'q' 退出)")
|
||||
|
||||
while True:
|
||||
try:
|
||||
prompt = input("\n请输入测试指令: ").strip()
|
||||
if prompt.lower() in ("exit", "q"):
|
||||
break
|
||||
if not prompt:
|
||||
continue
|
||||
|
||||
target_stage = _select_stage()
|
||||
drone_state = input("无人机状态 [on_ground/in_air,回车默认根据指令推断]: ").strip()
|
||||
if not drone_state:
|
||||
drone_state = _infer_drone_state_from_prompt(prompt)
|
||||
|
||||
print(f"\n⏳ 运行至 {STAGE_NAMES[target_stage]}...")
|
||||
result = client.send_debug_stage(
|
||||
prompt=prompt,
|
||||
drone_state=drone_state,
|
||||
target_stage=target_stage,
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
print(f"✅ 请求成功 (耗时: {result['latency']:.2f}s)")
|
||||
data = result["data"]
|
||||
output = data.get("output", data)
|
||||
print("\n" + "=" * 60)
|
||||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||||
print("=" * 60)
|
||||
|
||||
# 保存到 validation/temporary
|
||||
base_dir = os.path.dirname(os.path.dirname(__file__))
|
||||
safe_name = sanitize_filename(prompt)[:80]
|
||||
out_dir = os.path.join(
|
||||
base_dir, "validation", "temporary", f"stage{target_stage}_{safe_name}"
|
||||
)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
out_path = os.path.join(out_dir, "response.json")
|
||||
with open(out_path, "w", encoding="utf-8") as f:
|
||||
json.dump(result["data"], f, indent=2, ensure_ascii=False)
|
||||
print(f"\n📂 结果已保存: {out_path}")
|
||||
|
||||
# Stage 6 输出含 root 时生成可视化
|
||||
if target_stage == 6 and isinstance(output, dict) and "root" in output:
|
||||
png_path = os.path.join(out_dir, "plan.png")
|
||||
if generate_visualization(output["root"], png_path):
|
||||
print(f"🖼️ 可视化: {png_path}")
|
||||
else:
|
||||
print(f"❌ 请求失败: {result['error']}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n已取消")
|
||||
break
|
||||
|
||||
print("\n已返回 Stage 调试菜单")
|
||||
|
||||
|
||||
def run_stage_debug_batch():
|
||||
"""批量指令 Stage 调试(参考 batch_runner)"""
|
||||
base_dir = os.path.dirname(os.path.dirname(__file__))
|
||||
instr_dir = os.path.join(base_dir, "instructions")
|
||||
files = [f for f in os.listdir(instr_dir) if f.endswith(".txt")]
|
||||
|
||||
if not files:
|
||||
print("❌ 未在 instructions 目录下找到 .txt 文件")
|
||||
return
|
||||
|
||||
print("\n请选择测试指令文件:")
|
||||
for i, f in enumerate(files):
|
||||
print(f" {i+1}. {f}")
|
||||
try:
|
||||
idx = int(input("请输入序号: ").strip()) - 1
|
||||
if idx < 0 or idx >= len(files):
|
||||
print("❌ 无效序号")
|
||||
return
|
||||
selected_file = os.path.join(instr_dir, files[idx])
|
||||
except ValueError:
|
||||
print("❌ 输入无效")
|
||||
return
|
||||
|
||||
target_stage = _select_stage()
|
||||
drone_state_override = input(
|
||||
"无人机状态 [回车=每条根据指令推断, on_ground/in_air=全局固定]: "
|
||||
).strip()
|
||||
if drone_state_override and drone_state_override not in ("on_ground", "in_air"):
|
||||
drone_state_override = ""
|
||||
|
||||
try:
|
||||
iterations = int(input("每条指令测试次数 (默认1): ").strip() or "1")
|
||||
except ValueError:
|
||||
iterations = 1
|
||||
|
||||
# 输出目录
|
||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
output_dir = os.path.join(
|
||||
base_dir, "validation", f"stage{target_stage}_debug_{timestamp}"
|
||||
)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
shutil.copy(selected_file, os.path.join(output_dir, "instructions_backup.txt"))
|
||||
|
||||
with open(selected_file, "r", encoding="utf-8") as f:
|
||||
instructions = [
|
||||
line.strip()
|
||||
for line in f
|
||||
if line.strip() and not line.startswith("#")
|
||||
]
|
||||
|
||||
print(
|
||||
f"\n🚀 开始批量 Stage{target_stage} 调试 (共 {len(instructions)} 条, 每条 {iterations} 次)"
|
||||
)
|
||||
print(f"📂 输出: {output_dir}\n")
|
||||
|
||||
client = APIClient()
|
||||
detailed_results = []
|
||||
summary_stats = {}
|
||||
|
||||
for i, prompt in enumerate(instructions, 1):
|
||||
drone_state = (
|
||||
drone_state_override
|
||||
if drone_state_override
|
||||
else _infer_drone_state_from_prompt(prompt)
|
||||
)
|
||||
print(f"[{i}/{len(instructions)}] {prompt[:40]}... (state={drone_state})")
|
||||
|
||||
safe_name = sanitize_filename(prompt)
|
||||
instr_out_dir = os.path.join(output_dir, safe_name)
|
||||
os.makedirs(instr_out_dir, exist_ok=True)
|
||||
|
||||
success_count = 0
|
||||
total_latency = 0
|
||||
|
||||
for k in range(1, iterations + 1):
|
||||
print(f" - 第 {k} 次...", end="", flush=True)
|
||||
result = client.send_debug_stage(
|
||||
prompt=prompt,
|
||||
drone_state=drone_state,
|
||||
target_stage=target_stage,
|
||||
)
|
||||
|
||||
detailed_results.append(
|
||||
{
|
||||
"instruction": prompt,
|
||||
"run_id": k,
|
||||
"success": result["success"],
|
||||
"latency": result["latency"],
|
||||
"error": result.get("error") or "",
|
||||
}
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
print(f" ✅ ({result['latency']:.2f}s)")
|
||||
success_count += 1
|
||||
total_latency += result["latency"]
|
||||
|
||||
out_path = os.path.join(instr_out_dir, f"{k}.json")
|
||||
with open(out_path, "w", encoding="utf-8") as f:
|
||||
json.dump(result["data"], f, indent=2, ensure_ascii=False)
|
||||
|
||||
# Stage6 且含 root 时生成可视化
|
||||
data = result["data"]
|
||||
output = data.get("output", data) if isinstance(data, dict) else {}
|
||||
if (
|
||||
target_stage == 6
|
||||
and isinstance(output, dict)
|
||||
and "root" in output
|
||||
):
|
||||
generate_visualization(
|
||||
output["root"],
|
||||
os.path.join(instr_out_dir, f"{k}.png"),
|
||||
)
|
||||
else:
|
||||
print(f" ❌ {result.get('error', 'Unknown')}")
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
avg_lat = total_latency / success_count if success_count > 0 else 0
|
||||
summary_stats[prompt] = {
|
||||
"total_runs": iterations,
|
||||
"success_runs": success_count,
|
||||
"success_rate": f"{(success_count / iterations) * 100:.1f}%",
|
||||
"avg_latency": f"{avg_lat:.2f}s",
|
||||
}
|
||||
|
||||
# 报告
|
||||
with open(os.path.join(output_dir, "test_details.csv"), "w", newline="", encoding="utf-8") as f:
|
||||
writer = csv.DictWriter(
|
||||
f, fieldnames=["instruction", "run_id", "success", "latency", "error"]
|
||||
)
|
||||
writer.writeheader()
|
||||
writer.writerows(detailed_results)
|
||||
|
||||
with open(os.path.join(output_dir, "test_summary.csv"), "w", newline="", encoding="utf-8") as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(
|
||||
["Instruction", "Total Runs", "Success Runs", "Success Rate", "Avg Latency"]
|
||||
)
|
||||
for prompt, stats in summary_stats.items():
|
||||
writer.writerow(
|
||||
[
|
||||
prompt,
|
||||
stats["total_runs"],
|
||||
stats["success_runs"],
|
||||
stats["success_rate"],
|
||||
stats["avg_latency"],
|
||||
]
|
||||
)
|
||||
|
||||
print(f"\n✅ Stage{target_stage} 批量调试完成! 报告: {output_dir}")
|
||||
@@ -12,6 +12,7 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
from modules.interactive_test import run_interactive_test
|
||||
from modules.batch_runner import run_batch_test
|
||||
from modules.json_visualizer import run_json_visualization
|
||||
from modules.stage_debugger import run_stage_debug_single, run_stage_debug_batch
|
||||
|
||||
def clear_screen():
|
||||
os.system('cls' if os.name == 'nt' else 'clear')
|
||||
@@ -51,6 +52,34 @@ def run_legacy_module(module_name, args=None):
|
||||
|
||||
input("\n按回车键返回菜单...")
|
||||
|
||||
def _run_stage_debug_menu():
|
||||
"""Stage 分阶段调试子菜单"""
|
||||
while True:
|
||||
print_header()
|
||||
print("Stage 分阶段调试")
|
||||
print("-" * 60)
|
||||
print("1. 单条指令调试 - 输入指令,选择 Stage,查看该 Stage 输出")
|
||||
print("2. 批量指令调试 - 从文件读取指令,批量运行到选定 Stage")
|
||||
print("0. 返回主菜单")
|
||||
print("-" * 60)
|
||||
sub = input("请选择 [0-2]: ").strip()
|
||||
if sub == "1":
|
||||
try:
|
||||
run_stage_debug_single()
|
||||
except Exception as e:
|
||||
print(f"❌ 运行出错: {e}")
|
||||
input("\n按回车键返回...")
|
||||
elif sub == "2":
|
||||
try:
|
||||
run_stage_debug_batch()
|
||||
except Exception as e:
|
||||
print(f"❌ 运行出错: {e}")
|
||||
input("\n按回车键返回...")
|
||||
elif sub == "0":
|
||||
break
|
||||
else:
|
||||
print("❌ 无效选项")
|
||||
|
||||
def menu_drone_upload():
|
||||
print("\n[3] 上传任务到无人机")
|
||||
print("说明: 将生成的任务文件上传到无人机 (Ground Station Client)。")
|
||||
@@ -84,10 +113,12 @@ def main():
|
||||
print("3. 上传任务到无人机 (Drone Uploader)")
|
||||
print("4. LLM 服务连通性测试 (LLM Tester)")
|
||||
print("5. JSON 文件可视化 (Visualize JSON File)")
|
||||
print("6. Stage 分阶段调试 (Stage Debug)")
|
||||
print(" - 单条/批量运行到指定 Stage,查看中间输出")
|
||||
print("0. 退出")
|
||||
print("-" * 60)
|
||||
|
||||
choice = input("请输入选项 [0-5]: ").strip()
|
||||
choice = input("请输入选项 [0-6]: ").strip()
|
||||
|
||||
if choice == '1':
|
||||
try:
|
||||
@@ -111,7 +142,10 @@ def main():
|
||||
|
||||
elif choice == '5':
|
||||
run_json_visualization()
|
||||
|
||||
|
||||
elif choice == '6':
|
||||
_run_stage_debug_menu()
|
||||
|
||||
elif choice == '0':
|
||||
print("\n👋 再见!")
|
||||
break
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
无人机当前在地面,到飞行场地查找穿红色衣服的男子,找到后近距离拍照。
|
||||
无人机当前在空中,回到飞行场地,对戴帽子的人进行拍照。
|
||||
无人机当前在空中,去飞行场地西边50米,对过往穿红色衣服的人拍张照,然后返航。
|
||||
无人机当前在地面,到飞行场地查找长头发的人,看见了拍个照片。
|
||||
无人机当前在空中,搜索穿红色衣服的人,搜索到了拍张照,我确认后再决定要不要返航。
|
||||
无人机当前在空中,往飞行场地西边飞50米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。
|
||||
无人机当前在地面,到飞行场地,发现未带帽子的飞近后拍照。
|
||||
无人机当前在空中,紧急回到飞行场地,看见了树之后直接降落。
|
||||
无人机当前在地面,快速去往东边30米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。
|
||||
|
After Width: | Height: | Size: 86 KiB |
@@ -0,0 +1,10 @@
|
||||
无人机当前在地面,到飞行场地查找穿红色衣服的男子,找到后近距离拍照。
|
||||
无人机当前在空中,回到飞行场地,对戴帽子的人进行拍照。
|
||||
无人机当前在空中,去飞行场地西边50米,对过往穿红色衣服的人拍张照,然后返航。
|
||||
无人机当前在地面,到飞行场地查找长头发的人,看见了拍个照片。
|
||||
无人机当前在空中,搜索穿红色衣服的人,搜索到了拍张照,我确认后再决定要不要返航。
|
||||
无人机当前在空中,往飞行场地西边飞50米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。
|
||||
无人机当前在地面,到飞行场地,发现未带帽子的飞近后拍照。
|
||||
无人机当前在空中,紧急回到飞行场地,看见了树之后直接降落。
|
||||
无人机当前在地面,快速去往东边30米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。
|
||||
|
After Width: | Height: | Size: 86 KiB |
@@ -0,0 +1,9 @@
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。
|
||||
无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的人并拍照。
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。
|
||||
@@ -0,0 +1,10 @@
|
||||
instruction,run_id,success,latency,error
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。,1,True,16.063878774642944,
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。,1,False,16.235912084579468,500 Server Error: Internal Server Error for url: http://127.0.0.1:8000/generate_plan
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。,1,True,11.32945990562439,
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。,1,False,18.68914246559143,500 Server Error: Internal Server Error for url: http://127.0.0.1:8000/generate_plan
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。,1,True,14.857678651809692,
|
||||
无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。,1,True,11.974151134490967,
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。,1,True,15.218279838562012,
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的人并拍照。,1,True,15.252280473709106,
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。,1,True,12.335286378860474,
|
||||
|
@@ -0,0 +1,10 @@
|
||||
Instruction,Total Runs,Success Runs,Success Rate,Avg Latency
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。,1,1,100.0%,16.06s
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。,1,0,0.0%,0.00s
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。,1,1,100.0%,11.33s
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。,1,0,0.0%,0.00s
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。,1,1,100.0%,14.86s
|
||||
无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。,1,1,100.0%,11.97s
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。,1,1,100.0%,15.22s
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的人并拍照。,1,1,100.0%,15.25s
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。,1,1,100.0%,12.34s
|
||||
|
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,11 @@
|
||||
无人机当前在地面,到广场查找穿红色衣服的人,找到后近距离拍照。
|
||||
无人机当前在空中,回到广场,对戴帽子的人进行拍照。
|
||||
无人机当前在空中,去广场南边40米,对过往的公交车拍张照,然后返航。
|
||||
无人机当前在地面,到广场查找绿色公交车,看见了拍个照片。
|
||||
无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。
|
||||
无人机当前在空中,搜索小汽车,搜索到了拍张照,我确认后再决定要不要返航。
|
||||
无人机当前在空中,往广场南边飞40米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。
|
||||
无人机当前在地面,到广场边上的施工区域内,发现有没带安全帽的飞近后拍照。
|
||||
无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。
|
||||
无人机当前在地面,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。
|
||||
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "on_ground",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "无人机当前在地面,起飞"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "无人机当前在空中,飞到广场"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "无人机当前在空中,飞到广场北边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": true,
|
||||
"entities": {
|
||||
"raw_prompt": "无人机当前在空中,飞到面前的大楼"
|
||||
},
|
||||
"risk_flags": [
|
||||
"relative_reference_detected"
|
||||
],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene4",
|
||||
"drone_state": "on_ground",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "无空中,飞到广场"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "on_ground",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "起飞"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到南广场"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到大楼"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到学校"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到学校北边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到宿舍"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到宿舍北边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到宿舍南边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到宿舍南边60米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到广场"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到广场北边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到广场南边"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到广场南边40米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到广场南边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到广场西边"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到建筑物A"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到建筑物A南边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到研究所东侧30米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到研究所东边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到研究所东边60米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到研究所东边60米的施工场所"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "scene1",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "generic_mission",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到研究所南边50米"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"target_stage": 1,
|
||||
"stage_name": "TaskUnderstanding",
|
||||
"output": {
|
||||
"scene_mode": "simple",
|
||||
"drone_state": "in_air",
|
||||
"intent_type": "single_action",
|
||||
"requires_relative_target": false,
|
||||
"entities": {
|
||||
"raw_prompt": "飞到研究院"
|
||||
},
|
||||
"risk_flags": [],
|
||||
"constraints": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"target_stage": 2,
|
||||
"stage_name": "ContextBinding",
|
||||
"output": {
|
||||
"location_context": "{\"property\": \"location\", \"information\": {\"name\": \"广场\", \"coordinates\": {\"x\": 100, \"y\": 260, \"z\": 0}}}\n\n{\"property\": \"location\", \"information\": {\"name\": \"飞行场地\", \"coordinates\": {\"x\": 0, \"y\": 0, \"z\": 0}}}\n\n{\"property\": \"location\", \"information\": {\"name\": \"大楼外围四个点东南天坐标系坐标\", \"coordinates\": {\"A\": {\"x\": -24.0, \"y\": 241.8, \"z\": 0}, \"B\": {\"x\": -108.5, \"y\": 241.8, \"z\": 0}, \"C\": {\"x\": -108.5, \"y\": 289.8, \"z\": 0}, \"D\": {\"x\": -24.0, \"y\": 292.8, \"z\": 0}}}}",
|
||||
"pattern_context": "无人机当前在空中,往广场西边飞200米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。\n\n无人机当前在地面,去研究所正大门,搜索扎辫子女子,找到后拍照。\n\n地面起飞后到面前大楼约12米高度,沿外围巡查打开窗户;如发现窗户则拍照回传。",
|
||||
"rules_context": "",
|
||||
"citations": {
|
||||
"location": [
|
||||
"{\"property\": \"location\", \"information\": {\"name\": \"广场\", \"coordinates\": {\"x\": 100, \"y\": 260, \"z\": 0}}}",
|
||||
"{\"property\": \"location\", \"information\": {\"name\": \"飞行场地\", \"coordinates\": {\"x\": 0, \"y\": 0, \"z\": 0}}}",
|
||||
"{\"property\": \"location\", \"information\": {\"name\": \"大楼外围四个点东南天坐标系坐标\", \"coordinates\": {\"A\": {\"x\": -24.0, \"y\": 241.8, \"z\": 0}, \"B\": {\"x\": -108.5, \"y\": 241.8, \"z\": 0}, \"C\": {\"x\": -108.5, \"y\": 289.8, \"z\": 0}, \"D\": {\"x\": -24.0, \"y\": 292.8, \"z\": 0}}}}"
|
||||
],
|
||||
"pattern": [
|
||||
"无人机当前在空中,往广场西边飞200米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。",
|
||||
"无人机当前在地面,去研究所正大门,搜索扎辫子女子,找到后拍照。",
|
||||
"地面起飞后到面前大楼约12米高度,沿外围巡查打开窗户;如发现窗户则拍照回传。"
|
||||
],
|
||||
"rules": []
|
||||
},
|
||||
"resolved_refs": {},
|
||||
"precomputed_waypoints": [
|
||||
{
|
||||
"x": 150.0,
|
||||
"y": 260.0,
|
||||
"z": 0.0
|
||||
}
|
||||
],
|
||||
"relative_refs": [],
|
||||
"required_actions": [
|
||||
"Selector",
|
||||
"Sequence",
|
||||
"fly_to_waypoint",
|
||||
"land",
|
||||
"move_direction",
|
||||
"object_detect",
|
||||
"object_detected",
|
||||
"rotate_search",
|
||||
"take_photos",
|
||||
"takeoff"
|
||||
]
|
||||
}
|
||||
}
|
||||