update
This commit is contained in:
@@ -62,7 +62,7 @@ def vessel_available_thrust():
|
|||||||
print('Vessel available thrust = %.1f kN' % (thrust / 1000))
|
print('Vessel available thrust = %.1f kN' % (thrust / 1000))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, target_vspeed=-2.0, safety_margin=5.0, verbose=True):
|
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):
|
||||||
"""预测式自动着陆(suicide burn 思路)。
|
"""预测式自动着陆(suicide burn 思路)。
|
||||||
|
|
||||||
关键点:
|
关键点:
|
||||||
@@ -81,6 +81,8 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
|
|
||||||
注:这里 v 取“相对地表速度”的标量(surface speed),更贴近你提到的 get_surface_speed。
|
注:这里 v 取“相对地表速度”的标量(surface speed),更贴近你提到的 get_surface_speed。
|
||||||
若需要更精细,可改成取 surface_velocity 向量的径向分量/或用垂直速度替代。
|
若需要更精细,可改成取 surface_velocity 向量的径向分量/或用垂直速度替代。
|
||||||
|
|
||||||
|
bottom_clearance_margin = 12 # m:按载具尺寸调整(越大越早开始末端减速)
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
import math
|
import math
|
||||||
@@ -100,13 +102,15 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
status = {'result': 'failed', 'logs': []}
|
status = {'result': 'failed', 'logs': []}
|
||||||
|
|
||||||
# WAIT 阶段按折减推力估算刹车距离(提前点火,补偿点火/推力建立延迟)
|
# WAIT 阶段按折减推力估算刹车距离(提前点火,补偿点火/推力建立延迟)
|
||||||
thrust_discount_wait = 0.9
|
thrust_discount_wait = 0.85
|
||||||
|
|
||||||
# 低空/接地参数(用于“最后几米慢下来”)
|
# 低空/接地参数(用于“最后几米慢下来”)
|
||||||
touchdown_vspeed_tol = 0.6 # m/s:认为“软着陆”的竖直速度容差
|
touchdown_vspeed_tol = 0.6 # m/s:认为“软着陆”的竖直速度容差
|
||||||
low_altitude_pid_switch = 10.0 # m:低于该高度切换到竖直速度控制
|
low_altitude_pid_switch = 10.0 # m:低于该高度切换到竖直速度控制
|
||||||
vspeed_p_gain = 1.2 # 比例增益:越大越积极(建议 0.6~2.0)
|
vspeed_p_gain = 1.2 # 比例增益:越大越积极(建议 0.6~2.0)
|
||||||
low_altitude_ff_gain = 0.3 # 低空前馈增益:按“需要的减速距离/剩余距离”做额外加速度
|
low_altitude_ff_gain = 0.3 # 低空前馈增益:按“需要的减速距离/剩余距离”做额外加速度
|
||||||
|
# 由于 surface_altitude 近似是“载具质心高度”,末端会偏乐观。
|
||||||
|
# 用 bedrock_altitude(雷达高度)并减去一个底部几何余量,近似得到“最低点离地高度”。
|
||||||
|
|
||||||
def _get_g(local_vessel):
|
def _get_g(local_vessel):
|
||||||
try:
|
try:
|
||||||
@@ -140,9 +144,10 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
ap = None
|
ap = None
|
||||||
|
|
||||||
def _read_state():
|
def _read_state():
|
||||||
"""从接口读取状态:alt, surface_speed(标量), vertical_speed, mass, available_thrust, g, situation_name"""
|
"""从接口读取状态:alt(surface_altitude), radar_alt(bedrock_altitude), surface_speed, vertical_speed, mass, available_thrust, g, situation_name"""
|
||||||
flight = vessel.flight(surface_frame) if surface_frame is not None else vessel.flight()
|
flight = vessel.flight(surface_frame) if surface_frame is not None else vessel.flight()
|
||||||
alt = float(getattr(flight, 'surface_altitude', 0.0))
|
alt = float(getattr(flight, 'surface_altitude', 0.0))
|
||||||
|
radar_alt = float(getattr(flight, 'bedrock_altitude', alt))
|
||||||
srf_speed = float(getattr(flight, 'speed', 0.0))
|
srf_speed = float(getattr(flight, 'speed', 0.0))
|
||||||
v_speed = float(getattr(flight, 'vertical_speed', 0.0))
|
v_speed = float(getattr(flight, 'vertical_speed', 0.0))
|
||||||
mass = float(getattr(vessel, 'mass', 0.0))
|
mass = float(getattr(vessel, 'mass', 0.0))
|
||||||
@@ -152,7 +157,7 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
situation_name = str(getattr(getattr(vessel, 'situation', None), 'name', ''))
|
situation_name = str(getattr(getattr(vessel, 'situation', None), 'name', ''))
|
||||||
except Exception:
|
except Exception:
|
||||||
situation_name = ''
|
situation_name = ''
|
||||||
return alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name
|
return alt, radar_alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 初始确保不点火
|
# 初始确保不点火
|
||||||
@@ -164,8 +169,10 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
# 倒计时/等待点火
|
# 倒计时/等待点火
|
||||||
last_log_t = 0.0
|
last_log_t = 0.0
|
||||||
while True:
|
while True:
|
||||||
alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name = _read_state()
|
alt, radar_alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name = _read_state()
|
||||||
remaining_alt = max(0.0, alt - float(target_altitude))
|
# 用“雷达高度-底部余量”近似最低点离地高度
|
||||||
|
alt_eff = max(0.0, float(radar_alt) - float(bottom_clearance_margin))
|
||||||
|
remaining_alt = max(0.0, alt_eff - float(target_altitude))
|
||||||
|
|
||||||
# v:使用 surface speed(标量)作为“需要刹掉的速度”
|
# v:使用 surface speed(标量)作为“需要刹掉的速度”
|
||||||
v = max(0.0, float(srf_speed))
|
v = max(0.0, float(srf_speed))
|
||||||
@@ -192,7 +199,7 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
if verbose and now - last_log_t > 0.2:
|
if verbose and now - last_log_t > 0.2:
|
||||||
last_log_t = now
|
last_log_t = now
|
||||||
msg = (
|
msg = (
|
||||||
f'WAIT alt={alt:.1f} rem={remaining_alt:.1f} '
|
f'WAIT alt={alt:.1f} radar={radar_alt:.1f} alt_eff={alt_eff:.1f} rem={remaining_alt:.1f} '
|
||||||
f'srf_speed={srf_speed:.2f} vs={v_speed:.2f} '
|
f'srf_speed={srf_speed:.2f} vs={v_speed:.2f} '
|
||||||
f'a_max_up={a_max_up:.2f} braking={braking_dist:.1f} thr_disc={thrust_discount_wait:.2f} '
|
f'a_max_up={a_max_up:.2f} braking={braking_dist:.1f} thr_disc={thrust_discount_wait:.2f} '
|
||||||
f'countdown={(countdown if countdown is not None else float("nan")):.2f}'
|
f'countdown={(countdown if countdown is not None else float("nan")):.2f}'
|
||||||
@@ -212,16 +219,17 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
pass
|
pass
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
# 点火
|
# # 点火
|
||||||
try:
|
# try:
|
||||||
vessel.control.activate_next_stage()
|
# vessel.control.activate_next_stage()
|
||||||
except Exception:
|
# except Exception:
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
# 燃烧闭环:根据 remaining_alt 反推需要的减速度 -> 油门
|
# 燃烧闭环:根据 remaining_alt 反推需要的减速度 -> 油门
|
||||||
while True:
|
while True:
|
||||||
alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name = _read_state()
|
alt, radar_alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name = _read_state()
|
||||||
remaining_alt = max(0.0, alt - float(target_altitude))
|
alt_eff = max(0.0, float(radar_alt) - float(bottom_clearance_margin))
|
||||||
|
remaining_alt = max(0.0, alt_eff - float(target_altitude))
|
||||||
|
|
||||||
# BURN 阶段以“竖直下降速度”为控制对象:下降为负,统一转成向下为正的标量 v_down
|
# BURN 阶段以“竖直下降速度”为控制对象:下降为负,统一转成向下为正的标量 v_down
|
||||||
v_down = max(0.0, -float(v_speed))
|
v_down = max(0.0, -float(v_speed))
|
||||||
@@ -254,7 +262,7 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 低空策略:切换到“竖直速度跟踪”以确保最后几米把速度压到目标值
|
# 低空策略:切换到“竖直速度跟踪”以确保最后几米把速度压到目标值
|
||||||
if alt <= float(low_altitude_pid_switch):
|
if alt_eff <= float(low_altitude_pid_switch):
|
||||||
# 低空:比例 + 前馈(用当前速度估算“需要多少距离才能刹到目标速度”)
|
# 低空:比例 + 前馈(用当前速度估算“需要多少距离才能刹到目标速度”)
|
||||||
# a_p:把竖直速度拉向目标
|
# a_p:把竖直速度拉向目标
|
||||||
a_p = float(vspeed_p_gain) * max(0.0, (v_down - vf_down))
|
a_p = float(vspeed_p_gain) * max(0.0, (v_down - vf_down))
|
||||||
@@ -280,7 +288,7 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
throttle = max(0.0, min(1.0, float(throttle)))
|
throttle = max(0.0, min(1.0, float(throttle)))
|
||||||
|
|
||||||
# 低空兜底:高度<5m 且仍很快 -> 满油门
|
# 低空兜底:高度<5m 且仍很快 -> 满油门
|
||||||
if alt < 5.0 and v_down > 10.0:
|
if alt_eff < 5.0 and v_down > 10.0:
|
||||||
throttle = 1.0
|
throttle = 1.0
|
||||||
|
|
||||||
# 若已经触发 LANDED 但竖直速度仍偏大,避免油门过低导致“硬砸/反弹”
|
# 若已经触发 LANDED 但竖直速度仍偏大,避免油门过低导致“硬砸/反弹”
|
||||||
@@ -294,7 +302,7 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
msg = (
|
msg = (
|
||||||
f'BURN alt={alt:.1f} rem={remaining_alt:.1f} '
|
f'BURN alt={alt:.1f} radar={radar_alt:.1f} alt_eff={alt_eff:.1f} rem={remaining_alt:.1f} '
|
||||||
f'srf_speed={srf_speed:.2f} vs={v_speed:.2f} '
|
f'srf_speed={srf_speed:.2f} vs={v_speed:.2f} '
|
||||||
f'v_down={v_down:.2f} vf_down={vf_down:.2f} '
|
f'v_down={v_down:.2f} vf_down={vf_down:.2f} '
|
||||||
f'a_req_up={a_req_up:.2f} throttle={throttle:.2f} '
|
f'a_req_up={a_req_up:.2f} throttle={throttle:.2f} '
|
||||||
@@ -322,6 +330,6 @@ def auto_land_predictive(host='localhost', port=50000, target_altitude=0.5, targ
|
|||||||
return status
|
return status
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
xxx = auto_land_predictive()
|
xxx = auto_land_predictive(bottom_clearance_margin=20)
|
||||||
print(xxx)
|
print(xxx)
|
||||||
print('done')
|
print('done')
|
||||||
Reference in New Issue
Block a user