3、交通需求建模:交通流理论简介、OD矩阵概念、flow与route定义、随机交通生成
好,咱们进入第三章。这一章我把它叫做「交通仿真的灵魂」。
为什么这么说?你想想看,路网建得再漂亮,信号灯配得再花哨,如果没有车在上面跑,那就是个空壳子。车怎么来、往哪去、什么时候出发——这些就是交通需求建模要解决的问题。
我个人习惯把这一章分成四个台阶:先搞懂交通流的基本规律,再理解OD矩阵这个核心概念,然后学会在SUMO里定义flow和route,最后玩转随机交通生成。咱们一个一个来。
3.1 交通流理论简介:别被名字吓到
交通流理论,说白了就是研究「车流」的物理规律。你开车堵在路上时,有没有想过为什么车一多速度就上不去?这就是交通流理论要回答的问题。
三个核心参数,记住就行:
- 流量(Flow):单位时间内通过某断面的车辆数,单位veh/h。我习惯叫它「车流密度」。
- 密度(Density):单位长度路段上的车辆数,单位veh/km。密度高了,车距就小了。
- 速度(Speed):车辆的平均行驶速度,单位km/h。
它们之间有个基本关系:流量 = 密度 × 速度。嗯,就这么简单。但实际中你会发现,速度会随着密度增加而下降——这就是所谓的「速度-密度关系」。
我在项目中遇到过一个典型场景:某城市快速路,早高峰时密度达到80veh/km,速度从80km/h掉到20km/h,流量反而下降了。这就是「过饱和」状态——车太多,谁也走不快。
在SUMO里,你不需要手动算这些。但理解这个关系,能帮你判断仿真结果是否合理。比如你设了一个每小时2000辆的流量,结果路网里堵成一锅粥——那说明你的路网容量不够,或者流量设得太高了。
3.2 OD矩阵概念:从哪来到哪去
OD矩阵,全称是Origin-Destination Matrix。说白了就是一张表,记录着「从哪个区域出发,要去哪个区域」的车流量。
举个例子:
| 出发\到达 | 区域A | 区域B | 区域C |
|---|---|---|---|
| 区域A | 100 | 300 | 200 |
| 区域B | 250 | 50 | 400 |
| 区域C | 150 | 350 | 80 |
这个表的意思是:从区域A到区域B,每小时有300辆车。从区域B到区域C,每小时有400辆车。对角线上的数字(比如区域A到区域A)表示区域内出行。
避坑指南:我曾经在做一个城市级仿真时,OD矩阵里把区域A到区域B的流量写反了,结果仿真出来的交通流向完全不对。检查了三天才发现是矩阵转置的问题。所以,拿到OD矩阵后,先手动验证几个关键对的值。
在SUMO里,OD矩阵通常不会直接写进代码。你需要把它转换成flow或route定义。怎么转?往下看。
3.3 flow与route定义:让车跑起来
在SUMO里,有两种方式定义车辆怎么走:flow和route。
route:定义一条具体的路径。比如「从edge1出发,经过edge2、edge3,到达edge4」。每个车辆都走同一条路。
flow:定义车流。你只需要指定出发边、到达边、流量大小,SUMO会自动为每辆车计算路径。
我个人更推荐用flow,尤其是做大规模仿真时。为什么?因为route需要你手动指定每一条路径,而flow只需要OD对,SUMO会利用Dijkstra算法自动找最短路径。
来看一个flow定义的例子:
<routes>
<vType id="car" accel="2.6" decel="4.5" sigma="0.5" length="4.5" maxSpeed="50"/>
<flow id="flow_AB" type="car" from="edge_A" to="edge_B" begin="0" end="3600" vehsPerHour="500"/>
<flow id="flow_BC" type="car" from="edge_B" to="edge_C" begin="0" end="3600" vehsPerHour="300"/>
</routes>
这段代码的意思是:从edge_A到edge_B,每小时500辆车,持续1小时。从edge_B到edge_C,每小时300辆车。
注意:vehsPerHour是流量参数,但SUMO实际生成车辆时会考虑随机性。如果你想要精确控制车辆数,可以用number参数代替。
如果你需要更复杂的路径,比如车辆必须经过某些特定路段,那就用route:
<routes>
<route id="route_1" edges="edge_A edge_B edge_C edge_D"/>
<vehicle id="veh_1" type="car" route="route_1" depart="0"/>
<vehicle id="veh_2" type="car" route="route_1" depart="10"/>
</routes>
嗯,这里每个车辆都要单独定义出发时间。如果车多,写起来很累。所以大规模仿真时,我几乎只用flow。
3.4 随机交通生成:让仿真更真实
真实世界的交通不是均匀的。车流有高峰有低谷,有随机波动。SUMO提供了几种随机化手段:
- 随机出发时间:用
departPos="random"让车辆在路段上随机位置出发。 - 随机速度:通过
speedFactor参数让每辆车的速度在基准值附近波动。 - 随机路径:用
routeDistribution让车辆从多条路径中随机选择。 - 随机流量:用
poisson分布生成车辆到达时间间隔。
来看一个带随机性的flow定义:
<routes>
<vType id="car" accel="2.6" decel="4.5" sigma="0.5" length="4.5" maxSpeed="50" speedFactor="0.9" speedDev="0.1"/>
<flow id="flow_AB" type="car" from="edge_A" to="edge_B" begin="0" end="3600" vehsPerHour="500" departPos="random"/>
</routes>
这里speedFactor="0.9" speedDev="0.1"的意思是:每辆车的速度会在基准速度的0.9倍附近波动,标准差为0.1。也就是说,有的车开得快,有的车开得慢——这才像真实路况嘛。
我曾经做过一个高速公路仿真,一开始所有车都按统一速度跑,结果仿真出来的交通流跟流水线似的,一点都不真实。后来加了随机速度因子,车流开始出现自然的跟驰和变道行为,仿真结果跟实测数据对上了。
还有一个常用的随机化手段是poisson分布。在SUMO里,你可以用flow的poisson属性:
<flow id="flow_AB" type="car" from="edge_A" to="edge_B" begin="0" end="3600" vehsPerHour="500" departPos="random" poisson="true"/>
加上poisson="true"后,车辆到达时间间隔服从泊松分布。这意味着什么?有时候两辆车几乎同时到达,有时候间隔好几秒——这才是真实交通的随机性。
知识体系总览
下面这张图,是我自己梳理的本章知识结构。你可以把它当作一个导航图:
好,这一章的内容就到这儿。交通需求建模是仿真的起点,也是决定仿真质量的关键。你想想看,如果OD矩阵不准,后面的信号优化、排放计算全都是空中楼阁。所以,花时间把这一章的内容吃透,后面的路就好走了。
我的个人习惯:每次新建仿真项目,我都会先画一张OD矩阵的草图,哪怕只有三个区域。然后对照着写flow定义,最后加随机参数。这样一步步来,不容易出错。
可可精品资料库