add 飞行模式
This commit is contained in:
113
flight_mode.py
Normal file
113
flight_mode.py
Normal file
@@ -0,0 +1,113 @@
|
||||
"""
|
||||
飞行模式逻辑:
|
||||
- 从坐标 JSON 读取最后一个坐标点作为目的地
|
||||
- 每帧调用 `CoordinatePatrol.simple_flight_navigate()` 执行:
|
||||
1) 上马(未上马则先上马,mount_key/mount_hold_sec 从 game_state_config.json 读取)
|
||||
2) 起飞
|
||||
3) 飞向目的地坐标
|
||||
4) 降落
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from coordinate_patrol import CoordinatePatrol
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _load_last_waypoint_from_json(path):
|
||||
"""读取与巡逻相同的 JSON 格式:[[x,y], ...],返回最后一个有效点 (x, y)。"""
|
||||
if not path:
|
||||
return None
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
except Exception as e:
|
||||
logger.warning("读取航线 JSON 失败: %s", e)
|
||||
return None
|
||||
if not isinstance(data, list):
|
||||
return None
|
||||
last = None
|
||||
for item in data:
|
||||
if isinstance(item, (list, tuple)) and len(item) >= 2:
|
||||
try:
|
||||
last = (float(item[0]), float(item[1]))
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
return last
|
||||
|
||||
|
||||
class FlightModeBot:
|
||||
"""飞行模式控制器:每次执行逻辑只推动状态前进一步。"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
json_path,
|
||||
log_callback=None,
|
||||
*,
|
||||
takeoff_key="space",
|
||||
takeoff_hold_sec=2.0,
|
||||
land_key="p",
|
||||
land_hold_sec=2.0,
|
||||
):
|
||||
self._log = log_callback or (lambda _m: None)
|
||||
self.destination = _load_last_waypoint_from_json(json_path)
|
||||
self.done = False
|
||||
|
||||
# 上马按键与时长来自 game_state_config.json
|
||||
try:
|
||||
from game_state import load_layout_config
|
||||
|
||||
cfg = load_layout_config()
|
||||
mount_key = str(cfg.get("mount_key", "x") or "x")
|
||||
mount_hold_sec = float(cfg.get("mount_hold_sec", 1.6))
|
||||
mount_retry_after_sec = float(cfg.get("mount_retry_after_sec", 2.0))
|
||||
except Exception:
|
||||
mount_key, mount_hold_sec, mount_retry_after_sec = "x", 1.6, 2.0
|
||||
|
||||
# 只用于 simple_flight_navigate 内部的 _ensure_mounted 与一些公共参数
|
||||
self._patrol = CoordinatePatrol(
|
||||
waypoints=[(0.0, 0.0)] if self.destination else [],
|
||||
mount_key=mount_key,
|
||||
mount_hold_sec=mount_hold_sec,
|
||||
mount_retry_after_sec=mount_retry_after_sec,
|
||||
)
|
||||
|
||||
self.takeoff_key = takeoff_key
|
||||
self.takeoff_hold_sec = float(takeoff_hold_sec)
|
||||
self.land_key = land_key
|
||||
self.land_hold_sec = float(land_hold_sec)
|
||||
|
||||
if not self.destination:
|
||||
self._log("❌ 飞行模式:JSON 中无有效坐标点")
|
||||
self.done = True
|
||||
|
||||
def execute_logic(self, state):
|
||||
if self.done:
|
||||
return
|
||||
if state is None:
|
||||
return
|
||||
if not self.destination:
|
||||
self.done = True
|
||||
return
|
||||
|
||||
arrived = self._patrol.simple_flight_navigate(
|
||||
state,
|
||||
self.destination[0],
|
||||
self.destination[1],
|
||||
takeoff_key=self.takeoff_key,
|
||||
takeoff_hold_sec=self.takeoff_hold_sec,
|
||||
land_key=self.land_key,
|
||||
land_hold_sec=self.land_hold_sec,
|
||||
dismount_key=self._patrol.mount_key,
|
||||
arrival_threshold=self._patrol.arrival_threshold,
|
||||
mount_wait_sec=self._patrol.mount_hold_sec,
|
||||
)
|
||||
|
||||
if arrived:
|
||||
self._patrol.stop_all()
|
||||
self.done = True
|
||||
self._log("✅ 飞行模式:已到达目的地并降落完成")
|
||||
|
||||
Reference in New Issue
Block a user