5

使用 SUMO 进行仿真(2)-Node 和 Edge

 3 years ago
source link: https://mathpretty.com/12797.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

使用 SUMO 进行仿真(2)-Node 和 Edge

王 茂南 2021年9月24日07:43:00评论7220字阅读24分4秒

摘要本文是 SUMO 进行仿真的第二篇。主要详细的介绍 Node 和 Edge 这两个文件类型(详细了解一下这两个文件的组成,如何生成 Network),通过这两个文件来生成 Network。

这是使用 SUMO 来进行仿真的第二篇内容。在上一篇的例子中,我们使用 SUMO 完成了一个简单的例子,了解了 nodeedge 文件,并制作了一个简单的路网。这一篇会就上面的问题进行展开,进一步了解 nodeedge 文件(我们会创建一个稍微复杂的环境)。

  • Network 的创建,关于 nodeedge 的用法;
  • Edge Type 的使用,设置 edge 的属性,来简化 edge 文件;
  • Road Access Permissions(规定道路允许通行的车辆);
  • 知乎上关于 sumo 的一个教程文章, 还是很不错的:
  • 本文的相关代码参考 Github 仓库,SUMO TutorialNode_Edge_Introduce 文件夹部分)

Network 文件生成

这一部分参考自,Networks/PlainXML。首先我们创建 net.xml。整个 network 的结构如下所示,共有 9 个节点(中心节点+周围的 8 个节点):

使用 SUMO 进行仿真(2)-Node 和 Edge

Node 的相关说明 (Node Descriptions)

按照上面的示意图,我们新建 ".nod.xml" 来描述上面的路网结构。完整文件如下所示:

  1. <nodes> <!-- The opening tag -->
  2.   <node id="0" x="0.0" y="0.0" type="traffic_light"/> <!-- def. of node "0" -->
  3.   <node id="1" x="-500.0" y="0.0" type="priority"/> <!-- def. of node "1" -->
  4.   <node id="2" x="+500.0" y="0.0" type="priority"/> <!-- def. of node "2" -->
  5.   <node id="3" x="0.0" y="-500.0" type="priority"/> <!-- def. of node "3" -->
  6.   <node id="4" x="0.0" y="+500.0" type="priority"/> <!-- def. of node "4" -->
  7.   <node id="m1" x="-250.0" y="0.0" type="priority"/> <!-- def. of node "m1" -->
  8.   <node id="m2" x="+250.0" y="0.0" type="priority"/> <!-- def. of node "m2" -->
  9.   <node id="m3" x="0.0" y="-250.0" type="priority"/> <!-- def. of node "m3" -->
  10.   <node id="m4" x="0.0" y="+250.0" type="priority"/> <!-- def. of node "m4" -->
  11. </nodes> <!-- The closing tag -->

在上面的例子中,id0 的节点是整个十字路口的中心节点,也是红绿灯。可以看他的 typetraffic_light,表示这个 node 是信号灯。 于是整个 node 的关系如下图所示(和上面的结构是一样的):

使用 SUMO 进行仿真(2)-Node 和 Edge

Edge 的相关说明 (Edge Descriptions)

在有了上面的 Node 的定义之后,下面需要定义 Edge。下面是一个基础的 Edge 文件的定义,对于每一个 edge 来说,最基础的是需要包含:

  • id, 每一个 edge 独特的标志, 用来找到指定的 edge;
  • from, to,from 和 to 是与上面的 node 的 id 对应的)
  • priority,优先级, 在转弯处有用;
  • numLanes,这个edge上包含多少个车道;
  • speed,车道的车速,也就是限速;

我们新建一个「hello.edg.xml」,并输入以下的内容:

  1. <edges>
  2.   <edge id="1fi" from="1" to="m1" priority="2" numLanes="2" speed="11.11"/>
  3.   <edge id="1si" from="m1" to="0" priority="3" numLanes="3" speed="13.89"/>
  4.   <edge id="1o" from="0" to="1" priority="1" numLanes="1" speed="11.11"/>
  5.   <edge id="2fi" from="2" to="m2" priority="2" numLanes="2" speed="11.11"/>
  6.   <edge id="2si" from="m2" to="0" priority="3" numLanes="3" speed="13.89"/>
  7.   <edge id="2o" from="0" to="2" priority="1" numLanes="1" speed="11.11"/>
  8.   <edge id="3fi" from="3" to="m3" priority="2" numLanes="2" speed="11.11"/>
  9.   <edge id="3si" from="m3" to="0" priority="3" numLanes="3" speed="13.89"/>
  10.   <edge id="3o" from="0" to="3" priority="1" numLanes="1" speed="11.11"/>
  11.   <edge id="4fi" from="4" to="m4" priority="2" numLanes="2" speed="11.11"/>
  12.   <edge id="4si" from="m4" to="0" priority="3" numLanes="3" speed="13.89"/>
  13.   <edge id="4o" from="0" to="4" priority="1" numLanes="1" speed="11.11"/>
  14. </edges>

