基于无迹卡尔曼滤波(Unscented Kalmam Filter, UKF)的车辆状态观测器 Carsim与Simulink联合 可估计车辆纵向车速,横向车速,横摆角速度和四个车轮侧向力(效果见图) UKF使用子函数形式编程,只要定义好状态方程和观测方程,便可方便的进行二次开发 Carsim2018 兼容Carsim2019 MATLAB2018b 带有详细注释和说明文档 Carsim与Simulink联合估计难度与单纯的Simulink模型估计难度不同 ★用Carsim做状态估计的难度在于carsim的车辆模型完全是黑箱状态,为了获得较好的估计结果需要不断的调整车辆模型参数 ★估计的参数较多也增加了估计难度,比如估计侧向车速需要用到轮胎侧向力,但轮胎侧向力也是需要通过估计获得的,这样就会存在误差的累积,因此估计的参数越多难度越大

最近在倒腾Carsim和Simulink联合仿真做车辆状态估计,发现这玩意比纯Simulink模型刺激多了。UKF(无迹卡尔曼滤波)虽然算法框架成熟,但真要和黑箱般的Carsim车辆模型配合,调参调得我头秃——特别是当你要同时估计纵向车速、横向车速、横摆角速度外加四个轮子的侧向力时,简直像在玩参数俄罗斯方块。

先说说系统架构(直接上代码骨架更直观):

function [x_est, P] = UKF_vehicle(f_func, h_func, y, x_pred, P_pred, Q, R)
    % 核心就这几步:生成sigma点->预测->更新
    % 这里能看到状态方程f_func和观测方程h_func是外部传入的
    chi = sigma_points(x_pred, P_pred);  % 撒点操作
    [chi_pred, x_pred, P_pred] = ut(f_func, chi, Q); % 无迹变换
    [zeta_pred, y_pred, Pyy] = ut(h_func, chi_pred, R);
    Pxy = chi_pred*zeta_pred'/(2*nx) + ...; % 协方差计算
    K = Pxy/Pyy; % 卡尔曼增益
    x_est = x_pred + K*(y - y_pred); % 状态更新
end

这种子函数封装方式最香的是二次开发时,只要重写ffunc和hfunc就能快速换模型。不过和Carsim对接时,观测方程里的车辆输出得特别注意采样同步——有次因为0.01秒的延迟导致估计器直接崩了,查了三天才发现是时钟同步问题。

轮胎力估计最坑的地方在于数据耦合。比如观测方程里需要轮速和加速度:

function y = observe(x)
    % x包含[vx, vy, yaw_rate, Fy1~Fy4]
    y = [x(1)*cos(beta) + x(2)*sin(beta);  % 纵向加速度观测
         (x(4)+x(5)+x(6)+x(7))/mass;       % 横向加速度观测
         (a*(x(4)+x(5)) - b*(x(6)+x(7)))/Iz]; % 横摆角加速度
end

但轮胎侧向力本身又依赖滑移率,而滑移率计算需要...没错,还是vx和vy。这种鸡生蛋蛋生鸡的死循环,只能靠UKF的迭代特性硬刚。实测发现把轮胎松弛特性参数调大能缓解震荡,不过这会牺牲动态响应——永远在走钢丝的平衡。

调Carsim参数更玄学。有组悬挂刚度参数,官方手册说取值范围是150~250N/mm,但实际调参发现:

参数估计误差变化趋势
K=180横向速度误差↑15%
K=220轮胎力相位滞后明显
K=195各项指标最优

这种非线性的参数影响,光靠理论计算根本搞不定,最后是开着Carsim的动画,边看车辆"抽搐"边微调出来的。更别说Carsim2018和2019的兼容性坑——明明同一个模型文件,在2019里跑着正常,到2018里轮胎接地点计算就飘了。

几点血泪经验:

  1. 噪声矩阵Q的主对角线别全设为相同量级,车轮动态噪声应该比车身大一个数量级
  2. 在Carsim里把输出信号的物理单位统一成SI制,避免出现牛顿和千牛混用的惨案
  3. 调试时先锁住部分状态(比如固定纵向车速),等残差收敛后再放开全状态估计

现在这套系统能在双移线工况下,把横向车速估计误差控制在0.3m/s以内(真值靠Carsim内部输出)。不过遇到对开路面制动时,前轮侧向力估计还是会抽风——果然没有完美的状态观测器,就像没有不写bug的程序员。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