3、路网文件解析:.net.xml文件结构、节点与边的关系、车道属性详解

好,咱们今天来聊聊SUMO里最核心的东西——路网文件。.net.xml。说实话,我刚接触SUMO那会儿,看着这个XML文件头都大了。密密麻麻的标签,一堆看不懂的属性。但后来我发现,只要你搞懂了三个东西:节点、边、车道,整个路网文件就清晰了。

说白了,路网就是一张图。节点是路口,边是道路,车道是道路上的具体行驶轨迹。嗯,就这么简单。

.net.xml 路网文件 节点 (Node) 边 (Edge) 车道 (Lane) id, type, x, y tl (信号灯) from, to, id priority, numLanes speed, length shape 节点定义路口 → 边连接节点 → 车道承载车辆

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的解析就到这里。记住我说的:节点、边、车道,三者的关系搞清楚了,路网文件在你眼里就是一张清晰的地图。下次你打开一个陌生的路网文件,先看节点有哪些,再看边怎么连的,最后看车道细节。嗯,这样就不会迷路了。

可可精品资料库