3、路网文件解析:.net.xml文件结构、节点与边的关系、车道属性详解
好,咱们今天来聊聊SUMO里最核心的东西——路网文件。.net.xml。说实话,我刚接触SUMO那会儿,看着这个XML文件头都大了。密密麻麻的标签,一堆看不懂的属性。但后来我发现,只要你搞懂了三个东西:节点、边、车道,整个路网文件就清晰了。
说白了,路网就是一张图。节点是路口,边是道路,车道是道路上的具体行驶轨迹。嗯,就这么简单。
3.1 节点(Node)—— 路口的灵魂
先看节点。在.net.xml里,节点用<node>标签表示。每个节点都有一个唯一的id,还有x和y坐标。你想想看,这不就是地图上的一个点吗?
<node id="1" x="0.0" y="0.0" type="priority"/>
<node id="2" x="500.0" y="0.0" type="traffic_light"/>
<node id="3" x="250.0" y="300.0" type="dead_end"/>
节点的type属性很关键。它决定了这个路口的行为逻辑。我个人习惯把节点类型分为三类:
- priority:优先权路口,没有信号灯,靠让行规则通行。我在做城市主干道仿真时,这种节点用得最多。
- traffic_light:信号灯控制路口。嗯,这里要注意,信号灯的配时方案是在另外的文件里定义的,节点只负责告诉你「这里有灯」。
- dead_end:死胡同或边界节点。车辆到了这里就消失了。
--turn-lanes 参数。我曾经因为忘了加这个,结果仿真里的车全在路口打转,死活掉不了头。
3.2 边(Edge)—— 连接节点的道路
边就是道路。它连接两个节点,用<edge>标签表示。每条边都有id、from(起点节点)、to(终点节点)。
<edge id="e1" from="1" to="2" priority="3" numLanes="2" speed="13.89"/>
<edge id="e2" from="2" to="3" priority="1" numLanes="1" speed="8.33"/>
这里有几个属性值得细说:
- priority:优先级。数值越大,优先级越高。说白了就是「谁的路权大」。主干道一般设3或4,支路设1或2。
- numLanes:车道数。双向道路需要分别定义两条边。
- speed:限速,单位是m/s。13.89 m/s 约等于 50 km/h。
你可能会问:为什么双向道路要定义两条边?因为SUMO里的边是有向的。从节点A到节点B是一条边,从B到A是另一条边。我刚开始做项目时,经常只定义了一条边,结果车全往一个方向开,另一个方向空空如也。尴尬。
id 不能重复。如果你用 netedit 手动画路网,它会自动生成类似 e0、e1 这样的ID。但如果你自己写XML,一定要保证唯一性。
3.3 车道(Lane)—— 车辆的实际行驶轨迹
车道是边的子元素。每条边包含一个或多个车道。车道用<lane>标签表示,它定义了车辆具体在哪条轨迹上行驶。
<edge id="e1" from="1" to="2" numLanes="2" speed="13.89">
<lane id="e1_0" index="0" speed="13.89" length="500.0" shape="0.0,-3.2 500.0,-3.2"/>
<lane id="e1_1" index="1" speed="13.89" length="500.0" shape="0.0,0.0 500.0,0.0"/>
</edge>
车道属性详解:
| 属性 | 说明 | 我的经验 |
|---|---|---|
id |
车道ID,格式为 边ID_索引 |
索引从0开始,0是最右侧车道 |
index |
车道序号 | 别搞混了,index和id里的数字要一致 |
speed |
车道限速,可覆盖边的限速 | 我常用这个来做可变限速区的仿真 |
length |
车道长度,单位米 | 一般由SUMO自动计算,不用手动改 |
shape |
车道几何形状,一串坐标点 | 直线车道就两个点,弯道会有多个点 |
这里有个坑,我曾经踩过。车道的shape属性定义了它的实际走向。如果你手动修改了shape,但没改length,那车辆行驶的距离和实际路径长度就不匹配了。结果就是车速显示异常,明明限速60,跑出来像蜗牛爬。
3.4 连接器(Connection)—— 转弯的奥秘
光有节点、边、车道还不够。车辆怎么从一个车道转到另一个车道?这就需要连接器了。连接器用<connection>标签表示。
<connection from="e1" to="e2" fromLane="0" toLane="0" dir="r"/>
<connection from="e1" to="e2" fromLane="1" toLane="0" dir="s"/>
属性说明:
from/to:起始边和目标边fromLane/toLane:起始车道和目标车道dir:转向方向,r右转,s直行,l左转,t掉头
你想想看,如果没有连接器,车辆到了路口就不知道往哪走了。SUMO默认会根据几何关系自动生成连接器,但有时候不准。我建议你在做复杂路口时,手动检查一下连接器配置。
3.5 实战:一个简单的十字路口
说了这么多,咱们来个实际的例子。一个十字路口,东西方向是主干道(双向4车道),南北方向是支路(双向2车道)。
<?xml version="1.0" encoding="UTF-8"?>
<net version="1.16" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/net_file.xsd">
<location netOffset="0.00,0.00" convBoundary="0.00,0.00,500.00,500.00" origBoundary="0.00,0.00,500.00,500.00" projParameter="!"/>
<edge id="ew_east" from="1" to="2" numLanes="2" speed="13.89">
<lane id="ew_east_0" index="0" speed="13.89" length="500.0" shape="0.00,-3.20 500.00,-3.20"/>
<lane id="ew_east_1" index="1" speed="13.89" length="500.0" shape="0.00,0.00 500.00,0.00"/>
</edge>
<edge id="ew_west" from="2" to="1" numLanes="2" speed="13.89">
<lane id="ew_west_0" index="0" speed="13.89" length="500.0" shape="500.00,-3.20 0.00,-3.20"/>
<lane id="ew_west_1" index="1" speed="13.89" length="500.0" shape="500.00,0.00 0.00,0.00"/>
</edge>
<edge id="ns_north" from="3" to="2" numLanes="1" speed="8.33">
<lane id="ns_north_0" index="0" speed="8.33" length="500.0" shape="250.00,500.00 250.00,0.00"/>
</edge>
<edge id="ns_south" from="2" to="3" numLanes="1" speed="8.33">
<lane id="ns_south_0" index="0" speed="8.33" length="500.0" shape="250.00,0.00 250.00,500.00"/>
</edge>
<node id="1" x="0.0" y="250.0" type="dead_end"/>
<node id="2" x="250.0" y="250.0" type="traffic_light"/>
<node id="3" x="250.0" y="500.0" type="dead_end"/>
</net>
这个例子虽然简单,但包含了所有核心要素。你可以看到:
- 节点1和3是边界,节点2是信号灯路口
- 东西方向有两条边,每条边2个车道
- 南北方向有两条边,每条边1个车道
- 车道shape定义了具体的几何位置
type 设成了 dead_end。车辆到了那里就直接被删除了。所以,内部路口一定要用 priority 或 traffic_light。
好了,关于.net.xml的解析就到这里。记住我说的:节点、边、车道,三者的关系搞清楚了,路网文件在你眼里就是一张清晰的地图。下次你打开一个陌生的路网文件,先看节点有哪些,再看边怎么连的,最后看车道细节。嗯,这样就不会迷路了。
可可精品资料库