github地址:
https://github.com/JunXie-ZH/SUMO_Tutorial/tree/main/Parking
在SUMO中实现停车场仿真需要掌握三个部分的工作(如图1),分别为:
本章节将围绕这三部分工作对SUMO停车仿真进行详细介绍。
在SUMO中,停车设施由元素*
一个元素*
<parkingArea id="parkingArea_B2C2_0_0" lane="B2C2_0" startPos="20.00" endPos="80.00" roadsideCapacity="5" width="3.50">
<space x="123.00" y="180.00"/>
<space x="128.00" y="180.00"/>
<space x="133.00" y="180.00"/>
<space x="138.00" y="180.00"/>
<space x="143.00" y="180.00"/>
<space x="152.00" y="184.00" angle="120.00"/>
<space x="160.00" y="184.00" angle="120.00"/>
<space x="168.00" y="184.00" angle="120.00"/>
<space x="176.00" y="184.00" angle="120.00"/>
<space x="184.00" y="184.00" angle="120.00"/>
parkingArea>
元素*
属性 | 值类型 | 定义 |
---|---|---|
id | 字符串 | 停车区域ID,由用户自定义,且必须为唯一的 |
lane | 字符串 | 停车区域所在的车道,在SUMO中停车区域通常与车道是绑定在一起的 |
startPos | 浮点数 | 停车区域的起始位置,以车道起始点为标准,数值表示为距离车道起始点x米 |
endPos | 浮点数 | 停车区域的终止位置,以车道起始点为标准,数值表示为距离车道起始点x米,endPos>startPos |
friendlyPos | 布尔型变量 | 是否自动纠正无效的停车位置(默认为false) |
name | 字符串 | 对停车场的描述,可以用任意文字,仅用于可视化目的。 |
roadsideCapacity | 整型 | 该停车区域的路内停车位容量,默认值为0 |
onRoad | 布尔型变量 | 车辆停车时是否停留在路中,默认值为false,若设置为true,则只使用roadsideccapacity,不允许定义space给车辆停车 |
width | 浮点数 | 路内停车位的宽度 |
length | 浮点数 | 路内停车位的长度 |
angle | 浮点数 | 路边停车位的角度相对于车道角度,正值表示顺时针 |
从元素*
对于③,在示例中,roadsideCapacity=5,*
停车设施的构建可以通过netedit编辑器实现,用户可以在已有道路路网的基础上,根据使用需求在合适的区域构建停车设施。
Step 1 用netedit编辑器打开路网文件(.net.xml),在Network模式下,点击上方工具栏[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5vxOmxzn-1643112936687)(./pic/addtionalMode.png)] 打开Additional mode(或点击上方菜单栏 Edit–>Additional mode打开)。在界面左侧Additionals中,点击Additional elements的下拉菜单选择parkingArea;
Step 2 完成上一步后,即可点击某个车道构建停车区域。在SUMO中,停车区域与车道是绑定的,表示为车辆需通过该车道进入该停车区域。一个车道上可以构建多个停车区域(图4.a),也可以只构建一个停车区域(图4.b),并可以在左侧的属性栏中的修改该停车区域的属性:如id,roadsideCapacity等,详细可见表1。
<additional xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/additional_file.xsd">
<parkingArea id="parkingArea_B2C2_0_0" lane="B2C2_0" startPos="20.00" endPos="80.00" roadsideCapacity="5" width="3.50" angle="45.00">
<space x="123.00" y="180.00"/>
<space x="128.00" y="180.00"/>
<space x="133.00" y="180.00"/>
<space x="138.00" y="180.00"/>
<space x="143.00" y="180.00"/>
<space x="192.00" y="184.00" angle="120.00"/>
<space x="160.00" y="184.00" angle="120.00"/>
<space x="168.00" y="184.00" angle="120.00"/>
<space x="176.00" y="184.00" angle="120.00"/>
<space x="184.00" y="184.00" angle="120.00"/>
parkingArea>
additional>
停车是出行的其中一个环节,在前面的章节中,我们介绍了如何加载车辆的出行需求,停车需求的加载则是在出行需求的基础上进行实现的。停车需求的实战加载方式如图1所示主要有三种:直接在*.rou.xml文件中编写,通过netedit编辑器加载,通过TraCI*进行动态加载。
首先可以直接在*.rou.xml文件中编写实现停车需求的加载。停车需求在.rou.xml*文件中的编写是在出行的基础上完成的,我们以一个出行(trip)为例:
<trip id="vehicle_0" depart="0" from="a" to="e">
<stop parkingArea="parkingArea_e" duration="100.00"/>
trip>
我们在一个OD级的个体出行需求的基础上,添加了一个*
Error: parkingArea 'parkingArea_x' for vehicle 'type2.0' on lane 'c_0' is not downstream the current route.
因此,在OD级的车辆出行需求中,停车区域最好选择在终点路段,或者采用路径级车辆出行需求,为车辆指定出行路径,并在路径中间路段的停车场进行停车:
<route edges="a b c d e f g" color="yellow" id="route_0">
<stop parkingArea="parkingArea_d" duration="100.00"/>
route>
<vehicle id="v0" route="route_0" depart="0">vehicle>
以上均是个体级的停车需求在*.rou.xml*文件中的表示,对于集计型的交通需求(OD级与路径级)同样可以加载停车需求。
OD级:
<flow id="flow_0" begin="0" end= "7200" period="10" from="a" to="e">
<stop parkingArea="parkingArea_e" duration="100.00"/>
flow>
路径级:
<route edges="a b c d e f g" color="yellow" id="route_0">
<stop parkingArea="parkingArea_d" duration="100.00"/>
route>
<flow id="flow_0" begin="0" end= "7200" period="10" route="route_0">flow>
netedit编辑器提供了可视化界面来进行停车需求的加载,但本质上还是为了生成一个*.rou.xml*文件来加载停车需求。
Step 1 如上所述,停车需求是在出行需求的基础上完成的,因此,首先在编辑器中加载好对应的出行需求,各粒度出行需求的编辑方式在前面已经介绍。假设已经创建了一个个体OD级出行需求,如下图:
Step 3 将停车需求的各项属性设置好后,点击车辆在出行过程中需要停留的停车区域(需要在出行路径上),即可给该需求添加上停车行为;
Step 4 点击保存后,打开保存好的*.rou.xml*文件,可以看到,相应的停车需求生成成功。
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/routes_file.xsd">
<trip id="vehicle_0" depart="0" from="a" to="e">
<stop parkingArea="parkingArea_e" duration="100.00"/>
trip>
routes>
在实际的一些应用中,通过直接在*.rou.xml文件中编写和通过netedit编辑器来加载停车需求并不方便,这时候可以通过TraCI来动态加载出行需求和停车需求。TraCI动态加载需求的方式更加灵活,可以在每一个仿真步长中判断是否添加出行需求,且借助Python*的部分工具可以实现对车辆运动的精准监控。
我们以一个简单的例子来介绍如何通过TraCI动态加载停车需求。仿真时间一小时,每半分钟加载一个车辆出行需求,OD均为a–>e,并均在parkingArea_e停放100秒。应用的TraCI相关命令有traci.route.add、traci.vehicle.add以及traci.vehicle.setParkingAreaStop。
for step in range(3600): # 仿真一小时(3600s)
if step % 30==0: # 每半分钟添加一个出行需求,并指定其停车位置
# 定义相关变量
tripid="trip"+str(step) # 出行ID
origin="a" # 出发路段
destination="e" # 终点路段
vehid="v"+str(step) # 车辆ID
parkingArea='parkingArea_e' # 停车区域
# 添加出行需求 & 停车需求
traci.route.add(tripid, [origin,destination])
traci.vehicle.add(vehid, tripid, typeID="type1")
traci.vehicle.setParkingAreaStop(vehid, parkingArea,duration=100)
在停车场的实践过程中,经常会遇到这种情况:当车辆行驶到系统为其分配的停车区域时,发现已经无空闲的停车位。此时车辆是无法在该区域进行停车的,在这种情况下,车辆可以在道路上等待,直到该停车区域出现了可用的停车位。但是在现实场景中,司机会根据自己的需求与实际情况重新选择一个新的停车区域,因此,SUMO中也提供了让车辆重新选择一个停车区的功能。
针对停车区重选择行为,在SUMO中可以通过定义*
<rerouter id="Rerouter_1" edges="a b c">
<interval begin="0" end="3600">
<parkingAreaReroute id="parkingArea_a"/>
<parkingAreaReroute id="parkingArea_b"/>
<parkingAreaReroute id="parkingArea_c"/>
interval>
rerouter>
*
属性 | 值类型 | 定义 |
---|---|---|
id | 字符串 | 所定义的 rerouter的ID,用户自定义 |
edges | 浮点型 | 一个路段id或一个路段id列表,车辆在这些路段上可以触发rerouter |
probability | 浮点型 | 车辆触发rerouter的概率,默认为1 |
timeThreshold | 时间(秒) | rerouter触发时需与上一次触发时的间隔时间(默认为0) |
vTypes | 字符串列表 | 该rerouter适用的车辆类型,默认为适用所有车辆类型 |
off | 布尔型变量 | rerouter初始是否为不活动的,默认值:false |
*
属性 | 值类型 | 定义 |
---|---|---|
id | 字符串 | 已经定义好的停车区域ID |
probability | 浮点型 | 每个可选方案(即备用停车区域被选中概率)被选中的概率(默认为1)。在重路由中,所有定义的概率都自动归一化。 |
visible | 布尔型 | 在车辆到达停车区域所在路段之前,是否知道该停车区的占用情况 |
通常而言,在以下两种情况时会触发停车的rerouter:
由于备选停车区域可能有多个,如上例,加入车辆初始的目标停车区域为parkingArea_a,若该停车区域已满,那么车辆则会根据一些因素的权重设置,选择parkingArea_b与parkingArea_c其中一个进行停车。相关的因素如下表:
属性 | 默认值 | 定义 | 值是否越大越好 |
---|---|---|---|
parking.probability.weight | 0 | parkingAreaReroute元素中所定义的probability | yes |
parking.capacity.weight | 0 | 备选停车区域的总容量 | yes |
parking.absfreespace.weight | 0 | 备选停车区域的绝对空闲车位数 | yes |
parking.relfreespace.weight | 0 | 备选停车区域的相对空闲车位数 | yes |
parking.distanceto.weight | 1 | 车辆到达备选停车区域的距离 | no |
parking.timeto.weight | 0 | 车辆到达备选停车区域所要花费的时间(假设值) | no |
parking.distancefrom.weight | 0 | 备选停车区域到车辆目的地的距离 | no |
parking.timefrom.weight | 0 | 备选停车区域到车辆目的地的行驶时间(假设值) | no |
SUMO会根据每个备选停车位的上述因子相对应的属性值,最终得出一个评估值 P i P_i Pi。根据评估值的大小来决定选择哪一个备选停车位。 f j f_j fj为第j个因子的值, α j \alpha_j αj为第j个因子的权重。
P i = ∑ j = 0 n α j f j P_i=\sum_{j=0}^{n}\alpha_j f_j Pi=j=0∑nαjfj
若用户未对这部分因子进行设置,则默认parking.distanceto.weight因子的权重为1,其余因子的权重均为0,即可只有parking.distanceto.weight生效。另外需要注意得是,当*
用户定义这些因子的权重,可以在*
<vehicle id="v0" route="route0" depart="0">
<param key="parking.capacity.weight" value="0.5"/>
<param key="parking.timeto.weight" value="0.1"/>
......
vehicle>
<vType id="veh_1" width="1.5" length="3.50" maneuverAngleTimes="10 3.0 4.0,80 1.6 11.0,110 11.0 2.0,170 8.1 3.0,181 3.0 4.0">
<param key="parking.distanceto.weight" value="0"/>
<param key="parking.distancefrom.weight" value="0.2"/>
<param key="parking.absfreespace.weight" value="0.8"/>
......
vType>
随着城市汽车保有量的不断增长,停车问题愈发突出,体现在:城市停车位短缺巨大,我国车位配比远低于全球平均水平;停车资源缺乏统一管理,城市停车位空置率高。为了缓解停车难问题,降低车辆寻找停车位的难度,提高整体的停车效率,相关的学者们提出了各种停车管理模型来优化停车管理,这些管理模型的验证则是需要仿真来进行。
在本章节的实例中,我们来实现一个简单的智能停车场管理系统。如下图,该系统主要包含两个模块:停车场状态感知模块与车位选择模块。感知模块我们将实现两种程度的感知系统:半感知与全感知,车位选择模块我们将对贪婪策略与随机选择策略进行实现。另外,该场景的实现将主要基于TraCI进行。
我们首先构建如图11所示的停车场路网,出入口分别有两个。
构建该路网的小技巧:可以利用netgenerate.exe工具,先构建一个方格路网,再通过删减部分路段从而构建如图11所示的停车场路网。相关命令示例:
netgenerate --grid --grid.number=6 --grid.length=50 --output-file=park.net.xml
在该路网的基础上,在部分路段中构建停车区域,如图11所示:
本场景中,分别实现了两种程度的停车场状态感知模块:半感知与全感知。
在半感知的条件下,车辆仍然可能出现抢占车位资源的现象,导致不必要的巡航时间。而在全感知的条件下,则能够真正实现高效停车。
我们定义了一个类Half_perception来实现半感知模块。此次仿真场景中我们暂时只需要感知各个停车区域的占有率,因此该类下只定义了两个函数。在有更加多元化的感知需求时,同样可以直接在该类下添加函数实现。
class Half_perception:
# 感知停车场桩体,以“停车区域--占有率”表示
def Perceived_occupancy(self):
# 获取所有停车区域的ID
ParkingAreaList=traci.parkingarea.getIDList()
# 遍历所有停车区域,获取每一个区域的占有率
Occ=list(map(lambda x: float(traci.simulation.getParameter(x,
"parkingArea.occupancy")), ParkingAreaList))
# 构建一个datafrmame来存储“停车区域--占有率”
ParkingOcc=pd.DataFrame({"ParkingArea":ParkingAreaList,"Occupancy":Occ})
return ParkingOcc
# 获取可用停车区域
def get_AvailableParking(self):
# 获取“停车区域--占有率”关系表
ParkingOcc=self.Perceived_occupancy()
# 获取占有率小于1的停车区域列表
AvailableParking=list(ParkingOcc[ParkingOcc["Occupancy"]< 1]["ParkingArea"])
return AvailableParking
我们定义了另一个类Com_perception来实现全感知模块。
class Com_perception:
def __init__(self):
# 获取所有停车区域的ID
ParkingAreaList=traci.parkingarea.getIDList()
# 遍历所有停车区域,获取每一个区域的总容量
Capacity=list(map(lambda x: float(traci.simulation.getParameter(x, "parkingArea.capacity")),ParkingAreaList))
# 构建一个datafrmame来存储“停车区域--容量”
self.ParkingCapacity=pd.DataFrame
({"ParkingArea":ParkingAreaList,"Capacity":Capacity})
# 函数Add_update用于当车辆决定选择某个停车区域后,更新停车区域的剩余容量,即使该车辆还未行驶到停车区
def Add_update(self,parkingArea):
# 车辆进入停车场后,选择停在parkingArea(可用),则parkingArea的容量减1
self.ParkingCapacity.loc[(self.ParkingCapacity.ParkingArea == parkingArea),
'Capacity'] -= 1
# 函数Leave_update用于当车辆离开停车位时,更新停车区域的剩余容量
# parkInformation为存储的“车辆--停车区域”关系表,即每个车辆停在了哪个停车区
def Leave_update(self,VehiclePark):
# traci.simulation.getStopEndingVehiclesIDList()获取准备离开停车位的车辆列表
for veh in list(traci.simulation.getStopEndingVehiclesIDList()):
# 获取这些车辆所停的停车区域
parkingArea=VehiclePark[VehiclePark.Veh==veh]["park"].values[0]
# 更新该区域容量
self.ParkingCapacity.loc[(self.ParkingCapacity.ParkingArea == parkingArea),
'Capacity'] += 1
# 获取“停车区域--剩余容量”
def get_ParkingCapacity(self):
return self.ParkingCapacity
# 获取可用停车区域
def get_AvailableParking(self):
# 获取“停车区域--剩余容量”关系表
ParkingCapacity=self.get_ParkingCapacity()
# 获取剩余容量大于0的停车区域列表
AvailableParking=list(ParkingCapacity[ParkingCapacity["Capacity"]>0]
["ParkingArea"])
return AvailableParking
在智能停车管理系统中,车位选择策略很大程度上影响着整个停车场的运行效率。我们在这次场景中主要介绍了两种车位选择策略:随机策略与贪婪策略。以下策略的实现我们都将基于全感知条件进行。
在随机策略下,车辆在进入停车场后,系统在半感知或全感知的基础上,随机分配一个有空闲停车位的停车区域给车辆,车辆随即行驶到目标停车区域进行停车。策略的流程如下图所示:
我们定义了一个类Allocation来作为策略实现的模块。其中定义了Random_allocation函数来实现随机策略:
class Allocation:
def __init__(self):
# 实例化感知模块
# self.Perception=Half_perception() # 半感知
self.Perception = Com_perception() # 全感知
# 随机策略
def Random_allocation(self):
# 获取可用的停车区域列表
AvailableParking=self.Perception.get_AvailableParking()
# 利用random.choice从AvailableParking中随机选取一个可用的停车区域
TargetParking=random.choice(AvailableParking)
return TargetParking
在贪婪策略中,车辆进入停车场时,会选择一个距离其入口最近的停车区域进行停车。策略的流程如下:
为了更加高效地完成贪婪策略,我们可以定义一个Environment类初始化停车区域信息,获取每个停车区域距离各个入口的距离:
class Environment:
def __init__(self):
# 获取所有停车区域的ID
ParkingAreaList = traci.parkingarea.getIDList()
# 用于储存每个停车区域和两个入口间的距离
EntryDistance_1 = []
EntryDistance_2 = []
# 遍历所有停车区域
for parkingSpace in ParkingAreaList:
# 获取停车区域的车道和路段
lane=traci.parkingarea.getLaneID(parkingSpace)
edge=traci.lane.getEdgeID(lane)
# 计算入口路段和停车区域路段的距离
distance_1 = traci.simulation.getDistanceRoad("F5E5", 0 , edge , 0)
distance_2 = traci.simulation.getDistanceRoad("A2B2", 0, edge , 0)
# 存储
EntryDistance_1.append(distance_1)
EntryDistance_2.append(distance_2)
# 构建一个datafrmame来存储“停车区域--距离1--距离2”
self.ParkingInformation = pd.DataFrame({"ParkingArea":ParkingAreaList,
"EntryDistance_1":EntryDistance_1,
"EntryDistance_2":EntryDistance_2})
# 获取“停车区域--距离1--距离2”
def get_ParkingInformation(self):
return self.ParkingInformation
在有了Environment类后,感知模块的初始化函数也需要变动,以全感知为例:我们会将Environment类中的ParkingInformation输入到感知模块,在此基础上将各个区域的容量信息加入。
class Com_perception:
def __init__(self,ParkingInformation):
self.ParkingCapacity = ParkingInformation
# 遍历所有停车区域,获取每一个区域的总容量
Capacity = list(map(lambda x: float(traci.simulation.getParameter(x,
"parkingArea.capacity")),
list(ParkingInformation["ParkingArea"])))
# 将容量信息加入
self.ParkingCapacity["Capacity"]=Capacity
在此基础上,我们要实现贪婪策略将变得较为容易,在Allocation类下加入实现贪婪策略的函数Greedy_allocation。函数需输入车辆进入停车场的入口:
class Allocation:
def __init__(self,parkingInformation):
# 实例化感知模块
# self.Perception = Half_perception(ParkingInformation) # 半感知
self.Perception = Com_perception(ParkingInformation) # 全感知
# 贪婪策略
def Greedy_allocation(self,Entry):
# 感知各个区域的剩余容量
AvailableParking = self.Perception.get_ParkingCapacity()
# 将可用的停车区域筛选出来
AvailableParking=AvailableParking[AvailableParking["Capacity"] > 0]
# 重设索引
AvailableParking=AvailableParking.reset_index(drop=True)
# 根据距离进行从小到大排序
AvailableParking=AvailableParking.sort_values(by=Entry, ascending=True)
AvailableParking = AvailableParking.reset_index(drop=True)
# 将第一个停车区域分配给车辆
TargetParking = AvailableParking["ParkingArea"][0]
return TargetParking
由此我们即可实现贪婪策略。
下面我们将整个场景的所有代码展示出来:我们在全感知条件下实现场景,每个入口的车流量为2 veh/min,停车时间为[200s,300s]中的随机数,仿真时长为一小时,车位选择策略为贪婪策略:
# 相关包导入
import random
import os
import sys
import optparse
import traci
from sumolib import checkBinary
import pandas as pd
# SUMO环境变量配置,需根据用户的实际配置进行调整
if 'SUMO_HOME' in os.environ:
os.environ['SUMO_HOME']='E:\\sumo-1.8.0\\'
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
sys.path.append(tools)
else:
sys.exit("please declare environment variable 'SUMO_HOME'")
def get_options():
optParser = optparse.OptionParser()
optParser.add_option("--nogui", action="store_true",
default=False, help="run the commandline version of sumo")
options, args = optParser.parse_args()
return options
# 全感知模块
class Com_perception:
def __init__(self,ParkingInformation):
# 获取所有停车区域的ID
ParkingAreaList=traci.parkingarea.getIDList()
# 遍历所有停车区域,获取每一个区域的总容量
Capacity=list(map(lambda x: float(traci.simulation.getParameter(x, "parkingArea.capacity")),ParkingAreaList))
# 构建一个datafrmame来存储“停车区域--容量”
self.ParkingCapacity=pd.DataFrame
({"ParkingArea":ParkingAreaList,"Capacity":Capacity})
# 函数Add_update用于当车辆决定选择某个停车区域后,更新停车区域的剩余容量,即使该车辆还未行驶到停车区
def Add_update(self, parkingArea):
# 车辆进入停车场后,选择停在parkingArea(可用),则parkingArea的容量减1
self.ParkingCapacity.loc[(self.ParkingCapacity.ParkingArea == parkingArea),
'Capacity'] -= 1
# 函数Leave_update用于当车辆离开停车位时,更新停车区域的剩余容量
# parkInformation为存储的“车辆--停车区域”关系表,即每个车辆停在了哪个停车区
def Leave_update(self, VehiclePark):
for veh in list(traci.simulation.getStopEndingVehiclesIDList()):
# 获取这些车辆所停的停车区域
parkingArea = VehiclePark[VehiclePark.Veh == veh]["park"].values[0]
# 更新该区域容量
self.ParkingCapacity.loc[(self.ParkingCapacity.ParkingArea == parkingArea),
'Capacity'] += 1
# 获取“停车区域--剩余容量”
def get_ParkingCapacity(self):
return self.ParkingCapacity
# 获取可用停车区域
def get_AvailableParking(self):
# 获取“停车区域--剩余容量”关系表
ParkingCapacity = self.get_ParkingCapacity()
# 获取剩余容量大于0的停车区域列表
AvailableParking = list(ParkingCapacity[ParkingCapacity["Capacity"] > 0]
["ParkingArea"])
return AvailableParking
class Allocation:
def __init__(self,parkingInformation):
# 实例化感知模块
self.Perception = Com_perception(parkingInformation) # 全感知
# 贪婪策略
def Greedy_allocation(self,Entry):
# 感知各个区域的剩余容量
AvailableParking = self.Perception.get_ParkingCapacity()
# 将可用的停车区域筛选出来
AvailableParking=AvailableParking[AvailableParking["Capacity"] > 0]
# 重设索引
AvailableParking=AvailableParking.reset_index(drop=True)
# 根据距离进行从小到大排序
AvailableParking=AvailableParking.sort_values(by=Entry, ascending=True)
AvailableParking = AvailableParking.reset_index(drop=True)
# 将第一个停车区域分配给车辆
TargetParking = AvailableParking["ParkingArea"][0]
return TargetParking
class Environment:
def __init__(self):
# 获取所有停车区域的ID
ParkingAreaList = traci.parkingarea.getIDList()
# 用于储存每个停车区域和两个入口间的距离
EntryDistance_1 = []
EntryDistance_2 = []
# 遍历所有停车区域
for parkingSpace in ParkingAreaList:
# 获取停车区域的车道和路段
lane=traci.parkingarea.getLaneID(parkingSpace)
edge=traci.lane.getEdgeID(lane)
# 计算入口路段和停车区域路段的距离
distance_1 = traci.simulation.getDistanceRoad("F5E5", 0 , edge , 0)
distance_2 = traci.simulation.getDistanceRoad("A2B2", 0, edge , 0)
# 存储
EntryDistance_1.append(distance_1)
EntryDistance_2.append(distance_2)
# 构建一个datafrmame来存储“停车区域--距离1--距离2”
self.ParkingInformation = pd.DataFrame({"ParkingArea":ParkingAreaList,
"EntryDistance_1":EntryDistance_1,
"EntryDistance_2":EntryDistance_2})
# 获取“停车区域--距离1--距离2”
def get_ParkingInformation(self):
return self.ParkingInformation
if __name__ == '__main__' :
options = get_options()
if options.nogui:
sumoBinary = checkBinary('sumo')
else:
sumoBinary = checkBinary('sumo-gui')
# 启动工程文件
traci.start([sumoBinary, "-c", "./P1/test.sumocfg", "--tripinfo-output", "tripinfo.xml",
"--quit-on-end"]) # ,"--start"
# 将各个路段的最大速度调小,停车场内的行驶速度是较慢的
SetMaxspeed = list(
map(lambda x: traci.edge.setMaxSpeed(x, 3), list(traci.edge.getIDList()))) #####将所有道路的最大速度设为6m/s
# 实例化Environment类
Env=Environment()
ParkingInformation=Env.get_ParkingInformation()
# 实例化分配策略
AL=Allocation(ParkingInformation)
# 实例化全感知模块
PER=Com_perception(ParkingInformation)
# “车辆--停车区域”关系表
VehiclePark=pd.DataFrame(columns=['Veh', 'park'])
for step in range(3600):
if step%20==0:
# 第一个入口
# 选定车位
parkingArea_1=AL.Greedy_allocation("EntryDistance_1")
# 各类参数信息
tripid = "trip_1_" + str(step) # 出行ID
origin = "F5E5" # 出发路段
destination = traci.lane.getEdgeID(traci.parkingarea.getLaneID(parkingArea_1))
vehid = "v_1_" + str(step) # 车辆ID
# 添加需求
traci.route.add(tripid, [origin, destination])
traci.vehicle.add(vehid, tripid)
traci.vehicle.setParkingAreaStop(vehid, parkingArea_1, duration=random.randint(600,3600))
# 将该信息加入到VehiclePark
VehiclePark=VehiclePark.append({'Veh':vehid,'park':parkingArea_1},ignore_index=True)
# 更新全感知模块
PER.Add_update(parkingArea_1)
# 第二个入口
# 选定车位
parkingArea_2=AL.Greedy_allocation("EntryDistance_2")
# 各类参数信息
tripid_2 = "trip_2_" + str(step) # 出行ID
origin_2 = "A2B2" # 出发路段
destination_2 = traci.lane.getEdgeID(traci.parkingarea.getLaneID(parkingArea_2))
vehid_2 = "v_2_" + str(step) # 车辆ID
# 添加需求
traci.route.add(tripid_2, [origin_2, destination_2])
traci.vehicle.add(vehid_2, tripid_2)
traci.vehicle.setParkingAreaStop(vehid_2, parkingArea_2, duration=random.randint(600,3600))
# 将该信息加入到VehiclePark
VehiclePark = VehiclePark.append({'Veh': vehid_2, 'park': parkingArea_2}, ignore_index=True)
# 更新全感知模块
PER.Add_update(parkingArea_2)
PER.Leave_update(VehiclePark)
traci.simulationStep()