ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于Carsim与Matlab Simulink的AEB联合仿真算法设计详解

基于Carsim与Matlab Simulink的AEB联合仿真算法设计详解

这两年智能驾驶开发圈里,AEB(自动紧急制动)基本成了ADAS入门必做的项目。学校里做课题、企业里做预研、甚至个人想搞一套完整的仿真验证链路,都绕不开Carsim与Matlab/Simulink这套组合。我最初接触这个方向的时候,也踩了不少弯路:要么只顾着调算法参数,要么一头扎进Carsim的车辆模型里出不来,真正把联合仿真跑通、把AEB逻辑闭环调稳,花的功夫远比想象中多。这篇就把我做“基于Carsim与Matlab Simulink的AEB联合仿真算法设计”这套模块化建模方案的完整过程拆开讲,从架构思路到算法实现、从接口配置到工况测试,全部梳理出来,给正在做联合仿真或者准备入坑AEB的朋友一个可直接复现的参考。

先交代一下这个方案解决的痛点。AEB算法开发不能只停留在纯数学推导层面,车辆在紧急制动时的俯仰、轮胎滑移、制动系统响应延迟,都会直接影响碰撞距离和减速度表现。如果只用简单的运动学模型,算出来的TTC和制动距离往往偏乐观,落地到实车就会出问题。Carsim提供高保真车辆动力学响应,Simulink承载AEB算法逻辑,两者联合起来,才能在仿真阶段就把动力学边界吃透。这也是为什么我坚持用联合仿真而不是纯Simulink建模的核心原因。

1. 为什么必须联合仿真:Carsim与Simulink的分工逻辑

1.1 AEB算法开发的仿真需求到底在哪

AEB系统的核心任务是:在检测到前方碰撞风险时,通过主动制动避免碰撞或减轻碰撞后果。这个任务听起来就是“距离近就刹车”,但真正实现起来,算法需要同时处理感知输入、危险评估、执行决策三个层面的问题。

感知输入层面,需要融合目标车辆的距离、相对速度、相对加速度等信息;危险评估层面,要在“过早制动造成误触发”和“过晚制动导致刹不住”之间找到平衡;执行决策层面,要有明确的减速度请求输出给车辆制动系统。这三个层面单独看都不复杂,但它们共同依赖一个关键前提——车辆在当前车速、当前路面条件下的真实制动响应是多少。

这就是Carsim的意义所在。Carsim内置了车身、悬架、轮胎、制动系统、转向系统等详细的动力学模型,能给算法提供一个接近真实的“被控对象”。我在实际测试中对比过:给同一个AEB算法分别接Carsim车辆模型和接简化运动学模型,同样的初始车速和距离,最终碰撞结果完全不同。Carsim模型里制动减速度会随着车速下降而衰减,轮胎附着力有边界,制动系统有响应延迟,这些细节直接决定了算法触发的边界条件要不要留安全余量。

1.2 模块化建模的核心价值

很多人在Simulink里开发AEB算法时,习惯把所有逻辑堆在一个大子系统里,信号线拉得密密麻麻。这种方式在单工况调试时勉强能跑,但一旦要扩展传感器模型、切换控制策略、复现不同车型参数,就会陷入“改一处动全身”的泥潭。

我采用的模块化建模方式,是把整个算法拆成四个独立层次:感知输入层、危险评估层、决策执行层、参数标定层。每个层次有明确的输入输出接口,层与层之间通过Simulink总线信号交互。这样做的好处有三个:

第一,可替换性强。感知输入层以后要接真实雷达数据或者换成毫米波雷达模型,只改这一层就行,危险评估和决策执行不需要动。

第二,标定效率高。所有阈值参数统一集中在参数标定层,用结构体管理。测试不同工况时,直接改标定文件,不用打开模型逐个查找。

第三,团队协作方便。不同层次可以由不同人并行开发,只要接口定义清楚,最后集成时的冲突会少很多。

这套模块化思路,我后来用在不同项目里也都成立。AEB只是起点,这套架构往FCW、ACC方向扩展,只需要替换危险评估层或者决策执行层的部分模块,整体框架完全能复用。

2. AEB算法核心:TTC计算与分级制动策略

2.1 TTC的计算与触发逻辑

AEB算法中最核心的危险评估指标是TTC(Time to Collision,碰撞时间)。它的原始定义是当前相对距离除以相对速度:

TTC = D / Vrel

