做车辆底盘控制或者自动驾驶路径跟踪的朋友大概率绕不开轮胎模型。最近我把Dugoff轮胎模型在Simulink里搭好再接上CarSim做联合仿真前前后后折腾了接近一周踩了不少坑。这篇就把整个搭建思路、信号流、公式细节和排查经验完整写出来。这套联合仿真模型解决的是这样一个问题CarSim自带的高精度轮胎模型通常是Pacejka魔术公式不能直接把轮胎力输出给你自己的控制器而纯Simulink里自己写整车模型又往往太简化。Dugoff轮胎模型介于两者之间——公式简单、参数少、物理意义清楚特别适合做基于模型的控制算法开发。把CarSim当成整车动力学提供者把Simulink里的Dugoff模块当成轮胎力计算器两头一接控制算法需要的关键变量就全都有了。如果你在搞车辆稳定性控制、底盘控制或轨迹跟踪这篇文章的模型和排坑经验可以直接抄。我会把搭建步骤写得比较完整新手可以按步骤复现老手可以直接看第五章的常见问题基本覆盖了联合仿真最容易翻车的几个点。1. 为什么是Dugoff轮胎模型先想清楚再动手1.1 选型背后的三个理由轮胎模型选型这件事第一步不是看哪个公式精度最高而是先想清楚你这套仿真到底要拿来干什么。如果目的是做整车操稳性分析CarSim内置的Pacejka魔术公式肯定是对的它基于大量试验数据拟合横向纵向精度都够。但如果你的目的是开发控制算法比如ESP、TCS、轨迹跟踪控制器那Pacejka就有点“过于沉重”了。Dugoff模型的核心优势是三个第一计算简单。整个模型只有加减乘除、开方和一次条件判断没有三角函数表也没有大量拟合系数。在Simulink里跑一个步长内四个轮的轮胎力计算开销几乎可以忽略。将来要生成C代码上快速原型这种纯代数表达非常友好。第二参数少。整个模型需要标定的参数就四个纵向刚度Cx、侧偏刚度Cα、路面附着系数μ和滚动半径R。相比Pacejka动辄几十个拟合系数这四个参数都能从常规轮胎数据里查到或者估算。对做控制的人来说参数越少模型越可控。第三自带轮胎饱和特性。Dugoff模型的修正系数f(L)非常巧妙地描述了轮胎接近附着极限时的行为——纵向力和侧向力不再线性增长而是互相制约形成附着椭圆。这在极限工况控制策略验证里非常关键。如果你用纯线性轮胎模型车辆快要失控时控制器看到的轮胎力还在线性增长那基于这个模型设计的控制器在极限工况下就是个瞎子。1.2 与魔术公式、线性模型的取舍模型参数数量精度实时性控制器友好度适用场景Pacejka魔术公式大量拟合系数高中低表达式复杂难求导高精度整车动力学分析Dugoff模型Cx、Cα、μ、R共4个中高高高解析表达式带饱和控制算法开发与实时仿真线性模型2-4个低高高但无饱和常规工况非极限工况在CarSim联合仿真的场景里我自己更倾向于把Dugoff当成“控制算法内部模型”把CarSim当成“被控对象真值”。也就是说CarSim内部用它的高精度轮胎算车怎么跑你的控制器里用Dugoff模型预测轮胎力两者对比控制效果好说明你的算法对模型误差有鲁棒性。反过来如果你直接用CarSim输出轮胎力来喂控制器那你验证的控制器等于“作弊”了因为它拿到了真实对象的信息。所以这篇联合仿真的正确打开方式是CarSim里关闭内部轮胎力改用外部Dugoff模型算出的力来驱动整车。这样你的控制算法在Simulink里看到的所有力和运动状态都来自同一个模型构建了一个完全一致的控制闭环。1.3 数学表达与符号定义Dugoff模型的完整计算公式如下sigma_x (omega * R - Vx_wheel) / Vx_wheel % 纵向滑移率制动时为负 sigma_y tan(alpha) % 侧向滑移量 S sqrt((Cx * sigma_x)^2 (Calpha * sigma_y)^2) % 综合滑移强度 L mu * Fz * (1 sigma_x) / (2 * S) % 无量纲饱和因子 f_L L * (2 - L), L 1 f_L 1, L 1 Fx Cx * sigma_x / (1 sigma_x) * f_L Fy Calpha * sigma_y / (1 sigma_x) * f_L式子里涉及的物理量再展开解释一下omega是车轮旋转角速度单位rad/s乘以滚动半径R变成等效纵向速度。制动时omega*R Vx所以sigma_x为负对应的Fx也是负值表示制动力这符合直觉。alpha是轮胎侧偏角单位rad。侧偏角由轮心处速度方向与轮胎指向的夹角决定tan(alpha)直接作为侧向滑移量进入模型。Fz是车轮垂直载荷单位N。就是轮胎压在地面上的力这个量很重要因为它直接出现在饱和因子L的分母里。Fz越大轮胎能提供的最大附着力越大越不容易饱和。mu是路面附着系数。干沥青大约0.8-0.9湿滑路面0.3-0.5冰雪路面可能低到0.1-0.2。有一个细节特别容易踩坑公式中S表达式的分母当sigma_x和alpha同时为0时S为0计算L会除零。车辆静止或匀速直线行驶时正好是这个状态。解决方法是加上一个极小量保护比如S max(S, 1e-3)或者干脆设一个速度门限当轮心速度小于0.5m/s时直接把轮胎力置零。2. 联合仿真总体架构轮胎力从哪来到哪去2.1 CarSim和Simulink各干各的活做联合仿真之前先要把“分工”理清楚。CarSim负责的是整车的运动学与动力学解算车身六个自由度、悬架运动学、转向系统、驾驶员模型、路面和障碍物定义以及最后的三维动画。Simulink这边负责的是控制算法和自定义模型——这次的核心是Dugoff轮胎力计算模块。在这套架构里CarSim的轮胎模型被设置成外部模型。也就是说CarSim不再自己算轮胎与地面的作用力而是等着Simulink把四个轮的Fx、Fy送进来再把这些力施加到车体上算出车辆接下来往哪儿跑。这样做的最大好处是控制算法和轮胎模型在同一个Simulink环境里状态变量没有跨工具的数据壁垒调试起来非常舒服。2.2 信号流设计完整的信号流可以这样概括CarSim输出给Simulink的信号整车纵向速度Vx和侧向速度Vy每个车轮的轮心纵向速度Vx_wheel和侧向速度Vy_wheel每个车轮的角速度omega每个车轮的垂直载荷Fz路面附着系数mu如果道路有变化Simulink根据这些输入利用Dugoff公式算出每个车轮的纵向力Fx和侧向力Fy再送回给CarSim作为外部轮胎力的输入。这里有一个很容易忽视的问题滑移率的计算到底用轮心速度还是整车速度我强烈建议用CarSim输出的轮心速度。因为转向和横摆时四个轮的轮心速度差别很大——外侧轮快、内侧轮慢转弯时外轮滑移率天然和内轮不一样。如果统一用整车Vx计算侧偏角和滑移率都会失真尤其在双移线这种大幅度转向工况下误差会直接反映到轮胎力上。2.3 坐标系与符号约定坐标系问题是我这次联调当中花时间最多的一个点。CarSim的车辆坐标系是ISO标准的右手系X轴向前Y轴向左Z轴向上。在这个坐标系下纵向力Fx向前为正制动力为负侧向力Fy向左为正。Dugoff模型算出来的轮胎力尽管数学上是沿着滑移方向的实际输出到CarSim之前还是要仔细对一次符号。一个最直接的验证方法直线制动工况四个轮的Fx应该都是负值车速应该下降。如果仿真结果显示出速度不降反升或者车辆自动加速不用怀疑符号反了去模型里把Fx输出加个负号。侧偏力的符号也一样。让车辆有一个向左的侧偏角比如方向盘轻微左打左前轮产生的侧向力应该向右即Fy为负因为轮胎要抵抗侧偏。如果你发现Fy方向和侧偏角方向一致了那说明公式里sigma_y的符号或者CarSim输出信道的正负定义有冲突需要统一。2.4 步长与解算器配置联合仿真跑起来之后步长选多少直接影响稳定性和运行速度。我实测的经验值如下配置项推荐值说明Simulink求解器ode4固定步长不建议用ode45变步长CarSim的S-Function是混合系统变步长容易出问题仿真步长1ms常规工况足够低附着路面建议降到0.5msCarSim通信步长与Simulink一致在CarSim的Run Control里设置低速门限Vx_wheel 0.5m/s轮胎力强制置零防止除零步长这个参数看似是小事但实际影响非常大。1ms步长跑双移线工况整车轨迹和0.5ms步长的差别很小但一旦路面附着系数降到0.3以下车辆进入极限工况轮胎力变化剧烈1ms就开始出现数值抖动。如果你在低附着仿真中看到车辆的横摆角速度高频振荡先别急着怀疑模型把步长改成0.5ms试试。3. Simulink端搭建Dugoff轮胎模型的实操过程3.1 顶层模型组织我习惯把顶层模型拆成几个清晰的功能块CarSim S-Function模块、Bus Selector信号提取、四个独立的Dugoff轮胎子系统、以及输出信号汇总。这样做的目的是将来好维护——如果你想对比Pacejka和Dugoff只需把Dugoff子系统换成另一个轮胎模型其余不动。四个轮胎子系统必须独立不能一个模块算四次因为每个轮的垂直载荷、滑移率、侧偏角都不一样。我建议把Dugoff模块封装成Masked Subsystem参数直接填在Mask里比如前轮Cx 60000 N 前轮Calpha 85000 N/rad 滚动半径R 0.325 m每个轮实例化一次填对应参数。3.2 车速与滑移率计算细节滑移率的计算在Bus Selector提取信号之后做一个子模块来完成。这里推荐自己写公式计算滑移率和侧偏角不要直接用CarSim内部输出的轮胎滑移率通道。原因是CarSim输出的滑移率符号定义和Dugoff公式要求的不一定完全一致不同版本之间也有差异自己算一遍最保险。omega_eff omega * R; kappa (omega_eff - Vx_wheel) / Vx_wheel; alpha atan2(Vy_wheel, Vx_wheel);轮心速度和车轮角速度都从CarSim模块的输出总线里取。注意atan2而不是atan这样可以保留侧偏角的正负号信息。如果只用atan(Vy/Vx)在侧向速度方向变化时角度符号会丢失低速时尤其明显。这里还有一条重要经验低速保护一定要放在滑移率计算之前。我第一版模型没做这个保护车辆原地静止起步那一刻Vx_wheel是0算出来的kappa是无穷大NaN整个仿真直接崩了。后来加了门限判断Vx_wheel小于0.5m/s时把kappa和alpha都强制设成0轮胎力输出0问题才解决。3.3 垂直载荷的处理方式垂直载荷这个量在CarSim联合仿真里最好直接用CarSim输出的动态Fz。CarSim已经把静态载荷、俯仰转移、侧倾转移、悬架几何等全部考虑进去了精度比你自己搭公式高得多。如果你的CarSim版本找不到动态Fz输出我给出一个常用的估算公式做后备方案Fz_fl m * g * Lr / (2*L) - m * ax * h / (2*L) - m * ay * h / (2*tf) Fz_fr m * g * Lr / (2*L) - m * ax * h / (2*L) m * ay * h / (2*tf)其中m是整车质量g是重力加速度L是轴距Lr是质心到后轴距离h是质心高度tf是前轮距ax和ay是纵向和侧向加速度。注意最后一项的正负号要跟转向方向匹配。左侧轮在右转时载荷减小右侧轮增大这个方向别搞反。不过再次强调能直接从CarSim拿到动态Fz就用CarSim的自己做公式只是为了应对没有信号的情况。3.4 修正系数与输出限幅Dugoff模型里最容易引起数值问题的地方就是修正系数f_L的切换。L1这个地方是一个折角模型从线性区平滑过渡到饱和区理论上没问题但数值积分时如果步长偏大或者周围模块对导数比较敏感折角处可能引起高频抖动。我实际处理办法是给f_L增加一点平滑处理。不一定要用复杂的平滑函数简单的饱和限幅加一阶低通滤波就够了L_limited max(L, 0); % 防止负值 f_L L_limited * (2 - L_limited); f_L min(f_L, 1); % 饱和限幅 f_L lowpass(f_L, 30Hz); % 一阶低通滤掉高频抖动这个低通滤波的截止频率要选好太低了会拖慢轮胎力响应太高了起不到滤波作用。我一般从20Hz开始试根据仿真结果调整。对于普通的底盘控制仿真30Hz左右是个不错的起点。3.5 前后轮参数差异前后轮因为载荷和规格不同Cx和Cα不能取同一个值。我参考的是一辆1.5吨轿车的典型数据参数前轮后轮Cx纵向刚度55000N48000NCα侧偏刚度82000N/rad70000N/rad滚动半径R0.32m0.32m单轮静态Fz约4300N约3800N这个数据不是绝对的不同车型、不同轮胎差异很大。你可以先用一个合理的初值让模型跑起来再根据仿真曲线微调。判断的标准很直观同样的方向盘转角输入下车辆横摆角速度和侧向加速度是否符合直觉。4. CarSim端配置与接口对接4.1 车辆模型选择与外部轮胎开关CarSim端配置是整个联合仿真的另一个大头。以我常用的CarSim 2019版为例进入车辆动力学模型后在轮胎设置页面需要把轮胎模型切换成外部模型。这一步非常关键如果没切换成功CarSim内部默认的轮胎模型也在算力外部Simulink的力又往车上叠一遍轮胎力就重复了仿真结果必然离谱。切换成外部模型后CarSim的Import通道会自动出现四个轮的外部力输入变量通常是这样命名的IMP_FX_L1 / IMP_FY_L1 / IMP_MZ_L1 % 左前轮 IMP_FX_R1 / IMP_FY_R1 / IMP_MZ_R1 % 右前轮 IMP_FX_L2 / IMP_FY_L2 / IMP_MZ_L2 % 左后轮 IMP_FX_R2 / IMP_FY_R2 / IMP_MZ_R2 % 右后轮不同版本命名可能略有差异但规律都是把L1/R1/L2/R2当作四个车轮的代号。搜索“External Tire”或“IMP_FX”应该能定位到相应配置页。4.2 导入导出信道设置在CarSim的I/O Channels页面需要把下面这些信号加到Export输出列表里输出信号用途Vx / Vy整车速度Vx_wheel_L1/R1/L2/R2各轮轮心纵向速度算滑移率Vy_wheel_L1/R1/L2/R2各轮轮心侧向速度算侧偏角omega_L1/R1/L2/R2各轮角速度Fz_L1/R1/L2/R2各轮垂直载荷mu_L1/R1/L2/R2路面附着系数这些量在CarSim里的具体通道名不同版本不太一样最稳妥的办法是在Export列表里搜索关键词比如搜“wheel speed”“omega”“Fz”等。找到对应通道拖到列表里即可。4.3 生成Simulink模型的标准流程配置完成后开始生成联合仿真模型。标准流程是在CarSim的Run Control页面设置仿真时长和Simulink里的仿真时长一致。确认求解器配置为固定步长步长选1ms。点击“Send to Simulink”按钮CarSim会生成对应的Simulink模型并自动打开。生成的模型里有一个CarSim的S-Function模块双击可以加载parfile。把S-Function的输出总线用Bus Selector拆开提取需要的信号。将处理后的信号接入你的Dugoff轮胎模型。把Dugoff模型的四个轮Fx/Fy输出接回到CarSim S-Function模块的输入端口。这个流程每一步都有坑但最关键的还是第5步和第7步。信号接错顺序或者接错端口仿真能跑但结果完全不对。4.4 启动顺序与参数初始化联合仿真的启动顺序也有讲究。我推荐的操作是先打开CarSim GUI确认车辆参数和I/O配置都没问题点击“Send to Simulink”生成模型再在Simulink里运行仿真。如果你直接打开一个之前生成过的Simulink模型而不经过CarSim的Send步骤S-Function里加载的parfile可能和当前CarSim工程的参数不一致仿真结果不是你想要的。还有一个容易忽略的问题工作目录不能有中文或者特殊字符。CarSim生成临时文件和编译S-Function时路径带中文会直接报错。尽量把整个工程放到纯英文路径下比如D:/Simulation/Dugoff_CarSim/。5. 联调常见问题与排查经验5.1 Bus Selector没有可选信号热词“simulink bus selector 没有可选信号”被问得非常多我自己也撞到过。症状是双击Bus Selector模块想选需要的信号结果输入总线的信号列表是空的。最可能的原因有三个第一CarSim生成的S-Function模块没有被正确初始化总线对象没有加载到MATLAB工作区。解决方法是重新运行CarSim的Send步骤或者手动执行CarSim自带的脚本load_ctrl_parfile.m之类的初始化脚本。第二换了MATLAB版本后总线对象丢失。这个只能重新生成模型没有别的办法。第三CarSim模块输出端口的信号类型不是总线而是普通向量。检查一下S-Function模块的输出端口参数确保它使用的是Bus Object。5.2 一运行就NaN这个问题的典型表现是仿真刚启动还没跑到0.1秒车速直接变成NaNSimulink报错。原因十有八九是低速除零。车辆静止时Vx_wheel0滑移率公式里分母为0kappa变成无穷大NaN然后一路传给Dugoff模型整个仿真链全崩。解决思路很明确在滑移率计算模块前面加一个低车速保护逻辑。Vx_wheel的绝对值小于0.5m/s时直接把kappa和alpha置零对应的轮胎力输出也为零。等车速超过0.5m/s再正常计算。这里有一点要注意不要把门限设得太高否则车辆在低速蠕行时轮胎力一直是0起车过程的仿真结果就不对了。5.3 轮胎力方向反了或者左右轮搞混了轮胎力方向反了的排查方法前面已经提过直线制动验证。这里再说一个检查左右轮的技巧。在CarSim的3D动画里做一次方向盘阶跃输入比如0.5秒内方向盘打到90度然后分别查看四个轮的Fx和Fy随时间的变化曲线。右侧车轮和左侧车轮在转向时侧偏角方向是相反的所以Fy的符号也应该相反。如果发现四个轮的Fy符号完全一致那就是车轮编号搞混了。5.4 动画里车轮箭头显示不对CarSim动画里的车轮箭头其实是力的可视化。如果你用了外部轮胎模型箭头默认显示的可能还是内部的计算量看起来就会和Simulink里算出的力对不上。解决办法是在3D动画的显示设置里把力箭头的显示源切换到外部力通道。不同版本的菜单名称有差异一般搜“Force Arrow”或“External Tire Force”就能找到。还有一个细节箭头显示的力大小和方向受缩放比例影响经常出现“箭头巨大”或者“几乎看不见”的情况。在动画设置里调整Force Scale参数让箭头长度适中。5.5 高附着转低附着瞬间发散把路面附着系数从0.85突然切到0.35时仿真很容易发散。原因是Dugoff模型的饱和因子L对mu的变化非常敏感mu跳变瞬间轮胎力突变车辆动力学状态出现脉冲激励。我惯用的处理方式是对mu做渐变过渡而不是阶跃切换。比如在Simulink里用一个斜坡信号模块让mu在0.3秒内从0.85线性降到0.35。这样更接近真实路面变化也能有效避免数值发散。如果你的道路场景必须在某个位置突然变得很滑那就把仿真步长进一步缩小到0.5ms。5.6 问题排查速查表现象可能原因排查手段Bus Selector空列表总线对象未加载重新Send to Simulink启动即NaN低速除零加低速门限保护车速曲线异常轮胎力符号反直线制动验符号动画箭头不对显示源设错切换力箭头显示源低附着发散mu跳变导致mu渐变替代阶跃编译报错路径含中文全英文工作目录6. 结果验证与工况设计6.1 先做单元验证再联调我强烈建议在把Dugoff模型接入CarSim之前先在Simulink里单独做一次开环测试。方法很简单给Dugoff模型固定一组Fz和mu然后让滑移率从-0.3扫描到0.3侧偏角分别设0度、5度、10度把所有输出曲线画出来。你会发现典型的Dugoff特性滑移率绝对值较小时纵向力近似线性增长超过一定范围后Fx进入饱和平台不再增加。侧偏角和纵向力同时存在时总力会被“附着椭圆”限制。这些曲线就是你联调之后判断仿真结果是否合理的参考基准。6.2 双移线工况验证联调完成后第一个验证场景我建议做ISO双移线或者简单的单移线工况。双移线的好处是既有纵向加减速又有大幅横向变道轮胎力变化剧烈能充分检验模型是否正确。观察指标主要是三个车辆横向位移轨迹、横摆角速度、侧向加速度。对比CarSim内置轮胎模型和Dugoff外部轮胎模型的仿真结果两者整体趋势要一致峰值横向加速度差异在10%-20%以内都算正常。如果差异非常大优先检查Cx和Cα的取值是否合理其次检查垂直载荷的符号。6.3 不同附着路面下的表现对比模型调通之后一定要做一组不同附着系数的对比。干沥青mu0.85和湿滑路面mu0.35分别跑同一个双移线工况。干沥青路面上车辆能够顺利完成双移线横摆角速度跟得上方向盘输入湿滑路面上车辆侧偏角明显加大横摆响应滞后如果车速足够快车辆会在第二个弯道出现过度转向的趋势。这一组对比结果非常直观地说明Dugoff模型的饱和特性是否起作用了。如果两个附着系数下的结果几乎一样多半是mu没有真正接到模型里检查一下mu信号是否从CarSim输出正确传到了Simulink。6.4 后续可扩展方向这套模型跑通之后扩展空间非常大。一个很自然的方向是路面附着系数在线估计。Dugoff模型的mu作为独立输入完全可以把它当成待估计的状态量用扩展卡尔曼滤波或者递推最小二乘来辨识。还有一个方向是直接和底盘控制算法闭环——把Dugoff模型算出的轮胎力作为前馈项叠加到ESP或者MPC控制器里能明显改善低附着路面的控制效果。如果你有快速原型的需求Dugoff模块因为只用到代数运算用Simulink Coder生成C代码非常简单可以直接部署到实时硬件上做HIL测试。但要注意CarSim的S-Function模块本身不建议生成C代码进实时机联调模型和实时模型最好分开维护。这套模型我在项目里反复用了很多次最直观的感受是Dugoff模型让你终于知道你Simulink里那套控制算法看到的轮胎力是怎么来的而不是一个黑盒。以后如果做紧急避障或者低附着路面稳定控制在这个基础上改起来会顺手很多。最后分享一个小经验把这个Dugoff模块做成子系统并留好mu输入口之后你无论是做附着估计还是变路面仿真都不用回来动核心算法。