使用 SUMO 的交叉口速度引导
系列文章目录
文章目录
目录
前言
最近,本人由于项目上和一些实际上的学习需求,本文利用SUMO仿真平台对交叉口速度引导进行了一定的实践。
一、交叉口速度引导公式推算
根据车辆的速度、信号相位等信息,基本可以将车辆经过交叉口的速度引导情景概括为以下几类:
①绿灯匀速通过
②绿灯加速通过
③绿灯减速通过
④绿灯停车
⑤红灯匀速通过
⑥红灯加速通过
⑦红灯减速通过
⑧红灯停车
下面对于上述八种情况对于引导速度的计算过程
①绿灯匀速通过:
车辆能够匀速通过,如果车辆行驶速度较低,不仅不利于交叉口的通行效率提升,也提升了整体燃油消耗。
因此如果车辆速度<经济速度:
如果车辆速度大于经济速度:
②红灯匀速通过:
③加速通过:
④减速通过:
⑤停车通过:
二、仿真场景搭建
1.SUMO仿真场景搭建
由于本文所进行构建的场景为工程场景,需要使用项目地址的路网,所以本文利用OSM真实路网构建仿真场景。为了能够更加便利地构建真实道路网络,这里使用SUMO自带的OSM web wizard工具,自动生成真实路网。
点击generate即可自动生成路网,以及车流文件,但是本文中所使用的算法仅为一阶段算法,不考虑车辆排队和车辆之间的相互作用,因此实际运用过程中,还需要对车流做进一步 调整。构建完成的路网如下:
仿真车流为项目道路,双向车流,车流量为60辆/小时
2.车速引导算法实现
1.功能函数实现:
①信号周期计算:
def cycle_time(tls_id):
tls_logic = traci.trafficlight.getAllProgramLogics(tls_id)#获取下一信号交叉口的控制方案
current_phase = tls_logic[0].currentPhaseIndex#获取信号相位traci.simulation.getCurrentTime()/1000#获取当前仿真时间
cycle_time = 0#周期时长初始化
for i in range(len(tls_logic[0].phases)):
cycle_time += tls_logic[0].phases[i].duration#将控制方案中各相位的控制方案累加获得周期长
return cycle_time
②获取交叉口各相位进口道信息:
def incoming_lane(tls_id):
logic = traci.trafficlight.getAllProgramLogics(tls_id)#获取控制方案
in_lane = traci.trafficlight.getControlledLanes(tls_id)
program = logic[0]
phase = {}#定义空相位
for i in range(len(program.phases)):#遍历信号相位
if i%2 ==0:#因为相位中间存在黄灯信号,所以绿灯信号全为双数
phase[i] = program.phases[i].state#信号为logic格式,.state是其中的具体信号控制方案
incoming_lanes_all = {}#定义进口车道集
for i in phase:#遍历相位
incoming_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])
#print(incoming_lanes)
k = k+1
incoming_lanes_all[i] = incoming_lanes#将每一相位的车道保存
return incoming_lanes_all
③获取下一绿灯相位开始时间和结束时间
def next_green(vehicle_id):
data = traci.vehicle.getNextTLS(vehicle_id)#获取下一信号交叉口信息
tls_id_1 = data[0][0]#获取交叉口id
in_lane = incoming_lane(tls_id_1)#获取各相位进口道
cycle = cycle_time(tls_id_1)#获取周期时长
current_lane = traci.vehicle.getLaneID(vehicle_id)#获取车辆所在车道
signal_state_1 = data[0][3]#获取当前车道信号状态
phases = traci.trafficlight.getAllProgramLogics(tls_id_1)[0].phases#获取信号相位
phases_num = len(phases)#获取相位数
remaining_time = traci.trafficlight.getNextSwitch(tls_id_1) - traci.simulation.getCurrentTime()/1000 #获取当前信号相位剩余时间
if current_lane in in_lane[0]:#如果当前车道为相位0通行相位,则绿灯相位为0
green_phase = 0
#print(green_phase)
elif current_lane in in_lane[2]:#如果当前车道为相位2通行相位,则绿灯相位为2
green_phase = 2
#print(green_phase)
elif current_lane[0:8] == 'cluster':
print(current_lane)
green_phase = 0
else :
print("绿灯相位读取错误")
green_phase = 0
current_phase = traci.trafficlight.getPhase(tls_id_1)
if signal_state_1 == 'g' or signal_state_1 == 'G':#如果当前相位为绿灯
next_g_start = cycle - traci.trafficlight.getPhaseDuration(tls_id_1) + remaining_time#下一绿灯开始时间为周期长-当前相位周期时长+相位剩余时间
next_g_end = cycle + remaining_time#下一绿灯结束时间为周期长加相位剩余时间
elif signal_state_1 == 'r' or signal_state_1 == 'y':
if green_phase == 0 :
if current_phase == 1:#如果为黄灯相位
next_g_start = remaining_time+phases[2].duration+phases[3].duration#下一绿灯开始为剩余时间+下一相位+下一相位
next_g_end = next_g_start + phases[0].duration
elif current_phase == 2:
next_g_start = remaining_time + phases[3].duration
next_g_end = next_g_start + phases[0].duration
elif current_phase == 3:
next_g_start = remaining_time
next_g_end = next_g_start + phases[0].duration
elif current_phase == 0:
next_g_start = remaining_time + phases[1].duration
next_g_end = remaining_time + phases[1].duration + phases[2].duration
if green_phase == 2:#如果绿灯相位为相位2
if current_phase == 3:
next_g_start = remaining_time+phases[0].duration+phases[1].duration
next_g_end = next_g_start + phases[2].duration
elif current_phase == 0:
next_g_start = remaining_time+phases[1].duration
next_g_end = next_g_start + phases[2].duration
elif current_phase == 1:
next_g_start = remaining_time
next_g_end = next_g_start + phases[2].duration
return next_g_start,next_g_end
④建议速度计算:
def advise_speed(vehicle_id,next_g_start,next_g_end):
min_speed = 2.0#最小速度
max_speed = traci.vehicle.getAllowedSpeed(vehicle_id)#道路通行最大速度
acc = traci.vehicle.getAccel(vehicle_id)#加速度
dec = -traci.vehicle.getDecel(vehicle_id)#减速度
distance = traci.vehicle.getNextTLS(vehicle_id)[0][2]#车辆距离交叉口距离
speed_now = traci.vehicle.getSpeed(vehicle_id)#当前车辆速度
phase_now = traci.vehicle.getNextTLS(vehicle_id)[0][3]#下一交叉口相位
if phase_now == 'G' or phase_now == 'g':#如果相位为绿灯
remaining_time = traci.trafficlight.getNextSwitch(traci.vehicle.getNextTLS(vehicle_id)[0][0]) - traci.simulation.getCurrentTime()/1000
if remaining_time > distance/(speed_now+0.01):#绿灯匀速通过
speed_advise = speed_now
traci.vehicle.setColor(vehicle_id,(0,255,0))#设置颜色为绿色
print('speed_now:',speed_now)
print(speed_advise,'绿灯匀速通过')
elif remaining_time > ((distance-(max_speed**2-speed_now**2)/(2*acc))/max_speed + (max_speed-speed_now)/acc) and remaining_time<distance/(speed_now+0.0000000001):
discriminant = acc**2*remaining_time**2+2*acc*speed_now*remaining_time-2*acc*distance #计算方程判别式
accTime = (acc*remaining_time-math.sqrt(discriminant))/acc
speed_advise = speed_now+accTime*acc #绿灯加速通过
traci.vehicle.setColor(vehicle_id,(255,0,255))#设置颜色为粉色
print('speed_now:',speed_now)
print(speed_advise,'绿灯加速通过')
elif remaining_time <= ((distance-(max_speed**2-speed_now**2)/(2*acc))/max_speed + (max_speed-speed_now)/acc) and next_g_start < ((distance-(min_speed**2-speed_now**2)/(2*dec))/min_speed + (min_speed-speed_now)/dec) :
discriminant_1 = dec**2*next_g_start**2+2*dec*speed_now*next_g_start-2*dec*distance
decTime_1 = (dec*next_g_start+math.sqrt(discriminant_1))/dec
speed_advise_1 = speed_now + decTime_1*dec#绿灯减速通行 最大速度
discriminant_2 = dec**2*next_g_end**2+2*dec*speed_now*next_g_end-2*dec*distance
decTime_2 = (dec*next_g_end+math.sqrt(discriminant_2))/dec
speed_advise_2 = speed_now + decTime_2*dec#绿灯减速通行 最小速度
speed_advise = (speed_advise_1+speed_advise_2)/2# 确保车辆能够通过
traci.vehicle.setColor(vehicle_id,(0,255,255))#设置颜色为蓝色
print(traci.simulation.getCurrentTime()/1000)
print('speed_now:',speed_now)
print(speed_advise_1,speed_advise_2,'绿灯减速通行')
elif remaining_time <= ((distance-(max_speed**2-speed_now**2)/(2*acc))/max_speed + (max_speed-speed_now)/acc) and next_g_start >= ((distance-(min_speed**2-speed_now**2)/(2*dec))/min_speed + (min_speed-speed_now)/dec) :
discriminant = dec**2*next_g_start**2+2*dec*speed_now*next_g_start-2*dec*distance
decTime = (dec*next_g_start+math.sqrt(discriminant))/dec
speed_advise = speed_now + decTime*dec#绿灯减速停车
if speed_advise<min_speed:
speed_advise = min_speed
traci.vehicle.setColor(vehicle_id,(255,0,0))#设置为红色
print('speed_now:',speed_now)
print(speed_advise,'绿灯减速停车')
if phase_now == 'r' or phase_now == 'y':
if next_g_start< distance/(speed_now+0.01) and next_g_end> distance/(speed_now+0.01):
if distance/(speed_now+0.01)-next_g_start < 2:
speed_advise = distance/(next_g_start+3)
print('略微减速')
else:
speed_advise = speed_now #红灯匀速通行
traci.vehicle.setColor(vehicle_id,(255,255,255))#设置颜色为白色
print('speed_now:',speed_now)
print(speed_advise,'红灯匀速通过')
elif next_g_start < distance / (speed_now+0.0000001) and next_g_start > ((distance-(max_speed**2-speed_now**2)/(2*acc))/max_speed + (max_speed-speed_now)/acc):
discriminant = dec**2*next_g_start**2+2*dec*speed_now*next_g_start-2*dec*distance #计算方程判别式
decTime = (dec*next_g_start+math.sqrt(discriminant))/dec
speed_advise = speed_now + decTime*dec#红灯减速通行
traci.vehicle.setColor(vehicle_id,(0,0,255))#设置颜色为蓝色
print('speed_now:',speed_now)
print(speed_advise,'红灯减速通过')
elif next_g_end>((distance-(max_speed**2-speed_now**2)/(2*acc))/max_speed + (max_speed-speed_now)/acc) and next_g_end<distance/(speed_now+0.00000001):
discriminant = acc**2*next_g_end**2+2*acc*speed_now*next_g_end-2*acc*distance #计算方程判别式
accTime = (acc*next_g_end-math.sqrt(discriminant))/acc
speed_advise = speed_now+accTime*acc #红灯加速通过
traci.vehicle.setColor(vehicle_id,(255,0,255))#设置颜色为粉色
print('speed_now:',speed_now)
print(speed_advise,'红灯加速通过')
print(traci.simulation.getCurrentTime()/1000)
else :
print('红灯减速停车')
speed_advise = min_speed
traci.vehicle.setColor(vehicle_id,(255,0,0))#设置为红色
return speed_advise
2.速度引导控制主程序实现:
while traci.simulation.getMinExpectedNumber() > 0:
traci.simulationStep()
for vehicle_id in traci.vehicle.getIDList():
traci.vehicle.setMaxSpeed(vehicle_id,16.67)
allowed_speed = traci.vehicle.getAllowedSpeed(vehicle_id)#获取路网允许速度
if traci.vehicle.getNextTLS(vehicle_id) != ():#确保车辆下一交叉口信息不为空
if traci.vehicle.getNextTLS(vehicle_id)[0][2] < 210: #车辆进入交叉口停止线210m范围内
next_g_start , next_g_end = next_green(vehicle_id)#获取下一绿灯开始时间、结束时间
distance = traci.vehicle.getNextTLS(vehicle_id)[0][2]#获取距离交叉口停止线的距离
speed_adv = advise_speed(vehicle_id,next_g_start,next_g_end)#获取引导速度
traci.vehicle.setSpeed(vehicle_id,speed_adv)#对车辆速度进行控制
elif traci.vehicle.getNextTLS(vehicle_id)[0][2] > 220:#车辆距离交叉口大于220m时,控制车辆按照正常速度行驶
traci.vehicle.setColor(vehicle_id,(255,255,0))
traci.vehicle.setSpeed(vehicle_id,allowed_speed)
elif traci.vehicle.getNextTLS(vehicle_id) == ():#如果车辆即将离开路网,控制车辆按允许速度行驶
print(vehicle_id,'结束')
traci.vehicle.setColor(vehicle_id,(255,255,0))
traci.vehicle.setSpeed(vehicle_id,allowed_speed)#对车辆速度进行控制
三、程序结果分析
仿真结果:
优化前后行程时间,技术参数表 |
|||||
|
arrivalSpeed |
行程时间 |
等待时间 |
启停次数 |
timeLoss |
优化后 |
13.92 |
469.93 |
0.00 |
0.00 |
129.93 |
优化前 |
13.64 |
425.48 |
49.59 |
3.31 |
85.58 |
优化前后步均燃油消耗量及污染物 |
||||||
|
CO2 |
CO |
HC |
Nox |
PMx |
fuel |
优化后 |
13963.28786 |
21.5826697 |
0 |
124.2140218 |
2.719787913 |
5.919309 |
优化前 |
14829.80422 |
22.3261729 |
0 |
129.304049 |
2.773325695 |
6.28883 |
仿真图像:
车辆运动轨迹图:
正向车流
优化前:
优化后:
逆向车流:
优化前:
优化后:
速度-距离图:
优化前:
优化后:
结论分析
本文所提出的车辆速度引导算法可以在不考虑排队车辆和车辆间相互影响的情况下,显著减少车辆的启停次数和排队等待时间,但是由于SUMO仿真默认按照较高的速度行驶,速度引导算法为了使车辆能够顺利通过,部分场景使用了较低的引导速度,所以行程时间和timeloss并没有显著下降。
下一阶段算法的设计将考虑排队长度、车辆间的相互影响,队列的信号优化等方面,可以使得算法的使用场景更加广阔,实用性更强。如果有朋友对这一方面感兴趣,欢迎交流讨论。