新增方位解析function call
This commit is contained in:
@@ -299,10 +299,20 @@
|
|||||||
|
|
||||||
**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:**
|
**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:**
|
||||||
|
|
||||||
当指令包含“具体地点 + 方向 + 距离”的偏移(如“广场西边200米”)时,**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
当指令包含“具体地点 + 方向 + 距离”的偏移时,按方向类型选择工具:
|
||||||
|
- **单一方向**(东/西/南/北/上/下,如“广场西边200米”):**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||||
- `direction`: east/west/north/south/up/down
|
- `direction`: east/west/north/south/up/down
|
||||||
- `distance`: 偏移距离(米)
|
- `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`。
|
当指令只有“方向 + 距离”且**没有具体地点名词**时,**禁止**调用`calc_offset_enu`,必须使用`move_direction`。
|
||||||
当指令描述“附近/边上/区域内”等模糊位置且**无方向+距离**时,视为到该地点本身,不做偏移计算。
|
当指令描述“附近/边上/区域内”等模糊位置且**无方向+距离**时,视为到该地点本身,不做偏移计算。
|
||||||
|
|||||||
@@ -789,10 +789,20 @@
|
|||||||
|
|
||||||
**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:**
|
**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:**
|
||||||
|
|
||||||
当指令包含“具体地点 + 方向 + 距离”的偏移(如“广场西边200米”)时,**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
当指令包含“具体地点 + 方向 + 距离”的偏移时,按方向类型选择工具:
|
||||||
|
- **单一方向**(东/西/南/北/上/下,如“广场西边200米”):**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||||
- `direction`: east/west/north/south/up/down
|
- `direction`: east/west/north/south/up/down
|
||||||
- `distance`: 偏移距离(米)
|
- `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`。
|
当指令只有“方向 + 距离”且**没有具体地点名词**时,**禁止**调用`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
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
import re
|
||||||
from typing import Dict, Tuple
|
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
|
offset_z = z + dz * distance
|
||||||
|
|
||||||
return {"x": offset_x, "y": offset_y, "z": offset_z}
|
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