ARTICLE DETAIL

资讯详情

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

CTM交叉口仿真与MATLAB实现:从流量守恒到排队分析

CTM交叉口仿真与MATLAB实现:从流量守恒到排队分析 简介ctm_matlab-master.zip是一款基于MATLAB的CTM细胞传输模型交通流仿真项目聚焦交叉口交通管理与信号控制。面向交通工程专业学生、科研人员及智能交通系统开发者可用于理解交通流动态、评估不同信号配时与管控策略效果。压缩包共45个文件包含30个.m核心建模与仿真脚本覆盖细胞构建、车道/路段配置、相位切换、延误读取等、11个.png示意图辅助理解模型结构、3个.md说明文档整体仅82KB轻量易部署。目前已有455人学习下载。项目中提供了CTM仿真主程序、四交叉口示例、输入初始化文件及完整的延迟/排队/车道输出分析函数并附有开发日志与使用说明。通过研读代码与示例可快速掌握在MATLAB中搭建CTM网络、设定信号相位、读取仿真指标的方法并进一步开展信号控制策略的对比与优化研究兼具学术探索与实际工程参考价值。1. 拿到 ctm_matlab-master 之后先弄清楚 CTM 在交叉口到底算的是什么解开 ctm_matlab-master.zip 之后里面大概率是一个用 MATLAB 写的 CTM 交通流仿真骨架核心对象是交叉口算的是车辆在元胞之间的流入流出。CTM 的全称是 Cell Transmission Model1994 年由 Daganzo 提出的 LWR 宏观交通流模型的离散化格式它把道路切成等长的元胞每个时间步只做两件事按流量守恒更新每个元胞的车辆数再用密度-流量关系限制上下游能传多少车。看起来简单到像一道数组练习题但它能复现排队形成、激波回传、绿灯放行和红灯锁车的全过程。对交通工程和相关专业的从业者来说这套代码最大的价值不是跑通一个仿真而是把信号配时怎么影响排队长度这个问题变成可重复实验的算例。本文按理论、MATLAB 实现、参数校准、进阶用法四层展开目标是让读者拿到任意一个 CTM 交叉口代码后能快速看懂网络定义、改参数并验证结果。2. CTM 交叉口模型的理论基础与参数设定2.1 元胞划分与流量守恒方程CTM 的第一步是把道路离散成等间距的元胞。假设一个进口方向长 400 米元胞长度取 100 米就会得到 4 个普通元胞再加一个靠近停车线的交叉口控制元胞。时间步长必须满足 Courant 条件自由流速度乘以时间步长不能超过元胞长度否则一次更新会跳过下游元胞仿真直接失真。常见做法是取元胞长度 100 米、时间步长 2 秒自由流速度 50 km/h 时每步最多走 27.8 米安全满足条件。每个元胞的车辆数演化遵循守恒方程 n_i(t1) n_i(t) f_{i-1}(t) - f_i(t) 其中 f_i(t) 是第 i 个元胞和第 i1 个元胞之间的流量。这个方程的意思是这个步长内进来的车减去出去的车就是本元胞车辆数的变化。CTM 的全部精髓都集中在 f_i(t) 怎么算以及交叉口元胞如何被信号状态约束。在 MATLAB 实现里整个道路状态就是一个列向量 n长度等于元胞总数。更新时用向量化运算同时算出所有界面的流量 f再用加减法完成更新。这里的 n 保存的是整数车辆数还是连续车流密度取决于应用场景信号配时方案对比用连续值即可排队长度统计更关心的是密度阈值而不是单辆车的位置。2.2 发送函数与接收函数的物理含义Daganzo 原始 CTM 把界面流量拆成发送能力和接收能力两个概念。上游元胞能送出去多少车取当前车辆数和饱和流率的最小值这就是发送函数下游元胞能收进来多少车取剩余容量和饱和流率的最小值这就是接收函数。界面流量最终取两者的较小值。这个机制天然处理了自由流和拥堵两个状态不堵时上下游都缺车流流量由上游供给决定堵时下游容量不足流量被接收能力钳制排队向上游延伸。这里有一个新手常忽略的细节。如果基本图采用三角形近似拥堵状态的接收能力应该写成 min(剩余容量, 波速比例 × 饱和流率)其中波速 w q_max / (k_j - k_c)。要是代码里直接把接收能力写成 min(剩余容量, Q)相当于默认 w v_f会在高速公路上游排队估计时产生明显误差。对城市交叉口 200 米左右的进口道来说误差可能不大但做多路口网络时建议按三角形基本图的完整形式修正。典型参数表如下参数符号取值示例说明元胞长度dx100 m划分道路的基本单元长度时间步长dt2 s满足 v_f * dt dx自由流速度v_f50 km/h决定自由流传播速度每车道饱和流率q_max1800 veh/h绿灯时的最大通过率拥堵密度k_j120 veh/km/lane元胞可容纳的最大密度临界密度k_c36 veh/km/lane通行能力对应的密度反向波速w18 km/h由三角形基本图推导这些参数必须自洽。先给定 v_f、q_max、k_j、wk_c 由 q_max / v_f 推出再用 w q_max/(k_j-k_c) 校验。如果从别处抄来的参数组不满足这个关系仿真结果在拥堵段会出现车凭空消失或密度超过拥堵密度的现象。2.3 交叉口建模把信号当成动态容量约束交叉口和路段的区别在于绿灯/红灯会周期性改变通行能力。最简单可靠的做法是将停车线前那个元胞的接收能力乘以信号状态。红灯时接收能力设为 0下游元胞收不到车排队在停车线上游累积绿灯时恢复正常饱和流率车流以最大能力放行。启动波损失、黄灯和清空时间不单独建模而是折算进有效绿灯时间也就是从总绿灯时长里扣除 2 到 3 秒。如果交叉口有多个进口方向每个进口各建一条 CTM 链路它们共享同一个信号相位表。代码层面就是把每个方向的 green 向量预先生成绿灯为 1红灯为 0。这种做法能直接回答这个相位方案下东进口排队会不会回溢到上一个路口这类问题算力开销比微观仿真低几个数量级。提示不要试图在 CTM 里逐辆描述转向行为。CTM 是宏观模型车流是连续的转向比例只能通过各方向需求的分配来体现。3. 用 MATLAB 搭建单交叉口 CTM 仿真3.1 从路网拓扑到向量化数据结构先做一个最简但有代表性的场景单车道、单方向进口道接交叉口再接下游路段信号只影响交叉口元胞的接收能力。这个模型跑通之后向多进口多车道扩展只是复制粘贴加参数重组的问题。MATLAB 里用两个向量保存状态n 是元胞车辆数向量Q 与 Ncap 分别是每个元胞的流出能力和容量。% CTM_intersection_demo.m % 单方向进口道 单交叉口 下游路段的稀疏 CTM clear; clc; dx 100; % 元胞长度单位 m dt 2; % 时间步长单位 s vf 50 / 3.6; % 自由流速度50 km/h 转 m/s qmax 1800 / 3600 * dt; % 每步单车道饱和通过量veh/step kj 0.12; % 拥堵密度veh/m/车道 lanes 2; % 车道数 Q qmax * lanes; % 元胞流出能力veh/step Ncap kj * dx * lanes; % 元胞最大车辆数veh N 10; % 元胞总数最后一个是交叉口控制元胞 n zeros(N, 1); % 当前每元胞车辆数 f zeros(N - 1, 1); % 元胞间流量 T 300; % 总仿真步数对应 600 秒 inflow 0.8; % 上游每步注入车辆数约 1440 veh/h green [zeros(60, 1); ones(80, 1); zeros(60, 1); ones(80, 1); zeros(20, 1)]; % 先红灯 120s再绿灯 160s再红灯 40s模拟一个完整周期 trip_log zeros(T, N); % 记录时空状态用于画图 for t 1:T % 边界流入简单均匀注入 n(1) n(1) inflow; % 发送能力当前车辆数不超过饱和能力 S min(n(1:end-1), Q); % 接收能力受剩余容量限制简化版不考虑反向波速 R min(Ncap - n(2:end), Q); % 交叉口约束红灯时接收能力归零绿灯恢复 R(end) min(R(end), green(t) * Q); % 界面流量取收发较小值 f min(S, R); % 流量守恒更新 n(2:end) n(2:end) f; n(1:end-1) n(1:end-1) - f; % 记录输出元胞的离开流量用于流量统计 outflow(t) f(end); trip_log(t, :) n; end这段代码里 S 和 R 都是长度为 N-1 的向量分别对应除最后一个元胞外的所有上游元胞发送能力和除第一个元胞外的所有下游元胞接收能力。关键的交叉口逻辑在 R(end) 这一行最后一个元胞作为交叉口红灯时 green(t)0接收能力变成 0没有车能越过停车线绿灯时恢复 Q。通过 min 函数两两取小任何一步都不会出现流量为负或元胞超容的情况。inflow 参数按 1800 veh/h 折算过来就是 1.0这里取 0.8 模拟中等负荷。这个脚本不需要 MATLAB 工具箱任何 R2016 以后的版本都能直接运行。如果机器上装的是 R2023b 或更新版本注意脚本文件名不要和内置函数重名即可。3.2 信号相位表与多进口扩展上面的代码只放行了一个方向。真实交叉口至少是东西、南北两个方向交替放行。这时不再改单条链路的代码而是把两条链路拼成一个共享信号相位的结构。常见做法是把两条路的状态向量拼接成一个长向量或者用 MATLAB struct 保存每个进口方向自己的 n、S、R然后在一个循环里按相位表逐方向更新。% 两相位两进口的简写架构 approach(1).n zeros(N, 1); % 东进口 approach(2).n zeros(N, 1); % 西进口 phase_plan [1 0 1 0]; % 相位1放行东进口相位3放行西进口 for t 1:T active get_phase(t); % 根据时间返回当前放行方向 for a 1:2 % 只对允许放行的进口方向应用 CTM 更新 if ismember(a, active) update_approach(approach(a)); else % 红灯方向只推进排队不放行 approach(a).n(end) approach(a).n(end); end end end这段伪代码强调的是编程模式不要为每个方向复制整套 CTM 核心而是把每个进口的元胞链路封装成一个结构体更新逻辑复用同一个函数。红灯方向照常更新上游车辆数只是最后一个元胞不产生输出流。这样扩展成四相位、加入左转专用相位时改动只发生在相位表和结构体定义处。3.3 时空图与排队长度可视化仿真跑完之后工作量的一半在结果验证上。最直观的输出是时空图横轴是元胞位置纵轴是时间颜色深浅代表密度。直接用 imagesc 显示三元组矩阵即可。排队长度可以从密度超过临界密度的元胞位置反推出来。% 时空图行是时间步列是元胞位置 figure(Name, CTM 时空图); imagesc(trip_log); colorbar; xlabel(元胞编号); ylabel(时间步); title(密度演化 时空图); caxis([0 Ncap]); % 让颜色上限固定为元胞容量 % 排队长度密谋超过临界密度的元胞视为排队 kc qmax / (vf * dt); % 临界密度对应的车辆数 queue_len zeros(T, 1); for t 1:T idx find(trip_log(t, :) kc); if ~isempty(idx) queue_len(t) (N - max(idx)) * dx; end end plot(queue_len);这里用 caxis 固定颜色范围可以避免不同时刻密度差异造成的伪色差。队列计算逻辑是从下游往上游找最后一个密度超过临界值的元胞其到停车线的距离就是排队长度。绿灯启动后车流以饱和流率离开排队长度会逐段衰减成功的 CTM 仿真一定能看到这种锯齿形变化曲线。4. 参数标定、验证方法与常见坑4.1 首先验证基础路段自由流与激波传播交叉口仿真任何结论的有效性都建立在基础 CTM 正确的基础上。改交叉口之前先把信号约束去掉让一条无信号路段运行 1000 秒检查两件事。第一在入口给一个持续 50 步的脉冲流量观察它在时空图上的运动速度是不是接近 v_f第二让下游元胞容量突然收紧观察拥堵激波是否以大约 w 的速度向上游移动。这两项通过说明发送接收函数的参数没有配错。验证激波时注意接收函数的完整形式。只用剩余容量限制的简化版接收函数会高估拥堵状态下的流入能力导致激波回传速度偏快。用三角形基本图推导的波速公式做一次定量比对% 理论激波速度与实际模拟速度对比 qmax 0.5; kj 0.12; kc 0.036; % 均为 per meter per lane 的单位 w_theory qmax / (kj - kc) % 约 18 km/h % 从仿真时空图中提取激波轨迹的斜率与 w_theory 比较如果两者差超过 20%优先检查元胞长度和时间步长是否满足 Courant 条件其次检查接收函数是否遗漏了波速因子。4.2 用排队验证交叉口信号逻辑信号逻辑错误的典型表现是排队长度与红灯时长不成线性关系。在一个恒定到达率下红灯期排队车辆数约等于到达率乘以红灯时长绿灯期按饱和流率释放。做一个简单的敏感性实验固定周期 120 秒分别将绿信比设为 0.3、0.4、0.5观察稳态排队长度和最大排队长度。绿信比 0.4 到 0.5 的变化应该显著改变排队峰值如果曲线几乎不动大概率是接收函数里信号约束没用上。MATLAB 中做这种批量实验不需要重写仿真主循环把绿信比作为外层循环参数内部用同一套 CTM 核心计算每次记录最大排队长度。这也是 CTM 最有工程价值的地方信号配时的候选方案有几十组微观仿真跑一次要几分钟CTM 每组只要几秒钟直接可以用 fminbnd 之类的函数做单变量绿信比寻优。4.3 三个高频坑流量不守恒、信号突变、密度超限第一个坑是流量不守恒车凭空消失。常见原因是边界注入和元胞更新的顺序不对例如先更新 n(1:end-1) 再更新 n(2:end)导致中间元胞在同一个时间步内被加减两次但边界元胞没有配对更新。第二个坑是信号从红灯切绿灯的瞬间green(t)*Q 让接收能力瞬间从 0 跳到 Q产生一个非常大的流量脉冲。缓解办法是让接收能力按 2 到 3 步线性爬坡模拟启动波。第三个坑是密度超过元胞容量 Ncap通常因为 initial condition 在红灯期间仍然向上游元胞注入车辆但上游元胞已经满了注入过程没有做容量检查。现象可能原因检查方法车辆总数漂移边界更新顺序错误统计 sum(n)outflow 是否守恒绿灯瞬间流量尖峰接收能力跳变平滑过渡绿闪 2-3 个时间步密度超过容量注入未检查剩余容量打印超限元胞编号和时间步5. 用流量守恒核验作为最终技术手段无论 CTM 代码结构多清晰交接或改参数之后都要做一次守恒性定量检验。这一步的核心是一个断言排除边界流动之后整个路网内的车辆总数变化必须严格等于累计流入与累计流出的差值。MATLAB 里实现这个检查只需要几行代码但能拦截掉一大部分隐蔽 bug。% 守恒性检验每一时刻都满足 n_total n_initial inflow_cum - outflow_cum n_initial sum(n0); for t 1:T inflow_cum inflow_cum inflow(t); outflow_cum outflow_cum outflow(t); total_now sum(current_n); err(t) abs(total_now - (n_initial inflow_cum - outflow_cum)); end if max(err) 1e-6 error(CTM 流量不守恒最大误差 %.2e, max(err)); end浮点误差累计到 1e-6 量级是正常的一旦达到 0.1 量级就是结构性问题。在做多进口交叉口扩展时把每个进口方向分别记录 inflow 与 outflow再汇总检验能定位到具体是哪一个方向引起的泄漏。进阶用法中还可以将这个核验函数和绿信比敏感度分析组合在批量搜索最优配时方案的循环内先跑守恒检查检查通过再记录排队指标否则丢弃该组参数并给出警告。成熟的交通流仿真工作流中CTM 通常不作为最终结论的唯一依据而是先粗筛信号方案筛出的少数备选再交给 Vissim 或 SUMO 这类更精细的仿真器验证兼顾计算效率和保真度。守恒核验就是粗筛环节的最后一班岗把这个关守住后面的一切指标统计才可信。本文还有配套的精品资源点击获取
返回列表