这里每一个 edge 包含多个 lane (车道,通过参数「numLanes」进行设置)。我们以上面的 node 0, node m4, node 4 这三个 node 之间的 edge 作为例子来进行简单的说明. 他们整体的车道关系如下所示:

  • node 4node m4 方向, 有 2 个车道
  • node m4node 0 方向, 有 3 个车道
  • node 0node 4 方向, 有 1 个车道
使用 SUMO 进行仿真(2)-Node 和 Edge

所以他们上面 edge 的关系如下所示,这里设置的车道数与上面解释的是一样的:

  1. <edge id="4fi" from="4" to="m4" priority="2" numLanes="2" speed="11.11"/> <!-- 4->m4, 2 车道 -->
  2. <edge id="4si" from="m4" to="0" priority="3" numLanes="3" speed="13.89"/> <!-- m4->0, 3 车道 -->
  3. <edge id="4o" from="0" to="4" priority="1" numLanes="1" speed="11.11"/> <!-- 0->4, 1 车道 -->

在有了 nodeedge 之后,我们就可以生成 network 文件了。我们通过下面的命令进行生成:

  1. netconvert --node-files=hello.nod.xml --edge-files=hello.edg.xml --output-file=hello.net.xml

成功运行上面的命令后,会生成 hello.net.xml 文件。我们使用 NetEdit 打开该文件,可以看到如下所示的路网结构,与上面我们介绍的结构是一样的:

使用 SUMO 进行仿真(2)-Node 和 Edge

Edge Type

上面我们对于每一个 edge 是单独设置他的属性的。可以看到其中有些属性是重复的,所以我们可以先定义 edge type,接着将 edge type 用在每一个 edge 上面。我们将 edge type 存储在 cross3l.typ.xml 的文件中,如下所示:

  1. <types>
  2.   <type id="a" priority="3" numLanes="3" speed="13.889"/>
  3.   <type id="b" priority="2" numLanes="2" speed="11.111"/>
  4.   <type id="c" priority="1" numLanes="1" speed="11.111"/>
  5. </types>

接着定义 edge 文件。该文件还是保存为 cross3l.edg.xml 文件。 所有 edge 的类型通过 type 来进行定义(这里就不需要说明每一个 edge 的 「numLanes」、「speed」等属性了):

  1. <edges>
  2.   <edge id="1fi" from="1" to="m1" type="b"/>
  3.   <edge id="1si" from="m1" to="0" type="a"/>
  4.   <edge id="1o" from="0" to="1" type="c"/>
  5.   <edge id="2fi" from="2" to="m2" type="b"/>
  6.   <edge id="2si" from="m2" to="0" type="a"/>
  7.   <edge id="2o" from="0" to="2" type="c"/>
  8.   <edge id="3fi" from="3" to="m3" type="b"/>
  9.   <edge id="3si" from="m3" to="0" type="a"/>
  10.   <edge id="3o" from="0" to="3" type="c"/>
  11.   <edge id="4fi" from="4" to="m4" type="b"/>
  12.   <edge id="4si" from="m4" to="0" type="a"/>
  13.   <edge id="4o" from="0" to="4" type="c"/>
  14. </edges>

之后我们在生成 cross3l.net.xml 的时候, 只需要加上cross3l.typ.xml文件即可。我们还是使用 netconvert 来生成最终的 netfile

  1. netconvert --node-files=cross3l.nod.xml --edge-files=cross3l.edg.xml --type-files=cross3l.typ.xml --output-file=cross3l.net.xml

Road Access Permissions

我们还可以对其中某个 edge 其中的 lane 进行额外的设置。例如可以定义 disallow 和 allow。disallow='all' 的时候,这个可能表示是绿化带等,不能通行。这里 disallow 和 allow 后面接车辆的类型(list of vehicle classes)。例如可以写 disallow="passenger taxi"

我们对上面的 cross3l.edg.xml 文件进行修改。我们修改 edge_id=1si,本来他是有三个车道的,我们将其中第二个车道设置为无法通行:

  1. ... previous definitions ...
  2.   <edge id="1si" from="m1" to="0" type="a">
  3.     <lane index="1" disallow="all"/>
  4.   </edge>
  5.   <edge id="1o" from="0" to="1" type="c"/>
  6. ... further definitions ...

