2. SUMO核心概念:网络、路线、车辆类型与交通需求
各位同学,欢迎来到第二章。上一章我们聊了SUMO能干什么,这一章咱们得把地基打牢。
说实话,我刚接触SUMO那会儿,最头疼的就是这几个概念——网络、路线、车辆类型、交通需求。它们听起来都懂,但一上手就乱。后来我才明白,这四样东西就是SUMO世界的「四根柱子」。你把这四根柱子立稳了,后面搭建任何场景都顺风顺水。
2.1 网络(Network)—— 仿真的「地图」
网络是什么?说白了,就是车跑的路。在SUMO里,网络由两个基本元素构成:节点(Node)和路段(Edge)。
- 节点:路口、交叉点、或者道路的端点。你可以把它想象成地图上的「点」。
- 路段:连接两个节点的道路。它是有方向的,有车道数,有速度限制。
举个例子,一个十字路口,中间那个交叉点是节点,四条伸出去的路是路段。就这么简单。
核心要点:网络文件的后缀是 .net.xml。它是SUMO仿真的「底盘」,所有车辆都在这个网络上跑。
我个人习惯,拿到一个项目先画网络。网络画不好,后面全是白费。我在项目中遇到过好几次,因为网络里一个节点坐标偏了,结果车辆全在路外漂移……嗯,那画面挺尴尬的。
2.2 路线(Route)—— 车怎么走
有了路,车怎么走?这就是路线要解决的问题。
路线,就是一系列路段的顺序列表。比如:从路段A出发,经过路段B,最后到路段C。SUMO里的车会严格按照这个顺序跑。
<routes>
<route id="route_1" edges="edgeA edgeB edgeC"/>
</routes>
你看,上面这段代码定义了一条叫 route_1 的路线,它依次经过 edgeA、edgeB、edgeC。
小技巧:路线里的路段必须首尾相连。如果edgeA的终点不是edgeB的起点,车会卡住。我曾经因为这个bug排查了一下午……
你想想看,路线其实就是给车画了一条「导航路径」。没有路线,车就是无头苍蝇。
2.3 车辆类型(VType)—— 车长什么样
车和车不一样。小轿车、公交车、卡车,它们的长度、速度、加速度都不一样。在SUMO里,我们用车辆类型(VType)来定义这些属性。
| 属性 | 含义 | 示例值 |
|---|---|---|
| id | 类型名称 | "car" |
| length | 车身长度(米) | 5.0 |
| maxSpeed | 最高速度(m/s) | 50.0 |
| accel | 加速度(m/s²) | 2.6 |
| decel | 减速度(m/s²) | 4.5 |
| sigma | 驾驶不完美度(0-1) | 0.5 |
<vType id="car" length="5.0" maxSpeed="50.0" accel="2.6" decel="4.5" sigma="0.5"/>
这段代码定义了一种叫 car 的车辆类型。它长5米,最高速度50m/s(约180km/h),加速和减速都挺正常。
注意:sigma这个参数很有意思。它模拟了驾驶员的不完美性。sigma=0表示完美驾驶,sigma=1表示完全随机。我一般设0.5,比较真实。
为什么要定义车辆类型?因为不同车的表现差异太大了。你让一辆卡车和一辆跑车用同样的参数,仿真结果肯定不对。我在做物流仿真时,专门给货车定义了低加速、高减速的类型,效果才真实。
2.4 交通需求(Demand)—— 车什么时候来
网络有了,路线有了,车类型也有了。但车什么时候出现?出现多少?这就是交通需求要干的事。
交通需求,说白了就是「发车计划」。它告诉SUMO:在什么时间,发什么类型的车,走哪条路线。
<flows>
<flow id="flow_1" type="car" route="route_1" begin="0" end="3600" number="500"/>
</flows>
上面这段代码定义了一个车流:从第0秒到第3600秒(1小时),总共发500辆car类型的车,全部走route_1路线。
你也可以用单个车辆的方式定义:
<vehicles>
<vehicle id="veh_1" type="car" route="route_1" depart="10"/>
<vehicle id="veh_2" type="car" route="route_1" depart="20"/>
</vehicles>
这种方式适合精确控制每一辆车。但如果你要模拟高峰期车流,用flow更省事。
总结一下:网络是「路」,路线是「导航」,车辆类型是「车」,交通需求是「发车计划」。四者缺一不可。
2.5 它们之间的关系 —— 一张图看懂
说了这么多,你可能有点晕。没关系,我画了一张图,把这四个概念的关系串起来。
你看这张图就明白了。网络在最左边,是基础。路线依赖网络,车辆类型独立定义,最后交通需求把路线和车辆类型组合起来,加上时间信息,就生成了完整的仿真场景。
我的经验:刚开始学的时候,别急着写代码。先在纸上把这四个概念画出来。网络长什么样?车走哪条路?车是什么类型?什么时候发车?想清楚了再动手,效率翻倍。
2.6 一个完整的例子
光说不练假把式。咱们来看一个完整的例子,把四个概念串起来。
<!-- 网络文件:simple.net.xml -->
<net>
<node id="A" x="0" y="0"/>
<node id="B" x="100" y="0"/>
<edge id="road1" from="A" to="B" numLanes="2" speed="13.89"/>
<edge id="road2" from="B" to="A" numLanes="2" speed="13.89"/>
</net>
<!-- 路线和车辆定义:simple.rou.xml -->
<routes>
<vType id="sedan" length="4.5" maxSpeed="40.0" accel="2.0" decel="3.5"/>
<route id="route_AB" edges="road1"/>
<flow id="flow_AB" type="sedan" route="route_AB" begin="0" end="100" number="20"/>
</routes>
这个例子很简单:一条双向两车道的路,从A到B。车辆类型是sedan(轿车),20辆车在100秒内从A出发到B。
你把这个跑起来,就能看到一辆辆小轿车从A点开到B点。嗯,虽然简单,但核心逻辑全在里面了。
避坑指南:我曾经犯过一个低级错误——网络文件和路线文件里的路段ID没对上。网络里叫"road_1",路线里写"road1",结果SUMO报错说找不到路段。这种问题排查起来特别烦,所以命名一定要规范,保持一致。
好了,这一章的内容就到这里。四个核心概念——网络、路线、车辆类型、交通需求,你记住了吗?它们是SUMO仿真的基石,后面的所有场景都建立在它们之上。
可可精品资料库