SUMO交通仿真實戰

理解、預測並最終減少城市路網中的交通擁堵是一個複雜的問題。即使瞭解最簡單的單車道情況下出現的交通擁堵, 也是具有挑戰性的。SUMO是一個開源平臺,可模擬複雜環境中的交通流。在這個教程裏,我們將學習如何從零創建複雜的交通流模擬,使用網格上的流量案例研究來做這方面的工作,教程結構如下:

  1. 爲什麼要研究交通網絡中的流量?
  2. 從SUMO開始
  3. 仿真網格網絡中的交通流
  4. 關鍵流量性能指標分析
  5. 仿真現實交通的未來方向

1、爲什麼要研究交通網絡中的流量?

在之前的一篇文章中,我討論了第一篇論文,該論文最終展示了交通"幻象"衝擊波是如何從無到有地產生的,除了駕駛員的互動。

在這裏插入圖片描述

最近的研究表明,簡化自動駕駛車輛之間的交互可能會減少人爲場景(如繞圈行駛的車輛)的交通堵塞。但是,當你有多條路時會發生什麼,就像在典型的城市道路網中一樣?有趣的是,僅僅通過更多的車道或更長的道路增加容量可能不會符合擬的預期。在另一篇文章中我展示了"Braess悖論"如何導致不尋常的結果,即增加城市網絡中的道路數量,反而可能會使交通惡化!

在進行基建工程,例如興建新道路、增加車道、紅綠燈等前,必須實事求是地仿真交通流量,使項目有最好的機會成功緩解交通。將音樂會、體育賽事等重大活動或機場和醫院等公共建築納入場景時,情況變得更加複雜。在不遠的將來,重要的是要仿真網聯車輛和智能交通技術創新的影響,以最好地發揮其在簡化交通流量方面的潛力。

2、從SUMO開始

交通仿真似乎屬於交通流研究人員或工程承包公司的細分社區。例如,Anylogic、VISSIM和Aimsun是提供交通流建模解決方案的公司。 但是,SUMO 是公開的,並且很容易上手。

有多種方法來安裝SUMO,但我更喜歡使用pip安裝SUMO以及Python庫,以便與SUMO交互。

python -m pip install sumo

就是這樣!現在,讓我們開始創建交通流量的首次仿真!

3、仿真網格中的交通流

在城市規劃中,網格相當普遍。在 SUMO 中,我們設置了一個 5x5 網格,每條道路長度爲 200 米,並設置了 3 條車道,如下所示:

netgenerate — grid — grid.number=5 -L=3 — grid.length=200 — output-file=grid.net.xml

接下來,我們使用位於SUMO主目錄(sumo->tools)中的tools文件夾中的 randomTrips.py,爲一定數量(示例中使用 200 輛車)的車輛生成隨機行程。開始和結束時間表示車輛進入仿真的時間。我選擇了 0&1,這意味着所有車輛在仿真的前 1 秒進入仿真。Period表示車輛的到達率。

randomTrips.py -n grid.net.xml -o flows.xml — begin 0 — end 1 — period 1 — flows 200

接下來,我們使用 SUMO 的 jtrrouter 生成單個車輛的路線,時間從 0 到 10000。

jtrrouter — flow-files=flows.xml — net-file=grid.net.xml — output-file=grid.rou.xml — begin 0 — end 10000 — accept-all-destinations

最後,爲簡單起見,我們希望保持恆定的車輛密度。最顯而易見的方法是車輛隨機駕駛,而不是退出仿真。爲此,我們使用曼哈頓交通模型,在曼哈頓交通模型中,遇到交叉路口的車輛會根據設定的概率選擇直行、左路或右行。在 SUMO 中默認情況下,車輛一旦到達目的地就退出仿真。但是,SUMO也有曼哈頓模型的實現,使用連續變道Python腳本。

generateContinuousRerouters.py -n grid.net.xml — end 10000 -o rerouter.add.xml

接下來,我們創建一個SUMO配置文件,以便在 SUMO 中運行仿真,該文件是具有某些屬性的.xml文件,包含網絡文件的名稱、路由文件和其他變道文件,供車輛在仿真中停留,直到仿真完成。我們定義輸出文件,以便在交通仿真期間存儲詳細的車輛信息。

