Files
krpc-auto-landing/自动着陆.py
2026-01-30 18:50:52 +08:00

90 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from enum import Enum
import time
import krpc
from pid import PID
conn = krpc.connect(name='SpaceX Landing')
if not conn.space_center:
print("No active vessel found.")
exit()
# control = vessel.control
vessel = conn.space_center.active_vessel
celestial = vessel.orbit.body # 当前天体
# 创建 PID 控制器
# 外环:高度 -> 目标垂直速度(允许负值)
altitude_pid = PID(kp=0.3, ki=0.03, kd=0.05, integral_limit=2.0, alpha=0.8, output_limit=(-10.0, 10.0))
# 内环:垂直速度 -> 节流阀0~1
speed_pid = PID(kp=0.06, ki=0.05, kd=0.05, integral_limit=10.0, alpha=0.5, output_limit=(0.0, 1.0))
target_altitude = 30 # 目标高度,单位 m
# 状态机定义:高于 100m 为滑翔GLIDE100m 及以下为减速着陆LAND
class STATE(str, Enum):
GLIDE = "GLIDE"
LAND = "LAND"
current_state = STATE.GLIDE
last_time = time.monotonic()
loop_dt = 0.1
# 进入减速着陆时使用的目标垂直速度(保持原有行为)
target_vertical_speed = -3
try:
while True:
now = time.monotonic()
dt = now - last_time
last_time = now
flight = vessel.flight(vessel.orbit.body.reference_frame)
current_altitude = flight.surface_altitude
current_vertical_speed = flight.vertical_speed
# 计算转换距离
available_thrust = vessel.available_thrust # 可用推力
gav = celestial.surface_gravity # 重力加速度
twr = available_thrust / (vessel.mass * gav) # 推重比
if twr > 1.0:
transition_distance = (current_vertical_speed**2) / (2 * gav * (twr - 1)) # 米
else:
transition_distance = float('inf') # 无法减速,设为无穷大
# 状态判断:大于 200m 为滑翔(无需控制,油门 0否则为减速着陆使用现有内环 PID
if current_state == STATE.GLIDE: # 禁止反向切换
new_state = STATE.GLIDE if current_altitude > transition_distance else STATE.LAND
if new_state != current_state and new_state is not None:
print(f"状态切换: {current_state} -> {new_state}")
current_state = new_state
# 在状态切换时重置 PID避免积分风up
try:
altitude_pid.reset()
except Exception:
pass
try:
speed_pid.reset()
except Exception:
pass
if current_state == STATE.GLIDE:
# 滑翔:不做具体控制,油门设为 0
vessel.control.throttle = 0.0
print(f"当前高度: {current_altitude:.2f} m, 预计点火距离: {transition_distance:.2f} m, 状态: GLIDE, 油门: 0.00"," "*10, end='\r')
else:
# 内环:垂直速度误差 -> 节流阀
speed_error = target_vertical_speed - current_vertical_speed
throttle = speed_pid.update(speed_error, dt)
vessel.control.throttle = throttle
print(f"当前高度: {current_altitude:.2f} m, 预计点火距离: {transition_distance:.2f} m, 目标速: {target_vertical_speed:.2f} m/s, 速: {current_vertical_speed:.2f} m/s, 节流阀: {throttle:.2f}"," "*10, end='\r')
# 保持大致的控制周期
sleep_time = loop_dt - (time.monotonic() - now)
if sleep_time > 0:
time.sleep(sleep_time)
except KeyboardInterrupt:
vessel.control.throttle = 0.0
print("已停止控制,节流设为 0。")