
简介面向数学建模竞赛及本科、硕士教研学习场景这份压缩包演示了如何用Matlab模拟十字路口车辆通行属于基础教程级资料适合初步接触交通流仿真的读者进行源码复现与结果对照也可用于课程设计或赛题中的快速验证。包内共8个文件压缩包仅65KB以3个.m脚本和5张结果图片为主m文件分别承担主仿真、车距计算和绘图生成等环节jpg运行结果可用于直观校对模型输出。资源基于Matlab 2019a编写内含可直接运行的脚本与结果截图已有765人浏览学习下载后打开即可查看基础演示效果。对准备数学建模赛题或完成课程设计作业的读者来说这组小体积代码能帮助快速理解路口车流离散仿真流程也可作为后续扩展车道数、加入信号灯配时算法的起点整体轻量易用适合边看边练尤其适合Matlab初学者模仿改写。 我最近整理资料时翻出一个以前做的项目用 MATLAB 模拟十字路口的车辆通行。当时是给数学建模比赛做准备后来发现这个仿真框架不仅能用来交作业放到交通工程、算法验证里也很能打。今天就把这个思路完整拆一遍讲讲车辆模型怎么建、冲突怎么判、动画怎么画以及我调参时踩过的那些坑。这东西本质上属于微观交通流仿真。所谓微观就是每辆车都有独立的位置、速度、目标方向车辆之间互相影响不像宏观模型那样只关心流量和密度。用 MATLAB 写这类仿真优势很明显矩阵运算方便面对几十上百辆车的数据操作很顺手画图能力强能把路口和车辆运动过程直接可视化调试门槛低数学建模的学生不需要额外学一套仿真引擎。适合谁看如果你是准备数学建模竞赛的学生这个案例可以当作排队论、决策论题目的底层引擎如果你在搞智能交通、自动驾驶相关的课程设计可以用它验证路权分配策略。代码逻辑不长但对新手来说信息量不低我尽量讲得具体一些。1. 仿真建模的起点为什么是十字路口场景1.1 交通仿真在数学建模里的典型位置十字路口车辆通行问题在中美各类建模比赛里都出现过变种非常多无信号灯环岛、借道左转、可变车道、信号配时优化底层都是同一套机制——车辆在不同方向上竞争路口的时空资源。用 MATLAB 建模时首先要明确你要回答的问题是什么。是“无信号灯路口通行效率有多低”还是“不同让行规则下平均等待时间对比”还是“车流量增加到多少会死锁”问题不同模型的粒度就不同。如果只是评估平均延误可以简化到排队论级别如果要做路权博弈就需要逐车跟踪。1.2 核心难点冲突不是“撞上去”那么简单一段直行路段上的跟驰模拟不难真正的难点在路口。四个方向的车流都涌向同一个交叉区域直行、右转、左转相互交叉谁先走、谁该让必须有一个明确的判定逻辑。从建模角度冲突的本质是时空占用碰撞两辆车在未来某个时刻可能占据同一个位置区域。所以不能只看当前时刻是否重合要预判它们未来一段时间的轨迹。MATLAB 里可以做实时碰撞预测也可以做响应式避让——每次步进前检查“我下一步要去的格子或区域有没有被占用”。后者计算量小更适合教学演示。另外一个容易被忽略的点车辆不是质点。任何车辆都有长宽和最小转弯半径。在低速交叉口场景很多数学建模题目允许简化成质点但也必须给车身长度留出安全距离否则你会看到两辆车“穿模”叠在一起极其出戏。2. 整体方案设计把真实路口变成可计算模型2.1 车辆模型与状态抽象每一辆车在这个仿真里我会保存以下信息。字段不多但对微观仿真来说已经够了。字段含义说明id车辆编号用来追踪个体便于统计type车辆类型本案例可以全是小汽车也可混合货车direction进入方向可以用 1东→西2西→东3南→北4北→南target转向意图1直行2左转3右转x / y位置坐标路口中心通常设为 (0,0)v速度单位 m/sdesiredSpeed期望速度每辆车有自己的巡航速度gap与前车的距离用于跟驰判断在路口起点外一定距离生成车辆比如离中心 100 米的位置。车距通过泊松分布模拟随机到达这样更接近真实情况而不是定时定点放车。2.2 运动逻辑与安全跟驰直行路段的运动逻辑用简单跟驰模型就够如果前面有车就根据距离调整车速如果前方开阔就朝着期望速度加速。这里我采用一个比较稳妥的简化规则同一车道内后车速度 (v_{next}) 由前车距离 (g) 和前车速度 (v_{lead}) 决定。如果 (g safeGap)减速如果 (g) 很大就正常加速到目标速度。[ v_{next} \min(v_{current} a \cdot dt,; v_{lead}, ; k \cdot (g - minGap)) ]简单说安全距离内后车的速度上限由前车速度和物理距离共同决定。实际代码里不需要做复杂的微分方程求解用离散时间步进即可(dt) 取 0.1~0.2 秒已经足够稳定。做过仿真的人都知道(dt) 太小则计算慢太大则车辆可能直接“穿越”障碍物。0.2 秒是经验平衡点。2.3 路口冲突与让行优先级无信号灯路口的核心规则是路权分配。我用的是基于交通法规简化的优先规则并在代码里实现为“暂停判断”右转车辆优先级最高基本不用等但要注意避让直行非机动车。直行车辆优先于左转车辆。对向直行优先于本方左转。如果多方向冲突默认“先进入路口者先行”。这套规则在代码里很直接每次步进前车辆检查自己前方冲突区域内是否有来自其他方向、尚未通过路口的车辆。如果有根据优先级决定走还是等。左转是比较容易死锁的场景。比如东向西左转和北向南直行相冲突时如果双方都不让两个方向都会堵住。我的解决方案是引入一个小的随机礼貌因子等待超过一定时间后车辆会试探性前进一部分迫使对方减速从而打破僵局。这在真实驾驶里很常见也能有效缓解仿真死锁。2.4 可视化与分析指标MATLAB 的可视化用plot和quiver就能完成。路面画成十字交叉线车辆用不同颜色的矩形或箭头表示方向不同颜色不同这样在动画里一眼能看出哪边的车流量大。同时还要记录几个关键指标通过车辆总数平均等待时间最大排队长度死锁次数这些指标是判断模型是否合理的依据。如果平均等待时间随时间单调递增大概率是路口容量已饱和或者让行规则有缺陷。3. MATLAB 核心实现关键代码拆解3.1 初始化车辆首先定义路口参数和车辆结构体。我用struct数组而不是对象因为对 MATLAB 新手更友好性能也足够。% 路口参数 roadLen 100; % 路段长度米 dt 0.2; % 仿真步长秒 simTime 300; % 仿真总时长秒 safeGap 2.5; % 最小安全车距米 desiredSpeed 10; % 期望速度m/s % 车辆结构体初始化 car struct(id, {}, dir, {}, turn, {}, ... x, {}, y, {}, v, {}, active, {});这里的active字段很关键。车辆一旦驶出路口区域就可以从活跃列表里移出不再参与计算否则累积车辆会让仿真越来越卡。生成车辆的节奏用泊松过程。每个时间步以概率 (p \lambda \cdot dt) 生成新车(\lambda) 是到达率单位是辆/秒。四个方向独立生成这样不同方向的车流量不平衡时效果更明显。lambda 0.25; % 每个方向的平均到达率辆/秒 if rand lambda * dt % 随机选择方向和转向意图 dir randi(4); turn randi(3); % 1直行 2左转 3右转 % 设置初始位置离路口 100 米外 switch dir case 1 % 东向西从右侧进入 x roadLen; y 0; v 0; case 2 % 西向东 x -roadLen; y 0; v 0; case 3 % 南向北从下方进入 x 0; y -roadLen; v 0; case 4 % 北向南 x 0; y roadLen; v 0; end end3.2 仿真主循环与位置更新主循环里每次做三件事更新每辆车的位置和速度、检查路口冲突、绘制当前画面。for t 0:dt:simTime % 遍历所有活跃车辆 for i 1:length(car) if ~car(i).active continue; end % 判断是否需要刹车让行 if inConflictZone(car(i)) shouldYield(car(i)) car(i).v max(0, car(i).v - 2*dt); else car(i).v min(car(i).v 1.5*dt, desiredSpeed); end % 更新位置 car(i).x car(i).x car(i).v * dt * cos(car(i).angle); car(i).y car(i).y car(i).v * dt * sin(car(i).angle); % 离开路口区域后置为非活跃 if abs(car(i).x) roadLen || abs(car(i).y) roadLen car(i).active false; end end % 绘制 drawIntersection(car); endangle根据进入方向和转向意图预先算好比如东向西右转的车辆在接近路口后角度会从 180° 变成 90°。3.3 冲突检测函数这是整个仿真里最容易出 bug 的地方。ConflictZone是路口中心一个半径为 5 米左右的圆形区域或者更精确一点四个方向形成的内接矩形区域。任何还没驶离该区域的车辆都在占用路口。function flag hasConflict(carA, carB) % 只看两车是否同时在冲突区域内 distA sqrt(carA.x^2 carA.y^2); distB sqrt(carB.x^2 carB.y^2); flag (distA 6) (distB 6); end完整版还会根据转向轨迹判断两条路径是否有交点。方法很简单把每辆车的路径离散成点序列判断其他车辆的路径点是否与本车下一步的路径点距离过近。这个做法的优点是直观缺点是循环多但车辆数量在 50 辆以内时 MATLAB 完全能扛住。3.4 动画绘制动画用rectangle绘制车身用quiver画速度方向箭头比plot单纯画点效果好很多。function drawIntersection(car) clf; hold on; % 画道路 line([-roadLen, roadLen], [0, 0], Color, [0.4 0.4 0.4], LineWidth, 6); line([0, 0], [-roadLen, roadLen], Color, [0.4 0.4 0.4], LineWidth, 6); % 画车辆 for i 1:length(car) if car(i).active plot(car(i).x, car(i).y, o, MarkerSize, 6, ... Color, getColor(car(i).dir)); end end axis equal; xlim([-120 120]); ylim([-120 120]); drawnow; end如果每次都用clf重绘车辆多了会闪。性能优化方案是用animatedline或者预先创建图形句柄后用set更新数据而不是clf重新画。但作为教学演示clf drawnow足够用300 辆车也不至于卡死。4. 仿真实战参数调试与结果观察4.1 一组可复现的初始参数分享一组我测试过效果不错的参数可以直接跑。参数取值说明仿真时长300 秒5 分钟足够统计时间步长0.2 秒稳定且消耗低道路长度100 米留出加速/减速空间到达率0.25 辆/秒/方向中等流量路口开始出现排队期望速度10 m/s约 36 km/h城市道路合理值最小安全距离2.5 米防止追尾冲突区半径6 米略大于路口中心范围在这个参数下五分钟内每个方向大约产生 75 辆车四个方向共 300 辆。无信号灯情况下车辆会出现间歇性拥堵但不会完全堵死。左转车流的平均等待时间比直行高 60% 左右这是符合预期的。4.2 统计指标怎么算统计每辆车的等待时间核心思路是在车辆速度低于 0.5 m/s 时累计停车时间。每辆车设置一个字段waitTime主循环里累加即可。车辆安全通过后根据方向和转向意图存入统计表格。我比较关注的是“左转车辆平均延误”。现实路口的左转延误本来就高如果仿真结果里左转比直行还快说明让行规则写错了。if car(i).v 0.5 car(i).waitTime car(i).waitTime dt; end4.3 不同流量下的对比结果我调过三组流量0.1低流量、0.25中等、0.4高流量。结果如下流量辆/秒/方向总通过车辆数平均延误秒最大排队长度辆0.101091.830.252388.4110.4029726.725流量从 0.25 跳到 0.4 时平均延误翻了 3 倍多这说明路口已经接近饱和。0.4 以上再增加流量通过车辆数几乎不涨说明已经到了容量上限。这种非线性增长在无信号灯路口非常典型也是论文里很值得写的现象。5. 踩坑记录仿真里最常见的 5 个问题5.1 车辆重叠和“瞬移”现象这是新手最常遇到的问题。车辆重叠的根源通常是安全距离过小或 (dt) 太大。我调试时发现如果 (dt0.5) 秒车速 10 m/s每一步车辆前进 5 米而安全距离只有 2.5 米那后车完全可能一步跨进前车的位置。解决办法把时间步长降到 0.1~0.2 秒同时将后车的速度上限设置为与前车距离相关。前车距离不足时后车直接设速度为 0而不是渐进减速。5.2 死锁四个方向谁也不让谁无信号灯路口最常见的问题是死锁。当我设置为严格“先到先走”模式时四个方向同时到达每辆车都在路口前停住谁也不动。打断死锁的方案有三种引入随机的礼貌因子等待超过 5 秒后车辆强行试探前进设置全局路权序列同一时间只允许一个方向通行添加一个极小的发车时间偏移破坏完全对称性。我实际用的是第一种效果好而且看起来更像真实驾驶。5.3 仿真越跑越慢如果不把驶出道路的车辆移除车辆数量会无限增加每个时间步遍历几百辆甚至上千辆车MATLAB 动画会明显掉帧。在车辆abs(x) roadLen或abs(y) roadLen后立刻把active置为false。循环内只处理活跃车辆。另外一个优化点别在循环内部动态扩充结构体数组预分配一个大数组用索引标记活跃位置能显著提升速度。5.4 结果不稳定随机性太强泊松随机到达导致每次仿真结果都不一样。如果想做多组实验对比需要设置随机种子。rng(42);如果不固定种子每组对比实验的数据波动可能非常大导致“流量 0.2 比 0.25 结果还好”这种完全没有说服力的现象。固定种子是仿真的好习惯正式实验前多测几组种子稳定后再跑记录。5.5 动画闪烁问题动画闪烁主要因为每次刷新时用了clf整个坐标区被清空重画。速度优化方案预先用scatter创建句柄循环里用set(handle, XData, ..., YData, ...)更新位置数据。这样完全避免了重绘底层对象动画流畅度提升明显。h scatter(nan, nan, filled); for t 0:dt:simTime set(h, XData, allX, YData, allY); drawnow; end6. 扩展方向从十字路口到更大的世界这个仿真框架的扩展性很好。我在原有基础上做过三个方向的延伸都挺有意思。第一加入红绿灯。在路口四条进口道设置信号灯状态红绿灯循环用全局时钟控制。车辆判断逻辑从“有冲突就让”变成“红灯停、绿灯行”统计不同绿信比下的通行效率。这个方向可以直接对接 2023 年一些智能交通类赛题。第二把单向车道改成双向多车道。车辆需要换道逻辑核心是判断目标车道的可用间隙。这个工作量比想象中大换道决策一旦写不合理车辆会在路上反复横跳。第三加入博弈优化的概念。让每个方向的车流带上有“耐心值”参数等待时间长了会变激进模拟真实人类的驾驶心理。这属于行为建模的范畴写出来论文效果不错。这个项目表面上是个交通仿真实际上涵盖了随机过程、状态机设计、图形可视化、性能优化多个知识点。做完一次对 MATLAB 的整体掌控能力会有明显提升。我后来数学建模比赛遇到排队优化类题目时直接改改参数就得到了对照实验数据节省了大量时间。最后再分享一个小技巧做这类仿真时不要一开始就追求把细节全部做完整。先把两辆车跑通再扩展到多车最后再处理碰撞、换道、让行这些复杂逻辑。一上来就加满车道和信号灯调试会让你怀疑人生。本文还有配套的精品资源点击获取