D是本车与前车的相对距离,Vrel是本车相对前车的速度(本车更快时为正)。这个公式直观、计算量小,是AEB算法的基础。但我实测下来,直接用这个原始公式在真实场景中误报率偏高,原因在于它假设相对速度恒定,没有考虑本车加速度和前车加减速的影响。

实际项目中,我更推荐使用考虑加速度修正的TTC形式:

TTC = Vrel / (Arel) + sqrt((Vrel/Arel)^2 + 2D/Arel)

其中Arel是相对加速度。这个公式在相对加速度不为零时更准确,但要注意:当Arel接近于零时计算会发散,必须在代码里加保护条件。我在模型里用一个Switch模块判断|Arel|小于某个阈值时回退到原始公式,这样既保证稳定性又不牺牲精度。

TTC的触发逻辑需要结合车速分档处理。低速工况(比如低于30km/h)和前车静止,系统反应时间相对充裕,可以在TTC较小时触发;高速工况下制动距离更长,需要在TTC较大时就提前介入。我的做法是设计两套阈值——预警阈值和制动阈值,分别对应FCW功能(前方碰撞预警)和AEB主动制动。

2.2 分级制动策略与舒适性平衡

AEB不是一上来就全力制动。粗暴的全制动虽然碰撞概率最低,但会给驾乘人员带来强烈的冲击感,也会让后车追尾风险上升。合理的策略是分级制动。

我在这个项目中设计了三段式制动策略:

第一级是预警阶段。TTC达到预警阈值后,系统先输出声音报警信号,同时施加一个极小的预填充制动压力(比如0.2MPa),目的是消除制动间隙,为后续制动做准备。这一级不产生明显减速度,驾乘人员几乎感知不到。

第二级是部分制动阶段。TTC继续缩短达到部分制动阈值后,系统按照标定好的减速度曲线进行部分制动。减速度一般控制在2.5到4m/s²之间,这个区间既要保证明显的减速效果,又不至于让车辆姿态发生剧烈变化。

第三级是全力制动阶段。当TTC进入紧急区域且驾驶员仍然没有接管迹象时,系统输出最大制动减速度请求。这里要注意,最大减速度受到路面附着系数的限制。干燥沥青路面可以请求7到8m/s²,但湿滑路面如果把请求值拉满,车轮会抱死,反而延长制动距离。

为了解决这个问题,我在决策执行层集成了路面附着系数估算模块。一种实用的做法是利用ABS轮速信号和车身参考车速的差值估算滑移率,再根据滑移率反推当前路面的峰值附着系数,然后限制最大减速度请求。这套逻辑在Carsim里验证效果很好,仿真中设置湿滑路面工况后,AEB依然能在不抱死的前提下尽可能缩短制动距离。

2.3 用Simulink快速实现AEB状态机

AEB的逻辑具有明显的状态迁移特征:无风险、预警、部分制动、全力制动、碰撞后解除。用Stateflow实现状态机比纯逻辑判断清晰得多。

我的状态机设计如下:

State 0: Idle(无风险) 条件: TTC > TTC_WARN || Vrel <= 0 动作: 输出无制动请求 State 1: Warning(预警) 条件: TTC <= TTC_WARN && TTC > TTC_PARTIAL 动作: 输出报警信号+预填充压力 State 2: PartialBrake(部分制动) 条件: TTC <= TTC_PARTIAL && TTC > TTC_FULL 动作: 输出部分减速度请求,并随时间递增 State 3: FullBrake(全力制动) 条件: TTC <= TTC_FULL 动作: 输出最大减速度请求(受附着系数限制) State 4: Release(解除) 条件: Vrel <= 0.5 m/s 且相对距离开始增大 动作: 解除制动

这个状态机的关键细节是State 2向State 3的转移一定要快。部分制动阶段如果持续时间过长,实际车速已经下降很多,TTC的变化速率会比预期慢,全力制动的介入时机就晚了。我在这里用了一个持续计数器,当TTC持续低于部分制动阈值超过200ms就立即转移,防止信号抖动造成状态来回跳。

另外,State 4解除条件不能只看TTC。如果本车已经刹停但前车在缓慢移动,TTC可能仍然很小,但继续制动已经没有必要。所以解除条件要加上“相对距离开始增大”这条,确保碰撞已经规避。

3. 模块化Simulink模型搭建实录

3.1 接口定义:Carsim输入输出变量的映射关系

