前文連結:要點初見:用Python進行微觀交通模型模擬——基於SUMO的伯克利開源專案Flow Project初探與拓展
(https://blog.csdn.net/m0_37857300/article/details/100076886)
前文連結中是博主先前寫TRB論文時根據個人研究所寫的Flow Project介紹、程式碼解釋以及初步的功能拓展方法介紹,簡單說就是一個能用python設計執行微觀交通流模擬、方便在微觀交通流中進行強化學習(Reinforcement Learning)的好東西(官方連結:https://github.com/flow-project/flow)。最近寫畢業論文又撿起了Flow Project用來做微觀交通流模擬,安裝運行了Flow官方Github上的master分支程式碼(最新flow版本:flow0.5.0)後發現這新版本仍然沒有實現眾多模擬時必要的功能,譬如每個車輛的長寬等引數定製、每條道路的行駛速度等引數定製等等。其實這些功能都是SUMO中已有的,只需要一點銜接就能在Flow中實現這些功能,Flow作為SUMO的二次開發框架可能更集中於強化學習部分的功能開發,故在基礎功能開發方面未有深入。
本文不會具體介紹這些功能銜接的具體實現(想了解可以將highway_newfunc分支的程式碼覆蓋至master分支,並用VSCode之類的IDE檢視Source Control-CHANGES),本文主要是給出連結、介紹最佳化後的Flow超簡單安裝方法、介紹此次拓展出的功能,並分析示例程式碼(test0205.py)。本文的執行環境是 Ubuntu16.04, anaconda 4.6.11。
不多廢話,此處是在Flow(2021.2.8 master分支)上實現了這些功能銜接的程式碼連結(注意是highway_newfunc分支而非master分支):
Github 連結:
https://github.com/BingLiHanShuang/flow/tree/highway_newfunc
百度網盤連結:
https://pan.baidu.com/s/1GD3gb5sHthAzTBpvM0JTSw
提取碼:59pe
1、下載並切換分支
此處展示透過git下載並切換至本分支所需的命令:
1、git clone
https://github.com/BingLiHanShuang/flow.git
2、cd flow
3、git checkout highway_newfunc
2、安裝Flow
切換至highway_newfunc分支後,Flow安裝起來相比master分支更簡單!具體方法如下(此時在flow目錄下,需提前安裝好anaconda)(參考Flow官方文件:https://flow.readthedocs.io/en/latest/flow_setup.html):
1、pip config set global.index-url
https://pypi.tuna.tsinghua.edu.cn/simple(更適合中國寶寶體質)
2、conda env create -f environment.yml
3、pip install -r requirements.txt
4、安裝sumo:根據自己的系統執行如下對應的指令碼
Ubuntu 14.04:
執行flow/scripts/setup_sumo_ubuntu1404.sh
Ubuntu 16.04:
執行flow/scripts/setup_sumo_ubuntu1604.sh
Ubuntu 18.04:
執行flow/scripts/setup_sumo_ubuntu1804.sh
Mac:
執行flow/scripts/setup_sumo_osx.sh
5、執行如下命令測試sumo是否安裝成功:
which sumo
sumo --version
sumo-gui
6、conda activate flow_new2
7、python setup.py develop(此步驟若執行timeout超時可多次執行)
3、Flow拓展的原理以及修改的檔案
Flow的本質實際上是透過程式碼自動化撰寫SUMO相關的xml等檔案、設定Flow引數,並呼叫SUMO中的Python介面TraCI從而實現SUMO模擬:前者主要由example/exp_configs裡的python指令碼實現,後者估摸著是由simulate.py實現。先前在stackoverflow上博主曾詢問了Flow是否能實現定製每條道路單獨速度的問題
(https://stackoverflow.com/questions/56901221/can-we-choose-max-and-min-speeds-for-each-traffic-lane-in-flow-project),得到的回答說是可以直接單獨呼叫TraCI實現該功能,實際上博主嘗試後發現暫時還無法介入Flow呼叫TraCI的層面進行功能實現,但可以從撰寫xml檔案(即前文所述的銜接)的角度入手進行原始碼修改從而將SUMO中已有的功能移植到flow中。
本highway_newfunc分支修改的檔案如下:
1、flow/environment.yml
2、flow/README.md
3、flow/requirements.txt
4、flow/examples/exp_configs/non_rl/test0205.py
5、flow/core/params.py
6、flow/core/kernel/network/traci.py
7、flow/networks/highway.py
4、highway_newfunc分支的拓展功能
本highway_newfunc分支主要實現的功能如下:
1、改進了Flow安裝方法,解決了一個依賴庫的版本bug:在conda env create時pip應先被安裝再安裝其他庫。而redis需>=3.3.2才能符合environment.yml中某個庫的依賴。(具體哪個忘了……)
2、為VehicleParams類增加了length、width、height和vClass引數,即可在Flow程式碼中新增車輛時設定該種車輛的長、寬、高、車輛型別,這些設定能在SUMO模擬中直觀生效。車輛型別預設為passenger,具體內容選擇可在該連結中查詢:
https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#abstract_vehicle_class。
未來還能為VehicleParams類新增的引數可以參考這個連結:
https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#available_vtype_attributes。
3、在highway路網中增加了lane_list引數(其他路網中未新增,若想新增請參考flow/flow/networks/highway.py),即可為每個edge上的每條lane單獨設定專門的行駛速度上限、禁行的車輛種類名單。SUMO中的道路(lane)是建立在edge(出發邊緣)上的。禁行的車輛種類名單的書寫格式為“A”或“A B C 等等”,A的內容需從上文車輛型別的具體內容連結中選取,不同種類由空格隔開。未來還能為每條道路新增的引數可以參考這個連結:
https://sumo.dlr.de/docs/Networks/PlainXML.html#lane-specific_definitions
4、為TraCIKernelNetwork類增加了width引數,即可設定整個模擬中的道路寬度,同樣能在SUMO模擬中直觀生效。未來如果想定製每個edge中每條lane的寬度,方法可以參考3中lane_list的修改方法對原始碼進行修改。
5、增加了對如上4項功能的示例程式碼
flow/examples/exp_configs/non_rl/test0205.py,也是博主畢業論文的模擬基礎……目前未寫測試,待問問Flow官方看不看的上這個拓展版本。
6、以上所有拓展內容都是可選的,模擬不設定上述內容一樣可跑。
5、執行示例程式碼
示例程式碼的執行方法:
flow/examples/exp_configs/non_rl/test0205.py
1、新開一個Terminal視窗,切換到flow專案目錄下
2、conda deactivate
3、source activate flow_new2
4、export
PYTHONPATH="/home/hongyong/.conda/envs/flow_new2/lib/python3.7/site-packages:$PYTHONPATH"
5、python examples/simulate.py test0205 --gen_emission
輸出結果:
/home/hongyong/.conda/envs/flow_new2/lib/python3.7/site-packages/numpy/core/fromnumeric.py:3335: RuntimeWarning: Mean of empty slice. out=out, **kwargs) /home/hongyong/.conda/envs/flow_new2/lib/python3.7/site-packages/numpy/core/_methods.py:161: RuntimeWarning: invalid value encountered in double_scalars ret = ret.dtype.type(ret / rcount) Round 0, return: -0.1 ./data/test0205_20210208-1735491612776949.4998093-0_emission.csv ./data Average, std returns: -0.1, 0.0 Average, std velocities: nan, nan Average, std outflows: 2030.4, 0.0 Total time: 220.84119844436646 steps/second: 48.04350433419724
執行生成的檔案:flow/data/test0205.jsonflow/data/test0205_20210208-1735491612776949.4998093-0_emission.csv (237.8 MB, 研究Flow模擬的核心所在,但太大了所以git pull前和json檔案一起刪了)6、示例程式碼flow/examples/exp_configs/non_rl/test0205.py分析先給出全貌:
"""Example of an open multi-lane network with human-driven vehicles.""" import tracifrom flow.core.kernel.vehicle import KernelVehiclefrom flow.core.kernel.vehicle import TraCIVehiclefrom flow.core.kernel import Kernelfrom flow.core.params import SimParams from flow.controllers import IDMController, SimLaneChangeController, RLControllerfrom flow.core.params import SumoParams, EnvParams, NetParams, InitialConfig, SumoLaneChangeParams, SumoCarFollowingParamsfrom flow.core.params import VehicleParams, InFlowsfrom flow.envs.ring.lane_change_accel import ADDITIONAL_ENV_PARAMSfrom flow.networks.highway import HighwayNetwork, ADDITIONAL_NET_PARAMSfrom flow.envs import LaneChangeAccelEnv vehicles = VehicleParams() vehicles.add( veh_id="rlcar",# Lincoln MKC 4552*1864*1654 THIS IS TYPE NAME length = 4.552, width = 1.864, height = 1.654, vClass = "passenger", #color = "1,0,0", acceleration_controller=(RLController, {}), car_following_params=SumoCarFollowingParams( speed_mode="obey_safe_speed", max_speed=33.333, accel=2.6, #Wait changed decel=4.5, sigma=0.5, tau=1.0, min_gap=2.5, speed_factor=1.0, speed_dev=0.1, impatience=0.5, car_follow_model="IDM" ), lane_change_params=SumoLaneChangeParams( lane_change_mode="only_speed_gain_safe",# no_lc_safe, Disable all SUMO lane changing but still handle safety checks (collision avoidance and safety-gap enforcement) in the simulation. model="SL2015", lc_sublane=2.0, ), num_vehicles=0) vehicles.add( veh_id="humancar",# Volkswagen LAVIDA 4670*1806*1474 max:120km/h length = 4.67, width = 1.806, height = 1.474, vClass = "passenger", #v0 : desirable velocity, in m/s (default: 30) in flow/flow/controllers/car_following_models.py 352 acceleration_controller=(IDMController,{'v0':32}),# desirable velocity 115km/h car_following_params=SumoCarFollowingParams( speed_mode="obey_safe_speed", # default max_speed=33.333, accel=2.6, #Wait changed decel=4.5, sigma=0.5, tau=1.0, min_gap=2.5, speed_factor=1.0, speed_dev=0.1, impatience=0.5, car_follow_model="IDM" ), lane_change_params=SumoLaneChangeParams( lane_change_mode="only_speed_gain_safe",# sumo_default, only_speed_gain_safe, only_strategic_safe, only_cooperative_safe model="SL2015", # Lane-changing model for sublane-simulation [https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html] [https://sumo.dlr.de/docs/Simulation/SublaneModel.html] lc_sublane=2.0, # The eagerness for using the configured lateral alignment within the lane. Higher values result in increased willingness to sacrifice speed for alignment. default: 1.0, range [0-inf] ), num_vehicles=0) vehicles.add( veh_id="humanbus",# YUTONG ZK6826BEV 8245*2500*3240 max:100km/h length = 8.245, width = 2.500, height = 3.240, vClass = "bus", color = "1,1,0", acceleration_controller=(IDMController, {'v0':26.4}),# 95km/h car_following_params=SumoCarFollowingParams( speed_mode="obey_safe_speed", # default max_speed=27.778, accel=2.6, #Wait changed decel=4.5, sigma=0.5, tau=1.0, min_gap=2.5, speed_factor=1.0, speed_dev=0.1, impatience=0.5, car_follow_model="IDM" ), lane_change_params=SumoLaneChangeParams( lane_change_mode="only_speed_gain_safe", model="SL2015", lc_sublane=2.0, ), num_vehicles=0) vehicles.add( veh_id="humantruck",# FOTON BJ5319XXY-AB 12000*2550*3950 max:100km/h length = 12, width = 2.550, height = 3.950, vClass = "truck", color = "0,1,0", acceleration_controller=(IDMController, {'v0':25}),# 90km/h car_following_params=SumoCarFollowingParams( speed_mode="obey_safe_speed", # default max_speed=27.778, accel=2.6, #Wait changed decel=4.5, sigma=0.5, tau=1.0, min_gap=2.5, speed_factor=1.0, speed_dev=0.1, impatience=0.5, car_follow_model="IDM" ), lane_change_params=SumoLaneChangeParams( lane_change_mode="only_speed_gain_safe", model="SL2015", lc_sublane=2.0, ), num_vehicles=0) env_params = EnvParams(additional_params=ADDITIONAL_ENV_PARAMS) inflow = InFlows()inflow.add( veh_type="rlcar", edge="highway_0", #probability=0.025,# 0.25 probability for emitting a vehicle each second (not together with vehsPerHour or period) vehs_per_hour=120,#250 depart_lane=3,# the index of the lane, starting with rightmost=0 depart_speed=30) inflow.add( veh_type="humancar", edge="highway_0", #probability=0.85,# 0.25 probability for emitting a vehicle each second (not together with vehsPerHour or period) vehs_per_hour=2500,#15000 depart_lane="random",#free random allowed best first depart_speed=30) inflow.add( veh_type="humanbus", edge="highway_0", #probability=0.1, vehs_per_hour=486,#486 depart_lane="random", depart_speed=26.4) inflow.add( veh_type="humantruck", edge="highway_0", #probability=0.05, vehs_per_hour=486,#486 depart_lane="random", depart_speed=25) flow_params = dict( # name of the experiment exp_tag='test0205', # name of the flow environment the experiment is running on env_name=LaneChangeAccelEnv, # name of the network class the experiment is running on network=HighwayNetwork, # simulator that is used by the experiment simulator='traci', # sumo-related parameters (see flow.core.params.SumoParams) #sim=SumoParams( #render=True, #lateral_resolution=1.0, #), sim=SumoParams( restart_instance=True, sim_step=0.1, # seconds per simulation step, default emission_path="./data/", render=True, # delegate rendering to sumo-gui for back-compatibility(Color) lateral_resolution=3.75, sight_radius=120, # sets the radius of observation for RL vehicles (meter) pxpm=3, # specifies rendering resolution (pixel / meter) show_radius=True # specifies whether to render the radius of RL observation #save_render=True # specifies whether to save rendering data to disk ), # environment related parameters (see flow.core.params.EnvParams) env=EnvParams( horizon=5000, # number of steps per rollouts additional_params=ADDITIONAL_ENV_PARAMS.copy(), ), # network-related parameters (see flow.core.params.NetParams and the # network's documentation or ADDITIONAL_NET_PARAMS component) net=NetParams( inflows=inflow, #additional_params=ADDITIONAL_NET_PARAMS.copy(), additional_params={ 'length': 6000, 'width': 3.75, 'lanes': 4,# highway_0_0(right) highway_0_3(left) 'speed_limit': 33.333, 'num_edges': 1, # 'lane_list': {}, # must available 'lane_list': {'0': # edge index [ { 'index': '0', # 0(right) n-1(left) 'speed': '27.778' }, { 'index': '1', 'speed': '27.778' }, { 'index': '3', 'speed': '33.333', 'disallow': "bus truck" } ] }, #In the order of edges index "use_ghost_edge": False, "ghost_speed_limit": 25, "boundary_cell_length": 500 }, ), # vehicles to be placed in the network at the start of a rollout (see # flow.core.params.VehicleParams) veh=vehicles, # parameters specifying the positioning of vehicles upon initialization/ # reset (see flow.core.params.InitialConfig) initial=InitialConfig( spacing="uniform", shuffle=True, ),)
單步分解可以參考文首的前文連結,裡面有非常詳細的介紹啦。此處主要介紹與本文拓展有關的部分:a. 透過VehicleParams類定製每輛車
vehicles.add( veh_id="humanbus",# YUTONG ZK6826BEV 8245*2500*3240 max:100km/h length = 8.245, width = 2.500, height = 3.240, vClass = "bus", color = "1,1,0", acceleration_controller=(IDMController, {'v0':26.4}),# 95km/h car_following_params=SumoCarFollowingParams( speed_mode="obey_safe_speed", # default max_speed=27.778, accel=2.6, #Wait changed decel=4.5, sigma=0.5, tau=1.0, min_gap=2.5, speed_factor=1.0, speed_dev=0.1, impatience=0.5, car_follow_model="IDM" ), lane_change_params=SumoLaneChangeParams( lane_change_mode="only_speed_gain_safe", model="SL2015", lc_sublane=2.0, ), num_vehicles=0)
以大客車的新增為例,你可以自由設定它的長、寬、高、車輛種類啦。在SUMO模擬中的效果圖如下(即圖中的黃色車輛,右側是其SUMO引數介面):
b.為highway路網增加增加道路寬度引數,並定製每條道路的最高限速、禁行車輛種類名單
net=NetParams( inflows=inflow, #additional_params=ADDITIONAL_NET_PARAMS.copy(), additional_params={ 'length': 6000, 'width': 3.75, 'lanes': 4,# highway_0_0(right) highway_0_3(left) 'speed_limit': 33.333, 'num_edges': 1, # 'lane_list': {}, # must available 'lane_list': {'0': # edge index [ { 'index': '0', # 0(right) n-1(left) 'speed': '27.778' }, { 'index': '1', 'speed': '27.778' }, { 'index': '3', 'speed': '33.333', 'disallow': "bus truck" } ] }, #In the order of edges index "use_ghost_edge": False, "ghost_speed_limit": 25, "boundary_cell_length": 500 }, ),
可以看到,上述程式碼中將道路寬度設定為3.75m,透過lane_list為index為0(edge的index可能需要參考原始碼中讀取edge的順序)的edge上的0、1、3號道路(Flow中0號道路是edge最右側那條)分別定製了最高限速,併為3號道路定製了禁行bus和truck的規則。在SUMO模擬中的0到3號道路的引數圖如下:
建議大家在該示例程式碼的基礎上進行修改開發,如果需要在其他路網(例如下圖Flow官方示例中魔幻的minicity)中實現這些功能,如文首所說可以將highway_newfunc分支的程式碼覆蓋至master分支,並用VSCode之類的IDE檢視Source Control-CHANGES,從而對其他路網進行類似的修改(主要還是修改flow/flow/networks中的檔案)。
https://stackoverflow.com/questions/tagged/flow-project
CSDN閱讀原文:
https://blog.csdn.net/m0_37857300/article/details/113762705