Files
krpc-auto-landing/测试文件/动态着陆v2.py
2026-01-30 18:50:52 +08:00

311 lines
10 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.
import time
import krpc
import math
# ================= 配置参数 =================
TARGET_LANDING_VELOCITY = -2.0 # 目标着陆速度 (m/s)
SAFETY_MARGIN = 80.0 # 安全余量 (m)
MIN_TWR_FOR_BURN = 1.1 # 开始减速的最小TWR
# PID 控制器参数
SPEED_KP = 0.15
SPEED_KI = 0.05
SPEED_KD = 0.1
INTEGRAL_LIMIT = 0.5
# 节流阀滤波
ALPHA = 0.3 # 平滑系数
DT = 0.1 # 控制周期
# 预测参数
PREDICTION_STEPS = 50 # 预测步数
# ===========================================
conn = krpc.connect(name='Dynamic Landing V2')
if not conn.space_center:
print("No active vessel found.")
exit()
vessel = conn.space_center.active_vessel
class PID:
def __init__(self, kp, ki, kd, integral_limit=1.0):
self.kp, self.ki, self.kd = kp, ki, kd
self.prev_error = 0
self.integral = 0
self.integral_limit = integral_limit
def update(self, error, dt):
self.integral += error * dt
self.integral = max(-self.integral_limit, min(self.integral_limit, self.integral))
derivative = (error - self.prev_error) / dt
self.prev_error = error
return (self.kp * error) + (self.ki * self.integral) + (self.kd * derivative)
class AdvancedRocketPerformance:
"""高级火箭性能计算器 - 考虑燃料消耗和TWR变化"""
def __init__(self, vessel):
self.vessel = vessel
self.body = vessel.orbit.body
self.g = self.body.surface_gravity # 重力加速度 (m/s²)
# 获取发动机参数
self.engines = vessel.parts.engines
self.max_thrust = sum(e.max_thrust for e in self.engines if e.active)
# 计算燃料消耗率 (kg/s) - 假设所有发动机都激活
self.fuel_flow_rate = 0.0
for engine in self.engines:
if engine.active:
# 获取发动机的比冲和推力
# fuel_flow = thrust / (Isp * g0)
# g0 = 9.80665 m/s²
isp = engine.vacuum_specific_impulse
self.fuel_flow_rate += engine.max_thrust / (isp * 9.80665)
def get_mass(self):
"""获取当前质量 (kg)"""
return self.vessel.mass
def get_fuel_mass(self):
"""获取燃料质量 (kg)"""
fuel_mass = 0.0
for part in self.vessel.parts.all:
for resource in part.resources:
if resource.name in ['LiquidFuel', 'Oxidizer', 'MonoPropellant']:
fuel_mass += resource.amount * resource.density
return fuel_mass
def get_dry_mass(self):
"""获取干重 (kg)"""
return self.get_mass() - self.get_fuel_mass()
def get_twr(self, mass=None):
"""
计算推重比 (Thrust-to-Weight Ratio)
Args:
mass: 可选指定质量计算TWR。如果为None使用当前质量
"""
if mass is None:
mass = self.get_mass()
if mass == 0:
return 0.0
return self.max_thrust / (mass * self.g)
def get_max_deceleration(self, mass=None):
"""
计算最大减速度 (m/s²)
Args:
mass: 可选指定质量计算减速度。如果为None使用当前质量
"""
twr = self.get_twr(mass)
# 有效减速度 = 推重比 * g - g = g * (TWR - 1)
return self.g * (twr - 1) if twr > 1 else 0.0
def predict_mass_after_burn(self, burn_time, throttle=1.0):
"""
预测燃烧指定时间后的质量
Args:
burn_time: 燃烧时间 (s)
throttle: 节流阀 (0-1)
Returns:
预测的质量 (kg)
"""
fuel_consumed = self.fuel_flow_rate * throttle * burn_time
current_fuel = self.get_fuel_mass()
remaining_fuel = max(0, current_fuel - fuel_consumed)
return self.get_dry_mass() + remaining_fuel
def calculate_deceleration_distance_advanced(self, current_velocity, target_velocity):
"""
计算从当前速度减速到目标速度需要的距离考虑TWR变化
使用数值积分方法考虑燃料消耗导致的TWR增加
Args:
current_velocity: 当前垂直速度 (m/s, 负值表示下降)
target_velocity: 目标速度 (m/s, 负值表示下降)
Returns:
需要的减速距离 (m)
"""
# 检查当前是否能够减速
current_twr = self.get_twr()
if current_twr <= MIN_TWR_FOR_BURN:
return float('inf') # 无法减速
# 使用数值积分计算减速距离
# 将减速过程分成多个小段每段使用该段的平均TWR
total_distance = 0.0
v = current_velocity
dt = 0.1 # 时间步长 (s)
while v < target_velocity:
# 预测当前速度下燃烧dt时间后的质量
# 假设平均节流阀为0.8(保守估计)
predicted_mass = self.predict_mass_after_burn(dt, throttle=0.8)
# 计算该段的平均减速度
avg_decel = self.get_max_deceleration(predicted_mass)
if avg_decel <= 0:
return float('inf') # 无法继续减速
# 计算该段的速度变化和距离
dv = avg_decel * dt
new_v = v + dv
# 使用平均速度计算距离
avg_v = (v + new_v) / 2
distance = abs(avg_v * dt)
total_distance += distance
v = new_v
# 防止无限循环
if total_distance > 100000: # 超过100km认为不合理
return float('inf')
return total_distance
def should_start_deceleration(self, altitude, current_velocity, target_velocity):
"""
判断是否应该开始减速(高级版)
Args:
altitude: 当前高度 (m)
current_velocity: 当前垂直速度 (m/s)
target_velocity: 目标速度 (m/s)
Returns:
(should_burn, required_distance, trigger_altitude, current_twr)
"""
# 计算需要的减速距离考虑TWR变化
required_distance = self.calculate_deceleration_distance_advanced(
current_velocity, target_velocity
)
# 添加安全余量
trigger_altitude = required_distance + SAFETY_MARGIN
# 检查TWR是否足够
current_twr = self.get_twr()
should_burn = (altitude <= trigger_altitude) and (current_twr >= MIN_TWR_FOR_BURN)
return should_burn, required_distance, trigger_altitude, current_twr
# 初始化控制器
speed_pid = PID(SPEED_KP, SPEED_KI, SPEED_KD, INTEGRAL_LIMIT)
performance = AdvancedRocketPerformance(vessel)
# 节流阀平滑处理
last_throttle = 0.0
# 姿态控制设置
vessel.auto_pilot.engage()
vessel.auto_pilot.reference_frame = vessel.surface_velocity_reference_frame
vessel.auto_pilot.target_direction = (0, -1, 0) # 始终指向速度反方向
print("高级动态着陆程序启动...")
print(f"目标着陆速度: {TARGET_LANDING_VELOCITY} m/s")
print(f"安全余量: {SAFETY_MARGIN} m")
print(f"最大推力: {performance.max_thrust:.0f} N")
print(f"燃料消耗率: {performance.fuel_flow_rate:.2f} kg/s")
# 自检
vessel.control.throttle = 0.99
time.sleep(0.1)
vessel.control.throttle = 0
burn_started = False
last_status = ""
while True:
# 1. 获取飞行数据
flight = vessel.flight(vessel.orbit.body.reference_frame)
alt = max(0, flight.surface_altitude - 9.50) # 考虑雷达高度计偏移
vel = flight.vertical_speed
# 2. 获取火箭性能
mass = performance.get_mass()
fuel_mass = performance.get_fuel_mass()
dry_mass = performance.get_dry_mass()
thrust = performance.max_thrust
twr = performance.get_twr()
max_decel = performance.get_max_deceleration()
# 3. 判断是否应该开始减速
should_burn, required_dist, trigger_alt, current_twr = performance.should_start_deceleration(
alt, vel, TARGET_LANDING_VELOCITY
)
# 4. 姿态控制逻辑
if alt < 30 or abs(vel) < 0.5:
# 离地很近或速度很慢时,强制垂直向上
vessel.auto_pilot.reference_frame = vessel.surface_reference_frame
vessel.auto_pilot.target_direction = (1, 0, 0) # 向天
else:
# 正常减速阶段,锁定速度反方向
vessel.auto_pilot.reference_frame = vessel.surface_velocity_reference_frame
vessel.auto_pilot.target_direction = (0, -1, 0)
# 5. 刹车控制
if alt < 10000 and thrust > 0 and not vessel.control.brakes:
vessel.control.brakes = True
if alt < 30 and vessel.control.brakes:
vessel.control.brakes = False
# 6. 自动部署脚架
if alt < 500:
vessel.control.gear = True
# 7. 动态速度规划
if should_burn:
burn_started = True
target_vel = TARGET_LANDING_VELOCITY
elif not burn_started:
# 还没开始减速,使用自由落体或微调
target_vel = -10000.0 # 允许快速下降
else:
# 已经开始减速,保持目标着陆速度
target_vel = TARGET_LANDING_VELOCITY
# 8. 触地检测
if alt < 1.0 and abs(vel) < 0.5:
vessel.control.throttle = 0
vessel.control.sas = True
print("已着陆!")
break
# 9. PID 计算
error = target_vel - vel
raw_throttle = speed_pid.update(error, DT)
# 10. 节流阀滤波
throttle = (ALPHA * raw_throttle) + ((1.0 - ALPHA) * last_throttle)
throttle = max(0.0, min(1.0, throttle))
last_throttle = throttle
# 11. 执行控制
vessel.control.throttle = throttle
# 12. 信息输出
if burn_started:
status = f"减速中 | TWR: {twr:.2f} | 燃料: {fuel_mass:.0f}kg"
else:
status = f"自由落体 | 触发高度: {trigger_alt:.0f}m"
print(f"高度: {alt:6.1f}m | 速度: {vel:6.1f}m/s | 目标速: {target_vel:6.1f}m/s | "
f"节流阀: {throttle:.2f} | 质量: {mass:.0f}kg | 减速距离: {required_dist:6.1f}m | "
f"{status}")
time.sleep(DT)