联合仿真的核心是搞清楚Carsim和Simulink之间的数据流方向。Carsim作为被控对象,接收Simulink发出的控制指令;Simulink中的AEB算法接收Carsim反馈的车辆状态。

我习惯把Carsim的输入输出变量定义成一个接口表,固定下来了再动模型。典型配置如下:

信号方向变量名含义单位
Simulink -> CarsimIMP_BRK_MASTER_CYL_PRESSURE制动主缸压力请求MPa
Simulink -> CarsimIMP_THROTTLE_ENGINE节气门开度(通常置0)percent
Carsim -> SimulinkVx_SM纵向车速km/h
Carsim -> SimulinkAx_SM纵向加速度m/s²
Carsim -> SimulinkStation_X_SM本车纵向位置m
Carsim -> SimulinkYaw_Rate_SM横摆角速度rad/s
Carsim -> SimulinkSteer_LF_SM前轮转角deg

这里有一个非常容易踩的坑:Carsim的输出车速默认是km/h,而Simulink中的TTC计算需要m/s,单位不一致会导致距离计算结果差3.6倍。我第一次联调时,TTC算出来始终偏大,排查了半天才发现是单位问题。现在我的做法是,在Simulink输入端口后统一加一个单位转换模块,把km/h转成m/s,后续所有计算都用国际单位制。

另外一个要注意的是制动压力的接口。Carsim的制动模型接受主缸压力作为输入,但AEB算法计算出的通常是减速度请求,中间需要做一次转换。转换公式为:

P_brake = a_request * m_vehicle / (K_brake * BRK_EFF)

其中P_brake是主缸压力,a_request是减速度请求,m_vehicle是整车质量,K_brake是制动效能系数,BRK_EFF是制动效率。这些参数都放在参数标定层中,通过Carsim的车辆参数读取,不写死。

3.2 感知层、决策层、执行层的解耦设计

感知层在真实车辆中对应的是毫米波雷达或激光雷达输出。在仿真环境中,我直接使用Carsim输出的目标车辆信息(在Carsim中配置跟随前车场景时会输出前车位置、速度等)加上一个理想传感器模型模块。

理想传感器模型的意义在于模拟信号延迟和噪声。实际雷达的测量周期一般是50ms,数据还有高斯噪声。在感知层中加入一个Transport Delay模块(延迟50ms)和Band-Limited White Noise模块,这样AEB算法在仿真中就能提前暴露真实传感器带来的问题。我测试过,不加噪声时TTC计算曲线非常平滑,加上噪声后触发时刻会有几十毫秒的抖动,这直接影响了不同的延误和误报概率。

决策层是AEB算法的核心,包含TTC计算模块、危险评估状态机和制动策略生成模块。这一层只接受感知层的处理结果,不直接读取Carsim的原始信号。感知层输出的目标距离、相对速度已经经过滤波和单位转换,决策层的职责就是纯粹的逻辑判断。

执行层负责把决策层输出的减速度请求转换为Carsim可接受的指令信号,并加上斜率限制器。斜率限制器很关键:如果减速度请求直接从0跳到8m/s²,车辆模型会出现明显的俯仰震荡,这在实车上会严重损害乘坐舒适性。我设置的默认斜率为5m/s³,即从0加速到8m/s²需要1.6秒。在紧急工况下可以放宽到8m/s³,但不能再高。

3.3 参数标定层的设计思路

参数标定层不参与实时计算,它只是一个包含所有可调参数的Simulink结构体参数空间。我的做法是,在模型初始化回调函数中加载一个.m文件,里面定义各种参数:

% AEB参数定义文件 % —— 基础参数 veh.mass = 1700; % 整车质量 kg veh.brakeEff = 0.8; % 制动效率 % —— TTC阈值参数 aeb.TTC_WARN = 2.8; % 预警TTC阈值 s aeb.TTC_PARTIAL = 1.8; % 部分制动TTC阈值 s aeb.TTC_FULL = 0.8; % 全力制动TTC阈值 s aeb.MIN_VREL = 2.0; % 最小相对速度阈值 m/s % —— 制动请求参数 aeb.a_partial = 3.0; % 部分制动减速度 m/s^2 aeb.a_full = 8.0; % 全力制动减速度 m/s^2 aeb.a_rate = 5.0; % 减速度斜率 m/s^3 % —— 传感器参数 sens.radarPeriod = 0.05; % 雷达周期 s sens.radarDelay = 0.05; % 雷达延迟 s sens.noiseSigma = 0.1; % 测距噪声标准差 m

