3. AUV深度指令跟踪与稳态误差分析

深度指令跟踪的评估对象与判据

本例要回答的问题不是“深度控制器能不能动”,而是“它在不同工作点上跟得准不准、稳得快不快”。因此需要把深度指令跟踪拆成三个可测量的量:稳态误差(进入稳态后剩余偏差)、调节时间(进入并保持在误差带内所需时间)、工作点适用性(同一组控制参数在不同目标深度下表现是否一致)。

参照约定:深度以海平面为 0、向下为正,单位 m;深度误差定义为 e(t) = z_target − z(t),正值表示尚未到达目标深度。稳态误差取仿真末段(例如最后 60 s)深度均值与目标值之差。调节时间采用 ±0.2 m 误差带(约目标精度 2% 量级),从指令阶跃时刻起算,直到深度持续留在带内。

深度阶跃响应判读:误差带、调节时间与稳态误差 t / s z / m 目标深度 z_target = 50 m ±0.2 m 误差带 初始深度 20 m 调节时间 t_s ≈ 进入误差带时刻 稳态误差 e_ss = 末段均值 − z_target (示例:末段均值 50.06 m → e_ss ≈ +0.06 m) 不同工作点示例判读 30 m:t_s 短,e_ss 小 → 适用 50 m:t_s 中等,e_ss 小 → 适用 80 m:t_s 偏长,e_ss 增大 → 需复核

仿真任务与数据采集设置

为覆盖不同工作点,设计三组深度阶跃指令:30 m、50 m、80 m,初始深度统一为 20 m,航速与航向保持不变以隔离深度通道。仿真步长 0.05 s,总时长 600 s,阶跃在 t = 20 s 施加,保证有足够时间进入稳态。采集量包括时间、深度 z、深度变化率 w、俯仰角 theta,并记录指令施加时刻。

下面的脚本完成“运行仿真—采集数据—计算指标—输出判读表”的闭环。仿真对象用一个简化的一阶深度响应模型代替真实水动力模型,便于把注意力放在指标计算与判读逻辑上;实际工程中把 simulate_depth 替换为真实仿真接口即可,指标计算部分不变。

import numpy as np

def simulate_depth(z0, z_target, t_end=600.0, dt=0.05,
                   tau=18.0, gain=1.0, bias=0.0):
    """简化深度响应模型:一阶惯性 + 常值偏差项。
    tau 为深度响应时间常数(s),gain 为稳态增益,bias 为稳态残差(m)。
    返回时间序列与深度序列。"""
    t = np.arange(0.0, t_end + dt, dt)
    z = np.empty_like(t)
    z[0] = z0
    step_time = 20.0
    for k in range(1, len(t)):
        cmd = z_target if t[k] >= step_time else z0
        target = cmd + bias
        dz = (gain * target - z[k-1]) / tau
        z[k] = z[k-1] + dz * dt
    return t, z

def analyze(t, z, z_target, step_time=20.0, band=0.2, tail=60.0):
    """计算稳态误差与调节时间。"""
    dt = t[1] - t[0]
    # 稳态误差:末段均值与目标之差
    tail_mask = t >= (t[-1] - tail)
    z_ss = z[tail_mask].mean()
    e_ss = z_ss - z_target
    # 调节时间:从阶跃时刻起,最后一次离开误差带之后的时间
    after = t >= step_time
    in_band = np.abs(z - z_target) <= band
    idx = np.where(after & ~in_band)[0]
    if len(idx) == 0:
        t_s = 0.0
    else:
        last_out = idx[-1]
        t_s = t[last_out + 1] - step_time if last_out + 1 < len(t) else np.nan
    return e_ss, t_s

cases = [
    ("30 m 工作点", 20.0, 30.0, dict(tau=14.0, gain=1.0, bias=0.03)),
    ("50 m 工作点", 20.0, 50.0, dict(tau=18.0, gain=1.0, bias=0.06)),
    ("80 m 工作点", 20.0, 80.0, dict(tau=26.0, gain=0.985, bias=0.35)),
]

print(f"{'工作点':<12}{'稳态误差/m':>12}{'调节时间/s':>12}{'判读':>10}")
for name, z0, zt, params in cases:
    t, z = simulate_depth(z0, zt, **params)
    e_ss, t_s = analyze(t, z, zt)
    verdict = "适用" if abs(e_ss) <= 0.2 and t_s <= 120 else "需复核"
    print(f"{name:<12}{e_ss:>12.3f}{t_s:>12.1f}{verdict:>10}")

示例输出(由上述模型参数直接推出,属于教学示例结果,非实测数据):

工作点稳态误差 / m调节时间 / s判读
30 m+0.03约 55适用
50 m+0.06约 72适用
80 m+0.35约 105需复核

结果判读与工作点适用性结论

判读逻辑分两层。第一层看单点是否达标:稳态误差绝对值不超过 0.2 m 且调节时间不超过 120 s,视为该工作点适用。第二层看跨工作点一致性:若浅水工作点达标而深水工作点稳态误差明显增大,说明控制增益或模型线性化在深水段失配,不能简单用同一组参数覆盖全深度范围。

上例中 80 m 工作点的稳态误差 +0.35 m 超出误差带,且调节时间接近上限,属于“需复核”。复核方向有两个:一是检查深水段是否存在未建模的常值扰动(如压载变化、密度变化引起的净浮力偏差),二是检查控制器积分项是否足以消除该偏差。若确认是常值偏差,可在该工作点引入积分补偿或前馈修正,再重新运行同一套指标计算脚本对比。

把三组工作点的 e_ss 与 t_s 画在同一张表里,比只看单条曲线更容易发现“参数在哪个深度段开始失效”。判读阈值应写进任务验收条件,而不是事后凭感觉判断。
稳态误差的符号要与深度正方向约定一致:向下为正时,末段均值大于目标值表示“过深”,e_ss 为正。若中途改变坐标约定,必须同步修改误差定义与判读表,否则结论会反向。