ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Matlab与Simulink的自动驾驶联合仿真架构与实战解析

基于Matlab与Simulink的自动驾驶联合仿真架构与实战解析 简介这是一套基于Matlab与Simulink的自动驾驶联合仿真项目源自作者获得99分的高分答辩大作业经过完整调试确保可直接运行适合计算机、通信、人工智能、自动化等专业学生用于课程设计、期末大作业与毕业设计也方便初学者从零学习仿真建模流程。包内共8个文件涵盖2个M脚本含模型线性化Jacobian函数、Simulink模型文件mdl/sim/r2019a、cpar配置、MAT数据与README说明压缩包整体仅118KB结构紧凑、便于快速部署。项目涉及路径规划、车辆动力学建模、控制器设计等自动驾驶关键环节并配有文档说明可帮助读者理解联合仿真整体框架与调试思路。目前已有63人学习下载对希望以低成本入门自动驾驶仿真或在此基础上扩展功能的中级学习者具有不错的参考价值。1. 基于Matlab和Simulink的自动驾驶联合仿真这套源码包解决什么问题做自动驾驶算法的人90% 的精力耗在仿真环境上而不是算法本身。纯 MATLAB 脚本跑不出来传感器噪声、车辆动力学和控制器延迟换成 Prescan、CarSim 这类商业工具又要另外掏钱、环境还重。这套基于 Matlab 和 Simulink 的自动驾驶联合仿真源码把场景编辑、感知融合、路径规划、横纵向控制四段链路收在一个工程里用 Simulink 的时间调度统一驱动跑通一个从传感器输出原始数据到方向盘转角和油门踏板的完整闭环。它适合三类人做课程设计或毕设的学生想快速验证控制算法的工程师以及刚接手自动驾驶仿真、需要一份可修改骨架的入门者。你能拿到的不只是模型还有怎么改参数、怎么排查发散、怎么测决策延迟的具体答案。2. 联合仿真的架构设计从场景到控制器的数据链路与模块边界2.1 自动驾驶仿真的四层架构场景、感知、决策、执行联合仿真不是把一堆模块拖进 Simulink 就完事。这套源码采用四层架构每层之间有明确的接口约定改一层不影响另外三层。第一层是场景层负责生成车辆行驶环境包括道路几何、障碍物位置、目标车速度曲线、天气和光照参数。在 Simulink 里这一层通常用道路传感器模块和 3D 场景编辑器配合或者用虚拟场景建模工具生成路网文件后导入。场景层输出的核心是坐标系和障碍物列表坐标系必须统一到车辆后轴中心为原点否则后续所有传感器数据都会错位。第二层是感知层接收场景层输出的真值数据叠加噪声后输出带不确定性的目标列表。这里的关键点是仿真里没有真正的摄像头或毫米波雷达只有数学抽象。比如毫米波雷达模块会为每个目标生成距离、相对速度、方位角并附加高斯噪声和漏检概率。感知层的输出接口通常是一个结构体数组每条记录包含目标 ID、位置、速度、航向角和置信度。第三层是决策层包括全局路径规划和局部行为决策。全局规划跑在低频率上5Hz 左右负责生成一条从起点到终点的参考路径局部规划跑在高频率上20-50Hz负责避障、跟车、变道。多数课程设计把局部规划写成一个有限状态机状态切换条件绑在感知层输出的 TTCTime to Collision或车头时距上这块是看代码时最先要读的部分。第四层是执行层包含横纵向控制器和车辆动力学模型。横向用 LQR 或纯跟踪纵向用 PID 或 ACC 模型。车辆动力学可以选择简单自行车模型也可以换成 CarSim 的整车模型做联合仿真。如果用的自行车模型状态量就是纵向速度、横向速度、横摆角和横摆角速度控制量是前轮转角和轮端扭矩。四层之间通过 Simulink 的总线Bus对象传递数据而不是各自定义独立端口。这么做的好处是新增一个传感器只需要在感知层内部加模块总线信号名不变决策层代码一行都不用动。2.2 数据总线与消息格式接口统一是这套源码的骨架打开模型后最先看的是 Bus 对象的定义文件。这套源码里定义了三条核心总线PerceptionBus、DecisionBus、ControlBus对应感知、决策、执行三层之间的口交数据。% 建立感知层输出总线对象 perceptionBus Simulink.Bus; perceptionBus.Elements(1) Simulink.BusElement; perceptionBus.Elements(1).Name TargetID; perceptionBus.Elements(1).DataType uint16; perceptionBus.Elements(2) Simulink.BusElement; perceptionBus.Elements(2).Name LongitudinalDistance; perceptionBus.Elements(2).DataType double;这段代码建立了一个包含目标 ID 和纵向距离的感知总线后续决策层只要从总线上取信号就行。第一次改模型的人最容易犯的错是直接在 Simulink 里手动加端口结果后续所有引用该信号的模块全部变红。正确的做法是始终通过 Bus 对象传递模型只是一个消费总线数据的外壳。参数说明TargetID用的是uint16而不是double因为目标数量通常不会超过 65535用uint16可以减小总线数据量在外部模式下传输带宽更省。LongitudinalDistance保留double因为纵向距离要用于 ACC 控制律计算精度损失会直接影响加速度输出。Simulink.BusElement的属性里还有SamplingMode和Dimensions多维传感器数据比如激光雷达点云设置Dimensions为[N 3]其中 N 是单帧最大点数。2.3 关键参数表哪些数值决定仿真逼真度拿到源码后不要急着跑先把参数脚本里的关键值过一遍。以下参数直接决定仿真结果是否可信也是答辩时最常被问到的点。参数名默认值作用改小会怎样改大会怎样传感器更新频率20 Hz感知层输出频率决策反应迟钝总线负载过大毫米波雷达噪声标准差0.3 m距离测量噪声感知太理想跟踪不稳定车辆纵向速度初值0 m/s起步条件起步更慢可能冲出道路LQR 权重矩阵 Qdiag([1 10 100])横向偏差惩罚控制太软转向抖动仿真步长0.01 s数值积分步长精度高但慢动力学发散决策周期0.05 s局部规划频率决策太频繁避障滞后仿真步长这个参数最容易踩坑。自动驾驶联合仿真是连续与离散混合系统车辆动力学是连续的控制器和传感器是离散的。步长设成0.01s意味着动力学积分步长和传感器采样同步但如果你把传感器频率改成 20Hz即 0.05s 周期而仿真步长还保持 0.01sSimulink 会用零阶保持器在传感器采样点之间做插值这个差值在高速场景下会造成 1-2 米的感知误差。我一般建议把仿真步长固定为最小采样周期的五分之一。也就是说传感器 20Hz、周期 0.05s步长用 0.01s但如果控制器跑 100Hz步长就要压到 0.002s否则控制器输出在两次执行之间会被衰减得不像样。3. 从下载到跑通环境配置与模型初始化3.1 版本匹配与工具箱依赖检查这套源码基于 R2020b 之后的结构设计太老的版本打不开模型文件。首先检查 Matlab 版本和已安装的工具箱% 检查版本和工具箱 ver(simulink) ver(automated_driving) ver(robotics) % 当前使用版本 matlabVersion version; fprintf(当前 Matlab 版本: %s\n, matlabVersion);逻辑说明ver函数逐个检查 Simulink、自动驾驶工具箱、机器人工具箱是否安装任何一个返回空结果都说明缺失。自动驾驶工具箱不是可选项联合仿真的场景层和传感器模块大多依赖它。参数说明如果显示automated_driving不存在说明装的是基础版本需要补装 Automated Driving Toolbox。注意不要用license(test, Automated_Driving_Toolbox)来测试授权因为部分破解环境会返回1但实际功能不可用跑模型时才报错。更可靠的检验方式是直接openExample(automated_driving)能打开官方示例才说明环境完整。3.2 文件夹结构与加载顺序下载解压后目录结构通常是proj_root/ ├── init/ # 初始化脚本 │ ├── setup_path.m # 路径设置 │ └── init_params.m # 全局参数写入 ├── models/ # Simulink 模型 │ ├── autonomous_driving.slx │ └── sensor_fusion_lib.slx ├── data/ # 测试场景与日志 │ ├── scenarios/highway.mat │ └── logs/result_hw08.mat ├── utils/ # 工具函数 │ ├── lat_lqr_controller.m │ └── calculate_ttc.m └── docs/ # 文档说明加载顺序很关键直接运行脚本而不是手动addpath。为什么要用脚本因为setup_path.m里会调用savepath把路径固化到环境变量手动addpath在重启 Matlab 后会丢失导致模型里引用的回调函数找不到。我在setup_path.m里习惯这样处理% 将项目根目录加入路径含子文件夹 projRoot fileparts(mfilename(fullpath)); addpath(genpath(projRoot)); % 清理重复路径避免多个版本冲突 restoredefaultpath; rehash toolboxcache; % 检查路径是否包含项目目录 assert(~isempty(which(init_params.m)), 路径设置失败);逻辑说明genpath递归加入所有子目录但也会把一些隐藏目录加进去造成冲突所以加完后用restoredefaultpath清理一遍再重建。这个顺序不能反——先restore再加自己的路径否则会把 Matlab 自带工具包路径全清掉。3.3 初始化脚本参数批量写入模型工作区初始化脚本的作用是把所有参数写到模型工作区Model Workspace而不是写到基础工作区Base Workspace。两者的区别是基础工作区的变量在多个模型间共享容易串数据模型工作区跟随模型文件保存换个机器重新打开参数还在。% init_params.m —— 写入模型工作区 mdlName autonomous_driving; load_system(mdlName); % 获取模型工作区句柄 mdlWS get_param(mdlName, ModelWorkspace); % 写入车辆参数 assignin(mdlWS, vehMass, 1520); % 车辆质量 kg assignin(mdlWS, frontAxleDist, 1.2); % 前轴到质心距离 m assignin(mdlWS, rearAxleDist, 1.4); % 后轴到质心距离 m assignin(mdlWS, cornerStiffness, 62000); % 前轮侧偏刚度 N/rad % 写入控制参数 assignin(mdlWS, lqrQ, diag([1 10 100])); assignin(mdlWS, lqrR, 0.01); % 刷新模型确保参数生效 set_param(mdlName, SimulationCommand, update);逻辑说明assignin的第二个参数ModelWorkspace表示写入目标第三个参数是变量名第四个是值。update命令让模型重新计算参数依赖关系避免在运行到一半时报未定义变量错误。参数说明cornerStiffness的 62000 N/rad 是基于普通家用轿车的典型值如果你换的是 SUV 车型这个值要调到 75000 左右否则横向控制器计算的前轮侧偏力不准高速变道会有明显的转向不足。lqrQ里的三个值依次是横向位置偏差权重、横向速度偏差权重、横摆角偏差权重第三个权重设得过大超过 500会导致控制器对横摆角变化过度敏感表现为方向盘的锯齿状抖动。4. 核心模块实战感知、规划与控制的三段式改法4.1 感知模块毫米波雷达与视觉目标的融合逻辑感知模块是多数人最想跳过、但最值得细读的部分。源码里的融合逻辑不是简单的加权平均而是基于误差协方差的择优选择。融合算法的核心思路是同一目标可能同时被雷达和视觉检测到两种传感器各有优势——雷达测距准、视觉测角准。融合时先做目标关联判断两路输出是否指向同一物理目标再用协方差最小化原则分配权重。% sensor_fusion_update.m —— 雷达与视觉目标融合 % 输入: 雷达距离测量 rRadar, 视觉距离测量 rVision % 雷达角度测量 aRadar, 视觉角度测量 aVision % 输出: 融合后的目标位置 (x, y) function [x_fused, y_fused] sensor_fusion_update( ... rRadar, rVision, aRadar, aVision, sigmaRadar, sigmaVision) % 计算两个传感器各自的位置估计 x_radar rRadar * cos(aRadar); y_radar rRadar * sin(aRadar); x_vision rVision * cos(aVision); y_vision rVision * sin(aVision); % 按方差倒数加权融合方差小权重高 wRadar (1 / sigmaRadar^2) / (1 / sigmaRadar^2 1 / sigmaVision^2); wVision 1 - wRadar; x_fused wRadar * x_radar wVision * x_vision; y_fused wRadar * y_radar wVision * y_vision; end逻辑说明wRadar的计算是方差倒数的归一化这里的数学依据是最大似然估计——在两个独立高斯噪声来源下最优融合权重与方差成反比。如果sigmaRadar是 0.3m、sigmaVision是 1.5m那么雷达的权重大约是 96%这个比例是合理的因为毫米波雷达测距确实比视觉单目要准。参数说明这个函数的输出只是融合位置没有考虑速度融合。完整融合还需要一个状态估计器KF 或 UKF。如果你发现融合后的轨迹有明显跳变先检查sigmaVision是否设得太乐观视觉测距在光线不佳时误差会翻倍源码里默认 1.5m 已经偏乐观实际路测通常要到 2.5m 级别。4.2 全局与局部两层规划参考路径生成与实时避障路径规划分成两层的原因是计算频率差异太大。全局规划要做 A* 或 RRT 搜索几十毫秒一次就是上限局部规划只需要做曲线插值或状态机切换可以做到 50Hz。把两者塞到一个频率跑要么全局规划拖慢局部响应要么局部规划浪费 CPU。全局路径生成脚本的核心是离散路点插值% generate_reference_path.m —— 生成平滑参考路径 % 基于稀疏路点用三次样条插值生成密集路径点 function [pathX, pathY, pathYaw] generate_reference_path(... sparseX, sparseY, stepSize) % 三次样条插值得到平滑路径 t 1:length(sparseX); tFine 1:stepSize:length(sparseX); pathX interp1(t, sparseX, tFine, spline); pathY interp1(t, sparseY, tFine, spline); % 用相邻点差分计算航向角 diffX diff(pathX); diffY diff(pathY); pathYaw atan2(diffY, diffX); pathYaw [pathYaw, pathYaw(end)]; % 末点补齐 end逻辑说明interp1的spline选项生成的三次样条在路点处连续可导避免折线路径导致控制器频繁修正转角。航向角通过atan2差分计算必须在插值之后做如果在稀疏点上直接算航向角两个路点之间的大转折会让局部控制器误判为急弯。参数说明stepSize是插值密度1 表示每个路点间插 1 个点。如果你把stepSize设成小于 1会得到比原路点更稀疏的路径局部规划器可能错过弯道特征。这个参数建议固定为 0.5也就是原路点间距的一半不要在运行中动态修改。局部规划器的避障逻辑是延伸状态机默认FOLLOW_LANE检测到 TTC 小于 3 秒且旁道有空位时切换到LANE_CHANGE超车完成后回到原车道。这里踩坑点在于状态切换的滞回——如果切换阈值是固定值车辆会频繁在两个状态间抖动。源码里对切换加了 2 秒的最小驻留时间这个值是个好人设别轻易改成 0。4.3 横纵向控制LQR 横向跟踪与 ACC 纵向跟车横向控制器用的是 LQR核心是状态加权矩阵 Q 和控制加权矩阵 R 的权衡。LQR 的好处是可以通过 Q、R 直接调节控制的激进程度不像 PID 那样要同时调 P、I、D 三个参数且相互耦合。% lat_lqr_controller.m —— LQR 横向路径跟踪控制器 % 状态: [横向位置偏差 e; 横向速度偏差 de; 横摆角偏差 psi; 横摆角速度偏差 dpsi] % 输出: 前轮转角 delta function delta lat_lqr_controller(e, de, psi, dpsi, vehSpeed) % 系统矩阵 A简化的线性自行车模型 A [0 1 0 0; 0 0 vehSpeed 0; 0 0 0 1; 0 0 -vehSpeed/3.0 0]; B [0; 1; 0; vehSpeed/3.0]; % 前轮转角输入矩阵 % 权重矩阵 Q diag([1 10 100 50]); R 0.01; % 求解黎卡提方程得到 K 矩阵 [K, ~, ~] lqr(A, B, Q, R); % 状态向量 x [e; de; psi; dpsi]; delta -K * x; end逻辑说明A矩阵第 3 行第 4 列的第 4 个参数vehSpeed / 3.0中的3.0是轴距这个值需要和初始化脚本里的frontAxleDist rearAxleDist保持一致。如果两边不一致模型会跑出稳定的横向偏差曲线但控制律算出来的转角始终有固定偏移。lqr函数的第三个输出是 P 矩阵黎卡提方程的解用~丢弃不用参与控制量计算。参数说明Q 矩阵第三个元素 100 是横摆角偏差的权重这个值越大车辆越倾向于快速摆正车头方向但过大会和前轮转角极限发生冲突——大转角下轮胎侧偏角超过线性区LQR 模型的假设就失效了。仿真中如果发现方向盘高频抖动先把 Q 第三个元素降到 50再观察横摆角响应。纵向控制是 ACC 加 PI 控制器。ACC 上层计算目标加速度核心是间距策略% acc_upper.m —— 上下层 ACC输出目标加速度 % 输入: 本车速度 vEgo, 前车速度 vLead, 相对距离 dRel % 输出: 目标加速度 aTarget function aTarget acc_upper(vEgo, vLead, dRel) dDesired 2.0 1.2 * vEgo; % 间距策略时距 1.2s 最小距离 2m errorDist dRel - dDesired; errorSpeed vLead - vEgo; % 线性二次型权重这里简化为系数 kDist 0.8; kSpeed 0.3; aTarget kDist * errorDist kSpeed * errorSpeed; aTarget max(min(aTarget, 3.0), -4.0); % 舒适性限幅 end逻辑说明dDesired 2.0 1.2 * vEgo的物理含义是速度每增加 1 m/s跟车距离增加 1.2m这就是常说的固定时距策略。kDist和kSpeed的比值决定了加速度响应是先补偿距离差还是先补偿速度差前者比重设太大容易出现先急加速再急刹车的往复运动。参数说明上限 3.0 m/s^2 是舒适制动和急加速的分界线下限 -4.0 m/s^2 是舒适制动的极限。如果你的场景里前车经常急刹把kDist从 0.8 提高到 1.2 比把下限从 -4 改到 -6 效果更好因为前者是从源头减少距离误差后者只是扩大执行器约束治标不治本。5. 联合仿真避坑指南五个高发问题的现象、原因与解决5.1 模型一打开就报 The block diagram is not defined现象双击.slx文件Simulink 弹窗提示模块图未定义模型里大量模块显示为灰色。原因这通常不是模型文件损坏而是启动时缺少模型回调函数依赖的变量。模型打开时默认执行InitFcn回调如果回调里引用了初始化脚本生成的变量比如vehMass而这些变量还没写入模型工作区整个模型就处于未定义状态。解决先手动运行setup_path.m和init_params.m确保工作区变量就绪后再打开模型。注意顺序必须是先setup_path再init_params因为后者里用到了前者的assignin函数。如果你已经在基础工作区跑过脚本但仍然报错检查模型回调是不是写成了evalin(base, init_params)这样会在基础工作区执行而不是模型工作区变量进不了模型工作区模块照样找不到。5.2 Bus Selector 下拉菜单里没有任何信号可选现象双击 Bus Selector 模块信号列表是空的但输入端明明是一条总线。原因这是总线对象和模型脚本不同步导致的。你更新了 Bus 对象定义比如新增了一个TargetID字段但模型里通过Simulink.Bus.createObject生成的旧总线缓存没有被清理。Simulink 优先读取模型文件里内嵌的总线定义而不是你通过脚本新建的那个。解决用如下命令清除总线缓存然后重新加载模型% 清除总线缓存并重载模型 clearBusCache(); close_system(autonomous_driving, 0); load_system(autonomous_driving);逻辑说明clearBusCache清理的是sl_customization和系统缓存目录下的总线定义副本。执行后重新加载模型Simulink 会读取工作区最新的Simulink.Bus对象。如果close_system的第二个参数设为1保存会把旧的坏定义写回文件所以这里必须传0表示不保存关闭。5.3 仿真到 3 秒附近数值发散车辆轨迹变成直线冲出道路现象仿真时间到 3 秒左右速度或横摆角急剧增大到天文数字车辆轨迹笔直冲出路沿。原因init_params.m里stepSize设成 0.01 且vehSpeed初速为 0 时车辆在原地由静止起步轮胎侧偏角的计算在极低速下数值条件数极差。自行车模型的侧偏力与侧偏角是线性关系但速度趋近 0 时侧偏角 atan(vy / vx) 的分母趋近 0计算溢出。解决给车辆一个小的初始速度比如vehSpeedInit 0.5 m/s并且把求解器从ode45变步长改成ode4固定步长 0.01避免变步长求解器在快速起步阶段不断缩小步长导致积分次数爆炸。5.4 模型里的中文注释显示成乱码现象打开源码模型或脚本所有中文注释变成 锟斤拷 或方块。原因文件编码不一致。Matlab 2023a 之后默认用 UTF-8 保存.m文件但 2022b 之前默认是 GBK 环境变量打开旧模型时按系统区域设置的编码解析。源码包里的.m脚本如果保存时用了 UTF-8而你的系统区域是中文简体GBKSimulink 读取时就会乱码。解决用 Matlab 的slCharacterEncoding命令暂时切到 UTF-8或者直接在setup_path.m第一行加上% 设置源码文件编码为 UTF-8 feature(DefaultCharacterSet, UTF-8);如果乱码出现在.slx模型内部的注释模块上述命令无效因为模型内部的注释以 UNICODE 存储、以系统编码显示这个无解只能手动改模块注释。但脚本乱码都可以用上面的方式修复。5.5 控制器输出抖动方向盘角度在 ±15 度之间往复现象车辆在直线段行驶前轮转角输出在以 10Hz 左右的频率抖动车身轻微摇摆。原因LQR 控制周期和仿真步长不匹配。控制器每 0.05s 输出一次转角但仿真步长 0.01s意味着同一个转角值被 Zero-Order Hold 重复使用了 5 次。如果感知层的航向角在这个 0.05s 内有噪声控制器输出的转角会跟随噪声变化形成抖动。解决给 LQR 控制器的输入信号加一阶低通滤波截止频率设为 2Hz。具体做法是在lat_lqr_controller模块前插入一个 Transfer Fcn分子为[1]分母为[0.08 1]这会把 10Hz 以上的横向偏差变化衰减掉保留 2Hz 以内的真实轨迹变化。不要用更低的截止频率否则车辆会感觉像喝醉了转向响应太钝。6. 把联合仿真做到可信决策延迟测量与外部模式验证仿真跑通只是第一步答辩或交付时对方一定会问决策延迟是多少。这个数字直接反映你的控制链路有没有多余等待也是衡量仿真实时性的核心指标。测延迟有两种方法我用的是第二种。方法一在 Simulink 里串联 Timer 模块记录从传感器数据到达决策模块的仿真时间差。优点是简单缺点是精确度被仿真步长限制只能测到步长的整数倍。方法二用数据日志和时间戳差做离线测算。在模型里给决策模块输出打上log标记跑完仿真后用Simulink.sdi读取两条信号的仿真时间戳差% measure_decision_latency.m —— 离线测量决策延迟 % 读取感知时间戳和决策输出时间戳计算平均延迟 function latency_ms measure_decision_latency(logName) % 获取仿真数据 run Simulink.sdi.getRun(logName); signalSensor Simulink.sdi.getSignal( ... run, SensorOutputTime); signalDecision Simulink.sdi.getSignal( ... run, DecisionOutputTime); % 提取时间戳向量 tSensor signalSensor.Values.Time; tDecision signalDecision.Values.Time; % 计算每个决策输出对应的感知时间差 delta tDecision - tSensor; latency_ms mean(delta) * 1000; end逻辑说明Simulink.sdi.getSignal按信号名从仿真数据检查器里取数据Values.Time返回时间戳数组。两个信号长度可能不一致感知频率 20Hz、决策 50Hz所以先按决策信号的时间戳对齐到最近的感知时间戳计算差值的均值。注意这里测的是纯计算延迟也就是从数据进决策模块到出决策模块的耗时不包括传感器采样本身的等待。我实际测过这套源码在默认参数下的结果感知 20Hz、决策 20Hz、LQR 控制 50Hz纯决策延迟大约在 28-35ms 之间。热搜里那个决策延迟 32.8 毫秒的数值和这套默认配置下测出的结果基本一致说明时序调度没有明显的资源竞争问题。如果你的配置测出来超过 60ms先检查是不是在决策模块里插了evalin这类耗时命令而不是检查算法复杂度。验证完延迟之后还可以用 Simulink 的 External Mode外部模式跑一组硬件在环测试。外部模式的意思是模型编译后部署到目标机实时运行Matlab 主机只负责交互和数据显示不再参与仿真计算。这一步的价值在于暴露离线仿真能跑、实时运行掉帧的问题% 配置外部模式实时仿真的参数 set_param(mdlName, SimulationMode, external); set_param(mdlName, StopTime, inf); set_param(mdlName, FixedStep, 0.01);逻辑说明external模式把模型编译成独立可执行文件运行主机通过 TCP/IP 连接读写参数。FixedStep必须与模型配置里的步长一致否则目标机运行频率和主机显示频率不匹配波形看起来像卡顿。外部模式下建议关闭所有数据日志因为日志记录本身会拖慢实时循环测出来的延迟会虚高。外部模式踩过的坑目标机回传的波形默认有 0.5-1s 的网络传输延迟这不是模型决策延迟而是显示延迟。在外部模式下看波形总感觉控制器响应慢半拍其实是数据在回传链路里排队。要区分两者在模型里加一个探针信号直接输出决策模块的仿真时间戳回传的时间戳减去主机侧的时间就是纯网络延迟。操作建议跑离线仿真时先测决策延迟用上述measure_decision_latency脚本确认数值在合理区间再切外部模式做实时验证。实时验证的重点是看 CPU 负载——在目标机任务管理里 CPU 使用率超过 85% 说明模型计算量偏大需要降低感知频率或传感器数量否则一旦出现任务抢占决策延迟会从 30ms 突然跳到 200ms这个跳变在离线仿真是复现不出来的。这套源码让我在课程设计和横向项目里省了不少事但最大的收获是养成了一个习惯每次改完参数哪怕是只改了一个Q矩阵的权重我都强制自己跑一遍完整流程——初始化、离线仿真、延迟测量、外部模式验证。前几步快最后一步慢但慢得值。希望这份拆解能帮你在自动驾驶联合仿真这条路上少走几个弯路有问题照着参数表和避坑清单排查基本都能落地。本文还有配套的精品资源点击获取
返回列表