这样设计的好处非常明显:标定工程师不需要打开Simulink模型,不需要懂算法逻辑,只需要改.m文件里的数值,就能调整AEB系统的表现。我做的某次测试中,要把同一套算法从轿车适配到SUV车型,只改了整车质量和制动效率两个参数,模型结构完全没动。

这里还要提醒一个细节:参数命名要带模块前缀。aeb开头的参数属于危险评估层,sens开头的属于感知层,veh开头的属于车辆参数。这样在模型里看信号线标注时,一眼就能看出参数来源,排查问题时不会混乱。

4. Carsim与Simulink联合仿真配置与工况测试

4.1 Carsim S-Function的生成与配置

Carsim和Simulink联合仿真的标准方式是生成S-Function。具体步骤是:

第一步,在Carsim中建立或选择车辆模型,配置好仿真工况(包括本车初始车速、目标车辆状态、路面附着系数等)。

第二步,选择Simulink联合仿真接口,Carsim会生成一个包含S-Function的Simulink模型模板,这个模板里面预设了输入输出变量映射。

第三步,把Carsim生成的S-Function模块复制到自己搭建的AEB模型里,替换掉原来的车辆数学建模部分。保持接口名一致,算法模型不用做任何修改。

这里有一个关键配置项——S-Function的采样时间。Carsim的内部仿真步长一般设置为0.001s,但S-Function模块在Simulink中的采样时间可以设置得更大,比如0.01s。我建议保持Carsim内部步长不变,Simulink中S-Function采样时间设置为0.01s或0.005s,这样仿真速度与精度比较平衡。注意,Simulink的主步长必须与S-Function采样时间匹配,否则会产生代步误差。

还有,Carsim的模型文件路径不能包含中文和空格。这个坑我已经踩过很多次,一旦路径有问题,S-Function初始化就会报错,而且报错信息往往不直接提示路径问题,排查起来很折磨。现在我的项目目录一律用英文小写加下划线命名。

4.2 测试工况选择与测试矩阵

AEB算法验证不能只跑一种工况。按照行业标准里的测试场景要求,至少要覆盖三类目标车状态和多个车速组合。我整理的测试矩阵如下:

工况编号本车初始速度目标车状态路面条件预期结果
TC-0130 km/h静止干燥沥青完全避免碰撞,最小距离 > 0
TC-0250 km/h静止干燥沥青完全避免碰撞,最小距离 > 0
TC-0380 km/h静止干燥沥青完全避免碰撞或碰撞速度 < 10 km/h
TC-0450 km/h匀速 20 km/h干燥沥青完全避免碰撞,不与前车距离小于0.5m
TC-0580 km/h匀速 40 km/h干燥沥青完全避免碰撞,最小相对距离 > 1m
TC-0650 km/h减速 8m/s²干燥沥青完全避免碰撞
TC-0750 km/h静止湿滑沥青避免碰撞或碰撞速度尽量低
TC-0830 km/h静止冰雪路面避免碰撞或碰撞速度尽量低

每个工况至少重复三次仿真,对比结果的一致性。Carsim的仿真本身是确定性的,但加入传感器噪声后,每次仿真的触发时刻会有细微差异,这正好可以验证算法的鲁棒性。

4.3 数据记录与结果分析

在Simulink中,我通过Signal Logging记录关键信号:TTC计算值、AEB状态、制动压力请求、本车速度、本车加速度、相对距离、碰撞指示标志。仿真结束后,用一个简单的脚本自动生成指标报告:

% 指标计算脚本摘要 % 1. 最小相对距离:min(relDist) % 2. 碰撞速度:如果 relDist < 0,取碰撞时刻本车速度 % 3. 最大减速度:max(abs(a_request)) % 4. AEB介入时刻:state从Idle变为Warning的时刻 % 5. 制动距离:从AEB介入到车速为零行驶的距离

实测下来,TC-02工况(50km/h对静止目标车)的结果最有代表性。在干燥沥青路面,AEB从预警到全力制动介入的时间大约0.9秒,最小相对距离保持在25厘米左右,最大减速度约8.4m/s²,整个制动过程车辆无抱死现象。

TC-07工况(50km/h对静止目标车,湿滑路面)则展示出路况修正的作用:如果没有附着系数限制,算法会请求8m/s²的减速度,车轮很快抱死,车辆进入滑移状态,实际减速度只有4m/s²左右,最终碰撞速度达到15km/h;加入附着系数修正后,算法把请求减速度限制在4.5m/s²以内,车辆全程处于稳定制动区间,碰撞速度降低到8km/h。这就是为什么我说“最大减速度”参数绝对不能写死。

