diff --git a/data/KSP_data/log_book.xlsx b/data/KSP_data/log_book.xlsx index 1f24825..663bc21 100644 Binary files a/data/KSP_data/log_book.xlsx and b/data/KSP_data/log_book.xlsx differ diff --git a/src/KSP_tools/krpc_explore.py b/src/KSP_tools/krpc_explore.py index 1463e3f..465c63e 100644 --- a/src/KSP_tools/krpc_explore.py +++ b/src/KSP_tools/krpc_explore.py @@ -1,7 +1,9 @@ import time import krpc +import math +G_EARTH = 9.80665 def get_surface_speed(): conn = krpc.connect(name='Vessel speed') @@ -62,7 +64,31 @@ def vessel_available_thrust(): print('Vessel available thrust = %.1f kN' % (thrust / 1000)) time.sleep(1) -def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=50000, target_altitude=0.5, target_vspeed=-2.0, safety_margin=5.0, verbose=True): +def get_body_g(local_vessel): + try: + body = local_vessel.orbit.body + g = float(getattr(body, 'surface_gravity', G_EARTH)) + if g > 0: + return g + except Exception: + pass + try: + g = float(getattr(local_vessel.flight(), 'surface_gravity', G_EARTH)) + if g > 0: + return g + except Exception: + pass + return G_EARTH + +def auto_land_predictive( + bottom_clearance_margin=12, + thrust_discount_wait=0.85, + host='localhost', + port=50000, + target_altitude=1.0, + target_vspeed=-1.0, + safety_margin=3.0, + verbose=True): """预测式自动着陆(suicide burn 思路)。 关键点: @@ -83,14 +109,46 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 若需要更精细,可改成取 surface_velocity 向量的径向分量/或用垂直速度替代。 bottom_clearance_margin = 12 # m:按载具尺寸调整(越大越早开始末端减速) - """ - try: - import math - except Exception: - math = None - if krpc is None: - raise RuntimeError('krpc 未安装') + 参数说明: + bottom_clearance_margin (float): + - 单位:米(m) + - 说明:从雷达(bedrock_altitude)读取的高度中减去该几何余量以近似载具最低点到地面的距离。 + 用于避免脚本在实际着陆时因底部结构接触地面而过早判断已着陆。值越大会更早开始末端减速。 + - 典型值:10~25,根据载具底部高度调整。 + + thrust_discount_wait (float): + - 单位:无(比例系数) + - 说明:在 WAIT 阶段估算可用推力时对 vessel.available_thrust 的折减因子。 + 会用 avail_thrust * thrust_discount_wait 来保守估算用于决定何时点火(补偿推力建立/响应延迟)。 + - 取值范围:0.0~1.0;越小越保守(更早点火)。默认 0.85。 + + host (str) / port (int): + - 说明:连接 kRPC 服务的地址和 RPC 端口(用于 krpc.connect)。一般本地运行时用 'localhost' 和 50000。 + + target_altitude (float): + - 单位:米(m) + - 说明:目标的“触地点高度基准”,脚本在计算剩余高度时会把 radar_alt - bottom_clearance_margin 与此值比较。 + 通常设为想要在接触地面时的质心高度(或 0/地面高度上方的偏移)。 + - 典型值:0~5(例如 3 表示目标在底部余量之上 3m 处被视为触地)。 + + target_vspeed (float): + - 单位:m/s(竖直速度,负值表示向下) + - 说明:期望的着陆竖直速度(向下为负)。脚本会把该值取绝对值作为目标的向下速度(vf_down)。 + 在计算刹车距离和 PID/前馈控制里以该目标速度为参考。 + - 典型值:-0.5 ~ -1.5(更接近 0 的值更“柔和”但更难实现)。默认为 -1.0。 + + safety_margin (float): + - 单位:米(m) + - 说明:在刹车距离上再加的安全余量,用于补偿模型误差(如空气阻力、推力随时间变化等)。 + - 典型值:几米(例如 3~10)。默认 5. + + verbose (bool): + - 说明:是否打印并记录运行时信息到返回的 status['logs'],用于调试或观察倒计时/燃烧过程。 + + 返回值: + 返回一个 dict 格式的状态描述,包含 'result' 字段('failed' / 'landed' / 'touchdown_pending')和 'logs'(运行时消息列表)。 + """ conn = krpc.connect(name='auto_land_predictive', address=host, rpc_port=port) sc = conn.space_center @@ -102,7 +160,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 status = {'result': 'failed', 'logs': []} # WAIT 阶段按折减推力估算刹车距离(提前点火,补偿点火/推力建立延迟) - thrust_discount_wait = 0.85 + # 低空/接地参数(用于“最后几米慢下来”) touchdown_vspeed_tol = 0.6 # m/s:认为“软着陆”的竖直速度容差 @@ -112,22 +170,6 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 # 由于 surface_altitude 近似是“载具质心高度”,末端会偏乐观。 # 用 bedrock_altitude(雷达高度)并减去一个底部几何余量,近似得到“最低点离地高度”。 - def _get_g(local_vessel): - try: - body = local_vessel.orbit.body - g = float(getattr(body, 'surface_gravity', 9.81)) - if g > 0: - return g - except Exception: - pass - try: - g = float(getattr(local_vessel.flight(), 'surface_gravity', 9.81)) - if g > 0: - return g - except Exception: - pass - return 9.81 - # 使用 body 的 reference_frame 读取 surface speed / vertical_speed(对应 get_surface_speed 思路) try: surface_frame = vessel.orbit.body.reference_frame @@ -152,19 +194,13 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 v_speed = float(getattr(flight, 'vertical_speed', 0.0)) mass = float(getattr(vessel, 'mass', 0.0)) avail_thrust = float(getattr(vessel, 'available_thrust', 0.0)) - g_local = _get_g(vessel) - try: - situation_name = str(getattr(getattr(vessel, 'situation', None), 'name', '')) - except Exception: - situation_name = '' + g_local = get_body_g(vessel) + situation_name = str(getattr(getattr(vessel, 'situation', None), 'name', '')) return alt, radar_alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name try: # 初始确保不点火 - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 # 倒计时/等待点火 last_log_t = 0.0 @@ -213,18 +249,9 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 break # 确保仍在滑行 - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 time.sleep(0.01) - # # 点火 - # try: - # vessel.control.activate_next_stage() - # except Exception: - # pass - # 燃烧闭环:根据 remaining_alt 反推需要的减速度 -> 油门 while True: alt, radar_alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name = _read_state() @@ -239,10 +266,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 # 因此要求:LANDED 且竖直速度足够小才结束 is_landed = str(situation_name).strip().lower() == 'landed' if is_landed and v_down <= (vf_down + float(touchdown_vspeed_tol)): - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 status['result'] = 'landed' status['logs'].append('检测到 vessel.situation=LANDED 且竖直速度满足软着陆阈值,着陆完成') if verbose: @@ -251,10 +275,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 # 兜底:极低高度 + 速度足够小(防止 situation 迟迟不切换导致卡死) if remaining_alt <= max(0.2, float(target_altitude)) and v_down <= (vf_down + float(touchdown_vspeed_tol)): - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 status['result'] = 'touchdown_pending' status['logs'].append('达到高度/速度阈值,但 vessel.situation 仍未变为 LANDED') if verbose: @@ -295,10 +316,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 if is_landed and v_down > (vf_down + float(touchdown_vspeed_tol)): throttle = max(throttle, 0.8) - try: - vessel.control.throttle = throttle - except Exception: - pass + vessel.control.throttle = throttle if verbose: msg = (