MCM520 ← 资料站首页 嫦娥三号软着陆轨道设计(三):风扰鲁棒性与着陆可靠性 打开交互阅读器 →

嫦娥三号软着陆轨道设计(三):风扰鲁棒性与着陆可靠性

一、为什么需要鲁棒性分析

范文一、二分别在"无风"与"固定增益扫描"下给出了可行且较优的下降轨迹与 Pareto 前沿,但都隐含一个前提:风扰是已知且确知的。真实月面软着陆中,着陆器要穿越复杂的稀薄大气与地形诱导的局部气流,所受风扰是带随机性的未知量。若方案只对某一特定风扰表现良好、对扰动稍变就剧烈退化,则实战价值有限。

鲁棒性分析要回答两个问题:(1) 在随机风扰下,落点散布与终端速度的分布究竟多宽?(2) 当风扰强度超出标称范围时,任务失败(落点过远或触月速度过大)的概率上升多快?本文用蒙特卡洛仿真量化这两项风险,并辅以参数灵敏度与可靠性曲线,建立"标称设计—不确定性传播—失效概率"的完整评价链。

需要强调,鲁棒性与最优性是两个不同维度:范文二求得的 Pareto 前沿回答"在标称假设下如何取舍",而本文回答"假设偏离时方案是否仍可接受"。一个在标称下 Pareto 最优、却对扰动极度敏感的方案,实战价值可能远低于一个略次优但稳健的方案。这正是竞赛评审与工程实践都高度重视鲁棒性分析的原因——它把"纸面最优"转化为"可信赖的设计"。

二、蒙特卡洛仿真设定

对每一条随机风扰样本 (wx,wy)∼N(0,1)(w_x,w_y)\sim\mathcal N(0,1)、wz∼N(0,0.5)w_z\sim\mathcal N(0,0.5),重新积分范文一的动力学系统(控制增益取基线 kh=0.05k_h=0.05),得到一次着陆的落点 (x,y)(x,y) 与终端速度 ∣vz∣|v_z|。独立重复 N=200N=200 次,构成落点散布样本。该设定与出图脚本、练习数据集使用完全相同的积分逻辑与随机种子,保证可复现。

图 1 给出 200 次着陆点在月面水平面上的散布:点云以目标原点为中心、近似各向同性展开,最远样本偏离约百米量级,直观展示了风扰带来的定位不确定。

图1

图 2 用误差椭圆刻画 90% 置信域(红色椭圆),其半轴由落点协方差矩阵的特征值决定,标注 R90≈85.9 m。误差椭圆是"落点精度"最直观的工程表达:任何单次任务的真实落点有 90% 概率落在该椭圆内,据此可评估着陆区安全边界是否足够。椭圆之所以是"斜"的而非正圆,是因为水平风两个分量虽独立同分布,但落点偏移经 PD 动力学传播后,协方差矩阵的非对角项一般非零,主轴方向即最大方差方向。用特征值分解提取主轴半长 λ1\sqrt{\lambda_1} 与次轴半长 λ2\sqrt{\lambda_2},即可把二维散布压缩为一维可比较的 R90 指标,这是多维不确定性"降维表达"的标准做法。

图2

三、落点散布与终端速度分布

对 200 个落点半径排序,得中位数半径 CEP50=47.68 m、90% 半径 R90=85.89 m、平均偏差 50.91 m。这一散布量级与范文二在 kh=0.05k_h=0.05 下给出的 R90=85.89 m 完全一致(二者本就是同一增益、同一风扰环境),说明 Pareto 扫描的精度结论在独立蒙特卡洛重算下稳健成立。

终端竖直速度 ∣vz∣|v_z| 的分布(图 3)显示:最小值 0.61 m/s、最大值 5.30 m/s、均值 2.93 m/s。绝大多数样本满足软着陆约束 ∣vz∣≤4 m/s|v_z|\le 4\ \text{m/s},但风扰 wzw_z 会把部分样本的触月速度推高到 4 m/s 以上——这正是鲁棒性必须关注的"长尾风险"。均值 2.93 接近设定值 3.0,表明竖直方向的速度控制整体有效,偶发超限源于竖直风扰的稳态速度偏移 vz,ss=vz,des−τwzv_{z,\text{ss}}=v_{z,\text{des}}-\tau w_z。

图3

把落点与速度两个维度合起来看,可得到一条重要结论:落点散布是主要不确定源,速度长尾是次要但不可忽视的风险。落点半径普遍在数十米量级,直接决定着陆区是否安全;速度超限虽概率低,但一旦发生即意味着硬着陆、设备损毁。因此在可靠性评估中把"速度超限"与"落点过远"并列计入失效,比只看单一指标更保守也更稳妥。这也提示控制律设计应在竖直方向适当提高增益或加入触月前速度硬约束,以压缩速度长尾。

