最近在复现一篇基于Carsim和Simulink联合仿真的车辆参数辨识文档,核心算法是递推最小二乘法(RLS),目标是在线估计轮胎侧偏刚度。这个方向在车辆动力学控制、底盘协调控制、自动驾驶模型预测控制里都很重要,因为轮胎侧偏刚度直接决定了车辆的稳定边界和转向响应特性。复现过程比预想中费劲,文档里的公式和Carsim的变量经常对不上号,联合仿真的I/O配置里也藏着不少坑。这篇把完整的复现思路、推导过程、Simulink实现细节和调试经验整理出来,给同样在啃这个方向的朋友做个参考。如果你刚接触Carsim与Simulink联合仿真,或者正准备用递推最小二乘法做轮胎侧偏刚度估计模型,这篇应该能帮你少走不少弯路。
1. 环境准备:Carsim与Simulink联合仿真,先让信号流跑通
1.1 版本兼容、路径和License:最容易卡住的三件事
我最初以为项目难点在算法本身,结果第一步联合仿真环境就折腾了很久。Carsim和Matlab/Simulink的版本匹配问题非常现实:Carsim 2021普遍搭配R2019b到R2021b的Matlab版本使用,Matlab版本太新或太旧,Carsim的Simulink接口库可能加载不出来,或者生成的S-Function模块报错。
所以我的建议是:动手前先去Carsim安装目录下的Release Notes里确认它支持的Matlab版本范围,不要图新装了个R2023a/R2024a,回头发现Carsim接口库根本不识别。
路径问题也容易踩。Carsim工程路径、Matlab工作目录、Simulink模型所在路径都必须保证纯英文、无空格、无特殊字符。很多人复现文档时,把模型放在“D:\我的文档\车辆参数辨识”这种目录下,Carsim通过S-Function加载动态库时就找不到文件,弹出一堆莫名其妙的加载错误。
再说License。网上搜Carsim安装问题时经常会遇到一个报错:invalid host。这个大概率是License管理器里的主机信息和你当前机器不匹配,比如网卡MAC地址变了、主机名改过,或者License服务没有正确启动。我自己的情况是换了一块USB网卡后出现了这个问题,把License绑定信息更新后就好了。注意,这个问题跟破解没有关系,正版授权同样会遇到,排查方向就是主机标识和License服务的启动状态。
这些环境问题看起来跟“算法复现”没关系,但如果不处理干净,后面所有工作都推进不下去。
1.2 从Carsim引出哪些状态量:输入输出通道配置
联合仿真要跑通,核心是搞清楚Carsim作为车辆动力学模型,应该向Simulink输出哪些信号,以及从Simulink接收哪些信号。
在Carsim的Run Control界面里,可以通过I/O通道配置来设定输入输出变量。对于RLS侧偏刚度估计,我在模型中用到的关键输出如下:
| Carsim输出通道(常见名称) | 物理含义 | 默认单位 | 建议换算 |
|---|---|---|---|
| Vx | 纵向车速 | km/h | m/s |
| Vy | 侧向车速 | m/s | m/s |
| Ay | 侧向加速度 | g | m/s^2 |
| YawRate | 横摆角速度 | deg/s | rad/s |
| Steer_L1 | 前轮转角 | deg | rad |
| Beta | 质心侧偏角 | deg | rad |
如果你要闭环控制,比如让Simulink生成转向角输入给Carsim,那需要在Carsim的输入通道里配置一个转向角接口,比如Steer_L1或Steer_SW(方向盘转角)。我复现的这篇文档里没有控制部分,所以Carsim的转向输入由内部驾驶员模型提供,Simulink只做状态观测和参数辨识。
单位换算是最容易出问题的环节。Carsim很多通道的默认单位是km/h、deg/s、deg,而RLS公式里需要全部使用国际单位。建议在Carsim的I/O配置界面直接把输出单位改成SI制(m/s、rad/s、rad),如果某些版本不好改,就在Simulink里加Gain模块手动换算。这个细节我后面还会再提,因为单位漏换算导致结果差几十倍的情况太常见了。
1.3 S-Function接入和步长设置
Carsim与Simulink联合仿真最常见的接入方式,是在Carsim主界面点击“Send to Simulink”,它会自动生成一个包含Carsim S-Function的Simulink模型。你在这个模型基础上添加自己的算法模块就行。
Simulink仿真步长建议设置为固定步长(Fixed-step),步长取0.001s或0.0005s。Carsim内部积分步长通常为0.001s,两者一致可以避免因步长不同引起的接口数据抖动。我在实际运行中用的是固定步长0.001s,Carsim的仿真步长也设为0.001s,整个模型运行稳定。
还有一个细节:如果使用解算器自动变步长,S-Function的采样时间可能被拉长,RLS的更新率不稳定,后续P矩阵的收敛轨迹会变得很难看。所以做参数辨识类仿真,固定步长是更稳妥的选择。
2. 模型推导:二自由度车辆模型如何变成RLS能用的回归方程
2.1 线性轮胎假设与侧偏刚度的出现
轮胎侧偏刚度是描述侧向力与侧偏角关系的参数。在侧偏角较小的线性区,侧向力可以近似为侧偏角的线性函数:
F_y = -C · α
这里的C就是侧偏刚度,单位N/rad,负号表示侧向力的方向与侧偏角方向相反。在Carsim里默认的轮胎模型通常是非线性的,但在小侧偏角范围内(比如侧偏角不超过4°到5°),线性近似的精度足够用于参数辨识复现。
车辆动力学里最常用的简化模型是二自由度单轨模型,也叫自行车模型。它把左右两个前轮合并成一个前轴,左右后轮合并成一个后轴,只考虑横向运动和横摆运动。两个关键方程分别是横向力平衡和横摆力矩平衡,推导过程如下。
横向力平衡方程(忽略前轮转角带来的纵向力分量,假设δ较小):
m · a_y = F_yf + F_yr
代入线性轮胎模型:
m · a_y = -C_f · α_f - C_r · α_r
横摆力矩平衡方程:
I_z · γ̇ = a · F_yf - b · F_yr
代入后得到:
I_z · γ̇ = -a · C_f · α_f + b · C_r · α_r
其中m是整车质量,a是质心到前轴距离,b是质心到后轴距离,I_z是绕垂向轴的转动惯量,γ是横摆角速度,α_f和α_r分别是前后轴侧偏角。
侧偏角可以由车辆运动状态推导:
α_f = β + (a · γ) / v_x - δ
α_r = β - (b · γ) / v_x
其中β是质心侧偏角,δ是前轮转角,v_x是纵向车速。这些量在Carsim的输出通道里都能找到。
2.2 整理成矩阵回归形式:目标、回归量和待估参数
RLS适合解决“观测值Y与回归量φ成线性关系”的参数估计问题,标准形式是Y = φ^T · θ。上面两个车辆方程正好可以改写成这个形式。
把横向力方程和横摆力矩方程联立起来,写成矩阵形式:
[m·a_y; I_z·γ̇] = [-α_f, -α_r; -a·α_f, b·α_r] · [C_f; C_r]
令:
- Y = [m·a_y; I_z·γ̇],称为观测向量
- Φ = [-α_f, -α_r; -a·α_f, b·α_r],称为回归矩阵
- θ = [C_f; C_r],称为待估参数向量
于是整个辨识问题被描述为:
Y = Φ · θ
这个形式非常干净。Carsim输出m、a、b、I_z这些车辆参数是已知常数(可以在Carsim车辆配置里查),a_y、γ、β、v_x、δ这些状态量可以从Carsim输出通道获取,唯一未知的就是C_f和C_r两个侧偏刚度。
2.3 可辨识性:为什么激励不丰富时两个刚度会一起发散
在实际仿真中我遇到过这样一个现象:直线行驶时RLS估计出的C_f和C_r会突然跳到很大的值,甚至变成正数,看起来很不合理。
原因在于可辨识性。当车辆直线行驶或者前轮转角恒定时,回归矩阵Φ的两个列向量之间可能出现强相关,信息矩阵的秩不足,RLS只能沿着一个方向更新参数,两个参数无法被唯一确定,就会出现一个变大、另一个变小但组合起来依然满足观测方程的情况。
解决办法是保证输入激励足够丰富。转向输入不能是恒定值,最好包含多个频率成分。这也是为什么后面推荐正弦扫描工况而不是单纯的角阶跃工况。另外,也可以给侧偏角计算加一个保护,当车速过低或激励强度不足时暂停RLS更新,避免P矩阵持续累积导致数值爆炸。
3. Simulink中的RLS估计器实现:从公式到可运行代码
3.1 数据处理:滤波、单位换算、噪声注入
在把Carsim输出信号送入RLS模块之前,需要做三件事:单位统一、滤波、以及(可选)加噪声。
单位统一在前面说过了,这里再强调一次:所有与角度相关的信号(前轮转角、质心侧偏角、横摆角速度)必须换算成rad或rad/s,车速统一成m/s,加速度统一成m/s²。如果Carsim输出的是km/h的Vx,需要除以3.6;deg转rad需要乘以π/180。
滤波方面,Carsim输出的信号是理想仿真信号,没有传感器噪声,但真实车辆上传感器信号一定带噪声,所以在复现阶段建议主动加一点噪声来检验算法鲁棒性。我在Simulink里用Band-Limited White Noise模块给横向加速度a_y加了一个噪声强度约0.05 m/s²的白噪声,然后在进入RLS之前加了一个二阶Butterworth低通滤波器,截止频率设在10Hz左右。
滤波器的截止频率不要设太低,比如1Hz以下会导致信号相位延迟明显,而RLS对输入信号的相位比较敏感,滤波延迟会让回归量和观测值在时间上错位,最终影响参数估计精度。我调试时的经验是:截止频率取5到10Hz,既能滤掉高频噪声,又不会把0.1到2Hz的车辆动力学频段压得太狠。
3.2 核心模块:MATLAB Function里的递推代码
RLS核心算法我用MATLAB Function模块实现。这个模块的好处是可以直接写矩阵运算,代码非常紧凑。
下面是完整的MATLAB Function代码:
function [Cf, Cr] = rls_tire(Y1, Y2, phi11, phi12, phi21, phi22) % RLS估计轮胎前后轴侧偏刚度 % Y1: m*a_y % Y2: I_z*gamma_dot % phi11 = -alpha_f, phi12 = -alpha_r % phi21 = -a*alpha_f, phi22 = b*alpha_r persistent theta P if isempty(theta) theta = [-80000; -60000]; % 初值: 前轴-80000 N/rad, 后轴-60000 N/rad P = 1e6 * eye(2); % 初始协方差矩阵 end lambda = 0.995; % 遗忘因子 Y = [Y1; Y2]; Phi = [phi11, phi12; phi21, phi22]; % 增益 K = P * Phi' / (lambda * eye(2) + Phi * P * Phi'); % 参数更新 theta = theta + K * (Y - Phi * theta); % 协方差更新 P = (eye(2) - K * Phi) * P / lambda; Cf = theta(1); Cr = theta(2); end这段代码里有一个关键点:MATLAB Function模块默认不支持动态改变矩阵维度,但这里theta固定为2×1、P固定为2×2、Phi固定为2×2,维度始终不变,所以代码生成和仿真都不会出问题。
遗忘因子lambda我直接写在代码里,如果你想在外面调参,可以把它作为额外的函数参数传入模块,这样就不用反复改代码。不过要注意:MATLAB Function模块的输入端口数量有限,每增加一个参数就要多一个输入连接线,模型会变乱。我的习惯是把lambda、P0这类常量放在代码里,仿真过程中暂不修改;等需要系统性扫参时,再改成外部输入或者用Matlab脚本批量修改。
3.3 观测窗口设置与Scope布局
运行联合仿真前,我建议先在Simulink模型里放几个Scope,至少观察以下信号:
- Carsim输出的纵向速度Vx和侧向加速度a_y,确认信号量级是否合理
- 计算得到的α_f和α_r,确认侧偏角量级是否在合理范围(一般应该在±0.1rad以内)
- Cf和Cr的估计值,确认收敛趋势
- 残差Y - Φ·θ,用于判断模型拟合质量
Scope不要一次性堆太多,否则模型会很乱。我通常按功能分成两个子系统:信号预处理子系统放在传感器信号和RLS估计器之间,结果监视子系统放在RLS输出部分,这样模型结构清晰,排查问题时一目了然。
4. 遗忘因子、初始协方差与仿真工况:三个决定收敛质量的旋钮
4.1 遗忘因子λ怎么选:记忆长度和跟踪能力的权衡
遗忘因子λ是RLS最重要的调节参数之一,它决定了过去数据的权重衰减速度。
λ=1时,所有历史数据权重相同,相当于普通最小二乘法,适合参数不随时间变化的系统;λ<1时,离当前时刻越远的数据权重越小,算法能跟踪参数的变化,但也会放大噪声的影响。
我复现的文档里,侧偏刚度本身不是一个恒定值,它会随着车辆载荷转移、速度变化、轮胎温度变化而缓慢漂移,所以用带遗忘因子的RLS更合理。λ的典型取值范围是0.95到0.999。
λ到底取多少,可以从有效记忆长度的角度来理解。有效记忆长度约等于1/(1-λ)。如果λ=0.995,有效记忆长度约200个采样点;在1ms步长下,相当于0.2秒内数据仍然有影响;如果λ=0.98,有效记忆长度只有50个采样点,参数更新会更“活跃”,但估计方差会明显变大。
我在做扫参实验时的结果是:λ=0.99到0.995这个区间,估计曲线最平滑,收敛速度也够快。λ小于0.97时,Cf和Cr的估计值会有明显抖动,尤其在转弯切换的瞬间。
4.2 P0和θ0:初值的影响与配置经验
RLS的初始协方差P0表示对初始参数估计值的信任程度。P0越大,说明初始参数越不确定,初始增益矩阵K就越大,算法会在头几步快速修正参数;如果P0取得太小,算法会认为初始参数很可靠,导致收敛非常缓慢。
我习惯把P0设成一个大对角阵,比如1e6·I。这个量级在侧偏刚度量级为10^4到10^5 N/rad的情况下,能保证初步收敛在零点几秒内完成。如果P0取到1e8甚至更大,虽然收敛更快,但一开始的增益过大会让参数估计值出现明显过冲,反而不利于后续稳定。
初始参数θ0可以取Carsim模型里的接近值,也可以取文献中同类车型的典型值。轿车前轴侧偏刚度量级在-60000到-100000 N/rad,后轴在-50000到-80000 N/rad。取一个接近真实值的初值可以加快收敛,但就算初值偏差很大,只要P0足够大,RLS也会在几个正弦周期内追上来。
4.3 三种激励工况对比:角阶跃、正弦扫描、双移线
工况选择直接决定辨识效果。我复现时对比了三种典型工况:
角阶跃工况:前轮转角从0快速阶跃到一个固定值,比如3°,保持数秒。这种工况能让车辆进入稳态转向,参数能快速收敛,但持续激励不足,回归矩阵两个列向量容易相关,同时辨识两个参数时可能发散。更适合用单方程先辨识某一个参数。
正弦扫描工况:前轮转角按正弦变化,且频率可以从0.1Hz扫到2Hz。这种工况信息丰富,能持续激励车辆横向动力学,是RLS辨识参数的理想工况。我在Carsim外部通过Simulink信号源生成扫描正弦信号,作为前轮转角输入,效果很好。
双移线工况:按照ISO 3888-1标准设置道路轨迹,接近真实驾驶员避障操作,激励成分更复杂,更适合验证参数辨识结果在实际工况中的泛化能力,但作为初始调参工况不够直观。
我的建议是:先用正弦扫描工况整定λ、P0等参数,再用角阶跃工况验证最小实现,最后用双移线工况做完整的泛化验证。三种工况在Carsim里的切换并不复杂,基本上就是改前轮转角输入信号源的方式。
5. 结果校验:估计值准不准,用三种方法互相印证
5.1 对照Carsim内置轮胎刚度参数
Carsim的车辆参数配置里通常能查到前轮和后轮的轮胎侧偏刚度信息。需要注意的是,Carsim显示的值可能是单胎的,也可能是整个车轴的,而二自由度模型中的C_f、C_r是整个前轴/后轴的等效侧偏刚度。
如果是单胎值,需要乘以2才是轴刚度。我在一次对比时忽略了这一点,前后轴估计结果跟Carsim里的参数差了接近一倍,排查了半天才发现是单胎和整轴的差别。
Carsim默认轮胎模型如果是非线性的,它的等效侧偏刚度在工作点附近会变化。为了保证线性近似合理,辨识工况中要让侧向加速度控制在0.3g左右甚至更低。这时候RLS估计出来的等效刚度应该和Carsim中轮胎特性线性段斜率比较接近,偏差在10%到15%以内都算合理。
5.2 回代二自由度模型比较动态响应
参数估计值是否可靠,最有力的验证方式是把估计出的C_f、C_r代回二自由度模型,用相同的前轮转角输入做一次开环仿真,然后对比二自由度模型的横摆角速度响应和Carsim输出的横摆角速度响应。
二自由度模型的微分方程可以在Simulink里用几个积分模块搭建:
β̇ = (-C_f·(β + a·γ/v_x - δ) - C_r·(β - b·γ/v_x)) / (m·v_x) - γ
γ̇ = (-a·C_f·(β + a·γ/v_x - δ) + b·C_r·(β - b·γ/v_x)) / I_z
对比结果显示,在正弦扫描工况下,二自由度模型的横摆角速度与Carsim输出的横摆角速度吻合得很好,峰值误差基本在5%以内。这说明RLS估计出的参数确实抓住了车辆横向动力学的主要特征。
如果回代后发现横摆角速度响应的幅值对不上,但趋势一致,通常是侧偏刚度估计值整体偏大或偏小,可以通过调整初值或者检查侧偏角计算是否正确来排查。
5.3 残差分析:误差到底出在哪个环节
RLS的残差e = Y - Φ·θ是判断模型拟合质量的重要指标。我在Simulink中把残差信号引出来观察,如果残差是零均值的白噪声,说明模型假设与数据基本一致;如果残差有明显周期性,说明回归量少了某个重要项,或者Carsim车辆模型的响应存在未建模动态。
我遇到的一个问题是:在大转角工况下,残差出现明显增大,原因是轮胎进入了非线性区,线性轮胎模型假设失效。把前轮转角幅值降低、让侧向加速度保持在0.3g以内后,残差就恢复正常了。
还有一个常见的误差来源是微分信号的噪声放大。I_z·γ̇里的γ̇需要通过横摆角速度求导得到,而Carsim输出本身虽然平滑,但叠加传感器噪声后求导会放大高频噪声。在这个信号上最好先加低通滤波,或者在求导之后再加一次平滑。
6. 复现文档时的高频问题与排查思路
6.1 符号、单位和滤波引起的“对不上账”
复现文档时最花时间的往往不是理论推导,而是各种细节对不上账。我整理了几个高频问题。
侧偏刚度符号不统一。有些教材把C定义为正数,侧偏力F_y = -C·α;有些文献定义为负数,F_y = C·α(C为负)。复现时如果从不同文献抄公式,很可能出现符号冲突。我的习惯是统一用正数C,公式里显式保留负号,这样写代码时不会混淆。
单位不一致。Carsim的Vx默认可能是km/h,YawRate默认是deg/s,前轮转角默认是deg,如果不换算直接代入公式,结果会偏到天差地远。有一次我忘了把前轮转角从deg转成rad,RLS估计出来的刚度比真实值大了57倍,排查了很久才发现是这个地方的问题。
滤波器相位延迟。前面提到过,滤波器截止频率太低会导致相位延迟,观测值和回归量在时间上错位,最终估计偏差。如果你发现参数估计值总是稳定地偏差某个比例,可以检查一下滤波器的群延迟,或者换截止频率更高的滤波器。
6.2 NaN、漂移、低速工况:数值稳定性问题与工程化处理
RLS在仿真中还会遇到几个典型的数值问题。
NaN或Inf。P矩阵在长时间缺乏有效激励的情况下可能发散,导致参数更新后出现NaN或Inf。我遇到这个情况时,第一反应是检查是不是有信号为零或者接近零的情况。比如车辆直线行驶时,侧偏角α_f和α_r都接近0,回归矩阵Φ接近零矩阵,信息量不足,P矩阵持续累积大值。工程化处理方式加一个使能逻辑:只有当侧偏角绝对值大于某个阈值(比如0.005rad)或转向加速度大于阈值时才启用RLS更新。
参数漂移到不合理区间。比如估计值从负数变成正数,这通常意味着可辨识性不足或者遗忘因子太小。降低遗忘因子会让参数更容易受噪声影响而漂移,所以如果参数在合理区间内小幅抖动,可以把λ调大一点;如果直接漂移大几十倍,则要检查激励是否充足。
低速工况的处理。侧偏角公式里有v_x在分母,当车速接近0时,α_f和α_r会趋于无穷大,RLS必然发散。我的处理是加一个车速判断:v_x低于某个值(比如1m/s)时,强制暂停估计器,输出上一次估计值。
这些看似“工程琐碎”的细节,恰恰是复现文档时最消耗时间的部分。文档里往往只写公式和结论,不会告诉你低速时怎么保护、滤波怎么调、单位怎么换算,而这些只能在实操中一点点摸索出来。
整套流程从环境搭建到跑出可靠结果,我前后大概花了两三天。最深的体会是:车辆参数辨识本身不算难,难的是保持“模型假设”和“仿真环境”之间的逻辑一致。二自由度模型只描述了线性区横向动力学,Carsim则是完整的非线性车辆模型,两者本来就有天然偏差。复现的时候不要追求估计值和Carsim内部参数完全相等,重点应该是验证RLS算法能否在合理的激励条件下、合理的量级范围内把轮胎侧偏刚度辨识出来,并用回代验证确认参数确实刻画了车辆响应。按照“先跑通正弦扫描、再验证角阶跃、最后做双移线泛化”的顺序推进,整个过程会可控很多。如果你正在肝类似的联合仿真项目,希望这篇能帮你把几个最容易卡住的环节提前避开。