上面 id='1si' 这个 edge 上,index=1(第二个 lane 上面无法通行)。最后效果如下:

使用 SUMO 进行仿真(2)-Node 和 Edge

参考资料Road access permissions (allow, disallow)

Road Segment Refining

对于同一段 edge,我们可以对不同的位置来进行分别定义。例如下面的例子(一种比较常见的用法):

  1. ... previous definitions ...
  2.   <edge id="2si" from="m2" to="0" priority="3" numLanes="3" speed="13.89">
  3.     <split pos="0" lanes="0 1"/>
  4.     <split pos="30" lanes="0 1 2" speed="10"/>
  5.   </edge>
  6. ... further definitions ...

下面是按照上面的文件生成的 network。下面的 edge 有 3 个 lane。第一个 split 是从开始位置,到 0m 的位置,加一个 node(还是开始位置)。第二个 split 是从开始位置到 30m 的位置, 加一个 node (命名方式是<EDGE_ID>.<POSITION)。新增的 node 如下所示, 可以看到他的 ID 就是 edge_id+position

使用 SUMO 进行仿真(2)-Node 和 Edge

node 与 node 之间只包含参数 lanes 中的 lane。例如从起点 0m 到 30m 的这一段,就只包含 2 个 lane。

使用 SUMO 进行仿真(2)-Node 和 Edge

从 30m 到终点那一段, 速度就是被限制在 10, 上面 0-30 这一段速度是没有限制的. 但是这一段numLanes是=3, 因为上面 lanes="0 1 2"

使用 SUMO 进行仿真(2)-Node 和 Edge

生成网格状地图

对于一些比较复杂的 network,我们就不能自己去手写 nodeedge 文件了。下面是一个使用python 生成网格状 network 的例子(可以举一反三)。下面可以生成 node 和 edge 文件

首先是生成 node 文件,我们会生成若干个 100100 的小方格,每一个格点就是一个 node。这里我们生成一个 66 一共 36 个 node:

  1. # 生成Node文件, 从左下角(0,0)开始生成的
  2. with open('cross.nod.xml', 'w') as file:
  3.     file.write('<nodes> \n')
  4.     for i in range(6):
  5.         for j in range(6):
  6.             file.write('<node id="node%d" x="%d" y="%d" type="priority" /> \n' %(i*6+j, i*100, j*100))
  7.     file.write('</nodes> \n')

接着我们生成 edge 文件,我们需要将上面的 36 个 node 连接起来。这里所有的 edge 都是由两个 Lane 组成,速度都是 40。

  1. # 生成edge文件
  2. with open('cross.edg.xml', 'w') as file:
  3.     file.write('<edges> \n')
  4.     for i in range(6):
  5.         for j in range(6):
  6.             if i > 0:
  7.                 file.write('<edge id="edge%d_%d" from="node%d" to="node%d" priority="75" numLanes="2" speed="40" /> \n' % (i*6+j,k,i*6+j,(i-1)*6+j))
  8.                 k=k+1
  9.             if i < 5:
  10.                 file.write('<edge id="edge%d_%d" from="node%d" to="node%d" priority="75" numLanes="2" speed="40" /> \n' % (i*6+j,k,i*6+j,(i+1)*6+j))
  11.                 k=k+1
  12.             if j > 0:
  13.                 file.write('<edge id="edge%d_%d" from="node%d" to="node%d" priority="75" numLanes="2" speed="40" /> \n' % (i*6+j,k,i*6+j,i*6+j-1))
  14.                 k=k+1
  15.             if j < 5:
  16.                 file.write('<edge id="edge%d_%d" from="node%d" to="node%d" priority="75" numLanes="2" speed="40" /> \n' % (i*6+j,k,i*6+j,i*6+j+1))
  17.                 k=k+1
  18.     file.write('</edges> \n')

之后通过 netconvert 来生成 network 文件.

  1. netconvert --node-files=cross.nod.xml --edge-files=cross.edg.xml --output-file=cross.net.xml

最后生成的 network 如下所示:

使用 SUMO 进行仿真(2)-Node 和 Edge

Network 文件说明

下面简单介绍一下生成的 network 文件。在生成的 network 中, 会包含 direction,下面是一些缩写与全称的对应关系。

  • “s” = straight
  • “t” = turn
  • “l” = left
  • “r” = right
  • “L” = partially left
  • “R” = partially right
  • “invalid” = no direction
  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK