SUMO运行方法
S U M O SUMO SUMO以及 S U M O − G U I SUMO-GUI SUMO−GUI进行仿真所需要的文件实际上就只是仿真文件 ( . s u m o c f g ) (.sumocfg) (.sumocfg)。而要编写这个仿真文件,所需要只有两个文件:
- 路网文件 ( . n e t . x m l ) (.net.xml) (.net.xml)
- 路由文件 ( . r o u . x m l ) (.rou.xml) (.rou.xml)
然后将上面两个文件结合起来就可以生成一份仿真文件了。
那么接下来,我就分这两部分来说明如何编写出一份属于自己的仿真文件。
一、路网文件
路网文件有以下三种获取方式:
1.由其他路网文件转化而来
1.1 OSM
这种方法最常见的就是从 O S M OSM OSM上面获取路网文件,然后转化为 S U M O SUMO SUMO的路网文件。
在这上面可以选择自己想要的路网文件。在导出 O S M OSM OSM上面的路网文件之后,发现它的后缀是 . o s m .osm .osm。我们可以利用 S U M O SUMO SUMO自带的转换工具来进行转换。具体来说就是打开终端( W i n d o w s Windows Windows用户应该是 c m d cmd cmd),然后输入:
netconvert --osm-files map.osm -o map.net.xml
当然,要记得先 c d cd cd到待转化文件所在的文件夹。导入的和导出的文件名都可以根据自己的需求来进行更改。
(UPD 2022/5/30)
还可以通过osm文件生成地形文件!这样就可以是3D得了!!
polyconvert --net-file map.net.xml --osm-files map.osm -o map.poly.xml
然后在sumocfg文件里面addtional一下就可以了!!
1.2 shape文件转化
这个就有一点麻烦了。我们的基本思路是现将 . s h a p e .shape .shape文件转化成 . o s m .osm .osm文件,然后再用上面的方法转成 S U M O SUMO SUMO可以用的 . n e t . x m l .net.xml .net.xml文件。
请参考我的这一篇文章。SUMO(零)—— 地图文件转化。
2.利用netedit自己画路网
n e t e d i t netedit netedit是 S U M O SUMO SUMO自带的路网编辑器。通过它就可以可视化地对路网进行编辑。
3.自己写路网文件
饶命,这个我真的不行。
U P D 2022.5.27 UPD\ \ 2022.5.27 UPD 2022.5.27 我感觉我又可以了 哈哈!
真没中文资料啊好恶心。只能参考官方文档。
简单来说就是硬写。最基本的路网文件呢包括两部分: n o d . x m l nod.xml nod.xml文件以及 e d g . x m l edg.xml edg.xml 文件。
3.1 节点文件
顾名思义, n o d . x m l nod.xml nod.xml所存储的就是里面各个节点的信息。来看看它的基本格式:
<nodes>
<node id="nd0" x="0" y="0"/>
<node id="nd1" x="0" y="50"/>
<node id="nd2" x="0" y="-50"/>
<node id="nd3" x="50" y="0"/>
<node id="nd4" x="50" y="50"/>
<node id="nd5" x="50" y="-50"/>
<node id="nd6" x="-50" y="0"/>
<node id="nd7" x="-50" y="50"/>
<node id="nd8" x="-50" y="-50"/>
</nodes>
很好理解吧?每个参数里面第一个 i d id id 就是要独一无二,然后后面两个参数就是坐标嘛。
3.2 边文件
e d g . x m l edg.xml edg.xml 文件就是存储路网里面各个边的信息。
<edges>
<edge id="nd0to1" from="nd0" to="nd1" numLanes="3" spreadType="center"/>
<edge id="-nd0to1" from="nd1" to="nd0" numLanes="3" spreadType="center"/>
......
<edge id="nd6to8" from="nd6" to="nd8" numLanes="3" spreadType="center"/>
<edge id="-nd6to8" from="nd8" to="nd6" numLanes="3" spreadType="center"/>
</edges>
也很好理解嘛。第一个参数就是 i d id id ,第二三各参数就是表示从哪个节点到哪个节点,第四个节点就是这条边有几个车道,最后一个参数就是车道向哪边扩展。一般定义为 c e n t e r center center 时都是单向车道的情况,双向车道一般是 r i g h t right right ,系统默认也是如此(只不过我想试试,就定义了 c e n t e r center center)
可能会注意到,每条边都定义了两条相反的,毕竟基本上都得定义双向车道嘛!
3.3 connection文件
我暂时没有这个需求,就没写。后缀为 . c o n . x m l .con.xml .con.xml 。基本作用就是控制道路的每一条车道经过节点后要前往哪个车道。比如就可以定义靠左的车道必须左转,并且要左转到哪个车道。
官网给的例子:
<connections>
<connection from="1si" to="3o"/>
<connection from="1si" to="2o"/>
<connection from="2si" to="4o"/>
<connection from="2si" to="1o"/>
</connections>
3.4 组合
如果是只有前两种文件的情况:
netconvert --node-files=MyNodes.nod.xml --edge-files=MyEdges.edg.xml \
--output-file=MySUMONet.net.xml
如果是还有别的文件的情况:
netconvert --node-files=MyNodes.nod.xml --edge-files=MyEdges.edg.xml \
--connection-files=MyConnections.con.xml --type-files=MyTypes.typ.xml \
--output-file=MySUMONet.net.xml
( t y p e f i l e typefile typefile 就是对类型进行定义,方便用的罢了。)
3.5 用Python实现
3.5.1 常数文件
为了方便修改相关参数,我将常数全都放在一个文件 c o n s t a n t s . p y constants.py constants.py 里面了,这同样也是官方文档的处理方法。
INFINITY = 1e400
PREFIX = "net" # 文件名
DOUBLE_ROWS = 8 # 车道数(我没用到,可惜)
ROW_DIST = 50 (相邻节点的距离)
3.5.2 生成程序
import os
import sys
from constant import PREFIX, DOUBLE_ROWS, ROW_DIST
import sumolib
import numpy as np
nodes = open("%s.nod.xml" % PREFIX, "w")
print("<nodes>", file = nodes)
edges = open("%s.edg.xml" % PREFIX, "w")
print("<edges>", file = edges)
'''
connections = open("%s.con.xml" % PREFIX, "w")
print("<connections>", file = connections)
'''
# Generate nod.xml
fx = np.array([0, 1, -1], dtype=int)
mem = np.zeros((9, 4), dtype=int)
numn = 0
for i in fx :
for j in fx :
print(' <node id="nd%s" x="%s" y="%s"/>' % (numn, i * ROW_DIST, j * ROW_DIST), file = nodes)
mem[numn, 1] = numn
mem[numn, 2] = i
mem[numn, 3] = j
numn += 1
#Generate edg.xml
for i in range(0, numn) :
for j in range(i + 1, numn) :
if(mem[i, 2] == mem[j, 2] - 1 and mem[i, 3] == mem[j, 3]) :
print(' <edge id="nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, i, j), file = edges)
print(' <edge id="-nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, j, i), file = edges)
if(mem[i, 2] == mem[j, 2] + 1 and mem[i, 3] == mem[j, 3]) :
print(' <edge id="nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, i, j), file = edges)
print(' <edge id="-nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, j, i), file = edges)
if(mem[i, 2] == mem[j, 2] and mem[i, 3] == mem[j, 3] - 1) :
print(' <edge id="nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, i, j), file = edges)
print(' <edge id="-nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, j, i), file = edges)
if (mem[i, 2] == mem[j, 2] and mem[i, 3] == mem[j, 3] + 1):
print(' <edge id="nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, i, j), file = edges)
print(' <edge id="-nd%sto%s" from="nd%s" to="nd%s" numLanes="3" spreadType="center"/>' % (i, j, j, i), file = edges)
print("</nodes>", file = nodes)
print("</edges>", file = edges)
nodes.close()
edges.close()
os.system('netconvert --node-files=net.nod.xml --edge-files=net.edg.xml --output-file=map.net.xml')
写的真的很简单,最后生成的是一个 3 ∗ 3 3*3 3∗3 的田字形的路网。
二、路由文件
这里只介绍常用的方法。全部的方法请查看官方文档。
1.直接对路由文件进行编辑。
使用这个方法,可以创建一个后缀为 . r o u . x m l .rou.xml .rou.xml的文件,然后对其进行编辑。提一嘴,我超级推荐 用 S u b l i m e Sublime Sublime进行编辑。
<routes>
<vType id="type1" accel="0.8" decel="4.5" sigma="0.5" length="5" maxSpeed="70"/>
<vehicle id="0" type="type1" depart="0" color="1,0,0">
<route edges="beg middle end rend"/>
</vehicle>
</routes>
对其中的一些参数进行介绍。
vType
标签为 v T y p e vType vType的部分就是可以对一整类车辆进行定义。比如这个就是定义了类型为 t y p e 1 type1 type1的车辆。那么之后无论是车辆还是车流,只要让 t y p e type type属性等于 t y p e 1 type1 type1,那这车或者车流里面所有的车都是 t y p e 1 type1 type1属性的。
a
c
c
e
l
accel
accel:加速度
d
e
c
e
l
decel
decel:减速度
m
a
x
S
p
e
e
d
maxSpeed
maxSpeed:最大速度
注意:
i
d
id
id必须是独一无二的。
其他两个都是与跟车模型相关的参数。
Vehicle
这个标签就是定义单辆车的属性。
D
e
p
a
r
t
Depart
Depart是指到达路网的时间,必须递增。
c
o
l
o
r
color
color是
R
G
B
RGB
RGB。
t
y
p
e
type
type就是上面所定义的车辆类型。
r
o
u
t
e
e
d
g
e
s
route\ edges
route edges是指路线,填写的是道路的
i
d
id
id,就是从某一条道路,到某一条道路,再到某一条道路等等。用空格隔开,可以填很多。
有没有可能很多辆车都是同样的 r o u t e e d g e s route\ edges route edges呢?当然是有可能的。那如果还一个一个复制粘贴是不是有点过于麻烦了?所以也可以这么写:
<routes>
<vType id="type1" accel="0.8" decel="4.5" sigma="0.5" length="5" maxSpeed="70"/>
<route id="route0" color="1,1,0" edges="beg middle end rend"/>
<vehicle id="0" type="type1" route="route0" depart="0" color="1,0,0"/>
<vehicle id="1" type="type1" route="route0" depart="0" color="0,1,0"/>
</routes>
routes
所以说,路线也是可以提前预设的。在预设后,只需要让每一辆车的 r o u t e route route等于你所设的路线的 i d id id就可以了。
flows
<routes>
<vType id="type1" accel="0.8" decel="4.5" sigma="0.5" length="5" maxSpeed="70"/>
<route id="route0" color="1,1,0" edges="beg middle end rend"/>
<vehicle id="0" type="type1" route="route0" depart="0" color="1,0,0"/>
<vehicle id="1" type="type1" route="route0" depart="0" color="0,1,0"/>
<flow id="2" color="1,1,0" begin="0" end= "7200" period="900" type="type1" route="route0" />
</routes>
这样就可以直接增加车流。关于其中的参数:
b
e
g
i
n
begin
begin:车流出现时间,单位为毫秒。
e
n
d
end
end:车流结束时间,单位为毫秒。
p
e
r
i
o
d
period
period:车流中每辆车出现的间隔。
也有这样的形式:
<flow id="f2" begin="0" end="100" number="23" from="beg" to="end" via="e1 e23 e7"/>
不过这种形式并不常见,一般会直接用后面所会提及的 t u r n s turns turns和 f l o w s flows flows的联合使用来达到。
2.Flows和Turns文件联合生成
2.1 Flows文件
F l o w s Flows Flows文件的后缀为 . f l o w s . x m l .flows.xml .flows.xml。所以先创建一个以这个为后缀的文件,然后进行编辑。这个文件所记录的就是车流的信息。
<flowdefs>
<flow id="0" from="E7" begin="0" end="100" number="100"/>
</flowdefs>
f
r
o
m
from
from:就是这个车流从哪条道路出现。
b
e
g
i
n
begin
begin和
e
n
d
end
end在前一部分已经讲过,就是开始和停止时间,单位为毫秒。
n
u
m
b
e
r
number
number:就是在这一段时间内这个车流会包含多少辆车。当然,也可以使用
p
e
r
i
o
d
period
period属性。
2.2 Turns文件
T u r n s Turns Turns文件的后缀为 . t u r n s . x m l .turns.xml .turns.xml。所以先创建一个以这个为后缀的文件,然后进行编辑。这个文件所记录的车辆从某一条车道行驶到另一条车道的概率。
<turns>
<interval begin="0" end="3600">
<edgeRelation from="E1" to="-E2" probability="0.2"/>
<edgeRelation from="E1" to="-E3" probability="0.7"/>
<edgeRelation from="E1" to="E0" probability="0.1"/>
</interval>
</turns>
感觉不需要多解释了,就是从某车道到每一条相连的、可以到达的车辆的概率。切记概率之和一定要等于 1 1 1。
2.3 生成路由文件
jtrrouter --route-files=tmp.flows.xml --turn-ratio-files=tmp.turns.xml --net-file=123.net.xml --output-file=cross_turn.rou.xml --accept-all-destinations=t
在执行之前一定要记得 c d cd cd到当前文件夹。最后一句 − − a c c e p t − a l l − d e s t i n a t i o n s = t --accept-all-destinations=t −−accept−all−destinations=t一定要加。因为我们所绘制的路网一般来说都是直接断开的,并不相通。所以如果不加的话会产生 b u g bug bug。
3.OD矩阵
使用 O D OD OD矩阵来生成需要以下几个文件的编写:
3.1 TAZ文件
T A Z TAZ TAZ文件的后缀是“ . t a z . x m l .taz.xml .taz.xml”,主要的作用就是为每一条道路进行命名。代码如下:
<additional>
<tazs>
<taz id="1" edges="E0"></taz>
<taz id="2" edges="E1"></taz>
<taz id="3" edges="E2"></taz>
</tazs>
</additional>
代码样式也十分简单,就是为每一条 e d g e edge edge指定一个 i d id id。
3.2 OD文件
O D OD OD文件的后缀是 . o d .od .od。主要用来指定以起止的时间,以及从一条路到另一条路的车流量是多少。
$OR;D2
* From-Time To-Time
0.00 1.00
* Factor
1.00
* some
* additional
* comments
1 1 100
1 2 200
1 3 300
2 1 400
2 2 500
2 3 600
3 1 700
3 2 800
3 3 900
F r o m − T i m e From-Time From−Time和 T o − T i m e To-Time To−Time就是起止时间,格式为 H O U R . M I N U T E HOUR.MINUTE HOUR.MINUTE,也就是说小数点前面是小时数,后面是分钟数。
后面的行车因子一般不用管。
后面的几行就是:从某个车道到另一个车道通过了几辆车。车道的指定方法就是前面的 T A Z TAZ TAZ文件里面所定义的 i d id id。
3.3 config文件
主要的作用就是指定我们前面所说的 T A Z TAZ TAZ文件和 O D OD OD文件。文件命名为“ c o n f i g . x m l config.xml config.xml”。
<configuration>
<input>
<taz-files value="xxx.taz.xml"/>
<od-matrix-files value="xxx.od"/>
</input>
<!--
<output>
<output-file value="od_file.odtrips.xml"/>
</output>
-->
</configuration>
3.4 odtrips文件
这个文件比较简单,可以直接用命令行来得到。
od2trips -c xxx.config.xml -n xxx.taz.xml -d xxx.od -o od_file.odtrips.xml
在这个命令里面,你就看到了我们前面所搞到的三个文件: T A Z TAZ TAZ文件、 O D OD OD文件以及 c o n f i g config config文件。最后生成的文件是 o d f i l e . o d t r i p s . x m l od_file.odtrips.xml odfile.odtrips.xml。
3.5 duarcfg文件
文件名应为 d u a r c f g f i l e . t r i p s 2 r o u t e s . d u a r c f g duarcfg_file.trips2routes.duarcfg duarcfgfile.trips2routes.duarcfg,然后把下面的代码复制进去就可以了。路网文件以及 o d t r i p s odtrips odtrips文件别打错了。
<configuration>
<!-- The duarouter configuration file takes as input your network and the OD Trips File and output
the route file -->
<input>
<net-file value="xxx.net.xml"/> <!-- Your SUMO Network File -->
<route-files value="od_file.odtrips.xml"/> <!-- Your SUMO OD Trips File -->
</input>
<output>
<output-file value="od_route_file.odtrips.rou.xml"/>
</output>
<report>
<xml-validation value="never"/>
<no-step-log value="true"/>
</report>
</configuration>
3.6 生成rou文件
用命令行运行,就可以生成路由文件了(好麻烦)
duarouter -c duarcfg_file.trips2routes.duarcfg
4.生成随机车流
“你的sumo所在的位置\sumo\tools\randomTrips.py” -b t0 -e t1 -p ((t1 - t0) / n) -o map1.trips.xml
其中前面为randomTrips.py的地址
−
b
-b
−b 为开始时间
−
e
-e
−e为结束时间,单位均为秒
−
p
-p
−p就是多长时间生成一辆车(默认为1)
上面的写法就是在 t 0 t0 t0到 t 1 t1 t1时间内生成 n n n辆车的写法。
duarouter -n map.net.xml -t map1.trips.xml -o map1.rou.xml --ignore-errors
就可以生成路由文件了。
生成仿真文件
有了路网文件和路由文件,就可以生成仿真文件直接在 S U M O SUMO SUMO或者 S U M O − G U I SUMO-GUI SUMO−GUI里使用了。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<input>
<net-file value="xxx.net.xml"/>
<route-files value="xxx.rou.xml"/>
</input>
<time>
<begin value="0"/>
<end value="1000"/>
</time>
<processing>
<time-to-teleport value="-1"/>
</processing>
</configuration>
指定好我们之前千辛万苦生成的路网文件和路由文件,然后设定好运行时间(单位为秒)。
将上面的文本保存为 . s u m o c f g .sumocfg .sumocfg文件,就可以使用了。