本人小白,blog仅供记录本人的以下学习过程和结果,仅供大家参考学习。欢迎交流指正。
traci是微观交通流仿真软件的交通控制接口,全称为”Traffic Control Interface“。SUMO 本身可以实现很多实际交通场景的模拟。当 SUMO 被用作智能交通控制算法的测试平台时,需要其与外界程序/算法实现很好的互动,例如用户自定义的控制算法可以从 SUMO 获取实时交通信息,然后对其中车辆状态、信号灯状态等进行实时控制。TraCI 就是实现这类互动的接口。
作用:获取 SUMO 交通模拟环境中的数据,并实时修改、控制。
建立路网、车流等基础操作较为常见,不做过多介绍,这里简单介绍一下我所使用的检测器的布设方法。
SUMO安装包中自带了检测器的自动布设工具,可以一键生成道路检测器,如下图所示,分别是自动生成E1,E2,E3类型检测器的方法。
上述自动布设工具的使用需要将路网文件和.py工具至于同一目录下或添加较为完整的文件路径,具体的调用命令为:
python generateTLSE2Detectors.py -n sumo.net.xml -o E2.add.xml
这样就会生成一个E2.add.xml的检测器文件,在sumocfg中需要在
完整的路网如下图所示:
代码如下(示例):
import os
import sys
import optparse
import random
from sumolib import checkBinary # noqa
import traci # noqa
import pandas as pd
if 'SUMO_HOME' in os.environ:
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
sys.path.append(tools)
else:
sys.exit("please declare environment variable 'SUMO_HOME'")
sumocfg_file = "demo.sumocfg"#这里输入仿真的cfg文件
if__show__gui =True
if not if__show__gui :
sumoBinary = checkBinary('sumo')
else :
sumoBinary = checkBinary('sumo-gui')
traci.start([sumoBinary, "-c", sumocfg_file])#这里通过traci接口启动仿真程序
在进行信号控制方面的研究时,可能需要获取每个相位放行的车道的转向信息,并根据车道转向进行车道属性计算。由于traci自带的接口获取的信息包含一定的其他无效信息(如下图所示),这里对信息提出一种过滤方案,如下所示
代码如下(示例):
def get_dir(lane_list):#传入需要判断的车道信息
dir = {}
for lane in lane_list:
if len(traci.lane.getLinks(lane)) == 2:#因为例子中只有直右一种双向车道,所以这样定义
dir[lane] = 'sr'
elif len(traci.lane.getLinks(lane)) == 1:#如果为单转向车道
if traci.lane.getLinks(lane)[0][7] !=0:#并且最后一项不为0,如果为0则为junction内车道
dir[lane] = traci.lane.getLinks(lane)[0][6]#该项为车道的转向信息
dir_d = pd.DataFrame.from_dict(dir,orient='index')#将dir转换为dataframe格式
dir_d.rename(columns={0:"dir"},inplace = True)
return dir_d
E2检测器对应着显示中类似于交叉口的摄像头的同能,能够获得检测信号范围内的车辆排队长度、道路占用率等信息。由于在实际运用过程中,使用接口获得单条数据不利于信息的处理,本文提出一种信息获取方法。
def get_info(decid):#传入检测器id信息
quene_lenth={}#定义排队长度
occ = {}#定义占有率
lane_length = {}#定义车道长度
for dets in decid:#遍历检测器
lane_id = traci.lanearea.getLaneID(dets)#通过检测器获取车道id
lane_length[lane_id] = traci.lane.getLength(lane_id)#获取车道长度并记录
quene_lenth[lane_id] = traci.lanearea.getJamLengthMeters(dets)#获取排队长度并记录
occ[lane_id] = traci.lanearea.getLastStepOccupancy(dets)#获取占有率并记录
quene_lenth_d = pd.DataFrame.from_dict(quene_lenth,orient='index')#将排队长度转换为dataframe
quene_lenth_d.rename(columns={0:"quene_lenth"},inplace = True)#更改数据标签
occ_d = pd.DataFrame.from_dict(occ,orient='index')
occ_d.rename(columns={0:"occ"},inplace = True)
lane_length_d = pd.DataFrame.from_dict(lane_length,orient='index')
lane_length_d.rename(columns={0:"length"},inplace = True)
data = pd.concat([quene_lenth_d,occ_d,lane_length_d],axis=1)#融合获取的数据信息
return data
获取到的交叉口信息如下所示
通过pandas操作可以将上述获得的信息融合:
由于traci.trafficlight.getphase无法直接获取每个相位的放行信息,这里通过遍历信号灯的控制方案,获得每一相位的控制方案,选择‘G’的车道,并记录,构成放行车道信息,具体如下所示:
通过Traci接口获取到的信号方案如下所示:
logic = traci.trafficlight.getAllProgramLogics("gneJ0")#获取控制方案
program = logic[1]
phase = {}#定义空相位
for i in range(len(program)):#遍历信号相位
if i%2 ==0:#因为相位中间存在黄灯信号,所以绿灯信号全为双数
phase[i] = program[i].state#信号为logic格式,.state是其中的具体信号控制方案
incoming_lanes_all = {}#定义进口车道集
outcoming_lanes_all = {}#定义出口车道集
for i in phase:#遍历相位
incoming_lanes = []#定义进口空车道
outcoming_lanes = []#定义空出口车道
k = 0#控制相位数
print(phase[i])
for j in phase[i]:
print(k)
if j =='G':#将’G‘对应的车道记录下来
print(k)
incoming_lanes.append(in_lane[k])
outcoming_lanes.append(out_lane[k])
print(incoming_lanes)
k = k+1
incoming_lanes_all[i] = incoming_lanes#将每一相位的车道保存
outcoming_lanes_all[i] = outcoming_lanes
通过上述代码获取的进口车道信息和出口车道信息如下所示:
与信号控制接口获取的信息一致
本文主要介绍了本人在学习过程中一些利用traci接口获取交通流信息和交叉口信息的一些方式方法,仅供大家参考,如果有什么疑问或意见,欢迎评论区或私信交流讨论。