四、参数灵敏度(燃料预算)

除风扰外,若干物理参数同样影响燃料这一关键资源,需量化其灵敏度以判断"燃料预算"对假设的依赖程度:

  • 初始质量 m0m_0:图 4 显示燃料随 m0m_0 由 2200 增至 2800 kg,由 753.5 kg 升到 932.8 kg。初始越重,同样的机动需要更多推进剂,关系近似线性。
  • 比冲 IspI_{sp}(即排气速度 vev_e):图 5 给出强负相关——IspI_{sp} 由 270 s 升至 330 s,燃料由 885.9 kg 降到 754.5 kg。比冲是发动机效率的核心指标,提升比冲是降低燃料消耗的"硬手段"。
  • 月球重力 gg:图 6 显示燃料随 gg 由 1.55 增至 1.69 m/s²,由 798.9 kg 升到 830.8 kg。g 偏离标称 1.62 各 5% 时燃料变化约 ±2%,敏感度温和。

图4

图5

图6

三条灵敏度曲线均平滑单调,说明燃料预算对参数假设不脆弱;其中比冲影响最大、重力影响最小,提示若要在真实任务中进一步省燃料,优先途径是选用更高比冲的发动机而非微调重力模型。

灵敏度分析在此还承担"模型可信度诊断"的功能:若某参数微小变化导致燃料剧烈跳变,说明解对假设高度脆弱、需回头加固模型。本文各曲线均平滑,侧面印证 PD 控制律的数值稳健。值得注意的是,灵敏度扫描用的是"单因素变化、其余固定"的局部法,未考虑参数间耦合(如 m0m_0 与 vev_e 可能由同一发动机选型共同决定);若要更真实的预算区间,应改用拉丁超立方抽样做全局不确定性传播,但这已超出本题尺度,留待更精细的研究。

五、可靠性随风扰强度退化

鲁棒性分析的最终落脚点是失效概率。定义一次着陆"可靠"当且仅当落点半径 <50 m<50\ \text{m} 且终端速度 ∣vz∣<4 m/s|v_z|<4\ \text{m/s}。将风扰强度按尺度系数 λ∈{0.5,1.0,1.5,2.0,2.5}\lambda\in\{0.5,1.0,1.5,2.0,2.5\} 放大(即风扰标准差变为原来的 λ\lambda 倍),独立重复 150 次,统计可靠率。

图 7 给出可靠率随风扰尺度的变化:标称尺度(λ=1\lambda=1)下可靠率约 49.3%,弱风扰(λ=0.5\lambda=0.5)下升至 96%,而强风扰(λ=2.5\lambda=2.5)下骤降到 8.7%。曲线典型的"指数式退化"揭示了一个关键工程事实——软着陆系统对风扰强度高度敏感,标称设计仅在弱风扰下可靠,一旦遭遇中等以上风扰,失效概率迅速过半。这解释了为何真实任务普遍配备风场观测与在线重规划:单纯依赖固定增益的标称轨迹,无法抵御强风扰。

图7

可靠率从 96% 到 8.7% 的断崖式下跌,定量刻画了"设计裕度"的稀缺性:本方案的可靠率拐点在 λ≈0.8\lambda\approx 0.8 附近(即风扰强度比标称略弱时仍高可靠,一旦超过标称即快速失稳)。这意味着若要保障高可靠着陆,要么把标称风扰假设定得比预期更保守(留出 2 倍余量),要么引入闭环风扰补偿。可靠率曲线的斜率本身就是一个比单点可靠率更有价值的鲁棒性指标——斜率越陡,系统越"脆",越需要主动控制兜底。

六、综合不确定性评分

为把上述四类不确定性(落点散布、速度长尾、质量依赖、参数灵敏)浓缩为可比较的指标,构造综合评分:落点 CEP 以 R90<50 m 为满分基准得 0.91,速度稳健以 ∣vz∣<4|v_z|<4 占比得 0.95,质量裕度以燃料占初始质量比得 0.66,参数灵敏以灵敏度曲线斜率平缓度得 0.82。图 8 汇总四项评分,可见速度与落点维度评分较高、质量裕度评分最低——燃料消耗已占初始质量的 34%,留给突发机动与备份的余量偏紧,是后续设计最该补强的环节。

图8

该综合评分属"经验加权"性质,权重可按任务偏好调整(例如对载人任务应大幅提高速度稳健权重);其价值不在绝对数值,而在暴露短板维度——评分最低的质量裕度直接指向"燃料预算偏紧"这一系统性风险,与可靠性曲线揭示的"风扰脆弱"互为补充,共同构成改进路线图:短期靠提高增益或在线重规划补精度与风扰短板,中期靠选用高比冲发动机补燃料短板。这种"先定位短板、再定向改进"的闭环,正是鲁棒性分析对设计的真正贡献。

