这篇文章主要 S U M O SUMO SUMO 与 P y t h o n Python Python 的基本联合写法,还不涉及 T r a C I TraCI TraCI 接口。本文举的例子的目的是探索一个路口中到达率大小与停车率的关系
在看这篇文章之前,你需要:
在项目文件夹中,你需要:
我的路网文件名称是 c r o s s . n e t . x m l cross.net.xml cross.net.xml ,内容则是一个很简单的十字路口。
仿真文件的内容为:
<configuration>
<input>
<net-file value="cross.net.xml" />
<route-files value="cross.rou.xml" />
input>
<time>
<begin value="0" />
<end value="1000" />
time>
<output>
<fcd-output value="cross.output.xml" />
output>
configuration>
(仿真了1000秒的)
完成了这些工作,我们就继续进行吧!
在项目文件夹里新建 m a i n . p y main.py main.py ,开始编写程序吧!
这是最简单的生成路由文件的方法,一般来说就会用这种方法。
def GenerateRouXml(path, period) :
os.system(path + "randomTrips.py " + "-n cross.net.xml -o cross.trips.xml -b 0 -e 1000 -p " + str(period))
os.system("duarouter -n cross.net.xml -t cross.trips.xml -o cross.rou.xml --ignore-errors")
tree = ET.parse("cross.sumocfg")
root = tree.getroot()
for child in root :
if(child.tag == 'output') :
for child2 in child:
child2.attrib['value'] = 'cross.output' + str(period) + '.xml'
with open("cross.sumocfg", 'wb') as f :
tree.write(f)
os.system("sumo -c cross.sumocfg --device.fcd.period 100")
代码部分解释:
其他生成方式请参照0.1中所介绍的 S U M O SUMO SUMO 基本知识。但是应用那些方式的话需要从头开始创建 . x m l .xml .xml 文件,好麻烦。等什么时候有需求了我再来填坑吧。
先来看看看仿真结果长什么样子吧。找一个短一点的展示,就找 p e r i o d period period 为 9 9 9 的来吧!
<fcd-export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/fcd_file.xsd">
<timestep time="0.00">
<vehicle id="0" x="-94.90" y="-8.00" angle="90.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="5.10" lane="-E2_0" slope="0.00"/>
timestep>
<timestep time="100.00">
<vehicle id="10" x="-11.46" y="11.78" angle="182.98" type="DEFAULT_VEHTYPE" speed="5.60" pos="1.83" lane=":J0_0_0" slope="0.00"/>
<vehicle id="11" x="11.20" y="-92.50" angle="0.00" type="DEFAULT_VEHTYPE" speed="2.40" pos="7.50" lane="-E1_0" slope="0.00"/>
<vehicle id="9" x="-1.60" y="14.60" angle="180.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="85.40" lane="-E3_3" slope="0.00"/>
timestep>
<timestep time="200.00">
<vehicle id="16" x="-17.80" y="-1.60" angle="90.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E2_2" slope="0.00"/>
<vehicle id="20" x="10.68" y="-8.00" angle="90.00" type="DEFAULT_VEHTYPE" speed="9.81" pos="27.48" lane=":J0_15_0" slope="0.00"/>
<vehicle id="21" x="17.82" y="1.60" angle="270.00" type="DEFAULT_VEHTYPE" speed="0.06" pos="82.18" lane="-E0_2" slope="0.00"/>
timestep>
<timestep time="300.00">
<vehicle id="28" x="17.80" y="8.00" angle="270.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E0_0" slope="0.00"/>
<vehicle id="29" x="17.80" y="1.60" angle="270.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E0_2" slope="0.00"/>
timestep>
<timestep time="400.00">
<vehicle id="41" x="-17.80" y="-1.60" angle="90.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E2_2" slope="0.00"/>
<vehicle id="43" x="-41.28" y="8.00" angle="270.00" type="DEFAULT_VEHTYPE" speed="11.44" pos="24.48" lane="E2_0" slope="0.00"/>
timestep>
<timestep time="500.00">
<vehicle id="46" x="-11.20" y="13.19" angle="180.00" type="DEFAULT_VEHTYPE" speed="1.41" pos="0.41" lane=":J0_1_0" slope="0.00"/>
<vehicle id="52" x="1.60" y="-14.60" angle="0.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="85.40" lane="-E1_3" slope="0.00"/>
<vehicle id="54" x="11.20" y="-12.73" angle="0.00" type="DEFAULT_VEHTYPE" speed="1.93" pos="0.87" lane=":J0_10_0" slope="0.00"/>
<vehicle id="55" x="-11.20" y="65.97" angle="180.00" type="DEFAULT_VEHTYPE" speed="10.11" pos="34.03" lane="-E3_0" slope="0.00"/>
timestep>
<timestep time="600.00">
<vehicle id="62" x="17.80" y="1.60" angle="270.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E0_2" slope="0.00"/>
<vehicle id="65" x="37.35" y="-8.00" angle="90.00" type="DEFAULT_VEHTYPE" speed="9.18" pos="20.55" lane="E0_0" slope="0.00"/>
timestep>
<timestep time="700.00">
<vehicle id="74" x="17.80" y="1.60" angle="270.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E0_2" slope="0.00"/>
<vehicle id="76" x="1.60" y="-14.60" angle="0.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="85.40" lane="-E1_3" slope="0.00"/>
timestep>
<timestep time="800.00">
<vehicle id="76" x="-2.63" y="-2.71" angle="324.01" type="DEFAULT_VEHTYPE" speed="6.12" pos="11.99" lane=":J0_13_0" slope="0.00"/>
<vehicle id="78" x="1.60" y="-17.10" angle="0.00" type="DEFAULT_VEHTYPE" speed="3.56" pos="82.90" lane="-E1_3" slope="0.00"/>
<vehicle id="82" x="0.62" y="5.48" angle="160.76" type="DEFAULT_VEHTYPE" speed="4.84" pos="8.56" lane=":J0_4_0" slope="0.00"/>
<vehicle id="83" x="17.80" y="8.00" angle="270.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E0_0" slope="0.00"/>
<vehicle id="87" x="-1.60" y="18.35" angle="180.00" type="DEFAULT_VEHTYPE" speed="2.79" pos="81.65" lane="-E3_3" slope="0.00"/>
<vehicle id="88" x="26.61" y="1.60" angle="270.00" type="DEFAULT_VEHTYPE" speed="9.58" pos="73.39" lane="-E0_2" slope="0.00"/>
timestep>
<timestep time="900.00">
<vehicle id="91" x="-1.60" y="14.60" angle="180.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="85.40" lane="-E3_3" slope="0.00"/>
<vehicle id="93" x="-1.60" y="22.10" angle="180.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="77.90" lane="-E3_3" slope="0.00"/>
<vehicle id="98" x="-17.80" y="-8.00" angle="90.00" type="DEFAULT_VEHTYPE" speed="0.00" pos="82.20" lane="-E2_0" slope="0.00"/>
timestep>
fcd-export>
前面的注释部分已经被我删掉了。具体来看一下:
因为我们之前已经提到,仿真时间为 1000 1000 1000 秒,而我们又是每 100 100 100 秒进行一次数据的获取,所以就有 10 10 10 组结果。
基本结构很简单,就是 r o o t root root 下面有 10 10 10 个 t a g tag tag 为 t i m e s t e p timestep timestep 子节点,也就是记录了每 100 100 100 秒的情况。 t i m e s t e p timestep timestep 下面则是 t a g tag tag 为 v e h i c l e vehicle vehicle 子节点,记录了在这个时间点的每一辆车的具体数据,包括 i d id id ,坐标,速度,车辆类型,所在车道,所在车道的位置等信息。不同的应用会用到不同的信息,而我们所用到的信息就是速度,也就是 s p e e d speed speed 这个 a t t r i b u t e attribute attribute 。
了解了仿真结果的结构,接下来就来看看怎么进行分析吧:
def DealOutputXml(period, num) :
tree = ET.parse("cross.output" + str(period) + ".xml")
root = tree.getroot()
p = 0
l = 0
for child in root :
if(child.attrib['time'] == "900.00") :
for child2 in child :
if(child2.tag == 'vehicle') :
p = p + 1
speed = np.zeros(p)
for child2 in child :
if(child2.tag == 'vehicle') :
speed[l] = np.float(child2.attrib['speed'])
l = l + 1
zer = np.where(speed < 1.0)
ans = np.size(zer[0]) / p
data[(0, num)] = period
data[(1, num)] = ans
代码解释:
if __name__ == '__main__':
import os
import numpy as np
import xml.etree.ElementTree as ET
from decimal import *
path = "/Users/(我的用户名保密就不给你看)/Desktop/tools/"
num = 0 # 存储总共有多少period
now_num = 0 # 目前正在处理第几个period
for i in range(1, 21) :
b = i * 0.05
a = Decimal(b).quantize(Decimal('0.00'))
GenerateRouXml(path, a)
num += 1
for i in range(2, 10) :
GenerateRouXml(path, i)
num += 1
# 上面的代码就是先生成了每个period对应的路由文件 顺便统计了有几个period
data = np.zeros((2, num))
for i in range(1, 21) :
b = i * 0.05
a = Decimal(b).quantize(Decimal('0.00'))
DealOutputXml(a, now_num)
now_num += 1
for i in range(2, 10) :
DealOutputXml(i, now_num)
now_num += 1
np.savetxt("data.txt", data)
代码解释:
经过运行后,就获得了 d a t a . t x t data.txt data.txt
5.000000000000000278e-02 1.000000000000000056e-01 1.499999999999999944e-01 2.000000000000000111e-01 2.500000000000000000e-01 2.999999999999999889e-01 3.499999999999999778e-01 4.000000000000000222e-01 4.500000000000000111e-01 5.000000000000000000e-01 5.500000000000000444e-01 5.999999999999999778e-01 6.500000000000000222e-01 6.999999999999999556e-01 7.500000000000000000e-01 8.000000000000000444e-01 8.499999999999999778e-01 9.000000000000000222e-01 9.499999999999999556e-01 1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00 6.000000000000000000e+00 7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00
8.571428571428570953e-01 8.571428571428570953e-01 8.571428571428570953e-01 7.373737373737373479e-01 8.910891089108911034e-01 9.480519480519480346e-01 8.155339805825242427e-01 7.951807228915662717e-01 7.582417582417582125e-01 8.295454545454545858e-01 7.727272727272727071e-01 9.499999999999999556e-01 8.915662650602409478e-01 7.978723404255319007e-01 8.421052631578946901e-01 8.255813953488372325e-01 8.823529411764705621e-01 8.550724637681159646e-01 8.474576271186440302e-01 8.913043478260869179e-01 7.619047619047618625e-01 6.363636363636363535e-01 7.777777777777777901e-01 7.142857142857143016e-01 5.999999999999999778e-01 1.000000000000000000e+00 5.000000000000000000e-01 1.000000000000000000e+00
这个时候我又新建了一个 p y t h o n python python 文件,代码如下:
if __name__ == '__main__' :
import matplotlib.pyplot as plt
import numpy as np
from decimal import *
data = np.loadtxt("data.txt")
meanspeedr = np.around(data[1, :], 2)
x = np.around(1 / data[0, :], 2)
plt.plot(x, meanspeedr)
plt.xlabel("Arrive Rate")
plt.ylabel("Stop Rate")
plt.show()
在写这个的时候,我注意到一个问题—— N u m P y NumPy NumPy 本身也有保留小数的函数……算了,多学一点也没坏处对吧!
写的也很简单,就是读取了之前我们所存储的数据,然后进行了转化:
然后让到达率当 x x x 轴,停车比例当 y y y 轴进行画图,来实现数据的可视化。
就到这里结束啦。毕竟,从数据获得结论并不是本教程的人物捏。
我是竞赛出身的,所以之前一直是面向过程编程,现在正在努力面向对象编程,所以可能写的代码有些四不像,请大家多多见谅。