add 飞行模式
This commit is contained in:
@@ -343,6 +343,136 @@ class CoordinatePatrol:
|
||||
|
||||
return False
|
||||
|
||||
def simple_flight_navigate(
|
||||
self,
|
||||
state,
|
||||
target_x,
|
||||
target_y,
|
||||
*,
|
||||
takeoff_key="space",
|
||||
takeoff_hold_sec=2.0,
|
||||
land_key="p",
|
||||
land_hold_sec=4.0,
|
||||
dismount_key=None,
|
||||
arrival_threshold=0.003,
|
||||
turn_deadzone_deg=5.0,
|
||||
mount_wait_sec=2.5,
|
||||
):
|
||||
"""
|
||||
极简飞行导航:只做 1.上马 2.起飞 3.飞向坐标 4.降落。
|
||||
|
||||
说明:
|
||||
- 当前项目的飞行状态使用 `state['flight']`(0/0.5/1),并换算到 0..255 再按阈值判断阶段。
|
||||
- 只做“极简控制”,不包含卡死检测与复杂脱困逻辑。
|
||||
"""
|
||||
if state is None:
|
||||
return False
|
||||
|
||||
curr_x, curr_y = state.get("x"), state.get("y")
|
||||
curr_facing = state.get("facing")
|
||||
if None in (curr_x, curr_y, curr_facing):
|
||||
return False
|
||||
|
||||
# 统一 mount 逻辑:优先使用 mounted 字段
|
||||
if "mounted" in state and state.get("mounted") is False:
|
||||
# 用与其它逻辑一致的上马方式,按 game_state_config 的 mount_key/mount_hold_sec
|
||||
ok = self._ensure_mounted(state)
|
||||
return False if not ok else False
|
||||
|
||||
# 归一化飞行信号:把 state['flight'] 映射为 0..255
|
||||
flight_raw = state.get("flight", None)
|
||||
|
||||
f_signal = None
|
||||
if isinstance(flight_raw, (int, float)):
|
||||
# 若是三档 0/0.5/1,则换算到 0..255
|
||||
if float(flight_raw) <= 1.0:
|
||||
f_signal = float(flight_raw) * 255.0
|
||||
else:
|
||||
f_signal = float(flight_raw)
|
||||
|
||||
# 没有飞行信息:只能退化为“先尝试上马,再尝试起飞”
|
||||
if f_signal is None:
|
||||
ok = self._ensure_mounted(state)
|
||||
if not ok:
|
||||
return False
|
||||
pyautogui.keyDown(str(takeoff_key))
|
||||
time.sleep(float(takeoff_hold_sec))
|
||||
pyautogui.keyUp(str(takeoff_key))
|
||||
return False
|
||||
|
||||
# 计算距离
|
||||
dist = math.sqrt((target_x - float(curr_x)) ** 2 + (target_y - float(curr_y)) ** 2)
|
||||
dismount_key = str(dismount_key).strip() if dismount_key else self.mount_key
|
||||
dismount_key = dismount_key or "x"
|
||||
|
||||
# --- 1. 上马阶段(兼容你的阈值写法:f_signal < 10) ---
|
||||
if f_signal < 10:
|
||||
# 退化:直接按 mount_key 一次并等待
|
||||
self.logger.info(">>> 飞行阶段检测:未上马,先按 %s", self.mount_key)
|
||||
pyautogui.press(self.mount_key)
|
||||
time.sleep(float(mount_wait_sec))
|
||||
return False
|
||||
|
||||
# --- 2. 起飞阶段(兼容你的阈值写法:100~200) ---
|
||||
if 100 < f_signal < 200:
|
||||
self.logger.info(">>> 起飞:按住 %s %.1f 秒", takeoff_key, float(takeoff_hold_sec))
|
||||
pyautogui.keyDown(str(takeoff_key))
|
||||
time.sleep(float(takeoff_hold_sec))
|
||||
pyautogui.keyUp(str(takeoff_key))
|
||||
return False
|
||||
|
||||
# --- 3. 巡航与降落判定(兼容你的阈值写法:>240) ---
|
||||
if f_signal > 240:
|
||||
if dist > float(arrival_threshold):
|
||||
# A. 始终按住 W 前进
|
||||
pyautogui.keyDown("w")
|
||||
|
||||
# B. 修正方向(使用与本模块一致的朝向计算)
|
||||
target_heading = self.get_target_heading_deg((float(curr_x), float(curr_y)), (float(target_x), float(target_y)))
|
||||
angle_diff = (target_heading - float(curr_facing) + 180) % 360 - 180
|
||||
abs_diff = abs(angle_diff)
|
||||
|
||||
# 在死区内:确保转向键松开,减少左右抖动
|
||||
if abs_diff <= float(turn_deadzone_deg):
|
||||
pyautogui.keyUp("a")
|
||||
pyautogui.keyUp("d")
|
||||
return False
|
||||
|
||||
# 防止“上一个修正刚结束,下一帧立刻反向再修正”造成摆头
|
||||
now = time.time()
|
||||
last_t = getattr(self, "_last_simple_flight_turn_time", 0.0)
|
||||
if now - last_t < 0.08:
|
||||
return False
|
||||
|
||||
key = "d" if angle_diff > 0 else "a"
|
||||
other_key = "a" if key == "d" else "d"
|
||||
pyautogui.keyUp(other_key)
|
||||
pyautogui.keyDown(key)
|
||||
|
||||
# 修正脉冲时长随角度误差变化,避免固定 0.05s 过冲/欠冲
|
||||
duration = self._turn_duration_from_angle(abs_diff)
|
||||
safe_duration = min(float(duration), 0.12)
|
||||
# 误差只略大于死区时,进一步缩短,减少接近目标时的来回摆
|
||||
if abs_diff < float(turn_deadzone_deg) * 1.8:
|
||||
safe_duration = min(safe_duration, 0.04)
|
||||
|
||||
time.sleep(safe_duration)
|
||||
pyautogui.keyUp(key)
|
||||
setattr(self, "_last_simple_flight_turn_time", now)
|
||||
return False
|
||||
|
||||
# C. 到达目标,执行降落
|
||||
pyautogui.keyUp("w")
|
||||
self.logger.info(">>> 到达目标,执行降落:按住 %s %.1f 秒", land_key, float(land_hold_sec))
|
||||
pyautogui.keyDown(str(land_key))
|
||||
time.sleep(float(land_hold_sec))
|
||||
pyautogui.keyUp(str(land_key))
|
||||
pyautogui.press(dismount_key)
|
||||
self.logger.info(">>> 降落完成:已按 %s", dismount_key)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def navigate_path(self, get_state, path, forward=True, arrival_threshold=None):
|
||||
"""
|
||||
按 path 依次走完所有点后返回。每次调用都必须传入 path。
|
||||
|
||||
Reference in New Issue
Block a user