5. 联调常见问题与避坑清单

5.1 Carsim模型修改后Simulink不更新

这是我遇到最多的问题。在Carsim中修改了车辆参数或工况,回到Simulink重新运行,结果仿真结果没有任何变化——这通常是因为Carsim的S-Function缓存没有刷新。

解决办法是清理Simulink的缓存并重新生成S-Function。在Matlab命令行执行:

clear all; close all; clc; busyCounter = 0; % 清理函数缓存 delete(findall(0,'Type','block','Name','PPCarsim')) bdclose all;

然后重新打开模型运行。另外一个常用技巧是,在Carsim中重新点一次Send to Simulink按钮,覆盖生成S-Function文件,确认文件的时间戳是最新的。

5.2 仿真步长不匹配导致结果抖动

如果Simulink主步长与Carsim S-Function采样时间不匹配,刹车压力曲线会出现锯齿状抖动,TTC计算也会产生高频振荡。尤其是当Simulink使用变步长求解器时,Carsim S-Function的固定采样周期可能与求解器自适应步长产生冲突。

我最终使用的配置是:Simulink求解器选择固定步长(Fixed-step),步长设为0.01s,Carsim内部步长保持0.001s,S-Function采样时间设为0.01s。这样在10ms的算法周期内,Carsim已经完成了10次动力学计算,精度足够,仿真速度也在可接受范围。

5.3 AEB频繁误触发

在加入传感器噪声后,AEB偶尔会在明显没有碰撞风险的情况下进入预警状态。排查后发现,问题出在TTC计算时相对速度接近零的情况。当Vrel很小时,TTC计算值会瞬间变成非常大的数,或者变成负数,导致状态机做出错误判断。

解决方法是加入最小相对速度阈值判断:当Vrel小于2m/s时,认为不构成追尾风险,不触发AEB。同时,在状态机中引入持续条件确认——风险信号必须连续保持两帧(40ms)以上才触发状态迁移,这样偶发的噪声尖峰不会引起误报。

5.4 车辆模型制动响应滞后

AEB算法计算出的减速度请求,在Carsim车辆模型中大约有100到200ms的响应延迟,这包括制动系统建压时间和制动器作用时间。如果算法不考虑这个延迟,实际减速度曲线会比请求曲线滞后,导致真实制动距离比理论值长。

我的解决办法是在决策层中加入动态补偿模块。具体来说,就是根据当前的制动系统状态预测实际减速度,并以此预测值作为TTC计算的输入。这样计算出的TTC虽然略保守,但更贴近实际制动结果。实测下来,补偿后的系统在触发时机上提前了约0.15秒,制动终点距离更充裕。

6. 算法扩展方向与项目体会

模块化建模的框架跑通后,AEB只是起点。我在同一个框架上扩展过两项功能:

第一项是加入FCW与AEB的联合联动。FCW在更早的TTC阈值下预警,同时预留驾驶员接管判断窗口——如果驾驶员在预警后的1.2秒内踩下制动踏板,AEB自动退出,把控制权交还给驾驶员;如果没有接管动作,AEB才自主介入。这套逻辑在Simulink中实现起来非常方便,因为状态机框架已经搭好了。

第二项是ACC自适应巡航与AEB的协同控制。ACC负责跟车巡航,AEB负责紧急避险,两者共享感知层和车辆接口层,区别只在决策层的控制目标不同。ACC用PID控制期望车速与车距,AEB用TTC控制碰撞规避。把这两套逻辑模块并联在决策层里,根据工况优先级做仲裁,整个系统的架构没有改变,只是多了一个仲裁模块。

最后说一点个人体会:AEB联合仿真的难点从来不在算法公式本身,而在于把各层模块边界划清楚、把各接口参数定明白。很多同学做项目时喜欢一开始就打开Simulink拖模块,结果做到一半发现接口不统一、单位不一致、参数散落在模型各处,改起来焦头烂额。我自己也经历过这个阶段,后来养成了先画接口表、先写参数文件、先设计状态图、最后才动手搭模型的习惯,效率高了很多。这套方法论,不管你是做课题、做量产预研还是个人学习,都值得参考。希望这篇内容能帮你少踩几个坑,把精力真正花在算法设计本身。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进