4. 交通需求建模:.rou.xml 文件深度解析
各位同学,今天我们来聊聊交通需求建模。说白了,就是告诉仿真软件:路上跑的都是什么车?从哪来?到哪去?这些信息都写在 .rou.xml 文件里。我个人习惯把这个文件叫做「剧本」——它定义了整个仿真世界的「演员」和「剧情」。
核心要点:.rou.xml 文件 = 车辆类型定义 + 车流生成器 + 路径定义 + 随机路径
4.1 文件结构长什么样?
先看一个最简单的 .rou.xml 骨架:
<?xml version="1.0" encoding="UTF-8"?>
<routes>
<!-- 车辆类型定义 -->
<vType id="car" accel="2.6" decel="4.5" maxSpeed="50" />
<!-- 路径定义 -->
<route id="route1" edges="edge1 edge2 edge3" />
<!-- 车流生成器 -->
<flow id="flow1" type="car" route="route1" begin="0" end="3600" vehsPerHour="600" />
</routes>
嗯,这里要注意:<routes> 是根标签,所有定义都包在里面。我见过新手把标签名写错成 <route>,结果仿真器直接报错——这种低级错误排查起来最浪费时间。
4.2 车辆类型定义:给车「画像」
车辆类型用 <vType> 标签定义。为什么需要这个?你想想看,路上跑的小轿车和公交车,加速能力、最大速度、车身长度能一样吗?
| 属性 | 说明 | 典型值(小轿车) |
|---|---|---|
| id | 类型名称,唯一标识 | "car" |
| accel | 最大加速度 (m/s²) | 2.6 |
| decel | 最大减速度 (m/s²) | 4.5 |
| maxSpeed | 最大速度 (m/s) | 50(约180km/h) |
| length | 车身长度 (m) | 5.0 |
| sigma | 驾驶随机性(0=完美,1=随机) | 0.5 |
我的经验:sigma 参数很多人忽略。我曾经调一个拥堵仿真,怎么跑都不堵车,后来把 sigma 从 0.1 调到 0.5,瞬间就真实了——因为现实中司机不可能都完美驾驶。
定义多种车辆类型也很简单:
<vType id="car" accel="2.6" decel="4.5" maxSpeed="50" length="5.0" sigma="0.5" />
<vType id="bus" accel="1.2" decel="3.0" maxSpeed="30" length="12.0" sigma="0.3" />
<vType id="truck" accel="1.0" decel="2.5" maxSpeed="25" length="15.0" sigma="0.4" />
4.3 车流生成器:让车「流」起来
手动一辆一辆发车?太傻了。用 <flow> 标签,一句话就能生成上千辆车。
<flow id="flow_main" type="car" route="route1" begin="0" end="3600" vehsPerHour="1200" />
参数解读:
- id:这个车流的名字,方便后面引用或修改
- type:引用上面定义的车辆类型
- route:引用下面定义的路径
- begin / end:发车时间窗口(秒),0 到 3600 就是仿真开始后第一小时
- vehsPerHour:每小时发车数,1200 就是平均 3 秒一辆
避坑指南:我曾经把 vehsPerHour 写成 10000,结果仿真器直接卡死——车太多,路网根本消化不了。建议先从小流量开始调试,逐步增加。
还可以用 probability 替代 vehsPerHour,按概率发车:
<flow id="flow_random" type="car" route="route1" begin="0" end="3600" probability="0.1" />
这个 0.1 表示每个仿真步(默认 1 秒)有 10% 的概率发一辆车。适合模拟随机到达的交通流。
4.4 路径定义:给车指路
路径用 <route> 标签定义。说白了就是告诉车:按什么顺序经过哪些路段。
<route id="route_A_to_B" edges="edge1 edge2 edge3 edge4" />
<route id="route_A_to_C" edges="edge1 edge5 edge6" />
这里 edges 属性里写的是路网文件中定义的路段 ID,用空格分隔。车会从第一个路段进入,依次经过,最后在最后一个路段消失。
我建议路径命名要有规律,比如 route_起点_终点,不然几十条路径混在一起,后期维护起来想哭。
4.5 随机路径:让车自己「选路」
有时候我们不想指定具体路径,想让车在路网中随机游走。这时候用 <routeDistribution> 或者直接在 flow 里用 from 和 to 属性。
方法一:路径分布
<routeDistribution id="random_routes">
<route id="r1" edges="edge1 edge2 edge3" probability="0.5" />
<route id="r2" edges="edge1 edge4 edge5" probability="0.3" />
<route id="r3" edges="edge1 edge6" probability="0.2" />
</routeDistribution>
<flow id="flow_random" type="car" route="random_routes" begin="0" end="3600" vehsPerHour="600" />
方法二:只指定起终点(需要路网支持)
<flow id="flow_od" type="car" from="edge1" to="edge5" begin="0" end="3600" vehsPerHour="800" />
仿真器会自动计算最短路径。嗯,这里要注意:如果路网中有拥堵,最短路径可能不是最优的——但这是另一个话题了。
4.6 知识体系总览
下面这张图帮你理清本章的核心逻辑:
4.7 实战小贴士
最后分享几个我踩过的坑:
- ID 不要用中文:XML 解析器对中文支持不好,老老实实用英文或拼音
- 先验证再跑仿真:用
sumo -c your.sumocfg --validate检查文件语法 - 流量从低到高:先跑 100 vehsPerHour 看看路网能不能通,再逐步加到目标值
- 路径别写错:edges 里的路段 ID 必须在 .net.xml 中存在,否则车发不出来
我的习惯:每次修改 .rou.xml 后,先用 sumo-gui 打开跑 10 秒看看效果。肉眼确认没问题了,再跑批量仿真。这比盯着日志文件找错误高效多了。
好了,这一章的内容就到这里。记住:交通需求建模是仿真的灵魂——路网再漂亮,车流定义错了,结果全是废的。下一章我们聊聊如何用 Python 动态生成 .rou.xml,实现更灵活的交通需求控制。