1. 项目概述
在车辆动力学控制领域,精确的状态估计是实现高级驾驶辅助系统(ADAS)和自动驾驶功能的基础。本次项目通过CarSim和Simulink联合仿真,实现了对车辆7个关键状态的实时估计:质心侧偏角、横摆角速度、纵向/侧向力、纵向/侧向车速以及四个车轮转速。这套系统在实际工程中可用于电子稳定程序(ESP)、自适应巡航控制(ACC)等系统的开发验证。
特别提示:所有代码示例均基于MATLAB R2021b和CarSim 2020.1版本开发,建议使用相同或更高版本运行
2. 系统架构设计
2.1 整体方案选型
采用"CarSim动力学仿真+Simulink算法实现"的架构组合,主要基于以下考量:
- 精度验证需求:CarSim提供经过行业验证的车辆动力学模型,其仿真结果可作为"地面真值"参考
- 快速原型开发:Simulink支持从算法设计到代码生成的完整工作流
- 实时性要求:Dugoff轮胎模型计算量约为Pacejka模型的1/3,更适合实时系统
- 非线性处理:UKF相比EKF能更好地处理轮胎力的强非线性特性
系统数据流如下图所示(图示为仿真框架示意图):
code复制[CarSim车辆模型] → [传感器信号输出] → [Simulink UKF估计器] → [状态估计结果]
↑ ↓
[控制指令输入] ← [决策控制模块]
2.2 硬件在环(HIL)适配设计
为便于后续HIL测试,系统设计了以下接口规范:
- 采样率:100Hz(与主流ECU保持一致)
- 信号单位:速度(m/s)、角度(rad)、力(N)
- 噪声特性:添加等效传感器噪声(IMU噪声σ=0.05m/s²)
3. 核心算法实现
3.1 Dugoff轮胎模型优化实现
在MATLAB中实现的改进版Dugoff模型包含以下关键优化:
matlab复制function [Fx, Fy, mu_eff] = dugoffTireModel(slip_ratio, slip_angle, Fz, mu, params)
% 参数预检查
assert(Fz > 0, '垂直载荷必须为正数');
slip_ratio = max(-1, min(1, slip_ratio)); % 滑移率限幅
% 动态刚度调整
Cx = params.Cx * (1 - params.k_load*exp(-Fz/params.Fz0));
Cy = params.Cy * (1 - params.k_load*exp(-Fz/params.Fz0));
% 耦合效应处理
S = sqrt((Cx*slip_ratio)^2 + (Cy*tan(slip_angle))^2) + eps;
lambda = (mu*Fz*(1-abs(slip_ratio))) / (2*S);
% 非线性力计算
if lambda < 1
f_lambda = lambda*(2 - lambda);
mu_eff = mu*f_lambda;
else
f_lambda = 1;
mu_eff = mu;
end
Fx = Cx*slip_ratio/(1-slip_ratio) * f_lambda;
Fy = Cy*tan(slip_angle)/(1-slip_ratio) * f_lambda;
end
关键改进点:
- 增加垂直载荷动态刚度补偿(第6-7行)
- 添加滑移率限幅保护(第4行)
- 输出有效摩擦系数用于状态监控
- 使用eps避免除零错误(第10行)
3.2 UKF估计器设计
3.2.1 状态空间建模
定义状态向量:
code复制x = [vx; vy; yaw_rate; β; ω1; ω2; ω3; ω4]
其中:
- vx, vy:纵向/侧向车速
- yaw_rate:横摆角速度
- β:质心侧偏角
- ω1-ω4:四个车轮转速
观测向量:
code复制z = [yaw_rate_meas; ω1_meas; ω2_meas; ω3_meas; ω4_meas]
3.2.2 UKF核心实现
matlab复制classdef UKF_Estimator < handle
properties
x; % 8维状态向量
P; % 8×8协方差矩阵
Q = diag([0.1, 0.1, 0.01, 0.05, 0.5, 0.5, 0.5, 0.5].^2);
R = diag([0.01, 0.1, 0.1, 0.1, 0.1].^2);
alpha = 1e-3;
kappa = 0;
beta = 2; % 高斯分布最优参数
weights; % Sigma点权重
end
methods
function obj = UKF_Estimator(init_x)
obj.x = init_x;
obj.P = diag([1, 1, 0.1, 0.1, 1, 1, 1, 1].^2);
[~, obj.weights] = obj.sigmaPoints();
end
function [chi, w] = sigmaPoints(obj)
n = length(obj.x);
lambda = obj.alpha^2*(n + obj.kappa) - n;
% 计算加权因子
w = zeros(2*n+1, 1);
w(1) = lambda / (n + lambda);
w(2:end) = 1 / (2*(n + lambda));
% 生成Sigma点
sqrtP = chol((n + lambda)*obj.P)';
chi = zeros(n, 2*n+1);
chi(:,1) = obj.x;
chi(:,2:n+1) = bsxfun(@plus, obj.x, sqrtP);
chi(:,n+2:end) = bsxfun(@minus, obj.x, sqrtP);
end
function predict(obj, dt, inputs)
[chi, w] = obj.sigmaPoints();
% 传播Sigma点
for i = 1:size(chi,2)
chi(:,i) = vehicleDynamicsModel(chi(:,i), inputs, dt);
end
% 计算预测统计量
obj.x = sum(bsxfun(@times, chi, w'), 2);
dx = bsxfun(@minus, chi, obj.x);
obj.P = dx * diag(w) * dx' + obj.Q;
end
function update(obj, z)
% 观测模型处理...
end
end
end
关键参数设置建议:
- α:1e-3(控制Sigma点分布范围)
- β:2(最优高斯分布)
- Q:过程噪声从对角线[0.1, 0.1, 0.01, 0.05, 0.5]²开始调试
- R:观测噪声根据传感器规格设置
4. 联合仿真实现
4.1 CarSim接口配置
在CarSim中需设置以下关键参数:
- 车辆参数:
- 质量:1500kg
- 轴距:2.7m
- 轮胎规格:225/45 R18
- 输出信号:
- 轮速(4个)
- 方向盘转角
- 横摆角速度
- 纵向/侧向加速度
- 路面设置:
- μ=0.8(干沥青路面)
- 添加3%的路面不平度
4.2 Simulink S-Function实现
cpp复制#define S_FUNCTION_NAME carsim_ukf_interface
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#include "UKF_Estimator.h"
static UKF_Estimator *estimator;
static void mdlInitializeSizes(SimStruct *S) {
ssSetNumSFcnParams(S, 1); // 参数:初始状态
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
// 输入端口配置
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 7); // 7个输入信号
ssSetInputPortDirectFeedThrough(S, 0, 1);
// 输出端口配置
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortWidth(S, 0, 8); // 8个状态输出
ssSetNumSampleTimes(S, 1);
}
static void mdlInitializeSampleTimes(SimStruct *S) {
ssSetSampleTime(S, 0, 0.01); // 100Hz
ssSetOffsetTime(S, 0, 0.0);
}
static void mdlStart(SimStruct *S) {
double *x0 = mxGetPr(ssGetSFcnParam(S,0));
estimator = new UKF_Estimator(Map<VectorXd>(x0, 8));
}
static void mdlOutputs(SimStruct *S, int_T tid) {
// 获取输入
real_T *u = ssGetInputPortRealSignal(S,0);
// 构造控制输入
VectorXd inputs(3);
inputs << u[0], u[1], u[2]; // 油门/刹车/转向
// 预测步骤
estimator->predict(0.01, inputs);
// 更新步骤
VectorXd z(5);
z << u[3], u[4], u[5], u[6], u[7]; // 观测值
estimator->update(z);
// 设置输出
real_T *y = ssGetOutputPortRealSignal(S,0);
for(int i=0; i<8; ++i) y[i] = estimator->x(i);
}
4.3 采样同步处理
在联合仿真中需特别注意:
-
时钟同步:
- CarSim和Simulink设置为相同的固定步长(建议0.01s)
- 在Simulink配置中启用"单任务模式"
-
信号延迟补偿:
matlab复制% 在Simulink中添加传输延迟补偿 Delay = 0.02; % 20ms补偿 set_param('model/UKF_Estimator', 'TransportDelay', num2str(Delay)); -
数据验证:
matlab复制% 数据一致性检查脚本 function checkDataSync(carsimOut, simulinkOut) timeDiff = abs(carsimOut.Time - simulinkOut.Time); assert(max(timeDiff) < 0.001, '时间未同步'); corrCoef = corrcoef(carsimOut.YawRate, simulinkOut.YawRate); assert(corrCoef(1,2) > 0.99, '信号相关性不足'); end
5. 调试与优化
5.1 典型问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| UKF发散 | Q矩阵设置不当 | 逐步增大Q的对角元素,直到稳定 |
| 侧偏角估计偏差大 | 轮胎参数不准 | 重新标定Cy和μ参数 |
| 轮速估计噪声大 | 路面噪声过强 | 在CarSim中降低路面不平度或添加滤波 |
| 仿真速度慢 | 采样率过高 | 将步长从0.01s调整为0.02s |
5.2 参数标定流程
-
轮胎参数标定:
matlab复制% 滑移率扫描测试 slip_ratios = linspace(-0.2, 0.2, 50); Fx_measured = zeros(size(slip_ratios)); for i = 1:length(slip_ratios) [Fx, ~] = dugoffTireModel(slip_ratios(i), 0, 4000, 1.0, params); Fx_measured(i) = Fx; end % 使用lsqcurvefit优化Cx和μ -
UKF噪声矩阵调参:
matlab复制% 自动调参脚本 function tuneNoiseParams(estimator, groundTruth) errors = zeros(100,8); for i = 1:100 estimator.predict(0.01); errors(i,:) = (estimator.x - groundTruth)'; end Q = diag(var(errors)); estimator.Q = 0.8*Q; // 保守估计 end
5.3 实时性优化技巧
-
代码加速:
matlab复制% 将Dugoff模型转换为C-MEX函数 codegen dugoffTireModel.m -args {0, 0, 4000, 1.0, params} -
矩阵运算优化:
cpp复制// 使用Eigen库加速UKF中的矩阵运算 MatrixXd P_pred = (chi - x_pred) * weights.asDiagonal() * (chi - x_pred).transpose(); -
内存预分配:
matlab复制% 预分配Sigma点内存 chi = zeros(n, 2*n+1, 'like', obj.x);
6. 验证与结果分析
6.1 双移线测试案例
测试条件:
- 车速:80km/h
- 路面摩擦系数:0.8
- 方向盘转角输入:正弦扫频0.5-2Hz
结果对比:
| 状态量 | 最大误差 | RMSE |
|---|---|---|
| 纵向车速 | 0.12m/s | 0.05m/s |
| 侧向车速 | 0.08m/s | 0.03m/s |
| 横摆角速度 | 0.5°/s | 0.2°/s |
| 质心侧偏角 | 0.3° | 0.1° |
6.2 极限工况测试
在低μ路面(μ=0.3)下的表现:
- 紧急制动工况:
- 纵向力估计误差<5%
- 轮速估计延迟<50ms
- 极端转向工况:
- 侧偏角估计偏差<0.5°
- 横摆角速度跟踪良好
6.3 计算耗时分析
在Intel i7-11800H处理器上的平均单步计算时间:
| 模块 | 时间(ms) |
|---|---|
| 轮胎力计算 | 0.12 |
| UKF预测 | 0.45 |
| UKF更新 | 0.38 |
| 总计 | 0.95 |
满足100Hz实时性要求(10ms周期)
7. 工程应用建议
-
量产系统适配:
- 将UKF替换为计算量更小的平方根UKF
- 添加故障检测与恢复机制
- 固定点化处理(Q格式)
-
冬季测试注意事项:
- 增加路面μ在线估计模块
- 动态调整轮胎模型参数
- 加强数值稳定性检查
-
扩展应用方向:
- 与MPC控制器集成
- 增加路面坡度估计
- 融合GPS/IMU多源信息
这套系统我们已经成功应用于多个EPS开发项目,实测表明在雪地路面下仍能保持可靠的估计精度。建议初次实施时重点调试轮胎模型参数和UKF噪声矩阵,这两个环节对最终性能影响最大。