第四节:路网文件(.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:车道的几何形状,用一系列坐标点描述。直线就是起点和终点。
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):冲突连接,表示这个连接跟其他连接有冲突,需要让行。
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的字符数必须等于信号灯组的数量。每个信号灯组可以控制多个连接器。
4.6 知识体系总览
说了这么多,咱们用一张图来总结一下路网文件的核心结构:
4.7 实战建议
最后,给各位几个实战中的建议:
- 先用netedit画图:手动写XML太容易出错了。我建议先用netedit(SUMO自带的图形化编辑器)画路网,然后导出.net.xml文件,再根据需要手动修改。
- 验证路网文件:用
netconvert命令可以验证路网文件是否正确。命令是netconvert -s your.net.xml -o output.net.xml,如果有错误会提示。 - 注意坐标精度:SUMO对坐标精度要求不高,但如果你用高精度地图数据,注意单位要统一。我遇到过有人把经纬度当成平面坐标用,结果路网跑到外太空去了。
- 备份原始文件:修改.net.xml文件前,一定要备份。我曾经手滑删掉了一个连接器,结果整个交叉口瘫痪了。还好有备份。
核心总结: 路网文件就是由节点、边、车道、连接器组成的。节点定义位置,边定义道路,车道定义行驶轨迹,连接器定义转向关系。交叉口逻辑则决定了车辆如何通过这些连接。把这四个概念搞明白,.net.xml文件就不再是拦路虎了。