4、路网编辑进阶:道路类型与限速设置、交叉口转向规则与信号灯配置、公交专用道与自行车道添加、路网可视化与错误检查
好,咱们继续往下走。上一节我们把路网的基本骨架搭起来了,能跑车了。但说实话,那个路网太「素」了,像个毛坯房。这一节,咱们要做的就是精装修——把道路类型、限速、转向、信号灯、公交专用道、自行车道这些细节全部怼进去。
我个人的习惯是,先把路网文件用文本编辑器打开看一眼,心里有个底。但真正动手改,还是得靠 netedit 或者直接写 .net.xml 的配置。别怕,咱们一步步来。
4.1 道路类型与限速设置
SUMO 里的道路类型,说白了就是给路贴个标签。比如主干道、次干道、支路、高速。每种类型可以有自己的默认限速、车道数、甚至外观颜色。
为什么要区分道路类型? 你想想看,如果所有路都一个速度,那仿真出来的车流跟现实差太远了。现实中没人会在小区里开 80 码,对吧?
在 .net.xml 里,道路类型定义在 <type> 标签里。举个例子:
<type id="highway.primary" priority="3" numLanes="2" speed="22.22" />
<type id="highway.secondary" priority="2" numLanes="1" speed="13.89" />
<type id="highway.residential" priority="1" numLanes="1" speed="8.33" />
这里 speed 的单位是 m/s。22.22 m/s 换算一下就是 80 km/h。我刚开始做项目时,经常忘记换算单位,结果仿真出来的车都像蜗牛爬。后来我学乖了,直接在脑子里记:除以 3.6 就是 m/s。
speed 字段。改完后记得点「保存」,不然白干。
如果你想让某条路单独限速,而不是跟着类型走,可以在 <edge> 里单独指定 speed 属性。比如:
<edge id="my_slow_road" from="node1" to="node2" type="highway.residential" speed="5.56"/>
这样,即使它属于 residential 类型,实际限速也只有 20 km/h。嗯,这里要注意:单独指定的限速会覆盖类型默认值。
4.2 交叉口转向规则与信号灯配置
交叉口是路网里最容易出幺蛾子的地方。我记得有一次,仿真跑着跑着,所有车都在一个路口堵死了。排查了半天,发现是转向规则没配好——左转车和直行车抢道,谁也不让谁。
SUMO 里,交叉口的转向规则由 <connection> 标签控制。它定义了从哪条路、哪个车道,可以转到哪条路、哪个车道。举个例子:
<connection from="edge1" to="edge2" fromLane="0" toLane="0" dir="s" state="M"/>
这里的 dir 是方向:s 直行,l 左转,r 右转。state 是信号灯状态:M 表示主路有优先权,m 表示支路需要让行,G 是绿灯,r 是红灯。
信号灯配置 稍微复杂一点。你需要先定义一个 <tlLogic>,然后给它配相位(phase)。每个相位里,哪些方向是绿灯,哪些是红灯,清清楚楚。
<tlLogic id="my_traffic_light" type="static" programID="0" offset="0">
<phase duration="30" state="GGGrrr"/>
<phase duration="5" state="yyyrrr"/>
<phase duration="30" state="rrrGGG"/>
<phase duration="5" state="rrryyy"/>
</tlLogic>
你看,state 字符串里每个字符对应一个信号灯组。G 是绿灯,y 是黄灯,r 是红灯。顺序跟你定义的连接顺序一致。我曾经犯过一个低级错误:相位时长写成了 300 秒,结果仿真里车等了 5 分钟红灯……嗯,从那以后我每次配信号灯都会反复检查时长。
state 字符串长度必须跟你定义的连接数一致。少一个字符,SUMO 直接报错,不跟你商量。
4.3 公交专用道与自行车道添加
现在很多城市都在推公交优先、绿色出行。仿真里也得体现出来。SUMO 支持在道路上划出专用车道,比如公交专用道、自行车道。
实现方式其实很简单:在 <lane> 标签里加一个 allow 或 disallow 属性,限制哪些车辆类型可以使用该车道。
<lane id="my_road_0" index="0" allow="bus" speed="13.89"/>
<lane id="my_road_1" index="1" allow="bicycle" speed="8.33"/>
<lane id="my_road_2" index="2" allow="private" speed="13.89"/>
上面这个例子,车道 0 只允许公交车走,车道 1 只允许自行车走,车道 2 只允许私家车走。你想想看,这样仿真出来的场景,是不是跟现实里的公交专用道一模一样?
我个人建议,在添加公交专用道时,最好同时设置 busStop。不然公交车光跑不停,那还叫公交吗?
<busStop id="stop1" lane="my_road_0" startPos="50" endPos="70" lines="101 202"/>
这里 startPos 和 endPos 是公交站台在车道上的起止位置,单位是米。lines 是停靠的公交线路号。
4.4 路网可视化与错误检查
路网建好了,别急着跑仿真。先可视化检查一遍。SUMO 自带的 netedit 就是最好的检查工具。
打开 netedit,加载你的 .net.xml 文件。然后你可以:
- 放大缩小,看看有没有断头路、孤立的节点。
- 选中一条路,看它的属性对不对,限速、车道数、类型。
- 检查交叉口,看转向箭头是不是都画出来了,有没有缺失的连接。
SUMO 还提供了一个命令行工具 netcheck,可以自动检测路网里的问题。用法很简单:
netcheck --net-file my_network.net.xml --output-file errors.xml
它会生成一个错误报告,告诉你哪些地方有问题。比如:
- 某条路的
from节点不存在 - 某个交叉口的连接数不匹配
- 某条车道的
allow属性写错了
我记得有一次,我导出一个很大的路网,跑 netcheck 出来 200 多个警告。当时头都大了。但一个个排查下来,发现大部分都是小问题——比如节点坐标重复、车道长度不一致。修完之后,仿真就顺畅多了。
最后,我强烈建议你养成一个习惯:每次修改路网后,都跑一遍 netcheck。这就像写代码要编译一样,能帮你省下大量调试时间。
好了,这一节的内容就到这儿。路网编辑进阶,说白了就是让仿真更真实。你想想看,如果连道路类型、限速、信号灯这些基础东西都没配好,那后面的交通流生成、路径规划,全都是空中楼阁。
下一节我们会进入更刺激的部分——交通需求生成。到时候你会看到,怎么让车流真正「活」起来。
- 道路类型用
<type>定义,限速单位是 m/s - 交叉口转向用
<connection>控制,信号灯用<tlLogic>+<phase> - 公交专用道和自行车道通过
allow/disallow实现 - 可视化用 netedit,错误检查用 netcheck,两者结合效果最佳