第四节:路网文件(.net.xml)详解——节点、边、车道与交叉口逻辑

好,咱们今天来啃一块硬骨头——.net.xml文件。说实话,很多初学者一看到这个XML文件就头大,密密麻麻的标签,动辄几千行。我刚开始接触SUMO那会儿,也是对着这个文件发懵。但后来我发现,只要搞懂了四个核心概念,这个文件其实就是一层窗户纸。

哪四个概念?节点(Node)、边(Edge)、车道(Lane)、连接器(Connection)。说白了,路网文件就是把这些东西用XML描述出来。咱们一个一个拆开讲。

4.1 节点(Node)——路网的骨架

节点是什么?就是路网中的交叉点或端点。你可以把它想象成骨骼的关节。每个节点都有一个唯一的ID,还有类型(type)和坐标(x, y)。

我举个例子,一个最简单的十字路口,中心点就是一个节点。路的两端,也是节点。

<node id="1" x="0.0" y="0.0" type="priority"/>
<node id="2" x="500.0" y="0.0" type="priority"/>

这里有几个关键属性:

  • id:节点的唯一标识,不能重复。我习惯用数字,但用字符串也行。
  • x, y:坐标,单位是米。注意,SUMO用的是平面直角坐标系,不是经纬度。
  • type:节点类型。常见的有priority(优先规则)、traffic_light(信号灯)、unregulated(无管制)。
小技巧: 如果你只是做仿真,不关心交叉口细节,用priority类型最省事。SUMO会自动根据路权规则处理。

4.2 边(Edge)——连接节点的道路

边就是连接两个节点的道路。每条边可以包含多条车道。边的定义也很简单:

<edge id="e1" from="1" to="2" numLanes="2" speed="13.89" priority="1"/>

关键属性:

  • id:边的唯一标识。
  • from, to:起点节点和终点节点。注意方向,从from到to。
  • numLanes:车道数量。双向道路需要两条边,一条正向一条反向。
  • speed:限速,单位是m/s。13.89 m/s ≈ 50 km/h。
  • priority:优先级,数值越大优先级越高。这个在交叉口路权计算时会用到。

嗯,这里有个坑。我曾经在项目中犯过一个低级错误:只定义了一条边,结果车辆只能单向行驶。后来才发现,双向道路需要定义两条边,比如e1和e1_rev。你想想看,如果只有一条边,车怎么回来?

4.3 车道(Lane)——车辆行驶的轨道

每条边下面,会详细定义每条车道。车道是车辆真正行驶的地方。看这个例子:

<lane id="e1_0" index="0" speed="13.89" length="500.0" shape="0.0,-3.0 500.0,-3.0"/>
<lane id="e1_1" index="1" speed="13.89" length="500.0" shape="0.0,0.0 500.0,0.0"/>

车道属性解析:

  • id:格式是边ID_车道索引,比如e1_0表示边e1的第0条车道。
  • index:车道索引,从0开始。0是最右侧车道(靠路肩),数字越大越靠左。
  • speed:该车道的限速。可以跟边的限速不同,但一般保持一致。
  • length:车道长度,单位米。
  • shape:车道的几何形状,用一系列坐标点描述。直线就是起点和终点。
重点: 车道索引的顺序很重要!在SUMO里,index="0"永远是最右侧车道。这个跟咱们国内靠右行驶的习惯是一致的。但如果你在国外做靠左行驶的仿真,就要注意了。

我记得有一次,我做一个高速公路匝道的仿真,匝道只有一条车道,但主路有三条。结果车辆从匝道汇入时总是跑到最左侧车道去。查了半天,发现是匝道车道的index设成了2,SUMO以为它是左侧车道。改成0就对了。

4.4 连接器(Connection)——交叉口的灵魂

连接器定义了车辆在交叉口如何从一个车道转到另一个车道。这是路网文件中最复杂、也最容易出错的部分。

<connection from="e1" to="e2" fromLane="0" toLane="0" dir="r" state="M"/>
<connection from="e1" to="e2" fromLane="1" toLane="0" dir="s" state="M"/>

连接器的关键属性:

  • from, to:从哪条边到哪条边。
  • fromLane, toLane:从哪条车道到哪条车道。
  • dir:转向方向。r右转,s直行,l左转,t掉头。
  • state:连接状态。M表示主要连接(默认),o表示可选连接,c表示冲突连接。

这里有个容易混淆的地方:state="M"和state="o"有什么区别?我简单解释一下:

  • M(Major):主要连接,车辆必须从这里走。比如直行车道,只能直行。
  • o(Optional):可选连接,车辆可以选择走或不走。比如左转车道,也可以直行(如果允许的话)。
  • c(Conflict):冲突连接,表示这个连接跟其他连接有冲突,需要让行。
注意: 如果你不定义连接器,SUMO会自动生成默认连接。但自动生成的连接往往不符合实际需求。比如,它可能允许左转车道直行,这在现实中是不允许的。所以,我强烈建议手动定义所有连接器,尤其是复杂的交叉口。

4.5 交叉口逻辑——信号灯与路权

交叉口逻辑是SUMO仿真中最核心的部分。它决定了车辆在交叉口如何通行。主要有两种方式:

4.5.1 优先规则(Priority Rules)

这种方式不需要信号灯,车辆根据路权规则自行判断。SUMO会根据边的优先级、转向方向等自动计算。比如,主路优先、右转优先等。

<node id="3" type="priority"/>

就这么简单。但实际仿真中,你会发现车辆在无信号灯交叉口的表现可能不太理想。比如,车辆可能会在路口犹豫不决,或者抢行。这时候就需要调整参数了。

4.5.2 信号灯逻辑(Traffic Light Logic)

信号灯逻辑就复杂多了。你需要定义信号灯的相位(phase)、持续时间等。

<tlLogic id="3" type="static" programID="0" offset="0">
  <phase duration="30" state="GGGrrr"/>
  <phase duration="3" state="yyyrrr"/>
  <phase duration="30" state="rrrGGG"/>
  <phase duration="3" state="rrryyy"/>
</tlLogic>

这里state字符串的每个字符对应一个信号灯组。G表示绿灯,y表示黄灯,r表示红灯。顺序跟连接器的顺序有关。

我刚开始做信号灯仿真时,最头疼的就是这个state字符串。明明定义了4个连接器,但state只有3个字符,结果仿真报错。后来才明白,state的字符数必须等于信号灯组的数量。每个信号灯组可以控制多个连接器。

调试技巧: 如果你不确定信号灯的状态,可以在SUMO-GUI中打开「Show Traffic Lights」选项,它会显示每个信号灯组的状态。这个功能帮了我大忙。

4.6 知识体系总览

说了这么多,咱们用一张图来总结一下路网文件的核心结构:

路网文件(.net.xml)核心结构 net.xml 节点 (Node) 边 (Edge) 车道 (Lane) 连接器 (Connection) 属性 • id (唯一标识) • x, y (坐标) • type (类型) 属性 • id, from, to • numLanes • speed, priority 属性 • id, index • speed, length • shape (几何) 属性 • from, to • fromLane, toLane • dir, state 交叉口逻辑 (tlLogic / priority) 四个核心组件共同构成了完整的SUMO路网描述

4.7 实战建议

最后,给各位几个实战中的建议:

  1. 先用netedit画图:手动写XML太容易出错了。我建议先用netedit(SUMO自带的图形化编辑器)画路网,然后导出.net.xml文件,再根据需要手动修改。
  2. 验证路网文件:用netconvert命令可以验证路网文件是否正确。命令是netconvert -s your.net.xml -o output.net.xml,如果有错误会提示。
  3. 注意坐标精度:SUMO对坐标精度要求不高,但如果你用高精度地图数据,注意单位要统一。我遇到过有人把经纬度当成平面坐标用,结果路网跑到外太空去了。
  4. 备份原始文件:修改.net.xml文件前,一定要备份。我曾经手滑删掉了一个连接器,结果整个交叉口瘫痪了。还好有备份。

核心总结: 路网文件就是由节点、边、车道、连接器组成的。节点定义位置,边定义道路,车道定义行驶轨迹,连接器定义转向关系。交叉口逻辑则决定了车辆如何通过这些连接。把这四个概念搞明白,.net.xml文件就不再是拦路虎了。

可可精品资料库