3. 燃料消耗在线辨识

燃料消耗在线辨识 学习卡片

任务定义

飞行器在巡航过程中因燃料消耗导致质量持续减小,若控制器仍按初始质量设计增益,会造成响应过快、舵面饱和甚至振荡。本案例要求:利用飞行数据(轴向加速度、发动机推力、阻力系数)在线递推估计当前质量,并将估计值实时映射为控制增益调整系数,使闭环动态特性在质量变化时保持近似不变。

质量辨识模型

沿飞行器速度方向的力平衡方程为:

m·a_x = T - ½·ρ·V²·S·C_D

其中 m 为当前质量,a_x 为轴向加速度,T 为发动机推力,ρ 为大气密度,V 为速度,S 为参考面积,C_D 为阻力系数。定义广义阻力 D = ½·ρ·V²·S·C_D,则每个采样时刻可得到带噪声的观测:

z(k) = a_x(k) = (T(k) - D(k)) / m(k) + v(k)

由于燃料消耗速率远低于飞行动态,质量变化可建模为随机游走:m(k+1) = m(k) + w(k)。采用带遗忘因子的递推最小二乘(FF-RLS)估计质量倒数 θ = 1/m,以增强对缓变参数的跟踪能力。

自洽实现

以下Python代码实现完整的在线辨识与增益调整闭环:

import numpy as np
import matplotlib.pyplot as plt

# ---------- 飞行器参数 ----------
rho = 0.4135        # 大气密度 kg/m³ (20km高度)
S = 50.0            # 参考面积 m²
CD = 0.02           # 阻力系数
V = 250.0           # 巡航速度 m/s
D = 0.5 * rho * V**2 * S * CD   # 广义阻力 = 12921.875 N

# 真实质量变化:初始12000kg,燃料消耗率0.5kg/s
m0 = 12000.0
fuel_rate = 0.5     # kg/s
dt = 0.1            # 采样周期 100ms
sim_time = 200.0    # 仿真时长200s
n_steps = int(sim_time / dt)

# 控制器参考增益(按初始质量设计)
K0 = 0.02           # 基础增益

# ---------- FF-RLS 初始化 ----------
theta_hat = 1.0 / m0    # 质量倒数估计
P = 1e6                 # 协方差初值
lam = 0.995             # 遗忘因子

# 数据存储
m_true = np.zeros(n_steps)
m_est = np.zeros(n_steps)
gain_adj = np.zeros(n_steps)
a_cmd = np.zeros(n_steps)   # 指令加速度(阶跃)
a_x = np.zeros(n_steps)     # 实际轴向加速度

# ---------- 仿真主循环 ----------
for k in range(n_steps):
    t = k * dt
    m_true[k] = m0 - fuel_rate * t
    
    # 控制器:根据当前质量估计调整增益,输出指令加速度
    if t < 5.0:
        a_cmd[k] = 0.0
    else:
        a_cmd[k] = 3.0      # 阶跃指令 3 m/s²
    
    # 增益调整:K = K0 * (m_hat / m0)
    m_hat = 1.0 / theta_hat
    K_adj = K0 * (m_hat / m0)
    gain_adj[k] = K_adj
    
    # 控制输入(推力增量):u = K_adj * (a_cmd - a_x_prev)
    if k == 0:
        u = K_adj * a_cmd[k]
    else:
        u = K_adj * (a_cmd[k] - a_x[k-1])
    
    # 推力 = 配平推力 + 控制增量
    T_trim = D + m_true[k] * 9.8 * 0.0   # 水平飞行,配平推力=阻力
    T_total = T_trim + u * 1000.0        # 控制量转换为N
    
    # 真实动力学
    a_true = (T_total - D) / m_true[k]
    # 测量噪声
    a_meas = a_true + np.random.normal(0, 0.05)
    a_x[k] = a_true
    
    # ---------- FF-RLS 更新 ----------
    phi = 1.0   # 回归量(θ=1/m,z=phi*θ)
    z = a_meas / (T_total - D) if abs(T_total - D) > 1e-6 else 0.0
    # 注意:z = a/(T-D) = 1/m,当T-D接近0时跳过更新
    if abs(T_total - D) > 1.0:
        # 增益矩阵
        K_gain = P * phi / (lam + phi * P * phi)
        # 估计更新
        theta_hat = theta_hat + K_gain * (z - phi * theta_hat)
        # 协方差更新
        P = (1.0 - K_gain * phi) * P / lam
        # 协方差限幅防止发散
        P = np.clip(P, 1e-6, 1e8)
    
    m_est[k] = 1.0 / theta_hat

# ---------- 验证与绘图 ----------
fig, axes = plt.subplots(3, 1, figsize=(10, 8))
t_axis = np.arange(n_steps) * dt

axes[0].plot(t_axis, m_true, 'b-', label='真实质量')
axes[0].plot(t_axis, m_est, 'r--', label='RLS估计质量')
axes[0].set_ylabel('质量 (kg)')
axes[0].legend()
axes[0].grid(True)

axes[1].plot(t_axis, gain_adj, 'g-')
axes[1].set_ylabel('增益调整系数')
axes[1].grid(True)

axes[2].plot(t_axis, a_x, 'm-', label='实际加速度')
axes[2].plot(t_axis, a_cmd, 'k--', label='指令加速度')
axes[2].set_ylabel('加速度 (m/s²)')
axes[2].set_xlabel('时间 (s)')
axes[2].legend()
axes[2].grid(True)

plt.tight_layout()
plt.savefig('fuel_estimation_result.png', dpi=100)
plt.show()

# 输出最终估计误差
final_err = abs(m_est[-1] - m_true[-1]) / m_true[-1] * 100
print(f"最终质量估计误差: {final_err:.2f}%")

关键实现说明

代码中FF-RLS直接估计质量倒数 θ=1/m,观测方程构造为 z = a_x/(T-D),当推力与阻力之差过小时跳过更新以避免除零。遗忘因子 λ=0.995 对应约200个采样点(20秒)的有效记忆窗口,能跟踪燃料消耗引起的缓变质量变化。控制器增益按 K = K0·(m̂/m0) 实时缩放,使开环增益 K/m 保持恒定。

SVG:辨识与增益调整闭环结构

燃料消耗在线辨识与增益调整闭环 飞行器动力学 m(t) = m₀ - ṁ·t a = (T-D)/m 测量 a_x (含噪声) FF-RLS 辨识器 θ = 1/m̂ 遗忘因子 λ=0.995 P(k) 协方差递推 增益调整 K = K₀·(m̂/m₀) 保持 K/m 恒定 控制器 u = K·(a_cmd - a_x) a_cmd 推力T、阻力D作为已知输入 z = a_x/(T-D) → θ

运行与验证

运行方式:直接执行上述Python脚本,需安装numpy和matplotlib。脚本将生成fuel_estimation_result.png并显示三幅子图。

验证方法与判定标准:

  1. 第一幅子图中红色虚线(估计质量)应跟随蓝色实线(真实质量)下降,两者在初始瞬态(约5秒)后偏差小于2%;
  2. 第二幅子图中增益调整系数应从1.0逐渐减小,200秒时约为m(200)/m0 = (12000-100)/12000 ≈ 0.992;
  3. 第三幅子图中实际加速度在阶跃指令后应快速收敛至3 m/s²附近,超调量小于10%,且无持续振荡;
  4. 控制台输出的最终质量估计误差应小于1%。

以上标准基于代码逻辑与给定参数可直接推导,实际执行时以运行结果为准。