<configuration>
  <input>
    <net-file value=”grid.net.xml”/>
    <route-files value=”grid.rou.xml”/>
    <additional-files value=”rerouter.add.xml”/>
  </input>
  <time>
    <begin value=”0"/>
    <end value=”10000"/>
  </time>
   <output>
     <fcd-output value=”grid.output.xml”/>
   </output>
</configuration>

最後,我們將在終端中運行如下仿真。Peroid表示保存數據的時間間隔 - 100 表示每 100 個時間步保存車輛信息,即速度和位置。

sumo-gui -c grid.sumocfg — device.fcd.period 100

運行上面命令將彈出 SUMO GUI,你可以看到仿真: 在這裏插入圖片描述

車輛顏色表示其速度從最慢(紅色)到最快(綠色)。

4、多次運行交通仿真

手動更改參數並輸出文件是相當煩人的。如果你要運行100+次仿真探索不同的參數,如車輛數量,交通是如何變化的,然後的多個運行的統計平均。

爲此,我使用操OS模塊在命令提示上與python交互:

def initialize(grids=5,lanes=3,length=200):
    os.system("netgenerate --grid --grid.number=5 -L="+str(lanes)+" --grid.length="+str(length)+" --output-file=grid.net.xml")

def single(path,vehicles):
    os.system(path + "randomTrips.py -n grid.net.xml -o flows.xml --begin 0 --end 1 --period 1 --flows "+str(vehicles))
    os.system("jtrrouter --flow-files=flows.xml --net-file=grid.net.xml --output-file=grid.rou.xml --begin 0 --end 10000 --accept-all-destinations")
    os.system(path + "generateContinuousRerouters.py -n grid.net.xml --end 10000 -o rerouter.add.xml")
    tree = ET.parse("grid.sumocfg")
    root = tree.getroot()
    for child in root:
        if (child.tag == 'output'):
            for child2 in child:
                child2.attrib['value'] = 'grid.output'+str(vehicles)+'.xml'
    with open('grid.sumocfg', 'wb') as f:
        tree.write(f)
    os.system("sumo -c grid.sumocfg --device.fcd.period 100")

    if __name__ == '__main__':
    import os
    import numpy as np
    import analysis
    from matplotlib import pyplot as plt

    import xml.etree.ElementTree as ET
    path = "C:\\Users\\BLAH\\AppData\\Local\\Programs\\Python\\Python39\\Lib\\site-packages\\sumo\\tools\\"
    initialize()
    vehicles_arr=np.r_[np.linspace(10,100,10).astype(int),np.linspace(100,2000,20).astype(int)]
    for i in range(0,len(vehicles_arr)):
        single(path,vehicles_arr[i])

5、分析

SUMO xml 輸出包含每個時間步的單個車輛時間、位置和速度的信息。我希望分析速度是如何依賴車輛密度,或仿真中的車輛數量 - 基本上在每一個時間步獲得速度,然後在仿真的所有車輛上進行平均。

def textify(vehicles):
    tree = ET.parse("grid.output"+str(vehicles)+".xml")
    root = tree.getroot()

    l = 0
    for child in root:
        for child2 in child:
            l += 1

    c = 0
    t = 0
    a = ''
    speeds = np.zeros(l)
    times = np.zeros(l)
    ids = np.zeros(l)
    for child in root:
        for child2 in child:
            # print(child2.tag, child2.attrib)
            if (child2.tag == 'vehicle'):
                a = (child2.attrib)
                speeds[c] = np.float(a['speed'])
                ids[c] = np.float(a['id'])
                times[c] = t
                c = c + 1
        t = t + 1
        # print(t)
    data = np.c_[ids, times, speeds]

    tt = len(np.unique(data[:, 1]))
    vel = np.zeros(tt)
    nc = np.zeros(tt)
    flux = np.zeros(tt)

    for i in range(0, tt):
        w = np.where(data[:, 1] == i)
        vel[i] = np.mean(data[w, 2])
        nc[i] = len(w[0])
        flux[i] = np.sum(data[w, 2])
        velm = np.c_[nc, vel, flux]

    np.savetxt('velm'+str(vehicles)+'.txt',velm)

