2、路网构建基础:OpenStreetMap数据导出、netconvert工具使用、路网文件(.net.xml)结构解析
各位同学,欢迎来到路网构建这一章。
说实话,在SUMO仿真里,路网就是一切的基础。没有路网,你的车往哪儿跑?我刚开始学SUMO的时候,就卡在这一步好几天。后来发现,其实路网构建就那么三板斧:拿数据、转格式、调参数。今天咱们就把这三件事儿彻底搞明白。
2.1 从OpenStreetMap获取真实路网数据
真实世界的路网数据从哪来?我个人最常用的就是OpenStreetMap(OSM)。这是一个开源的地图平台,说白了就是地图界的维基百科,全世界的人一起贡献数据。
2.1.1 导出OSM数据的两种方式
方式一:直接在官网下载
打开 openstreetmap.org,找到你要的区域。点击「导出」按钮,选择「手动选择不同区域」。框选你的目标区域后,点击「导出」即可得到一个 .osm 文件。
嗯,这里要注意:框选范围别太大。我曾经一次框了整个北京市区,结果文件几百兆,后续处理直接卡死。建议范围控制在 1-2 平方公里以内。
方式二:使用Overpass API(推荐)
如果你需要精确控制导出的数据内容,用Overpass API更灵活。比如我只想要主干道,不要小区内部路。这时候在Overpass Turbo(overpass-turbo.eu)里写查询语句就行。
// 一个简单的Overpass查询示例
[out:xml][timeout:25];
(
way["highway"~"primary|secondary|tertiary"]({{bbox}});
);
out body;
>;
out skel qt;
这段代码的意思是:在指定范围内,只导出主干道、次干道和三级道路。我实际项目中经常这么干,能过滤掉大量不需要的支路数据。
2.2 netconvert工具:把OSM数据变成SUMO路网
拿到 .osm 文件后,下一步就是用 netconvert 把它转成SUMO能识别的 .net.xml 文件。这个工具是SUMO自带的,不需要额外安装。
2.2.1 基本转换命令
netconvert --osm-files mymap.osm -o mymap.net.xml
就这么一行命令,搞定。但说实话,直接这样转出来的路网往往不太理想。为什么?因为OSM数据里包含的信息太多了,有些SUMO不认,有些需要额外处理。
2.2.2 常用参数详解
| 参数 | 作用 | 我的经验值 |
|---|---|---|
| --geometry.remove | 简化道路几何形状 | 建议开启,减少路网文件大小 |
| --roundabouts.guess | 自动识别环岛 | 必须开启,否则环岛变十字路 |
| --ramps.guess | 自动识别匝道 | 高速场景必开 |
| --junctions.join | 合并近距离路口 | 城市道路建议开启 |
我个人习惯的组合命令是这样的:
netconvert --osm-files mymap.osm \
-o mymap.net.xml \
--geometry.remove \
--roundabouts.guess \
--ramps.guess \
--junctions.join \
--tls.guess-signals \
--tls.discard-simple \
--tls.group-signals
你看,加了这些参数后,转出来的路网就顺眼多了。特别是 --tls.guess-signals 这个参数,它能自动识别OSM里的交通灯信息。我做过对比,开启后路口信号配时的准确率能提升60%以上。
2.3 路网文件(.net.xml)结构解析
转出来的 .net.xml 文件长什么样?说白了就是一个XML文件,里面描述了路网的所有元素。我带你看看核心结构。
2.3.1 文件整体骨架
<?xml version="1.0" encoding="UTF-8"?>
<net version="1.16" junctionCornerDetail="5">
<location netOffset="..." convBoundary="..." />
<edge id="..." from="..." to="..." priority="...">
<lane id="..." index="..." speed="..." length="..." />
</edge>
<junction id="..." type="..." x="..." y="...">
<request index="..." />
</junction>
<connection from="..." to="..." fromLane="..." toLane="..." />
<tlLogic id="..." type="..." programID="...">
<phase duration="..." state="..." />
</tlLogic>
</net>
嗯,看着有点复杂对吧?其实核心就四个元素:edge(路段)、lane(车道)、junction(路口)、connection(连接关系)。
2.3.2 核心元素详解
Edge(路段):两个路口之间的道路。每个edge包含一个或多个lane。注意看priority属性,它表示道路等级,数值越大优先级越高。
Lane(车道):edge里的具体车道。index从0开始,0是最右侧车道。speed单位是m/s,别搞错了。我见过有人把km/h直接填进去,结果车跑得比飞机还快。
Junction(路口):道路交汇点。type属性有priority(优先通行)、traffic_light(信号灯控制)、right_before_left(右侧先行)等。这个决定了车辆通过路口的规则。
Connection(连接):定义车辆怎么从一个车道转到另一个车道。比如左转、直行、右转。没有connection,车辆到了路口就傻眼了。
2.3.3 一个实际例子
咱们看一个简单的十字路口结构:
<edge id="E0" from="J0" to="J1" priority="3">
<lane id="E0_0" index="0" speed="13.89" length="100.0"/>
<lane id="E0_1" index="1" speed="13.89" length="100.0"/>
</edge>
<junction id="J1" type="traffic_light" x="500.0" y="500.0">
<request index="0" foes="1 2 3"/>
<request index="1" foes="0 2 3"/>
</junction>
<connection from="E0" to="E1" fromLane="0" toLane="0" dir="s"/>
<connection from="E0" to="E2" fromLane="1" toLane="0" dir="l"/>
这段代码描述了一个双向两车道的路段E0,连接到路口J1(信号灯控制)。E0_0车道直行到E1,E0_1车道左转到E2。你看,dir属性用s表示直行,l表示左转,r表示右转。
2.4 本章知识体系总览
说了这么多,咱们用一张图来总结一下路网构建的完整流程:
这张图把咱们今天讲的内容串起来了。从OSM数据导出,到netconvert转换,再到理解.net.xml的结构,每一步都有它的意义。
好了,路网构建基础就讲到这里。记住,路网是仿真的地基,地基打不牢,后面全是白搭。下一章咱们会在这个路网上跑车流,到时候你就知道今天这些功夫没白费。