赞
踩
博主近期基于研发项目驱动,项目第一阶段需求为基于仿真环境,探索多交叉路口信号灯配时协同优化策略。由于研发内容偏向智慧交通流方向,所以博主选择功能较为强大的交通流仿真软件SUMO+自动驾驶开源仿真软件Carla进行联合仿真。话不多说,博主的开发环境为:Carla0.9.12(source build)+SUMO-V1.12+ROS Melody+Python3.8。关于Carla0.9.12源码安装方法建议参考博主上篇博文+Carla官方安装文档
Carla官方安装文档:https://carla.readthedocs.io/en/latest/build_linux/
关于SUMO源码编译版本安装方法建议参考SUMO官网
SUMO官方安装文档:https://sumo.dlr.de/docs/Installing/index.html
ROS melody及python环境安装网上教程较多,本篇略过。
整个仿真环境大致分为几类元素:
由于项目需求,需要尽可能复现上海某区某路段的真实情景,博主仿真环境中采用的地图是基于高精地图采图车采集到的原始点云数据(.pcd .ply格式),再用roadrunner标注好生成opendrive(1.4)格式的高精地图。高精地图采集过程本文略过,如果没有地图采集条件的同学可以使用Carla自带的地图例子,也是opendrive1.4版本,亲测可行。
真实场景复现其中一项就是配置某路口对应的真实信号灯位置、数量、初始各相位时间及周期。博主采用SUMO自带插件NetEdit,启动方法直接开启终端输出netedit即可。具体配置方法见下文,此处略过。
多交叉路口信号灯配时协同优化需要实时根据当前路口范围内的车流量动态调整信号灯的相位时间,所以仿真环境中,如何生成符合期望的车流量也是非常重要的,博主采用SUMO进行车流生成。具体方法见下文,此处略过
信号灯配时协同优化算法需要不断从仿真软件作为Server端回调各类元素的实时数据,主要包括:
地图数据,例如Junction编号、Node编号、路段路口属性等等;
信号灯实时数据,主要包括初始相位配置、各相位初始持续时间、信号灯实时相位等,并且需要订阅优化算法输出的被优化信号灯编号、相位、优化后该相位对应的时间,通过调用Sumo Traci接口实现对信号灯的控制,具体调用接口的方法见下文,此处略过;
背景车辆实时数据,主要包括某路口一定范围内的场景车辆实时数据,例如车辆速度、位置、姿态、类型、绿灯期间路口通过车辆的数量、车辆等待时间等(后两者主要是为了作为优化算法的优化指标)。
上述元素数据的实时回调方法主要是通过SUMO Traci接口或Carla Python API获得。
仿真框架如下图所示:
整个联合仿真框架主要使用了四种软件分别是:RoadRunner、Carla、SUMO、Netedit
其中Carla与SUMO安装方法不再赘述,netedit作为SUMO的一个插件只要安装好SUMO也无需再单独安装。RoadRunner作为matlab一个单独插件,有需要的同学可能要学校授权才能使用。
首先通过采图车获取某路口的原始点云,FX.pcd文件导入Roadrunner中,通过人工标注,添加路口指示牌、车道线、信号灯、建筑物等信息,其中大部分roadrunner中有自带的3D模型,如果有自定义3D模型需求可以自己用Solidworks或其他建模软件画完导入。将标好的高精地图输出FX.xodr与FX.fbx格式的文件,其中.xodr主要为道路路网信息,.fbx主要是人工标注时添加的各类3D模型。将生成好的.xodr与.fbx导入Carla自定义地图,该方法Carla官方文档写的比较详细,此处不赘述。导入Carla后生成FX.umap作为一个新的“关卡”,可以在UE4中继续编辑。
上述操作基本实现了现实环境在仿真环境中的基础渲染效果,在roadrunner中或者Carla-UE4中添加路口信号灯模型,信号灯相位配置应该是不能通过Carla-UE4的可视化界面进行配置,可以通过Carla-PythonAPI进行相位配置(但此种方法貌似比较麻烦),此处博主采用的方法是用sumo-NetEdit进行配置,非常方便。首先将标注好的FX.xodr转化为sumo可编辑的.net格式文件。转换方法如下:
#先切换到carla源码目录下
cd /<your_carla_folder>/Co-simulation/Sumo/util
#将自己的.xodr文件放入上述目录下
python netconvert_carla.py FX.xodr --output FX.net.xml
#文件夹下出现FX.net.xml则转换成功,其中该脚本的一些可选项命令含义可以输入查询
python netconvert_carla.py -h
#终端输入NetEdit对生成的.net文件进行编辑
netedit
打开sumo-netedit后如下图导入生成的.net文件
左上角File/Open Network打开刚生成的.net文件,随机点击一个junction,然后进入信号灯编辑模式Traffic light mode
上图为配置好初始相位的一个junction,左侧工具栏可以看到,junction的编号为1012,一般信号灯的id与junction的id一样,其中phase一栏可以看出,配置了4个相位(默认配置),1012号junction总共有10个车道,所谓相位就是每条车道的可通行状态的灯色状态组合,每一种灯色状态组合代表一组相位。42、3代表该状态的持续时间。配置完成后点击save然后Create TLS即可。
其中关于“Ggry”的字母含义官方文档是这样解释的:
大致意思就是r代表red红灯,车辆必须停车;y代表yellow黄灯,车辆如果距离路口太远则开始减速,较近的话直接通过;g代表green优先级较低的绿灯,需要让行优先级高的绿灯,例如转弯让直行,右转让左转;G代表优先级最高的绿灯。由于我们国内常见的信号灯基本就是红黄绿,其他灯色目前没有需求也就没研究,基本是用不上的。
关于Ggry的车道排列顺序官方文档是这样解释的:
此处讲一下博主自己的理解,如有误请大家指教。一个标准的十字路口具备四个Link,其中Link的含义为驶入此junction的车道集合,例如上图0到3号link均包括一个车道,所以一个车道即为一个link。SUMO配置相位的默认顺序为从12点钟开始顺时针旋转以link为单位进行配置,其中Link中的车道也为顺时针旋转配置。上图路口此时的相位则为“GrGr”。
到此已经为我们的.net文件配置了信号灯初始相位,后续只要依次按照现实道路的情况配置其他信号灯即可。
生成.rou车流文件之前先生成sumo的车辆类型配置文件,此处运用到一个关键文件,位置在
/<your_carla_folder_root>/Co-Simulation/Sumo/data路径下的vtypes.json。此文件主要内容为carla中的车辆蓝图,vehicle.blueprint,囊括了Carla中的部分车辆类型,例如常见家用车、警车、救护车、电动车等,开发者可以根据自己的需求添加喜欢的车辆蓝图,通过查询carla官方文档中关于vehicle blueprint部分。由于开发环境为sumo+carla的联合仿真,所以需要保证sumo环境下的车辆类型与Carla中保持一致。所以vtypes.json的主要作用是通过create_sumo_vtypes.py脚本(位置在/<your_carla_folder_root>/Co-Simulation/Sumo/util)生成sumo车辆类型文件。
#默认生成文件在/<your_carla_folder_root>/Co-Simulation/Sumo/examples下的carlavtypes.rou.xml python create_sumo_vtypes.py –output-file <yourname>.rou.xml #carlavtypes.rou.xml部分内容 <?xml version='1.0' encoding='UTF-8'?> <!--generated on 2020-03-04 18:25:00 by create_sumo_vtypes.py--> <routes> <vType id="vehicle.audi.a2" length="3.7186214923858643" width="1.7924479246139526" height="1.5354934930801392" vClass="passenger"/> <vType id="vehicle.audi.tt" length="4.147226333618164" width="2.0032031536102295" height="1.382421851158142" vClass="passenger"/> <vType id="vehicle.carlamotors.carlacola" length="5.1992292404174805" width="2.6150190830230713" height="2.4768505096435547" vClass="truck" guiShape="truck"/> <vType id="vehicle.dodge.charger_police" length="5.010976314544678" width="2.054335832595825" height="1.5807031393051147" vClass="authority" guiShape="police"/> <vType id="vehicle.jeep.wrangler_rubicon" length="3.8681068420410156" width="1.906570553779602" height="1.8799999952316284" vClass="passenger"/> <vType id="vehicle.chevrolet.impala" length="5.369193077087402" width="2.052736520767212" height="1.4150995016098022" vClass="passenger"/> <vType id="vehicle.mini.cooper_s" length="3.8021926879882812" width="1.9740344285964966" height="1.4750006198883057" vClass="passenger"/> <vType id="vehicle.micro.microlino" length="2.2024967670440674" width="1.4853248596191406" height="1.3464953899383545" vClass="evehicle"/> <vType id="vehicle.audi.etron" length="4.892005443572998" width="2.08632230758667" height="1.6511509418487549" vClass="evehicle"/> <vType id="vehicle.mercedes.coupe" length="5.043785095214844" width="2.1629974842071533" height="1.640134572982788" vClass="passenger"/> <vType id="vehicle.bmw.grandtourer" length="4.639087677001953" width="2.259321928024292" height="1.6781779527664185" vClass="passenger"/> <vType id="vehicle.toyota.prius" length="4.538333415985107" width="2.0011305809020996" height="1.5373616218566895" vClass="evehicle"/> <vType id="vehicle.citroen.c3" length="3.9753477573394775" width="1.862074851989746" height="1.6257729530334473" vClass="passenger"/> <vType id="vehicle.ford.mustang" length="4.904701232910156" width="2.0606582164764404" height="1.478397011756897" vClass="passenger"/> <vType id="vehicle.tesla.model3" length="4.808821678161621" width="2.1695058345794678" height="1.5231821537017822" vClass="evehicle"/> <vType id="vehicle.diamondback.century" length="1.6562436819076538" width="0.42141881585121155" height="1.49351167678833" vClass="bicycle"/> <vType id="vehicle.gazelle.omafiets" length="1.843441367149353" width="0.4674844741821289" height="1.590073823928833" vClass="bicycle"/> <vType id="vehicle.harley-davidson.low_rider" length="2.350175619125366" width="0.7662330269813538" height="1.4637391567230225" vClass="motorcycle"/> <vType id="vehicle.bh.crossbike" length="1.5093227624893188" width="0.8659406304359436" height="1.5306309461593628" vClass="bicycle"/> <vType id="vehicle.tesla.cybertruck" length="6.364232063293457" width="2.3934903144836426" height="2.1439828872680664" vClass="evehicle"/> <vType id="vehicle.volkswagen.t2" length="4.473711013793945" width="1.8112499713897705" height="2.0543651580810547" vClass="passenger" guiShape="passenger/van"/> <vType id="vehicle.kawasaki.ninja" length="2.043684244155884" width="0.7969123125076294" height="1.374603033065796" vClass="motorcycle"/> <vType id="vehicle.lincoln.mkz_2017" length="4.904701232910156" width="2.0606582164764404" height="1.478397011756897" vClass="passenger"/> <vType id="vehicle.seat.leon" length="4.207873821258545" width="1.8198652267456055" height="1.4694602489471436" vClass="passenger"/> <vType id="vehicle.yamaha.yzf" length="2.1907684803009033" width="0.7662330269813538" height="1.6345058679580688" vClass="motorcycle"/> <vType id="vehicle.nissan.patrol" length="4.519999980926514" width="1.9199999570846558" height="1.8871309757232666" vClass="passenger"/> <vType id="vehicle.nissan.micra" length="3.6688475608825684" width="1.8561522960662842" height="1.5232137441635132" vClass="passenger"/> </routes>
配置好sumo车辆类型文件后准备生成sumo车流文件,具体方法主要是运用路网.net文件先生成.trips文件再生成.rou文件
#切换到sumo源码目录下 cd /<your_sumo_folder_root>/tools #将.net文件放入上述目录,先生成.trips文件,每个可选项命令-h查看 python randomTrips.py -n FX.net.xml -b 0 -e 10 –period 0.1 #.trips文件生成.rou文件,每个可选项命令-h查看 duarouter -n FX.net.xml -r FX.trips.xml --ignore-errors --begin 0 --end 50.0 --no-step-log --no-warnings -o FX.rou.xml #生成的.rou文件部分内容如下: <?xml version='1.0' encoding='UTF-8'?> <routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/routes_file.xsd"> <vehicle id="0" type="vehicle.chevrolet.impala" depart="0.00"> <route edges="-46.0.00 -47.0.00 34.0.00 -39.0.00 33.0.00 47.0.00 44.0.00 39.0.00 38.0.00 37.0.00 36.0.00 35.0.00 42.0.00 -23.0.00"/> </vehicle> <vehicle id="1" type="vehicle.micro.microlino" depart="1.00"> <route edges="34.0.00 -39.0.00 33.0.00 47.0.00 44.0.00 39.0.00 31.0.00 -47.0.00 -48.0.00 -7.0.00 -8.0.00 52.0.00 27.0.00 26.0.00"/> </vehicle> <vehicle id="2" type="vehicle.tesla.model3" depart="2.00"> <route edges="45.0.00 40.0.00 39.0.00 31.0.00 -47.0.00 -48.0.00 -7.0.00 -8.0.00 -9.0.00 -10.0.00 -11.0.00 3.0.00 2.0.00"/> </vehicle> <vehicle id="3" type="vehicle.mini.cooper_s" depart="3.00"> <route edges="38.0.00 37.0.00 36.0.00 35.0.00 42.0.00 49.0.00 48.0.00 47.0.00 46.0.00"/> </vehicle> <vehicle id="4" type="vehicle.citroen.c3" depart="4.00"> <route edges="-52.0.00 -9.0.00 17.0.00"/> </vehicle> <vehicle id="5" type="vehicle.ford.mustang" depart="5.00"> <route edges="18.0.00 -10.0.00 -11.0.00 -12.0.00 -13.0.00 -14.0.00 -36.0.00 -37.0.00 -38.0.00 -39.0.00 33.0.00 47.0.00 44.0.00 39.0.00 38.0.00 37.0.00 36.0.00 35.0.00 42.0.00 49.0.00"/> </vehicle> <vehicle id="6" type="vehicle.ford.mustang" depart="6.00"> <route edges="-5.0.00 -37.0.00 -38.0.00 -39.0.00 33.0.00 47.0.00 44.0.00 39.0.00 31.0.00 -47.0.00 -48.0.00 -7.0.00 -8.0.00 52.0.00 27.0.00 -30.0.00"/> </vehicle>
此种通过sumo自带脚本随机生成.rou文件的方法可能不会满足开发者的某些特定需求,例如某场景就需要特定路段特定数量的车流量,那么用脚本随机生成的方法则无法满足(上述两个sumo自带的脚本博主没有看源码,并不了解随机生成车流量的过程与原理,但感觉应该是可以通过脚本来满足特定的车流量需求)。为了满足特定的车流量需求,也可通过一种笨方法就是手动编写.rou文件。通过生成的.rou文件可以看出,只需要对每一个vehicle字段,添加type、depart信息,然后填写route edges字段,可以通过地图上的坐标手动添加路线(此种笨方法只适用于车流量不大的仿真场景,几十量车手动添加的工作量还是可以完成的hhhhh)。
已经生成的地图路网文件FX.net.xml、Sumo车辆类型文件Carlavtypes.rou.xml、交通流文件FX.rou.xml三者组成了Sumo仿真的基本配置文件FX.sumocfg
#在模板基础上只需更改<input>字段的net-files 跟route-files替换成自己的文件即可
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/sumoConfiguration.xsd">
<input>
<net-file value="net/FX.net.xml"/>
<route-files value="carlavtypes.rou.xml,rou/FX.rou.xml"/>
</input>
<gui_only>
<gui-settings-file value="viewsettings.xml"/>
</gui_only>
</configuration>
配置好.sumocfg就可以开始联合仿真啦!
先开启carla
#切换到该目录下
cd /<your_carla_folder_root>/Unreal/CarlaUE4/Binaries/Linux
#运行可执行文件
./CarlaUE4
#进入Carla后切换地图,博主测试采用Town04
cd /<your_carla_folder_root>/PythonAPI/util
python config.py --map Town04
#切换目录
cd /<your_carla_folder_root>/Co-simulation/Sumo
#运行同步器实现联合仿真,其中--tls-manager sumo代表在仿真环境中的交通信号灯管理是通过sumo控制的
#如果想通过carla的pythonAPI控制信号灯是不可行的,只能通过Sumo的Traci接口
#当然也可以改成--tls-manager carla
#具体可执行命令行可以参考-h
python run_synchronization.py examples/Town04.sumocfg --tls-manager sumo --sumo-gui
执行完上述命令后,就会出现sumo-gui界面,点击开始按钮即可
如下图所示:
至此,可以开启你自己的carla-sumo联合仿真。
可编程控制信号灯目前有两种方法,一种是通过sumo的Traci接口控制,一种是通过Carla PythonAPI。
博主两种方法都尝试过,在使用PythonAPI控制红绿灯时发现一个诡异的问题,PythonAPI返回的黄灯和绿灯的时间都正常,红灯持续时间有些错乱。而且上文讲过,在Carla可视化是无法配置信号灯相位及持续时间的,只能通过PythonAPI来编程配置,具体方法是需要通过Opendrive地图拿到某路口的id,再通过carla world类来访问该路口的信号灯
#先通过client访问carla world
world = client.get_world()
#再通过world访问opendrive id路口,例如此时访问1607号路口
traffic_light = world.get_traffic_light_from_opendrive_id('1607')
#设置路口信号灯灯色持续时间 绿25s 红25s 黄3s
traffic_light.set_red_time(30)
traffic_light.set_green_time(30)
traffic_light.set_yellow_time(3)
#访问路口信号灯持续时间
red_time = traffic_light.get_red_time()
yellow_time = traffic_light.get_yellow_time()
rest_time = traffic_light.get_elapsed_time()
green_time = traffic_light.get_green_time()
此种方法貌似不能配置多个相位,相当于十字路口只有两组相位(东西绿、南北红;东西红、南北吕),也有可能是因为Carla自带的Town04地图中此路口的信号灯每个方向上只有一个灯,而非灯组(例如某大型路口各方向上的红绿灯都是左转一组灯,直行一组灯,部分路口有可能右转也有一组灯)。如果建模的时候放置一个大型多组的信号灯是否可行呢?
第二种方式也是最终博主采用的可编程控制方法就是通过Sumo Traci接口来实现,上文已经提过,用sumo的NetEdit可以非常方便的进行可视化配置路口信号灯相位及时间,而Traci接口个人认为也比Carla PythonAPI相对方便一点,最终也实现了动态改变信号灯相位的需求,此处挖个坑慢慢填,下一篇博文准备详细记录一下代码实现。
实现的过程中发现,Carla环境中的信号灯渲染效果貌似与Sumo是对应不上的,例如目前Sumo环境下某路口其实是红灯状态,但Carla环境中的信号灯永远都处于绿色状态,不过车辆还是在遵循交通规则红灯停绿灯行在正常行驶,说明Carla环境中只是渲染的问题,该时刻其实还是处于红灯状态。目前还没找到具体原因。
以上记录了博主使用Carla sumo联合仿真时总结的一些经验,希望可以帮助到有需要的同学!下一篇博文准备记录一下可编程动态控制信号灯相位的代码实现!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。