基于无迹卡尔曼滤波(Unscented Kalmam Filter, UKF)的车辆状态观测器
基于无迹卡尔曼滤波(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里轮胎接地点计算就飘了。
几点血泪经验:
- 噪声矩阵Q的主对角线别全设为相同量级,车轮动态噪声应该比车身大一个数量级
- 在Carsim里把输出信号的物理单位统一成SI制,避免出现牛顿和千牛混用的惨案
- 调试时先锁住部分状态(比如固定纵向车速),等残差收敛后再放开全状态估计
现在这套系统能在双移线工况下,把横向车速估计误差控制在0.3m/s以内(真值靠Carsim内部输出)。不过遇到对开路面制动时,前轮侧向力估计还是会抽风——果然没有完美的状态观测器,就像没有不写bug的程序员。

更多推荐
所有评论(0)