新增方位解析function call
This commit is contained in:
@@ -299,10 +299,20 @@
|
||||
|
||||
**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:**
|
||||
|
||||
当指令包含“具体地点 + 方向 + 距离”的偏移(如“广场西边200米”)时,**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||
- `direction`: east/west/north/south/up/down
|
||||
- `distance`: 偏移距离(米)
|
||||
当指令包含“具体地点 + 方向 + 距离”的偏移时,按方向类型选择工具:
|
||||
- **单一方向**(东/西/南/北/上/下,如“广场西边200米”):**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||
- `direction`: east/west/north/south/up/down
|
||||
- `distance`: 偏移距离(米)
|
||||
- **中文复合方位**(东南/西北/东北/西南/南偏东10度/北偏西15度等):**必须**先调用工具`calc_offset_esu_direction_text`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||
- `direction_text`: 中文方位原文(如“东南”“南偏东10度”)
|
||||
- `distance`: 偏移距离(米)
|
||||
- **禁止简化**:当出现“东南/西北/东北/西南/南偏东/北偏西”等复合方位时,禁止将其简化为单一方向(如仅“东”或仅“南”)。
|
||||
|
||||
示例(必须遵守):
|
||||
- “飞到广场东南方向100米” → 必须调用 `calc_offset_esu_direction_text`,参数 `direction_text` 为 `"东南"`,`distance` 为 `100`,再使用 `fly_to_waypoint`。
|
||||
- “飞到广场南偏东10度100米” → 必须调用 `calc_offset_esu_direction_text`,参数 `direction_text` 为 `"南偏东10度"`,`distance` 为 `100`。
|
||||
|
||||
当指令只有“方向 + 距离”且**没有具体地点名词**时,**禁止**调用`calc_offset_enu`,必须使用`move_direction`。
|
||||
当指令描述“附近/边上/区域内”等模糊位置且**无方向+距离**时,视为到该地点本身,不做偏移计算。
|
||||
|
||||
@@ -789,10 +789,20 @@
|
||||
|
||||
**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:**
|
||||
|
||||
当指令包含“具体地点 + 方向 + 距离”的偏移(如“广场西边200米”)时,**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||
- `direction`: east/west/north/south/up/down
|
||||
- `distance`: 偏移距离(米)
|
||||
当指令包含“具体地点 + 方向 + 距离”的偏移时,按方向类型选择工具:
|
||||
- **单一方向**(东/西/南/北/上/下,如“广场西边200米”):**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||
- `direction`: east/west/north/south/up/down
|
||||
- `distance`: 偏移距离(米)
|
||||
- **中文复合方位**(东南/西北/东北/西南/南偏东10度/北偏西15度等):**必须**先调用工具`calc_offset_esu_direction_text`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||
- `direction_text`: 中文方位原文(如“东南”“南偏东10度”)
|
||||
- `distance`: 偏移距离(米)
|
||||
- **禁止简化**:当出现“东南/西北/东北/西南/南偏东/北偏西”等复合方位时,禁止将其简化为单一方向(如仅“东”或仅“南”)。
|
||||
|
||||
示例(必须遵守):
|
||||
- “飞到广场东南方向100米” → 必须调用 `calc_offset_esu_direction_text`,参数 `direction_text` 为 `"东南"`,`distance` 为 `100`,再使用 `fly_to_waypoint`。
|
||||
- “飞到广场南偏东10度100米” → 必须调用 `calc_offset_esu_direction_text`,参数 `direction_text` 为 `"南偏东10度"`,`distance` 为 `100`。
|
||||
|
||||
当指令只有“方向 + 距离”且**没有具体地点名词**时,**禁止**调用`calc_offset_enu`,必须使用`move_direction`。
|
||||
当指令描述“附近/边上/区域内”等模糊位置且**无方向+距离**时,视为到该地点本身,不做偏移计算。
|
||||
|
||||
BIN
backend_service/src/tools/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
backend_service/src/tools/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import re
|
||||
from typing import Dict, Tuple
|
||||
|
||||
|
||||
@@ -37,3 +39,72 @@ def calc_offset_enu(base: Dict[str, float], direction: str, distance: float) ->
|
||||
offset_z = z + dz * distance
|
||||
|
||||
return {"x": offset_x, "y": offset_y, "z": offset_z}
|
||||
|
||||
|
||||
_DIRECTION_TEXT_DIAGONALS_ESU: Dict[str, Tuple[float, float]] = {
|
||||
"东南": (1.0, 1.0),
|
||||
"西南": (-1.0, 1.0),
|
||||
"东北": (1.0, -1.0),
|
||||
"西北": (-1.0, -1.0),
|
||||
}
|
||||
|
||||
|
||||
def _parse_direction_text_esu(direction_text: str) -> Tuple[float, float]:
|
||||
text = (direction_text or "").strip().replace(" ", "")
|
||||
if not text:
|
||||
raise ValueError("direction_text must be a non-empty string")
|
||||
|
||||
for prefix in ("向", "正"):
|
||||
if text.startswith(prefix):
|
||||
text = text[len(prefix):]
|
||||
|
||||
if text in _DIRECTION_TEXT_DIAGONALS_ESU:
|
||||
x, y = _DIRECTION_TEXT_DIAGONALS_ESU[text]
|
||||
length = math.hypot(x, y)
|
||||
return x / length, y / length
|
||||
|
||||
if text in ("东", "西", "南", "北"):
|
||||
if text == "东":
|
||||
return 1.0, 0.0
|
||||
if text == "西":
|
||||
return -1.0, 0.0
|
||||
if text == "南":
|
||||
return 0.0, 1.0
|
||||
return 0.0, -1.0
|
||||
|
||||
match = re.match(r"^(南|北)偏(东|西)(\d+(?:\.\d+)?)度?$", text)
|
||||
if match:
|
||||
base_dir, toward_dir, angle_str = match.groups()
|
||||
angle_deg = float(angle_str)
|
||||
if angle_deg < 0 or angle_deg > 90:
|
||||
raise ValueError("angle must be between 0 and 90 degrees")
|
||||
angle_rad = math.radians(angle_deg)
|
||||
x_sign = 1.0 if toward_dir == "东" else -1.0
|
||||
if base_dir == "南":
|
||||
return math.sin(angle_rad) * x_sign, math.cos(angle_rad)
|
||||
return math.sin(angle_rad) * x_sign, -math.cos(angle_rad)
|
||||
|
||||
raise ValueError(f"unsupported direction_text: {direction_text}")
|
||||
|
||||
|
||||
def calc_offset_esu_direction_text(
|
||||
base: Dict[str, float], direction_text: str, distance: float
|
||||
) -> Dict[str, float]:
|
||||
"""在ESU坐标系下按中文方位偏移固定距离。"""
|
||||
if distance < 0:
|
||||
raise ValueError("distance must be non-negative")
|
||||
if not isinstance(base, dict):
|
||||
raise ValueError("base must be an object with x/y/z")
|
||||
|
||||
try:
|
||||
x = float(base["x"])
|
||||
y = float(base["y"])
|
||||
z = float(base["z"])
|
||||
except Exception as exc:
|
||||
raise ValueError("base must contain numeric x/y/z") from exc
|
||||
|
||||
dx_unit, dy_unit = _parse_direction_text_esu(direction_text)
|
||||
offset_x = x + dx_unit * distance
|
||||
offset_y = y + dy_unit * distance
|
||||
|
||||
return {"x": offset_x, "y": offset_y, "z": z}
|
||||
|
||||
Reference in New Issue
Block a user