这一次真正被拉去做项目的仿真了!整个过程总的来说应该还是非常痛苦的,并且最终的结果应该说不是特别完美的。
0 项目总述
整个项目就是选择一个地址来修建停车场,而我需要做的,就是对停车场选址进行仿真评价。
停车场的选址是通过四阶段法,结合出行需求以及 POI 点云等技术来选出停车场的停车需求旺盛的区域,从而得到几个停车场的待选择区域,然后分别进行仿真看看哪一个的仿真效果更加优秀。
整体思路就是先选定一个交通小区,然后将里面的已经存在的停车场建好。为了模拟真正的车流,我们选择从两个很远的地方生成车辆然后行驶到交通小区内的停车场。每辆车行驶到哪一个停车场都是随机的,如果到达的停车场已经满了那就选择最近的停车场来进行停泊。在停一段时间后离开停车场并驶离道路。
1 路网构建
这个过程是真的坐牢,真的是最麻烦的步骤了。从OpenStreetMap上下载了一块区域的道路,然后(过了很长时间才)发现居然基本上都是单车道!武汉怎么可能呢?打开街景地图后发现捏妈妈滴真不是单车道,甚至有一条路实际上是单行道它也没有标对!真的很无奈,还得在 n e t e d i t netedit netedit 上自己编辑一下路网。
编辑完开始试跑的时候发现……它的路口结构是我没有见过的???
怎么一个路口两个红绿灯??这我这个二线小城市的土狗是真的没见过啊喂。还有更离谱的:
捏妈妈滴,四个红绿灯就他妈离谱。更有甚者……:
?????这都扭曲了啊喂!
信号配时真的是一个极其艰辛的工作……一定要小心小心再小心,否则真的会出大问题:可能仿真跑到一两千秒的时候所有的车都被卡死了你却浑然不知继续压榨你的电脑(别问我怎么知道的)
我其实是只处理了交通小区内道路的情况,别的就已经……无所谓了
2 附加文件
本次项目的附加文件包括停车场信息、E2Detector 信息以及 rerouter 信息。前两个都好说,之前的文章也都介绍过,而 rerouter 是我所没有介绍的。顾名思义,就是一个重新设计路线的模块。我也正是通过这个模块完成了之前我所说的:“如果到达的停车场已经满了那就选择最近的停车场来进行停泊。”
<rerouter id="re1" edges="-231776134#0 231787845#2 236668171#1 -105857812#6 -105857812#4 -231778177#7 105573446#1 -105573446#1 105570362#1 105857815#1" pos="10922.88,11783.01">
<interval begin="0.00" end="36000.00">
<parkingAreaReroute id="pa_0"/>
<parkingAreaReroute id="pa_1"/>
<parkingAreaReroute id="pa_2"/>
<parkingAreaReroute id="pa_3"/>
<parkingAreaReroute id="pa_4"/>
<parkingAreaReroute id="pa_5"/>
<parkingAreaReroute id="pa_6"/>
<parkingAreaReroute id="pa_7"/>
<parkingAreaReroute id="pa_8"/>
<parkingAreaReroute id="pa_9"/>
<parkingAreaReroute id="pa_12"/>
</interval>
</rerouter>
其中的 edges 就是各个停车场所在的边的 id ,pos 位置其实感觉没啥必要,真没啥必要……不写它也会自动给你补全的。然后下面就是所生效的仿真时间 begin 和 end ,再往下就是 reroute 的停车场了,整体的结构还是很简单的捏。
3 路由文件
我的路由文件写的相当相当之短,因为我的车辆生成是依靠 T r a C I TraCI TraCI 来实现的。
<routes>
<vType id="type1" accel="0.8" decel="4.5" sigma="0.5" length="5" maxSpeed="70"/>
<route id="route1" edges="231522794"/>
<route id="route2" edges="236665017"/>
<route id="route3" edges="457868441#0"/>
<route id="route4" edges="455183575#0"/>
<route id="route5" edges="-105854054#3"/>
</routes>
只定义了一种车,并且还有几条路线。猜猜这几条只有一条边的路线是干什么的?哈哈,这些边是车辆生成的边。车辆出现之后,我会再用 T r a C I TraCI TraCI 来重新设定路线的。
4 程序主体
4.1 车辆的生成
for step in range(0, SIMULATE_DURATION):
traci.simulationStep()
if(step % GENERATE_DURATION == 0) :
num += 1
random1 = 0
if(sign == 0) :
random1 = int(random.uniform(0, 10))
else :
random1 = int(random.uniform(0, 11))
if(sign == 2 and random1 == 10) :
random1 = 11
PARKING_DURATION = random.uniform(PARKING_MINDUR, PARKING_MAXDUR)
traci.vehicle.add("vhe%s" % num, "route2", typeID="type1")
traci.vehicle.changeTarget("vhe%s" % num, PARKING_LOCATE[random1])
traci.vehicle.setParkingAreaStop("vhe%s" % num, "pa_%s" % random1, PARKING_DURATION)
num += 1
traci.vehicle.add("vhe%s" % num, "route3", typeID="type1")
traci.vehicle.changeTarget("vhe%s" % num, PARKING_LOCATE[random1])
traci.vehicle.setParkingAreaStop("vhe%s" % num, "pa_%s" % random1, PARKING_DURATION)
num += 1
for i in range(0, 12) :
stop_vheID = traci.parkingarea.getVehicleIDs("pa_%s" % i)
for vhe in stop_vheID :
traci.vehicle.changeTarget(vhe, "-457868463#0")
感觉也很好理解的,就是加车,然后把车辆的目标线路随机分配给好几个停车场。然后检测停车场里停着的车,让这些车从停车场出来之后直接从边==“-457868463#0”==离开路网。
4.2 计算各个停车场的占有率
for i in range(0, 13) :
parking[i] += traci.parkingarea.getVehicleCount("pa_%s" % i)
......
for i in range(0, 13) :
parking[i] /= k
print(parking[0] / PARKINGLOT_NUM_0)
print(parking[1] / PARKINGLOT_NUM_1)
print(parking[2] / PARKINGLOT_NUM_2)
print(parking[3] / PARKINGLOT_NUM_3)
print(parking[4] / PARKINGLOT_NUM_4)
print(parking[5] / PARKINGLOT_NUM_5)
print(parking[6] / PARKINGLOT_NUM_6)
print(parking[7] / PARKINGLOT_NUM_7)
print(parking[8] / PARKINGLOT_NUM_8)
print(parking[9] / PARKINGLOT_NUM_9)
print(parking[10] / PARKINGLOT_NUM_10)
print(parking[11] / PARKINGLOT_NUM_11)
print(parking[12] / PARKINGLOT_NUM_12)
这真的没啥好说的了哈,真的很无脑,就不多解释了
4.3 交叉口排队长度
# 交叉口排队
# N-0 E-1 S-2 W-3
if (traci.lanearea.getJamLengthVehicle("e2_0_E") >= 1):
numCross_0[1] += 1
ansCross_0[1] += traci.lanearea.getJamLengthVehicle("e2_0_E")
if (traci.lanearea.getJamLengthVehicle("e2_0_S") >= 1):
numCross_0[2] += 1
ansCross_0[2] += traci.lanearea.getJamLengthVehicle("e2_0_S")
if (traci.lanearea.getJamLengthVehicle("e2_0_W") >= 1):
numCross_0[3] += 1
ansCross_0[3] += traci.lanearea.getJamLengthVehicle("e2_0_W")
if (traci.lanearea.getJamLengthVehicle("e2_1_N") >= 1):
numCross_1[0] += 1
ansCross_1[0] += traci.lanearea.getJamLengthVehicle("e2_1_N")
if (traci.lanearea.getJamLengthVehicle("e2_1_E") >= 1):
numCross_1[1] += 1
ansCross_1[1] += traci.lanearea.getJamLengthVehicle("e2_1_E")
if (traci.lanearea.getJamLengthVehicle("e2_1_S") >= 1):
numCross_1[2] += 1
ansCross_1[2] += traci.lanearea.getJamLengthVehicle("e2_1_S")
if (traci.lanearea.getJamLengthVehicle("e2_1_W") >= 1):
numCross_1[3] += 1
ansCross_1[3] += traci.lanearea.getJamLengthVehicle("e2_1_W")
if (traci.lanearea.getJamLengthVehicle("e2_2_N") >= 1):
numCross_2[0] += 1
ansCross_2[0] += traci.lanearea.getJamLengthVehicle("e2_2_N")
if (traci.lanearea.getJamLengthVehicle("e2_2_E") >= 1):
numCross_2[1] += 1
ansCross_2[1] += traci.lanearea.getJamLengthVehicle("e2_2_E")
if (traci.lanearea.getJamLengthVehicle("e2_2_W") >= 1):
numCross_2[3] += 1
ansCross_2[3] += traci.lanearea.getJamLengthVehicle("e2_2_W")
if (traci.lanearea.getJamLengthVehicle("e2_3_N") >= 1):
numCross_3[0] += 1
ansCross_3[0] += traci.lanearea.getJamLengthVehicle("e2_3_N")
if (traci.lanearea.getJamLengthVehicle("e2_3_E") >= 1):
numCross_3[1] += 1
ansCross_3[1] += traci.lanearea.getJamLengthVehicle("e2_3_E")
if (traci.lanearea.getJamLengthVehicle("e2_3_S") >= 1):
numCross_3[2] += 1
ansCross_3[2] += traci.lanearea.getJamLengthVehicle("e2_3_S")
if (traci.lanearea.getJamLengthVehicle("e2_3_W") >= 1):
numCross_3[3] += 1
ansCross_3[3] += traci.lanearea.getJamLengthVehicle("e2_3_W")
......
for i in range(0, 4) :
if(i == 0) :
continue
print(ansCross_0[i] / numCross_0[i])
for i in range(0, 4) :
print(ansCross_1[i] / numCross_1[i])
for i in range(0, 4) :
if(i == 2) :
continue
print(ansCross_2[i] / numCross_2[i])
for i in range(0, 4) :
print(ansCross_3[i] / numCross_3[i])
也真的很无脑……可恶,要不是有几个 T 型路口我高低得给他整个循环一次满足
4.4 平均行程时间
T r a C I TraCI TraCI 自带的平均行程时间函数真的很怪,他是通过道路长度除以平均速度计算得来的,但是有些时候很多车停着,最后算出来一条路 nm 几万秒是不是就稍微带点离谱了??
于是我就想出来了一个比较逆天但是比这个方法要靠谱的一个方法:每秒钟检测这条路上有哪些车,检测到的车在这条路上(在停车场里不算)的话行驶时间就加一。最后就检索这条路上的车的行驶时间,行驶时间为 0 的就是没有在这条路上走过的车,不用管他。其他的就把所有的时间都加起来,然后除以不为 0 的车辆的数量,就是比较粗略的平均行程时间了。
代码如下:
while(step < SIMULATION_TIME):
a = traci.edge.getLastStepVehicleIDs("-231778177#7")
for vhe in a :
if(traci.vehicle.isStoppedParking(vhe) == True) :
continue
ansJiefangRoad[int(vhe[3:])] += 1
a = traci.edge.getLastStepVehicleIDs("-105857812#4")
for vhe in a:
if (traci.vehicle.isStoppedParking(vhe) == True):
continue
ansHouchangStreet[int(vhe[3:])] += 1
a = traci.edge.getLastStepVehicleIDs("105857815#2")
b = traci.edge.getLastStepVehicleIDs("105857815#1")
for vhe in a:
if (traci.vehicle.isStoppedParking(vhe) == True):
continue
ansPengliuyangRoad[int(vhe[3:])] += 1
for vhe in b:
if (traci.vehicle.isStoppedParking(vhe) == True):
continue
ansPengliuyangRoad[int(vhe[3:])] += 1
tmp = 0
tmpJFR = 0
for i in range(36000) :
if(ansJiefangRoad[i] == 0):
continue
tmp += 1
tmpJFR += ansJiefangRoad[i]
ansJFR = tmpJFR / tmp
print(ansJFR)
tmp = 0
tmpHCS = 0
for i in range(36000):
if (ansHouchangStreet[i] == 0):
continue
tmp += 1
tmpHCS += ansHouchangStreet[i]
ansHCS = tmpHCS / tmp
print(ansHCS)
tmp = 0
tmpPLYR = 0
for i in range(36000):
if (ansPengliuyangRoad[i] == 0):
continue
tmp += 1
tmpPLYR += ansPengliuyangRoad[i]
ansPLYR = tmpPLYR / tmp
print(ansPLYR)
4.5 与Cesium的联合仿真
就是把每秒的结果都记录下来,然后传到 Cesium 里面进行仿真。所需要的信息就是车辆类型、车辆姿态、经纬度信息。但是我还不会转换成 czml 格式,所以暂时不涉及这一方面。
代码如下:
txtfile = open("file%s.txt" % sign, "w")
print("ID\tClass\tTime\tHeading\tLongitude\tLatitude", file = txtfile)
......
while(step < SIMULATION_TIME):
nett = net.readNet('fin.net.xml')
data = traci.vehicle.getIDList()
print(step)
if(step < 1800) :
continue
k += 1
for vhe in data:
if(traci.vehicle.isStoppedParking(vhe) == True) :
continue
tt = traci.vehicle.getPosition(vhe)
flag = False
for i in range(13) :
dissq = (tt[0] - PARKING_POS[i, 0]) * (tt[0] - PARKING_POS[i, 0]) + (tt[1] - PARKING_POS[i, 1]) * (tt[1] - PARKING_POS[i, 1])
if(dissq < 10000) :
flag = True
break
if(flag == False):
continue
lon, lat = nett.convertXY2LonLat(tt[0], tt[1])
print("%s\t%s\t%s\t%s\t%s\t%s\t" % (vhe, traci.vehicle.getVehicleClass(vhe), traci.simulation.getTime(), traci.vehicle.getAngle(vhe), lon, lat), file = txtfile)
txtfile.close()
以上!因为快开始周了所以写的就比较潦草了!