在 sumo-gui 中打开的 SUMO 网络文件截图。显示了德国城市 Eichstätt 的地图。
| SUMO 道路网络 | |
|---|---|
| 文件扩展名 | .net.xml |
| 内容类型 | 地图 |
| 是否为开放格式? | 是 |
| 是否为 SUMO 特有? | 是 |
| XML 模式 | net_file.xsd |
SUMO 网络文件描述了地图中与交通相关的部分,即模拟车辆行驶经过的道路和交叉口。从宏观尺度来看,SUMO 网络是一个有向图。节点(在 SUMO 语境中通常称为“junctions”)代表交叉口,“edges”代表道路或街道。请注意,边(edges)是单向的。具体来说,SUMO 网络包含以下信息:
- 每条街道(边)作为车道的集合,包括每个车道的位置、形状和限速,
- 由交叉口引用的交通信号灯逻辑,
- 交叉口,包括其路权规则,
- 交叉口(节点)处车道之间的连接。
此外,根据使用的输入格式和设定的处理选项,还可能包含:
- 区域(districts),
- 环岛描述。
尽管 SUMO 网络文件是人类可读的(XML),但并不意味着要手动编辑。 相反,您应该使用 SUMO XML 描述文件 配合 netconvert。您也可以使用 netconvert 从各种格式转换现有地图,或者使用 netgenerate 生成几何上简单的抽象道路地图。要修改现有的 .net.xml 文件,您可以将其与补丁文件一起加载到 netconvert 中。您也可以使用 netedit 来构建自己的道路网络,或对从 netconvert 或 netgenerate 获得的网络进行修改。
Caution
当从自定义输入数据创建 SUMO 网络时,推荐的方法是创建/生成 plain-xml 文件,并使用 netconvert 将其转换为 *.net.xml 文件。直接生成 .net.xml 文件充满危险。
网络格式#
SUMO 道路网络被编码为 XML 文件。内容按以下顺序的实例进行分组:
- 适用于该网络的制图投影
- 边;首先给出内部边,然后是普通边;每条边包含属于它的车道列表
- 交通信号灯逻辑
- 交叉口,包括其路权定义;首先是普通交叉口,然后是内部交叉口
- 连接,首先是普通连接,然后是内部连接
- 可选的环岛
坐标和对齐#
网络使用笛卡尔度量坐标,其中最左侧的节点位于 x=0,最底部的节点位于 y=0。这意味着在导入时,netconvert 和 netgenerate 会首先投影网络(如果原始网络未使用笛卡尔和/或度量坐标)。然后,它们将道路网络移动到原点 (0,0)。
此过程在生成的网络中的 location 元素内有记录。您可能会在这里找到以下属性:
| 名称 | 类型 | 描述 |
|---|---|---|
| netOffset | 偏移量 (<2D-POSITION>) | 为将网络移动到 (0,0) 而应用的偏移量 |
| convBoundary | 边界 (<2D-BOUNDING_BOX>) | 覆盖转换后网络节点的边界(即当前给出的网络) |
| origBoundary | 边界 (<2D-BOUNDING_BOX>) | 投影和转换前网络的初始边界 |
| projParameter | 投影参数 | 网络如何被投影的信息(见下文) |
projParameter 可能具有以下值之一:
| 编码 | 描述 |
|---|---|
| '!' | 未应用投影。 |
| '-' | 应用了“简单”投影 |
| '.' | ? |
| proj-definition (<PROJ_DEFINITION>) | 使用 proj 进行投影,并使用这些参数初始化它。 |
要从 SUMO 报告的 x/y 坐标获取原始坐标,必须首先减去网络偏移量。然后,必须应用初始投影的逆变换,这取决于 projParameter。对于 proj 投影的网络,可以使用名为 pj_inv 的 proj 函数执行逆变换。首先必须使用来自 projParameter 的投影参数初始化 proj。对于 proj 投影的网络,如下所示:
Position2D cartesian = sumoXY(x, y);
projPJ myProjection = pj_init_plus(projParameter.c_str());
cartesian.sub(netOffset);
projUV p;
p.u = cartesian.x();
p.v = cartesian.y();
p = pj_inv(p, myProjection);
p.u *= RAD_TO_DEG;
p.v *= RAD_TO_DEG;
cartesian.set(p.u, p.v);
对于没有投影的网络(projParameter='!'),只需应用偏移量。对于具有“简单”投影的网络(projParameter='-'),目前没有已知的逆投影方法。
SUMO 道路网络旨在与北对齐。当然,这取决于用户如何定义道路网络,但当从 Open Street Map 或 shape 文件等来源导入时,向上的方向应对应于北方。
边和车道#
“普通”边和“内部”边的编码方式几乎相同,但它们在必需和使用的属性上有所不同。
普通边#
“普通”边是两个节点(“交叉口”)之间的连接。
<edge id="<ID>" from="<FROM_NODE_ID>" to="<TO_NODE_ID>" priority="<PRIORITY>">
... 一个或多个车道 ...
</edge>
这里,ID(上例中的 <ID>)是网络导入期间读取的 ID。起始节点和结束节点的 ID 分别在 from 和 to 属性中给出。优先级(priority)是一个抽象的序数,用于确定路权规则。上例中省略了 function 属性,因为它默认为 "normal",即该示例边的 function 值。
边的属性如下:
| 名称 | 类型 | 描述 |
|---|---|---|
| id | id (string) | 边的 ID |
| from | id (string) | 起始节点的 ID |
| to | id (string) | 结束节点的 ID |
| priority | integer | 指示道路的重要性(可选) |
| function | enum ( "normal", "internal", "connector", "crossing", "walkingarea" ) |
抽象的边用途(可选,默认为 "normal") |
对于模拟,只有 "function" 属性是有意义的。它描述了边的使用方式,以及它是可以在现实世界中找到的边,还是仅用于分配的辅助构造。定义了以下用途:
normal:边是道路网络的一部分,例如高速公路或连接两条道路的普通街道connector:边是宏观连接器——不是现实世界道路网络的一部分。尽管如此,在模拟中,"connector" 道路和 "normal" 节点之间没有区别。只有 sumo-gui 允许隐藏连接器边。internal:边是交叉口的一部分(位于交叉口内部),见上文。crossing:walkingarea:
车道#
每条边包含其组成的车道定义。以下示例显示了一个包含两条车道的单边。请注意,坐标可以是 2D 或 3D。
<edge id="<ID>" from="<FROM_NODE_ID>" to="<TO_NODE_ID>" priority="<PRIORITY>">
<lane id="<ID>_0" index="0" speed="<SPEED>" length="<LENGTH>" shape="0.00,495.05 248.50,495.05"/>
<lane id="<ID>_1" index="1" speed="<SPEED>" length="<LENGTH>" shape="0.00,498.35,2.00 248.50,498.35,3.00"/>
</edge>
如您所见,ID 由边的 ID 和一个流水号组成,两者以下划线 ('_') 分隔。流水号从最右侧的车道开始为零。相同的数字也由 "index" 属性给出。车道也按此数字排序。@note:这是高度重复的
车道的属性如下:
| 名称 | 类型 | 描述 |
|---|---|---|
| id | id (string) | 车道的 ID |
| index | 流水号 (unsigned int) | 流水号,从最右侧的车道开始为零 |
| speed | float | 此车道允许的最大速度 [m/s] |
| length | float | 此车道的长度 [m] |
| shape | 位置向量 | 车道的几何形状,由描述车道中心线的折线给出;不能为空或少于两个位置 |
需要注意的是,目前边的所有车道长度都相同,即使它与形状的几何长度不同。netconvert 甚至明确允许覆盖几何长度。此外,即使网络被移动到从 (0,0) 开始,也不能保证网络的所有部分都具有正坐标。
Caution
最小边长为 0.1 米。
内部边#
内部边位于交叉口内部,连接传入的普通边和传出的普通边。如果网络是使用 --no-internal-links 选项构建的,则不包含内部边。内部边的示例如下:
<edge id="<ID>" function="internal">
... 一个车道 ...
</edge>
内部边的 ID 组成如下:<NODE_ID>_<EDGE_INDEX>,其中 <NODE_ID> 是边所在节点的 ID,<EDGE_INDEX> 是围绕节点顺时针运行的流水号(从北开始)。请注意,ID 以 ':' 为前缀。如果内部边连接的传入和传出边有多条车道,则内部边也有多条车道(根据这两条边之间的连接数)。对于多车道内部边,INDEX 跳跃车道数,因此 EDGE_INDEX + LANE_INDEX = CONNECTION_INDEX。
属性如下表所示。
| 名称 | 类型 | 描述 |
|---|---|---|
| id | id (string) | 内部边的 ID |
| function | "internal" |
内部边始终为 "internal" |
当网络构建时包含内部边时,每个连接通常对应于恰好一条内部车道。
如果存在多个具有相同 from 和 to 边对的连接,则这些边的内部车道将是同一内部边的一部分。在标记为直行(dir="s")的连接上,允许在内部车道上变道。
特殊情况是所谓的内部交叉口。这些标记了车辆在通过冲突交通之前在交叉口内等待的位置。最常见的发生情况是:
- 左转车辆让行对向交通
- 右转车辆让行人过街处
对应于此类运动的连接被分成两条内部车道:一条在等待位置之前,一条在等待位置之后。内部交叉口之后的车道始终有自己的内部边。
停止偏移量#
每条边或车道可以携带一个 stopOffset 子元素,以指定特定类别车辆的附加停止偏移量。这可用于定义自行车等待区。确切的语法在 stopOffset 中解释。
交通信号灯程序#
交通信号灯程序定义了交通信号灯的相位。
<tlLogic id="<ID>" type="<ALGORITHM_ID>" programID="<PROGRAM_ID>" offset="<TIME_OFFSET>">
<phase duration="<DURATION#1>" state="<STATE#1>"/>
<phase duration="<DURATION#1>" state="<STATE#1>"/>
... 更多状态 ...
<phase duration="<DURATION#n>" state="<STATE#n>"/>
</tlLogic>
有关属性和语义的解释,请参阅 Simulation/Traffic Lights。 请注意,通常生成的程序 ID 为 "0"。
交叉口和路权#
普通交叉口#
交叉口代表不同交通流交叉的区域,包括车辆在通过交叉口时必须遵循的路权规则。示例如下:
<junction id="<ID>" type="<JUNCTION_TYPE>" x="<X-POSITION>" y="<Y-POSITION>"
incLanes="<INCOMING_LANES>" intLanes="<INTERNAL_LANES>"
shape="<SHAPE>">
... requests ...
</junction>
交叉口本身由以下属性描述:
| 名称 | 类型 | 描述 |
|---|---|---|
| id | id (string) | 交叉口的 ID;默认情况下,控制此交叉口的交通信号灯将具有相同的 ID,但这可能由用户更改或在合并交通信号灯时更改。 |
| x | x-position (real) | 交叉口的 x 坐标 |
| y | y-position (real) | 交叉口的 y 坐标 |
| z | z-position (real) | 交叉口的(可选)z 坐标 |
| incLanes | id 列表 | 结束于交叉口的车道 ID;按方向排序,顺时针,向上方向 = 0 |
| intLanes | id 列表 | 交叉口内部的车道 ID |
| shape | 位置列表 | 描述交叉口道路边界的多边形 |
| customShape | bool | 形状是否由用户自定义(因此不应由 netconvert 或 netedit 重建),默认为 False |
请注意,交叉口的 x/y 位置描述的是给定的中心,而不是计算出的交叉口中心。允许两个节点具有相同的位置。
Caution
自版本 0.25.0 起,每个交叉口的最大连接数(链接)限制为 256。在早期版本的 sumo 中,限制为 64。
请求(Requests)#
接下来是 "request",如下所示:
<request index="<INDEX>" response="<RELATIVE_MAJOR_LINKS>" foes="<FOE_LINKS>" cont="<MAY_ENTER>"/>
它们描述了对于每个链接(由 "index" 给出),哪些流具有更高的优先级("response")并强制索引为 "index" 的链接上的车辆停止,以及哪些流是冲突的("foes")。"foes" 是 "response" 的超集,添加了优先级低于索引为 "index" 的流的流。
可以这样理解请求:索引描述了通过交叉口的传入车道和传出车道之间的特定连接。索引是按连接计算的,顺序如下:首先,按方向对边排序,从 0°(向上)开始;其次,使用车道顺序(最右侧优先);第三,按连接遵循的方向排序,从最右侧开始。
相同的顺序应用于 "response" 和 "foes" 字段,从右侧开始。这意味着:
<request index="2" response="001" foes="011" cont="0"/>
使用索引为 "2" 的连接的车辆必须等待使用连接 "0" 的车辆。连接 "0" 和 "1" 是其冲突对象(foes)。请求元素的属性如下:
| 名称 | 类型 | 描述 |
|---|---|---|
| index | index (unsigned int) | 路权矩阵中描述的连接的索引 |
| response | bitset (string) | 一个位字符串,描述每个连接是否禁止此连接上的车辆不减速通过交叉口。最右侧的位对应于索引 0。 |
| foes | bitset (string) | 一个位字符串,描述每个连接是否与此连接冲突。最右侧的位对应于索引 0。 |
| cont | bool | 车辆是否可以通过第一条停车线在交叉口内等待,直到没有优先级更高的车辆。这通常是优先方向左转流的情况。 |
Caution
属性 response 和 foes 中的位字符串必须从右向左读取(对链接 0 的响应是最右侧的条目),这与 tlLogic-state 字符串(从左向右读取,链接 0 的状态是最左侧的条目)相反。
内部交叉口#
“内部”交叉口用于为某些交通关系定义交叉口内的等待位置。这通常用于优先方向的左转车辆或必须等待直行行人的右转车辆。
自版本 0.25.0 起,用户可以自定义内部交叉口的定位(和存在)。
这些交叉口不需要路权矩阵,只需要以下信息:
- 进入内部交叉口所在交叉口的车道,如果车辆正在接近,则禁止通过内部交叉口
- 在通过内部交叉口时不得占用的内部车道
内部交叉口的编码如下:
<junction id="<ID>" type="internal" x="<X-POSITION>" y="<Y-POSITION>"
incLanes="<INCOMING_PROHIBITING_LANES>"
intLanes="<INTERNAL_PROHIBITING_LANES>"/>
ID 与通过内部交叉口本身时要使用的车道相同。类型始终为 "internal"。请注意,内部交叉口通常在一行中编码。内部交叉口的属性如下:
| 名称 | 类型 | 描述 |
|---|---|---|
| id | id (string) | 内部交叉口的 ID;它总是以 : 开头,后跟父交叉口的 ID,然后是 _,最后是唯一的索引。 |
| x | x-position (real) | 交叉口的 x 坐标 |
| y | y-position (real) | 交叉口的 y 坐标 |
| z | z-position (real) | 交叉口的(可选)z 坐标 |
| incLanes | id 列表 | 结束于内部交叉口所在交叉口的车道 ID,这些车道禁止通过内部交叉口 |
| intLanes | id 列表 | 内部交叉口所在交叉口内部的车道 ID,这些车道禁止通过内部交叉口 |
连接#
普通连接#
普通连接或“链接”描述了从传入车道可以到达哪些传出车道。此外,还给出了通过交叉口时要使用的第一条车道。附加信息描述了连接的方向和“状态”。如果连接由交通信号灯控制,则给出交通信号灯的名称以及在交通信号灯相位定义中控制此连接的信号的索引。连接编码为:
<connection from="<FROM_EDGE_ID>" to="<TO_EDGE_ID>" fromLane="<FROM_LANE_INDEX>" toLane="<TO_LANE_INDEX>"
via="<VIA_LANE_ID>" tl="<TRAFFIC_LIGHT_ID>" linkIndex="12" dir="r" state="o"/>
属性如下:
| 名称 | 类型 | 描述 |
|---|---|---|
| from | edge id (string) | 连接开始的传入边的 ID |
| to | edge id (string) | 连接结束的传出边的 ID |
| fromLane | index (unsigned int) | 连接开始的传入边的车道 |
| toLane | index (unsigned int) | 连接结束的传出边的车道 |
| via | lane id (string) | 用于通过交叉口传递此连接的车道 ID |
| tl | traffic light id (string) | 控制此连接的交通信号灯的 ID;如果连接不受交通信号灯控制,则缺少该属性 |
| linkIndex | index (unsigned int) | 交通信号灯内负责此连接的信号的索引;如果连接不受交通信号灯控制,则缺少该属性 |
| dir | enum ("s" = straight, "t" = turn, "l" = left, "r" = right, "L" = partially left, R = partially right, "invalid" = no direction) | 连接的方向 |
| state | enum ("-" = dead end, "=" = equal, "m" = minor link, "M" = major link, traffic light only: "O" = controller off, "o" = yellow flashing, "y" = yellow minor link, "Y" = yellow major link, "r" = red, "g" = green minor, "G" green major) | 连接的状态 |
在不使用 netconvert 创建这些连接时(不推荐),应考虑到具有内部车道的连接遵循特殊模式。例如,当车道 1_f_0 需要通过 1_v_0 连接到 1_t_0 时,存在以下连接条目:[from=1_f_0, to=1_t_0 via=1_v_0] 和 [from=1_v_0 to=1_t_0]。如果省略后者,SUMO 将无法加载网络。如果在必要连接旁边存在连接 [from=1_f_0 to=1_v_0],它也将无法加载。
连接的索引#
每个连接都有相关的索引,可以通过自定义 GUI 设置并在 Junctions->Show ... index 中激活来在 sumo-gui 中显示。这些索引通常是相同的,但可以彼此独立地配置。
- 交叉口索引 (Junction Index):此索引在 #Requests 部分中描述。它不能被修改。索引对应于
<junctions>的 incLanes 属性的顺序,也对应于<connection>元素的顺序。这些索引在(右手通行的网络中)围绕交叉口顺时针运行,从顶部开始。
- TLS 索引 (TLS Index):此索引分配给由交通信号灯控制的连接。对于连接的交通信号灯(控制多个交叉口),此索引与交叉口索引不同,因为后者不再是唯一的。TLS 索引可以使用.con.xml 文件进行配置。自定义索引可用于创建信号组(多个连接始终具有相同状态并共享相同的索引),从而简化交通信号灯相位的 state 定义。
网络中的环岛#
网络中的环岛影响路权(在网络构建期间编码在交叉口的请求 <request> 元素中)。它们在网络文件中的存在有两个原因:
- 它便于使用 netconvert 重新导入 .net.xml 文件
- 变道模型可能会考虑环岛
每个环岛由其节点和边(有些冗余地)定义:
<roundabout nodes="nodeID1 nodeID2 ..." edges="edgeID1 edgeID2 ..."/>
用于查看、编辑和处理的软件#
要创建 SUMO 网络文件,netconvert 可帮助从其他格式的地图生成它,而 netgenerate 则使用简单的几何结构构建新地图。sumo 直接在此文件的地图中执行其模拟。大多数其他 SUMO 工具读取此类文件以生成或导入必须映射到道路网络上的信息。
可以使用 netedit 以图形方式创建和编辑网络。
SUMO 网络文件不适合手动编辑。请使用 netconvert 将其转换为 SUMO 原生 XML 描述。然后您可以手动处理这些文件,并使用 netconvert 重建网络。
更多文档#
- 网络导入
- 抽象道路网络的生成
- netedit 手册
- 开发者/网络构建过程
Note
处理由旧版本 netconvert / netgenerate 生成的网络时,请参阅 ChangeLog。
