要点初见:安装教程与二度拓展——基于SUMO的Flow Project(附代码链接)

前文链接:要点初见:用Python进行微观交通模型仿真——基于SUMO的伯克利开源项目Flow Project初探与拓展

前文链接中是博主先前写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/flow中的源码后需要重新运行python setup.py develop对项目进行rebuild,Flow核心中部分的代码需要rebuild才会生效,例如flow/flow/core/kernel/simulation/、flow/flow/core/experiment.py,部分核心代码不需要rebuild也能生效,例如flow/flow/core/kernel/network/,但每次修改源码后运行python setup.py develop能避免改动未生效。

**************************************************************

不多废话,此处是在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.json

flow/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 traci
from flow.core.kernel.vehicle import KernelVehicle
from flow.core.kernel.vehicle import TraCIVehicle
from flow.core.kernel import Kernel
from flow.core.params import SimParams

from flow.controllers import IDMController, SimLaneChangeController, RLController
from flow.core.params import SumoParams, EnvParams, NetParams, InitialConfig, SumoLaneChangeParams, SumoCarFollowingParams
from flow.core.params import VehicleParams, InFlows
from flow.envs.ring.lane_change_accel import ADDITIONAL_ENV_PARAMS
from flow.networks.highway import HighwayNetwork, ADDITIONAL_NET_PARAMS
from 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中的文件)。

欢迎交流讨论!对Flow Project有更深入的疑惑可以在stackoverflow的专题链接中提问(带上flow-project的标签,回的挺快):https://stackoverflow.com/questions/tagged/flow-project

猜你喜欢

转载自blog.csdn.net/m0_37857300/article/details/113762705