当前位置:   article > 正文

SUMO(二)——与Python的基本联合_sumo python

sumo python

这篇文章主要 S U M O SUMO SUMO P y t h o n Python Python 的基本联合写法,还不涉及 T r a C I TraCI TraCI 接口。本文举的例子的目的是探索一个路口中到达率大小与停车率的关系

0 基础准备

0.1 知识准备

在看这篇文章之前,你需要:

0.2 文件准备

在项目文件夹中,你需要:

  • 一个路网文件( . n e t . x m l .net.xml .net.xml)
  • 一个仿真文件 ( . s u m o c f g .sumocfg .sumocfg)

我的路网文件名称是 c r o s s . n e t . x m l cross.net.xml 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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

(仿真了1000秒的)

完成了这些工作,我们就继续进行吧!

1 生成相关数据

在项目文件夹里新建 m a i n . p y main.py main.py ,开始编写程序吧!

1.1 生成路由文件

1.1.1 生成随机车流

这是最简单的生成路由文件的方法,一般来说就会用这种方法。

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")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

代码部分解释:

  • 函数参数中的 p a t h path path 是指 S U M O SUMO SUMO 文件夹中 t o o l s tools tools 文件夹的路径。 p e r i o d period period 是指每隔多长时间生成一辆车,单位为秒,实际上也就是到达率的倒数。
  • 2 2 2 3 3 3行就是 S U M O SUMO SUMO 自带的一些命令,通过 o s os os 模块来模拟命令提示符的使用来输入指令。第二行就是生成随机车流,我们设定仿真时间为 1000 1000 1000。第三行将其转化为路由文件。
  • 后面则是对仿真文件进行转换。由于我们会调用好多次生成路由文件的函数,而每次调用的 p e r i o d period period 都不一样,我们要保留每种情况的仿真结果。于是我们让每次仿真的仿真结果保存为 c r o s s . o u t p u t + s t r ( p e r i o d ) + . x m l cross.output + str(period) + .xml cross.output+str(period)+.xml 形式。比如说我们某一次仿真的 p e r i o d period period 0.05 0.05 0.05 ,那么我们保存的输出结果就会是 c r o s s . o u t p u t 0.05. x m l cross.output0.05.xml cross.output0.05.xml 。这样就不会出现名字重复的问题,我们也可以找到各个 p e r i o d period period 所对应的仿真结果。如果这一部分代码看不明白请参照 0.1 中的 “掌握基本的 x m l . e t r e e . E l e m e n t T r e e xml.etree.ElementTree xml.etree.ElementTree (或者其他处理 x m l xml xml 文件的方法)知识;”
  • 最后则是运行 S U M O SUMO SUMO 进行仿真,每 100 100 100 秒保存一次结果。

1.1.2 其他生成方式

其他生成方式请参照0.1中所介绍的 S U M O SUMO SUMO 基本知识。但是应用那些方式的话需要从头开始创建 . x m l .xml .xml 文件,好麻烦。等什么时候有需求了我再来填坑吧。

1.2 对仿真结果进行处理

先来看看看仿真结果长什么样子吧。找一个短一点的展示,就找 p e r i o d period period 9 9 9 的来吧!

<?xml version="1.0" encoding="UTF-8"?>

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

前面的注释部分已经被我删掉了。具体来看一下:

因为我们之前已经提到,仿真时间为 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

代码解释:

  • 函数的参数和上面一样, n u m num num 代表的是正在处理的是第几个 p e r i o d period period,也就是标号。
  • 由于我们所期望的是得到一个相对稳定的结果,所以我们肯定是选择仿真了一段时间之后的结果,也就是选择所经过时间最长,也就是经过了 900 900 900 秒的结果。
  • 将这个时间里面的静止车辆(1 m / s m/s m/s 以下我也算作是静止了)的车辆数统计来,与总的车辆数相除,得到静止车辆的比例。
  • p e r i o d period period 与相对应的静止车辆的比例记录到 d a t a data data 中。(第 0 0 0 行是 p e r i o d period period,第 1 1 1 行是比例,记录到第 n u m num num 列中)

1.3 主函数

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

代码解释:

  • 感觉……没啥好解释的。写的很简单。
  • 就是要注意我用了 D e c i m a l Decimal Decimal 保留两位小数。不这么干的话,由于二进制储存小数的机制,就会出现储存的小数不准的问题,就会出现如下情况:

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/645495
推荐阅读
相关标签