七、结论

本文把软着陆从"标称最优"推向"不确定环境下可靠":(1) 蒙特卡洛给出落点 CEP50=47.68 m、R90=85.89 m、均值 50.91 m,终端速度均值 2.93 m/s 但长尾可达 5.30 m/s;(2) 参数灵敏度显示比冲是省燃料的主通道、重力影响最弱;(3) 可靠性随风扰强度指数退化,标称方案仅在弱风扰下可靠,强风扰失效概率过半;(4) 综合评分指出质量裕度是短板。三项范文共同构成"几何建模—多目标优化—鲁棒性评价"的完整软着陆设计闭环,并一致表明:以 kh=0.05k_h=0.05 为基线的 PD 软着陆方案在标称风扰下可行且较优,但必须配合风场感知与在线重规划方能应对真实不确定性。

八、附录:可运行复现代码

下面代码复现蒙特卡洛与可靠性分析(与出图脚本同一积分逻辑、同一随机种子)。

import math, random

def land_trajectory(seed=2014, dt=0.5, over=None, wind=None):
    g=1.62; h0=15000.0; x0,y0=8000.0,6000.0
    vx0,vy0,vz0=-110.0,-80.0,-210.0; m0=2400.0; mdry=1200.0
    ve=300.0*9.81; Tmax=35000.0; h_hover=120.0; v_app=30.0; v_land=3.0
    tau=2.0; kh=0.05; vmax_h=200.0
    if over:
        g=over.get("g",g); h0=over.get("h0",h0); x0=over.get("x0",x0); y0=over.get("y0",y0)
        vx0=over.get("vx0",vx0); vy0=over.get("vy0",vy0); vz0=over.get("vz0",vz0)
        m0=over.get("m0",m0); Tmax=over.get("Tmax",Tmax); v_app=over.get("v_app",v_app)
        v_land=over.get("v_land",v_land); kh=over.get("kh",kh)
    wx,wy,wz = wind if wind else (0.0,0.0,0.0)
    x,y,h=x0,y0,h0; vx,vy,vz=vx0,vy0,vz0; m=m0
    t=0.0; land=None
    while h>0 and m>mdry and t<6000:
        if h>h_hover and math.hypot(vx,vy,vz)>80: phase="brake"
        elif h>h_hover: phase="approach"
        else: phase="land"
        vz_des = -v_app if h>h_hover else -v_land
        vx_des=max(-vmax_h,min(vmax_h,-kh*x)); vy_des=max(-vmax_h,min(vmax_h,-kh*y))
        ax=(vx_des-vx)/tau; ay=(vy_des-vy)/tau; az=(vz_des-vz)/tau
        tax=ax-wx; tay=ay-wy; taz=az+g-wz
        Tmag=m*math.hypot(tax,tay,taz)
        if Tmag>Tmax:
            s=Tmax/Tmag; tax,tay,taz=tax*s,tay*s,taz*s; Tmag=Tmax
        vx+=tax*dt; vy+=tay*dt; vz+=(taz-g)*dt
        x+=vx*dt; y+=vy*dt; h+=vz*dt; m-=(Tmag/ve)*dt; t+=dt
        if h<=0 and land is None:
            land=dict(x=round(x,2),y=round(y,2),vz=round(vz,2),fuel=m0-m)
    if land is None:
        land=dict(x=round(x,2),y=round(y,2),vz=round(vz,2),fuel=m0-m)
    return land

# 蒙特卡洛
rng=random.Random(2014); N=200; land_xy=[]; vz=[]
for _ in range(N):
    wx=rng.gauss(0,1.0); wy=rng.gauss(0,1.0); wz=rng.gauss(0,0.5)
    ld=land_trajectory(seed=2014, wind=(wx,wy,wz))
    land_xy.append((ld["x"],ld["y"])); vz.append(abs(ld["vz"]))
dist=sorted(math.hypot(a,b) for a,b in land_xy)
print("CEP50=%.2f  R90=%.2f  平均=%.2f"%(dist[N//2], dist[int(N*0.9)], sum(dist)/N))
print("|vz| min=%.2f max=%.2f mean=%.2f"%(min(vz),max(vz),sum(vz)/N))

# 可靠性 vs 风扰尺度
scales=[0.5,1.0,1.5,2.0,2.5]; rel=[]
for sc in scales:
    rr=random.Random(99); ok=0
    for _ in range(150):
        wx=rr.gauss(0,1.0*sc); wy=rr.gauss(0,1.0*sc); wz=rr.gauss(0,0.5*sc)
        ld=land_trajectory(seed=99, wind=(wx,wy,wz))
        if math.hypot(ld["x"],ld["y"])<50 and abs(ld["vz"])<4: ok+=1
    rel.append(ok/150)
print("可靠率:", [round(v,3) for v in rel])