最後,繪製速度 - 密度圖,其中每個仿真運行都有單獨的密度:

import numpy as np
from matplotlib import pyplot as plt
def plots(vehicles):
    vel=np.zeros(len(vehicles))
    nc=np.zeros(len(vehicles))
    flux=np.zeros(len(vehicles))
    for i in range(0,len(vehicles)):
        txt=np.loadtxt('velm'+str(vehicles[i])+'.txt')
        nc[i] = np.mean(txt[95:100, 0])
        vel[i] = np.mean(txt[95:100, 1])
        flux[i]=np.mean(txt[95:100,2])
        print(nc[i],vel[i],flux[i])
    fig=plt.figure()
    plt.plot(nc/3000,vel,'o')
    plt.plot(nc / 3000, vel, color='k')
    plt.xlabel('Density')
    plt.ylabel('Velocity')
    plt.tight_layout()
    plt.savefig('vel-density.png',dpi=600)
    #plt.show()

    fig=plt.figure()
    plt.plot(nc / 3000,flux,'o',label='Traffic Simulation')
    plt.plot(nc / 3000, flux, color='k')
    plt.plot(vehicles/3000,vehicles*vel[0],'r--',label='No Interaction')
    plt.ylim(0,2800)
    plt.legend()
    plt.xlabel('Density')
    plt.ylabel('Flux')
    plt.tight_layout()
    plt.savefig('flux-density.png', dpi=600)

在這裏插入圖片描述

正如你所看到的,隨着密度的增加,速度會降低。這是因爲仿真中的車輛越多,擁塞越多,導致行駛速度降低。這是我們大家在高速公路上看到的東西,尤其是在高峯時段。

交通仿真中另一個常用的參數是通量。正如我在上一篇文章中所討論的,通量衡量每次通過給定點的車輛數量,是衡量車輛吞吐量的指標。通量公式爲: 在這裏插入圖片描述

上述公式彙總長度 L 內的所有車輛的速度,以及車道數量 n_l。

在低密度下,每輛車基本上都是在限速行駛,因此通量會隨着密度的直線增加(下面圖中的紅線)。但是,在密度較高時,車輛不能在限速行駛,在某一點上,以較小的速度行駛的每輛車都會抵消車輛數量較多的影響,從而減少通量。在特徵密度(此模擬中爲 +0.1= 0.2)之上,會出現交通堵塞,並且通量隨着密度降低而減小。 在這裏插入圖片描述

6、仿真真實的交通

我已經演示瞭如何使用 SUMO+Python 在具有代表性的網格中設置基本的交通仿真和合奏運行。然而,這絕不是對城市交通網絡的全面仿真。在最近的一項研究中,利用OpenStreetMap和OSMnx,發現了城市網格的一些特點。SUMO 包括通過將 OpenStreetMap數據轉換爲 SUMO.net文件來仿真城市街道網絡中的流量。

但是,除了現實城市網絡上的仿真之外,還有校準這些交通仿真以匹配日常交通模式的問題。爲了與日常生活中看到的詳細交通模式相匹配,人們需要考慮進入道路的人的起伏,他們何時進入,何時/何地離開。這是一個極其複雜的問題,因爲不可能知道每一個車輛的軌跡。現在,許多車輛將 GPS 數據傳輸給 INRIX 和 HERE這樣的公司。Google和Apple等公司利用手機數據來獲得稀疏的位置和速度信息。但是,這隻能提供整個人口的一小部分信息。交通流是一個高度非線性的問題:這意味着小的變化可能會產生極端的後果。

同時,我們希望交通流仿真結果在不同的初始條件下是可靠的。結果應清楚地表明,對於各種情況,建議的項目是否具有顯著的交通流改善。擁有詳細的大規模交通仿真是一項挑戰,這些仿真在可行的時間內運行,並且是現實的。

在 SUMO 頁面上,只有少數這樣的現實場景。頁面頂部如下文字:

構建一個場景包含很多工作。如果你已經構建了一個 可以共享的SUMO 場景,請與我們聯繫。 希望交通運動數據的民主化、計算資源的日益可用以及開源交通流建模平臺將使這些大型仿真更加容易訪問。


原文鏈接:SUMO交通流仿真實戰 - BimAnt

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章