前两年做操稳性能对标项目,我最初图省事,直接用线性轮胎模型搭了一套Simulink整车模型。结果双移线工况推出来的横摆角速度响应跟试验数据对不上,侧向加速度峰值差了将近20%。后来把轮胎换成魔术公式轮胎模型,重新拟合参数、搭子系统、做联合仿真,整套曲线才拉回来。那次之后我就把Simulink里搭建魔术公式轮胎模型的完整流程沉淀了下来:从公式原理、三种建模实现路径的取舍,到纵向、侧向、综合滑移工况的处理,再到参数辨识和与Carsim联合仿真验证。这篇文章就是给那些同样在车辆动力学仿真里被轮胎模型折磨的同学,一份能直接照着落地的工作笔记。
1. 为什么选魔术公式:从一次对不上试验的操稳仿真说起
1.1 整车仿真里,轮胎是唯一"创收"的力源
做底盘控制算法或者整车操稳仿真的朋友应该都有同感:一台车不管车身建模得多精细,悬架K&C特性标定得多准,最后所有力都得通过轮胎接地点传出去。车辆加速要靠轮胎纵向力,过弯要靠轮胎侧向力,制动距离、横摆响应、侧偏特性全部由轮胎的附着状态决定。轮胎模型精度不够,整车仿真的可信度就是空中楼阁。
我那次翻车就是典型的反面案例。当时用的线性模型里侧偏刚度按常数给,认为侧偏角小的时候勉强可用。但操稳仿真一进到极限工况,比如双移线避障、蛇行绕桩,轮胎早就进入非线性区,侧向力随侧偏角增大出现饱和,线性模型完全表达不出这种"力先增大后回落"的特性。仿真结果是横摆角速度发飘、方向盘转角响应滞后,怎么调PID都救不回来。
后来我把轮胎模型换成魔术公式,同样的整车框架、同样的驾驶员模型,曲线一下子就对上了。那次经历让我彻底明白:轮胎模型的复杂度不是锦上添花,而是整车级仿真能否反映真实物理过程的基本前提。
1.2 主流轮胎模型横评与选型逻辑
在做选型之前,我先梳理过市面上常用的几类轮胎模型,大家可以根据自己的应用场景对号入座。
| 模型类别 | 表达能力 | 计算量 | 适用场景 | 局限 |
|---|---|---|---|---|
| 线性轮胎模型 | 只覆盖小侧偏角线性区 | 极低 | 经典车辆动力学理论推导、线性控制设计 | 无法进入极限工况 |
| Dugoff模型 | 有纵向/侧向耦合的简化表达 | 低 | 控制算法快速验证 | 无法精确拟合试验曲线 |
| UA模型 | 基于刷子理论,半经验 | 中 | 需要一定物理外推时 | 参数解释性较弱 |
| 魔术公式MF | 高精度拟合试验数据 | 中低 | 操稳仿真、ABS/TCS开发、整车级实时仿真 | 对参数数据质量依赖高 |
| FTire等柔性环模型 | 高频、高精度 | 高 | NVH、路面冲击 | 参数多,辨识成本高 |
我的结论很直接:做整车级操纵稳定性、底盘控制算法开发,魔术公式是精度和计算量的最优平衡点。它本质上是经验模型,把轮胎的力特性通过一组带明确物理含义的参数拟合出来,既能反映非线性饱和,又不至于像柔性环模型那样动辄上百个参数,Simulink里跑实时仿真毫无压力。
2. 魔术公式的数学骨架:B、C、D、E四旋钮如何控制曲线
2.1 一个公式通吃三个方向的由来
魔术公式最早是Pacejka等人在上世纪80年代末提出的,核心思路很有意思:用一个统一的三角函数表达式,分别描述纵向力、侧向力、回正力矩与滑移率/侧偏角的关系。
以纵向力为例,纯滑移工况下的表达式是:
Fx = D·sin(C·arctan(B·s − E·(B·s − arctan(B·s)))) + Sv
其中s是纵向滑移率,定义是驱动时(ω·R − Vx)/Vx,制动时可能取不同定义,但要保持一致性。Sv是垂直力偏移,通常处理滚动阻力或残余力。
我最初看到这个公式的时候觉得挺玄乎,但后来理解了一个关键点:反正切函数天然自带"先近似线性、后趋向饱和"的形状,外层再套一个正弦函数,通过改变参数就可以压出各种各样的轮胎力曲线。这就是它为什么能用一个表达式同时拟合纵向力、侧向力的原因——反正切配正弦的组合,表达能力足够强。
2.2 四个因子的几何意义与载荷依赖
魔术公式里最核心的四根旋钮是B、C、D、E,理解清楚它们对调参至关重要。
| 因子 | 名称 | 几何意义 | 对曲线的影响 |
|---|---|---|---|
| D | 峰值因子 | 决定曲线峰值 | 直观对应最大附着系数下的峰值力 |
| C | 形状因子 | 决定曲线整体形状 | 接近正弦程度,控制峰值的宽窄 |
| B | 刚度因子 | 与原点斜率相关 | B·C·D就是原点斜率,即纵向刚度 |
| E | 曲率因子 | 决定峰值附近的曲率 | 控制从线性区到饱和区过渡的陡缓 |
这里最容易踩的一个坑是:这四个因子通常不是常数,而是随垂直载荷Fz变化的。比如D随Fz基本呈抛物增长,但有饱和趋势;原点斜率B·C·D也随Fz增大而增大。完整的PAC2002参数表里每个系数都带载荷多项式,我实战中用到的典型数值是:某B级车前轮在Fz=4000N左右时,纵向力的D大约在4500~5500N,C取1.65附近,B约10~13,E约0.3~0.6。侧向力的C通常在1.3左右,E可能是负值,要注意不要按纵向的参数习惯去猜。
所以在Simulink里建模时,我建议把四个因子都先表达成Fz的函数,再代入主公式,而不是图省事把四个因子设成固定常数。固定常数的模型载荷一变就失真,后面做制动转向联合工况时误差会特别明显。
2.3 侧向力与回正力矩:公式换汤不换药,但系数要重标定
侧向力的表达式和纵向力长得几乎一样,只是自变量从滑移率s换成了侧偏角α:
Fy = D·sin(C·arctan(B·α − E·(B·α − arctan(B·α)))) + Sv
但同一套字母,系数含义和数值完全不同。侧向工况通常还要考虑水平偏移Sh和垂直偏移Sv,因为轮胎本身有锥度、帘布层转向效应,导致侧偏角为零时侧向力不一定为零。这类偏移项在赛车轮胎上尤其明显,民用车会小一些。
回正力矩Mz也是用同构公式,只是形状更复杂。我的建议是:如果刚起步做轮胎模型,第一版可以先不管Mz,用简化方式估算或直接置零,先把纵向、侧向力做准。等把Fx、Fy调通、再往整车模型集成,那时候再回头加Mz,否则一上来就要拟合三组公式,参数辨识工作量会把你劝退。
3. Simulink里落地:从函数到可复用封装子系统
3.1 三种实现路径的取舍
在Simulink里实现魔术公式,我见过三种主流做法,各有适用场景。
| 实现方式 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| Fcn模块直接写表达式 | 搭建快,模型简单 | 多输入表达式需要拼向量,易写错;不支持复杂分支 | 快速验证纯工况 |
| MATLAB Function模块 | 可写完整m函数,支持分支、循环、代码生成 | 编译慢一点,调试稍麻烦 | 正规工程模型,推荐 |
| Lookup Table查表 | 不需拟合公式,直接插值试验数据 | 数据颗粒度不够时,插值结果不平滑 | 有大量实测台架数据时 |
我自己主力用的是MATLAB Function模块。一方面是因为参数多、公式长,Fcn模块的字符串解析写着实在太痛苦;另一方面是MATLAB Function天然兼容Embedded Coder,后面做C代码生成、硬件在环时不至于推倒重来。
3.2 MATLAB Function实现关键代码
下面给一个可以抄作业的代码框架,包含纵向力和侧向力的纯工况计算。我用的是简化PAC89风格,参数常量可以后续替换成Fz的多项式函数。
function [Fx, Fy] = MF_Tire(Fz, kappa, alpha) % 魔术公式轮胎模型简化实现(纯工况) % Fz: 垂直载荷(单位N) % kappa: 纵向滑移率(无因次,驱动为正) % alpha: 侧偏角(单位deg,使用前转弧度) alpha_rad = alpha * pi / 180; % 纵向力参数(示例:某205/55R16型轿车胎) Dx = 1.15 * Fz; % 峰值因子,随Fz线性近似 Cx = 1.65; % 形状因子 BCDx = 0.28 * Fz; % 原点刚度(N/滑移率单位) Bx = BCDx / (Cx * Dx); % 刚度因子反算 Ex = 0.55; % 曲率因子 % 纵向力公式 Fx = Dx * sin(Cx * atan(Bx * kappa - Ex * (Bx * kappa - atan(Bx * kappa)))); % 侧向力参数(示例) Dy = 1.12 * Fz; Cy = 1.30; BCDy = 0.09 * Fz; % 侧偏刚度( N/deg ),注意角度单位 By = BCDy / (Cy * Dy); Ey = -0.25; % 侧向E一般取负,曲线峰值后回落更明显 % 侧向力公式:角度用弧度 Fy = Dy * sin(Cy * atan(By * alpha_rad - Ey * (By * alpha_rad - atan(By * alpha_rad)))); end这段代码里藏了两个我在实际项目中反复强调的细节。
第一,侧偏刚度的单位。轮胎厂家给的侧偏刚度很多是N/deg,我习惯保留这个单位去算B,但公式里sin/atan的自变量必须用弧度,所以入口要把alpha转成rad。单位不统一是Simulink里曲线一开始完全变形的最常见原因。
第二,B不直接设参数,而是通过B·C·D反算。这样做的原因是,你手头能查到的数据往往是"原点斜率"或者"侧偏刚度",而不是孤立的B值。直接给B然后指望凑出正确刚度,效率太低了。
3.3 子系统封装和信号防呆
代码写好之后,我会在Simulink里创建一个子系统,把MATLAB Function放进去,然后做Mask封装。输入接口做成三个:Fz、kappa、alpha,输出两个:Fx、Fy。
封装的好处是:整车模型里其他模块看到的是一个干净的轮胎组件,双击可以填参数、换参数组,而不是面对一大团连线和公式。我在做多工况仿真时,会提前准备好Set1、Set2、Set3三组参数,通过Mask参数切换,方便做干湿路面、不同载荷的对照试验。
信号集这块,我强烈建议用Bus信号做整车集成。把轮胎的力输出定义成Bus,后续接到车身模型、悬架模型时,接口字段一目了然,比徒手拉一根根信号线清晰得多。另外,MATLAB Function里所有输入输出都要显式声明类型,避免仿真过程中出现隐式类型转换导致的数据抖动。
防除零也是仿真实战里必须处理的点。滑移率的计算会除Vx,车辆起步瞬间Vx接近零,直接把0放进去会出现-inf或者NaN,仿真直接发散。我一般在除之前加一个下限保护:
Vx = max(0.1, Vx_measured); % 车速下限保护,单位m/s kappa = (wheel_speed * Re - Vx) / Vx;4. 综合滑移工况:为什么不能把纯工况结果简单叠加
4.1 附着椭圆:纵向力吃掉一部分附着余量
很多刚开始做轮胎模型的人会下意识以为:综合工况就是纵向力按纯纵向算,侧向力按纯侧向算,然后直接叠加。这个想法在物理上不成立。轮胎与地面的附着能力是有限的,可以想象成一个椭圆包络:纵向力占用的附着多,侧向能用的余量就少;反过来刹车过弯时,车速越高侧向力越大,能施加的制动力就越小。
这正是所谓"摩擦圆"或"附着椭圆"的本质。制动力分配策略、弯道ABS策略都建立在这个耦合关系之上,轮胎模型如果不反映这一点,后面做纵向-侧向联合控制策略开发时完全不可用。
4.2 G函数加权法:用余弦加权把纯工况力"打折"
Pacejka模型处理综合工况的核心思路不是重新拟合一整张二维曲面,而是在纯工况结果上乘一个衰减因子,也就是G函数。基本形式是:
Fx = Fx0 · Gxα(α)
Fy = Fy0 · Gyκ(κ)
这里的G函数通常也是魔术公式结构,比如:
Gxα = cos(Cxα · atan(Bxα · α))
Gyκ = cos(Cyκ · atan(Byκ · κ))
我特意选这个结构是有原因的:当自变量为0时,atan(0)=0,cos(0)=1,G函数恰好等于1,也就是说纯工况的力完全不变;当侧偏角或滑移率逐渐增大时,G函数从1开始单调下降,相当于按比例削弱纯工况力。这个巧妙的性质让综合模型在低速小侧偏时能平滑退化为纯工况模型。
实际PAC2002里面的G函数更复杂一些,分母里会多出归一化项,但原理完全一致。我在工程模型里常用简化版,参数少、代码清爽,只要数据范围不跑到太极端的地方,精度完全够用。
4.3 综合工况仿真发散的三个常见原因
把G函数加进去之后,仿真发散的概率一下子就上来了,我总结三个高频翻车点。
第一,G函数出现负值。cos(C·atan(B·x))在自变量很大的时候是有可能穿越零点的,一旦G变成负值,轮胎力方向反了,整车模型立刻震荡。解决办法是加边界保护,把G限制在0到1之间:
Gx = max(0, cos(Cxa * atan(Bxa * alpha_rad)));第二,滑移率定义切换引起的跳变。驱动和制动工况的滑移率定义不同,如果不统一处理,模型在油门松踩切换的时候力会跳变。我的做法是统一用一版定义,并在模块内部做平滑过渡。
第三,固定步长仿真时步长太大。综合工况两个G函数叠加上去,曲线梯度比纯工况陡,步长一大会漏掉峰值点。我把固定步长从1ms改到0.5ms后,模型震荡立刻缓解。实时性允许的情况下,尽量先加密步长验证模型稳定性,再逐步放宽。
5. 参数从哪来:数据集、辨识流程与拟合避坑
5.1 参数获取渠道
很多同学卡在"公式我懂了,但参数去哪找"。市面上轮胎模型的参数来源大概有四条路径:
- 轮胎制造商提供的试验数据或MF参数文件,这是精度最高的来源。
- Carsim、Adams等商业软件自带的轮胎参数示例文件,比如扩展名为tir的PAC2002参数文件,可以直接读出来参考,但注意版权和使用边界。
- Pacejka专著《Tyre and Vehicle Dynamics》附录中公开的参数表,适合起步验证模型。
- 自己搭胎架试验或用高精度轮胎模型生成虚拟试验数据,再反向辨识。
我自己做预研的时候用的是第三条路径,先确保模型框架没问题,再等有台架数据后进实验室精修。
5.2 先粗后精的四步辨识流程
拿到一堆试验散点数据后,不要直接扔给优化算法硬啃。魔术公式参数辨识最稳的是分步走,每步只解少量未知数。
第一步,估算D。直接取试验曲线峰值附近的值,峰值力除以对应载荷就是D的初值。第二步,估算BCD。看原点附近曲线的斜率,B·C·D就是这个斜率,所以B = 斜率/(C·D)。第三步,估算C和E。C通常在一个窄区间里波动(纵向约1.65,侧向约1.30),E决定曲线回落趋势,可以先用手调几个值看趋势。第四步,把前三步的结果当作初始值,用非线性最小二乘整体优化。
我用lsqcurvefit做过一个最小二乘辨识的例子,代码思路如下:
% x = [B, C, D, E] fun = @(x, s) x(3) * sin(x(2) * atan(x(1) * s - x(4) * (x(1) * s - atan(x(1) * s)))); x0 = [12, 1.65, 4800, 0.5]; % 初始值 lb = [5, 1.0, 1000, -1]; % 下界 ub = [30, 2.0, 9000, 2]; % 上界 x_opt = lsqcurvefit(fun, x0, s_data, Fx_data, lb, ub);这里务必注意:一定要给参数设置合理的上下界。魔术公式这套函数存在多个局部最优解,不给约束直接优化很容易收敛到一个错误谷底。
5.3 拟合中最容易翻车的三个细节
第一,量纲。Fz你用N还是kN,α你用deg还是rad,力你用N还是kN,差一个数量级整个优化结果全错。我的习惯是内部统一SI单位,N、m、rad,只在与外部接口交互时做单位换算。
第二,数据覆盖不足。如果只有小侧偏角数据,拟合出的E毫无意义,外推到大侧偏时曲线随便飞。一定要确保试验数据覆盖你要仿真的全部工况范围,尤其是饱和段。
第三,初值离谱。lsqcurvefit这类算法对初值很敏感,别指望黑箱自动收敛。我是按照"峰值估D-斜率估B-经验定C-调试定E"的顺序手动粗调一轮,再交给优化算法精修,收敛速度快且结果物理上更合理。
6. 把轮胎模型接进整车控制器:联合仿真、外部模式与代码生成
6.1 整车信号流与代数环处理
轮胎模型在整车模型里处于信号流的中游:从车辆运动状态计算出滑移率和侧偏角,喂给轮胎模型,得到Fx、Fy,再反馈给车身模型更新加速度和速度。即:
Vx、Vy、ω → κ、α → 轮胎力Fx、Fy → 整车加速度 → 速度积分 → 再回到滑移率计算
这个回路意味着存在代数环。如果直接用硬反馈连接,Simulink在每个步长内都要迭代求解,模型一复杂就容易收敛慢甚至报错。我的工程化做法是在反馈路径上加一个Memory模块或者Unit Delay,把轮胎力反馈延迟一拍。只要步长足够小,延迟一拍引入的误差完全可以忽略,但模型稳定性和编译速度大幅提升。
6.2 与Carsim联合仿真的两个套路
Carsim和Simulink联合仿真是车辆动力学开发中非常经典的配置。和Carsim联合时,我用过两种不同的套路。
第一种,Carsim作为车辆环境提供车身运动状态和车轮转速,把魔术公式轮胎模型放在Simulink侧计算轮胎力,然后再把力返回给Carsim更新车辆运动。这种方法可以把自研轮胎模型嵌入到成熟的整车动力学环境中,适合做轮胎参数影响研究。
第二种,Carsim本身的虚拟轮胎作为高精度参考模型,Simulink侧同时运行我的魔术公式模型,两者在相同工况下做对比验证。这是一种非常好的模型确认方式,能直观看到简化模型与商业精细模型的偏差,做到心里有底。
联调过程中最容易出问题的就是接口变量命名和单位不匹配。我自己的习惯是先在Carsim的I/O通道列表里把输出输入变量全部导出成CSV对照表,确认单位、符号方向、更新频率之后,再在Simulink里建Bus信号,这样能省掉大半天的联调时间。
6.3 外部模式与C代码生成的工程化注意点
做控制算法开发的同学还会用到Simulink外部模式:模型跑在目标机或快速原型硬件上,通过外部模式通信在宿主机实时调参。魔术公式轮胎模型的B、C、D、E非常适合作为可调参数,这样在实车测试或硬件在环时可以不停机地调整轮胎特性,观察整车响应。
再说C代码生成。Embedded Coder可以把MATLAB Function代码生成C代码,烧进控制器里做实时仿真。但有几个写法禁忌:不能用eval这类动态执行函数,不能使用可变大小数组,尽量避免persistent变量在多任务环境下的污染。我有一段代码就是因为用了可变数组,代码生成阶段直接报错,后来改成固定大小数组才编译通过。如果一开始就注意这些限制,MATLAB Function模块的代码生成体验是非常顺滑的。
最后再分享一个小技巧。在做多工况轮胎参数切换时,用Simulink的Bus对象配合参数组结构体,可以避免模型里到处是手工常量。把每一组轮胎参数定义成一个结构体数组,通过Mask参数选择索引,模型内部自动切换,UI干净,仿真失控的概率也小很多。这套工作流我前前后后用了几年,稳定性和可维护性都经得起考验,希望对正在啃轮胎模型的你也有帮助。