Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/contributed/sumopy/plugins/hcprt/hcprt.py
169689 views
1
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
2
# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.
3
# SUMOPy module
4
# Copyright (C) 2012-2021 University of Bologna - DICAM
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file hcprt.py
16
# @author Joerg Schweizer
17
# @date 2012
18
19
"""
20
This plugin provides methods to run and analyze HCPRT networks.
21
22
23
"""
24
import os
25
import sys
26
import numpy as np
27
import random
28
import string # for debugging used in display_flows_est
29
from agilepy.lib_base.processes import Process
30
#from xml.sax import saxutils, parse, handler
31
from collections import OrderedDict, Counter
32
33
34
from coremodules.modules_common import *
35
import agilepy.lib_base.classman as cm
36
import agilepy.lib_base.arrayman as am
37
import agilepy.lib_base.xmlman as xm
38
#from agilepy.lib_base.misc import get_inversemap
39
#from agilepy.lib_base.geometry import find_area
40
#from agilepy.lib_base.processes import Process,CmlMixin,ff,call
41
from coremodules.network.network import SumoIdsConf
42
from coremodules.network.routing import edgedijkstra, get_mincostroute_edge2edge
43
from coremodules.simulation import sumo
44
from coremodules.simulation.sumo import traci
45
#from coremodules.network import routing
46
from coremodules.demand.demandbase import DemandobjMixin
47
from coremodules.simulation.simulationbase import SimobjMixin
48
49
from coremodules.demand.virtualpop import StageTypeMixin, StrategyMixin
50
from coremodules.simulation import results as res
51
52
np.set_printoptions(0, linewidth=180)
53
54
#from demo import TraciDemo
55
56
BERTHSTATES = {'free': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3,
57
'allocated': 4, 'waiting_occupied': 5, 'waiting_routed': 6}
58
59
#
60
VEHICLESTATES = {'init': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3, 'emptytrip': 4, 'occupiedtrip': 5, 'forewarding': 6, 'await_forwarding': 7,
61
'forewarding_enter': 8, 'boarding_completed': 9, 'forewarding_exit': 10, 'forewarding_passthrough': 11, 'forewarding_exit_kickout': 12, 'kickout_berth': 13}
62
63
LEADVEHICLESTATES = [VEHICLESTATES['boarding'], VEHICLESTATES['waiting'],
64
VEHICLESTATES['emptytrip'], VEHICLESTATES['occupiedtrip']]
65
STOPTYPES = {'person': 0, 'freight': 1, 'depot': 2, 'group': 3, 'mixed': 4}
66
67
FASE_MOVE_IN = 0
68
FASE_MOVE_OUT = 1
69
70
get_traci_odo = traci.vehicle.getDistance
71
get_traci_velocity = traci.vehicle.getSpeed
72
get_traci_route_all = traci.vehicle.getRoute
73
get_traci_routeindex = traci.vehicle.getRouteIndex
74
get_traci_distance = traci.vehicle.getDrivingDistance
75
76
77
def get_traci_route(id_veh_sumo):
78
return get_traci_route_all(id_veh_sumo)[get_traci_routeindex(id_veh_sumo):]
79
80
81
INF = 10.0**10
82
INFINT = 10**10
83
# def detect_entered_left(x,y):
84
# """
85
# returns the enter and left elemets of list x (before)
86
# and list y (after)
87
# """
88
# if len(x) == 0:
89
# if len(y) == 0:
90
# return
91
92
93
class Compressors(am.ArrayObjman):
94
def __init__(self, ident, prtservices, **kwargs):
95
self._init_objman(ident=ident,
96
parent=prtservices,
97
name='Compressors',
98
info='Comressors try to create platoons by shunting vehicles with common destination in a common shunt edge. Contains information and methods for compressors to create platoons.',
99
version=0.1,
100
**kwargs)
101
self._init_attributes()
102
103
def _init_attributes(self):
104
#self.add(cm.ObjConf(PrtBerths('berths',self)) )
105
106
self.add(cm.AttrConf('time_update', 1.0,
107
groupnames=['parameters'],
108
name='Update time',
109
info="Simulation update time.",
110
unit='s',
111
))
112
113
self.add(cm.AttrConf('time_accumulation_max', 29.0,
114
groupnames=['parameters'],
115
name='Maximum accumulation time',
116
info="Maximum accumulation time in a buffer. After this time the buffer is trying to release the vehicles.",
117
unit='s',
118
))
119
120
self.add(cm.AttrConf('time_release_min', 40.0,
121
groupnames=['parameters'],
122
name='Minimum realease time',
123
info="Minimum time that must pass between successive releases.",
124
unit='s',
125
))
126
127
net = self.get_scenario().net
128
129
self.add_col(am.IdsArrayConf('ids_detectoredge', net.edges,
130
name='Detector edge ID',
131
info='Detector edge ID is the edge from where vehicles are deviated into the compressor.',
132
is_index=True,
133
))
134
135
self.add_col(am.IdlistsArrayConf('ids_shuntedges', net.edges,
136
name='Shunt edge IDs',
137
info='Shunt edge IDs where PRT vehicles with common destination are sorted.',
138
))
139
140
self.set_version(0.1)
141
142
def _init_constants(self):
143
self.do_not_save_attrs([
144
'decel', 'ids_comp_to_ids_detectedge_sumo', 'queuess',
145
'queuess_alloc', 'capacitiess', 'ids_edge_sumo_targets',
146
'are_queues_avail', 'releasetimes', 'releasetimes_queues',
147
'length_veh',
148
])
149
150
def make(self, id_detectoredge=None, **kwargs):
151
print 'make', kwargs
152
# print ' ids_shuntedge',kwargs.get('ids_shuntedge',None),type(kwargs.get('ids_shuntedge',None)[0])
153
id_comp = self.add_row(ids_shuntedges=kwargs.get('ids_shuntedge', None),
154
ids_detectoredge=id_detectoredge
155
)
156
if id_detectoredge is None:
157
self.update(id_comp)
158
return id_comp
159
160
def update(self, id_comp):
161
print 'update id_comp', id_comp
162
edges = self.get_scenario().net.edges
163
164
self.ids_detectoredge[id_comp] = edges.get_incoming(self.ids_shuntedges[id_comp][0])[0]
165
166
def update_all(self):
167
print 'update_all'
168
for id_comp in self.get_ids():
169
self.update(id_comp)
170
171
def get_scenario(self):
172
return self.parent.get_scenario()
173
174
def prepare_sim(self, process):
175
print 'Compressors.prepare_sim'
176
net = self.get_scenario().net
177
nodes = net.nodes
178
edges = net.edges
179
lanes = net.lanes
180
ids_edge_sumo = edges.ids_sumo
181
182
id_prtmode = self.parent.id_prtmode
183
self.decel = self.parent.prtvehicles.decel_emergency.get_value()
184
185
ids = self.get_ids()
186
187
if len(ids) == 0:
188
return []
189
190
n_id_max = np.max(ids)+1
191
192
self.ids_comp_to_ids_detectedge_sumo = np.zeros(n_id_max, dtype=np.object)
193
self.ids_comp_to_ids_detectedge_sumo[ids] = edges.ids_sumo[self.ids_detectoredge[ids]]
194
195
# this is list of queues for all shunt lines for each compressor
196
self.queuess = np.zeros(n_id_max, dtype=np.object)
197
198
# thses queus are the same as queuess but contains the allocated, but not yet arrived vehicles
199
self.queuess_alloc = np.zeros(n_id_max, dtype=np.object)
200
201
# this is list of maximum queue length for all shunt lines for each compressor
202
self.capacitiess = np.zeros(n_id_max, dtype=np.object)
203
204
# list with target edges for each queue for each compressor
205
self.ids_edge_sumo_targets = np.zeros(n_id_max, dtype=np.object)
206
207
# list with availabilities for each queue for each compressor
208
self.are_queues_avail = np.zeros(n_id_max, dtype=np.object)
209
210
# releasetimes for each compressor
211
self.releasetimes = np.zeros(n_id_max, dtype=np.int32)
212
213
# releasetimes for each queue for each compressor
214
self.releasetimes_queues = np.zeros(n_id_max, dtype=np.object)
215
216
self.length_veh = self.parent.prtvehicles.get_length()
217
218
# this queue contains all vehicles on the detect edge
219
# it is used to identify whether a new vehicle has left the merge
220
self.ids_vehs_detect_sumo = np.zeros(n_id_max, dtype=np.object)
221
222
for id_comp, ids_shuntedge in zip(ids, self.ids_shuntedges[ids]):
223
print ' id_comp', id_comp
224
n_shunts = len(ids_shuntedge) # first edge is not a real shunt!!
225
226
queues = n_shunts*[None]
227
queues_alloc = n_shunts*[None]
228
capacities = n_shunts*[None]
229
230
for i, length_edge in zip(range(n_shunts), edges.lengths[ids_shuntedge]):
231
capacities[i] = max(2, int((length_edge-30.0)/(self.length_veh+0.5)))
232
queues[i] = []
233
queues_alloc[i] = []
234
235
self.queuess[id_comp] = queues
236
self.queuess_alloc[id_comp] = queues_alloc
237
self.capacitiess[id_comp] = capacities
238
self.ids_edge_sumo_targets[id_comp] = n_shunts*['']
239
self.are_queues_avail[id_comp] = n_shunts*[True]
240
self.releasetimes_queues[id_comp] = n_shunts*[0]
241
242
self.ids_vehs_detect_sumo[id_comp] = set()
243
print ' capacities', self.capacitiess[id_comp]
244
print ' queues', self.queuess[id_comp]
245
246
return [(self.time_update.get_value(), self.process_step),
247
]
248
249
def process_step(self, process):
250
simtime = process.simtime
251
print 79*'_'
252
print 'Compressors.process_step at', simtime
253
net = self.get_scenario().net
254
edges = net.edges
255
vehicles = self.parent.prtvehicles
256
ids = self.get_ids()
257
for id_comp,\
258
id_detectedge_sumo,\
259
ids_veh_detect_sumo,\
260
ids_shuntedge,\
261
ids_edge_sumo_target,\
262
queues,\
263
queues_alloc,\
264
capacities,\
265
are_queue_avail,\
266
releasetime_queues\
267
in zip(ids,
268
self.ids_comp_to_ids_detectedge_sumo[ids],
269
self.ids_vehs_detect_sumo[ids],
270
self.ids_shuntedges[ids],
271
self.ids_edge_sumo_targets[ids],
272
self.queuess[ids],
273
self.queuess_alloc[ids],
274
self.capacitiess[ids],
275
self.are_queues_avail[ids],
276
self.releasetimes_queues[ids],
277
):
278
n_queues = len(queues)
279
print ' '+30*'><'
280
print ' Compressor id_comp', id_comp, 'n_queues', n_queues
281
# check for new vehicle arrivals/departures
282
283
ids_veh_entered_sumo, ids_veh_left_sumo, ids_veh_new_sumo = vehicles.get_entered_left(
284
id_detectedge_sumo, ids_veh_detect_sumo)
285
286
if 1:
287
print ' id_detectedge_sumo', id_detectedge_sumo
288
print ' ids_veh_detect_sumo', ids_veh_detect_sumo
289
print ' ids_veh_new_sumo', ids_veh_new_sumo
290
print ' ids_veh_entered_sumo=', ids_veh_entered_sumo
291
print ' ids_veh_left_sumo=', ids_veh_left_sumo
292
293
if len(ids_veh_entered_sumo) > 0:
294
295
ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)
296
297
for id_veh_entered, id_veh_entered_sumo, id_leader, length_plat\
298
in zip(ids_veh_entered, ids_veh_entered_sumo,
299
vehicles.ids_leader[ids_veh_entered],
300
vehicles.lengths_plat[ids_veh_entered]):
301
302
# we cannot deconcatenate here, vehicles are in movement
303
# instead, measure if there is enough room for the platoon
304
# otherwise send platoon through bypass
305
if (length_plat < 0.001) & (id_leader == -1):
306
# no platoon, it is a single vehicle
307
id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]
308
ids_shuntedge_sumo = edges.ids_sumo[ids_shuntedge]
309
print ' dispatch id_veh_entered_sumo %s' % id_veh_entered_sumo, id_targetedge_sumo, ids_edge_sumo_target
310
311
is_found_queue = False
312
inds_queue = np.flatnonzero((np.array(ids_edge_sumo_target, object)
313
== id_targetedge_sumo) & np.array(are_queue_avail, dtype=np.bool))
314
# print ' inds_queue',inds_queue
315
if len(inds_queue) > 0:
316
#ind_queue = ids_edge_sumo_target.index(id_targetedge_sumo)
317
ind_queue = inds_queue[0]
318
queue = queues[ind_queue]
319
capa_queue = capacities[ind_queue]
320
len_queue = len(queue)
321
# print ' found ind_queue,len_queue,capa_queue',ind_queue,len_queue,capa_queue
322
# if len_queue < capa_queue:
323
self._alloc_queue(queue, queues_alloc[ind_queue],
324
capa_queue,
325
id_veh_entered,
326
id_veh_entered_sumo,
327
ids_shuntedge[ind_queue],
328
ids_shuntedge_sumo[ind_queue],
329
vehicles, edges)
330
331
# queue is full now, remove target
332
# no, otherwise th target is lost to program the vehicles
333
if len_queue+1 == capa_queue:
334
are_queue_avail[ind_queue] = False
335
336
is_found_queue = True
337
338
if not is_found_queue:
339
# print ' no queue with target or specific queue is full, search for a new queue'
340
341
is_found_queue = False
342
for ind_queue, queue in zip(range(1, n_queues), queues[1:]):
343
if len(queue) == 0:
344
is_found_queue = True
345
break
346
# ind_queue = 1 # start with 1 because 0 is bypass
347
#is_queueend = False
348
# while len(queues[ind_queue])>0 & (not is_queueend):
349
# is_queueend = ind_queue == n_queues-1
350
# if not
351
# ind_queue += 1
352
353
if not is_found_queue:
354
# print ' all queues are busy, let vehicle %s go ahead'%id_veh_entered_sumo
355
pass
356
else:
357
print ' configure target of new queue', ind_queue, id_targetedge_sumo
358
ids_edge_sumo_target[ind_queue] = id_targetedge_sumo
359
self._alloc_queue(queues[ind_queue],
360
queues_alloc[ind_queue],
361
capacities[ind_queue],
362
id_veh_entered,
363
id_veh_entered_sumo,
364
ids_shuntedge[ind_queue],
365
ids_shuntedge_sumo[ind_queue],
366
vehicles, edges)
367
368
else:
369
# let platoon pass
370
pass
371
else:
372
# nothing happened
373
pass
374
375
# update veh on detector edge
376
self.ids_vehs_detect_sumo[id_comp] = ids_veh_new_sumo
377
378
if True: # do this later ...simtime - self.releasetimes[id_comp]> 10:
379
# now check if any of the vehicle in any of the queues has arrived
380
# and if a queue is complete, create a platoon, send it off and
381
# reset the queue
382
# print ' Deal with queues...'
383
for ind_queue, queue, queue_alloc,\
384
capacity, id_edge_sumo_target,\
385
id_shuntedge_sumo, releasetime_queue\
386
in zip(
387
range(n_queues), queues, queues_alloc,
388
capacities, ids_edge_sumo_target,
389
edges.ids_sumo[ids_shuntedge], releasetime_queues):
390
if 0:
391
print ' OOOO shunt %s --> target %s' % (id_shuntedge_sumo, id_edge_sumo_target)
392
print ' simtime-releasetime_queue', simtime-releasetime_queue
393
print ' queue', queue, id(queue)
394
print ' queue_alloc', queue_alloc
395
396
# check if allocated arrived
397
ids_veh_arrived = []
398
for id_veh, id_veh_sumo in zip(queue_alloc, vehicles.ids_sumo[queue_alloc]):
399
if vehicles.reached_stop_sumo(id_veh_sumo):
400
ids_veh_arrived.append(id_veh)
401
402
for id_veh in ids_veh_arrived:
403
queue_alloc.remove(id_veh)
404
405
# check if queue reached capacity limit
406
len_queue = len(queue)
407
if (len(queue_alloc) == 0) & (len_queue > 0):
408
# no allocations for this queue
409
len_queue = len(queue)
410
# print ' rtq,rtc',releasetime_queue,self.releasetimes[id_comp], len_queue == capacity,simtime - releasetime_queue,simtime - self.releasetimes[id_comp]
411
# here we coukd also test timeout conditions
412
if ((len_queue == capacity) | ((simtime - releasetime_queue) > self.time_accumulation_max.get_value())) & (simtime - self.releasetimes[id_comp] > self.time_release_min.get_value()):
413
# queue is full
414
print ' platoon and send vehicles:', queue
415
# action 1
416
# platoon all vehicles in queue, starting from last in queue
417
for i in range(len_queue-1, 0, -1):
418
vehicles.concatenate(queue[i], queue[i-1])
419
420
# print ' check platooned vehicles:'
421
vehicles.get_platoon(queue[0])
422
# reprogram destination and start
423
for id_veh, id_veh_sumo in zip(queue, vehicles.ids_sumo[queue]):
424
vehicles.reschedule_trip_sumo(id_veh_sumo, id_edge_sumo_target)
425
#vehicles.control_slow_down( id_veh, speed = 6.0/3.6)
426
traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
427
428
# reset queue
429
del queue[:]
430
ids_edge_sumo_target[ind_queue] = ""
431
are_queue_avail[ind_queue] = True
432
releasetime_queues[ind_queue] = int(simtime)
433
self.releasetimes[id_comp] = int(simtime)
434
435
def _alloc_queue(self, queue, queue_alloc, capa_queue,
436
id_veh, id_veh_sumo,
437
id_shuntedge, id_shuntedge_sumo, vehicles, edges):
438
439
queue.append(id_veh)
440
queue_alloc.append(id_veh)
441
len_queue = len(queue)
442
#pos_stop = 1.0+(capa_queue-len_queue)*(self.length_veh+0.5)
443
pos_stop = edges.lengths[id_shuntedge]-10-len_queue*(self.length_veh+0.5)
444
# print '_alloc_queue',id_veh_sumo,id_shuntedge_sumo,capa_queue-len_queue,pos_stop
445
vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)
446
447
vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex=0)
448
# print ' get_traci_route',get_traci_route(id_veh_sumo)
449
# print ' get_traci_route_all',get_traci_route_all(id_veh_sumo)
450
# print ' get_traci_routeindex',get_traci_routeindex(id_veh_sumo)
451
#get_traci_route_all = traci.vehicle.getRoute
452
#get_traci_routeindex = traci.vehicle.getRouteIndex
453
# def get_traci_route
454
455
456
class Decompressors(Compressors):
457
def __init__(self, ident, prtservices, **kwargs):
458
self._init_objman(ident=ident,
459
parent=prtservices,
460
name='Decompressors',
461
info='Decomressors dissolve platoons by stopping and decatenating vehicles in parallel shunt edges. Contains information and methods for decompressors to create platoons.',
462
version=0.1,
463
**kwargs)
464
self._init_attributes()
465
466
def _init_constants(self):
467
self.do_not_save_attrs([
468
'decel', 'ids_comp_to_ids_detectedge_sumo', 'queuess',
469
'queuess_alloc', 'capacitiess', # 'ids_edge_sumo_targets',
470
'are_queues_avail', 'releasetimes', 'releasetimes_queues',
471
'length_veh', 'ids_vehs_detect_sumo',
472
])
473
474
def prepare_sim(self, process):
475
print 'Decompressors.prepare_sim'
476
net = self.get_scenario().net
477
nodes = net.nodes
478
edges = net.edges
479
lanes = net.lanes
480
ids_edge_sumo = edges.ids_sumo
481
482
id_prtmode = self.parent.id_prtmode
483
self.decel = self.parent.prtvehicles.decel_emergency.get_value()
484
485
ids = self.get_ids()
486
if len(ids) == 0:
487
return []
488
n_id_max = np.max(ids)+1
489
490
self.ids_comp_to_ids_detectedge_sumo = np.zeros(n_id_max, dtype=np.object)
491
self.ids_comp_to_ids_detectedge_sumo[ids] = edges.ids_sumo[self.ids_detectoredge[ids]]
492
493
# this is list of queues for all shunt lines for each compressor
494
self.queuess = np.zeros(n_id_max, dtype=np.object)
495
496
# this is list of target edges for all shunt lines for each compressor
497
self.ids_targetedgess_sumo = np.zeros(n_id_max, dtype=np.object)
498
499
# thses queus are the same as queuess but contains the allocated, but not yet arrived vehicles
500
self.queuess_alloc = np.zeros(n_id_max, dtype=np.object)
501
502
# this is list of maximum queue length for all shunt lines for each compressor
503
self.capacitiess = np.zeros(n_id_max, dtype=np.object)
504
505
# list with target edges for each queue for each compressor
506
#self.ids_edge_sumo_targets = np.zeros(n_id_max,dtype = np.object)
507
508
# list with availabilities for each queue for each compressor
509
self.are_queues_avail = np.zeros(n_id_max, dtype=np.object)
510
511
# releasetimes for each compressor
512
self.releasetimes = np.zeros(n_id_max, dtype=np.int32)
513
514
# releasetimes for each queue for each compressor
515
self.releasetimes_queues = np.zeros(n_id_max, dtype=np.object)
516
517
self.length_veh = self.parent.prtvehicles.get_length()
518
519
# this queue contains all vehicles on the detect edge
520
# it is used to identify whether a new vehicle has left the merge
521
self.ids_vehs_detect_sumo = np.zeros(n_id_max, dtype=np.object)
522
523
for id_comp, ids_shuntedge in zip(ids, self.ids_shuntedges[ids]):
524
print ' id_comp', id_comp
525
n_shunts = len(ids_shuntedge) # first edge is not a real shunt!!
526
527
queues = n_shunts*[None]
528
queues_alloc = n_shunts*[None]
529
capacities = n_shunts*[None]
530
ids_targetedges_sumo = n_shunts*[None]
531
for i, length_edge in zip(range(n_shunts), edges.lengths[ids_shuntedge]):
532
capacities[i] = int((length_edge-25.0)/(self.length_veh+0.5))
533
queues[i] = []
534
queues_alloc[i] = []
535
ids_targetedges_sumo[i] = {}
536
537
self.queuess[id_comp] = queues
538
self.queuess_alloc[id_comp] = queues_alloc
539
self.capacitiess[id_comp] = capacities
540
self.ids_targetedgess_sumo[id_comp] = ids_targetedges_sumo
541
#self.ids_edge_sumo_targets [id_comp] = n_shunts*['']
542
self.are_queues_avail[id_comp] = n_shunts*[True]
543
self.releasetimes_queues[id_comp] = np.arange(n_shunts)*int(self.time_accumulation_max.get_value()/n_shunts)
544
545
self.ids_vehs_detect_sumo[id_comp] = set()
546
# print ' capacities',self.capacitiess[id_comp]
547
# print ' queues',self.queuess[id_comp]
548
549
return [(self.time_update.get_value(), self.process_step),
550
]
551
552
def process_step(self, process):
553
simtime = process.simtime
554
print 79*'_'
555
print 'Deompressors.process_step at', simtime
556
net = self.get_scenario().net
557
edges = net.edges
558
vehicles = self.parent.prtvehicles
559
ids = self.get_ids()
560
for id_comp,\
561
id_detectedge_sumo,\
562
ids_veh_detect_sumo,\
563
ids_shuntedge,\
564
queues,\
565
queues_alloc,\
566
capacities,\
567
are_queue_avail,\
568
releasetime_queues,\
569
ids_targetedges_sumo\
570
in zip(ids,
571
self.ids_comp_to_ids_detectedge_sumo[ids],
572
self.ids_vehs_detect_sumo[ids],
573
self.ids_shuntedges[ids],
574
self.queuess[ids],
575
self.queuess_alloc[ids],
576
self.capacitiess[ids],
577
self.are_queues_avail[ids],
578
self.releasetimes_queues[ids],
579
self.ids_targetedgess_sumo[ids]
580
):
581
n_queues = len(queues)
582
ids_shuntedge_sumo = edges.ids_sumo[ids_shuntedge]
583
print ' '+60*'|'
584
print ' Decompressor id_comp', id_comp, 'n_queues', n_queues
585
# check for new vehicle arrivals/departures
586
587
ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_detectedge_sumo))
588
if 0:
589
print ' id_detectedge_sumo', id_detectedge_sumo
590
print ' ids_veh_detect_sumo', ids_veh_detect_sumo, ids_veh_detect_sumo != ids_veh_sumo
591
print ' ids_veh_sumo=', ids_veh_sumo
592
ids_veh_sumo_raw = traci.edge.getLastStepVehicleIDs(id_detectedge_sumo)
593
print ' ids_veh_sumo_raw=', ids_veh_sumo_raw
594
595
if ids_veh_detect_sumo != ids_veh_sumo:
596
# there are new vehicles
597
598
#ids_veh_entered_sumo, poss = vehicles.get_ids_sumo_sorted(ids_veh_sumo.difference(ids_veh_detect_sumo))
599
ids_veh_entered_sumo = list(ids_veh_sumo.difference(ids_veh_detect_sumo))
600
ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)
601
602
if 1:
603
print ' ids_veh_entered', ids_veh_entered, type(ids_veh_entered)
604
# print ' poss',poss
605
print ' ids_veh_entered_sumo', ids_veh_entered_sumo
606
print ' ids_leader', vehicles.ids_leader[ids_veh_entered]
607
print ' ids_follower', vehicles.ids_follower[ids_veh_entered]
608
print ' lengths_plat', vehicles.lengths_plat[ids_veh_entered]
609
610
for id_veh_entered, id_veh_entered_sumo, id_leader, length_plat\
611
in zip(ids_veh_entered, ids_veh_entered_sumo,
612
vehicles.ids_leader[ids_veh_entered],
613
vehicles.lengths_plat[ids_veh_entered]):
614
615
# we cannot deconcatenate here, vehicles are in movement
616
# instead, measure if there is enough room for the platoon
617
# otherwise send platoon through bypass
618
if (length_plat > 0.001) & (id_leader == -1):
619
# vehicle is a platoon leader:
620
# find a queue that fits the platoon
621
id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]
622
# print ' dispatch id_veh_entered_sumo %s with target %s'%(id_veh_entered_sumo,id_targetedge_sumo)
623
624
is_found_queue = False
625
costs = np.zeros(n_queues, dtype=np.float32)
626
for ind_queue, queue, is_avail, capa in zip(range(n_queues), queues, are_queue_avail, capacities):
627
628
dl = (capa - len(queue)) * self.length_veh - 2*length_plat
629
# print ' ceck queue %d with capa %d, len = %d, dl=%d'%(ind_queue,capa,len(queue),dl)
630
if (dl > 0) & is_avail:
631
costs[ind_queue] = dl
632
else:
633
costs[ind_queue] = np.inf
634
635
ind_queue = np.argmin(costs)
636
# print ' ind_queue,costs',ind_queue,costs
637
# if costs[ind_queue] <10000:# OK queue has been found
638
#ind_queue = ids_edge_sumo_target.index(id_targetedge_sumo)
639
#ind_queue = inds_queue[0]
640
queue = queues[ind_queue]
641
capa_queue = capacities[ind_queue]
642
len_queue = len(queue)
643
# print ' found ind_queue,len_queue,capa_queue',ind_queue,len_queue,capa_queue
644
# if len_queue < capa_queue:
645
self._alloc_queue(queue, queues_alloc[ind_queue],
646
ids_targetedges_sumo[ind_queue],
647
capa_queue,
648
id_veh_entered,
649
id_veh_entered_sumo,
650
id_targetedge_sumo,
651
ids_shuntedge[ind_queue],
652
ids_shuntedge_sumo[ind_queue],
653
vehicles, edges)
654
655
elif (id_leader > -1):
656
# this is a follower:
657
# shunt it to the same edge as its leader
658
id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]
659
id_platoonleader = vehicles.get_platoonleader(id_leader)
660
for ind_queue, queue, capa_queue, in zip(range(n_queues), queues, capacities):
661
if id_platoonleader in queue:
662
# print ' found id_platoonleader prt.%d of prt.%d at queue %d'%(id_platoonleader,id_veh_entered,ind_queue)
663
self._alloc_queue_follower(
664
queue, queues_alloc[ind_queue],
665
ids_targetedges_sumo[ind_queue],
666
capa_queue,
667
id_veh_entered,
668
id_veh_entered_sumo,
669
id_targetedge_sumo,
670
ids_shuntedge_sumo[ind_queue],
671
vehicles)
672
break
673
else:
674
# individual vehicle
675
pass
676
677
# update veh on detector edge
678
self.ids_vehs_detect_sumo[id_comp] = ids_veh_sumo
679
680
# (simtime - self.releasetimes[id_comp]> self.time_release_min.get_value()): # do this later ...simtime - self.releasetimes[id_comp]> 10:
681
if 1:
682
# now check if any of the vehicle in any of the queues has arrived
683
# and if a queue is complete, create a platoon, send it off and
684
# reset the queue
685
# print ' Deal with queues...'
686
is_released = False
687
for ind_queue, queue, queue_alloc,\
688
ids_targetedge_sumo, capacity,\
689
id_shuntedge_sumo, releasetime_queue\
690
in zip(
691
range(n_queues), queues, queues_alloc,
692
ids_targetedges_sumo, capacities,
693
edges.ids_sumo[ids_shuntedge], releasetime_queues):
694
if 0:
695
print ' QQQQQQQQQQQ shunt %s ' % (id_shuntedge_sumo)
696
print ' simtime-releasetime_queue', simtime-releasetime_queue, (simtime - releasetime_queue > 15), (simtime - self.releasetimes[id_comp] > 10)
697
print ' queue', queue, id(queue)
698
print ' ids_targetedge_sumo', ids_targetedge_sumo
699
print ' queue_alloc', queue_alloc
700
print ' releasetime_queue', releasetime_queue, simtime - releasetime_queue, simtime - releasetime_queue > self.time_accumulation_max.get_value()
701
# here we could also test timeout conditions
702
if (simtime - self.releasetimes[id_comp] > self.time_release_min.get_value()) & (simtime - releasetime_queue > self.time_accumulation_max.get_value()):
703
# if (simtime - self.releasetimes[id_comp]> self.time_release_min.get_value()):
704
705
# check if allocated arrived
706
id_veh_arrived = -1
707
# for id_vehinfo,id_veh_sumo, length_plat in zip(range(),queue_alloc, vehicles.ids_sumo[queue_alloc],vehicles.lengths_plat[queue_alloc]):
708
709
for id_veh in queue_alloc:
710
if vehicles.reached_stop_sumo(vehicles.ids_sumo[id_veh]):
711
id_veh_arrived = id_veh
712
break
713
714
# print ' allocated prt.%d reached stop (-1 means no vehicle)'%(id_veh_arrived)
715
716
if id_veh_arrived > -1:
717
# a platoon leader id_veh_arrived has arrived
718
719
# print ' check if entire platoon arrived at the queue'
720
length_plat = vehicles.lengths_plat[id_veh_arrived]
721
ind_pl = queue.index(id_veh_arrived)
722
len_queue = len(queue)
723
ids_platoon = []
724
#ids_targetedge_plat_sumo= []
725
726
if len_queue > ind_pl+1:
727
728
for i, id_veh in zip(range(ind_pl+1, len_queue), queue[ind_pl+1:]):
729
# print ' check prt.%d with leader prt.%d'%(id_veh,vehicles.ids_leader[id_veh])
730
if vehicles.ids_leader[id_veh] != -1:
731
# print ' real lead prt.%d qlead prt.%d | plat lead prt.%d plat qlead prt.%d '%(vehicles.ids_leader[id_veh],queue[i-1],vehicles.get_platoonleader(id_veh),id_veh_arrived)
732
# if vehicles.ids_leader[id_veh] == queue[i-1]:
733
# print ' add'
734
# ids_platoon.append(id_veh)
735
#
736
if vehicles.get_platoonleader(id_veh) == id_veh_arrived:
737
# TODO: this is very inefficient, by happens
738
# when platoon has ben broken up during a merge operation
739
# idea: use a pointer to follower
740
ids_platoon.append(id_veh)
741
# ids_targetedge_plat_sumo.append(id_targetedge_sumo)
742
# print ' add'
743
else:
744
# is not a follower
745
pass
746
length_plat_arrived = len(ids_platoon)*self.length_veh + 0.5
747
# print ' arrived id_veh_arrived prt.%d at queue pos ind_pl=%d (should be 0)'%(id_veh_arrived,ind_pl)
748
# print ' with platoon length %.2fm greater %.2fm?'%(length_plat_arrived,length_plat)
749
750
if (length_plat_arrived >= length_plat) & (not is_released):
751
# print ' entire platoon length in queue, now release...',ids_platoon
752
is_released = True
753
# reschedule leader
754
755
vehicles.reschedule_trip(id_veh_arrived, ids_targetedge_sumo[id_veh_arrived])
756
id_veh_sumo = vehicles.get_id_sumo(id_veh_arrived)
757
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
758
#vehicles.control_slow_down( id_veh_arrived, speed = 6.0/3.6)
759
# print ' queue_alloc',queue_alloc
760
# print ' queue',queue
761
# deconcatenate and reschedule followers
762
for id_veh, id_veh_sumo in zip(ids_platoon[::-1], vehicles.ids_sumo[ids_platoon[::-1]]):
763
vehicles.decatenate(id_veh)
764
vehicles.reschedule_trip_sumo(id_veh_sumo, ids_targetedge_sumo[id_veh])
765
#vehicles.control_slow_down( id_veh, speed = 6.0/3.6)
766
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
767
queue.remove(id_veh)
768
del ids_targetedge_sumo[id_veh]
769
770
releasetime_queues[ind_queue] = int(simtime)
771
self.releasetimes[id_comp] = int(simtime)
772
773
# remove platoon leader
774
queue_alloc.remove(id_veh_arrived)
775
queue.remove(id_veh_arrived)
776
del ids_targetedge_sumo[id_veh_arrived]
777
778
else:
779
print ' platoon incomplete'
780
else:
781
# print ' no leaders arrived in this quque'
782
pass
783
784
def _alloc_queue(self, queue, queue_alloc, ids_targetedge_sumo, capa_queue,
785
id_veh, id_veh_sumo, id_targetedge_sumo,
786
id_shuntedge, id_shuntedge_sumo, vehicles, edges):
787
"""Queue allocation for platoon leader only."""
788
queue.append(id_veh)
789
790
# store here also the target necessary to reprogram
791
queue_alloc.append(id_veh)
792
# TODO: idea, the original target should be stored in the vehicles db
793
ids_targetedge_sumo[id_veh] = id_targetedge_sumo
794
len_queue = len(queue)
795
796
# make platoon leder always stop at the foremost position
797
pos_stop = 1.0 + capa_queue*(self.length_veh)
798
# print '_alloc_queue',id_veh_sumo,id_shuntedge_sumo,capa_queue-len_queue,pos_stop
799
vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)
800
vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex=0)
801
802
# Forced exit of vehicle from merge conrol
803
self.parent.mergenodes.exit_veh_forced(id_veh, id_veh_sumo, vehicles)
804
805
def _alloc_queue_follower(self, queue, queue_alloc, ids_targetedge_sumo,
806
capa_queue,
807
id_veh, id_veh_sumo, id_targetedge_sumo,
808
id_shuntedge_sumo, vehicles):
809
"""Queue allocation for follower only."""
810
queue.append(id_veh)
811
# TODO: idea, the original target should be stored in the vehicles db
812
ids_targetedge_sumo[id_veh] = id_targetedge_sumo
813
# queue_alloc.append(id_veh)
814
#len_queue = len(queue)
815
816
# make platoon leder always stop at the foremost position
817
#pos_stop = 1.0 + capa_queue*(self.length_veh + 0.5)
818
# print '_alloc_queue_follower',id_veh_sumo,id_shuntedge_sumo,id_targetedge_sumo
819
vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)
820
#vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex = 0)
821
822
823
# class Shortmergenodes(Mergenodes):
824
825
class Mergenodes(am.ArrayObjman):
826
def __init__(self, ident, prtservices, **kwargs):
827
self._init_objman(ident=ident,
828
parent=prtservices,
829
name='Merge nodes',
830
info='Contains information and methods for merging the flow of two vehicle streams, including platoons.',
831
version=0.2,
832
**kwargs)
833
self._init_attributes()
834
835
def _init_attributes(self):
836
#self.add(cm.ObjConf(PrtBerths('berths',self)) )
837
838
self.add(cm.AttrConf('time_update', 0.5,
839
groupnames=['parameters'],
840
name='Update time',
841
info="Update time for merges.",
842
unit='s',
843
))
844
845
net = self.get_scenario().net
846
847
self.add_col(am.IdsArrayConf('ids_node', net.nodes,
848
name='Node ID',
849
info='Network node ID.',
850
is_index=True,
851
))
852
853
# self.add_col(am.IdsArrayConf('ids_edge_in1', net.edges,
854
# name = 'ID edge 1',
855
# info = 'ID of edge at entrance 1.',
856
# ))
857
if self.get_version() < 0.2:
858
self.delete('ids_mergenode_in1')
859
self.delete('ids_mergenode_in2')
860
self.delete('ids_mergenodes_out')
861
self.delete('distances_mergenode_in1')
862
self.delete('distances_mergenode_in2')
863
864
self.add_col(am.IdsArrayConf('ids_node_in1', net.nodes,
865
name='ID node in 1',
866
info='ID of upstream network node at incoming line 1.',
867
))
868
869
self.add_col(am.ArrayConf('distances_node_in1', 0.0,
870
groupnames=['parameters'],
871
name='Distance node in 1',
872
info="Distance to network node at incoming line 1.",
873
unit='m',
874
))
875
876
# self.add_col(am.IdsArrayConf('ids_edge2', net.edges,
877
# name = 'ID edge 2',
878
# info = 'ID of edge at entrance 2.',
879
# ))
880
881
self.add_col(am.IdsArrayConf('ids_node_in2', net.nodes,
882
name='ID node in 2',
883
info='ID of upstream network node at incoming line 2.',
884
))
885
886
self.add_col(am.ArrayConf('distances_node_in2', 0.0,
887
groupnames=['parameters'],
888
name='Distance mergenode in 2',
889
info="Distance to upstream network node at incoming line 2.",
890
unit='m',
891
))
892
893
self.add_col(am.IdlistsArrayConf('ids_nodes_out', net.nodes,
894
name='IDs nodes out',
895
info='IDs of downstream network nodes.',
896
))
897
898
self.add_col(am.ArrayConf('are_station', default=False,
899
groupnames=['parameters'],
900
name='is station',
901
info="Node is the exit node of a station, comressor or decompressor. The incoming edge of this are internal and are not considered.",
902
))
903
904
self.add_col(am.ArrayConf('are_entry', default=False,
905
groupnames=['parameters'],
906
name='is entry',
907
info="Node is a merge wich receives an entry line from a station, comressor or decompressor. This shorter line is always input line 1 and expects that vehicles have a speed close to zero.",
908
))
909
910
self.set_version(0.2)
911
912
def _init_constants(self):
913
self.do_not_save_attrs([
914
'ids_merge_to_ids_node_sumo', 'ids_merge_to_ids_edge_out_sumo',
915
'ids_node_to_ids_merge', 'ids_vehs_out_sumo,'
916
'ids_vehs_in1', 'ids_vehs_in1_sumo',
917
'ids_vehs_in2', 'ids_vehs_in2_sumo',
918
'ids_vehs_merged', 'ids_vehs_merged_sumo', 'odos_vehs_merged',
919
'lineinds_vehs_merged', 'vehicle_to_merge',
920
'vehicles_entries', 'vehicles_mains',
921
])
922
923
def make_from_net(self):
924
"""
925
Make merge node database from network.
926
"""
927
print 'Mergenodes.make_from_net'
928
self.clear()
929
id_prtmode = self.parent.id_prtmode
930
931
net = self.get_scenario().net
932
nodes = net.nodes
933
edges = net.edges
934
lanes = net.lanes
935
id_zippertype = nodes.types.choices['zipper']
936
937
compressors = self.parent.compressors
938
decompressors = self.parent.decompressors
939
ids_detectoredges = set(compressors.ids_detectoredge.get_value())
940
ids_detectoredges.update(decompressors.ids_detectoredge.get_value())
941
942
distances = edges.get_distances(is_precise=True)
943
944
# debug
945
ids_edge = edges.get_ids()
946
print 'distances:'
947
for id_edge, id_edge_sumo, length, dist in zip(ids_edge, edges.ids_sumo[ids_edge], edges.lengths[ids_edge], distances[ids_edge]):
948
print ' id_edge=%d id_edge_sumo=%s length=%.1f dist=%.1f' % (id_edge, id_edge_sumo, length, dist)
949
950
ids_shuntedges = set()
951
ids_mainlinedges = set()
952
953
ids = compressors.get_ids()
954
for id_unit, ids_edge in zip(ids, compressors.ids_shuntedges[ids]):
955
# put in all shunts except for the bypass
956
print ' bypass of compressor', id_unit, '=', ids_edge[0]
957
ids_mainlinedges.add(ids_edge[0])
958
print ' update ids_shuntedges with compressors', ids_edge[1:]
959
ids_shuntedges.update(ids_edge[1:])
960
961
# collect decompressornodes, wich will not become entry merges
962
ids = decompressors.get_ids()
963
ids_node_decompressorout = []
964
for id_unit, ids_edge in zip(ids, decompressors.ids_shuntedges[ids]):
965
# put in all shunts except for the bypass
966
print ' bypass of decompressor', id_unit, '=', ids_edge[0], 'id_tonode', edges.ids_tonode[ids_edge[0]]
967
ids_mainlinedges.add(ids_edge[0])
968
ids_node_decompressorout.append(edges.ids_tonode[ids_edge[0]])
969
print ' update ids_shuntedges with decompressors', ids_edge[1:]
970
ids_shuntedges.update(ids_edge[1:])
971
print ' ids_node_decompressorout', ids_node_decompressorout
972
ids_node_compressorout = edges.ids_tonode[list(ids_mainlinedges)]
973
ids_mainlinefromnodes = edges.ids_fromnode[list(ids_mainlinedges)]
974
975
# now put also all incoming edges of main lines as shunts
976
# in order to cut of compressor entrance from downstrem search
977
# for id_edge in ids_mainlinedges:
978
# print ' update ids_shuntedges with mainline incoming',edges.get_incoming(id_edge)
979
# ids_shuntedges.update(edges.get_incoming(id_edge))
980
981
print ' ids_shuntedges', ids_shuntedges
982
#ids_ptstop = ptstops.get_ids()
983
#id_mode_prt = self.parent.id_prtmode
984
985
#ids_edges = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]
986
#ids_lanes = net.edges.ids_lanes[ids_edges]
987
#ids_lane = ptstops.ids_lane[ids_ptstop]
988
#edgelengths = net.edges.lengths
989
990
ids_node = nodes.get_ids()
991
print ' ids_node', ids_node
992
for id_node, ids_edge_from, ids_edge_to, id_type in zip(
993
ids_node,
994
nodes.ids_incoming[ids_node],
995
nodes.ids_outgoing[ids_node],
996
nodes.types[ids_node],
997
):
998
999
if True:
1000
#
1001
1002
print 79*'-'
1003
print ' check node', id_node, nodes.ids_sumo[id_node], id_type, id_zippertype == id_type
1004
print ' ids_edge_from', ids_edge_from
1005
print ' ids_edge_to', ids_edge_to
1006
# id merge to be created, for debugging
1007
id_merge = -1
1008
1009
if (ids_edge_from is None) | (ids_edge_to is None):
1010
print ' WARNING: isolate node: ids_edge_from,ids_edge_to', ids_edge_from, ids_edge_to
1011
pass
1012
1013
elif (len(ids_edge_from) == 2) & (len(ids_edge_to) == 1):
1014
1015
# ids_mainlinedges.add(ids_edge[0])
1016
# ids_shuntedges.update(ids_edge[1:])
1017
1018
# check accesslevels
1019
id_edge1, id_edge2 = ids_edge_from
1020
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_from]
1021
print ' id_edge1', id_edge1, 'ids_lane1', ids_lane1, self.is_prt_only(ids_lane1, lanes)
1022
print ' id_edge2', id_edge2, 'ids_lane2', ids_lane2, self.is_prt_only(ids_lane2, lanes)
1023
if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
1024
print ' +PRT merge with 2 PRT lines entering'
1025
1026
if id_type != id_zippertype:
1027
print 'WARNING: PRT network node %d %s is NOT in zipper mode!' % (id_node, nodes.ids_sumo[id_node])
1028
1029
# elif not ids_mainlinedges.isdisjoint(ids_edge_from):
1030
# print ' one incoming line is the bypass'
1031
# ids_node_out = self.search_downstream_merges(ids_edge_to[0], edges, lanes, id_prtmode)
1032
#
1033
# # model this node as a station output
1034
# self.add_row( ids_node = id_node,
1035
# ids_nodes_out = ids_node_out,
1036
# are_station = True,
1037
# )
1038
1039
else:
1040
print ' make regular merge'
1041
print ' branch 1:'
1042
id_node_up1, dist1 = self.search_upstream_merge(
1043
id_edge1, edges, lanes, id_prtmode, distances=distances)
1044
print ' id_node_up1', id_node_up1, 'dist1', dist1
1045
1046
print '\n branch 2:'
1047
id_node_up2, dist2 = self.search_upstream_merge(
1048
id_edge2, edges, lanes, id_prtmode, distances=distances)
1049
print ' id_node_up2', id_node_up1, 'dist2', dist2, '\n'
1050
1051
ids_node_out = self.search_downstream_merges(
1052
ids_edge_to[0], edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)
1053
id_merge = self.add_row(ids_node=id_node,
1054
ids_node_in1=id_node_up1,
1055
distances_node_in1=dist1,
1056
ids_node_in2=id_node_up2,
1057
distances_node_in2=dist2,
1058
ids_nodes_out=ids_node_out,
1059
are_station=False,
1060
)
1061
1062
elif (len(ids_edge_from) == 1) & (len(ids_edge_to) == 2):
1063
1064
id_edge_from = ids_edge_from[0]
1065
ids_lane_in = edges.ids_lanes[id_edge_from]
1066
#al_in = lanes.get_accesslevel(edges.ids_lanes[id_edge_from], id_prtmode)
1067
#is_prt_in = lanes.ids_modes_allow[edges.ids_lanes[id_edge_from]] == id_prtmode
1068
is_prt_in = self.is_prt_only(ids_lane_in, lanes)
1069
print ' one in, 2 out => diverge node, access is_prt_in', is_prt_in, 'is_platform_in', self.is_platform(ids_lane_in, lanes)
1070
1071
# if id_edge_from in ids_detectoredges:
1072
# print ' fromnode is a detectoredge of a compressor'
1073
# id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1074
# self.add_row( ids_node = id_node,
1075
# ids_node_in1 = id_node_up,
1076
# distances_node_in1 = dist,
1077
# #ids_nodes_out = ids_node_out,
1078
# are_station = True,
1079
# )
1080
1081
# check if node is outgoing node at a station
1082
if 0: # no longer considered
1083
if is_prt_in & (id_node in ids_mainlinefromnodes):
1084
print ' Diverge node in front of a compressor/decompressorr.'
1085
id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1086
1087
id_edge1, id_edge2 = ids_edge_to
1088
if id_edge1 in ids_mainlinedges:
1089
id_edge = id_edge1
1090
else:
1091
id_edge = id_edge2
1092
1093
#ids_node_out = self.search_downstream_merges(id_edge, edges, lanes, id_prtmode, ids_sinkedge = ids_shuntedges)
1094
ids_node_out = [edges.ids_tonode[id_edge]]
1095
self.add_row(ids_node=id_node,
1096
ids_node_in1=id_node_up,
1097
distances_node_in1=dist,
1098
ids_nodes_out=ids_node_out,
1099
are_station=True,
1100
)
1101
1102
if self.is_platform(ids_lane_in, lanes):
1103
print ' mixed access level of incoming edge, check for platform exit node'
1104
1105
id_edge1, id_edge2 = ids_edge_to
1106
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_to]
1107
1108
# here we could also decide on the number of lanes
1109
# but this may not be robust in the future
1110
print ' out id_edge1', id_edge1, 'ids_lane1', ids_lane1, 'is_prt_only', self.is_prt_only(ids_lane1, lanes)
1111
print ' out id_edge2', id_edge2, 'ids_lane2', ids_lane2, 'is_prt_only', self.is_prt_only(ids_lane2, lanes)
1112
# if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
1113
if self.is_prt_only(ids_lane2, lanes):
1114
1115
print ' Ped exit on outedge 1'
1116
#id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1117
ids_node_out = self.search_downstream_merges(
1118
id_edge2, edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)
1119
id_merge = self.add_row(ids_node=id_node,
1120
#ids_node_in1 = id_node_up,
1121
#distances_node_in1 = dist,
1122
ids_nodes_out=ids_node_out,
1123
are_station=True,
1124
)
1125
1126
elif self.is_prt_only(ids_lane1, lanes):
1127
print ' Ped exit on outedge 2'
1128
#id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1129
ids_node_out = self.search_downstream_merges(
1130
id_edge1, edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)
1131
id_merge = self.add_row(ids_node=id_node,
1132
#ids_node_in1 = id_node_up,
1133
#distances_node_in1 = dist,
1134
ids_nodes_out=ids_node_out,
1135
are_station=True,
1136
)
1137
1138
if id_merge >= 0:
1139
self.print_attrs(ids=[id_merge, ])
1140
print '\n now check if merge has entry line form stations or compressors'
1141
1142
ids = self.get_ids()
1143
i = 0
1144
while i < len(ids):
1145
id_merge = ids[i]
1146
1147
id_node_in1 = self.ids_node_in1[id_merge]
1148
id_node_in2 = self.ids_node_in2[id_merge]
1149
print 79*'-'
1150
print ' check entry of id_merge', id_merge, 'id_node', self.ids_node[id_merge], ' no decomp', self.ids_node[id_merge] not in ids_node_decompressorout
1151
if (id_node_in1 > -1) & (id_node_in2 > -1)\
1152
& (self.ids_node[id_merge] not in ids_node_decompressorout):
1153
1154
print ' id_node_in1', self.ids_node_in1[id_merge], nodes.ids_sumo[self.ids_node_in1[id_merge]], self.ids_node.has_index(self.ids_node_in1[id_merge])
1155
print ' id_node_in2', self.ids_node_in2[id_merge], nodes.ids_sumo[self.ids_node_in2[id_merge]], self.ids_node.has_index(self.ids_node_in2[id_merge])
1156
if 1:
1157
1158
print ' self.ids_node._index_to_id', self.ids_node._index_to_id
1159
1160
id_merge_in1 = self.ids_node.get_id_from_index(self.ids_node_in1[id_merge])
1161
id_merge_in2 = self.ids_node.get_id_from_index(self.ids_node_in2[id_merge])
1162
1163
print ' station check id_merge', id_merge, 'id_merge_in1', id_merge_in1, 'station', self.are_station[id_merge_in1], 'id_merge_in2', id_merge_in2, 'station', self.are_station[id_merge_in2]
1164
1165
if self.are_station[id_merge_in2]:
1166
self.are_entry[id_merge] = True
1167
# in line 2 is already entry line
1168
pass
1169
1170
elif self.are_station[id_merge_in1]:
1171
self.are_entry[id_merge] = True
1172
# move entry line from inline 1 to inline 2
1173
1174
id_node_in2 = self.ids_node_in2[id_merge]
1175
dist2 = self.distances_node_in2[id_merge]
1176
1177
self.ids_node_in2[id_merge] = self.ids_node_in1[id_merge]
1178
self.distances_node_in2[id_merge] = self.distances_node_in1[id_merge]
1179
1180
self.ids_node_in1[id_merge] = id_node_in2
1181
self.distances_node_in1[id_merge] = dist2
1182
1183
i += 1
1184
1185
def get_scenario(self):
1186
return self.parent.get_scenario()
1187
1188
def prepare_sim(self, process):
1189
print 'Mergenodes.prepare_sim'
1190
net = self.get_scenario().net
1191
nodes = net.nodes
1192
edges = net.edges
1193
lanes = net.lanes
1194
ids_edge_sumo = edges.ids_sumo
1195
1196
id_prtmode = self.parent.id_prtmode
1197
self.decel = self.parent.prtvehicles.decel_emergency.get_value()
1198
1199
ids = self.get_ids()
1200
if len(ids) == 0:
1201
return []
1202
n_id_max = np.max(ids)+1
1203
1204
# database with vehicle id as key and controlling merge as value
1205
self.vehicle_to_merge = {}
1206
1207
# vehicle database for merge operation
1208
self.vehicles_entries = {}
1209
1210
# TODO: this is only used to indicate that a vehicle on main
1211
# is involved in merging with entry line.
1212
# A simple set per merge would suffice
1213
self.vehicles_mains = {}
1214
1215
#self.ids_merge_to_ids_node_sumo = np.zeros(n_id_max,dtype = np.object)
1216
#self.ids_merge_to_ids_node_sumo[ids] = nodes.ids_sumo[self.ids_node[ids]]
1217
1218
self.ids_merge_to_ids_edge_out_sumo = np.zeros(n_id_max, dtype=np.object)
1219
#self.ids_node_to_ids_edge_out_sumo = np.zeros(n_id_max,dtype = np.object)
1220
self.ids_node_to_ids_merge = np.zeros(np.max(self.ids_node[ids])+1, dtype=np.int32)
1221
self.ids_node_to_ids_merge[self.ids_node[ids]] = ids
1222
1223
# this queue contains all vehicles on the outgoing edge
1224
# it is used to identify whether a new vehicle has left the merge
1225
self.ids_vehs_out_sumo = np.zeros(n_id_max, dtype=np.object)
1226
1227
# this queue contains all vehicles on line 1 between
1228
# merge and id_node_in1
1229
self.ids_vehs_in1 = np.zeros(n_id_max, dtype=np.object)
1230
self.ids_vehs_in1_sumo = np.zeros(n_id_max, dtype=np.object)
1231
1232
# this queue contains all vehicles on line 2 between
1233
# merge and id_node_in2
1234
self.ids_vehs_in2 = np.zeros(n_id_max, dtype=np.object)
1235
self.ids_vehs_in2_sumo = np.zeros(n_id_max, dtype=np.object)
1236
1237
# this queue contains the merged vehicles for the controlled range
1238
self.ids_vehs_merged = np.zeros(n_id_max, dtype=np.object)
1239
self.ids_vehs_merged_sumo = np.zeros(n_id_max, dtype=np.object)
1240
1241
# this queuse contains the line index (1 or 2, 0= not assigned)
1242
self.lineinds_vehs_merged = np.zeros(n_id_max, dtype=np.object)
1243
1244
# odometer of vehicle when vehicle enters merge
1245
self.odos_vehs_merged = np.zeros(n_id_max, dtype=np.object)
1246
1247
# this is the first and last vehicle of a platoon that is about to exit th merge
1248
# the platoon will wait for exit from merge until the entire platoon
1249
# passed the merge node. This means the last vehicle of the platoon
1250
# must be detected on the exit edge.
1251
self.ids_plat_wait_exit = -1*np.ones((n_id_max, 2), dtype=np.int32)
1252
1253
#self.ids_merge_to_ids_edge_out_sumo[ids] = edges.ids_sumo[self.ids_node[ids]]
1254
ids_node = self.ids_node[ids]
1255
for id_merge, id_node, ids_edge_out in zip(ids, ids_node, nodes.ids_outgoing[ids_node]):
1256
if len(ids_edge_out) == 1:
1257
# regular merge
1258
self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[ids_edge_out[0]]
1259
1260
elif len(ids_edge_out) == 2:
1261
# one edge is PRT, the other ped access
1262
# check accesslevels
1263
id_edge1, id_edge2 = ids_edge_out
1264
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_out]
1265
al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)
1266
al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)
1267
if al1 == 2:
1268
self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge1]
1269
#self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge1]
1270
if al2 == 2:
1271
self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge2]
1272
#self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge2]
1273
1274
self.ids_vehs_out_sumo[id_merge] = set()
1275
1276
self.ids_vehs_in1[id_merge] = list()
1277
self.ids_vehs_in1_sumo[id_merge] = list()
1278
1279
self.ids_vehs_in2[id_merge] = list()
1280
self.ids_vehs_in2_sumo[id_merge] = list()
1281
1282
self.ids_vehs_merged[id_merge] = list()
1283
self.ids_vehs_merged_sumo[id_merge] = list()
1284
self.lineinds_vehs_merged[id_merge] = list()
1285
self.odos_vehs_merged[id_merge] = list()
1286
1287
self.vehicles_entries[id_merge] = OrderedDict()
1288
1289
# A simple set per merge would suffice
1290
self.vehicles_mains[id_merge] = OrderedDict()
1291
1292
return [(self.time_update.get_value(), self.process_step),
1293
]
1294
1295
def process_step(self, process):
1296
simtime = process.simtime
1297
print 79*'_'
1298
print 'Mergenodes.process_step at', simtime
1299
net = self.get_scenario().net
1300
vehicles = self.parent.prtvehicles
1301
1302
# if vehicles.id_follower_probe != vehicles.ids_follower[271]:
1303
# print 'MERGE WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]
1304
1305
ids = self.get_ids()
1306
for id_merge, id_node, id_edge_out, ids_node_out, ids_veh_out_sumo, is_entry in\
1307
zip(ids,
1308
self.ids_node[ids],
1309
self.ids_merge_to_ids_edge_out_sumo[ids],
1310
self.ids_nodes_out[ids],
1311
self.ids_vehs_out_sumo[ids],
1312
self.are_entry[ids],
1313
):
1314
print ' '+60*'.'
1315
1316
####
1317
debug = False # id_merge in [24,22,19]
1318
# debug = id_merge in [59,18,15,16] #(id_merge==2)|(id_merge==7)
1319
# debug = (id_merge==1)|('gneJ1' in net.nodes.ids_sumo[ids_node_out])#'gneJ29':#'gneJ1':
1320
#debug = debug | (id_merge==17)| ('gneJ29' in net.nodes.ids_sumo[ids_node_out])
1321
1322
###
1323
print ' process id_merge', id_merge, ',id_node', id_node, net.nodes.ids_sumo[id_node], 'debug', debug
1324
1325
# check for new vehicle arrivals/departures
1326
ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_out))
1327
1328
# if debug:
1329
# print ' check id_edge_out',id_edge_out
1330
# print ' ids_veh_out_sumo=',ids_veh_out_sumo
1331
# print ' ids_veh_sumo=',ids_veh_sumo
1332
# print ' ids_node_out',ids_node_out
1333
# print ' ids_vehs_merged_sumo',self.ids_vehs_merged_sumo[id_merge]
1334
1335
if ids_veh_out_sumo != ids_veh_sumo:
1336
1337
# attention, this is a list, not an array with numpy indexing
1338
ids_veh_entered_sumo = list(ids_veh_sumo.difference(ids_veh_out_sumo))
1339
1340
# this is an array
1341
ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)
1342
#ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo)))
1343
1344
if debug:
1345
print ' ids_veh_entered', ids_veh_entered, type(ids_veh_entered)
1346
# print ' ids_veh_entered_sumo',ids_veh_entered_sumo
1347
# print ' ids_leader',vehicles.ids_leader[ids_veh_entered]
1348
1349
if ids_node_out is None:
1350
# the present merge is an end node example at a station
1351
ids_merge_out = []
1352
else:
1353
# determine id merge according to given output node
1354
ids_merge_out = self.ids_node_to_ids_merge[ids_node_out]
1355
1356
ids_edge_mergeout_sumo = self.ids_merge_to_ids_edge_out_sumo[ids_merge_out]
1357
# if debug:
1358
# print ' ids_node_out',ids_node_out
1359
# print ' ids_merge_out',ids_merge_out
1360
# print ' ids_edge_mergeout_sumo',ids_edge_mergeout_sumo
1361
# print ' ids_leader',vehicles.ids_leader[ids_veh_entered]
1362
# merge only vehicle without a leader (individual or first in a platoon)
1363
1364
# check first if the last vehicle of an exiting platoon
1365
# entered the out edge
1366
1367
id_veh_first, id_veh_last = self.ids_plat_wait_exit[id_merge]
1368
if id_veh_first > -1:
1369
if debug > 0:
1370
print ' platoon waiting for exit: id_veh_first prt.%d, id_veh_last prt.%d' % (id_veh_first, id_veh_last)
1371
inds_entered = np.flatnonzero(vehicles.ids_leader[ids_veh_entered] > -1)
1372
if np.any(id_veh_last == ids_veh_entered[inds_entered]):
1373
if debug > 0:
1374
print ' last vehicle of platoon left merge -> exit leader prt.%d' % id_veh_first
1375
self.exit_veh(id_veh_first, vehicles.get_id_sumo(id_veh_first), id_merge, vehicles, debug=debug)
1376
self.ids_plat_wait_exit[id_merge] = [-1, -1]
1377
1378
if self.ids_plat_wait_exit[id_merge][0] == -1:
1379
# no platoon waiting for exit
1380
inds_entered = np.flatnonzero(vehicles.ids_leader[ids_veh_entered] == -1)
1381
else:
1382
# platoon waiting for exit, so do not check for new leaders
1383
inds_entered = []
1384
1385
if debug:
1386
print ' inds_entered', inds_entered
1387
if len(inds_entered) > 0:
1388
for ind_entered, id_veh in zip(inds_entered, ids_veh_entered[inds_entered]):
1389
1390
id_veh_sumo = ids_veh_entered_sumo[ind_entered]
1391
if debug > 0:
1392
print ' >>try exiting vehicle', id_veh_sumo, 'is_leader', vehicles.ids_leader[id_veh] == -1, 'ids_node_out', ids_node_out, 'ids_merge_out', ids_merge_out
1393
1394
# print ' route_sumo',route_sumo
1395
1396
if ids_node_out is not None:
1397
1398
# check whether all platoon vehicles are on out edge
1399
id_veh_last = vehicles.get_platoontail(id_veh)
1400
if (id_veh_last != id_veh):
1401
if id_veh_last not in ids_veh_entered:
1402
if debug:
1403
print ' wait for last plat vehicle', id_veh_last
1404
self.ids_plat_wait_exit[id_merge] = [id_veh, id_veh_last]
1405
else:
1406
if debug:
1407
print ' last plat vehicle', id_veh_last, 'after merge node, exit', id_veh_sumo
1408
self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles, debug=debug)
1409
else:
1410
if debug:
1411
print ' vehicle', id_veh, 'has no platoon, exit', id_veh_sumo
1412
self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles, debug=debug)
1413
1414
# exit from previous merge
1415
# if debug:
1416
# print ' vehicle',id_veh_sumo,'exits id_merge',id_merge
1417
1418
if debug > 0:
1419
print ' check which out mergenode are on the current route of the vehicle'
1420
1421
if len(ids_merge_out) > 0:
1422
1423
# inform the respectine merges
1424
# then communicate vehicle with dist to merge
1425
# attention, we need the first hit in the route
1426
# check which downstream merge to enter
1427
route_sumo = get_traci_route(id_veh_sumo)
1428
1429
routeinds = [INFINT]*len(ids_merge_out)
1430
# print ' ids_merge_out',ids_merge_out
1431
i = 0
1432
for id_edge_sumo in ids_edge_mergeout_sumo:
1433
1434
if id_edge_sumo in route_sumo:
1435
routeinds[i] = route_sumo.index(id_edge_sumo)
1436
i += 1
1437
1438
mergeind = np.argmin(routeinds)
1439
1440
if debug: # debug>0:
1441
print ' route_sumo', route_sumo
1442
print ' routeinds', routeinds, 'downstream merge', routeinds[mergeind] < INFINT
1443
# print ' ids_edge_mergeout_sumo',ids_edge_mergeout_sumo
1444
# print ' mergeind,routeinds',mergeind,routeinds
1445
# print ' ids_merge_out[mergeind]',ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind]
1446
1447
if routeinds[mergeind] < INFINT:
1448
if debug:
1449
print ' next merge is on the route'
1450
if self.are_entry[ids_merge_out[mergeind]]:
1451
if debug:
1452
print ' call enter_veh_entry id_merge_out', ids_merge_out[mergeind]
1453
self.enter_veh_entry(
1454
id_veh, id_veh_sumo, id_merge, ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind], vehicles, debug=debug)
1455
else:
1456
if debug:
1457
print ' call enter_veh id_merge_out', ids_merge_out[mergeind]
1458
self.enter_veh(
1459
id_veh, id_veh_sumo, id_merge, ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind], vehicles, debug=debug)
1460
else:
1461
# no downstream merge, vehicle goes into a station
1462
pass
1463
else:
1464
# print ' ids_node_out is empty means that there is a station or compressor'
1465
pass
1466
1467
else:
1468
# ids_node_out is None
1469
if debug:
1470
print ' There is a station or compressor shunt edges next'
1471
print ' completely disconnect from all merge and ghost controlls'
1472
1473
# exit from previous merge
1474
self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles)
1475
1476
# update vehicles on detection edge
1477
self.ids_vehs_out_sumo[id_merge] = ids_veh_sumo
1478
1479
# process special merge decisions and processes for entry merge types
1480
if is_entry:
1481
self.process_step_entry(id_merge, vehicles, debug)
1482
1483
if 0:
1484
print '========check mergeprocess'
1485
for id_merge, id_node_sumo, ids_veh_merged_sumo, ids_veh_merged in\
1486
zip(ids,
1487
net.nodes.ids_sumo[self.ids_node[ids]],
1488
self.ids_vehs_merged_sumo[ids],
1489
self.ids_vehs_merged[ids]
1490
):
1491
1492
print ' ', id_merge, id_node_sumo, ids_veh_merged_sumo
1493
# print ' ids_veh_merged',ids_veh_merged
1494
1495
def exit_veh(self, id_veh, id_veh_sumo, id_merge_from, vehicles, is_remove_from_control=False, debug=0):
1496
print 'exit_veh id_veh %s, id_merge_from %d ' % (id_veh_sumo, id_merge_from), 'entry', self.are_entry[id_merge_from], 'is_remove_from_control', is_remove_from_control
1497
1498
# print ' check for platooned vehicles:'
1499
# vehicles.get_platoon(id_veh)
1500
# in id_merge_from: take vehicle out of merged queue and input queue
1501
1502
if id_veh in self.ids_vehs_merged[id_merge_from]:
1503
# enterd veh should be in pole position in merge queue of merge_from
1504
1505
# pop if vehicles are properly merged
1506
# id_veh_from = self.ids_vehs_merged[id_merge_from].pop()
1507
# self.ids_vehs_merged_sumo.ids_vehs_merged[id_merge_from].pop()
1508
# if id_veh_from != id_veh:
1509
# print 'WARNING in enter_veh: veh %d instead of veh %d in polepos of merge %d'%(id_veh_from,id_veh, id_merge_from)
1510
# return False
1511
# lineind = self.lineinds_vehs_merged[id_merge_from].pop()
1512
# for testing: just remove, no matter where
1513
ind_pos = self.ids_vehs_merged[id_merge_from].index(id_veh)
1514
lineind = self.lineinds_vehs_merged[id_merge_from][ind_pos]
1515
1516
if len(self.ids_vehs_merged[id_merge_from]) > ind_pos+1:
1517
# there is a vehicle behind=> remove ghost from vehicle behind to tail veh
1518
1519
id_veh_behind = self.ids_vehs_merged[id_merge_from][ind_pos+1]
1520
id_veh_tail = vehicles.get_platoontail(id_veh) # get last in platoon
1521
if debug > 0:
1522
print ' del ghost from veh behind prt.%d to platoon tail prt.%d' % (id_veh_behind, id_veh_tail)
1523
vehicles.del_ghost(id_veh_behind, id_veh_tail)
1524
if debug > 0:
1525
print ' check ghosts of behind prt.%d:' % id_veh_behind, vehicles.ids_ghosts[id_veh_behind]
1526
# is there a vehicle in front of the removed vehicle
1527
# this happens if a vehicle is interactively deviated
1528
if ind_pos > 0:
1529
1530
id_veh_infront = self.ids_vehs_merged[id_merge_from][ind_pos-1]
1531
id_veh_tail = vehicles.get_platoontail(id_veh_infront) # get last in platoon
1532
1533
id_edge_mergeout_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_from]
1534
dist_to_merge_behind = get_traci_distance(
1535
vehicles.get_id_sumo(id_veh_behind), id_edge_mergeout_sumo, 3.0)
1536
dist_to_merge_infront = get_traci_distance(
1537
vehicles.get_id_sumo(id_veh_infront), id_edge_mergeout_sumo, 3.0)
1538
if debug:
1539
print ' now let the vehicle behind %d, d=%.2f' % (id_veh_behind, dist_to_merge_behind), 'see the vehicle in front %d, d=%.2f' % (id_veh_infront, dist_to_merge_infront)
1540
1541
vehicles.add_ghost(id_veh_behind, id_veh_tail, dist_to_merge_behind, dist_to_merge_infront)
1542
if debug > 0:
1543
print ' check ghosts of behind prt.%d:' % id_veh_behind, vehicles.ids_ghosts[id_veh_behind]
1544
1545
# remove any possible ghosts from this vehicle to vehicles behind
1546
# this can happen if this vehicle passed by its ghost vehicle
1547
# should no longer happen
1548
# vehicles.del_ghosts(id_veh)
1549
if debug > 0:
1550
print ' check ghosts of prt.%d (no ghosts from this merge?):' % id_veh, vehicles.ids_ghosts[id_veh]
1551
1552
self.ids_vehs_merged[id_merge_from].pop(ind_pos) # remove(id_veh)
1553
self.ids_vehs_merged_sumo[id_merge_from].pop(ind_pos) # remove(id_veh_sumo)
1554
self.lineinds_vehs_merged[id_merge_from].pop(ind_pos)
1555
self.odos_vehs_merged[id_merge_from].pop(ind_pos)
1556
1557
# remove vehicle from line buffers
1558
if lineind == 1:
1559
# vehicle in main line
1560
self.ids_vehs_in1[id_merge_from].remove(id_veh) # pop()
1561
self.ids_vehs_in1_sumo[id_merge_from].remove(id_veh_sumo) # .pop()
1562
if self.are_entry[id_merge_from]:
1563
if debug:
1564
print ' vehicle is involved in entry merge processes?', self.vehicles_mains[id_merge_from].has_key(id_veh)
1565
1566
if self.vehicles_mains[id_merge_from].has_key(id_veh):
1567
if self.vehicles_entries[id_merge_from].has_key(id_veh):
1568
state_veh = self.vehicles_entries[id_merge_from][id_veh]
1569
if state.has_key('id_veh_infront'):
1570
id_veh_infront = state['id_veh_infront']
1571
id_veh_infront_sumo = vehicles.ids_sumo[id_veh_infront]
1572
id_veh_infront_sumo_eff, dist_eff = getLeader(id_veh_infront_sumo)
1573
print ' should have this veh in front:', id_veh_infront_sumo, 'leader', id_veh_infront_sumo_eff, 'd=%.1fm' % dist_eff
1574
if id_veh_infront_sumo_eff != id_veh_infront_sumo:
1575
print 'ERROR: faled merge of ', id_veh_sumo, 'exiting merge', id_merge_from
1576
sys.exit(1)
1577
#
1578
#id_veh_entry = self.vehicles_mains[id_merge_from][id_veh]
1579
1580
# TODO: this is still a lousy method, vehicles_mains neds to be improved
1581
for id_veh_entry, state in zip(self.vehicles_entries[id_merge_from].keys(), self.vehicles_entries[id_merge_from].values()):
1582
#state = self.vehicles_entries[id_merge_from][id_veh_entry]
1583
# if debug:
1584
# print ' state before',state
1585
if state.has_key('id_veh_infront'):
1586
if state['id_veh_infront'] == id_veh:
1587
del state['id_veh_infront']
1588
if state.has_key('id_veh_behind'):
1589
if state['id_veh_behind'] == id_veh:
1590
del state['id_veh_behind']
1591
# if debug:
1592
# print ' state after',state
1593
1594
del self.vehicles_mains[id_merge_from][id_veh]
1595
1596
if lineind == 2:
1597
# vehicle in entry line
1598
self.ids_vehs_in2[id_merge_from].remove(id_veh) # .pop()
1599
self.ids_vehs_in2_sumo[id_merge_from].remove(id_veh_sumo) # .pop()
1600
1601
if self.are_entry[id_merge_from]:
1602
if debug:
1603
print ' del veh prt.%s from vehicles_entries' % id_veh
1604
del self.vehicles_entries[id_merge_from][id_veh]
1605
else:
1606
pass
1607
1608
# remove from centralized database
1609
#del self.vehicle_to_merge[id_veh]
1610
1611
else:
1612
# the entered vehicle is not in a merge queue
1613
# probably a new vehicle at station
1614
1615
# just be sure that the vehicle is not in any queue
1616
# but actually this cannot happen
1617
if id_veh in self.ids_vehs_in1[id_merge_from]:
1618
print 'WARNING in exit_veh: new veh %d should not be in inqueue 1' % id_veh
1619
self.ids_vehs_in1[id_merge_from].remove(id_veh)
1620
self.ids_vehs_in1_sumo[id_merge_from].remove(id_veh_sumo)
1621
1622
if id_veh in self.ids_vehs_in2[id_merge_from]:
1623
print 'WARNING in exit_veh: new veh %d should not be in inqueue 2' % id_veh
1624
self.ids_vehs_in2[id_merge_from].remove(id_veh)
1625
self.ids_vehs_in2_sumo[id_merge_from].remove(id_veh_sumo)
1626
1627
# if self.vehicle_to_merge.has_key(id_veh):
1628
# del self.vehicle_to_merge[id_veh]
1629
1630
if is_remove_from_control:
1631
# remove any merge control operations
1632
vehicles.del_all_ghosts(id_veh)
1633
1634
def exit_veh_forced(self, id_veh, id_veh_sumo, vehicles):
1635
"""Used by decompressors to remove a vehicle from merge control"""
1636
if self.vehicle_to_merge.has_key(id_veh):
1637
# exit vehicle from respective merge
1638
self.exit_veh(id_veh, id_veh_sumo, self.vehicle_to_merge[id_veh], vehicles, is_remove_from_control=True)
1639
else:
1640
# id_veh not under any merge conrol
1641
pass
1642
1643
def print_vehs(self, id_veh1, id_veh2, dist1_min, dist1_max, dist2_min, dist2_max,
1644
lineind1, lineind2, pos_max=79):
1645
dist_max = max(dist1_min, dist1_max, dist2_min, dist2_max)+1
1646
#dist_min = min(dist1_min, dist1_max, dist2_min, dist2_max)
1647
#dist_diff = dist_max-dist_min+10.0
1648
print 'print_vehs id_veh1', id_veh1, 'id_veh2', id_veh2
1649
# print ' dist1_min',dist1_min,'dist1_max',dist1_max
1650
# print ' dist2_min',dist2_min,'dist2_max',dist2_max
1651
# print ' min[dist1_min, dist1_max, dist2_min, dist2_max]>0.01',np.min([dist1_min, dist1_max, dist2_min, dist2_max])>0.01
1652
if np.min([dist1_min, dist1_max, dist2_min, dist2_max]) > 0.01:
1653
f = float(pos_max)/dist_max
1654
# print ' f',f
1655
print '________________________'
1656
print 'vehicle %s from line %d: %.f--%2f' % (id_veh1, lineind1, dist1_min, dist1_max)
1657
pos_min = int(dist1_min*f)
1658
pos_max = int(dist1_max*f)
1659
print max(pos_min-1, 0)*' '+'<'+(pos_max-pos_min)*'X'+'|'
1660
1661
pos_min = int(dist2_min*f)
1662
pos_max = int(dist2_max*f)
1663
# print ' pos_min',pos_min
1664
# print ' pos_max',pos_max
1665
# print ' max(pos_min-1,0)',max(pos_min-1,0),'(pos_max-pos_min)',(pos_max-pos_min)
1666
print max(pos_min-1, 0)*' '+'<'+(pos_max-pos_min)*'X'+'|'
1667
print 'vehicle %s from line %d: %.f--%2f' % (id_veh2, lineind2, dist2_min, dist2_max)
1668
print '________________________'
1669
else:
1670
print 'WARNING: some negative distances:'
1671
print 'vehicle %s from line %d: %.f--%2f' % (id_veh1, lineind1, dist1_min, dist1_max)
1672
print 'vehicle %s from line %d: %.f--%2f' % (id_veh2, lineind2, dist2_min, dist2_max)
1673
1674
def enter_veh(self, id_veh, id_veh_sumo, id_merge_from, id_merge_to, id_edge_merge_sumo, vehicles, debug=0):
1675
print 'enter_veh id_veh %s, id_merge_from %d to id_merge_to %d' % (id_veh_sumo, id_merge_from, id_merge_to)
1676
1677
# in id_merge_from: take vehicle out of merged queue and input queue
1678
1679
# put vehicle in centralized database
1680
self.vehicle_to_merge[id_veh] = id_merge_to
1681
1682
# on which input line of merge id_merge_to does the vehicle approach?
1683
if id_veh in self.ids_vehs_merged[id_merge_to]:
1684
# vehicle is in merge queue and input line can be retrived from it
1685
indpos = self.ids_vehs_merged[id_merge_to].index(id_veh)
1686
1687
# on which input line is the vehicle at position index indpos
1688
lineind = self.lineinds_vehs_merged[id_merge_to][indpos]
1689
1690
elif self.ids_node_to_ids_merge[self.ids_node_in1[id_merge_to]] == id_merge_from:
1691
# vehicle not in merge queue, detect input line 1 with nodes db
1692
indpos = -1
1693
lineind = 1
1694
else:
1695
# vehicle not in merge queue, detect input line 2 with nodes db
1696
indpos = -1
1697
lineind = 2
1698
1699
if lineind == 1:
1700
# from line 1
1701
self.ids_vehs_in1[id_merge_to].append(id_veh)
1702
self.ids_vehs_in1_sumo[id_merge_to].append(id_veh_sumo)
1703
dist_tomerge_head_new = self.distances_node_in1[id_merge_to] - traci.vehicle.getLanePosition(id_veh_sumo)
1704
1705
elif lineind == 2:
1706
self.ids_vehs_in2[id_merge_to].append(id_veh)
1707
self.ids_vehs_in2_sumo[id_merge_to].append(id_veh_sumo)
1708
dist_tomerge_head_new = self.distances_node_in2[id_merge_to]-traci.vehicle.getLanePosition(id_veh_sumo)
1709
1710
if indpos == -1:
1711
# vehicle is new and must be merged into ids_vehs_merged
1712
print ' merge prt.%d' % id_veh, 'lineind', lineind, 'dtm %.1fm' % dist_tomerge_head_new, 'n_plat', vehicles.get_platoonsize(id_veh), vehicles.lengths_plat[id_veh]/vehicles.length
1713
1714
ids_vehs_merged = self.ids_vehs_merged[id_merge_to]
1715
ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge_to]
1716
lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge_to]
1717
odos_veh_merged = self.odos_vehs_merged[id_merge_to]
1718
#id_edge_merge_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_to]
1719
ind_insert = len(ids_vehs_merged)
1720
is_insert = False
1721
id_veh_merged = -1
1722
if debug > 0:
1723
print ' ids_vehs_merged_sumo[%d]' % id_merge_to, ids_vehs_merged_sumo
1724
print ' lineinds_vehs_merged[%d]' % id_merge_to, lineinds_vehs_merged
1725
if (ind_insert == 0) | self.are_station[id_merge_to]:
1726
if debug > 0:
1727
print ' new vehicle is the only vehicle or station', ind_insert, self.are_station[id_merge_to]
1728
1729
# vehicles heading toward a station merge are not
1730
# really merged because only one incoming line
1731
ids_vehs_merged.append(id_veh)
1732
ids_vehs_merged_sumo.append(id_veh_sumo)
1733
lineinds_vehs_merged.append(lineind)
1734
odos_veh_merged.append(get_traci_odo(id_veh_sumo))
1735
1736
elif ind_insert > 0: # there is at least another vehicle
1737
# slower, but more precise than self.distances_node_inX[id_merge_to]
1738
id_veh_tail_new = vehicles.get_platoontail(id_veh)
1739
id_veh_tail_new_sumo = vehicles.ids_sumo[id_veh_tail_new]
1740
1741
if debug > 0:
1742
dist_tomerge_head_new2 = get_traci_distance(id_veh_sumo, id_edge_merge_sumo, 3.0)
1743
print ' compare dist_tomerge_head_new', dist_tomerge_head_new, 'dist_tomerge_head_new2', dist_tomerge_head_new2
1744
1745
# get back to traci distance measurement
1746
dist_tomerge_head_new = get_traci_distance(id_veh_sumo, id_edge_merge_sumo, 3.0)
1747
1748
#dist_tomerge_tail_new = dist_tomerge_head_new-0.5/ get_traci_velocity(id_veh_sumo)**2+vehicles.lengths_plat[id_veh]
1749
dist_tomerge_tail_new = dist_tomerge_head_new+vehicles.lengths_plat[id_veh]+vehicles.length
1750
1751
#dist_tomerge_tail_new = dist_tomerge_head_new+vehicles.get_platoonsize(id_veh)*vehicles.get_length()
1752
#dist_tomerge_tail_new = get_traci_distance(id_veh_tail_new_sumo, id_edge_merge_sumo, 3.0)
1753
1754
if debug > 0:
1755
print ' new prt.%d arriving from in %d at dist head %.2f /__| tail prt.%d %.2fm' % (id_veh, lineind, dist_tomerge_head_new, id_veh_tail_new, dist_tomerge_tail_new)
1756
print ' ids_vehs_merged_sumo', ids_vehs_merged_sumo
1757
for id_veh_merged, id_veh_merged_sumo, odo, lineind_merge in zip(ids_vehs_merged[::-1], ids_vehs_merged_sumo[::-1], odos_veh_merged[::-1], lineinds_vehs_merged[::-1]):
1758
if debug > 0:
1759
print ' id_veh_merged_sumo', id_veh_merged_sumo
1760
# unprecise
1761
#dist_tomerge_head2 = get_traci_distance(id_veh_merged_sumo, id_edge_merge_sumo, 3.0)
1762
1763
if lineind_merge == 1:
1764
dist_tomerge_head = self.distances_node_in1[id_merge_to] - \
1765
(get_traci_odo(id_veh_merged_sumo)-odo)
1766
else:
1767
dist_tomerge_head = self.distances_node_in2[id_merge_to] - \
1768
(get_traci_odo(id_veh_merged_sumo)-odo)
1769
1770
if debug > 0:
1771
dist_tomerge_head2 = get_traci_distance(id_veh_merged_sumo, id_edge_merge_sumo, 3.0)
1772
print ' compare', id_veh_merged_sumo, ' dist_tomerge_head %.1f' % dist_tomerge_head, 'dist_tomerge_head2 %.1f' % dist_tomerge_head2
1773
1774
# get back to traci distance measurement
1775
dist_tomerge_head = get_traci_distance(id_veh_merged_sumo, id_edge_merge_sumo, 3.0)
1776
if lineind_merge == 1:
1777
dist_node = self.distances_node_in1[id_merge_to]
1778
else:
1779
dist_node = self.distances_node_in2[id_merge_to]
1780
if debug > 0:
1781
print ' M:odo_enter=%.1f odo=%.1f delta=%.f dist_node=%.1f line%d platl=%d' % (odo, get_traci_odo(id_veh_merged_sumo), get_traci_odo(id_veh_merged_sumo)-odo, dist_node, lineind_merge, vehicles.lengths_plat[id_veh_merged])
1782
1783
#stoppeddist_tomerge = dist-0.5/self.decel*get_traci_velocity(id_veh_merged_sumo)**2+vehicles.lengths_plat[id_veh]
1784
#stoppeddist_tomerge = dist+vehicles.lengths_plat[id_veh]
1785
id_veh_tail = vehicles.get_platoontail(id_veh_merged)
1786
id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
1787
1788
#dist_tomerge_tail = dist_tomerge_head +vehicles.get_platoonsize(id_veh_merged)*vehicles.get_length()
1789
dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_merge_sumo, 3.0)
1790
#dist_tomerge_tail = dist_tomerge_head + vehicles.lengths_plat[id_veh_merged]+vehicles.length
1791
if debug > 0:
1792
print ' compare lineind_merge', lineind_merge, '=?', lineinds_vehs_merged[ind_insert-1]
1793
1794
if debug > 0:
1795
self.print_vehs(id_veh, id_veh_merged,
1796
dist_tomerge_head_new, dist_tomerge_tail_new,
1797
dist_tomerge_head, dist_tomerge_tail,
1798
lineind, lineinds_vehs_merged[ind_insert-1])
1799
# print ' check veh %d arriving from in %d at dist head %.2f /__| tail %.2fm'%(id_veh,lineind,dist_tomerge_head_new,dist_tomerge_tail_new)
1800
# print ' check veh %d, d %.2fm, d_new %.2fm, ind_insert = %d'%(id_veh_merged,dist,dist_tomerge_head_new,ind_insert)
1801
# print ' ds %.2fm, ds_new %.2fm, v %.2f, v_new =%.2fm, '%(stoppeddist_tomerge,dist_tomerge_tail_new,get_traci_velocity(id_veh_merged_sumo),get_traci_velocity(id_veh_sumo),)
1802
# print ' tail veh %d, ds %.2fm'%(id_veh_tail,dist_tomerge_tail)
1803
1804
if lineind == lineinds_vehs_merged[ind_insert-1]: # get this from
1805
if debug > 0:
1806
print ' vehicle in front on same branch'
1807
is_insert = True
1808
break
1809
1810
if dist_tomerge_tail_new > dist_tomerge_tail:
1811
if debug > 0:
1812
print ' distance of tail to merge of new vehicle is greater than existing'
1813
# print ' =>insert new %s after existing %s'%(id_veh_sumo,id_veh_merged_sumo)
1814
is_insert = True
1815
break
1816
dist_last = dist_tomerge_head
1817
ind_insert -= 1
1818
1819
if is_insert:
1820
# at least one vehicle is in front
1821
if debug > 0:
1822
print ' insert veh %d behind veh %d, index %d' % (id_veh, id_veh_merged, ind_insert)
1823
# send control info to involved vehicles
1824
if ind_insert == len(ids_vehs_merged):
1825
if debug > 0:
1826
print ' appended vehicle after veh', id_veh_tail_sumo, 'with leader', ids_vehs_merged_sumo[ind_insert-1], 'dtm=%.2fm' % dist_tomerge_tail
1827
# V
1828
# |
1829
# G ind_insert-1
1830
1831
# is vehicle and ghost in the same input line?
1832
if lineinds_vehs_merged[ind_insert-1] != lineind:
1833
# id_ghost = ids_vehs_merged[ind_insert-1]# last veh in queue
1834
#vehicles.add_ghost(id_veh, id_ghost, dist_tomerge_head_new, dist)
1835
1836
vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge_head_new, dist_tomerge_tail)
1837
1838
elif ind_insert > 0:
1839
# there is at least 1 other veh in front
1840
1841
# G1
1842
# |
1843
# V
1844
# |
1845
# G2
1846
id_ghost1 = ids_vehs_merged[ind_insert]
1847
#id_ghost2 = ids_vehs_merged[ind_insert-1]
1848
id_ghost2 = id_veh_tail
1849
if debug > 0:
1850
print ' vehicle will be inserted in front of', ids_vehs_merged_sumo[ind_insert], 'and in behind', id_veh_tail_sumo, 'with leader', ids_vehs_merged_sumo[ind_insert-1], 'dtm=%.2fm' % dist_tomerge_tail
1851
1852
vehicles.del_ghost(id_ghost1, id_ghost2)
1853
if lineinds_vehs_merged[ind_insert] != lineind:
1854
vehicles.add_ghost(id_ghost1, id_veh_tail_new, dist_last, dist_tomerge_tail_new)
1855
1856
if lineinds_vehs_merged[ind_insert-1] != lineind:
1857
#vehicles.add_ghost(id_veh, id_ghost2, dist_tomerge_head_new, dist)
1858
vehicles.add_ghost(id_veh, id_ghost2, dist_tomerge_head_new, dist_tomerge_tail)
1859
1860
else:
1861
if debug > 0:
1862
print ' prepend prt.%d in front of prt.%d, first index %d' % (id_veh, id_veh_merged, ind_insert)
1863
# is vehicle and ghost in the same input line?
1864
if lineinds_vehs_merged[ind_insert] != lineind:
1865
id_veh_behind = ids_vehs_merged[ind_insert] # last veh in queue
1866
vehicles.add_ghost(id_veh_behind, id_veh_tail_new, dist_tomerge_head, dist_tomerge_tail_new)
1867
1868
# finally insert vehicle in merge queue
1869
ids_vehs_merged.insert(ind_insert, id_veh)
1870
ids_vehs_merged_sumo.insert(ind_insert, id_veh_sumo)
1871
lineinds_vehs_merged.insert(ind_insert, lineind)
1872
odos_veh_merged.insert(ind_insert, get_traci_odo(id_veh_sumo))
1873
1874
# inform downstream merges
1875
1876
# else:
1877
# # new vehicle is the only vehicle
1878
# ids_vehs_merged[0] = id_veh
1879
# ids_vehs_merged_sumo[0] = id_veh_sumo
1880
# lineinds_vehs_merged[0] = lineind
1881
1882
def enter_veh_entry(self, id_veh, id_veh_sumo, id_merge_from, id_merge_to, id_edge_merge_sumo, vehicles, debug=0):
1883
print 'enter_veh_entry id_veh %s, id_merge_from %d to id_merge_to %d' % (id_veh_sumo, id_merge_from, id_merge_to)
1884
1885
# in id_merge_from: take vehicle out of merged queue and input queue
1886
1887
# put vehicle in centralized database
1888
self.vehicle_to_merge[id_veh] = id_merge_to
1889
1890
# on which input line of merge id_merge_to does the vehicle approach?
1891
if id_veh in self.ids_vehs_merged[id_merge_to]:
1892
# vehicle is in merge queue and input line can be retrived from it
1893
indpos = self.ids_vehs_merged[id_merge_to].index(id_veh)
1894
1895
# on which input line is the vehicle at position index indpos
1896
lineind = self.lineinds_vehs_merged[id_merge_to][indpos]
1897
1898
elif self.ids_node_to_ids_merge[self.ids_node_in1[id_merge_to]] == id_merge_from:
1899
# vehicle not in merge queue, detect input line 1 with nodes db
1900
indpos = -1
1901
lineind = 1
1902
else:
1903
# vehicle not in merge queue, detect input line 2 with nodes db
1904
indpos = -1
1905
lineind = 2
1906
1907
# put vehicle in respective line queue
1908
ids_vehs_merged = self.ids_vehs_merged[id_merge_to]
1909
ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge_to]
1910
lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge_to]
1911
odos_veh_merged = self.odos_vehs_merged[id_merge_to]
1912
1913
if lineind == 1:
1914
# from line 1 (main line)
1915
if debug > 0:
1916
print ' Detected veh', id_veh_sumo, 'on mainline. Is new', indpos == -1
1917
print ' check for platooned vehicles:', vehicles.get_platoon(id_veh)
1918
1919
id_edge_out_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_to]
1920
dist_tomerge = get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)
1921
ids_vehs_in1 = self.ids_vehs_in1[id_merge_to]
1922
if len(ids_vehs_in1) > 0:
1923
id_veh1_last = self.ids_vehs_in1[id_merge_to][-1]
1924
else:
1925
id_veh1_last = -1
1926
1927
id_veh2, state2 = self.get_mergeveh_entry(id_merge_to, debug)
1928
if debug > 0:
1929
print ' Conflict vehicle from entry line: prt.%d state' % (id_veh2,), state2
1930
print ' Main line: ids_vehs_in1', ids_vehs_in1
1931
print ' id_veh1_last', id_veh1_last
1932
print ' dist_tomerge', dist_tomerge
1933
1934
if id_veh2 == -1:
1935
if debug > 0:
1936
print ' no vehicle to merge'
1937
1938
if id_veh1_last != -1:
1939
if debug > 0:
1940
print ' control distance to last vehicle in main...by SUMO'
1941
pass
1942
#
1943
#id_veh_tail = vehicles.get_platoontail(id_veh1_last)
1944
#id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
1945
#dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)
1946
#vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge, dist_tomerge_tail)
1947
1948
# let SUMO do the distances
1949
1950
else:
1951
if debug > 0:
1952
print ' merge is empty'
1953
pass
1954
1955
elif state2['status'] != 'wait':
1956
# there is an approaching vehicle on entry line
1957
if state2['status'] == 'accelerate':
1958
if debug > 0:
1959
print ' conflict vehicle in acceleration mode', 'is veh behind', state2.has_key('id_veh_behind')
1960
if state2.has_key('id_veh_behind'):
1961
# accelerating vehicle has already a vehicle
1962
# in front of which to merge
1963
# => look at last vehicle
1964
1965
# let SUMO do the distances
1966
pass
1967
1968
else:
1969
# let the entering vehicle see the new vehicle
1970
state2['id_veh_behind'] = id_veh
1971
1972
if state2['status'] == 'sync':
1973
if debug > 0:
1974
print ' conflict vehicle in sync mode'
1975
if state2.has_key('id_veh_behind'):
1976
# accelerating vehicle has already a vehicle
1977
# in front of which to merge
1978
# => look at last vehicle
1979
1980
# let SUMO do the distances
1981
pass
1982
1983
else:
1984
# speed is already synchonized, but has not yet
1985
# a vehicle behind
1986
1987
id_veh_tail = vehicles.get_platoontail(id_veh2)
1988
id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
1989
dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)
1990
print ' let look the new vehicle prt.%d look at the tail of the entering vehicle prt.%d' % (id_veh, id_veh_tail)
1991
vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge, dist_tomerge_tail)
1992
1993
# let the entering vehicle see the new vehicle
1994
state2['id_veh_behind'] = id_veh
1995
1996
self.ids_vehs_in1[id_merge_to].append(id_veh)
1997
self.ids_vehs_in1_sumo[id_merge_to].append(id_veh_sumo)
1998
1999
# append to main merge queue
2000
ids_vehs_merged.append(id_veh)
2001
ids_vehs_merged_sumo.append(id_veh_sumo)
2002
lineinds_vehs_merged.append(lineind)
2003
odos_veh_merged.append(get_traci_odo(id_veh_sumo))
2004
2005
elif lineind == 2:
2006
# from line 2 (entry line)
2007
print ' Detected veh', id_veh_sumo, 'on entry line. Is new', indpos == -1
2008
2009
self.ids_vehs_in2[id_merge_to].append(id_veh)
2010
self.ids_vehs_in2_sumo[id_merge_to].append(id_veh_sumo)
2011
2012
print ' command vehicle to stop and wait further instructions'
2013
#vehicles.control_slow_down(id_veh, speed = 6.0/3.6)
2014
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
2015
# print ' set speed to',traci.vehicle.getMaxSpeed(id_veh_sumo)
2016
#traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0)
2017
2018
vehicles.control_stop(id_veh)
2019
2020
# prevent SUMO from reaccelerating vehicle
2021
# vehicles.switch_off_control(id_veh)
2022
print ' set veh id_veh prt.%d' % id_veh
2023
self.vehicles_entries[id_merge_to][id_veh] = {'status': 'wait'}
2024
print ' vehicles_entries[', id_merge_to, ']=', self.vehicles_entries[id_merge_to]
2025
#
2026
# self.vehicles_mains[id_merge_to][id_veh] = {}# later when used
2027
2028
# Attention: Vehicle on entry line not yet in queue.
2029
# this needs to be fixed later when it becomes clear where to insert
2030
# ids_vehs_merged.append(id_veh)
2031
# ids_vehs_merged_sumo.append(id_veh_sumo)
2032
# lineinds_vehs_merged.append(lineind)
2033
2034
def get_mergeveh_entry(self, id_merge, debug):
2035
"""Returns ID and state of vehicle that is about to merege from
2036
the entry line. ID is -1 if no vehicle starts.
2037
"""
2038
2039
vehicles_entries = self.vehicles_entries[id_merge]
2040
if debug > 0:
2041
print 'get_mergeveh_entry vehicles_entries', vehicles_entries
2042
if len(vehicles_entries) == 0:
2043
return -1, {'status': 'wait'}
2044
else:
2045
return vehicles_entries.keys()[0], vehicles_entries.values()[0]
2046
2047
def process_step_entry(self, id_merge, vehicles, debug):
2048
print 'process_step_entry id_merge', id_merge
2049
2050
#self.vehicles_entries[id_merge]= OrderedDict()
2051
# self.vehicles_mains[id_merge] = OrderedDict()
2052
id_veh_del = -1
2053
2054
# for id_veh, state in zip(self.vehicles_entries[id_merge].keys()[::-1],self.vehicles_entries[id_merge].values()[::-1]):
2055
# for id_veh, state in self.vehicles_entries.iteritems():
2056
# for id_veh, state in zip(self.vehicles_entries[id_merge].keys(),self.vehicles_entries[id_merge].values()):
2057
ids_veh_entry = self.vehicles_entries[id_merge].keys()
2058
states_veh_entry = self.vehicles_entries[id_merge].values()
2059
id_edge_out_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge]
2060
ids_veh_in1 = self.ids_vehs_in1[id_merge]
2061
time_update = self.time_update.get_value()
2062
2063
if debug:
2064
print ' vehicles_entries=', self.vehicles_entries[id_merge]
2065
print ' vehicles_mains', self.vehicles_mains[id_merge]
2066
print ' ids_veh_in1', ids_veh_in1
2067
2068
i = 0
2069
#is_cont = len(ids_veh_entry)>0
2070
# while is_cont:
2071
if len(ids_veh_entry) > 0:
2072
id_veh = ids_veh_entry[0]
2073
id_veh_sumo = vehicles.get_id_sumo(id_veh)
2074
state = states_veh_entry[0]
2075
2076
ids_vehs_merged = self.ids_vehs_merged[id_merge]
2077
ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge]
2078
lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge]
2079
odos_veh_merged = self.odos_vehs_merged[id_merge]
2080
if debug:
2081
print ' check id_veh_sumo', id_veh_sumo, 'status', state['status'], 'n vehs on main', len(ids_veh_in1)
2082
if state['status'] == 'wait':
2083
if traci.vehicle.isStopped(id_veh_sumo):
2084
# check potential conflict vehicle on main line
2085
2086
n1 = len(ids_veh_in1)
2087
if n1 == 0:
2088
if debug:
2089
print ' main line is empty => accelerate immediately'
2090
for id_veh_plat in vehicles.get_platoon(id_veh):
2091
vehicles.control_speedup(id_veh_plat)
2092
state['status'] = 'accelerate'
2093
2094
ids_vehs_merged.append(id_veh)
2095
ids_vehs_merged_sumo.append(id_veh_sumo)
2096
lineinds_vehs_merged.append(2)
2097
odos_veh_merged.append(get_traci_odo(id_veh_sumo))
2098
2099
else:
2100
ids_veh_in1_sumo = self.ids_vehs_in1_sumo[id_merge]
2101
vehicles_main = self.vehicles_mains[id_merge]
2102
dist_in1 = self.distances_node_in1[id_merge]
2103
dist_in2 = self.distances_node_in2[id_merge]
2104
2105
i = 0 # n1-1
2106
is_found = False
2107
while (i < n1) & (not is_found):
2108
id_veh1_sumo = ids_veh_in1_sumo[i]
2109
id_veh1 = ids_veh_in1[i]
2110
if debug:
2111
print ' check', id_veh1_sumo, 'free', id_veh1 not in vehicles_main
2112
2113
if True: # id_veh1 not in vehicles_main:
2114
2115
# get tail position of id_veh_main
2116
id_veh1_tail = vehicles.get_platoontail(id_veh1)
2117
id_veh1_tail_sumo = vehicles.ids_sumo[id_veh1_tail]
2118
pos1 = dist_in1-get_traci_distance(id_veh1_sumo, id_edge_out_sumo, 3.0)
2119
pos1_tail = dist_in1-get_traci_distance(id_veh1_tail_sumo, id_edge_out_sumo, 3.0)
2120
pos2 = dist_in2 - get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)
2121
p_from, p_to = self.get_pos_crit_entry(pos2,
2122
vehicles.lengths_plat[id_veh],
2123
get_traci_velocity(id_veh1_sumo),
2124
dist_in1, dist_in2,
2125
vehicles)
2126
if debug:
2127
print ' potential veh %s (tail %s)' % (id_veh1_sumo, id_veh1_tail_sumo), 'at pos1_tail=%.1f>p_to=%.1f' % (pos1_tail, p_to), pos1_tail > p_to
2128
2129
# here we check whether the tail of the vehicle on the main line
2130
# has passed the critical point p_to
2131
2132
if pos1_tail > p_to:
2133
2134
if i == n1-1: # last vehicle on main
2135
if debug:
2136
print ' insert id_veh', id_veh_sumo, 'behind id_veh1', id_veh1_sumo, 'the only veh on main'
2137
state['id_veh_infront'] = id_veh1
2138
if vehicles_main.has_key(id_veh1):
2139
vehicles_main[id_veh1]['id_veh_behind'] = id_veh
2140
else:
2141
vehicles_main[id_veh1] = {'id_veh_behind': id_veh}
2142
is_found = True
2143
ids_vehs_merged.append(id_veh)
2144
ids_vehs_merged_sumo.append(id_veh_sumo)
2145
lineinds_vehs_merged.append(2)
2146
odos_veh_merged.append(get_traci_odo(id_veh_sumo))
2147
2148
elif i < n1-1: # there are others behind on main
2149
# ensure that gap is big enough
2150
id_veh_behind = ids_veh_in1[i+1]
2151
id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]
2152
pos1 = dist_in1 - get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)
2153
if debug:
2154
print ' vehicle behind', id_veh_behind_sumo, 'pos=%.1f, p_from=%.1f' % (pos1, p_from), 'ok', pos1 < p_from
2155
if pos1 < p_from:
2156
state['id_veh_infront'] = id_veh1
2157
state['id_veh_behind'] = id_veh_behind
2158
2159
#vehicles_main[id_veh_behind] = id_veh
2160
if vehicles_main.has_key(id_veh1):
2161
vehicles_main[id_veh1]['id_veh_behind'] = id_veh
2162
else:
2163
vehicles_main[id_veh1] = {'id_veh_behind': id_veh}
2164
#vehicles_main[id_veh1] = id_veh
2165
if vehicles_main.has_key(id_veh_behind):
2166
vehicles_main[id_veh_behind]['id_veh_infront'] = id_veh
2167
else:
2168
vehicles_main[id_veh_behind] = {'id_veh_infront': id_veh}
2169
2170
is_found = True
2171
j = ids_vehs_merged.index(id_veh1)+1
2172
if debug:
2173
print ' j=', j
2174
ids_vehs_merged.insert(j, id_veh)
2175
ids_vehs_merged_sumo.insert(j, id_veh_sumo)
2176
lineinds_vehs_merged.insert(j, 2)
2177
odos_veh_merged.insert(j, get_traci_odo(id_veh_sumo))
2178
2179
# here we check whether the vehicle on the main line
2180
# has not yet reached the critical point p_from
2181
elif pos1 < p_from:
2182
if i == 0: # first vehicle on main
2183
if debug:
2184
print ' insert id_veh', id_veh_sumo, 'in front of id_veh1', id_veh1_sumo, 'the only veh on main'
2185
state['id_veh_behind'] = id_veh1
2186
#vehicles_main[id_veh1] = id_veh
2187
if vehicles_main.has_key(id_veh1):
2188
vehicles_main[id_veh1]['id_veh_infront'] = id_veh
2189
else:
2190
vehicles_main[id_veh1] = {'id_veh_infront': id_veh}
2191
is_found = True
2192
# determine insert position
2193
j = ids_vehs_merged.index(id_veh1)
2194
# if debug:
2195
# print ' j=',j
2196
ids_vehs_merged.insert(j, id_veh)
2197
ids_vehs_merged_sumo.insert(j, id_veh_sumo)
2198
lineinds_vehs_merged.insert(j, 2)
2199
odos_veh_merged.insert(j, get_traci_odo(id_veh_sumo))
2200
if debug:
2201
print ' ids_vehs_merged_sumo', ids_vehs_merged_sumo
2202
# elif i < n1-1: # there are others behind on main
2203
# # ensure that gap is big enough
2204
# id_veh_behind = ids_veh_in1[i+1]
2205
# id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]
2206
# pos1 = dist_in1 - get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)
2207
# print ' vehicle behind',id_veh_behind_sumo,'pos=%.1f, p_from=%.1f'%(pos1,p_from),'ok',pos1<p_from
2208
# if pos1<p_from:
2209
# state['id_veh_infront'] = id_veh1
2210
# state['id_veh_behind'] = id_veh_behind
2211
# is_found = True
2212
2213
i += 1
2214
2215
if is_found:
2216
if debug:
2217
print ' suitable vehicle after which entry vehicle can run has been found'
2218
# Note: if no vehicle has been found then
2219
# nothing will happen and the vehicle will
2220
# wait until the righ moment has arrived
2221
for id_veh_plat in vehicles.get_platoon(id_veh):
2222
vehicles.control_speedup(id_veh_plat)
2223
state['status'] = 'accelerate'
2224
2225
elif state['status'] == 'accelerate':
2226
# test if speed reached
2227
if traci.vehicle.getSpeed(id_veh_sumo) > 0.9*vehicles.speed_max.get_value():
2228
if debug > 0:
2229
print ' synchronization reached for veh', id_veh_sumo
2230
state['status'] = 'sync'
2231
#id_veh_del = id_veh
2232
# now create ghosts
2233
# id_veh -> id_veh_infront_tail:
2234
if state.has_key('id_veh_infront'):
2235
id_veh_in_front = state['id_veh_infront']
2236
id_veh_infront_tail = vehicles.get_platoontail(id_veh_in_front)
2237
id_veh_infront_tail_sumo = vehicles.ids_sumo[id_veh_infront_tail]
2238
dist_tomerge = get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)
2239
dist_tomerge_tail = get_traci_distance(id_veh_infront_tail_sumo, id_edge_out_sumo, 3.0)
2240
2241
if debug > 0:
2242
print ' add ghost to entering veh', id_veh_sumo, ' behind', id_veh_infront_tail_sumo, 'with leader', id_veh_in_front
2243
vehicles.add_ghost(id_veh, id_veh_infront_tail, dist_tomerge,
2244
dist_tomerge_tail, is_substitute=True)
2245
2246
if state.has_key('id_veh_behind'):
2247
id_veh_behind = state['id_veh_behind']
2248
id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]
2249
2250
dist_tomerge_behind = get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)
2251
2252
id_veh_tail = vehicles.get_platoontail(id_veh)
2253
id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
2254
dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)
2255
2256
if debug > 0:
2257
print ' add ghost to mainline veh', id_veh_behind_sumo, ' behind', id_veh_tail_sumo, 'with leader', id_veh_sumo
2258
vehicles.add_ghost(id_veh_behind, id_veh_tail, dist_tomerge_behind,
2259
dist_tomerge_tail, is_substitute=True)
2260
2261
else:
2262
if 0:
2263
speed = traci.vehicle.getSpeed(id_veh_sumo)
2264
print ' sync of veh', id_veh_sumo, ',v=%.1f, not yet reached: %.2f' % (speed, speed/vehicles.speed_max.get_value())
2265
2266
if state.has_key('id_veh_behind'):
2267
id_veh_behind_sumo = vehicles.ids_sumo[state['id_veh_behind']]
2268
info = traci.vehicle.getLeader(id_veh_behind_sumo, dist=200.0)
2269
if (info is not None):
2270
# extract lead vehicle ID and distance from info
2271
id_leader_sumo, dist_leader = info
2272
#speed = vehicles.speed_max.get_value()
2273
speed = get_traci_velocity(id_veh_behind_sumo)
2274
dist_safe = vehicles.time_emergency.get_value()*speed + 0.5*speed**2/vehicles.decel_emergency.get_value()
2275
dist_target = 2*dist_safe+vehicles.lengths_plat[id_veh]
2276
# print ' behind',id_veh_behind_sumo,'with infront',id_leader_sumo,'at dist=%.2f'%dist_leader,'at ds=%.2f'%dist_safe,'is_brake',dist_leader<dist_target
2277
if dist_leader < dist_target:
2278
dv = time_update*vehicles.decel
2279
if (speed-dv) > 0:
2280
# print ' slowdown',id_veh_behind_sumo,'from speed %.2f to %.2f'%(speed,speed-dv)
2281
traci.vehicle.slowDown(id_veh_behind_sumo, speed-dv, time_update)
2282
else:
2283
dv = time_update*vehicles.decel
2284
# print ' accel',id_veh_behind_sumo,'from speed %.2f to %.2f'%(speed,speed+dv)
2285
traci.vehicle.slowDown(id_veh_behind_sumo, speed+dv, time_update)
2286
2287
elif state['status'] == 'sync':
2288
pass
2289
2290
# if id_veh_del > -1:
2291
# del self.vehicles_entries[id_merge][id_veh_del]
2292
2293
def get_pos_crit_entry(self, pos2, len_veh2, speed, dist1, dist2, vehicles):
2294
"""
2295
Returns critical position interval of vehicle-platoon on main line
2296
with respect to the starting position of a vehicle at entry line.
2297
The returned critical position interval(pos_from, pos_to), which should
2298
ideally be free of vehicles.
2299
pos_from refers to the position of the nose of a vehicle on the main line
2300
pos_to refers to the position of the tail of the platoon on the main line.
2301
2302
"""
2303
print 'get_pos_crit_entry pos2=%.1f, v=%.1f, d1=%.1f, d2=%.1f' % (pos2, speed, dist1, dist2)
2304
# see 191030
2305
decel_emergency = vehicles.decel_emergency.get_value()
2306
decel_comfort = vehicles.decel_comfort.get_value()
2307
time_emergency = vehicles.time_emergency.get_value()
2308
s2 = 0.5*speed**2/decel_comfort
2309
delta2 = dist2 - pos2 - s2
2310
2311
s1 = speed**2/decel_comfort
2312
s_safe = time_emergency*speed + 0.5*speed**2/decel_emergency
2313
p_to = dist1 - delta2 - s1 + s_safe
2314
p_from = p_to-len_veh2-2*s_safe
2315
# print ' delta2=%.1f, s2=%.1f, s1=%.1f, ss=%.1f, CI=(%.1f,%.1f)'%(delta2,s2,s1,s_safe,p_from,p_to)
2316
return p_from, p_to
2317
2318
def search_upstream_merge(self, id_edge_start, edges, lanes, id_prtmode, ids_mainline=set(), distances=None):
2319
"""
2320
Searches next upstream merge node.
2321
Returns id_node, length to node
2322
2323
"""
2324
print 'search_upstream_merge id_edge_start', id_edge_start
2325
length = distances[id_edge_start]
2326
print ' added id_edge', id_edge_start, 'dist', distances[id_edge_start], '=', length
2327
is_merge = False
2328
id_edge_platform = -1
2329
id_edge = id_edge_start
2330
while (not is_merge):
2331
ids_edge_incoming = edges.get_incoming(id_edge)
2332
2333
# print ' search id_edge,ids_edge_incoming',id_edge,ids_edge_incoming
2334
if len(ids_edge_incoming) == 2:
2335
#id_edge1, id_edge2 = ids_edge_to
2336
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_incoming]
2337
#al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)
2338
#al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)
2339
# print ' check: '
2340
# print ' id_edge1',ids_edge_incoming[0],'ids_lane1',ids_lane1,self.is_prt_only(ids_lane1, lanes)
2341
# print ' id_edge2',ids_edge_incoming[1],'ids_lane2',ids_lane2,self.is_prt_only(ids_lane2, lanes)
2342
if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
2343
# print ' 2 in, one out => it is a merge node'
2344
is_merge = True
2345
2346
elif len(ids_edge_incoming) == 1:
2347
ids_lane = edges.ids_lanes[ids_edge_incoming[0]]
2348
#al = lanes.get_accesslevel(ids_lane, id_prtmode)
2349
if self.is_prt_only(ids_lane, lanes) & (id_edge in ids_mainline):
2350
# print ' mainline input node
2351
is_merge = True
2352
2353
if self.is_platform(ids_lane, lanes):
2354
# print ' 1 in, with multiple access => it is a station output node'
2355
is_merge = True
2356
2357
if not is_merge:
2358
id_edge = ids_edge_incoming[0]
2359
length += distances[id_edge]
2360
print ' added id_edge', id_edge, 'dist', distances[id_edge], '=', length
2361
2362
# print ' id_edge,is_merge',id_edge,is_merge
2363
print ' found node', edges.ids_fromnode[id_edge]
2364
return edges.ids_fromnode[id_edge], length
2365
2366
def search_downstream_merges(self, id_edge_start, edges, lanes, id_prtmode, ids_sinkedge=set()):
2367
"""
2368
Searches next downstream merge nodes.
2369
Returns array of downstream merge node IDs
2370
2371
"""
2372
2373
ids_edge = set([id_edge_start])
2374
ids_mergenode = set()
2375
print 'search_downstream_merges id_edge_start', id_edge_start, 'is sinkedge', id_edge_start in ids_sinkedge
2376
2377
if id_edge_start in ids_sinkedge:
2378
return None # np.array([], dtype = np.int32)
2379
2380
is_cont = True
2381
#n_cont = 20
2382
while (len(ids_edge) > 0) & is_cont:
2383
# print ' len(ids_edge)',len(ids_edge),ids_edge
2384
ids_edge_new = set()
2385
2386
for id_edge in ids_edge:
2387
ids_edge_outgoing = edges.get_outgoing(id_edge)
2388
# print ' id_edge,ids_edge_outgoing',id_edge,ids_edge_outgoing
2389
for id_downedge in ids_edge_outgoing:
2390
ids_lane = edges.ids_lanes[id_downedge]
2391
if id_downedge in ids_sinkedge:
2392
# print ' sinkedge id_downedge',id_downedge
2393
pass
2394
2395
elif self.is_prt_only(ids_lane, lanes):
2396
ids_downedge_incoming = edges.get_incoming(id_downedge)
2397
# print ' id_downedge,ids_downedge_incoming',id_downedge,ids_downedge_incoming
2398
is_merge = False
2399
2400
if len(ids_downedge_incoming) == 2:
2401
ids_lane1, ids_lane2 = edges.ids_lanes[ids_downedge_incoming]
2402
#al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)
2403
#al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)
2404
# print ' check al1,al2',al1,al2,(al1 == 2) & (al2 == 2)
2405
# if (al1 == 2) & (al2 == 2):# real merges
2406
if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
2407
# print ' add mergenode',edges.ids_fromnode[id_downedge]
2408
ids_mergenode.add(edges.ids_fromnode[id_downedge])
2409
is_merge = True
2410
2411
if not is_merge: # len(ids_downedge_incoming) == 1:
2412
#ids_lane = edges.ids_lanes[ids_downedge_incoming]
2413
# if lanes.get_accesslevel(ids_lane1, id_prtmode) == 2:
2414
# print ' no merge detected, add edge',id_downedge
2415
ids_edge_new.add(id_downedge)
2416
2417
# else:
2418
# print 'WARNING in search_downstream_merges: edge %d has %d incoming edges.'%(id_downedge, len(ids_downedge_incoming))
2419
2420
ids_edge = ids_edge_new.copy()
2421
# print ' ids_edge_new',ids_edge_new,ids_edge,len(ids_edge)
2422
# is_cont = n_cont>0 #id_edge_start not in ids_edge
2423
#n_cont -= 1
2424
2425
# if not is_cont:
2426
# print ' endless!!id_edge_start,ids_edge',id_edge_start,ids_edge
2427
print ' found ids_mergenode', ids_mergenode
2428
return np.array(list(ids_mergenode), dtype=np.int32)
2429
2430
def is_prt_only(self, ids_lane, lanes):
2431
if len(ids_lane) > 1:
2432
return False
2433
else:
2434
if len(lanes.ids_modes_allow[ids_lane[0]]) > 0:
2435
return lanes.ids_modes_allow[ids_lane[0]][0] == self.parent.id_prtmode
2436
else:
2437
return False
2438
2439
def is_platform(self, ids_lane, lanes):
2440
if len(ids_lane) > 1:
2441
if len(lanes.ids_modes_allow[ids_lane[1]]) > 0:
2442
# we could also chech ped on lane 0
2443
return lanes.ids_modes_allow[ids_lane[1]][0] == self.parent.id_prtmode
2444
else:
2445
return False
2446
else:
2447
return False
2448
2449
2450
class PrtBerths(am.ArrayObjman):
2451
2452
def __init__(self, ident, prtstops, **kwargs):
2453
# print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1')
2454
self._init_objman(ident=ident,
2455
parent=prtstops,
2456
name='PRT Berths',
2457
info='PRT Berths.',
2458
**kwargs)
2459
2460
self._init_attributes()
2461
2462
def _init_attributes(self):
2463
#vtypes = self.get_scenario().demand.vtypes
2464
net = self.get_scenario().net
2465
self.add(cm.AttrConf('length_default', 4.0,
2466
groupnames=['parameters', 'options'],
2467
name='Default length',
2468
info='Default berth length.',
2469
unit='m',
2470
))
2471
2472
self.add_col(am.IdsArrayConf('ids_prtstop', self.parent,
2473
name='PRT stop ID',
2474
info='PRT stop ID',
2475
))
2476
2477
# states now dynamic, see prepare_sim
2478
# if hasattr(self,'states'):
2479
# self.delete('states')
2480
# self.add_col(am.ArrayConf( 'states', default = BERTHSTATES['free'],
2481
# dtype = np.int32,
2482
# choices = BERTHSTATES,
2483
# name = 'state',
2484
# info = 'State of berth.',
2485
# ))
2486
2487
self.add_col(am.ArrayConf('stoppositions', default=0.0,
2488
dtype=np.float32,
2489
name='Stop position',
2490
info='Position on edge where vehicle nose stops.',
2491
))
2492
2493
def _init_constants(self):
2494
self.do_not_save_attrs([
2495
'states', 'ids_veh',
2496
])
2497
2498
def prepare_sim(self, process):
2499
# print 'PrtBerths.prepare_sim'
2500
ids = self.get_ids()
2501
if len(ids) == 0:
2502
return []
2503
self.states = BERTHSTATES['free']*np.ones(np.max(ids)+1, dtype=np.int32)
2504
2505
# current vehicle at berth
2506
self.ids_veh = -1*np.ones(np.max(ids)+1, dtype=np.int32)
2507
2508
# last time when vehicle got boaded at this berth
2509
self.times_routes = 0.0 * np.ones(np.max(ids)+1, dtype=np.float32)
2510
return [] # berth has no update function
2511
2512
def get_scenario(self):
2513
return self.parent.get_scenario()
2514
2515
def get_prtvehicles(self):
2516
return self.parent.parent.prtvehicles
2517
2518
def get_length(self):
2519
return self.length_default.get_value()
2520
2521
def make(self, id_stop, position_from=None, position_to=None,
2522
n_berth=None,
2523
offset_firstberth=0.0, offset_stoppos=-0.0):
2524
stoplength = position_to-position_from
2525
# print 'Berths.make',id_stop,stoplength
2526
2527
# TODO: let define berth number either explicitely or through stoplength
2528
2529
length_berth = self.length_default.get_value()
2530
positions = position_from + offset_firstberth\
2531
+ np.arange(length_berth-offset_firstberth, stoplength+length_berth, length_berth) + offset_stoppos
2532
n_berth = len(positions)
2533
2534
# print ' n_berth,positions',n_berth,positions
2535
# force number of berth to be pair
2536
if n_berth % 2 == 1:
2537
positions = positions[1:]
2538
n_berth -= 1
2539
2540
ids_berth = self.add_rows(n=n_berth,
2541
stoppositions=positions,
2542
ids_prtstop=id_stop * np.ones(n_berth, dtype=np.int32),
2543
)
2544
return ids_berth
2545
2546
def set_prtvehicles(self, prtvehicles):
2547
"""
2548
Defines attributes which are linked with prtvehicles
2549
"""
2550
self.add_col(am.IdsArrayConf('ids_veh', prtvehicles,
2551
is_save=False,
2552
name='Vehicle ID',
2553
info='ID of vehicle currently alighting/boarding at this berth. -1 means no vehicle.',
2554
))
2555
2556
def set_allocate(self, ids_berth):
2557
print 'set_allocate ids_berth', ids_berth, self.ids_veh[ids_berth]
2558
self.states[ids_berth] = BERTHSTATES['allocated']
2559
2560
def set_alighting(self, id_berth, id_veh):
2561
self.states[id_berth] = BERTHSTATES['alighting']
2562
self.ids_veh[id_berth] = id_veh
2563
2564
def set_boarding(self, id_berth):
2565
self.states[id_berth] = BERTHSTATES['boarding']
2566
2567
def set_waiting_empty(self, id_berth):
2568
self.states[id_berth] = BERTHSTATES['waiting']
2569
2570
# def set_waiting_occupied(self, id_berth):
2571
# self.states[id_berth] = BERTHSTATES['waiting_occupied']
2572
2573
def set_waiting_routed(self, id_berth, simtime):
2574
2575
print 'set_waiting_routed', id_berth, 'prt.%d' % (self.ids_veh[id_berth]), 'simtime', simtime
2576
self.states[id_berth] = BERTHSTATES['waiting_routed']
2577
self.times_routes[id_berth] = simtime
2578
2579
def set_free(self, id_berth):
2580
self.states[id_berth] = BERTHSTATES['free']
2581
self.ids_veh[id_berth] = -1
2582
2583
2584
class PrtStops(am.ArrayObjman):
2585
"""
2586
This is just a dummy to prevent errors with old PRT plugin
2587
"""
2588
2589
def __init__(self, ident, prtservices, **kwargs):
2590
self._init_objman(ident=ident,
2591
parent=prtservices,
2592
name='PRT Platoon stops',
2593
info='Contains methods and information on PRT stops, able to sort vehicles and create platoons.',
2594
#xmltag = ('additional','busStop','stopnames'),
2595
version=0.0,
2596
**kwargs)
2597
# self._init_attributes()
2598
2599
def get_scenario(self):
2600
return self.parent.get_scenario()
2601
2602
2603
class PrtPlatoonStops(am.ArrayObjman):
2604
def __init__(self, ident, prtservices, **kwargs):
2605
self._init_objman(ident=ident,
2606
parent=prtservices,
2607
name='PRT Platoon stops',
2608
info='Contains methods and information on PRT stops, able to sort vehicles and create platoons.',
2609
#xmltag = ('additional','busStop','stopnames'),
2610
version=0.1,
2611
**kwargs)
2612
self._init_attributes()
2613
2614
def _init_attributes(self):
2615
self.add(cm.ObjConf(PrtBerths('berths', self)))
2616
2617
berths = self.get_berths()
2618
net = self.get_scenario().net
2619
2620
self.add(cm.AttrConf('time_update', 0.5,
2621
groupnames=['parameters'],
2622
name='Update time',
2623
info="Update time for station.",
2624
unit='s',
2625
))
2626
2627
# self.add(cm.AttrConf( 'time_kickout', 30.0,
2628
# groupnames = ['parameters'],
2629
# name = 'Kickout time',
2630
# info = "Time to kick out empty vehicles after vehicles behing have been occupied with passengers.",
2631
# unit = 's',
2632
# ))
2633
2634
self.add(cm.AttrConf('time_fase_in_max', 30.0,
2635
groupnames=['parameters'],
2636
name='Max. move in time',
2637
info="Maximum move in phase duration.",
2638
unit='s',
2639
))
2640
2641
self.add(cm.AttrConf('time_fase_out_max', 30.0,
2642
groupnames=['parameters'],
2643
name='Max. move out time',
2644
info="Maximum move out phase duration.",
2645
unit='s',
2646
))
2647
2648
self.add(cm.AttrConf('time_wait_berth_max', 60.0,
2649
groupnames=['parameters'],
2650
name='Max. berth wait time',
2651
info="Maximum time that an occupied vehicle can remain in the berth before getting moved out.",
2652
unit='s',
2653
))
2654
2655
self.add(cm.AttrConf('timeconst_flow', 0.98,
2656
groupnames=['parameters'],
2657
name='Flow time const',
2658
info="Constant to update the moving average flow.",
2659
))
2660
2661
self.add(cm.AttrConf('stoplinegap', 12.0,
2662
groupnames=['parameters'],
2663
name='Stopline gap',
2664
unit='m',
2665
info="Distance between stopline, where vehicles get started, and the end of the lane.",
2666
))
2667
2668
self.add(cm.AttrConf('capacity_per_berth', 80.0,
2669
groupnames=['parameters'],
2670
name='Capacity per berth',
2671
info="Capacity in processed vehicles per berth. This is to estimate the capacity limit of stops which are supposed to increase linearly with the number of berths",
2672
))
2673
2674
self.add_col(am.IdsArrayConf('ids_ptstop', net.ptstops,
2675
name='ID PT stop',
2676
info='ID of public transport stop. ',
2677
))
2678
2679
self.add_col(am.ArrayConf('types', default=STOPTYPES['person'],
2680
dtype=np.int32,
2681
perm='rw',
2682
choices=STOPTYPES,
2683
name='Type',
2684
info='Type of stop.',
2685
))
2686
2687
self.add_col(am.IdlistsArrayConf('ids_berths', berths,
2688
#groupnames = ['_private'],
2689
name='Berth IDs',
2690
info="Berth IDs. These berth can be used for both, boarding and alighting.",
2691
))
2692
2693
if self.get_version() < 0.1:
2694
self.delete('time_kickout')
2695
2696
self.set_version(0.1)
2697
2698
# will be determined automatically in function of stop and berth geometry
2699
# self.add_col(am.ArrayConf( 'numbers_veh_in_max', 12,
2700
# groupnames = ['parameters'],
2701
# name = 'Max. veh. input buffer',
2702
# info = "Maximum vehicles in input buffer. If this buffer at the entrance of the stop is ful then a move in face is triggered.",
2703
# ))
2704
#
2705
# self.add_col(am.ArrayConf( 'numbers_veh_out_max', 12,
2706
# groupnames = ['parameters'],
2707
# name = 'Max. veh. output buffer',
2708
# info = "Maximum vehicles in output buffer. This buffer at the exit of the stop limits the length of platoon formation.",
2709
# ))
2710
2711
def _init_constants(self):
2712
self.do_not_save_attrs([
2713
'fases',
2714
'ids_stop_to_ids_edge_sumo', 'ids_stop_to_ids_edge',
2715
'stoplines', 'ids_stop_to_ids_acceledge_sumo',
2716
'id_edge_sumo_to_id_stop',
2717
'inds_berth_allocated',
2718
'times_plat_accumulate', # time when last platoon vehicle accumulation started
2719
'ids_vehs_sumo_prev', 'ids_vehs',
2720
'ids_vehs_to_allocate',
2721
'times_lastboard',
2722
'numbers_veh', 'numbers_person_wait',
2723
'flows_person', 'ids_veh_lead',
2724
'ids_veh_lastdep', 'ids_vehs_prog',
2725
'ids_persons_sumo_prev', 'ids_persons_sumo_boarded',
2726
'waittimes_persons', 'waittimes_tot',
2727
'id_person_to_origs_dests',
2728
'ids_detectoredge_decompr'
2729
])
2730
2731
def get_edges(self, ids_prtstop):
2732
net = self.get_scenario().net
2733
return net.lanes.ids_edge[net.ptstops.ids_lane[self.ids_ptstop[ids_prtstop]]]
2734
2735
def get_berths(self):
2736
return self.berths.get_value()
2737
2738
def get_scenario(self):
2739
return self.parent.get_scenario()
2740
2741
def set_prtvehicles(self, prtvehicles):
2742
self.get_berths().set_prtvehicles(prtvehicles)
2743
2744
def set_vehicleman(self, vehicleman):
2745
self.add(cm.ObjConf(vehicleman, is_child=False, groups=['_private']))
2746
2747
def get_vehicleman(self):
2748
return self.vehicleman.get_value()
2749
2750
def get_closest_for_trip(self, coords_from, coords_to, walkspeeds=None, ids_person=None):
2751
"""
2752
Returns the prt stops and stop edges that minimize
2753
door to door trip time.
2754
Door from and to positions of each trip are given as coordinates.
2755
"""
2756
net = self.get_scenario().net
2757
ptstops = net.ptstops
2758
lanes = net.lanes
2759
n = len(coords_from)
2760
print 'get_closest_for_trip', n
2761
2762
times_stop_to_stop = self.parent.times_stop_to_stop[1:, 1:]
2763
2764
ids_prtstop = self.get_ids()
2765
n_stops = len(self)
2766
ids_ptstop = self.ids_ptstop[ids_prtstop]
2767
coords_stop = ptstops.centroids[ids_ptstop]
2768
ids_edge_stop = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]
2769
2770
inds_closest_from = np.zeros(n, dtype=np.int32)
2771
inds_closest_to = np.zeros(n, dtype=np.int32)
2772
if walkspeeds is None:
2773
# default walk speed in m/s
2774
walkspeeds = 0.8*np.ones(n, dtype=np.float32)
2775
2776
i = 0
2777
for coord_from, coord_to, walkspeed in zip(coords_from, coords_to, walkspeeds):
2778
walktimes_from = 1.0/walkspeed*np.sqrt(np.sum((coord_from-coords_stop)**2, 1))
2779
walktimes_to = 1.0/walkspeed*np.sqrt(np.sum((coord_to-coords_stop)**2, 1))
2780
2781
times_door_to_door = times_stop_to_stop+np.array([walktimes_from]).transpose()
2782
times_door_to_door += walktimes_to
2783
ind_from, ind_to = np.divmod(np.argmin(times_door_to_door), n_stops)
2784
2785
inds_closest_from[i] = ind_from
2786
inds_closest_to[i] = ind_to
2787
2788
if 0: # ids_person is not None:
2789
id_person = ids_person[i]
2790
if id_person == 17214:
2791
# print ' walktimes_from',(np.array([walktimes_from]).transpose()).shape
2792
# print ' walktimes_to',walktimes_to.shape
2793
# print ' times_stop_to_stop',times_stop_to_stop.shape
2794
2795
print ' id_person', id_person
2796
print ' coord_from, coord_to', coord_from, coord_to
2797
print ' times_door_to_door\n', times_door_to_door
2798
print ' ind_from, ind_to', ind_from, ind_to
2799
print ' id_stop_from, id_stop_to', ids_prtstop[ind_from], ids_prtstop[ind_to]
2800
2801
i += 1
2802
2803
ids_prtstop_closest_from = ids_prtstop[inds_closest_from]
2804
ids_edge_closest_from = ids_edge_stop[inds_closest_from]
2805
ids_prtstop_closest_to = ids_prtstop[inds_closest_to]
2806
ids_edge_closest_to = ids_edge_stop[inds_closest_to]
2807
return ids_prtstop_closest_from, ids_edge_closest_from, ids_prtstop_closest_to, ids_edge_closest_to
2808
2809
def get_closest(self, coords):
2810
"""
2811
Returns the closest prt stop for each coord in coords vector.
2812
"""
2813
net = self.get_scenario().net
2814
ptstops = net.ptstops
2815
lanes = net.lanes
2816
n = len(coords)
2817
# print 'get_closest',n
2818
2819
#ids_stop = self.get_ids()
2820
2821
ids_prtstop = self.get_ids()
2822
ids_ptstop = self.ids_ptstop[ids_prtstop]
2823
coords_stop = ptstops.centroids[ids_ptstop]
2824
ids_edge_stop = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]
2825
2826
inds_closest = np.zeros(n, dtype=np.int32)
2827
2828
i = 0
2829
for coord in coords:
2830
ind_closest = np.argmin(np.sum((coord-coords_stop)**2, 1))
2831
inds_closest[i] = ind_closest
2832
i += 1
2833
2834
ids_prtstop_closest = ids_prtstop[inds_closest]
2835
ids_edge_closest = ids_edge_stop[inds_closest]
2836
2837
return ids_prtstop_closest, ids_edge_closest
2838
2839
def get_waitpositions(self, ids, offset=-0.0):
2840
"""
2841
Assign randomly a wait-position for each stop in ids
2842
2843
offset is wait position relative to the vehicle nose.
2844
"""
2845
# print 'get_waitpositions min(ids),max(ids)',min(ids),is_alight,max(ids),offset
2846
positions = np.zeros(len(ids), dtype=np.float32)
2847
randint = random.randint
2848
ids_berths = self.ids_berths[ids]
2849
2850
stoppositions = self.get_berths().stoppositions
2851
# print ' ids_berths',ids_berths
2852
i = 0
2853
for id_stop, ids_berth in zip(ids, ids_berths):
2854
#ids_berth = ids_berths[id_stop]
2855
ind_berth = randint(0, len(ids_berth)-1)
2856
2857
positions[i] = stoppositions[ids_berth[ind_berth]]
2858
# print ' id_stop,ids_berth,posiions',id_stop,ids_berth,stoppositions[ids_berth[ind_berth]]
2859
i += 1
2860
#positions[i] = stoppositions[ids_berth[randint(0,len(ids_berth))]]
2861
# for id_stop , pos in zip(ids, positions):
2862
# print ' id_stop %d, is_alight = %s, pos %.2fm'%(id_stop, is_alight ,pos)
2863
2864
return positions+offset
2865
2866
def get_capacity(self, id_stop):
2867
"""
2868
Returns capacity in processed vehicles per hour for stop id_stop
2869
"""
2870
return self.capacity_per_berth.get_value() * len(self.ids_berths[id_stop])
2871
2872
def prepare_sim(self, process):
2873
simtime = process.simtime
2874
print 'PrtStops.prepare_sim', simtime
2875
self.debug = True
2876
net = self.get_scenario().net
2877
ptstops = net.ptstops
2878
ids_edge_sumo = net.edges.ids_sumo
2879
vehicles = self.parent.prtvehicles
2880
berths = self.get_berths()
2881
lanes = net.lanes
2882
ids_edge_sumo = net.edges.ids_sumo
2883
ids = self.get_ids()
2884
2885
if len(ids) == 0: # np PRT stops in network
2886
return []
2887
2888
get_outgoing = net.edges.get_outgoing
2889
2890
# station management
2891
# fase = 0: move in
2892
# fase = 1: move out
2893
self.fases = np.zeros(np.max(ids)+1, dtype=np.int32)
2894
# are_back_to_move_in allows a mechanism to switch back to move in fase
2895
self.are_back_to_move_in = np.zeros(np.max(ids)+1, dtype=np.bool)
2896
2897
self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1, dtype=np.object)
2898
self.ids_stop_to_ids_edge = np.zeros(np.max(ids)+1, dtype=np.int32)
2899
2900
ids_stopedge = lanes.ids_edge[ptstops.ids_lane[self.ids_ptstop[ids]]]
2901
# print ' ids,self.stoplines[ids]',ids,self.stoplines[ids]
2902
self.ids_stop_to_ids_edge_sumo[ids] = ids_edge_sumo[ids_stopedge]
2903
self.ids_stop_to_ids_edge[ids] = ids_stopedge
2904
2905
self.id_edge_to_id_stop = {}
2906
for id_stop, id_edge in zip(ids, ids_stopedge):
2907
self.id_edge_to_id_stop[id_edge] = id_stop
2908
2909
# Determine te position where vehicles are stopped while waiting for the
2910
# move in fase.
2911
# stop position at stoplinegap meters
2912
# before the beginning of the berth area
2913
self.stoplines_in = np.zeros(np.max(ids)+1, dtype=np.float32)
2914
2915
# input queue capacity
2916
self.capas_inqueue = np.zeros(np.max(ids)+1, dtype=np.int32)
2917
# output queue capacity
2918
self.capas_outqueue = np.zeros(np.max(ids)+1, dtype=np.int32)
2919
2920
stoplinegap = 1.0
2921
#self.stoplines[ids] = net.edges.lengths[ids_stopedge]-12.0
2922
#stoplengths = net.edges.lengths[ids_stopedge]
2923
for id_stop, ids_board, length_stopedge in zip(ids, self.ids_berths[ids], net.edges.lengths[ids_stopedge]):
2924
# print ' berthposs:',berths.stoppositions[ids_board]
2925
firstberthpos = berths.stoppositions[ids_board][0]-berths.get_length()
2926
2927
if (firstberthpos-stoplinegap) > 0:
2928
self.stoplines_in[id_stop] = firstberthpos-stoplinegap
2929
2930
print ' OK:id_stop', id_stop, 'stoplines_in', self.stoplines_in[id_stop]
2931
self.capas_inqueue[id_stop] = int(self.stoplines_in[id_stop]/vehicles.length)
2932
print ' capa_inqueue', self.capas_inqueue[id_stop]
2933
else:
2934
print 'WARNING in PrtStops.prepare_sim: stop ID %d has not enough space at before berth area.' % id_stop
2935
2936
# Determine stopline position where vehicles actually start
2937
# running off the station
2938
2939
# final stop at stoplinegap meters before end of stopedge
2940
self.stoplines = np.zeros(np.max(ids)+1, dtype=np.float32)
2941
stoplinegap = self.stoplinegap.get_value()
2942
2943
#self.stoplines[ids] = net.edges.lengths[ids_stopedge]-12.0
2944
#stoplengths = net.edges.lengths[ids_stopedge]
2945
for id_stop, ids_board, length_stopedge in zip(ids, self.ids_berths[ids], net.edges.lengths[ids_stopedge]):
2946
lastberthstoppos = berths.stoppositions[ids_board][-1]
2947
if (length_stopedge-lastberthstoppos) > stoplinegap+1:
2948
self.stoplines[id_stop] = length_stopedge-stoplinegap
2949
print ' OK:id_stop', id_stop, 'length_stopedge', length_stopedge, 'stopline', self.stoplines[id_stop]
2950
2951
elif length_stopedge > lastberthstoppos:
2952
self.stoplines[id_stop] = 0.5*(length_stopedge+lastberthstoppos)
2953
print ' Limit:id_stop', id_stop, 'length_stopedge', length_stopedge, 'stopline', self.stoplines[id_stop]
2954
2955
self.capas_outqueue[id_stop] = int((self.stoplines[id_stop]-lastberthstoppos)/vehicles.length)
2956
print ' capa_outqueue', self.capas_outqueue[id_stop]
2957
2958
self.ids_stop_to_ids_acceledge_sumo = np.zeros(np.max(ids)+1, dtype=np.object)
2959
for id_stop, id_stopedge in zip(ids, ids_stopedge):
2960
self.ids_stop_to_ids_acceledge_sumo[id_stop] = ids_edge_sumo[get_outgoing(id_stopedge)[0]]
2961
2962
self.id_edge_sumo_to_id_stop = {}
2963
for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]):
2964
self.id_edge_sumo_to_id_stop[id_edge_sumo] = id_stop
2965
2966
# current berth ready to be newly allocated by vehicles during move in fase
2967
self.ids_berths_to_allocate = np.ones(np.max(ids)+1, dtype=np.object)
2968
2969
# vehicles that are currently allocated for a berth for alighting
2970
# and are forwarded to the correct position of the berth
2971
self.ids_vehs_alight_forward = np.zeros(np.max(ids)+1, dtype=np.object)
2972
2973
# vehicles that are arrived at the stopline of the berth for alighting
2974
# and are moving into the berth
2975
self.ids_vehs_alight_aproach = np.zeros(np.max(ids)+1, dtype=np.object)
2976
2977
# sets of vehicles routed and ready to leave station
2978
# this is the set to search for vehicles for platooning
2979
# TODO: check if this variable is still in use
2980
self.ids_vehs_routed = np.zeros(np.max(ids)+1, dtype=np.object)
2981
2982
# berth with routed and started vehicles,
2983
# that are waiting for their turn to exit
2984
# theiy will leave the berth, sorted by destinatiom
2985
# this is managed in try_start_vehicles
2986
self.ids_berths_veh_wait_exit = np.zeros(np.max(ids)+1, dtype=np.object)
2987
2988
# pass through vehicles in input queue waiting for exit
2989
self.ids_vehs_pass_wait_exit = np.zeros(np.max(ids)+1, dtype=np.object)
2990
2991
# vehicles which move sidewards out of the berth
2992
self.ids_vehs_berth_exit = np.zeros(np.max(ids)+1, dtype=np.object)
2993
2994
# vehicles in the output queue ready for departure
2995
self.ids_vehs_out = np.zeros(np.max(ids)+1, dtype=np.object)
2996
2997
# should positions of vehicles in output queue be updated
2998
self.are_reposition_out = np.zeros(np.max(ids)+1, dtype=np.bool)
2999
3000
# vehicles in output queue already concatenated and ready for departure
3001
# and waiting for vehicle management to be lauched
3002
self.ids_vehs_ready_for_departure = np.zeros(np.max(ids)+1, dtype=np.object)
3003
3004
# current berth allocation index for departing vehicles during move out fase
3005
#
3006
self.inds_berth_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32)
3007
3008
#self.ids_vehs_alight_forward = np.zeros(np.max(ids)+1,dtype = np.object)
3009
self.ids_vehs_board_allocated = np.zeros(np.max(ids)+1, dtype=np.object)
3010
3011
self.times_phase_in = simtime*np.ones(np.max(ids)+1, dtype=np.int32)
3012
self.times_phase_out = simtime*np.ones(np.max(ids)+1, dtype=np.int32)
3013
3014
# time when last platoon vehicle accumulation started
3015
# -1 means no platoon accumulation takes place
3016
self.times_plat_accumulate = -1*np.ones(np.max(ids)+1, dtype=np.int32)
3017
3018
self.ids_vehs_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object)
3019
self.ids_vehs = np.zeros(np.max(ids)+1, dtype=np.object)
3020
self.ids_vehs_inqueue = np.zeros(np.max(ids)+1, dtype=np.object)
3021
#
3022
self.times_lastboard = 10**4*np.ones(np.max(ids)+1, dtype=np.int32)
3023
3024
# for vehicle management
3025
self.numbers_veh = np.zeros(np.max(ids)+1, dtype=np.int32)
3026
self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype=np.int32)
3027
self.flows_person = np.zeros(np.max(ids)+1, dtype=np.float32)
3028
self.ids_veh_lead = -1*np.ones(np.max(ids)+1, dtype=np.int32)
3029
#self.ids_veh_lastdep = -1*np.ones(np.max(ids)+1,dtype = np.int32)
3030
self.ids_vehs_prog = np.zeros(np.max(ids)+1, dtype=np.object)
3031
3032
# person management
3033
self.ids_persons_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object)
3034
#self.ids_persons_sumo_boarded = np.zeros(np.max(ids)+1,dtype = np.object)
3035
self.waittimes_persons = np.zeros(np.max(ids)+1, dtype=np.object)
3036
self.waittimes_tot = np.zeros(np.max(ids)+1, dtype=np.float32)
3037
3038
virtualpop = self.get_scenario().demand.virtualpop
3039
3040
ids_persons = virtualpop.get_ids()
3041
stagelists = virtualpop.get_plans().stagelists
3042
prttransits = virtualpop.get_plans().get_stagetable('hcprttransits')
3043
id_person_to_origs_dests = {}
3044
3045
# create map from person id to various destination information
3046
# TODO: needs to be improved for trip chains, move to prtservices
3047
# idea: whu not scan prttransits?
3048
for id_person, stagelist in zip(ids_persons, stagelists[virtualpop.ids_plan[ids_persons]]):
3049
# print ' check dests of id_person',id_person
3050
for stages, id_stage in stagelist:
3051
if stages.ident == 'hcprttransits':
3052
id_fromedge_sumo = ids_edge_sumo[stages.ids_fromedge[id_stage]]
3053
id_toedge_sumo = ids_edge_sumo[stages.ids_toedge[id_stage]]
3054
data_orig_dest = (self.id_edge_sumo_to_id_stop[id_fromedge_sumo],
3055
self.id_edge_sumo_to_id_stop[id_toedge_sumo],
3056
id_fromedge_sumo,
3057
id_toedge_sumo)
3058
3059
id_person_sumo = virtualpop.get_id_sumo_from_id(id_person)
3060
if id_person_to_origs_dests.has_key(id_person_sumo):
3061
id_person_to_origs_dests[id_person_sumo].append(data_orig_dest)
3062
else:
3063
id_person_to_origs_dests[id_person_sumo] = [data_orig_dest]
3064
# print ' prtdests = ',id_person_to_origs_dests[id_person_sumo]
3065
3066
# print ' id_person_to_origs_dests=\n',id_person_to_origs_dests
3067
self.id_person_to_origs_dests = id_person_to_origs_dests
3068
3069
# this is only used for crazy person stage detection
3070
# angles_stop =
3071
3072
# various initianilizations
3073
for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]):
3074
print ' initialize stop', id_stop
3075
3076
# initially all berth are avalable for allocation
3077
# print ' type(self.ids_berths[id_stop])',type(self.ids_berths[id_stop])
3078
self.ids_berths_to_allocate[id_stop] = 1 * self.ids_berths[id_stop]
3079
self.inds_berth_allocated[id_stop] = len(self.ids_berths[id_stop])
3080
# print ' type(self.ids_berths_to_allocate [id_stop])',type(self.ids_berths_to_allocate [id_stop])
3081
self.ids_vehs_alight_forward[id_stop] = []
3082
self.ids_vehs_alight_aproach[id_stop] = set([])
3083
# print ' type(self.ids_vehs_alight_aproach[id_stop])',type(self.ids_vehs_alight_aproach[id_stop])
3084
3085
self.ids_vehs_board_allocated[id_stop] = []
3086
3087
self.ids_vehs_sumo_prev[id_stop] = set([])
3088
self.ids_persons_sumo_prev[id_stop] = set([])
3089
3090
self.ids_vehs_routed[id_stop] = set([])
3091
self.ids_berths_veh_wait_exit[id_stop] = []
3092
self.ids_vehs_pass_wait_exit[id_stop] = []
3093
self.ids_vehs_berth_exit[id_stop] = []
3094
self.ids_vehs_out[id_stop] = []
3095
self.ids_vehs_ready_for_departure[id_stop] = []
3096
3097
#self.ids_persons_sumo_boarded [id_stop] = []
3098
self.waittimes_persons[id_stop] = {}
3099
self.ids_vehs[id_stop] = []
3100
self.ids_vehs_inqueue[id_stop] = []
3101
3102
self.ids_vehs_prog[id_stop] = []
3103
3104
# decompressor detector edge set
3105
#self.ids_detectoredge_decompr = set(self.parent.decompressors.ids_detectoredge.get_value())
3106
3107
# traci.edge.subscribe(id_edge_sumo, [traci.constants.VAR_ARRIVED_VEHICLES_IDS])
3108
updatedata_berth = berths.prepare_sim(process)
3109
3110
return [(self.time_update.get_value(), self.process_step),
3111
]+updatedata_berth
3112
3113
def get_waittime_max(self, id_stop, simtime):
3114
if len(self.waittimes_persons[id_stop]) > 0:
3115
return np.max(simtime - np.array(self.waittimes_persons[id_stop].values(), dtype=np.float32))
3116
else:
3117
return 0.0
3118
3119
def process_step(self, process):
3120
simtime = process.simtime
3121
print 79*'_'
3122
print 'PrtStops.process_step at', simtime
3123
3124
# vehicle station process:
3125
# >forewarding (def enter)
3126
# >alighting (def process_step)
3127
# >boarding (def process_step) > ?boarding_completed > occupiedtrip
3128
# >waiting_empty (def process_step)
3129
# > emptytrip
3130
# > boarding (def process_step) > ?boarding_completed > occupiedtrip
3131
3132
net = self.get_scenario().net
3133
ptstops = net.ptstops
3134
berths = self.get_berths()
3135
lanes = net.lanes
3136
ids_edge_sumo = net.edges.ids_sumo
3137
vehicles = self.parent.prtvehicles
3138
virtualpop = self.get_scenario().demand.virtualpop
3139
ids = self.get_ids()
3140
3141
for id_stop, id_edge_sumo, ids_veh_sumo_prev, ids_person_sumo_prev in\
3142
zip(ids, self.ids_stop_to_ids_edge_sumo[ids],
3143
self.ids_vehs_sumo_prev[ids],
3144
self.ids_persons_sumo_prev[ids]):
3145
print ' '+60*'.'
3146
fase = self.fases[id_stop]
3147
print ' process id_stop', id_stop, 'id_edge_sumo', id_edge_sumo, 'fase', fase
3148
3149
if id_stop in [3]:
3150
self.debug = 1
3151
else:
3152
self.debug = 0
3153
3154
# if vehicles.id_follower_probe != vehicles.ids_follower[271]:
3155
# print 'PRE STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]
3156
3157
if self.debug:
3158
3159
print ' ids_berths_to_allocate', type(self.ids_berths_to_allocate[id_stop]), self.ids_berths_to_allocate[id_stop]
3160
print ' ind_berth_allocated', self.inds_berth_allocated[id_stop]
3161
print ' ids_vehs_inqueue', self.ids_vehs_inqueue[id_stop]
3162
print ' Capa', self.get_capacity(id_stop), 'per 10 seconds', self.get_capacity(id_stop)/3600*10
3163
print
3164
3165
print ' ids_vehs_alight_forward', self.ids_vehs_alight_forward[id_stop]
3166
print ' ids_vehs_alight_aproach', self.ids_vehs_alight_aproach[id_stop]
3167
print
3168
3169
print ' ids_vehs_routed', self.ids_vehs_routed[id_stop]
3170
print ' ids_berths_veh_wait_exit ', self.ids_berths_veh_wait_exit[id_stop]
3171
print ' ids_vehs_pass_wait_exit ', self.ids_vehs_pass_wait_exit[id_stop]
3172
print ' ids_vehs_berth_exit', self.ids_vehs_berth_exit[id_stop]
3173
print ' ids_vehs_out', self.ids_vehs_out[id_stop]
3174
print ' ids_veh_ready_for_departure', self.ids_vehs_ready_for_departure[id_stop]
3175
3176
print ' Vehicles:'
3177
ids_veh = self.ids_vehs[id_stop]
3178
for id_veh, state, id_berth, route in zip(ids_veh, vehicles.states[ids_veh], vehicles.ids_berth[ids_veh], vehicles.routes[ids_veh]):
3179
# ,'len(route)',len(route)
3180
print ' id_veh', id_veh, 'state', state, 'id_berth', id_berth, 'route', route
3181
3182
print ' Berths:'
3183
3184
ids_berth = self.ids_berths[id_stop]
3185
for id_berth, state, id_veh in zip(ids_berth, berths.states[ids_berth], berths.ids_veh[ids_berth]):
3186
print ' id_berth', id_berth, 'state', state, 'id_veh', id_veh
3187
# print ' flow_person',self.flows_person[id_stop]
3188
# print ' waittimes_persons',self.waittimes_persons[id_stop]
3189
3190
# print ' waittimes_tot',self.waittimes_tot[id_stop]
3191
3192
# no longer print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop]
3193
# print ' times_lastboard',self.times_lastboard[id_stop]
3194
print
3195
3196
if 0:
3197
for id_veh_sumo in self.ids_vehs_sumo_prev[id_stop]:
3198
print ' stopstate ', id_veh_sumo, bin(traci.vehicle.getStopState(id_veh_sumo))[2:], traci.vehicle.getRoute(id_veh_sumo)
3199
3200
# check for new vehicle arrivals/departures
3201
ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_sumo))
3202
# print ' ids_veh_sumo_prev=',ids_veh_sumo_prev
3203
# print ' ids_veh_sumo=',ids_veh_sumo
3204
3205
if ids_veh_sumo_prev != ids_veh_sumo:
3206
ids_veh_entered = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo.difference(ids_veh_sumo_prev)))
3207
ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo)))
3208
# print ' ids_veh_entered',ids_veh_entered
3209
# print ' ids_veh_left',ids_veh_left
3210
# for id_veh in ids_veh_entered:
3211
self.enter(id_stop, ids_veh_entered, fase, simtime)
3212
3213
for id_veh in ids_veh_left:
3214
self.exit(id_stop, id_veh, fase)
3215
self.ids_vehs_sumo_prev[id_stop] = ids_veh_sumo
3216
# print ' ids_veh_sumo_entered',ids_veh_sumo_entered
3217
# print ' ids_veh_sumo_left',ids_veh_sumo_left
3218
3219
# check whether allocated vehicles arrived at stopline
3220
# of alighting berths and move sidewards into the berth
3221
ids_veh_remove = []
3222
for id_veh in self.ids_vehs_alight_forward[id_stop]:
3223
# TODO: here we could also check vehicle position
3224
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3225
3226
# print ' isStopped',id_veh_sumo,traci.vehicle.isStopped(id_veh_sumo)
3227
3228
if traci.vehicle.isStopped(id_veh_sumo):
3229
3230
id_berth_alight = vehicles.ids_berth[id_veh]
3231
pos_berth = berths.stoppositions[id_berth_alight]
3232
# print ' pos_berth',pos_berth,'pos_current',traci.vehicle.getLanePosition(id_veh_sumo)
3233
if abs(pos_berth-traci.vehicle.getLanePosition(id_veh_sumo)) < 1.0:
3234
# stop at berth reached, proceed with moving in
3235
ids_veh_remove.append(id_veh)
3236
self.ids_vehs_alight_aproach[id_stop].add(id_veh) # ??????? no further use
3237
3238
traci.vehicle.resume(id_veh_sumo)
3239
#traci.vehicle.changeLane(id_veh_sumo, 1, 3600.0)
3240
#pos = traci.vehicle.getLanePosition(id_veh_sumo)
3241
3242
# print ' vehicle moving into id_berth_alight',id_berth_alight,'pos',berths.stoppositions[id_berth_alight]
3243
# this will cause the vehicle to slip sidewards into the berth
3244
# upon arrival alighting and boarding can take place
3245
vehicles.control_berth_stop(
3246
id_veh,
3247
id_edge_sumo=id_edge_sumo,
3248
position=pos_berth,
3249
laneindex=1,
3250
)
3251
traci.vehicle.changeLane(id_veh_sumo, 1, 10.0)
3252
3253
else:
3254
# print ' vehicle is stopped but did not reach alight bearth'
3255
# ->remove stop
3256
traci.vehicle.resume(id_veh_sumo)
3257
3258
for id_veh in ids_veh_remove:
3259
self.ids_vehs_alight_forward[id_stop].remove(id_veh)
3260
3261
# if vehicles.id_follower_probe != vehicles.ids_follower[271]:
3262
# print 'PRE APPROACH STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]
3263
# check whether allocated vehicles arrived at berth
3264
# and alight passengers
3265
3266
ids_veh_remove = []
3267
for id_veh in self.ids_vehs_alight_aproach[id_stop]:
3268
# TODO: here we could also check vehicle position
3269
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3270
# print ' %s'%id_veh_sumo,'isStopped',traci.vehicle.isStopped(id_veh_sumo)
3271
3272
if traci.vehicle.isStopped(id_veh_sumo):
3273
ids_veh_remove.append(id_veh)
3274
id_berth_alight = vehicles.ids_berth[id_veh]
3275
if self.debug:
3276
print ' %s stopped inside berth %d and alights' % (id_veh_sumo, id_berth_alight)
3277
3278
# vehicles.set_stop( id_veh,
3279
# id_edge_sumo,
3280
# berths.stoppositions[id_berth_alight],
3281
# laneindex = 1)
3282
#
3283
3284
# this assigns a vehicle to a station berth in the berth db
3285
berths.set_alighting(id_berth_alight, id_veh)
3286
3287
# set vehicle in alight mode
3288
vehicles.alight(id_veh)
3289
3290
for id_veh in ids_veh_remove:
3291
self.ids_vehs_alight_aproach[id_stop].discard(id_veh)
3292
3293
# if vehicles.id_follower_probe != vehicles.ids_follower[271]:
3294
# print 'PRE PERS STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]
3295
3296
# check for new person entering/left the station edge
3297
ids_person_sumo = set(traci.edge.getLastStepPersonIDs(id_edge_sumo))
3298
3299
n_enter = 0
3300
if ids_person_sumo_prev != ids_person_sumo:
3301
3302
if 0:
3303
print ' change\n id_person_sumo', ids_person_sumo
3304
print ' ids_person_sumo_prev', ids_person_sumo_prev
3305
# print ' dir(traci.person)',dir(traci.person)
3306
# for id_person_sumo in ids_person_sumo:
3307
# print ' id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo),traci.person.getVehicle(id_person_sumo)
3308
3309
# deal with persons who entered the edge
3310
ids_person_sumo_entered = ids_person_sumo.difference(ids_person_sumo_prev)
3311
for id_person_sumo in ids_person_sumo_entered:
3312
# print ' entered id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo)
3313
if self.id_person_to_origs_dests.has_key(id_person_sumo):
3314
id_edge_sumo_dests = self.id_person_to_origs_dests[id_person_sumo]
3315
3316
# id_edge_sumo_dests[i] = ( id_stop_from,
3317
# id_stop_to,
3318
# id_fromedge_sumo,
3319
# id_toedge_sumo)
3320
3321
# check if person still has a PRT trip
3322
3323
if len(id_edge_sumo_dests) > 0: # valid dest
3324
# check if next trip has origin edge equal to edge of this stop
3325
if id_edge_sumo_dests[0][2] == id_edge_sumo:
3326
if self.debug:
3327
print ' add to waittimes_persons', id_person_sumo, 'id_stop_dest', id_edge_sumo_dests[0][1], 'id_toedge_sumo', id_edge_sumo_dests[0][3]
3328
self.waittimes_persons[id_stop][id_person_sumo] = simtime
3329
n_enter += 1
3330
3331
# else:
3332
# print 'WARNING: person %s starts with % insted of %s.'%(id_person_sumo,id_edge_sumo_dests[0][2],id_edge_sumo)
3333
3334
# communicate person entry to vehman
3335
# this is used for person flow measurements
3336
self.parent.vehicleman.note_person_entered(id_stop, n_enter)
3337
3338
self.numbers_person_wait[id_stop] += n_enter
3339
self.ids_persons_sumo_prev[id_stop] = ids_person_sumo
3340
3341
self.waittimes_tot += self.numbers_person_wait*self.time_update.get_value()
3342
3343
timeconst_flow = self.timeconst_flow.get_value()
3344
self.flows_person[id_stop] = timeconst_flow*self.flows_person[id_stop] + \
3345
(1.0-timeconst_flow)*float(n_enter)/self.time_update.get_value()
3346
3347
if 0:
3348
for id_person_sumo in ids_person_sumo_prev:
3349
print ' ids_person_sumo=%s pos = %.2f ' % (id_person_sumo, traci.person.getLanePosition(id_person_sumo))
3350
# nomore print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop]
3351
3352
# if vehicles.id_follower_probe != vehicles.ids_follower[271]:
3353
# print 'PRE BOARD STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]
3354
3355
# check berth if alighting is completed in load area,
3356
# starting with last vehicle
3357
ids_berth_board = self.ids_berths[id_stop][::-1]
3358
for id_berth_board, id_veh in zip(
3359
ids_berth_board,
3360
berths.ids_veh[ids_berth_board],
3361
):
3362
# print ' before: berth',id_berth_board,'state',berths.states[id_berth_board],'id_veh',id_veh
3363
3364
if (id_veh > -1): # is there a waiting vehicle
3365
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3366
if (berths.states[id_berth_board] == BERTHSTATES['alighting']):
3367
3368
# this will put the vehicle in waiting or boarding mode
3369
if vehicles.is_completed_alighting(id_veh):
3370
if self.debug:
3371
print ' state of prt.%d: %d' % (id_veh, vehicles.states[id_veh])
3372
if vehicles.states[id_veh] == VEHICLESTATES['boarding']:
3373
# print ' set id_berth_board',id_berth_board,'to state boarding'
3374
berths.set_boarding(id_berth_board)
3375
3376
else:
3377
berths.set_waiting_empty(id_berth_board)
3378
3379
elif (berths.states[id_berth_board] in [BERTHSTATES['waiting'], BERTHSTATES['boarding']]):
3380
3381
if vehicles.states[id_veh] != VEHICLESTATES['boarding_completed']:
3382
if vehicles.is_completed_boarding(id_veh):
3383
# has just completed boarding
3384
self.route_trip_occupied(id_stop,
3385
id_berth_board,
3386
id_veh,
3387
id_veh_sumo,
3388
simtime)
3389
3390
# print ' after alighting: berth',id_berth_board,'state',berths.states[id_berth_board]
3391
3392
ids_veh_to_allocate = self.get_ids_veh_to_allocate(id_stop)
3393
ids_veh_to_pass = self.get_ids_veh_to_pass(id_stop)
3394
3395
# check whether to change phases
3396
if fase == FASE_MOVE_IN:
3397
# stop is in move in fase
3398
if self.debug:
3399
print ' >>timeout fase 0: dt=%.2f timeout=%.2f' % ((simtime - self.times_phase_in[id_stop]), self.time_fase_in_max.get_value()),\
3400
'TOUT', ((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value()
3401
), '|ALLOC', (len(self.ids_vehs_inqueue[id_stop]) > 0)
3402
# print ' ap',(len(self.ids_vehs_alight_aproach[id_stop]) == 0)
3403
print ' no forward, all vehicles moved into berth', (len(self.ids_vehs_alight_forward[id_stop]) == 0)
3404
print ' ids_vehs_inqueue', self.ids_vehs_inqueue[id_stop]
3405
print ' ids_veh_to_allocate', ids_veh_to_allocate
3406
print ' ids_veh_to_pass', ids_veh_to_pass
3407
print ' is_back_to_move_in ', self.are_back_to_move_in[id_stop]
3408
# if np.isnan(self.times_phase_in[id_stop]):
3409
# # only for initialization
3410
# self.times_phase_in[id_stop] = simtime - self.time_fase_in_max.get_value()
3411
3412
if (((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value())
3413
| (self.inds_berth_allocated[id_stop] == -1)
3414
| (len(ids_veh_to_pass) > 0))\
3415
& (len(self.ids_vehs_alight_forward[id_stop]) == 0):
3416
3417
# if len(ids_veh_to_pass)>0 then passthrough vehicles are in pole position
3418
# to be handeled and required by try_start_vehicles method
3419
# in order to start them and create platoons
3420
# in this case the move in fase should continue as soon as the
3421
# pass through vehicles are processed
3422
self.are_back_to_move_in[id_stop] = len(ids_veh_to_pass) > 0
3423
3424
# if (((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value()) | (len(ids_berth_to_allocate)==0))\
3425
# &(len(self.ids_vehs_alight_forward[id_stop]) == 0):
3426
3427
# &(len(self.ids_vehs_alight_aproach[id_stop]) == 0)
3428
3429
# time out for fase in reached or allocation queue starts growing
3430
# which means that there are no more free berth to allocate
3431
# and all forwarded vehicles reached their berth to alight
3432
if self.debug:
3433
print ' Switch from fase %d to fase %d' % (self.fases[id_stop], FASE_MOVE_OUT)
3434
self.fases[id_stop] = FASE_MOVE_OUT
3435
self.times_phase_out[id_stop] = simtime
3436
3437
elif fase == FASE_MOVE_OUT:
3438
# stop is in move out fase
3439
if self.debug:
3440
print ' >>timeout fase 1: dt=%.2f timeout=%.2f' % ((simtime - self.times_phase_out[id_stop]), self.time_fase_out_max.get_value()), 'move out of berth', len(self.ids_vehs_berth_exit[id_stop])
3441
print ' n_berth_exit', len(self.ids_vehs_berth_exit[id_stop]), 'n_veh_pass', len(ids_veh_to_pass), 'ids_veh_to_pass', ids_veh_to_pass
3442
# check fase transition
3443
# if np.isnan(self.times_phase_out[id_stop]):
3444
# # only for initialization
3445
# self.times_phase_in[id_stop] = simtime - self.time_fase_out_max.get_value()
3446
3447
if (((simtime-self.times_phase_out[id_stop]) > self.time_fase_out_max.get_value()) | (len(self.ids_vehs_inqueue[id_stop]) >= self.capas_inqueue[id_stop]) | self.are_back_to_move_in[id_stop])\
3448
& (len(self.ids_vehs_berth_exit[id_stop]) == 0) & (len(ids_veh_to_pass) == 0) & (len(self.ids_berths_veh_wait_exit[id_stop]) == 0) & (len(self.ids_vehs_pass_wait_exit[id_stop]) == 0):
3449
# time out and no vehicles are about to exit berth
3450
# if len(ids_veh_to_pass) == 0 then this is to ensure that
3451
# there are no longer passthrough vehicles in the
3452
# input queue
3453
self.are_back_to_move_in[id_stop] = False
3454
3455
if self.debug:
3456
print ' Switch from fase %d to fase %d' % (self.fases[id_stop], FASE_MOVE_IN), 'ind_berth_allocated', self.inds_berth_allocated[id_stop]
3457
3458
self.fases[id_stop] = FASE_MOVE_IN
3459
self.times_phase_in[id_stop] = simtime
3460
3461
# check if bert allocation index arrver at -1 and reset
3462
if self.inds_berth_allocated[id_stop] == -1:
3463
# identify currently free berth
3464
# current available berth to allocate
3465
ids_berth_to_allocate = self.get_berths_with_state(id_stop, BERTHSTATES['free'])
3466
self.ids_berths_to_allocate[id_stop] = list(ids_berth_to_allocate)
3467
# reset counter
3468
self.inds_berth_allocated[id_stop] = len(self.ids_berths_to_allocate[id_stop])
3469
3470
# allocate vehicles accumulated in input queue
3471
3472
if (len(ids_veh_to_allocate) > 0) & (len(ids_veh_to_pass) == 0) & (self.inds_berth_allocated[id_stop] > -1):
3473
ids_veh_remove = []
3474
# print ' before:ids_vehs_to_allocate',self.ids_vehs_inqueue[id_stop]
3475
ids_berths = self.allocate_alight(id_stop, len(ids_veh_to_allocate))
3476
for id_veh, id_berth in zip(ids_veh_to_allocate, ids_berths):
3477
#id_berth = self.allocate_alight(id_stop)
3478
# command vehicle to go to berth for alighting
3479
if id_berth > -1:
3480
if self.debug:
3481
print ' foreward queued vehicle id_veh prt.%d to id_berth %d at pos %.2fm' % (id_veh, id_berth, berths.stoppositions[id_berth])
3482
vehicles.control_berth_position_enter(id_veh, id_berth,
3483
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],
3484
# needs to stop a bit before to move in
3485
position=berths.stoppositions[id_berth]-0.3,
3486
laneindex=2,
3487
)
3488
self.ids_vehs_alight_forward[id_stop].append(id_veh)
3489
ids_veh_remove.append(id_veh)
3490
# print ' after:ids_vehs_to_allocate',self.ids_vehs_inqueue[id_stop]
3491
for id_veh in ids_veh_remove:
3492
self.ids_vehs_inqueue[id_stop].remove(id_veh)
3493
3494
# print ' New fase:',self.fases[id_stop],'FASE_MOVE_OUT',self.fases[id_stop] == FASE_MOVE_OUT
3495
3496
# if vehicles.id_follower_probe != vehicles.ids_follower[271]:
3497
# print 'POST PHASECHANGE STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]
3498
3499
if self.fases[id_stop] == FASE_MOVE_IN:
3500
# specific tasks during move in fase
3501
pass
3502
3503
elif self.fases[id_stop] == FASE_MOVE_OUT:
3504
# specific tasks during move out fase
3505
3506
# check which vehicles to start
3507
self.try_start_vehicles(id_stop, simtime, n_plat_min=3)
3508
self.foreward_vehicles_exit(id_stop)
3509
3510
# try to release vehicles
3511
ids_veh = self.get_vehicles_ready_for_departure(id_stop)
3512
if len(ids_veh) > 0: # there are new vehicles ready for departure
3513
self.prepare_vehs_for_departure(id_stop, ids_veh)
3514
3515
if self.are_reposition_out[id_stop]:
3516
self._reposition_outqueue(id_stop)
3517
3518
def route_trip_occupied(self, id_stop, id_berth, id_veh, id_veh_sumo, simtime):
3519
3520
berths = self.get_berths()
3521
vehicles = self.parent.prtvehicles
3522
#id_veh_sumo = self.parent.prtvehicles.get_id_sumo(id_veh)
3523
n_pax = traci.vehicle.getPersonNumber(id_veh_sumo)
3524
if self.debug:
3525
print 'route_trip_occupied id_stop', id_stop, 'id_berth', id_berth, 'veh=%s' % id_veh_sumo, 'simtime', simtime, 'n_pax', n_pax
3526
3527
# identify which of the boarding persons is in the
3528
# vehicle which completed boarding
3529
dist_min = np.inf
3530
id_person_sumo_inveh = None
3531
stoppos = berths.stoppositions[id_berth]
3532
3533
# identify person(s) in vehicle
3534
ids_person_sumo_inveh = traci.vehicle.getPersonIDList(id_veh_sumo)
3535
if len(ids_person_sumo_inveh) > 0:
3536
id_person_sumo_inveh = ids_person_sumo_inveh[0]
3537
if self.debug:
3538
print ' found person %s in veh prt.%s' % (id_person_sumo_inveh, id_veh_sumo)
3539
3540
# program vehicle to person's destination
3541
# print ' found person,origs_dests',id_person_sumo_inveh,self.id_person_to_origs_dests[id_person_sumo_inveh]
3542
id_stop_orig, id_stop_dest, id_edge_sumo_from, id_edge_sumo_to = \
3543
self.id_person_to_origs_dests[id_person_sumo_inveh].pop(0)
3544
if self.debug:
3545
print ' found person %s' % id_person_sumo_inveh, 'from', id_stop_orig, id_edge_sumo_from, ' to', id_edge_sumo_to, id_stop_dest
3546
3547
route, duration = self.route_stop_to_stop(id_stop_orig, id_stop_dest)
3548
3549
# print ' found route',route
3550
# print ' found duration',duration
3551
3552
# this is setting the target route which
3553
# used to set the effective route and to identify possible
3554
# platoon cooperations
3555
vehicles.set_route_target(id_veh, route, id_stop_target=id_stop_dest, is_disengage_from_berth=True)
3556
#stopline = self._get_stopline(id_stop, simtime)
3557
# print ' simtime', simtime
3558
3559
# self.parent.prtvehicles.init_trip_occupied(\
3560
# id_veh, self.ids_stop_to_ids_edge_sumo[id_stop],
3561
# stopline,
3562
# )
3563
3564
# self.ids_persons_sumo_boarded[id_stop].remove(id_person_sumo_inveh)
3565
self.times_lastboard[id_stop] = simtime
3566
berths.set_waiting_routed(id_berth, simtime)
3567
#berths.ids_veh[id_berth] = -1
3568
self.ids_vehs_routed[id_stop].add(id_veh)
3569
#self.try_set_leadveh(id_stop, id_veh)
3570
self.parent.vehicleman.init_trip_occupied(id_veh, id_stop, id_stop_dest, simtime)
3571
3572
for id_person_sumo in ids_person_sumo_inveh:
3573
self.waittimes_tot[id_stop] -= simtime - self.waittimes_persons[id_stop][id_person_sumo]
3574
del self.waittimes_persons[id_stop][id_person_sumo]
3575
3576
self.numbers_person_wait[id_stop] -= len(ids_person_sumo_inveh)
3577
3578
else:
3579
print 'WARNING: on stop %d edge %s, berth %d no person found inside vehicle prt.%d' % (id_stop, self.ids_stop_to_ids_edge_sumo[id_stop], id_berth, id_veh)
3580
return None
3581
3582
def get_surplus_veh(self, id_stop):
3583
# all waiting vehicles
3584
3585
# use this method instead of self.get_vehs_waiting because it is faster
3586
# however in self.route_empties the method self.get_vehs_waiting
3587
# must be used to ensure that no vehicle has been occupied in the meanwhile
3588
n_veh_waiting = len(self.get_berths_with_state(id_stop, BERTHSTATES['waiting']))
3589
3590
# waiting vehicles that need to make room for arriving vehicles
3591
n_berth = len(self.ids_berths[id_stop])
3592
surplus_veh_urgent = max(len(self.ids_vehs_inqueue[id_stop])-(n_berth-n_veh_waiting), 0)
3593
return n_veh_waiting, surplus_veh_urgent
3594
3595
def get_vehs_waiting(self, id_stop):
3596
"""Returns lists of empty and occupied waiting vehicles, as well as their respective berth IDs."""
3597
print 'get_vehs_waiting id_stop', id_stop
3598
ids_berth_waiting = self.get_berths_with_state(id_stop, BERTHSTATES['waiting'])
3599
3600
ids_veh_waiting = self.get_berths().ids_veh[ids_berth_waiting]
3601
ids_veh_waiting_empty = []
3602
ids_veh_waiting_occup = []
3603
ids_berth_empty = []
3604
ids_berth_occup = []
3605
for id_berth, id_veh, id_veh_sumo in zip(ids_berth_waiting, ids_veh_waiting, self.parent.prtvehicles.ids_sumo[ids_veh_waiting]):
3606
# check here if these vehicles are still waiting or if
3607
# there has bee a person sitting in
3608
print ' check id_veh_sumo', id_veh_sumo, 'n_pers', traci.vehicle.getPersonNumber(id_veh_sumo)
3609
if traci.vehicle.getPersonNumber(id_veh_sumo) == 0:
3610
ids_veh_waiting_empty.append(id_veh)
3611
ids_berth_empty.append(id_berth)
3612
else:
3613
ids_veh_waiting_occup.append(id_veh)
3614
ids_berth_occup.append(id_berth)
3615
3616
print ' ids_veh_waiting_empty', ids_veh_waiting_empty
3617
return ids_veh_waiting_empty, ids_veh_waiting_occup, ids_berth_empty, ids_berth_occup
3618
3619
def route_empties(self, id_stop, id_stop_target, n_move, simtime):
3620
"""
3621
Route n_move empty vehicles to ids_stop_target.
3622
Route also newly occupied vehicles if present.
3623
Called by vehman
3624
"""
3625
print 'route_empties id_stop', id_stop, '>id_stop_target', id_stop_target, 'n_move', n_move
3626
berths = self.get_berths()
3627
vehicles = self.parent.prtvehicles
3628
ids_veh_empty, ids_veh_waiting_occup, ids_berth, ids_berth_occup = self.get_vehs_waiting(id_stop)
3629
n_veh_empty = len(ids_veh_empty)
3630
n_move_eff = min(n_move, n_veh_empty)
3631
print ' =>n_veh_empty', n_veh_empty, 'n_move_eff', n_move_eff
3632
3633
# if n_move <= n_veh_empty:
3634
3635
for id_berth, id_veh in zip(ids_berth[:n_move], ids_veh_empty[:n_move]):
3636
if self.debug:
3637
print ' route empty veh prt.%d' % id_veh, 'at berth', id_berth, 'from stop', id_stop, ' to', id_stop_target
3638
3639
route, duration = self.route_stop_to_stop(id_stop, id_stop_target)
3640
3641
# print ' found route',route
3642
# print ' found duration',duration
3643
3644
vehicles.set_route_target(id_veh, route, id_stop_target=id_stop_target,
3645
is_disengage_from_berth=True, is_emptytrip=True)
3646
#stopline = self._get_stopline(id_stop, simtime)
3647
# print ' simtime', simtime
3648
3649
berths.set_waiting_routed(id_berth, simtime)
3650
#berths.ids_veh[id_berth] = -1
3651
self.ids_vehs_routed[id_stop].add(id_veh)
3652
3653
# inform vehicle man when started and next destination is determined
3654
# self.parent.vehicleman.init_trip_empty(id_veh, id_stop, id_stop_target, simtime)
3655
3656
if 0: # not necessary, process step will take care of it
3657
for id_berth, id_veh in zip(ids_berth_occup, ids_veh_waiting_occup):
3658
if self.debug:
3659
print ' route occupied veh prt.%d' % id_veh, 'at berth', id_berth, 'from stop', id_stop, ' to', id_stop_target
3660
3661
route, duration = self.route_stop_to_stop(id_stop, id_stop_target)
3662
3663
# print ' found route',route
3664
# print ' found duration',duration
3665
3666
vehicles.set_route_target(id_veh, route, id_stop_target=id_stop_target,
3667
is_disengage_from_berth=True)
3668
#stopline = self._get_stopline(id_stop, simtime)
3669
# print ' simtime', simtime
3670
3671
berths.set_waiting_routed(id_berth, simtime)
3672
#berths.ids_veh[id_berth] = -1
3673
self.ids_vehs_routed[id_stop].add(id_veh)
3674
3675
# else:
3676
# print 'WARNING: on stop %d edge insufficient empty vehicles. Veh Man requested more than present.'%(id_stop)
3677
# return False
3678
3679
# return the effectively sent number of vrhicles to inform
3680
# vehicle management
3681
return n_move_eff
3682
3683
def route_stop_to_stop(self, id_stop_from, id_stop_to):
3684
# route
3685
return self.parent.get_route(self.ids_stop_to_ids_edge[id_stop_from],
3686
self.ids_stop_to_ids_edge[id_stop_to])
3687
3688
def foreward_vehicles_exit(self, id_stop):
3689
"""
3690
Check whether all vehicles moved out of the berth.
3691
If yes, then forward vehicles to the exit.
3692
"""
3693
# Here is the sequance of vehicle control calls and the change
3694
# of states
3695
# vehicles.control_berth_position_exit -> VEHICLESTATES['kickout_berth']
3696
# vehicles.control_berth_position_exit_slowdown -> VEHICLESTATES['forewarding_exit']
3697
# vehicles.control_forewarding_exit -> VEHICLESTATES['forewarding_exit_kickout']
3698
3699
ids_veh_berth_exit = self.ids_vehs_berth_exit[id_stop]
3700
ids_veh_out = self.ids_vehs_out[id_stop]
3701
capa_out = self.capas_outqueue[id_stop]
3702
n_veh = len(ids_veh_berth_exit)
3703
print 'foreward_vehicles_exit check', n_veh
3704
3705
if n_veh == 0:
3706
return False
3707
3708
berths = self.get_berths()
3709
vehicles = self.parent.prtvehicles
3710
3711
are_stopped = np.zeros(n_veh, dtype=np.bool)
3712
for i, id_veh, state in zip(xrange(n_veh), ids_veh_berth_exit, vehicles.states[ids_veh_berth_exit]):
3713
3714
# TODO: here we could also check vehicle position
3715
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3716
# if self.debug:
3717
# print ' ',id_veh_sumo,'state',state,'is_stopped',traci.vehicle.isStopped(id_veh_sumo),'ind_lane',traci.vehicle.getLaneIndex(id_veh_sumo)
3718
# now this is the workaround to prevent passengers
3719
# from jumping on board while the vehicle is stopped
3720
# on the third lane: vehicles that stopped on the 3rd lane
3721
# must be immediately put in (slow) motion
3722
if state == VEHICLESTATES['kickout_berth']:
3723
if traci.vehicle.isStopped(id_veh_sumo) & (traci.vehicle.getLaneIndex(id_veh_sumo) == 2):
3724
vehicles.control_berth_position_exit_slowdown(id_veh) # set VEHICLESTATES['forewarding_exit']
3725
is_stopped = False
3726
else:
3727
# vehicle has been previously stopped to slow speed
3728
is_stopped = state == VEHICLESTATES['forewarding_exit']
3729
3730
are_stopped[i] = is_stopped | (state == VEHICLESTATES['forewarding_passthrough'])
3731
if self.debug:
3732
print ' %s' % id_veh_sumo, 'are_stopped', are_stopped[i], 'stop', traci.vehicle.isStopped(id_veh_sumo), 'state', state, 'laneindex', traci.vehicle.getLaneIndex(id_veh_sumo)
3733
3734
if self.debug:
3735
print ' are_stopped', are_stopped
3736
3737
if np.all(are_stopped):
3738
if self.debug:
3739
print ' all vehicles are moved out of the berth'
3740
3741
# foreward to exit
3742
#ids_veh_out = self.ids_vehs_out[id_stop]
3743
# for id_veh in ids_veh_berth_exit:
3744
# self.append_to_outqueue(id_stop, id_veh)
3745
3746
# here we move to outqueue only if output lenth is not exceeded
3747
# this fixes the problem where passegers jump into vehicles
3748
# when stopping inside the platform range
3749
while (len(ids_veh_berth_exit) > 0) & (len(ids_veh_out) < capa_out):
3750
self.append_to_outqueue(id_stop, ids_veh_berth_exit.pop(0))
3751
3752
if self.debug:
3753
if (len(ids_veh_out) < capa_out):
3754
print ' Out buffer capacity exceeded, left veh:', ids_veh_berth_exit
3755
3756
#self.ids_vehs_berth_exit[id_stop] = []
3757
3758
return True
3759
3760
def append_to_outqueue(self, id_stop, id_veh):
3761
vehicles = self.parent.prtvehicles
3762
ids_veh_out = self.ids_vehs_out[id_stop]
3763
if len(ids_veh_out) == 0:
3764
stoppos = self.stoplines[id_stop]
3765
else:
3766
id_veh_pre, stoppos_pre = ids_veh_out[-1]
3767
stoppos = stoppos_pre - vehicles.length - 1.5*vehicles.dist_min
3768
3769
vehicles.control_forewarding_exit(id_veh,
3770
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],
3771
position=stoppos,
3772
laneindex=2,
3773
)
3774
if self.debug:
3775
print ' append prt.%d to output queue' % id_veh
3776
ids_veh_out.append((id_veh, stoppos))
3777
3778
def get_vehicles_ready_for_departure(self, id_stop):
3779
"""
3780
Check whether vehicles are in the output buffer ready for release.
3781
Theses are all stopped vehicles with identical destination
3782
at the exit of the output queue.
3783
"""
3784
ids_veh_out = self.ids_vehs_out[id_stop]
3785
n_veh = len(ids_veh_out)
3786
ids_veh_ready = self.ids_vehs_ready_for_departure[id_stop]
3787
is_veh_ready = len(ids_veh_ready) > 0
3788
print 'get_vehicles_ready_for_departure check id_stop', id_stop, ' len(ids_vehs_out)', n_veh, 'capa', self.capas_outqueue[id_stop]
3789
if is_veh_ready:
3790
if self.debug:
3791
print ' there are still vehicles ready to be launched'
3792
print ' ids_veh_ready', ids_veh_ready
3793
return []
3794
3795
berths = self.get_berths()
3796
vehicles = self.parent.prtvehicles
3797
if self.debug:
3798
print ' ids_berths_veh_wait_exit', type(self.ids_berths_veh_wait_exit[id_stop]), self.ids_berths_veh_wait_exit[id_stop], 'ids_veh_berth_wait', berths.ids_veh[self.ids_berths_veh_wait_exit[id_stop]]
3799
3800
if (n_veh == 0):
3801
if self.debug:
3802
print ' no vehicles in output queue'
3803
return []
3804
3805
# search after ready vehicles, that will be launched shortly
3806
3807
i = 0 # len(ids_veh_ready)
3808
ids_veh_platoon = []
3809
is_cont = True
3810
id_stopedge_target = -1
3811
while is_cont & (i < n_veh):
3812
id_veh, stoppos = ids_veh_out[i]
3813
if id_stopedge_target == -1: # target not yet defined
3814
id_stopedge_target = vehicles.routes[id_veh][-1]
3815
if self.debug:
3816
# ,'is_stopped',is_stopped
3817
print ' %d Leader prt.%d' % (i, id_veh), 'id_stopedge_target', id_stopedge_target
3818
3819
else:
3820
if self.debug:
3821
print ' %d Follower prt.%d' % (i, id_veh), 'is_cont next', vehicles.routes[id_veh][-1] == id_stopedge_target
3822
3823
if vehicles.routes[id_veh][-1] == id_stopedge_target:
3824
ids_veh_platoon.append((id_veh, stoppos))
3825
i += 1
3826
else:
3827
is_cont = False
3828
3829
if (i == n_veh):
3830
if ((len(self.ids_berths_veh_wait_exit[id_stop]) > 0) | (len(self.ids_vehs_pass_wait_exit[id_stop]) > 0))\
3831
& (i < self.capas_outqueue[id_stop]-1):
3832
if self.debug:
3833
print ' Maybe incomplete platoon, wait till all vehicles are kicked out of berths'
3834
print ' len(ids_berths_veh_wait_exit)', len(self.ids_berths_veh_wait_exit[id_stop]), 'len(ids_vehs_pass_wait_exit)', len(self.ids_vehs_pass_wait_exit[id_stop]), "i", i
3835
return []
3836
else:
3837
# the entire out queue has the same destination
3838
# and will leave the stop
3839
if self.debug:
3840
print ' entire out queue same dest and ready for departure'
3841
#is_update_outqueue = False
3842
else:
3843
# only a part of te out-queue departs, update position of rest
3844
if self.debug:
3845
print ' partial out queue ready for departure'
3846
#is_update_outqueue = True
3847
3848
# Check if all vehicles in the platoon are stopped at the
3849
# defined stopline
3850
id_stopedge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop]
3851
are_stopped = True
3852
are_finalpos = True
3853
ids_veh_ready_new = []
3854
if self.debug:
3855
print ' position check/update ids_veh_platoon', ids_veh_platoon
3856
for id_veh, stoppos in ids_veh_platoon:
3857
3858
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3859
is_stopped = traci.vehicle.isStopped(id_veh_sumo)
3860
if self.debug:
3861
print ' stopcheck ', id_veh_sumo, 'are_stopped', are_stopped, 'is_stopped', is_stopped
3862
3863
if is_stopped:
3864
# check if stopposition is correct
3865
pos_veh = traci.vehicle.getLanePosition(id_veh_sumo)
3866
are_finalpos &= abs(pos_veh-stoppos) < 0.1
3867
are_stopped &= are_finalpos
3868
3869
if 0: # be done for all in _reposition_outqueue
3870
if not is_stopped:
3871
# vehicle is stopped but not at correct position
3872
are_stopped = False
3873
if self.debug:
3874
print ' update stoppos of prt.%s:' % id_veh_sumo, 'from curpos', pos_veh, 'stoppos', stoppos
3875
# vehicle has stopped but not at the correct stop position
3876
# =>foreward vehicle to the correct position
3877
vehicles.control_forewarding_exit(id_veh,
3878
id_edge_sumo=id_stopedge_sumo,
3879
position=stoppos,
3880
laneindex=2,
3881
)
3882
else:
3883
are_stopped = False
3884
3885
#is_pos_correct = traci.vehicle.get
3886
# print ' Veh',id_veh_sumo,'is_stopped',is_stopped
3887
# if not is_veh_ready:# means that there are not already vehicles ready
3888
if self.debug:
3889
print ' append prt.%d to ids_veh_ready_new' % (id_veh)
3890
ids_veh_ready_new.append(id_veh)
3891
3892
if self.debug:
3893
print ' ready? are_stopped %s,' % (are_stopped), 'ids_veh_ready_new', ids_veh_ready_new
3894
3895
# value if platoon is ready to leave
3896
if (not is_veh_ready) & are_stopped:
3897
if self.debug:
3898
print ' all vehicles of the platoon are stopped, platoon ready.'
3899
return ids_veh_ready_new
3900
3901
else:
3902
if not are_finalpos:
3903
self.are_reposition_out[id_stop] = True
3904
if self.debug:
3905
print ' vehicles of platoon not stopped at coorect position or previous ready vehicles not launched.'
3906
else:
3907
if self.debug:
3908
print ' not all vehicles of platoon stopped or previous ready vehicles not launched.'
3909
return []
3910
3911
def _reposition_outqueue(self, id_stop):
3912
# print '_reposition_outqueue id_stop',id_stop
3913
vehicles = self.parent.prtvehicles
3914
id_stopedge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop]
3915
is_reposition = False
3916
for id_veh, stoppos in self.ids_vehs_out[id_stop]:
3917
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3918
pos_veh = traci.vehicle.getLanePosition(id_veh_sumo)
3919
is_correct_pos = abs(pos_veh-stoppos) < 0.1
3920
# print ' update stopcheck ',id_veh_sumo,'is_correct_pos',is_correct_pos
3921
3922
# check if stopposition is corrent
3923
if not is_correct_pos:
3924
3925
if traci.vehicle.isStopped(id_veh_sumo):
3926
3927
# vehicle is stopped but not at correct position
3928
# print ' update stoppos of rem prt.%s:'%id_veh_sumo,'from curpos',pos_veh,'stoppos',stoppos
3929
# vehicle has stopped but not at the correct stop position
3930
# =>foreward vehicle to the correct position
3931
vehicles.control_forewarding_exit(id_veh,
3932
id_edge_sumo=id_stopedge_sumo,
3933
position=stoppos,
3934
laneindex=2,
3935
)
3936
else:
3937
# vehicle needs correction but still in movement
3938
# print ' update stoppos when vehicle is stopped'
3939
is_reposition = True
3940
3941
self.are_reposition_out[id_stop] = is_reposition
3942
3943
def prepare_vehs_for_departure(self, id_stop, ids_veh):
3944
"""
3945
Concatenate vehicles ids_veh with identical destination
3946
and signals ready for departure to vehicle management .
3947
The vehicle management will the check capacity availability
3948
and launch the vehicles with the launch_vehs method.
3949
"""
3950
#ids_veh_out = self.ids_vehs_out[id_stop]
3951
n_veh = len(ids_veh)
3952
print 'prepare_vehs_for_departure id_stop', id_stop, 'n_veh', n_veh
3953
ids_veh_out = self.ids_vehs_out[id_stop]
3954
if n_veh == 0:
3955
return False
3956
3957
vehicles = self.parent.prtvehicles
3958
3959
if n_veh > 1:
3960
# concatenate platoon
3961
for id_veh_infront, id_veh in zip(ids_veh[:-1], ids_veh[1:]):
3962
vehicles.concatenate(id_veh, id_veh_infront)
3963
3964
if self.debug:
3965
print ' prepared:'
3966
for id_veh, route in zip(ids_veh, vehicles.routes[ids_veh]):
3967
id_stopedge = route[-1]
3968
print ' prep. prt.%d' % id_veh, 'with id_stopedge', id_stopedge, 'id_stop', self.id_edge_to_id_stop[id_stopedge]
3969
3970
id_veh_lead = ids_veh[0]
3971
id_stopedge_target = vehicles.routes[id_veh_lead][-1]
3972
id_stop_target = self.id_edge_to_id_stop[id_stopedge_target]
3973
time_est = np.sum(self.parent.edgetimes[vehicles.routes[id_veh_lead]])
3974
self.ids_vehs_ready_for_departure[id_stop] = list(ids_veh)
3975
3976
self.parent.vehicleman.note_vehs_ready_for_departure(id_stop, id_stop_target, time_est, n_veh)
3977
3978
for i in xrange(n_veh):
3979
ids_veh_out.pop(0)
3980
3981
if len(ids_veh_out) > 0:
3982
if self.debug:
3983
print ' position update for remaining ids_veh_out', ids_veh_out
3984
# move foreward stoplines of remaining vehicles in output queue
3985
stopline = self.stoplines[id_stop]
3986
id_edge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop]
3987
for ind in xrange(len(ids_veh_out)):
3988
id_veh, stoppos_prev = ids_veh_out[ind]
3989
stoppos = stopline - ind * (vehicles.length+1.5*vehicles.dist_min)
3990
# vehicles.control_forewarding_exit(id_veh,\
3991
# id_edge_sumo = id_edge_sumo,
3992
# position = stoppos,
3993
# laneindex = 2,
3994
# )
3995
3996
if self.debug:
3997
id_veh_sumo = 'prt.%s' % id_veh
3998
print ' update stoppos of prt.%s:' % id_veh_sumo, 'from curpos', traci.vehicle.getLanePosition(id_veh_sumo), 'to stoppos', stoppos
3999
# print ' stopinfo:',traci.vehicle.getNextStops(id_veh_sumo)
4000
ids_veh_out[ind] = (id_veh, stoppos)
4001
4002
# signal repositioning necessary
4003
self.are_reposition_out[id_stop] = True
4004
4005
def launch_vehs(self, id_stop, id_stop_target):
4006
"""
4007
Method called from vehicle management when vehicles are allowed to depart.
4008
"""
4009
print 'launch_vehs at id_stop', id_stop
4010
ids_veh = self.ids_vehs_ready_for_departure[id_stop]
4011
#ids_veh_out = self.ids_vehs_out[id_stop]
4012
vehicles = self.parent.prtvehicles
4013
#ids_veh = self.ids_vehs_ready_for_departure[id_stop]
4014
# if self.debug:
4015
print ' to launch: ids_veh', ids_veh # ,'with ids_stopedge_next',vehicles.routes[ids_veh]
4016
4017
if len(ids_veh) == 0:
4018
print 'WARNING in launch_vehs: there are no vehicles to lauche at id_stop', id_stop
4019
4020
# here may check if destination stop is correct
4021
4022
for id_veh in ids_veh:
4023
vehicles.launch_from_stop(id_veh)
4024
4025
#id_veh_out, stoppos = ids_veh_out.pop(0)
4026
# if self.debug:
4027
print ' launched prt.%d to id_stopedge_target %d' % (id_veh, vehicles.routes[id_veh][-1])
4028
# if id_veh_out != id_veh:
4029
# print 'WARNING: wrong vehicle from output queue'
4030
# sys.exit(0)
4031
# ids_veh_out.remove(id_veh)
4032
4033
# make sure that first vehicle in remaining out-queue stops at stopline
4034
# if len(ids_veh_out)>0:
4035
# id_veh = ids_veh_out[0]
4036
# vehicles.control_forewarding_exit(id_veh,\
4037
# id_edge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop],
4038
# position = self.stoplines[id_stop],
4039
# laneindex = 2,
4040
# )
4041
4042
return True
4043
4044
def is_outputqueue_compact(self, id_stop):
4045
"""Returns True if all vehicles in the output queue are beyond
4046
the last berth of the stop"""
4047
4048
pos_lastberth = self.get_berths().stoppositions[self.ids_berths[id_stop]][-1]
4049
print 'is_outputqueue_compact n_outqueue', len(self.ids_vehs_out[id_stop]), 'pos_lastberth %.2f' % pos_lastberth
4050
4051
vehicles = self.parent.prtvehicles
4052
is_compact = True
4053
if len(self.ids_vehs_out[id_stop]) > 0:
4054
for id_veh, stoppos in self.ids_vehs_out[id_stop]:
4055
id_veh_sumo = vehicles.get_id_sumo(id_veh)
4056
pos = traci.vehicle.pos = traci.vehicle.getLanePosition(id_veh_sumo)
4057
4058
is_compact &= pos > pos_lastberth
4059
# print ' %s'%id_veh_sumo,'pos %.1f'%pos,is_compact
4060
if not is_compact:
4061
break
4062
else:
4063
for id_veh in self.ids_vehs_ready_for_departure[id_stop]:
4064
id_veh_sumo = vehicles.get_id_sumo(id_veh)
4065
pos = traci.vehicle.pos = traci.vehicle.getLanePosition(id_veh_sumo)
4066
4067
is_compact &= pos > pos_lastberth
4068
# print ' %s'%id_veh_sumo,'pos %.1f'%pos,is_compact
4069
if not is_compact:
4070
break
4071
4072
if self.debug:
4073
print ' is_compact', is_compact
4074
return is_compact
4075
4076
def try_start_vehicles(self, id_stop, simtime, n_plat_min=-1):
4077
"""
4078
Look into already routed vehicles and start vehicles
4079
while maximizing platooning.
4080
"""
4081
4082
print 'try_start_vehicles id_stop', id_stop, 'veh exiting', len(self.ids_vehs_berth_exit[id_stop]),\
4083
'wait from berth', len(self.ids_berths_veh_wait_exit[id_stop]), 'wait to pass', len(
4084
self.ids_vehs_pass_wait_exit[id_stop])
4085
4086
n_plat_max = self.capas_inqueue[id_stop] - \
4087
(len(self.ids_vehs_out[id_stop])+len(self.ids_vehs_ready_for_departure[id_stop]))
4088
if self.debug:
4089
print ' n_plat_max', n_plat_max
4090
if n_plat_max == 0:
4091
if self.debug:
4092
print ' insufficient sapce in output queue'
4093
return False
4094
4095
if len(self.ids_vehs_berth_exit[id_stop]) > 0:
4096
if self.debug:
4097
print ' there are still vehicles moving out of berth'
4098
return False
4099
4100
elif not self.is_outputqueue_compact(id_stop):
4101
if self.debug:
4102
print ' there are still vehicles in berth area toward exit queue'
4103
return False
4104
4105
if self.debug:
4106
print ' len(ids_veh_inqueue)', len(self.ids_vehs_inqueue[id_stop])
4107
if len(self.ids_vehs_inqueue[id_stop]) > 0:
4108
ids_veh_pass = self.get_ids_veh_to_pass(id_stop)
4109
if self.debug:
4110
print ' found ids_veh_pass', ids_veh_pass, 'not yet started!'
4111
else:
4112
ids_veh_pass = []
4113
4114
n_veh_pass = len(ids_veh_pass)
4115
n_veh_pass_wait = len(self.ids_vehs_pass_wait_exit[id_stop])
4116
if self.debug:
4117
print ' n_veh_pass', n_veh_pass, 'n_veh_pass_wait', n_veh_pass_wait
4118
4119
berths = self.get_berths()
4120
vehicles = self.parent.prtvehicles
4121
vehicleman = self.parent.vehicleman
4122
4123
# ids_veh_ready = self.ids_vehs_routed# no let's build this vector
4124
4125
#ids_veh_pass_wait_exit = self.get_ids_veh_pass_wait_exit(id_stop)
4126
4127
if n_veh_pass_wait > 0:
4128
if self.debug:
4129
print ' there are passthrough vehicle in the input queue waiting to get started', self.ids_vehs_pass_wait_exit[id_stop]
4130
print ' ids_veh_pass_wait_exit', self.ids_vehs_pass_wait_exit[id_stop]
4131
# these vehicles have a common target
4132
ids_veh_pass_wait_exit = self.ids_vehs_pass_wait_exit[id_stop]
4133
while len(ids_veh_pass_wait_exit) > 0:
4134
id_veh = ids_veh_pass_wait_exit.pop(0)
4135
vehicles.foreward_passthrough(id_veh)
4136
self.ids_vehs_berth_exit[id_stop].append(id_veh)
4137
# remove from input queue
4138
self.ids_vehs_inqueue[id_stop].remove(id_veh)
4139
4140
return True
4141
4142
elif len(self.ids_berths_veh_wait_exit[id_stop]) > 0:
4143
ids_berth_veh_wait_exit = self.ids_berths_veh_wait_exit[id_stop]
4144
if self.debug:
4145
print ' there are vehicles in berth which are listed to start.', ids_berth_veh_wait_exit
4146
# do start them, sorted by final destination
4147
4148
# print ' ids_berth_veh_wait_exit',ids_berth_veh_wait_exit
4149
ids_veh = berths.ids_veh[ids_berth_veh_wait_exit]
4150
# print ' ids_veh',ids_veh
4151
#ids_targetedge = vehicles.ids_stopedge_target[ids_veh]
4152
# print ' ids_targetedge',ids_targetedge
4153
#id_targetedge_start = vehicles.get_targetedge_current(ids_veh[0])
4154
ids_stop_target = vehicles.ids_stop_target[ids_veh]
4155
inds_start = ids_stop_target == ids_stop_target[0]
4156
if self.debug:
4157
print ' start waiting vehicles', ids_veh[inds_start], 'to final id_stop_target', ids_stop_target[0]
4158
self._kick_out_of_berth(id_stop, ids_veh[inds_start], np.array(
4159
ids_berth_veh_wait_exit, dtype=np.int32)[inds_start], vehicles, berths)
4160
for id_berth in np.array(ids_berth_veh_wait_exit, dtype=np.int32)[inds_start]:
4161
ids_berth_veh_wait_exit.remove(id_berth)
4162
return True
4163
4164
if ((simtime - self.times_phase_out[id_stop]) > self.time_fase_out_max.get_value()) & (n_veh_pass == 0):
4165
# stop starting if move in phase is timed out
4166
if self.debug:
4167
print ' fase move out timeout, stop starting'
4168
return False
4169
4170
# berth in reverse order means that the berth closest to the exit comes first
4171
ids_berth = np.array(self.ids_berths[id_stop][::-1], dtype=np.int32)
4172
4173
inds_berth_ready = np.flatnonzero(berths.states[ids_berth] == BERTHSTATES['waiting_routed'])
4174
ids_berth_ready = ids_berth[inds_berth_ready].copy()
4175
ids_veh_ready = berths.ids_veh[ids_berth[inds_berth_ready]]
4176
n_veh = len(ids_veh_ready)
4177
4178
# deal with vehicle in input queue creating a list of consecutive vehicles
4179
# with common destination
4180
4181
if n_veh_pass > 0:
4182
ids_veh_ready_all = np.concatenate((ids_veh_ready, ids_veh_pass))
4183
else:
4184
ids_veh_ready_all = ids_veh_ready
4185
4186
n_veh_all = n_veh+n_veh_pass
4187
4188
n_edge_max = 0
4189
for i, id_veh, route in zip(xrange(n_veh_all), ids_veh_ready_all, vehicles.routes[ids_veh_ready_all]):
4190
#ids_edge_target[i] = route[-1]
4191
if len(route) > n_edge_max:
4192
n_edge_max = len(route)
4193
4194
ids_stop_target = vehicles.ids_stop_target[ids_veh_ready]
4195
4196
if n_veh_all > 0:
4197
4198
overtime = simtime - berths.times_routes[ids_berth_ready]-self.time_wait_berth_max.get_value()
4199
overtime_berth_ready = overtime * (overtime > 0)
4200
if self.debug:
4201
print ' vehicles ready to leave berth n_veh %d including input n_veh_all %d' % (n_veh, n_veh_all)
4202
print ' ids_stop_target from berths', ids_stop_target
4203
print ' ids_berth', berths.states[ids_berth]
4204
print ' berths.state', berths.states[ids_berth]
4205
print ' ids_berth_ready', ids_berth_ready
4206
print ' ids_veh_ready', ids_veh_ready
4207
print ' ids_veh_ready_all', ids_veh_ready_all
4208
print
4209
print ' simtime', simtime
4210
print ' overtime_berth_ready', overtime_berth_ready
4211
print ' berths.times_routes[ids_berth_ready]', berths.times_routes[ids_berth_ready]
4212
print ' time_wait_berth_max', self.time_wait_berth_max.get_value()
4213
4214
# if 0: # deal with this case in platoon optimizarion
4215
# print ' there are vehhicles in the input queue'
4216
# # check if there are passthrough vehicles in search
4217
# # for vehicles with same dest
4218
4219
if n_veh_pass > 0:
4220
if self.debug:
4221
print ' There is at least one passthrough vehicle which needs to get launched'
4222
#id_edge_target_max = vehicles.get_targetedge_current(ids_veh_pass[0])
4223
id_stop_target_max = vehicles.ids_stop_target[ids_veh_pass[0]]
4224
4225
# other vehicles with id_edge_target_max
4226
inds_veh_plat = ids_stop_target == id_stop_target_max
4227
ids_veh_plat = ids_veh_ready[inds_veh_plat]
4228
ids_berth_plat = ids_berth_ready[inds_veh_plat]
4229
if len(ids_veh_plat) > n_plat_max-n_veh_pass:
4230
if n_plat_max-n_veh_pass > 0:
4231
ids_veh_plat = ids_veh_plat[:n_plat_max-n_veh_pass]
4232
ids_berth_plat = ids_berth_plat[:n_plat_max-n_veh_pass]
4233
else:
4234
ids_veh_plat = np.array([])
4235
ids_berth_plat = np.array([])
4236
4237
if self.debug:
4238
print ' vehs with same dest as pass', ids_veh_plat
4239
4240
self._kick_out_of_berth(id_stop, ids_veh_plat, ids_berth_plat, vehicles, berths)
4241
4242
# add pass.through vehices to the waiting list
4243
# these vehicles will be started as soon as all berth vehicles
4244
# have been started and removed from the ids_vehs_berth_exit list
4245
self.ids_vehs_pass_wait_exit[id_stop] += ids_veh_pass
4246
4247
for id_veh in np.concatenate((ids_veh_plat, ids_veh_pass)):
4248
vehicleman.init_trip(id_veh, id_stop, id_stop_target_max, simtime)
4249
4250
elif (np.any(overtime_berth_ready) > 0) & (n_veh_pass == 0):
4251
if self.debug:
4252
print ' at some berth maximum wait time has been exceeded'
4253
4254
# TODO: launche all vehicles with overtime putting them into self.ids_berths_veh_wait_exit[id_stop]
4255
# take vehicle with maximum wait time and try to create a platoon
4256
4257
id_stop_target_max = ids_stop_target[np.argmax(overtime_berth_ready)]
4258
4259
# other vehicles with id_edge_target_max
4260
inds_veh_plat = ids_stop_target == id_stop_target_max
4261
ids_veh_plat = ids_veh_ready[inds_veh_plat]
4262
ids_berth_plat = ids_berth_ready[inds_veh_plat]
4263
if len(ids_veh_plat) > n_plat_max:
4264
ids_veh_plat = ids_veh_plat[:n_plat_max]
4265
ids_berth_plat = ids_berth_plat[:n_plat_max]
4266
4267
# here next stop is identical with final route
4268
# this may be different for platoons where only
4269
# a subroute is common.
4270
#vehicles.ids_stopedge_next[ids_veh_plat] = id_edge_target_max
4271
# print ' id_edge_target_max',id_edge_target_max,'n_veh_plat',len(ids_veh_plat)
4272
4273
# vehicles leave berth, programming later when platoon is completed
4274
# if destination of platoon are not
4275
self._kick_out_of_berth(id_stop, ids_veh_plat, ids_berth_plat, vehicles, berths)
4276
4277
# for id_veh, id_berth in zip(ids_veh_plat, ids_berth_plat):
4278
# print ' overtime: kick veh %d out of berth %d'%(id_veh, id_berth)
4279
# berths.set_free(id_berth)
4280
# vehicles.control_berth_position_exit( id_veh,\
4281
# id_edge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop],\
4282
# position = berths.stoppositions[id_berth]+0.3,# needs to move sidewards
4283
# laneindex = 2
4284
# )
4285
# # first vehicle in this queue is closest to exit
4286
# self.ids_vehs_berth_exit[id_stop].append(id_veh)
4287
# self.ids_vehs_routed[id_stop].discard(id_veh)
4288
4289
for id_veh in ids_veh_plat:
4290
vehicleman.init_trip(id_veh, id_stop, id_stop_target_max, simtime)
4291
4292
else: # if n_veh > n_plat_min:
4293
4294
print ' Maximize platoon length'
4295
4296
edgeutilities = self.get_scenario().net.edges.lengths
4297
# utilities = np.sum(edgeutilities[routes_common],1)*counts_common
4298
4299
# array with all routes
4300
# is one element longer than longest route because
4301
# -1 is required to detect stop
4302
ids_edges = -1*np.ones((n_veh_all, n_edge_max+1), dtype=np.int32)
4303
4304
for i, id_veh, route in zip(xrange(n_veh_all), ids_veh_ready_all, vehicles.routes[ids_veh_ready_all]):
4305
# print ' get route prt.%d'%id_veh,'i',i,'route',route
4306
ids_edges[i, :len(route)] = route
4307
4308
if self.debug > 9:
4309
print ' ids_edges=\n', ids_edges
4310
n_veh_all, n_edge_max = ids_edges.shape
4311
4312
is_cont = True # not used
4313
j = 3
4314
4315
utility_max = 0.0
4316
route_common_max = []
4317
counts_common_max = 0
4318
4319
while is_cont & (j < n_edge_max):
4320
4321
id_edge_probe = ids_edges[0, j]
4322
4323
inds_stop = np.flatnonzero(ids_edges[:, j] == -1)
4324
if self.debug:
4325
print ' j=', j, 'inds_stop', inds_stop
4326
if len(inds_stop) > 0:
4327
if self.debug:
4328
print ' create set of routes that lead to one of the stops'
4329
occurencies = OrderedDict()
4330
4331
for ids_edge, ind_stop in zip(ids_edges[inds_stop, 0:j-2], inds_stop):
4332
# print ' ind_stop',ind_stop,'ids_edge',ids_edge
4333
occurencies[tuple(ids_edge)] = 0
4334
4335
for ind, ids_edge in zip(xrange(n_veh_all), ids_edges[:, :]):
4336
ids_edge_tuple = tuple(ids_edge[0:j-2])
4337
# print ' check ids_edge',ids_edge
4338
# print ' common?',ids_edge_tuple
4339
# print ' stopinds',np.flatnonzero(ids_edge== -1),(ids_edge== -1)
4340
#j_stop = np.flatnonzero(ids_edge== -1)[0]
4341
#
4342
# here we want at least 50% gain in
4343
# terms of number of edges if the vehicle makes
4344
# an intermediate stop.
4345
# TODO: can be improved by counting the additional km
4346
if ids_edge_tuple in occurencies:
4347
if self._is_stop(j, ids_edge):
4348
occurencies[ids_edge_tuple] += 1
4349
4350
# print ' occurencies',occurencies
4351
routes_common = np.array(occurencies.keys(), dtype=np.int32)
4352
counts_common = occurencies.values()
4353
utilities = np.sum(edgeutilities[routes_common], 1)*counts_common
4354
ind_max = np.argmax(utilities)
4355
4356
# print ' routes_common',routes_common
4357
# print ' counts_common',counts_common
4358
# print ' utilities',utilities
4359
# print ' route_common_max',route_common_max
4360
# print ' utilities[ind_max]',utilities[ind_max]
4361
if utilities[ind_max] > utility_max:
4362
route_common_max = routes_common[ind_max]
4363
# print ' new route_common_max',route_common_max
4364
4365
utility_max = utilities[ind_max]
4366
counts_common_max = counts_common[ind_max]
4367
4368
j += 1
4369
4370
# print '-'*10
4371
if self.debug:
4372
print ' utility_max', utility_max
4373
print ' route_common_max', route_common_max, type(route_common_max)
4374
4375
j_max = len(route_common_max)+2
4376
4377
#ids_edges_out = ids_edges.copy()
4378
4379
inds_stop = np.flatnonzero(ids_edges[:, j_max] == -1)
4380
for ind, ids_edge in zip(inds_stop, ids_edges[inds_stop, 0:j_max-2]):
4381
# print ' ids_edge',ids_edge,np.array_equal(ids_edge, route_common_max)
4382
if np.array_equal(ids_edge, route_common_max):
4383
route_max = ids_edges[ind, :j_max]
4384
break
4385
4386
if self.debug:
4387
print ' route_max', route_max
4388
4389
inds_veh_plat_deviate = []
4390
inds_veh_plat_nodeviate = []
4391
inds_veh_plat = []
4392
for ind, ids_edge, is_stop in zip(xrange(n_veh_all), ids_edges[:, :], ids_edges[:, j_max] == -1):
4393
if np.array_equal(ids_edge[0:j_max-2], route_common_max):
4394
if self._is_stop(j_max, ids_edge):
4395
inds_veh_plat.append(ind)
4396
4397
if not is_stop:
4398
#ids_edges_out[ind, :] = route_max
4399
inds_veh_plat_deviate.append(ind)
4400
else:
4401
inds_veh_plat_nodeviate.append(ind)
4402
4403
# limit platoonlength
4404
if len(inds_veh_plat) > n_plat_max:
4405
if len(inds_veh_plat_nodeviate) > n_plat_max:
4406
inds_veh_plat_nodeviate = inds_veh_plat_nodeviate[:n_plat_max]
4407
inds_veh_plat_deviate = []
4408
else:
4409
inds_veh_plat_deviate = inds_veh_plat_deviate[:n_plat_max-len(inds_veh_plat_nodeviate)]
4410
4411
inds_veh_plat = np.array(inds_veh_plat, dtype=np.int32)
4412
inds_veh_plat_deviate = np.array(inds_veh_plat_deviate, dtype=np.int32)
4413
inds_veh_plat_nodeviate = np.array(inds_veh_plat_nodeviate, dtype=np.int32)
4414
iinds_plat_deviate_berth = inds_veh_plat_deviate < n_veh
4415
iinds_plat_nodeviate_berth = inds_veh_plat_nodeviate < n_veh
4416
iinds_plat_passthrough = inds_veh_plat >= n_veh
4417
# print ' ids_edges_out\n',ids_edges_out
4418
if self.debug:
4419
print ' inds_veh_plat\n', inds_veh_plat
4420
print ' inds_veh_plat_deviate\n', inds_veh_plat_deviate
4421
print ' inds_veh_plat_nodeviate\n', inds_veh_plat_nodeviate
4422
print ' inds_veh_plat_deviate_berth\n', inds_veh_plat_deviate[iinds_plat_deviate_berth]
4423
print ' inds_veh_plat_nodeviate_berth\n', inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]
4424
print ' iinds_plat_passthrough\n', iinds_plat_passthrough
4425
print ' inds_veh_plat_passthrough\n', inds_veh_plat[iinds_plat_passthrough]
4426
4427
n_veh_plat = len(inds_veh_plat)
4428
# print ' id_edge_target_max',id_edge_target_max,'n_veh_plat',n_veh_plat,n_veh_plat >= n_plat_min
4429
4430
if (n_veh_plat >= n_plat_min) | (np.max(inds_veh_plat) >= n_veh):
4431
if self.debug:
4432
print ' platoon formation long enough n_veh_plat', n_veh_plat, 'or passthrough', (np.max(inds_veh_plat) >= n_veh)
4433
4434
print ' deviate vehicles berth', ids_veh_ready_all[inds_veh_plat_deviate[iinds_plat_deviate_berth]]
4435
for id_veh in ids_veh_ready_all[inds_veh_plat_deviate[iinds_plat_deviate_berth]]:
4436
# note that all routed vehicles are already disengaged
4437
vehicles.set_route_target(id_veh, route_max, is_disengage_from_berth=False)
4438
if self.debug:
4439
print ' deviate vehicles passthrough', ids_veh_ready_all[inds_veh_plat_deviate[np.logical_not(iinds_plat_deviate_berth)]]
4440
for id_veh in ids_veh_ready_all[inds_veh_plat_deviate[np.logical_not(iinds_plat_deviate_berth)]]:
4441
vehicles.set_route_target(id_veh, route_max)
4442
# ?here next stop is identical with final route
4443
# ?this may be different for platoons where only
4444
# ?a subroute is common.
4445
# ?vehicles.ids_stopedge_next[ids_veh_plat] = id_edge_target_max
4446
4447
# start immediately vehicles with final destination from berths
4448
if self.debug:
4449
print ' kick out ids_veh', ids_veh_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]]
4450
print ' from berths ', ids_berth_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]]
4451
self._kick_out_of_berth(id_stop, ids_veh_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]],
4452
ids_berth_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]], vehicles, berths)
4453
4454
# add vehicles which require deviation to a waiting list
4455
# they will be started later while being sorted by final
4456
# destination
4457
if self.debug:
4458
print ' ids_berths_veh_wait_exit before', self.ids_berths_veh_wait_exit[id_stop]
4459
self.ids_berths_veh_wait_exit[id_stop] += ids_berth_ready[inds_veh_plat_deviate[iinds_plat_deviate_berth]].tolist()
4460
if self.debug:
4461
print ' ids_berths_veh_wait_exit after ', self.ids_berths_veh_wait_exit[id_stop]
4462
print ' ids_berth_ready', ids_berth_ready
4463
# ATTENTION: vehicles waiting in input queue cannot be sorted by destination...
4464
# but they are supposed to be sorted already?
4465
4466
self.ids_vehs_pass_wait_exit[id_stop] += ids_veh_ready_all[inds_veh_plat[iinds_plat_passthrough]].tolist()
4467
if self.debug:
4468
print ' ids_vehs_pass_wait_exit after ', self.ids_vehs_pass_wait_exit[id_stop]
4469
4470
# get the destination stop from final stop of the undevieted winner
4471
id_stop_target_max = vehicles.ids_stop_target[ids_veh_ready_all[inds_veh_plat_nodeviate[0]]]
4472
for id_veh in ids_veh_ready_all[inds_veh_plat]:
4473
vehicleman.init_trip(id_veh, id_stop, id_stop_target_max, simtime)
4474
return True
4475
4476
else:
4477
if self.debug:
4478
print ' platoon too short'
4479
return False
4480
4481
else:
4482
if self.debug:
4483
print ' no vehicles finished boarding'
4484
return False
4485
4486
def _is_stop(self, j, ids_edge):
4487
j_stop = np.flatnonzero(ids_edge == -1)[0]
4488
# TODO: measure gain in distance
4489
ans = (j == j_stop) | (j_stop > 1.1*j)
4490
# print ' _is_stop:',ans,'j',j, 'j_stop',j_stop,'===', (j_stop == j),'|', ( j_stop > 1.5*j)
4491
4492
return ans
4493
4494
def _kick_out_of_berth(self, id_stop, ids_veh_plat, ids_berth_plat, vehicles, berths):
4495
for id_veh, id_berth in zip(ids_veh_plat, ids_berth_plat):
4496
print ' kick veh %d out of berth %d and set berth free' % (id_veh, id_berth)
4497
berths.set_free(id_berth)
4498
vehicles.control_berth_position_exit(id_veh,
4499
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],\
4500
# position = berths.stoppositions[id_berth]+0.3,# needs to move sidewards
4501
laneindex=2
4502
)
4503
# first vehicle in this queue is closest to exit??
4504
self.ids_vehs_berth_exit[id_stop].append(id_veh)
4505
self.ids_vehs_routed[id_stop].discard(id_veh)
4506
4507
# print ' ids_vehs_berth_exit',self.ids_vehs_berth_exit[id_stop]
4508
# print ' freed berth %d state %d'%(id_berth,berths.states[id_berth])
4509
4510
def get_berths_with_state(self, id_stop, state):
4511
4512
ids_berth = np.array(self.ids_berths[id_stop], dtype=np.int32)
4513
#inds = np.flatnonzero(self.get_berths().states[ids_berth] == state)
4514
# if len(inds)>0:
4515
# return ids_berth[inds]
4516
# else:
4517
# return []
4518
return ids_berth[self.get_berths().states[ids_berth] == state]
4519
4520
def enter(self, id_stop, ids_veh, fase, simtime):
4521
print 'enter ids_veh', ids_veh
4522
4523
vehicles = self.parent.prtvehicles
4524
4525
# print ' ids_vehs',self.ids_vehs[id_stop],type(self.ids_vehs[id_stop])
4526
#ids_veh_current = self.ids_vehs[id_stop]
4527
# print ' ids_veh_current',ids_veh_current,'ids_veh',ids_veh,type(ids_veh)
4528
#ids_veh_current += ids_veh
4529
# print ' ids_veh_current',ids_veh_current
4530
self.ids_vehs[id_stop] += ids_veh.tolist()
4531
# self.ids_vehs[id_stop].append(id_veh)
4532
# print ' ids_vehs',self.ids_vehs[id_stop],type(self.ids_vehs[id_stop])
4533
id_stopedge = self.ids_stop_to_ids_edge[id_stop]
4534
n_veh = len(ids_veh)
4535
4536
self.numbers_veh[id_stop] += n_veh
4537
are_completed = np.zeros(n_veh, dtype=np.bool)
4538
for id_veh, i in zip(ids_veh, xrange(n_veh)):
4539
4540
vehicles.decatenate(id_veh)
4541
# here we should check whether the vehicle needs to alight
4542
# or wether it is a pass through
4543
route = vehicles.routes[id_veh]
4544
if self.debug:
4545
print ' enter prt.%d' % id_veh, 'with id_stop_target', vehicles.ids_stop_target[id_veh], 'route', route
4546
if len(route) == 0:
4547
# vehicle just initialized
4548
are_completed[i] = True
4549
else:
4550
if vehicles.ids_stop_target[id_veh] == id_stop:
4551
# vehicle reached destination stop
4552
are_completed[i] = True
4553
4554
# tell vehman that veh arrived
4555
self.parent.vehicleman.conclude_trip(id_veh, id_stop, is_final_dest=True)
4556
4557
# tell veicle that trip is completed
4558
# TODO: could be performed by vehman
4559
vehicles.set_route_completed(id_veh)
4560
4561
else:
4562
# stop is not final desination
4563
are_completed[i] = False
4564
# tell vehman that veh arrived, but trip not concluded
4565
self.parent.vehicleman.conclude_trip(id_veh, id_stop, is_final_dest=False)
4566
4567
if np.all(are_completed):
4568
ids_veh_completed = ids_veh.copy()
4569
4570
else:
4571
ind_first_passthrough = np.flatnonzero(np.logical_not(are_completed))[0]
4572
ids_veh_completed = ids_veh[:ind_first_passthrough]
4573
4574
n_veh_completed = len(ids_veh_completed)
4575
ids_berth = -1*np.ones(n_veh, dtype=np.int32)
4576
if self.debug:
4577
print ' n_veh_completed', n_veh_completed, 'no Timeout', ((simtime - self.times_phase_in[id_stop]) < self.time_fase_in_max.get_value()), 'veh input', self.ids_vehs_inqueue[id_stop]
4578
# if fase == FASE_MOVE_IN:
4579
# print ' timeout fase 0: dt=%.2f timeout=%.2f'%((simtime - self.times_phase_in[id_stop]), self.time_fase_in_max.get_value())
4580
if n_veh_completed > 0:
4581
# (simtime - self.times_phase_in[id_stop]), self.time_fase_in_max.get_value())
4582
if self.debug:
4583
# ,(len(self.ids_vehs_inqueue[id_stop]) == 0),((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value())
4584
print ' fase', fase
4585
if (fase == FASE_MOVE_IN) & (len(self.ids_vehs_inqueue[id_stop]) == 0)\
4586
& ((simtime - self.times_phase_in[id_stop]) < self.time_fase_in_max.get_value()):
4587
# here vehicles are sent to berth, if available
4588
# bit only in move in fase, there are no other vehicles
4589
# to allocate in the ids_vehs_to_allocate queue
4590
# and if move in fase time out has not been reached
4591
4592
# allocate berth only for vehicles which completed trip at this stop
4593
ids_berth_completed = self.allocate_alight(id_stop, n_veh_completed)
4594
if self.debug:
4595
print ' ids_berth_completed', ids_berth_completed
4596
ids_berth[are_completed] = ids_berth_completed
4597
4598
is_stop_moving_in = False
4599
for id_veh, state, id_berth, is_completed in zip(ids_veh, vehicles.states[ids_veh], ids_berth, are_completed):
4600
if self.debug:
4601
print ' check id_veh', id_veh, 'id_berth', id_berth, 'is_completed', is_completed, 'state', state
4602
4603
if not is_completed:
4604
# will be send directly to output queue
4605
if self.debug:
4606
print ' passthrough, not final destination of vehicle.'
4607
4608
is_stop_moving_in = True
4609
if self.debug:
4610
print ' stop before first berths, wait for try_start at %.1fm' % (self.stoplines_in[id_stop])
4611
4612
# this vehicle does not get allocated to a berth
4613
# but will wait until vehicles with same destination move out
4614
# if len(self.ids_vehs_inqueue[id_stop])>0:
4615
# id_veh_infront = self.ids_vehs_inqueue[id_stop][-1]
4616
# else:
4617
# id_veh_infront = -1
4618
4619
self.ids_vehs_inqueue[id_stop].append(id_veh)
4620
vehicles.init_passthrough(id_veh,
4621
self.ids_stop_to_ids_edge_sumo[id_stop],
4622
self.stoplines_in[id_stop],
4623
laneindex=2,
4624
#id_veh_infront = id_veh_infront,
4625
)
4626
# vehicle needs also to be rerouted to its target
4627
# TODO: this is a little bit crazy, routing could be done in vehicles
4628
4629
route, duration = self.parent.get_route(
4630
id_stopedge, self.ids_stop_to_ids_edge[vehicles.ids_stop_target[id_veh]])
4631
vehicles.set_route_target(id_veh, route)
4632
#stopline = self._get_stopline(id_stop, simtime)
4633
# print ' simtime', simtime
4634
4635
#berths.set_waiting_routed(id_berth, simtime)
4636
#berths.ids_veh[id_berth] = -1
4637
# todo: is this necessary? no further use...
4638
self.ids_vehs_routed[id_stop].add(id_veh)
4639
4640
elif id_berth == -1:
4641
if self.debug:
4642
print ' trip is completed but no berth => stop vehicles from moving in'
4643
is_stop_moving_in = True
4644
if self.debug:
4645
print ' stop before first berths and wait for allocation at %.1fm' % (self.stoplines_in[id_stop])
4646
self.ids_vehs_inqueue[id_stop].append(id_veh)
4647
vehicles.control_stopline_enter(id_veh,
4648
self.ids_stop_to_ids_edge_sumo[id_stop],
4649
self.stoplines_in[id_stop],
4650
laneindex=2)
4651
4652
elif (not is_stop_moving_in) & (id_berth != -1):
4653
if self.debug:
4654
print ' forewrard entering vehicle id_veh %d to id_berth_alight %d at pos %.2fm' % (id_veh, id_berth, self.get_berths().stoppositions[id_berth])
4655
self.ids_vehs_alight_forward[id_stop].append(id_veh)
4656
vehicles.control_berth_position_enter(
4657
id_veh, id_berth,
4658
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],
4659
position=self.get_berths().stoppositions[id_berth]-0.3, # needs to stop a bit before to move in
4660
laneindex=2,
4661
)
4662
if self.debug:
4663
print ' ids_vehs_inqueue (after)', self.ids_vehs_inqueue[id_stop]
4664
4665
def get_ids_veh_to_allocate(self, id_stop):
4666
"""Returns vehicle in input queue that needs berth allocation.
4667
But only vehicles in front of passthrough vehicles are considered.
4668
"""
4669
# print 'get_ids_veh_to_allocate id_stop',id_stop
4670
ids_veh = np.array(self.ids_vehs_inqueue[id_stop], dtype=np.int32)
4671
if len(ids_veh) > 0:
4672
are_forewarding = (self.parent.prtvehicles.states[ids_veh] == VEHICLESTATES['forewarding'])
4673
# print ' ids_veh in queue',ids_veh
4674
# print ' are_forewarding',are_forewarding
4675
if np.all(are_forewarding):
4676
return ids_veh.tolist()
4677
else:
4678
# print ' inds',np.flatnonzero(np.logical_not(are_forewarding))
4679
return ids_veh[0:np.flatnonzero(np.logical_not(are_forewarding))[0]].tolist()
4680
else:
4681
return []
4682
4683
def get_ids_veh_to_pass(self, id_stop):
4684
"""Retuns a list of vehicle IDs which are in pass through vehicles
4685
at the pole position of the input queue. All vehicles have the same destinaton.
4686
"""
4687
ids_veh_inqueue = np.array(self.ids_vehs_inqueue[id_stop], dtype=np.int32)
4688
# print 'get_ids_veh_to_pass id_stop',id_stop,len(ids_veh_inqueue),ids_veh_inqueue
4689
if len(ids_veh_inqueue) > 0:
4690
are_pass = self.parent.prtvehicles.states[ids_veh_inqueue] == VEHICLESTATES['forewarding_passthrough']
4691
# print ' are_pass[0]',are_pass[0],are_pass
4692
if are_pass[0]:
4693
# print ' ids_veh_inqueue',ids_veh_inqueue
4694
# print ' are_pass',are_pass
4695
# there is a pass through vehicle in pole position
4696
ids_stop_target = self.parent.prtvehicles.ids_stop_target[ids_veh_inqueue]
4697
# print ' ids_stopedge_target',ids_stopedge_target
4698
# algorithm to identify a cosecutive sequence of
4699
# passthrough vehicles
4700
are_firststop = ids_stop_target == ids_stop_target[0]
4701
# print ' are_firststop',are_firststop
4702
if np.all(are_firststop):
4703
ind_firststop = len(are_firststop)-1
4704
else:
4705
ind_firststop = np.flatnonzero(np.logical_xor(are_firststop[:-1], are_firststop[1:]))[0]
4706
4707
if np.all(are_pass):
4708
ind_pass = len(are_pass)-1
4709
else:
4710
ind_pass = np.flatnonzero(np.logical_xor(are_pass[:-1], are_pass[1:]))[0]
4711
4712
ind = min(ind_firststop, ind_pass)+1
4713
# print ' ind_firststop',ind_firststop,'ind_pass',ind_pass,'ind',ind
4714
return ids_veh_inqueue[:ind].tolist()
4715
4716
else:
4717
# first veh is not passthrough
4718
return []
4719
4720
else:
4721
return []
4722
4723
def exit(self, id_stop, id_veh, fase):
4724
print 'exit prt.%d at stop %d fase %d' % (id_veh, id_stop, fase)
4725
self.ids_vehs[id_stop].remove(id_veh)
4726
self.ids_vehs_ready_for_departure[id_stop].remove(id_veh)
4727
#id_stop_target = self.parent.vehicleman.start_trip(id_veh, id_stop)
4728
#self.parent.prtvehicles.reschedule_trip(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target])
4729
#ind_veh = -1
4730
# print ' ids_vehs_prog=\n',self.ids_vehs_prog[id_stop]
4731
# i=0
4732
# for time_start, id_veh_prog, id_stop_target, is_prog in self.ids_vehs_prog[id_stop]:
4733
# if id_veh_prog == id_veh:
4734
# self.ids_vehs_prog[id_stop].pop(i)
4735
# break
4736
# i =+1
4737
4738
# self.ids_vehs_prog[id_stop].remove(id_veh)
4739
4740
self.numbers_veh[id_stop] -= 1
4741
4742
def allocate_alight(self, id_stop, n_alloc):
4743
"""
4744
Return a vector of n_alloc berth IDs to be allocated for alighting/boarding
4745
at given stop ID.
4746
-1 means no berth could be allocated
4747
"""
4748
4749
# here we want that vehicles allocate berth with person queues
4750
# but we also want to allocate all vehicles if this is possible
4751
4752
# current berth allocation index running from
4753
# n_berth_to_allocate-1 to 0
4754
ind_berth_to_allocate = self.inds_berth_allocated[id_stop]
4755
4756
# get berth available for allocation
4757
ids_berth_to_allocate = self.ids_berths_to_allocate[id_stop][:ind_berth_to_allocate]
4758
# ids_berth_to_allocate.reverse()# index 0 is first to be allocated
4759
4760
# number of berth available for allocation
4761
n_berth_to_allocate = len(ids_berth_to_allocate)
4762
4763
# allocated berth vector
4764
# default berth ID is -1 means no merth available
4765
ids_berth_alloc = -1*np.ones(n_alloc, dtype=np.int32)
4766
4767
print 'allocate_alight n_alloc', n_alloc, 'n_berth_to_allocate', n_berth_to_allocate, 'ind_berth_to_allocate', ind_berth_to_allocate
4768
if self.debug:
4769
print ' ids_berth_to_allocate', ids_berth_to_allocate
4770
4771
if ind_berth_to_allocate == -1:
4772
if self.debug:
4773
print ' no free berth :('
4774
return ids_berth_alloc
4775
4776
elif n_berth_to_allocate <= n_alloc:
4777
if self.debug:
4778
print ' there is a less or equal number of free berth than requested'
4779
# => use all berth available for allocatation
4780
ids_berth_alloc[0:n_berth_to_allocate] = ids_berth_to_allocate[0:n_berth_to_allocate]
4781
self.inds_berth_allocated[id_stop] = -1
4782
4783
else:
4784
if self.debug:
4785
print ' there are more berths available than vehicles to allocate'
4786
# -> prefer berth with person queues
4787
queues = self.get_berthqueues(id_stop, ids_berth_to_allocate)
4788
#inds_nonzeroqueues = np.flatnonzero(ids_berth_to_allocate[::-1])
4789
4790
ind_alloc_eff = -1 # effective allocation index for result vector
4791
for i, queue, id_berth in zip(xrange(n_berth_to_allocate), queues[::-1], ids_berth_to_allocate[::-1]):
4792
print ' index i', i, 'id_berth', id_berth, 'queue', queue
4793
self.inds_berth_allocated[id_stop] -= 1
4794
if queue == 0:
4795
if self.debug:
4796
print ' no passengers waiting'
4797
4798
# allocate this berth only if the number of the remaining
4799
# available berth is less or equal the number of berth
4800
# that remain to be allocated
4801
is_allzero = not np.any(queues[::-1][i:])
4802
if self.debug:
4803
print ' remaining berth to alloc', ids_berth_to_allocate[::-1][i:]
4804
print ' remaining queus to alloc', queues[::-1][i:]
4805
print ' rem avail', n_berth_to_allocate-(i+1), 'rem to alloc', n_alloc-(ind_alloc_eff + 1), 'is_allzero', is_allzero
4806
if is_allzero | ((n_berth_to_allocate-(i+1)) < (n_alloc-(ind_alloc_eff + 1))):
4807
ind_alloc_eff += 1
4808
ids_berth_alloc[ind_alloc_eff] = id_berth
4809
if self.debug:
4810
print ' allocate id_berth', id_berth, 'at index', i
4811
else:
4812
if self.debug:
4813
print ' passengers waiting, allocate'
4814
ind_alloc_eff += 1
4815
ids_berth_alloc[ind_alloc_eff] = id_berth
4816
4817
if self.debug:
4818
print ' allocate id_berth', id_berth, 'at index', i
4819
4820
if n_alloc == ind_alloc_eff + 1:
4821
if self.debug:
4822
print ' all vehicles allocated. Stop allocating.'
4823
break
4824
4825
if self.debug:
4826
print ' finished allocating i', i, 'ind_berth_to_allocate', ind_berth_to_allocate, 'rem', n_berth_to_allocate-(i+1)
4827
4828
# print ' inds_berth_allocated',self.inds_berth_allocated [id_stop],n_berth_to_allocate-(i+1)
4829
#self.inds_berth_allocated [id_stop] = n_berth_to_allocate-(i+1)
4830
if self.debug:
4831
print ' ids_berth_alloc', ids_berth_alloc
4832
# set allocated to found berth only
4833
self.get_berths().set_allocate(ids_berth_alloc[ids_berth_alloc > -1])
4834
4835
return ids_berth_alloc
4836
4837
def is_queue(self, id_stop, id_berth):
4838
"""
4839
Returns True if there is at least 1 person detected at id_berth at id_stop
4840
"""
4841
# print 'get_berthqueues',id_stop
4842
# TODO: use stop angle and person angle to detect waiting persons
4843
# problem: persons just passing by are detected as queue
4844
stopposition = self.get_berths().stoppositions[id_berth]
4845
# print ' stopposition',stopposition
4846
is_queue = False
4847
for id_person_sumo in self.waittimes_persons[id_stop].keys():
4848
is_queue = np.abs(stopposition-traci.person.getLanePosition(id_person_sumo)) < 0.8
4849
if is_queue:
4850
break
4851
4852
return is_queue
4853
4854
def get_berthqueues(self, id_stop, ids_berth):
4855
print 'get_berthqueues ids_berth', ids_berth
4856
# currently not used
4857
# print 'get_berthqueues',id_stop
4858
# TODO: use stop angle and person angle to detect waiting persons
4859
stoppositions = self.get_berths().stoppositions[ids_berth]
4860
queues = np.zeros(len(ids_berth), dtype=np.int32)
4861
# print ' stoppositions',stoppositions
4862
for id_person_sumo in self.waittimes_persons[id_stop].keys():
4863
stage = traci.person.getStage(id_person_sumo, 0)
4864
if self.debug:
4865
print ' check id_person_sumo', id_person_sumo, 'Stagetype', stage.type, 'pos', traci.person.getLanePosition(id_person_sumo)
4866
# check if person is in wait pos! Actually this is stage type driving = 3
4867
if stage.type == 3:
4868
position = traci.person.getLanePosition(id_person_sumo)
4869
# print ' position',position
4870
dists = np.abs(stoppositions-position)
4871
# print ' dists',dists,np.any(dists<5)
4872
if np.any(dists < 0.8):
4873
ind_berth = np.argmin(dists)
4874
queues[ind_berth] += 1
4875
4876
# print ' queues=\n',queues
4877
return queues
4878
4879
def make_from_net(self):
4880
"""
4881
Make prt stop database from PT stops in network.
4882
"""
4883
print 'make_from_net'
4884
self.clear()
4885
net = self.get_scenario().net
4886
ptstops = net.ptstops
4887
4888
ids_ptstop = ptstops.get_ids()
4889
4890
id_mode_prt = self.parent.id_prtmode
4891
id_mode_ped = net.modes.get_id_mode('pedestrian')
4892
4893
ids_modes_allow = net.lanes.ids_modes_allow
4894
#get_accesslevel = net.lanes.get_accesslevel
4895
4896
ids_stoplane = ptstops.ids_lane[ids_ptstop]
4897
ids_stopedges = net.lanes.ids_edge[ids_stoplane]
4898
ids_stoplanes = net.edges.ids_lanes[ids_stopedges]
4899
edgelengths = net.edges.lengths[ids_stopedges]
4900
4901
for id_stop, ids_lane, id_lane, position_from, position_to, edgelength in zip(
4902
ids_ptstop,
4903
ids_stoplanes,
4904
ids_stoplane,
4905
ptstops.positions_from[ids_ptstop],
4906
ptstops.positions_to[ids_ptstop],
4907
edgelengths
4908
):
4909
print ' check', id_stop, 'number of lanes', len(ids_lane), ids_lane
4910
4911
ids_mode_allow = ids_modes_allow[ids_lane]
4912
if len(ids_lane) == 3:
4913
# check access of all lanes:
4914
# lane 0: at least ped access
4915
# lane 1: exclusive PRT access
4916
# lane 2: exclusive PRT access
4917
# print ' ids_modes_allow:',ids_mode_allow[0],ids_mode_allow[1],ids_mode_allow[2]
4918
4919
if (len(ids_mode_allow[1]) == 1) & (len(ids_mode_allow[2]) == 1):
4920
# print ' ids_mode_allow[1][0],ids_mode_allow[2][0]',ids_mode_allow[1][0],ids_mode_allow[2][0],id_mode_prt
4921
# print ' ',id_mode_ped in ids_mode_allow[0],id_mode_prt == ids_mode_allow[1][0],(id_mode_prt == ids_mode_allow[2][0])
4922
4923
if (id_mode_ped in ids_mode_allow[0]) & (id_mode_prt == ids_mode_allow[1][0]) & (id_mode_prt == ids_mode_allow[2][0]):
4924
self.make(id_stop,
4925
position_from,
4926
position_to)
4927
4928
self.parent.make_fstar(is_update=True)
4929
self.parent.make_times_stop_to_stop()
4930
4931
def make(self, id_ptstop, position_from, position_to):
4932
"""
4933
Initialize a new prt stop and generate berth.
4934
"""
4935
id_stop = self.add_row(ids_ptstop=id_ptstop)
4936
ids_berth = self.get_berths().make(id_stop, position_from=position_from,
4937
position_to=position_to)
4938
self.ids_berths[id_stop] = list(ids_berth) # IDs must be in a list
4939
return id_stop
4940
4941
4942
class VehicleAdder(Process):
4943
def __init__(self, vehicles, logger=None, **kwargs):
4944
print 'VehicleAdder.__init__', vehicles, vehicles.parent.get_ident()
4945
self._init_common('vehicleadder', name='Vehicle adder',
4946
logger=logger,
4947
info='Add vehicles to PRT stops of network.',
4948
)
4949
self._vehicles = vehicles
4950
4951
attrsman = self.set_attrsman(cm.Attrsman(self))
4952
4953
self.n_vehicles = attrsman.add(cm.AttrConf('n_vehicles', kwargs.get('n_vehicles', -1),
4954
groupnames=['options'],
4955
perm='rw',
4956
name='Number of vehicles',
4957
info='Number of PRT vehicles to be added to the network. Use -1 to fill all present PRT stations.',
4958
))
4959
4960
def do(self):
4961
# print 'VehicleAdder.do'
4962
self._vehicles.add_to_net(n=self.n_vehicles)
4963
return True
4964
4965
4966
class PrtVehicles(am.ArrayObjman):
4967
4968
def __init__(self, ident, prtservices, **kwargs):
4969
# print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1')
4970
self._init_objman(ident=ident,
4971
parent=prtservices,
4972
name='PRT Veh.',
4973
info='PRT vehicle database. These are shared vehicles.',
4974
version=0.2,
4975
**kwargs)
4976
4977
self._init_attributes()
4978
4979
def _init_attributes(self):
4980
vtypes = self.get_scenario().demand.vtypes
4981
net = self.get_scenario().net
4982
4983
self.add(cm.AttrConf('time_update', 0.5,
4984
groupnames=['parameters'],
4985
name='Update time',
4986
info="Update time for traci controlled vehicles, es. at merge points.",
4987
unit='s',
4988
))
4989
4990
self.add(cm.AttrConf('speed_max', 10.0,
4991
groupnames=['parameters'],
4992
name='Maximum speed',
4993
info="Maximum achievable speed.",
4994
unit='m/s',
4995
))
4996
4997
self.add(cm.AttrConf('time_emergency', 0.5,
4998
groupnames=['parameters'],
4999
name='Emergency reaction time',
5000
info="Time to react to emergency situations.",
5001
unit='s',
5002
))
5003
5004
self.add(cm.AttrConf('decel_comfort', 2.5,
5005
groupnames=['parameters'],
5006
name='Comfort deceleration',
5007
info="Comfort deceleration.",
5008
unit='m/s^2',
5009
))
5010
5011
self.add(cm.AttrConf('decel_emergency', 5.0,
5012
groupnames=['parameters'],
5013
name='Emergency deceleration',
5014
info="Emergency deceleration.",
5015
unit='m/s^2',
5016
))
5017
5018
self.add(cm.AttrConf('n_ghosts_max', 4,
5019
groupnames=['parameters'],
5020
name='Max ghosts',
5021
info="Maximum number of ghost vehicles. Ghost vehicles are used in merge controls.",
5022
))
5023
5024
# TODO: add/update vtypes here
5025
self.add_col(SumoIdsConf('Veh', xmltag='id'))
5026
5027
id_vtype = self.make_vtype()
5028
5029
if not hasattr(self, 'ids_vtype'):
5030
5031
self.add_col(am.IdsArrayConf('ids_vtype', vtypes,
5032
id_default=id_vtype,
5033
groupnames=['parameters'],
5034
name='Veh. type',
5035
info='PRT vehicle type.',
5036
#xmltag = 'type',
5037
))
5038
else:
5039
# this imposes parameters to alresdy existing data
5040
self.ids_vtype[self.get_ids()] = id_vtype
5041
5042
if self.get_version() < 0.2:
5043
5044
self.ids_vtype._default = id_vtype
5045
5046
self.add_col(am.ArrayConf('states', default=VEHICLESTATES['init'],
5047
dtype=np.int32,
5048
groupnames=['state'],
5049
choices=VEHICLESTATES,
5050
name='state',
5051
info='State of vehicle.',
5052
))
5053
5054
# self.add_col(am.IdsArrayConf( 'ids_targetprtstop', self.parent.prtstops,
5055
# groupnames = ['parameters'],
5056
# name = 'Target stop ID',
5057
# info = 'ID of current target PRT stop.',
5058
# ))
5059
5060
self.add_col(am.IdsArrayConf('ids_currentedge', net.edges,
5061
groupnames=['state'],
5062
name='Current edge ID',
5063
info='Edge ID of most recent reported position.',
5064
))
5065
5066
# self.add_col(am.IdsArrayConf( 'ids_targetedge', net.edges,
5067
# groupnames = ['state'],
5068
# name = 'Target edge ID',
5069
# info = 'Target edge ID to be reached. This can be either intermediate target edges (), such as a compressor station.',
5070
# ))
5071
5072
self.set_version(0.2)
5073
5074
def _init_constants(self):
5075
5076
self.do_not_save_attrs([
5077
'length',
5078
'tau', 'ids_berth',
5079
'are_update', 'velocities',
5080
'odos', 'ids_ghosts',
5081
'diststomerge0', 'diststomerge0_ghosts',
5082
'dists0', 'odos0_vehicles', 'odos0_ghosts',
5083
'ids_leader', 'ids_follower', 'lengths_plat',
5084
'ids_persons_sumo',
5085
])
5086
5087
def get_net(self):
5088
return self.parent.get_scenario().net
5089
5090
def make_vtype(self, is_reset_vtype=False):
5091
5092
vtypes = self.get_scenario().demand.vtypes
5093
prttype = 'HCPRT'
5094
print 'make_vtype HPRT', prttype
5095
# speedmode
5096
# https://sumo.dlr.de/docs/TraCI/Change_Vehicle_State.html
5097
# bit0: Regard safe speed
5098
# bit1: Regard maximum acceleration
5099
# bit2: Regard maximum deceleration -
5100
# bit3: Regard right of way at intersections
5101
# bit4: Brake hard to avoid passing a red light
5102
5103
#self._speedmode_leader = 7
5104
#self._speedmode_follower = 6
5105
5106
self._speedmode_leader = 7
5107
self._speedmode_follower = 1
5108
5109
self._factor_speed_leader = 0.9
5110
self._factor_speed_follower = 2.0
5111
5112
self._accel_leader = 2.5
5113
self._accel_follower = 5.0
5114
5115
self._decel_leader = self.decel_comfort.get_value()
5116
self._decel_follower = self.decel_comfort.get_value()
5117
5118
self._decel_emergency_leader = self.decel_emergency.get_value()
5119
self._decel_emergency_follower = self.decel_emergency.get_value()
5120
5121
self._dist_min_leader = 0.3
5122
self._dist_min_follower = 0.0
5123
5124
self._tau_leader = self.time_emergency.get_value()
5125
self._tau_follower = 0.0
5126
5127
# this is not very nice deleting the present type
5128
# but it is done to fully control parameters from here
5129
if vtypes.ids_sumo.has_index(prttype):
5130
id_vtype = vtypes.ids_sumo.get_id_from_index(prttype)
5131
vtypes.del_row(id_vtype)
5132
print ' deleted', prttype, 'id_vtype', id_vtype
5133
5134
if (not vtypes.ids_sumo.has_index(prttype)) | is_reset_vtype:
5135
print ' set default PRT values decel', self._decel_leader, 'decel_emergency', self._decel_emergency_leader
5136
id_vtype = vtypes.add_vtype(prttype,
5137
accel=self._accel_leader,
5138
decel=self._decel_leader,
5139
decel_apparent=self._decel_leader, # followe should not be freightened
5140
decel_emergency=self._decel_emergency_leader,
5141
sigma=0.0,
5142
length=3.5,
5143
width=1.6,
5144
height=1.7,
5145
number_persons=1,
5146
capacity_persons=1,
5147
dist_min=self._dist_min_leader,
5148
tau=self._tau_leader,
5149
speed_max=self.speed_max.get_value(),
5150
factor_speed=self._factor_speed_leader,
5151
deviation_speed=0.1, # slight deviation for better following
5152
id_mode=self.parent.id_prtmode, # specifies mode for demand
5153
color=np.array((255, 240, 0, 255), np.float32)/255.0,
5154
shape_gui='evehicle',
5155
times_boarding=1.5,
5156
times_loading=20.0,
5157
#lanechange = 0.0,
5158
lanechange_strategy=0.0,
5159
lanechange_coop=1.0,
5160
lanechange_gain=0.0,
5161
lanechange_rightkeeping=-1.0,
5162
sublane_alignment_lat='right',
5163
sublane_speed_max_lat=0.5,
5164
sublane_gap_min_lat=0.0,
5165
sublane_alignment_eager=0.0,
5166
sublane_pushyfactor=0.0,
5167
sublane_impatience=0.0,
5168
sublane_time_to_impatience=99999999,
5169
#
5170
power_max=50.0,
5171
mass=800.0,
5172
coefficient_drag_air=0.4,
5173
moment_inertia_internal=0.01,
5174
coefficient_drag_radial=0.5,
5175
coefficient_drag_roll=0.005,
5176
efficiency_propulsion=0.9,
5177
#
5178
eprofile='hcprt',
5179
capacity_battery=2000.0,
5180
efficiency_reuperation=0.4,
5181
speed_charging=0.03,
5182
)
5183
else:
5184
print ' PRT type existing'
5185
id_vtype = vtypes.ids_sumo.get_id_from_index(prttype)
5186
return id_vtype
5187
5188
def get_length(self):
5189
vtypes = self.ids_vtype.get_linktab()
5190
5191
# here take parameters from first vtype and assume that all are the same
5192
id_vtype = self.ids_vtype[self.get_ids()[0]]
5193
5194
return vtypes.lengths[id_vtype]
5195
5196
def prepare_sim(self, process):
5197
print 'PrtVehicles.prepare_sim'
5198
if len(self) == 0:
5199
return []
5200
5201
self.id_follower_probe = -1
5202
5203
ids = self.get_ids()
5204
net = self.get_scenario().net
5205
#nodes = net.nodes
5206
#edges = net.edges
5207
#lanes = net.lanes
5208
#ids_edge_sumo = edges.ids_sumo
5209
5210
id_prtmode = self.parent.id_prtmode
5211
5212
vtypes = self.ids_vtype.get_linktab()
5213
5214
# TODO: transfer vehicle parameters to vtype...but do not generate a new id_type
5215
# THIS IS A BIG MESS, WHY ARE PAPAMETERS TAKEN BACK FROM VTYPES?
5216
# self.make_vtype()
5217
5218
# here take parameters from first vtype and assume that all are the same
5219
id_vtype = self.ids_vtype[ids[0]]
5220
5221
self.length = vtypes.lengths[id_vtype]
5222
#self.speed_max = vtypes.speeds_max[id_vtype]
5223
self.dist_min = vtypes.dists_min[id_vtype]
5224
self.accel = vtypes.accels[id_vtype]
5225
self.decel = vtypes.decels[id_vtype]
5226
self.tau = vtypes.taus[id_vtype]
5227
self.dist_min = vtypes.dists_min[id_vtype]
5228
self.factor_speed = vtypes.factors_speed[id_vtype]
5229
5230
#ptstops = net.ptstops
5231
lanes = net.lanes
5232
#ids_edge_sumo = net.edges.ids_sumo
5233
5234
n_id_max = np.max(ids)+1
5235
5236
# current route
5237
self.routes = np.zeros(n_id_max, dtype=np.object)
5238
for id_veh in ids:
5239
self.routes[id_veh] = []
5240
5241
#self.ids_stopedge_target = -1*np.ones(n_id_max, dtype = np.int32)
5242
self.ids_stop_target = -1*np.ones(n_id_max, dtype=np.int32)
5243
5244
# persons
5245
self.ids_persons_sumo = np.zeros(n_id_max, dtype=np.object)
5246
for id_veh in ids:
5247
self.ids_persons_sumo[id_veh] = set()
5248
5249
# vehicle control parameters
5250
n_ghosts_max = self.n_ghosts_max.get_value()
5251
5252
self.ids_berth = -1*np.ones(n_id_max, dtype=np.int32)
5253
5254
self.are_update = np.zeros(n_id_max, dtype=np.bool)
5255
self.velocities = np.zeros(n_id_max, dtype=np.float32)
5256
self.odos = np.zeros(n_id_max, dtype=np.float32)
5257
5258
self.ids_ghosts = -1*np.ones((n_id_max, n_ghosts_max), dtype=np.int32)
5259
5260
self.diststomerge0 = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
5261
self.diststomerge0_ghosts = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
5262
self.dists0 = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
5263
5264
self.odos0_vehicles = -1 * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
5265
self.odos0_ghosts = -np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
5266
5267
# platooning
5268
# id of leader of this vehicle (vehicle in front), -1 = platoonleader
5269
self.ids_leader = -1 * np.ones(n_id_max, dtype=np.int32)
5270
5271
# id of follower of this vehicle (vehicle behind), -1 = last veh
5272
self.ids_follower = -1 * np.ones(n_id_max, dtype=np.int32)
5273
5274
# total length of platoon
5275
self.lengths_plat = np.zeros(n_id_max, dtype=np.float32)
5276
5277
return [(self.time_update.get_value(), self.process_step), ]
5278
5279
def add_ghost(self, id_veh, id_ghost, dist_to_merge_veh, dist_to_merge_ghost,
5280
is_substitute=False):
5281
ids_ghosts = list(self.ids_ghosts[id_veh])
5282
# if id_ghost in ids_ghosts:
5283
# # reconfigure existing
5284
# ind_ghost = self.ids_ghosts[id_veh].index(id_ghost)
5285
# id_ghost_old = self.ids_ghosts[id_veh][ind_ghost]
5286
# # try to delete old ghost
5287
# self.del_ghost(id_veh, id_ghost_old)
5288
# else:
5289
# add new ghost
5290
# ,self.ids_ghosts.shape
5291
print 'add_ghost veh prt.%d ghost prt.%d dtm = %.1f dtmg = %.1f d0=%.1f' % (id_veh, id_ghost, dist_to_merge_veh, dist_to_merge_ghost, dist_to_merge_veh - dist_to_merge_ghost)
5292
5293
if -1 not in ids_ghosts:
5294
print 'ERROR: no more ghosts available, ids_ghosts', ids_ghosts
5295
# sys.exit(1)
5296
print ' overwrite last ghost'
5297
# here we could sunstitute the ghost with the longest distance
5298
ind_ghost = len(ids_ghosts)-1
5299
else:
5300
ind_ghost = ids_ghosts.index(-1)
5301
5302
if is_substitute:
5303
id_ghost_prev = ids_ghosts[ind_ghost]
5304
if id_ghost_prev > -1:
5305
self.stop_update(id_ghost_prev)
5306
if ind_ghost > 0:
5307
ind_ghost -= 1
5308
5309
if ind_ghost > 0:
5310
print 'WARNING: unusual number of ghosts, ids_ghosts', ids_ghosts
5311
# sys.exit(1)
5312
5313
self.ids_ghosts[id_veh][ind_ghost] = id_ghost
5314
self.diststomerge0[id_veh][ind_ghost] = dist_to_merge_veh
5315
self.diststomerge0_ghosts[id_veh][ind_ghost] = dist_to_merge_ghost
5316
5317
# nose to nose distances
5318
self.dists0[id_veh][ind_ghost] = dist_to_merge_veh - dist_to_merge_ghost
5319
5320
# get absolute running distances
5321
self.odos0_vehicles[id_veh][ind_ghost] = get_traci_odo(self.get_id_sumo(id_veh))
5322
self.odos0_ghosts[id_veh][ind_ghost] = get_traci_odo(self.get_id_sumo(id_ghost))
5323
5324
# both ghosts and vehicles need update
5325
self.start_update(id_veh)
5326
self.start_update(id_ghost)
5327
5328
def del_ghosts(self, id_veh):
5329
if self.ids_ghosts[id_veh][0] == -1:
5330
# id_veh has no ghosts
5331
return
5332
else:
5333
for id_ghost in self.ids_ghosts[id_veh]:
5334
if id_ghost > -1:
5335
self.del_ghost(id_veh, id_ghost)
5336
5337
def del_ghost(self, id_veh, id_ghost):
5338
print 'del_ghost id_veh %d id_ghost %d' % (id_veh, id_ghost)
5339
if id_ghost in self.ids_ghosts[id_veh]:
5340
5341
ind_ghost = list(self.ids_ghosts[id_veh]).index(id_ghost)
5342
self.ids_ghosts[id_veh][ind_ghost] = -1
5343
5344
self.diststomerge0[id_veh][ind_ghost] = np.inf
5345
self.diststomerge0_ghosts[id_veh][ind_ghost] = np.inf
5346
self.dists0[id_veh][ind_ghost] = np.inf
5347
5348
self.odos0_vehicles[id_veh][ind_ghost] = -1.0
5349
self.odos0_ghosts[id_veh][ind_ghost] = -np.inf
5350
5351
self.stop_update(id_veh)
5352
self.stop_update(id_ghost)
5353
else:
5354
# veh has not such ghost
5355
pass
5356
5357
def del_all_ghosts(self, id_veh):
5358
if self.ids_ghosts[id_veh][0] == -1:
5359
# id_veh has no ghosts
5360
return
5361
5362
for id_ghost in self.ids_ghosts[id_veh]:
5363
if id_ghost > -1:
5364
self.del_ghost(id_veh, id_ghost)
5365
5366
# just to be sure ...
5367
self.stop_update(id_veh)
5368
5369
def switch_off_control(self, id_veh):
5370
"""Direct way to switch of SUMO control of vehicles"""
5371
print 'switch_off_control id_veh', id_veh
5372
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], 6) # 6=respect max accel/decel
5373
5374
def switch_on_control(self, id_veh):
5375
"""Direct way to switch of SUMO control of vehicles"""
5376
print 'switch_on_control id_veh', id_veh
5377
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], self._speedmode_leader)
5378
5379
def start_update(self, id_veh):
5380
"""Start updating control by ghosts"""
5381
self.are_update[id_veh] = True
5382
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], 6) # 6=respect max accel/decel
5383
5384
def stop_update(self, id_veh):
5385
"""Stop updating control by ghosts"""
5386
if np.all(self.ids_ghosts[id_veh] == -1): # id_veh has no ghosts?
5387
5388
# attention stopping from being conrolled by merge means
5389
# handing control back to SUMO.
5390
# followers are not controlled by the merge process
5391
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], self._speedmode_leader)
5392
if id_veh not in self.ids_ghosts: # id_veh is no ghost ?
5393
self.are_update[id_veh] = False # stop updating
5394
5395
def process_step(self, process):
5396
simtime = process.simtime
5397
print 79*'_'
5398
print 'PrtVehicles.process_step at', simtime
5399
net = self.get_scenario().net
5400
vehicles = self.parent.prtvehicles
5401
ids = self.get_ids()
5402
if len(ids) == 0:
5403
return
5404
time_update = self.time_update.get_value()
5405
decel_emergency = self.decel_emergency.get_value()
5406
print ' update', len(np.flatnonzero(self.are_update[ids])), 'vehicles'
5407
ids_update = ids[self.are_update[ids]]
5408
print ' ids_update', ids_update
5409
#ids_debug = [324,251,417,400]
5410
#ids_debug = [182,133,204,170]
5411
#ids_debug = [271, 304]
5412
ids_debug = [482, 483, 484]
5413
if 1:
5414
print ' *Debug:'
5415
#ids_debug = [307, 236, 41, 231, 208, 44, 249, 229, 136]
5416
#ids_debug = [56, 271, 264, 244, 256, 253, 240, 251, 163, 150]
5417
#ids_debug = [26,242,139,79,138]
5418
#ids_debug = [2,482,44,63,67]
5419
for id_veh, id_veh_sumo, id_follower, id_leader in zip(ids_debug, self.ids_sumo[ids_debug], self.ids_follower[ids_debug], self.ids_leader[ids_debug]):
5420
print ' *id_veh prt.%d' % id_veh, 'id_follower', id_follower, 'id_leader', id_leader, 'ids_ghost', self.ids_ghosts[id_veh]
5421
print ' id_stop_target', self.ids_stop_target[id_veh], 'lp=%.1fm' % self.lengths_plat[id_veh]
5422
if self.states[id_veh] > 0:
5423
print ' pax', traci.vehicle.getPersonIDList(id_veh_sumo), 'isStopped', traci.vehicle.isStopped(id_veh_sumo), 'speed', traci.vehicle.getSpeed(id_veh_sumo)
5424
5425
#self.id_follower_probe = self.ids_follower[271]
5426
5427
# loop through vehicles that need speed modifications
5428
# these are vehicles which have ghosts or vehicles which are
5429
# in merge processes
5430
for id_veh, id_veh_sumo in zip(ids_update, self.ids_sumo[ids_update]):
5431
# update odometer and speed
5432
self.velocities[id_veh] = get_traci_velocity(id_veh_sumo)
5433
self.odos[id_veh] = get_traci_odo(id_veh_sumo)
5434
5435
if 0:
5436
ids_ghost = self.ids_ghosts[id_veh]
5437
print ' %7s' % id_veh_sumo, 'ghosts', ids_ghost, self.ids_leader[id_veh], "lp=%.1fm" % self.lengths_plat[id_veh]
5438
#odo = self.odos[id_veh]
5439
#delta_vehs = odo-self.odos0_vehicles[id_veh]
5440
#delta_ghosts = self.odos[ids_ghost] - self.odos0_ghosts[id_veh]
5441
# print ' delta_vehs, delta_ghosts',min(delta_vehs), min(delta_ghosts)#, self.dists0[id_veh]
5442
# print ' dists', min(self.dists0[id_veh] + delta_ghosts - delta_vehs)
5443
5444
#self.diststomerge0[id_veh][ind_ghost] = np.inf
5445
#self.diststomerge0_ghosts[id_veh][ind_ghost] = np.inf
5446
5447
# pick vehicle ids that must be controlled due to a present ghost
5448
ids_contr = ids_update[self.ids_ghosts[ids_update][:, 0] > -1]
5449
# print ' ids_contr',ids_contr
5450
# print ' self.ids_ghosts[ids_update][:,0]',self.ids_ghosts[ids_update][:,0]
5451
# print ' inds',self.ids_ghosts[ids_update][:,0]>-1
5452
n_contr = len(ids_contr)
5453
n_ghosts_max = self.n_ghosts_max.get_value()
5454
5455
# no vehicles with ghost, nothing to control
5456
if n_contr == 0:
5457
return
5458
5459
# get gosts
5460
ids_ghosts = self.ids_ghosts[ids_contr]
5461
5462
# print ' self.odos[ids_contr]',self.odos[ids_contr].reshape(n_contr,1)
5463
# print ' self.odos0_vehicles[ids_contr]',self.odos0_vehicles[ids_contr]
5464
5465
# distance made since merge zone is entered
5466
deltas_vehs = self.odos[ids_contr].reshape(n_contr, 1)-self.odos0_vehicles[ids_contr]
5467
deltas_ghosts = self.odos[ids_ghosts] - self.odos0_ghosts[ids_contr]
5468
5469
#dists = self.dists0[ids_contr] + deltas_ghosts - deltas_vehs
5470
# print ' dists',dists
5471
#dists_min = np.min(self.dists0[ids_contr] + deltas_ghosts - deltas_vehs, 1) - (self.length+self.lengths_plat[ids_contr])
5472
5473
# get distance between nose of vehicle and tail of ghost which is closest
5474
dists_min = np.min(self.dists0[ids_contr] + deltas_ghosts - deltas_vehs -
5475
self.lengths_plat[ids_ghosts], 1) - self.length
5476
5477
# ??????? minimum dist to merge over all vehicles -> remove, not in use
5478
#diststomerge_min = np.min(self.diststomerge0[ids_contr] - deltas_vehs , 1)
5479
#self.diststomerge0[id_veh][ind_ghost] = dist_to_merge_veh
5480
# self.diststomerge0_ghosts[id_veh][ind_ghost] =
5481
5482
# print ' dists_min',dists_min
5483
velocities = self.velocities[ids_contr]
5484
5485
# print ' velocities_ghosts masked\n',self.velocities[ids_ghosts]
5486
5487
#mask_ghosts = INF*(ids_ghosts==-1).astype(np.float32)
5488
# print ' mask_ghosts\n',mask_ghosts
5489
velocities_ghosts = self.velocities[ids_ghosts] + INF*(ids_ghosts == -1)
5490
5491
# print ' velocities_ghosts masked\n',velocities_ghosts
5492
#
5493
# velocities of slowest ghosts
5494
velocities_ghost_min = np.min(self.velocities[ids_ghosts] + INF*(ids_ghosts == -1), 1)
5495
# print ' velocities_ghost_min\n',velocities_ghost_min
5496
dists_safe = self.tau*velocities + 0.5/decel_emergency*velocities*velocities
5497
dists_comf = self.tau*velocities + 0.5/self.decel * \
5498
(velocities*velocities-velocities_ghost_min*velocities_ghost_min)
5499
5500
# print ' dists_safe',dists_safe
5501
# print ' dists_comf',dists_comf
5502
#dists_crit = np.max(np.concatenate((dists_safe.reshape(n_contr,1),dists_comf.reshape(n_contr,1)),1),1)
5503
# print ' dists_crit',dists_crit
5504
5505
deltas_crit = dists_min-np.max(np.concatenate((dists_safe.reshape(n_contr, 1),
5506
dists_comf.reshape(n_contr, 1)), 1), 1)
5507
#deltas_crit = dists_min-dists_safe
5508
# print ' deltas_crit',deltas_crit
5509
inds_slow = deltas_crit < 0
5510
inds_accel = (deltas_crit > 0) & (velocities < 0.8*velocities_ghost_min)
5511
# print ' inds_slow',inds_slow
5512
5513
if 1:
5514
# print ' deltas_vehs',deltas_vehs
5515
for id_veh, id_sumo, velocity, velocitiy_ghost_min,\
5516
dist_safe, dist_comf, dist_min, delta_crit,\
5517
is_slow, is_accel, length_plat, odo, dist0, delta_veh, delta_ghost, dist_rel\
5518
in zip(ids_contr, self.ids_sumo[ids_contr],
5519
velocities,
5520
velocities_ghost_min,
5521
dists_safe,
5522
dists_comf,
5523
dists_min,
5524
deltas_crit,
5525
inds_slow, inds_accel, self.lengths_plat[ids_contr],
5526
# diststomerge_min,
5527
self.odos[ids_contr],
5528
self.dists0[ids_contr][:, 0],
5529
deltas_vehs[:, 0], # .flatten(),
5530
deltas_ghosts[:, 0],
5531
deltas_ghosts[:, 0] - deltas_vehs[:, 0]
5532
):
5533
5534
if id_veh in ids_debug:
5535
if is_slow:
5536
a = '-'
5537
elif is_accel:
5538
a = '+'
5539
else:
5540
a = '='
5541
# print 'id_sumo, velocity, velocitiy_ghost_min,dist_safe,dist_comf,dist_min,delta_crit,is_slow,is_accel, length_plat\n',\
5542
# id_sumo, velocity, velocitiy_ghost_min,\
5543
# dist_safe,dist_comf,dist_min,delta_crit,\
5544
#is_slow,is_accel, length_plat
5545
5546
th = (dist_min + self.length)/velocity
5547
ds_check = self.tau*velocity + 0.5/decel_emergency*velocity*velocity
5548
dist_min_check = dist0 + delta_ghost - delta_veh - \
5549
self.lengths_plat[self.ids_ghosts[id_veh][0]] - self.length
5550
# print ' %7s: v=%3.1f vg=%3.1f dh=%4.1f th=%4.1fs ds=%4.1f dc=%4.1f lp=%3.1f %s'%(id_sumo, velocity, velocitiy_ghost_min,dist_min,th,dist_safe,dist_comf,length_plat,a)
5551
print ' %7s: v=%3.1f vg=%3.1f d0=%4.1f dh=%4.1f th=%3.1fs ds=%4.1f dc=%4.1f odo=%4.1f %s' % (id_sumo, velocity, velocitiy_ghost_min, dist0, dist_min, th, dist_safe, dist_comf, odo, a)
5552
print ' dist_min', dist_min, 'dist_min_check', dist_min_check, 'id_ghost', self.ids_ghosts[id_veh][0]
5553
print ' delta_veh', delta_veh, 'delta_ghost', delta_ghost, 'dist_rel', dist_rel
5554
5555
fact_urgent = np.ones(dists_safe.shape, dtype=np.float32) # np.clip(dists_safe/diststomerge_min,0.0,1.0)
5556
5557
v_delta_brake = time_update*self.decel*fact_urgent
5558
for id_sumo, velocity, dv in zip(self.ids_sumo[ids_contr[inds_slow]], velocities[inds_slow], v_delta_brake):
5559
# print ' deccel %s from %.2f to %.2fm/s dv = %.2fm/s'%(id_sumo, velocity, velocity-dv,dv)
5560
if velocity-dv > 0: # upset when negative velocities
5561
traci.vehicle.slowDown(id_sumo, velocity-dv, time_update)
5562
5563
v_delta_accel = time_update*self.accel*fact_urgent
5564
for id_sumo, velocity, dv in zip(self.ids_sumo[ids_contr[inds_accel]], velocities[inds_accel], v_delta_accel):
5565
#dv = time_update*self.accel
5566
# print ' accel %s from %.2f to %.2fm/s dv = %.2fm/s'%(id_sumo, velocity, velocity+dv,dv)
5567
traci.vehicle.slowDown(id_sumo, velocity+dv, time_update)
5568
5569
# print ' deltas_vehs',deltas_vehs
5570
# print ' self.ids_ghosts[ids_contr]',self.ids_ghosts[ids_contr]
5571
# print ' self.odos[self.ids_ghosts[ids_contr]]',self.odos[self.ids_ghosts[ids_contr]]
5572
# print ' self.odos0_ghosts[id_veh]',self.odos0_ghosts[ids_contr]
5573
# print ' deltas_ghosts',deltas_ghosts
5574
# print ' dists',dists
5575
# for id_contr, delta_vehs, delta_ghosts,dist in zip(ids_contr,deltas_vehs,deltas_ghosts,dists):
5576
# print ' veh',id_contr,'dist',dist
5577
5578
#self.length = vtypes.lengths[id_vtype]
5579
#self.speed_max = vtypes.speeds_max[id_vtype]
5580
#self.accel = vtypes.accels[id_vtype]
5581
#self.decel = vtypes.decels[id_vtype]
5582
#self.tau = vtypes.taus[id_vtype]
5583
# if self.id_follower_probe != self.ids_follower[271]:
5584
# print 'WARNING: prt.271 changed follower'
5585
5586
def get_targetedge_current(self, id_veh):
5587
return self.routes[id_veh][-1]
5588
5589
def set_route_target(self, id_veh, route, id_stop_target=None, is_disengage_from_berth=False, is_emptytrip=False):
5590
"""
5591
This is the vehicle route to the next target, not necessary the final one.
5592
"""
5593
print 'set_route_target prt.%d' % id_veh, 'id_stop_target', id_stop_target, 'is_disengage_from_berth', is_disengage_from_berth
5594
print ' route', route
5595
5596
# set target only if valid target, otherwise set only route
5597
if id_stop_target is not None:
5598
self.ids_stop_target[id_veh] = id_stop_target
5599
5600
# these actions are taken only once when target is set in berth
5601
if is_disengage_from_berth:
5602
# now remove the stop in order to prevent that other passengers can board
5603
# this is mayby not the best way to do it
5604
id_veh_sumo = self.get_id_sumo(id_veh)
5605
# print ' pax',traci.vehicle.getPersonIDList(id_veh_sumo)
5606
traci.vehicle.resume(id_veh_sumo)
5607
#if is_emptytrip: #
5608
# # NO!! setPersonCapacity does not exist
5609
# traci.vehicle.setPersonCapacity(id_veh_sumo, 0)
5610
# make sure that vehicle does not move
5611
# traci.vehicle.setStop( id_veh_sumo,
5612
# traci.vehicle.getRoadID(id_veh_sumo),
5613
# pos = traci.vehicle.getLanePosition(id_veh_sumo)+0.1,
5614
# flags= 32,#
5615
# laneIndex= 1,
5616
# )
5617
traci.vehicle.setMaxSpeed(id_veh_sumo, 0.0000001) # 0 speed not allowed
5618
#traci.vehicle.slowDown(id_veh_sumo, 0.0,0.1)
5619
traci.vehicle.changeLane(id_veh_sumo, 1, 600.0)
5620
5621
self.routes[id_veh] = list(route)
5622
5623
def set_route_completed(self, id_veh):
5624
self.ids_stop_target[id_veh] = -1
5625
self.routes[id_veh] = []
5626
5627
def reset_speedmode(self, id_veh_sumo):
5628
print 'reset_speedmode', id_veh_sumo
5629
# speed mode (0xb3)
5630
# Per default, the vehicle is using the given speed regarding the safe gap, the maximum acceleration, and the maximum deceleration. Furthermore, vehicles follow the right-of-way rules when approaching an intersection and if necessary they brake hard to avoid driving across a red light. One can control this behavior using the speed mode (0xb3) command, the given integer is a bitset (bit0 is the least significant bit) with the following fields:
5631
# 1 bit0: Regard safe speed
5632
# 2 bit1: Regard maximum acceleration
5633
# 4 bit2: Regard maximum deceleration
5634
# 8 bit3: Regard right of way at intersections
5635
# 16 bit4: Brake hard to avoid passing a red light
5636
# 1+2+4
5637
# traci.vehicle.setSpeedMode(id_veh_sumo,7)
5638
#self.speed_max = vtypes.speeds_max[id_vtype]
5639
#self.accel = vtypes.accels[id_vtype]
5640
traci.vehicle.slowDown(id_veh_sumo, self.speed_max.get_value(), self.speed_max.get_value()/self.accel)
5641
# pass
5642
5643
def concatenate(self, id_veh, id_veh_pre):
5644
print 'concatenate prt.%d' % id_veh, 'behind prt.%d' % id_veh_pre
5645
self.ids_leader[id_veh] = id_veh_pre
5646
self.ids_follower[id_veh_pre] = id_veh
5647
5648
id_veh_sumo = self.get_id_sumo(id_veh)
5649
5650
# if 0:
5651
# traci.vehicle.setSpeedFactor(id_veh_sumo,2.0)# +random.uniform(-0.01,0.01)
5652
# traci.vehicle.setImperfection(id_veh_sumo,0.0)
5653
# traci.vehicle.setAccel(id_veh_sumo,3.5)
5654
# traci.vehicle.setMinGap(id_veh_sumo,0.01)
5655
# traci.vehicle.setTau(id_veh_sumo,0.2)
5656
5657
# if 1:
5658
traci.vehicle.setSpeedMode(id_veh_sumo, self._speedmode_follower)
5659
traci.vehicle.setSpeedFactor(id_veh_sumo, self._factor_speed_follower)
5660
# traci.vehicle.setImperfection(id_veh_sumo,0.0)
5661
traci.vehicle.setDecel(id_veh_sumo, self._decel_emergency_follower)
5662
traci.vehicle.setAccel(id_veh_sumo, self._accel_follower)
5663
traci.vehicle.setMinGap(id_veh_sumo, self._dist_min_follower)
5664
traci.vehicle.setTau(id_veh_sumo, self._tau_follower)
5665
5666
if self.lengths_plat[id_veh] > 0.1:
5667
self._update_concatenate(id_veh, self.lengths_plat[id_veh])
5668
else:
5669
self._update_concatenate(id_veh, 0.0)
5670
5671
print ' length_plat=', self.lengths_plat[id_veh]
5672
5673
def _update_concatenate(self, id_veh, length_plat):
5674
"""
5675
Propagates length to the first vehicle of the platoon
5676
"""
5677
# TODO: this is a very inefficient method because call each time a vehicle is added.
5678
# Try to avoid altogether
5679
print '_update_concatenate prt.%s, length_plat=%.1f, length=%.1f,' % (id_veh, length_plat, self.length), 'id_leader', self.ids_leader[id_veh]
5680
if self.ids_leader[id_veh] == -1:
5681
# first vehicle
5682
# print ' first vehicle prt.%s'%id_veh,length_plat
5683
self.lengths_plat[id_veh] = length_plat
5684
else:
5685
# propagate platoon length
5686
self.lengths_plat[id_veh] = 0.0
5687
self._update_concatenate(self.ids_leader[id_veh], length_plat + self.length)
5688
5689
def decatenate(self, id_veh):
5690
print 'decatenate prt.%d' % id_veh
5691
5692
id_leader = self.ids_leader[id_veh]
5693
# print ' id_leader',id_leader
5694
if id_leader > -1:
5695
id_veh_sumo = self.get_id_sumo(id_veh)
5696
5697
# if self.ids_leader[id_leader] == -1:
5698
# # leader of this vehicle is first in platoon
5699
# # this should be normally the case if a platoon is
5700
# # broken up from the first vehicle backwards
5701
#
5702
# # calculate new shortened platoon length
5703
# # TODO
5704
# self.lengths_plat[id_veh] = self.lengths_plat[id_leader]-self.length
5705
# else:
5706
# print 'WARNING in decatenate: platoon broken up in the middel at',id_veh_sumo,'with id_leader',id_leader
5707
# self.lengths_plat[id_veh] = 0.0
5708
5709
# this vehicle will become first in the platoon
5710
5711
self.lengths_plat[id_veh] = 0.0
5712
self.ids_leader[id_veh] = -1
5713
self.ids_follower[id_leader] = -1
5714
# if 0:
5715
# traci.vehicle.setSpeedFactor(id_veh_sumo, 1.5)#+random.uniform(-0.01,0.01)
5716
# traci.vehicle.setMinGap(id_veh_sumo,0.3)
5717
# traci.vehicle.setImperfection(id_veh_sumo,0.0)
5718
# traci.vehicle.setTau(id_veh_sumo,0.8)
5719
# traci.vehicle.setAccel(id_veh_sumo,2.5)
5720
5721
# if 1:
5722
# reset parameters
5723
traci.vehicle.setSpeedMode(id_veh_sumo, self._speedmode_leader)
5724
5725
# rest are leader values taken from type def
5726
traci.vehicle.setSpeedFactor(id_veh_sumo, self.factor_speed) # +random.uniform(-0.01,0.01)
5727
traci.vehicle.setMinGap(id_veh_sumo, self.dist_min)
5728
# traci.vehicle.setImperfection(id_veh_sumo,1.0)
5729
traci.vehicle.setTau(id_veh_sumo, self.tau)
5730
traci.vehicle.setDecel(id_veh_sumo, self.decel)
5731
traci.vehicle.setAccel(id_veh_sumo, self.accel)
5732
else:
5733
# it is a leader itself and does not need to decatenate
5734
# remove platoon length
5735
self.lengths_plat[id_veh] = 0.0
5736
5737
print ' length_plat=', self.lengths_plat[id_veh]
5738
5739
def get_platoonleader(self, id_veh_tail):
5740
id_veh = 1*id_veh_tail
5741
while self.ids_leader[id_veh] > -1:
5742
id_veh = self.ids_leader[id_veh]
5743
return id_veh
5744
5745
def get_platoontail(self, id_veh_leader):
5746
id_veh = 1*id_veh_leader
5747
while self.ids_follower[id_veh] > -1:
5748
id_veh = self.ids_follower[id_veh]
5749
return id_veh
5750
5751
def get_platoonsize(self, id_veh_leader):
5752
id_veh = 1*id_veh_leader
5753
n = 1
5754
while self.ids_follower[id_veh] > -1:
5755
id_veh = self.ids_follower[id_veh]
5756
n += 1
5757
return n
5758
5759
def get_platoon(self, id_veh_leader):
5760
print 'get_platoon for leader prt.%d' % id_veh_leader
5761
ids_veh = [id_veh_leader, ]
5762
id_veh = self.ids_follower[id_veh_leader]
5763
# print ' id_veh',id_veh
5764
while id_veh > -1:
5765
ids_veh.append(id_veh)
5766
id_veh = self.ids_follower[id_veh]
5767
# print ' id_veh',id_veh
5768
5769
print ' ids_veh', ids_veh
5770
return ids_veh
5771
5772
def get_entered_left(self, id_edge_sumo, ids_veh_previous_sumo):
5773
"""
5774
Returns:
5775
array with SUMO IDs of entered vehicles during last poll
5776
array with SUMO IDs of left vehicles during last poll
5777
array with SUMO IDs current vehicles on id_edge_sumo
5778
Attention: in the returned entered/left lists,
5779
the first vehicle in the list entered/left first
5780
"""
5781
ids_veh_new_sumo = traci.edge.getLastStepVehicleIDs(id_edge_sumo)
5782
print 'get_entered_left ids_veh_new_sumo=', ids_veh_new_sumo
5783
len_prev = len(ids_veh_previous_sumo)
5784
len_new = len(ids_veh_new_sumo)
5785
5786
if len_prev == 0:
5787
return ids_veh_new_sumo, [], ids_veh_new_sumo
5788
5789
if len_new == 0:
5790
return [], ids_veh_previous_sumo, []
5791
5792
ind_enter = 0
5793
5794
for id_veh_sumo in ids_veh_new_sumo:
5795
5796
# if ind_enter+1 == len_prev:
5797
# ind_enter = len_new -1
5798
# break
5799
5800
if id_veh_sumo == ids_veh_previous_sumo[0]:
5801
break
5802
5803
ind_enter += 1
5804
print ' ind_enter', ind_enter, ids_veh_new_sumo[0:ind_enter], ids_veh_new_sumo[ind_enter-1::-1]
5805
#ids_entered_sumo = ids_veh_new_sumo[0:ind_enter]
5806
5807
ind_leave = len_prev
5808
for id_veh_sumo in ids_veh_previous_sumo[::-1]:
5809
5810
if id_veh_sumo == ids_veh_new_sumo[-1]:
5811
break
5812
5813
ind_leave -= 1
5814
print ' ind_leave', ind_leave, ids_veh_previous_sumo[ind_leave:], ids_veh_previous_sumo[:ind_leave:-1]
5815
#ids_leave_sumo = ids_veh_previous_sumo[ind_leave:]
5816
5817
# return ids_entered_sumo, ids_leave_sumo, ids_veh_new_sumo
5818
# return reversed lists
5819
return ids_veh_new_sumo[0:ind_enter][::-1], ids_veh_previous_sumo[ind_leave:][::-1], ids_veh_new_sumo
5820
5821
# TODO: optimize!!!
5822
# return ids_veh_new_sumo[ind_enter-1::-1], ids_veh_previous_sumo[:ind_leave:-1], ids_veh_new_sumo
5823
5824
def control_stop(self, id_veh, laneindex=0):
5825
5826
id_veh_sumo = self.get_id_sumo(id_veh)
5827
speed = traci.vehicle.getSpeed(id_veh_sumo)
5828
pos = traci.vehicle.getLanePosition(id_veh_sumo)
5829
stopline = pos + 3.0 + 0.5/self.decel*speed**2
5830
#time_slowdown = np.abs((speed0-speed)/self.decel)
5831
5832
print 'control_stop', id_veh_sumo, 'v = %.2f at pos %.1fm to stop at %.1fm on %s' % (speed, pos, stopline, traci.vehicle.getRoadID(id_veh_sumo))
5833
traci.vehicle.setStop(id_veh_sumo,
5834
traci.vehicle.getRoadID(id_veh_sumo),
5835
pos=stopline,
5836
laneIndex=laneindex,
5837
)
5838
5839
def control_speedup(self, id_veh):
5840
5841
id_veh_sumo = self.get_id_sumo(id_veh)
5842
print 'control_speedup', id_veh_sumo, 'isStopped', traci.vehicle.isStopped(id_veh_sumo), self.speed_max.get_value()
5843
5844
if traci.vehicle.isStopped(id_veh_sumo):
5845
traci.vehicle.resume(id_veh_sumo)
5846
5847
traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())
5848
#self.control_slow_down(id_veh, self.speed_max.get_value())
5849
5850
def control_slow_down(self, id_veh, speed=1.0, time_slowdown=None):
5851
print 'control_slow_down', self.get_id_sumo(id_veh), speed, time_slowdown
5852
id_veh_sumo = self.get_id_sumo(id_veh)
5853
if time_slowdown is None:
5854
speed0 = traci.vehicle.getSpeed(id_veh_sumo)
5855
5856
time_slowdown = np.abs((speed0-speed)/self.decel)
5857
print ' speed0=%.2fm/s, time_slowdown = %.2fs, dv=%.2fm/s' % (speed0, time_slowdown, speed0-speed)
5858
5859
traci.vehicle.slowDown(id_veh_sumo, speed, time_slowdown)
5860
#self.speed_max = vtypes.speeds_max[id_vtype]
5861
#self.accel = vtypes.accels[id_vtype]
5862
#self.decel = vtypes.decels[id_vtype]
5863
5864
def control_forewarding_exit(self, id_veh,
5865
id_edge_sumo=None,
5866
position=None,
5867
laneindex=2,
5868
):
5869
"""Accelerates vehicle to line up at the exit.
5870
Make a stop with position at the end of the station.
5871
"""
5872
# ??? is this function called at all?
5873
# state forewarding_exit_kickout was unknown!!!
5874
id_veh_sumo = self.get_id_sumo(id_veh)
5875
p = traci.vehicle.getLanePosition(id_veh_sumo)
5876
print 'control_forewarding_exit', id_veh_sumo, p, '->', position, 'laneindex', laneindex
5877
if traci.vehicle.isStopped(id_veh_sumo):
5878
print ' resume stop'
5879
traci.vehicle.resume(id_veh_sumo)
5880
5881
self.states[id_veh] = VEHICLESTATES['forewarding_exit_kickout']
5882
5883
if position is None:
5884
# print ' do not set a stop'
5885
pass
5886
else:
5887
print ' set stop at pos', position
5888
traci.vehicle.setStop(id_veh_sumo,
5889
id_edge_sumo,
5890
pos=position,
5891
flags=0,
5892
laneIndex=laneindex,
5893
)
5894
traci.vehicle.changeLane(id_veh_sumo, laneindex, 600.0)
5895
# accelerate vehicle. Speed here is limited by the max speed of the lane
5896
traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())
5897
5898
def control_stopline_enter(self, id_veh, id_edge_sumo, stopline, laneindex=1, flags=0):
5899
# print 'control_stopline_enter',self.get_id_sumo(id_veh),stopline
5900
id_veh_sumo = self.get_id_sumo(id_veh)
5901
print 'control_stopline_enter', id_veh_sumo, 'lane %d, pos=%.2f->targetpos %.2f' % (laneindex, traci.vehicle.getLanePosition(id_veh_sumo), stopline)
5902
traci.vehicle.setStop(id_veh_sumo,
5903
id_edge_sumo,
5904
pos=stopline,
5905
startPos=stopline,
5906
laneIndex=laneindex,
5907
flags=flags,
5908
)
5909
self.states[id_veh] = VEHICLESTATES['forewarding']
5910
# traci.vehicle.changeLane(self.get_id_sumo(id_veh), laneIndex, duration(
5911
5912
def control_berth_position_enter(self, id_veh, id_berth,
5913
id_edge_sumo=None,
5914
position=None,
5915
laneindex=2,
5916
):
5917
"""Stop vehicle with id_veh at stopline of berth with id_berth
5918
Memorize berth for later use.
5919
"""
5920
id_veh_sumo = self.get_id_sumo(id_veh)
5921
p = traci.vehicle.getLanePosition(id_veh_sumo)
5922
print 'control_berth_position_enter', id_veh_sumo, p, '->', position, 'id_berth', id_berth
5923
5924
# here it can happen that vehicle has been programmed to stop in front
5925
# of first berth to wait for allocation
5926
# print ' getStopState',traci.vehicle.getStopState(id_veh_sumo)
5927
# print ' getNextStops',traci.vehicle.getNextStops(id_veh_sumo)
5928
print ' isStopped', traci.vehicle.isStopped(id_veh_sumo)
5929
# if len(traci.vehicle.getNextStops(id_veh_sumo))>0:
5930
5931
# already resumed
5932
# if traci.vehicle.isStopped(id_veh_sumo):
5933
# traci.vehicle.resume(id_veh_sumo)
5934
5935
self.states[id_veh] = VEHICLESTATES['forewarding_enter']
5936
self.ids_berth[id_veh] = id_berth
5937
traci.vehicle.setStop(id_veh_sumo,
5938
id_edge_sumo,
5939
pos=position,
5940
flags=0,
5941
laneIndex=laneindex,
5942
)
5943
# force vehicle to stay on lane
5944
traci.vehicle.changeLane(id_veh_sumo, laneindex, 60.0)
5945
5946
def control_berth_position_exit(self, id_veh,
5947
id_edge_sumo=None,
5948
position=None,
5949
laneindex=2,
5950
):
5951
"""Move vehicle out of berth and stop vehicle at stopline of berth to wait for exit
5952
"""
5953
id_veh_sumo = self.get_id_sumo(id_veh)
5954
p = traci.vehicle.getLanePosition(id_veh_sumo)
5955
if position is None:
5956
position = p+0.3
5957
print 'control_berth_position_exit', id_veh_sumo, p, '->', position
5958
if traci.vehicle.isStopped(id_veh_sumo):
5959
traci.vehicle.resume(id_veh_sumo)
5960
5961
self.ids_berth[id_veh] = -1
5962
self.states[id_veh] = VEHICLESTATES['kickout_berth']
5963
traci.vehicle.changeLane(id_veh_sumo, laneindex, 300.0)
5964
traci.vehicle.setStop(id_veh_sumo,
5965
id_edge_sumo,
5966
pos=position,
5967
flags=0,
5968
laneIndex=laneindex,
5969
)
5970
# accelerate vehicle. Speed here is limited by the max speed of the lane
5971
traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())
5972
5973
def control_berth_position_exit_slowdown(self, id_veh):
5974
id_veh_sumo = self.get_id_sumo(id_veh)
5975
print ' control_berth_position_exit_slowdown', id_veh_sumo
5976
# function to stop vehicle after it moved out of the berth
5977
if traci.vehicle.isStopped(id_veh_sumo):
5978
traci.vehicle.resume(id_veh_sumo)
5979
# set speed positive just to prevemnt that passenger jump in
5980
traci.vehicle.setMaxSpeed(id_veh_sumo, 0.0001)
5981
self.states[id_veh] = VEHICLESTATES['forewarding_exit']
5982
5983
def control_berth_stop(self, id_veh,
5984
id_edge_sumo=None,
5985
position=None,
5986
laneindex=1,
5987
):
5988
"""Move vehicle with id_veh into the berth and stop vehicle for lighting and boarding
5989
"""
5990
id_veh_sumo = self.get_id_sumo(id_veh)
5991
p = traci.vehicle.getLanePosition(id_veh_sumo)
5992
print 'control_berth_stop', id_veh_sumo, p, '->', position
5993
#d = position - p
5994
#v = traci.vehicle.getSpeed(id_veh_sumo)
5995
#d_save = 1.0/(2*2.5)*(v**2)
5996
# print ' v=',v
5997
# print ' d,d_save',d,d_save
5998
self.states[id_veh] = VEHICLESTATES['forewarding_enter']
5999
6000
traci.vehicle.setStop(id_veh_sumo,
6001
id_edge_sumo,
6002
startPos=position-2.0,
6003
pos=position,
6004
flags=2, # park and trigger 1+2,#
6005
laneIndex=laneindex,
6006
)
6007
6008
def control_stop_board(self, id_veh, id_stop, id_berth,
6009
id_edge_sumo=None,
6010
position=None,
6011
):
6012
6013
# NO LONGER USED
6014
id_veh_sumo = self.get_id_sumo(id_veh)
6015
print 'control_stop_board', id_veh_sumo, id_stop, id_berth, id_edge_sumo, 'pos=%.2f,target %.2f' % (traci.vehicle.getLanePosition(id_veh_sumo), position),
6016
print ' v=', traci.vehicle.getSpeed(id_veh_sumo)
6017
6018
# print 'control_stop_board',id_veh_sumo,traci.vehicle.getLanePosition(id_veh_sumo),'->',position,id_berth
6019
self.ids_berth[id_veh] = id_berth
6020
self.states[id_veh] = VEHICLESTATES['forewarding']
6021
# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
6022
if traci.vehicle.isStopped(id_veh_sumo):
6023
traci.vehicle.resume(id_veh_sumo)
6024
6025
traci.vehicle.setStop(id_veh_sumo,
6026
id_edge_sumo,
6027
startPos=position-4.0,
6028
pos=position,
6029
flags=2, # park and trigger 1+2,#
6030
laneIndex=1,
6031
)
6032
6033
def launch_from_stop(self, id_veh):
6034
6035
id_veh_sumo = self.get_id_sumo(id_veh)
6036
print 'launch_from_stop', id_veh_sumo, 'is stopped', traci.vehicle.isStopped(id_veh_sumo)
6037
if traci.vehicle.isStopped(id_veh_sumo):
6038
print ' resume!'
6039
traci.vehicle.resume(id_veh_sumo)
6040
6041
route_sumo = self.get_scenario().net.edges.ids_sumo[self.routes[id_veh]]
6042
traci.vehicle.setRoute(id_veh_sumo, route_sumo)
6043
# accelerate !
6044
traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
6045
#traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())
6046
#traci.vehicle.setMaxSpeed(id_veh_sumo, 0.66)
6047
print ' after launch is stopped', traci.vehicle.isStopped(id_veh_sumo), 'getMaxSpeed', traci.vehicle.getMaxSpeed(id_veh_sumo)
6048
6049
def alight(self, id_veh):
6050
# print 'alight',self.get_id_sumo(id_veh)
6051
# TODO: necessary to keep copy of state?
6052
self.states[id_veh] = VEHICLESTATES['alighting']
6053
6054
# traci.vehicle.getStopState(self.get_id_sumo(id_veh))
6055
# VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting'
6056
6057
def board(self, id_veh, id_edge_sumo=None, position=None):
6058
# print 'board',self.get_id_sumo(id_veh)
6059
# TODO: necessary to keep copy of state?
6060
self.states[id_veh] = VEHICLESTATES['boarding']
6061
#id_veh_sumo = self.get_id_sumo(id_veh)
6062
# print 'board',id_veh_sumo,'stopstate',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
6063
# print ' ',dir(traci.vehicle)
6064
# traci.vehicle.getLastStepPersonIDs()
6065
# traci.vehicle.getStopState(self.get_id_sumo(id_veh))
6066
# VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting'
6067
#traci.vehicle.setRoute(id_veh_sumo, [id_edge_sumo])
6068
# traci.vehicle.resume(id_veh_sumo)
6069
6070
# traci.vehicle.setStop( self.get_id_sumo(id_veh),
6071
# traci.vehicle.getRoadID(id_veh_sumo),
6072
# pos = traci.vehicle.getLanePosition(id_veh_sumo),
6073
# flags= 2,#
6074
# laneIndex= 1,
6075
# )
6076
# print 'board ',id_veh_sumo, traci.vehicle.getStopState(id_veh_sumo )# bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
6077
6078
def init_passthrough(self, id_veh, id_edge_sumo, stopline, laneindex=1, flags=0):
6079
id_veh_sumo = self.get_id_sumo(id_veh)
6080
print 'init_passthrough', id_veh_sumo, 'lane %d, pos=%.2f->targetpos %.2f' % (laneindex, traci.vehicle.getLanePosition(id_veh_sumo), stopline)
6081
6082
# do n
6083
#is_stop = True
6084
# if id_veh_infront > -1:
6085
# if self.states[id_veh_infront] == VEHICLESTATES['forewarding_passthrough']:
6086
# is_stop = False
6087
6088
# if is_stop:
6089
traci.vehicle.setStop(id_veh_sumo,
6090
id_edge_sumo,
6091
pos=stopline,
6092
startPos=stopline,
6093
laneIndex=laneindex,
6094
flags=flags,
6095
)
6096
6097
self.states[id_veh] = VEHICLESTATES['forewarding_passthrough']
6098
6099
def foreward_passthrough(self, id_veh):
6100
6101
id_veh_sumo = self.get_id_sumo(id_veh)
6102
print 'foreward_passthrough', id_veh_sumo
6103
if traci.vehicle.isStopped(id_veh_sumo):
6104
# print ' resume!'
6105
traci.vehicle.resume(id_veh_sumo)
6106
6107
traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
6108
6109
def reached_stop_sumo(self, id_veh_sumo):
6110
state = traci.vehicle.getStopState(id_veh_sumo)
6111
print 'reached_stop', id_veh_sumo, bin(state), bin(state)[-1] == '1'
6112
return bin(state)[-1] == '1'
6113
6114
def is_completed_alighting(self, id_veh):
6115
print 'is_completed_alighting', self.get_id_sumo(id_veh), self.states[id_veh], 'alighting', self.states[id_veh] == VEHICLESTATES['alighting'], 'pers on board', traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)), type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)))
6116
if self.states[id_veh] == VEHICLESTATES['alighting']:
6117
ids_persons_sumo_on_board = traci.vehicle.getPersonIDList(self.get_id_sumo(id_veh))
6118
if self.ids_persons_sumo[id_veh].isdisjoint(ids_persons_sumo_on_board):
6119
# if traci.vehicle.getPersonIDList(self.get_id_sumo(id_veh)) == 0:
6120
print ' completed alighting ids_persons_sumo_on_board', ids_persons_sumo_on_board
6121
if len(ids_persons_sumo_on_board) > 0:
6122
self.states[id_veh] = VEHICLESTATES['boarding']
6123
else:
6124
self.states[id_veh] = VEHICLESTATES['waiting']
6125
return True
6126
else:
6127
# somebody is still in the vehicle
6128
return False
6129
6130
else:
6131
return True
6132
6133
def is_completed_boarding(self, id_veh):
6134
# print 'is_completed_boarding',self.get_id_sumo(id_veh),traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)),type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)))
6135
6136
# TODO: this is still assuming one person at max
6137
# for groups this must change
6138
if self.states[id_veh] in (VEHICLESTATES['boarding'], VEHICLESTATES['waiting']):
6139
ids_person_sumo = traci.vehicle.getPersonIDList(self.get_id_sumo(id_veh))
6140
if len(ids_person_sumo) == 1:
6141
print ' completed boarding'
6142
self.states[id_veh] = VEHICLESTATES['boarding_completed']
6143
self.ids_persons_sumo[id_veh].add(ids_person_sumo)
6144
return True
6145
else:
6146
return False
6147
6148
elif self.states[id_veh] == VEHICLESTATES['boarding_completed']:
6149
return True
6150
6151
else:
6152
return False
6153
6154
def init_trip_occupied(self, id_veh, id_edge_sumo, stopline=None):
6155
id_veh_sumo = self.get_id_sumo(id_veh)
6156
print 'init_trip_occupied', self.get_id_sumo(id_veh), id_edge_sumo, stopline
6157
# print ' current route:',traci.vehicle.getRoute(id_veh_sumo)
6158
self.states[id_veh] = VEHICLESTATES['occupiedtrip']
6159
6160
# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
6161
if traci.vehicle.isStopped(id_veh_sumo):
6162
traci.vehicle.resume(id_veh_sumo)
6163
#traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest)
6164
#traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest)
6165
if stopline is not None:
6166
traci.vehicle.setStop(id_veh_sumo,
6167
id_edge_sumo,
6168
pos=stopline,
6169
laneIndex=1,
6170
)
6171
else:
6172
speed_crawl = 1.0
6173
time_accel = 4.0
6174
#traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel)
6175
6176
def init_trip_empty(self, id_veh, id_edge_sumo, stopline=None):
6177
print 'Vehicles.init_trip_empty', self.get_id_sumo(id_veh), id_edge_sumo, stopline
6178
self.states[id_veh] = VEHICLESTATES['emptytrip']
6179
id_veh_sumo = self.get_id_sumo(id_veh)
6180
if traci.vehicle.isStopped(id_veh_sumo):
6181
traci.vehicle.resume(id_veh_sumo)
6182
#traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to)
6183
if stopline is not None:
6184
# if stopline>=0:
6185
# print ' Route=',traci.vehicle.getRoute(id_veh_sumo)
6186
# print ' Position=',traci.vehicle.getLanePosition(id_veh_sumo),stopline
6187
# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
6188
6189
traci.vehicle.setStop(id_veh_sumo,
6190
id_edge_sumo,
6191
pos=stopline,
6192
laneIndex=1,
6193
)
6194
else:
6195
speed_crawl = 1.0
6196
time_accel = 4.0
6197
#traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel)
6198
6199
def reschedule_trip(self, id_veh, id_edge_sumo_to=None, route_sumo=None):
6200
print 'reschedule_trip', self.get_id_sumo(id_veh), id_edge_sumo_to, route_sumo
6201
id_veh_sumo = self.get_id_sumo(id_veh)
6202
if traci.vehicle.isStopped(id_veh_sumo):
6203
traci.vehicle.resume(id_veh_sumo)
6204
6205
if route_sumo is not None:
6206
# set entire route
6207
traci.vehicle.setRoute(id_veh_sumo, route_sumo)
6208
else:
6209
# set new target and let SUMO do the routing
6210
traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to)
6211
6212
#
6213
# self.reset_speedmode(id_veh_sumo)
6214
# limit speed to run slowly on exit line
6215
# the merge will take over speed control
6216
6217
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
6218
# print ' set speed to',traci.vehicle.getMaxSpeed(id_veh_sumo)
6219
#traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0)
6220
6221
def add_to_net(self, n=-1, length_veh_av=4.0):
6222
"""
6223
Add n PRT vehicles to network
6224
If n = -1 then fill up stops with vehicles.
6225
"""
6226
# print 'PrtVehicles.make',n,length_veh_av
6227
# self.clear()
6228
net = self.get_scenario().net
6229
ptstops = net.ptstops
6230
prtstops = self.parent.prtstops
6231
lanes = net.lanes
6232
ids_prtstop = prtstops.get_ids()
6233
ids_ptstop = prtstops.ids_ptstop[ids_prtstop]
6234
ids_veh = []
6235
n_stop = len(prtstops)
6236
6237
for id_stop, id_edge, pos_from, pos_to in zip(
6238
ids_prtstop,
6239
lanes.ids_edge[ptstops.ids_lane[ids_ptstop]],
6240
ptstops.positions_from[ids_ptstop],
6241
ptstops.positions_to[ids_ptstop],
6242
):
6243
# TODO: here we can select depos or distribute a
6244
# fixed number of vehicles or put them into berth
6245
6246
# print ' ',pos_to,pos_from,int((pos_to-pos_from)/length_veh_av)
6247
if n > 0:
6248
n_veh_per_stop = int(float(n)/n_stop+0.5)
6249
else:
6250
n_veh_per_stop = int((pos_to-pos_from)/length_veh_av)
6251
6252
# print ' n,n_stop,n_veh_per_stop',n,n_stop,n_veh_per_stop
6253
for i in range(n_veh_per_stop):
6254
id_veh = self.add_row(ids_stop_target=id_stop,
6255
ids_currentedge=id_edge,
6256
)
6257
6258
self.ids_sumo[id_veh] = self.get_id_sumo(id_veh)
6259
ids_veh.append(id_veh)
6260
6261
return ids_veh
6262
6263
# def write_veh
6264
#
6265
6266
def get_scenario(self):
6267
return self.parent.get_scenario()
6268
6269
def get_vtypes(self):
6270
"""
6271
Returns a set with all used PRT vehicle types.
6272
"""
6273
# print 'Vehicles_individual.get_vtypes',self.cols.vtype
6274
return set(self.ids_vtype.get_value())
6275
6276
def get_id_sumo(self, id_veh):
6277
return 'prt.%s' % (id_veh)
6278
6279
def get_id_from_id_sumo(self, id_veh_sumo):
6280
if len(id_veh_sumo.split('.')) == 2:
6281
prefix, id_veh = id_veh_sumo.split('.')
6282
if prefix == 'prt':
6283
return int(id_veh)
6284
else:
6285
return -1
6286
return -1
6287
6288
def get_ids_from_ids_sumo(self, ids_veh_sumo):
6289
n = len(ids_veh_sumo)
6290
ids = np.zeros(n, np.int32)
6291
for i in xrange(n):
6292
ids[i] = self.get_id_from_id_sumo(ids_veh_sumo[i])
6293
return ids
6294
6295
def get_id_line_xml(self):
6296
return 'prt'
6297
6298
6299
class HcPrtStrategy(StrategyMixin):
6300
def __init__(self, ident, parent=None,
6301
name='High Capacity Personal Rapid Transit Strategy',
6302
info='With this strategy, the person uses High Capacity Personla Rapid Transit as main transport mode.',
6303
**kwargs):
6304
6305
self._init_objman(ident, parent, name=name, info=info, **kwargs)
6306
attrsman = self.set_attrsman(cm.Attrsman(self))
6307
# specific init
6308
self._init_attributes()
6309
self._init_constants()
6310
6311
def _init_attributes(self):
6312
# print 'StrategyMixin._init_attributes'
6313
pass
6314
6315
def _init_constants(self):
6316
#virtualpop = self.get_virtualpop()
6317
#stagetables = virtualpop.get_stagetables()
6318
6319
#self._walkstages = stagetables.get_stagetable('walks')
6320
#self._ridestages = stagetables.get_stagetable('rides')
6321
#self._activitystages = stagetables.get_stagetable('activities')
6322
6323
#self._plans = virtualpop.get_plans()
6324
#
6325
# print 'AutoStrategy._init_constants'
6326
# print dir(self)
6327
# self.get_attrsman().do_not_save_attrs(['_activitystages','_ridestages','_walkstages','_plans'])
6328
6329
modes = self.get_virtualpop().get_scenario().net.modes
6330
self._id_mode_bike = modes.get_id_mode('bicycle')
6331
self._id_mode_auto = modes.get_id_mode('passenger')
6332
self._id_mode_moto = modes.get_id_mode('motorcycle')
6333
self._id_mode_bus = modes.get_id_mode('bus')
6334
self.get_attrsman().do_not_save_attrs([
6335
'_id_mode_bike', '_id_mode_auto', '_id_mode_moto', '_id_mode_bus'
6336
])
6337
6338
def set_prtservice(self, prtservice):
6339
#self.add( cm.ObjConf( prtservice, is_child = False,groups = ['_private']))
6340
self.prtservice = prtservice
6341
self.get_attrsman().do_not_save_attrs(['prtservice'])
6342
6343
def preevaluate(self, ids_person):
6344
"""
6345
Preevaluation strategies for person IDs in vector ids_person.
6346
6347
Returns a preevaluation vector with a preevaluation value
6348
for each person ID. The values of the preevaluation vector are as follows:
6349
-1 : Strategy cannot be applied
6350
0 : Stategy can be applied, but the preferred mode is not used
6351
1 : Stategy can be applied, and preferred mode is part of the strategy
6352
2 : Strategy uses predomunantly preferred mode
6353
6354
"""
6355
n_pers = len(ids_person)
6356
persons = self.get_virtualpop()
6357
preeval = np.zeros(n_pers, dtype=np.int32)
6358
6359
# TODO: here we could exclude by age or distance facilities-stops
6360
6361
# put 0 for persons whose preference is not public transport
6362
preeval[persons.ids_mode_preferred[ids_person] != self.prtservice.id_prtmode] = 0
6363
6364
# put 2 for persons who prefer prt (probably few in pre PRT times)
6365
preeval[persons.ids_mode_preferred[ids_person] == self.prtservice.id_prtmode] = 2
6366
6367
print ' HcPrtStrategy.preevaluate', len(np.flatnonzero(preeval))
6368
return preeval
6369
6370
def plan(self, ids_person, logger=None):
6371
"""
6372
Generates a plan for these person according to this strategie.
6373
Overriden by specific strategy.
6374
"""
6375
print 'HcPrtStrategy.plan', len(ids_person)
6376
#make_plans_private(self, ids_person = None, mode = 'passenger')
6377
# routing necessary?
6378
virtualpop = self.get_virtualpop()
6379
scenario = virtualpop.get_scenario()
6380
plans = virtualpop.get_plans() # self._plans
6381
demand = scenario.demand
6382
#ptlines = demand.ptlines
6383
6384
walkstages = plans.get_stagetable('walks')
6385
prtstages = plans.get_stagetable('hcprttransits')
6386
activitystages = plans.get_stagetable('activities')
6387
6388
activities = virtualpop.get_activities()
6389
activitytypes = demand.activitytypes
6390
prtstops = self.prtservice.prtstops
6391
6392
if len(prtstops) == 0:
6393
print 'WARNING: no prt stops, no prt plans'
6394
return True
6395
6396
net = scenario.net
6397
edges = net.edges
6398
lanes = net.lanes
6399
modes = net.modes
6400
landuse = scenario.landuse
6401
facilities = landuse.facilities
6402
6403
times_est_plan = plans.times_est
6404
# here we can determine edge weights for different modes
6405
6406
# this could be centralized to avoid redundance
6407
plans.prepare_stagetables(['walks', 'hcprttransits', 'activities'])
6408
# must be after preparation:
6409
if self.prtservice.times_stop_to_stop is None:
6410
self.prtservice.make_times_stop_to_stop()
6411
6412
times_stop_to_stop = self.prtservice.times_stop_to_stop
6413
if times_stop_to_stop is None:
6414
print 'WARNING: stop to stop matrix not calculated. Please configure the PRT system.'
6415
return True
6416
6417
ids_person_act, ids_act_from, ids_act_to\
6418
= virtualpop.get_activities_from_pattern(0, ids_person=ids_person)
6419
6420
if len(ids_person_act) == 0:
6421
print 'WARNING in TrasitStrategy.plan: no eligible persons found.'
6422
return False
6423
6424
# temporary maps from ids_person to other parameters
6425
nm = np.max(ids_person_act)+1
6426
map_ids_plan = np.zeros(nm, dtype=np.int32)
6427
#ids_plan_act = virtualpop.add_plans(ids_person_act, id_strategy = self.get_id_strategy())
6428
map_ids_plan[ids_person_act] = virtualpop.add_plans(ids_person_act, id_strategy=self.get_id_strategy())
6429
6430
map_times = np.zeros(nm, dtype=np.int32)
6431
map_times[ids_person_act] = activities.get_times_end(ids_act_from, pdf='unit')
6432
6433
# set start time to plans (important!)
6434
plans.times_begin[map_ids_plan[ids_person_act]] = map_times[ids_person_act]
6435
6436
map_ids_fac_from = np.zeros(nm, dtype=np.int32)
6437
map_ids_fac_from[ids_person_act] = activities.ids_facility[ids_act_from]
6438
6439
n_plans = len(ids_person_act)
6440
print 'TrasitStrategy.plan n_plans=', n_plans
6441
6442
# make initial activity stage
6443
ids_edge_from = facilities.ids_roadedge_closest[map_ids_fac_from[ids_person_act]]
6444
poss_edge_from = facilities.positions_roadedge_closest[map_ids_fac_from[ids_person_act]]
6445
# this is the time when first activity starts
6446
# first activity is normally not simulated
6447
6448
names_acttype_from = activitytypes.names[activities.ids_activitytype[ids_act_from]]
6449
durations_act_from = activities.get_durations(ids_act_from)
6450
times_from = map_times[ids_person_act]-durations_act_from
6451
#times_from = activities.get_times_end(ids_act_from, pdf = 'unit')
6452
6453
for id_plan,\
6454
time,\
6455
id_act_from,\
6456
name_acttype_from,\
6457
duration_act_from,\
6458
id_edge_from,\
6459
pos_edge_from \
6460
in zip(map_ids_plan[ids_person_act],
6461
times_from,
6462
ids_act_from,
6463
names_acttype_from,
6464
durations_act_from,
6465
ids_edge_from,
6466
poss_edge_from):
6467
6468
id_stage_act, time = activitystages.append_stage(
6469
id_plan, time,
6470
ids_activity=id_act_from,
6471
names_activitytype=name_acttype_from,
6472
durations=duration_act_from,
6473
ids_lane=edges.ids_lanes[id_edge_from][0],
6474
positions=pos_edge_from,
6475
)
6476
6477
##
6478
6479
ind_act = 0
6480
6481
# main loop while there are persons performing
6482
# an activity at index ind_act
6483
while len(ids_person_act) > 0:
6484
ids_plan = map_ids_plan[ids_person_act]
6485
6486
times_from = map_times[ids_person_act]
6487
6488
names_acttype_to = activitytypes.names[activities.ids_activitytype[ids_act_to]]
6489
durations_act_to = activities.get_durations(ids_act_to)
6490
6491
ids_fac_from = map_ids_fac_from[ids_person_act]
6492
ids_fac_to = activities.ids_facility[ids_act_to]
6493
6494
centroids_from = facilities.centroids[ids_fac_from]
6495
centroids_to = facilities.centroids[ids_fac_to]
6496
dists_from_to = np.sqrt(np.sum((centroids_to - centroids_from)**2, 1))
6497
dists_walk_max = virtualpop.dists_walk_max[ids_person_act]
6498
6499
# origin edge and position
6500
ids_edge_from = facilities.ids_roadedge_closest[ids_fac_from]
6501
poss_edge_from = facilities.positions_roadedge_closest[ids_fac_from]
6502
6503
# destination edge and position
6504
# attention, this methods assumes that all stops are reachable by foot
6505
ids_edge_to = facilities.ids_roadedge_closest[ids_fac_to]
6506
poss_edge_to = facilities.positions_roadedge_closest[ids_fac_to]
6507
6508
# find closest prt stop!!
6509
#ids_stop_from, ids_stopedge_from = prtstops.get_closest(centroids_from)
6510
#ids_stop_to, ids_stopedge_to = prtstops.get_closest(centroids_to)
6511
6512
ids_stop_from, ids_stopedge_from, ids_stop_to, ids_stopedge_to = prtstops.get_closest_for_trip(
6513
centroids_from, centroids_to, ids_person=ids_person_act)
6514
6515
poss_stop_from = prtstops.get_waitpositions(ids_stop_from, offset=-0.5)
6516
poss_stop_to = prtstops.get_waitpositions(ids_stop_to, offset=-0.5)
6517
6518
i = 0.0
6519
for id_person, id_plan, time_from, id_act_from, id_act_to, name_acttype_to, duration_act_to, id_edge_from, pos_edge_from, id_edge_to, pos_edge_to, id_stop_from, id_stopedge_from, pos_stop_from, id_stop_to, id_stopedge_to, pos_stop_to, dist_from_to, dist_walk_max\
6520
in zip(ids_person_act, ids_plan, times_from, ids_act_from, ids_act_to, names_acttype_to, durations_act_to, ids_edge_from, poss_edge_from, ids_edge_to, poss_edge_to, ids_stop_from, ids_stopedge_from, poss_stop_from, ids_stop_to, ids_stopedge_to, poss_stop_to, dists_from_to, dists_walk_max):
6521
n_pers = len(ids_person_act)
6522
if logger:
6523
logger.progress(i/n_pers*100)
6524
i += 1.0
6525
print 79*'_'
6526
print ' id_plan=%d, id_person=%d, ' % (id_plan, id_person)
6527
6528
if id_person == 17214:
6529
print ' id_stop_from', id_stop_from, 'id_stop_to', id_stop_to
6530
print ' id_stopedge_from', id_stopedge_from, 'id_stopedge_to', id_stopedge_to
6531
6532
if (dist_from_to < dist_walk_max) | (id_edge_from == -1) | (id_edge_to == -1) | (id_stop_from == id_stop_to):
6533
print ' go by foot because distance is too short ', dist_from_to, 'edges', id_edge_from, id_edge_to, 'stops', id_stop_from, id_stop_to
6534
6535
id_stage_walk1, time = walkstages.append_stage(
6536
id_plan, time_from,
6537
id_edge_from=id_edge_from,
6538
position_edge_from=pos_edge_from,
6539
id_edge_to=id_edge_to,
6540
position_edge_to=pos_edge_to,
6541
)
6542
else:
6543
id_stage_walk1, time = walkstages.append_stage(id_plan, time_from,
6544
id_edge_from=id_edge_from,
6545
position_edge_from=pos_edge_from,
6546
id_edge_to=id_stopedge_from,
6547
position_edge_to=pos_stop_from, # -7.0,
6548
)
6549
6550
# take PRT
6551
# self.ids_edge_to_ids_prtstop
6552
id_stage_transit, time = prtstages.append_stage(
6553
id_plan, time,
6554
duration=times_stop_to_stop[id_stop_from, id_stop_to],
6555
id_fromedge=id_stopedge_from,
6556
id_toedge=id_stopedge_to,
6557
)
6558
6559
# walk from final prtstop to activity
6560
# print ' Stage for linktype %2d fromedge %s toedge %s'%(linktype, edges.ids_sumo[id_stopedge_to],edges.ids_sumo[id_edge_to] )
6561
id_stage_walk2, time = walkstages.append_stage(id_plan, time,
6562
id_edge_from=id_stopedge_to,
6563
position_edge_from=pos_stop_to,
6564
id_edge_to=id_edge_to,
6565
position_edge_to=pos_edge_to,
6566
)
6567
6568
# update time for trips estimation for this plan
6569
plans.times_est[id_plan] += time-time_from
6570
6571
# define current end time without last activity duration
6572
plans.times_end[id_plan] = time
6573
6574
id_stage_act, time = activitystages.append_stage(
6575
id_plan, time,
6576
ids_to=id_act_to,
6577
names_totype=name_acttype_to,
6578
durations=duration_act_to,
6579
ids_lane=edges.ids_lanes[id_edge_to][0],
6580
positions=pos_edge_to,
6581
)
6582
6583
# store time for next iteration in case other activities are
6584
# following
6585
map_times[id_person] = time
6586
6587
# select persons and activities for next setp
6588
ind_act += 1
6589
ids_person_act, ids_act_from, ids_act_to\
6590
= virtualpop.get_activities_from_pattern(ind_act, ids_person=ids_person_act)
6591
6592
6593
class HcPrtTransits(StageTypeMixin):
6594
def __init__(self, ident, stages,
6595
name='Ride on HCPRT',
6596
info='Ride on High Capacity Personal Rapid Transit network.',
6597
# **kwargs,
6598
):
6599
6600
print 'HcPrtTransits.__init__', ident, stages
6601
self.init_stagetable(ident,
6602
stages, name=name,
6603
info=info,
6604
)
6605
self._init_attributes()
6606
self._init_constants()
6607
6608
def _init_attributes(self):
6609
edges = self.get_virtualpop().get_net().edges
6610
6611
self.add_col(am.IdsArrayConf('ids_fromedge', edges,
6612
groupnames=['parameters'],
6613
name='Edge ID from',
6614
info='Edge ID of departure PRT station.',
6615
))
6616
6617
self.add_col(am.IdsArrayConf('ids_toedge', edges,
6618
groupnames=['parameters'],
6619
name='Edge ID to',
6620
info='Edge ID of destination PRT station.',
6621
))
6622
6623
def set_prtservice(self, prtservice):
6624
print 'HcPrtTransits.set_prtservice', prtservice, 'id(self)', id(self)
6625
self.add(cm.ObjConf(prtservice, is_child=False, groups=['_private']))
6626
6627
def get_prtservice(self):
6628
print 'get_prtservice', self, id(self)
6629
return self.hcprtservice.get_value()
6630
6631
def prepare_planning(self):
6632
6633
prtservice = self.get_prtservice()
6634
print 'HcPrtTransits.prepare_planning', prtservice.times_stop_to_stop
6635
if prtservice.times_stop_to_stop is None:
6636
prtservice.make_times_stop_to_stop()
6637
print prtservice.times_stop_to_stop
6638
6639
def append_stage(self, id_plan, time_start=-1.0,
6640
duration=0.0,
6641
id_fromedge=-1, id_toedge=-1, **kwargs):
6642
"""
6643
Appends a PRT transit stage to plan id_plan.
6644
6645
"""
6646
# print 'HcPrtTransits.append_stage',id_stage
6647
6648
id_stage, time_end = StageTypeMixin.append_stage(self,
6649
id_plan,
6650
time_start,
6651
durations=duration,
6652
ids_fromedge=id_fromedge,
6653
ids_toedge=id_toedge,
6654
)
6655
6656
# add this stage to the vehicle database
6657
# ind_ride gives the index of this ride (within the same plan??)
6658
#ind_ride = self.parent.get_individualvehicles().append_ride(id_veh, id_stage)
6659
return id_stage, time_end
6660
6661
def to_xml(self, id_stage, fd, indent=0):
6662
# <ride from="1/3to0/3" to="0/4to1/4" lines="train0"/>
6663
net = self.get_virtualpop().get_net()
6664
#ids_stoplane = net.ptstops.ids_lane
6665
#ids_laneedge = net.lanes.ids_edge
6666
ids_sumoedge = net.edges.ids_sumo
6667
6668
#ind = self.get_ind(id_stage)
6669
fd.write(xm.start('ride', indent=indent))
6670
fd.write(xm.num('from', ids_sumoedge[self.ids_fromedge[id_stage]]))
6671
fd.write(xm.num('to', ids_sumoedge[self.ids_toedge[id_stage]]))
6672
fd.write(xm.num('lines', 'prt'))
6673
# if self.cols.pos_edge_from[ind]>0:
6674
# fd.write(xm.num('departPos', self.cols.pos_edge_from[ind]))
6675
# if self.cols.pos_edge_to[ind]>0:
6676
# fd.write(xm.num('arrivalPos', self.cols.pos_edge_to[ind]))
6677
6678
fd.write(xm.stopit()) # ends stage
6679
6680
6681
class VehicleMan(am.ArrayObjman):
6682
def __init__(self, ident, prtservices, **kwargs):
6683
self._init_objman(ident=ident,
6684
parent=prtservices,
6685
name='HC PRT vehicle management',
6686
info='HC PRT vehicle management.',
6687
#xmltag = ('additional','busStop','stopnames'),
6688
version=0.0,
6689
**kwargs)
6690
6691
self._init_attributes()
6692
self._init_constants()
6693
6694
def _init_attributes(self):
6695
self.add(cm.AttrConf('time_update', 2.0,
6696
groupnames=['parameters'],
6697
name='Man. update time',
6698
info="Update time for vehicle management.",
6699
unit='s',
6700
))
6701
6702
# self.time_update.set(5.0)
6703
6704
self.add(cm.AttrConf('time_update_flows', 10.0,
6705
groupnames=['parameters'],
6706
name='Flow update time',
6707
info="Update time for flow estimations.",
6708
unit='s',
6709
))
6710
# self.time_update.set(10.0)
6711
# if hasattr(self,'time_flowaverage'):
6712
# self.delete('time_flowaverage')
6713
6714
self.add(cm.AttrConf('time_est_max', 1200,
6715
groupnames=['parameters'],
6716
name='prediction interval',
6717
info="Prediction time range of vehicle management.",
6718
unit='s',
6719
))
6720
6721
self.add(cm.AttrConf('time_search_occupied', 10.0,
6722
groupnames=['parameters'],
6723
name='Occupied search time',
6724
info="Time interval for search of optimum departure time in case of an occupied vehicle trip.",
6725
unit='s',
6726
))
6727
6728
self.add(cm.AttrConf('time_search_empty', 20.0,
6729
groupnames=['parameters'],
6730
name='Empty search time',
6731
info="Time interval for search of optimum departure time in case of an empty vehicle trip.",
6732
unit='s',
6733
))
6734
6735
self.add(cm.AttrConf('weight_demand', 0.01,
6736
groupnames=['parameters'],
6737
name='Demand weight',
6738
info="Weight of current demand at stations when assigning empty vehicles trips.",
6739
))
6740
6741
self.add(cm.AttrConf('weight_flow', 1.0,
6742
groupnames=['parameters'],
6743
name='Flow weight',
6744
info="Weight of flows (changes in demand over time) at stations when assigning empty vehicles trips.",
6745
))
6746
6747
self.add(cm.AttrConf('constant_timeweight', 0.005,
6748
groupnames=['parameters'],
6749
name='Time weight const.',
6750
info="Constant for the exponential decay function weighting the time instance in the optimization function.",
6751
unit='1/s',
6752
))
6753
6754
self.add(cm.AttrConf('flow_max_default', 700.0,
6755
groupnames=['parameters'],
6756
name='Default max. veh flow',
6757
info="Maximum vehicle flow allowed for a stop. This is a default value an may be replaced by capacity capculations that depend on the geometry of the stop.",
6758
unit='1/h',
6759
))
6760
6761
# def set_stops(self,vehicleman):
6762
# self.add( cm.ObjConf( stops, is_child = False,groups = ['_private']))
6763
6764
def _init_constants(self):
6765
self.do_not_save_attrs([
6766
'ids_stop', 'numbers_veh_arr', 'n_est_max',
6767
'inflows_sched', 'inflows_person', 'inflows_person_last',
6768
'ids_veh', 'ids_stop_target', 'ids_stop_current',
6769
'times_order', 'occupiedtrips_new', 'emptytrips_new',
6770
'are_emptytrips',
6771
'log_inflows_temp',
6772
])
6773
6774
def get_stops(self):
6775
return self.parent.prtstops
6776
6777
def get_vehicles(self):
6778
return self.parent.prtvehicles
6779
6780
def get_scenario(self):
6781
return self.parent.parent.get_scenario()
6782
6783
def prepare_sim(self, process):
6784
print 'VehicleMan.prepare_sim'
6785
net = self.get_scenario().net
6786
6787
# station management
6788
# self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1,dtype = np.object)
6789
6790
self.ids_stop = self.get_stops().get_ids()
6791
6792
if len(self.ids_stop) == 0:
6793
return []
6794
6795
n_stoparray = np.max(self.ids_stop)+1
6796
6797
# number of arrived vehicles for each station and all future time intervals
6798
self.numbers_veh_arr = np.zeros(n_stoparray, dtype=np.int32)
6799
self.n_est_max = int(self.time_est_max.get_value()/self.time_update_flows.get_value())
6800
6801
# maximum station flows as maximum number of vehicles per timeslot
6802
# this should be delivered by each station in function of its dimension
6803
# self.flow_max_default.get_value() # vehicles per hour
6804
6805
self.flows_stop_max = np.zeros(n_stoparray, dtype=np.float32)
6806
6807
for id_stop in self.ids_stop:
6808
self.flows_stop_max[id_stop] = self.get_stops().get_capacity(
6809
id_stop) / (3600.0/self.time_update_flows.get_value())
6810
6811
#self.flows_stop_max = self.flow_max_default.get_value()/(3600.0/self.time_update_flows.get_value()) * np.ones(n_stoparray, dtype = np.float32)
6812
6813
# current targets by station, updated by station and processed each veh. man. step
6814
# this is the target stop of the vehicle(s) waiting at each stop to be launched by the vehicle man
6815
self.ids_stop_target_current = -1*np.ones(n_stoparray, dtype=np.int32)
6816
6817
# current etimated times to targets by station, updated by station and processed each veh. man. step
6818
self.duration_est_target_current = np.zeros(n_stoparray, dtype=np.float32)
6819
6820
# current number of waiting vehicles with targets by station, updated by station and processed each veh. man. step
6821
self.numbers_veh_target_current = np.zeros(n_stoparray, dtype=np.int32)
6822
6823
# scheduled departure time for vehicles to be launched at each station
6824
self.times_departure_sched = -np.ones(n_stoparray, dtype=np.int32)
6825
6826
# scheduled flows for each station and each future time intervals
6827
self.inflows_sched = np.zeros((n_stoparray, self.n_est_max), dtype=np.int32)
6828
6829
# inflow of persons for each stop in current time interval
6830
self.inflows_person = np.zeros(n_stoparray, dtype=np.int32)
6831
6832
# inflow of persons for each stop in last time interval
6833
self.inflows_person_last = np.zeros(n_stoparray, dtype=np.int32)
6834
6835
# numbers of vehicles which initiated a trip to each target station
6836
# the trip initiates when the vehicle is still in the berth
6837
# and ends when the vehicle is entering the target station
6838
self.numbers_veh_target_init = np.zeros(n_stoparray, dtype=np.int32)
6839
6840
# vehicle management
6841
self.ids_veh = self.get_vehicles().get_ids()
6842
6843
if len(self.ids_veh) == 0:
6844
print 'WARNING: no PRT vehicles, please add PRT vehicles.'
6845
return []
6846
6847
n_veharray = np.max(self.ids_veh)+1
6848
6849
# could go in vehicle array
6850
6851
self.ids_stop_target = -1*np.ones(n_veharray, dtype=np.int32)
6852
self.ids_stop_current = -1*np.ones(n_veharray, dtype=np.int32)
6853
self.times_order = 10**6*np.ones(n_veharray, dtype=np.int32)
6854
# self.occupiedtrips_new = []#?? put this is also in general time scheme with more urgency??
6855
#self.emptytrips_new = []
6856
6857
# from veh arrays
6858
#self.are_emptytrips = np.zeros(n_veharray, dtype = np.bool)
6859
6860
# logging
6861
results = process.get_results()
6862
if results is not None:
6863
time_update_flows = self.time_update_flows.get_value()
6864
n_timesteps = int((process.duration-process.time_warmup)/time_update_flows+1)
6865
results.hcprtstopresults.init_recording(n_timesteps, time_update_flows)
6866
6867
# number of vehicles arrived in each stop during one time interval
6868
self.log_inflows_temp = np.zeros(n_stoparray, dtype=np.int32)
6869
6870
return [(self.time_update.get_value(), self.process_step),
6871
(self.time_update_flows.get_value(), self.update_flows),
6872
]
6873
6874
def update_flows(self, process):
6875
print 'HC VehicleMan update flow prediction'
6876
self.inflows_sched[:, 0] = 0
6877
self.inflows_sched = np.roll(self.inflows_sched, -1)
6878
time_update_flows = self.time_update_flows.get_value()
6879
6880
if process.simtime > process.time_warmup:
6881
stops = self.get_stops()
6882
ids_stop = self.ids_stop
6883
# print ' dir(results)',dir(process.get_results())
6884
prtstopresults = process.get_results().hcprtstopresults
6885
const_time = 1.0/time_update_flows # np.array([1.0/time_update_flows],dtype=np.float32)
6886
timestep = (process.simtime - process.simtime_start - process.time_warmup)/time_update_flows
6887
prtstopresults.record(timestep, ids_stop,
6888
inflows_veh=np.array(const_time * self.log_inflows_temp[ids_stop], dtype=np.float32),
6889
inflows_veh_sched=np.array(
6890
const_time * self.inflows_sched[ids_stop, 0], dtype=np.float32),
6891
numbers_person_wait=stops.numbers_person_wait[ids_stop],
6892
waittimes_tot=stops.waittimes_tot[ids_stop],
6893
inflows_person=np.array(const_time * self.inflows_person[ids_stop], dtype=np.float32),
6894
#inflows_person = stops.flows_person[ids_stop],
6895
)
6896
if self.debug > 5:
6897
for id_stop in ids_stop:
6898
self.display_flows_est(id_stop)
6899
6900
self.inflows_person_last = self.inflows_person.copy()
6901
self.inflows_person[:] = 0
6902
self.log_inflows_temp[:] = 0
6903
6904
def process_step(self, process):
6905
print 79*'M'
6906
print 'HC VehicleMan.process_step'
6907
6908
self.debug = 9
6909
6910
# push all vehicles out of output queue, if flow conditions allow
6911
# these are vehicles which have already a destination
6912
self.push_out_vehicles(process)
6913
6914
is_cont = True
6915
while is_cont:
6916
surpluses_veh, surpluses_veh_urgent, demands_veh, balances_veh, n_move_eff_total = self.equalize_empty_vehicles(
6917
process)
6918
#is_cont = (n_move_eff_total>0) & ((np.any(surpluses_veh > 0) & np.any(balances_veh < 0)) | np.any(surpluses_veh_urgent > 0))
6919
is_cont = (n_move_eff_total > 0) & np.any(surpluses_veh_urgent > 0)
6920
is_cont = False
6921
if self.debug > 4:
6922
print 79*'-'
6923
print ' check equalize iteration', np.any(surpluses_veh > 0), np.any(balances_veh > 0), np.any(surpluses_veh_urgent > 0), 'is_cont', is_cont
6924
print ' n_move_eff_total', n_move_eff_total
6925
print ' surpluses_veh', surpluses_veh
6926
print ' demands_veh', demands_veh
6927
print ' balances_veh', balances_veh
6928
print ' surpluses_veh_urgent', surpluses_veh_urgent
6929
6930
if 0:
6931
stops = self.get_stops()
6932
#vehicles = self.get_vehicles()
6933
6934
has_programmed = True
6935
#ids_veh_ready_for_departure = stops.ids_veh_ready_for_departure[self.ids_stop]
6936
6937
while has_programmed:
6938
has_programmed = False
6939
6940
if len(inds_valid) > 0:
6941
6942
has_programmed |= self.push_out_vehicles(ids_veh_ready_for_departure, process)
6943
ids_veh_lead = stops.ids_veh_lead[self.ids_stop]
6944
inds_valid = np.flatnonzero(ids_veh_lead >= 0)
6945
has_programmed |= self.push_empty_leadvehs(ids_veh_lead[inds_valid], process)
6946
ids_veh_lead = stops.ids_veh_lead[self.ids_stop]
6947
inds_valid = np.flatnonzero(ids_veh_lead >= 0)
6948
6949
#has_programmed |= self.pull_empty_leadvehs(ids_veh_lead[inds_valid],process)
6950
#ids_veh_lead = stops.ids_veh_lead[self.ids_stop]
6951
#inds_valid = np.flatnonzero(ids_veh_lead >= 0)
6952
# print ' main:ids_veh_lead',has_programmed,len(inds_valid), stops.ids_veh_lead[self.ids_stop]
6953
else:
6954
# no more leaders
6955
has_programmed = False
6956
# print '\n terminated vehicle man n_est_max',self.n_est_max
6957
# print ' inflows_sched=\n',self.inflows_sched
6958
6959
def note_person_entered(self, id_stop, n_pax):
6960
# here just estimate person flows
6961
self.inflows_person[id_stop] += n_pax
6962
6963
def note_vehs_ready_for_departure(self, id_stop, id_stop_target, time_est, n_veh):
6964
print 'note_vehs_ready_for_departure id_stop', id_stop, id_stop_target, time_est, n_veh
6965
self.ids_stop_target_current[id_stop] = id_stop_target
6966
self.duration_est_target_current[id_stop] = time_est
6967
self.numbers_veh_target_current[id_stop] = n_veh
6968
6969
def fit_vehicles(self, id_stop, n_veh, ind_time_arrival):
6970
"""
6971
Try to fit n_veh at stop id_stop for the arrival timeslot ind_time_arrival
6972
6973
Returns:
6974
flows_alloc: a vector that distributes the newly allocated vehicles
6975
over one or more timeslots.
6976
If the vector is of zero size means vehicles cannot be fit
6977
"""
6978
capa = self.flows_stop_max[id_stop]
6979
n_slots = int(np.ceil(float(n_veh)/capa))
6980
6981
n_slots_search_empty = int(self.time_search_empty.get_value()/self.time_update_flows.get_value()+0.5)
6982
6983
# extend search interval proportionally to the number of slots
6984
# idea behind is that room for more slots are more difficult to find
6985
n_slots_search = n_slots_search_empty + n_slots
6986
if self.debug > 1:
6987
print 'fit_vehicles n_veh', n_veh, 'n_slots', n_slots, 'capa_slots %.2f' % (capa * n_slots), 'at slot', ind_time_arrival, 'n_slots_search', n_slots_search
6988
ind_delay = 0
6989
is_fit = False
6990
while (ind_delay < n_slots_search) & (not is_fit) & (ind_time_arrival + ind_delay + n_slots < self.n_est_max):
6991
6992
ind_time_arrival_sched = ind_time_arrival + ind_delay
6993
flows_sched = self.inflows_sched[id_stop, ind_time_arrival_sched:ind_time_arrival_sched+n_slots]
6994
6995
is_fit = np.sum(flows_sched) + n_veh < capa * n_slots
6996
print ' ind_delay', ind_delay, 'is_fit', is_fit, 'from', ind_time_arrival_sched, 'to', ind_time_arrival_sched + n_slots, 'flows_sched', flows_sched, # 'max',self.n_est_max
6997
ind_delay += 1
6998
6999
# check if sufficient time-slots in the future are available
7000
# at estimated arrival time
7001
if self.debug > 2:
7002
print ' ind_time_arrival_sched', ind_time_arrival_sched, 'ind_delay', ind_delay
7003
print ' flows_sched ', flows_sched
7004
print ' n_slots ', n_slots, 'scheduled', np.sum(flows_sched), 'avail', capa * n_slots, 'is_fit', is_fit
7005
7006
if self.debug > 5:
7007
self.display_flows_est(id_stop, ind_time_arrival_sched, ind_time_arrival_sched+n_slots)
7008
7009
if is_fit:
7010
# n_veh fit in n_slots, considering also previous allocations
7011
7012
# distribute the n_veh over n_slots by filling up time slot to capacity
7013
capa_slot = capa
7014
flows_alloc = np.zeros(n_slots, dtype=np.int32)
7015
i_slot = 0
7016
n_alloc_cum = 0
7017
while (i_slot < n_slots) & (n_alloc_cum < n_veh):
7018
flow_sched = flows_sched[i_slot]
7019
capa_avail = capa_slot - flow_sched
7020
n_alloc = min(int(capa_avail), n_veh-n_alloc_cum)
7021
if self.debug > 5:
7022
print ' i_slot', i_slot, 'capa_slot %.2f' % capa_slot, 'capa_avail %.2f' % capa_avail, 'n_alloc', n_alloc, 'n_alloc_cum', n_alloc_cum
7023
if n_alloc > 0:
7024
flows_alloc[i_slot] += n_alloc
7025
n_alloc_cum += n_alloc
7026
if self.debug > 5:
7027
print ' add n_alloc', n_alloc, 'n_alloc_cum', n_alloc_cum
7028
# capacity of next slot is augmented by the
7029
# rest capacity of the present slot
7030
capa_slot = capa + (capa - n_alloc - flow_sched)
7031
7032
i_slot += 1
7033
7034
# finally check whether all vehicle have been assigned
7035
if self.debug > 2:
7036
print ' n_alloc_cum', n_alloc_cum, 'n_veh', n_veh, 'flows_alloc', flows_alloc
7037
7038
# due to rounding errors the rest of the last slot may not be assigned
7039
if n_alloc_cum < n_veh:
7040
# assign the difference to the last slot
7041
flows_alloc[i_slot-1] += n_veh-n_alloc_cum
7042
7043
return flows_alloc, ind_time_arrival_sched
7044
7045
return [], -1
7046
7047
def get_timeslot_occupation(self, id_stop, n_veh):
7048
"""
7049
NO LONGER USED!!
7050
Returns for stop id_stop:
7051
capacity limit at integer level
7052
the number of needed timeslots to process n_veh vehicles
7053
the required flows for each time slot
7054
"""
7055
capa = self.flows_stop_max[id_stop]
7056
7057
#capa_int = int(capa)
7058
7059
n_slots = n_slots = np.ceil(float(n_veh)/capa)
7060
7061
print 'get_timeslot_occupation n_veh', n_veh, 'capa_int', capa_int, 'n_slots', n_slots, 'rem', n_veh - n_slots*capa_int
7062
if n_slots == 0:
7063
flows = np.zeros(1, dtype=np.int32)
7064
else:
7065
flows = np.ones(n_slots, dtype=np.int32)*capa_int
7066
7067
flows[0] += n_veh - n_slots*capa_int
7068
7069
return n_slots, flows
7070
7071
def push_out_vehicles(self, process):
7072
"""
7073
Kick vehicles out of stops if vehicles are ready to depart.
7074
Kick out immediately if flow-conditions at target allow.
7075
If not, delay appropriately and kick out later.
7076
"""
7077
simtime = process.simtime
7078
time_update_flows = self.time_update_flows.get_value()
7079
7080
stops = self.get_stops()
7081
ids_stop_all = stops.get_ids()
7082
ids_stop = ids_stop_all[self.numbers_veh_target_current[ids_stop_all] > 0]
7083
print 'HC push_out_vehicles of %d stops' % (len(ids_stop))
7084
#vehicles = self.get_vehicles()
7085
7086
ids_stop_launched = []
7087
for id_stop, id_stop_target, duration_est, n_veh\
7088
in zip(
7089
ids_stop,
7090
self.ids_stop_target_current[ids_stop],
7091
self.duration_est_target_current[ids_stop],
7092
self.numbers_veh_target_current[ids_stop],
7093
):
7094
time_depart = self.times_departure_sched[id_stop]
7095
print '\n check id_stop', id_stop, 'id_stop_target', id_stop_target, 'n_veh', n_veh, 'dur %.2f' % duration_est, 't_dep', time_depart, 'simtime', simtime
7096
7097
if time_depart != -1:
7098
print ' delay has been programmed is_launch', simtime > time_depart
7099
if (simtime > time_depart):
7100
# simtime has reached scheduled departure time, so launch
7101
self.times_departure_sched[id_stop] = -1
7102
is_launch = True
7103
else:
7104
# simtime has not yet reached scheduled departure time
7105
is_launch = False
7106
else:
7107
# no delay is programmed so check out availability of capacity
7108
time_arr_est = simtime + duration_est
7109
ind_time_arrival = int(duration_est/time_update_flows+0.5)
7110
7111
print ' time_arr_est', time_arr_est, 'ind_time_arrival', ind_time_arrival, 'in range', ind_time_arrival < self.n_est_max
7112
7113
if ind_time_arrival < self.n_est_max:
7114
# required number of free time slots for n_veh
7115
flows_alloc, ind_time_arrival_sched = self.fit_vehicles(id_stop_target, n_veh, ind_time_arrival)
7116
n_alloc = len(flows_alloc)
7117
if n_alloc > 0:
7118
# allocation successful
7119
self.inflows_sched[id_stop_target,
7120
ind_time_arrival_sched:ind_time_arrival_sched+n_alloc] += flows_alloc
7121
print ' schedule id_stop_target', id_stop_target, 'inflows_sched', self.inflows_sched[id_stop_target, ind_time_arrival_sched:ind_time_arrival_sched+n_alloc]
7122
if ind_time_arrival_sched == ind_time_arrival:
7123
print ' immediate launch'
7124
self.times_departure_sched[id_stop] = -1
7125
is_launch = True
7126
else:
7127
# delayed launch, determine scheduled launch time
7128
self.times_departure_sched[id_stop] = simtime + \
7129
ind_time_arrival_sched * time_update_flows - duration_est
7130
print ' delayed launch: sched dep time', self.times_departure_sched[id_stop]
7131
is_launch = False
7132
7133
else:
7134
print 'WARNING: no capacity available at id_stop_target', id_stop_target, ' at this arrival time.'
7135
is_launch = False
7136
else:
7137
#
7138
print'WARNING: arrival time out of measurement range for id_stop_target', id_stop_target
7139
is_launch = True
7140
7141
if is_launch:
7142
# here stop is called to start vehicles
7143
# argument id_stop_target is passed to check if correct
7144
# vehicle platoon is started. Alternatively this could be done
7145
# by an order ID that has been placed when notifying
7146
# the presence of the platoons at exit
7147
ids_stop_launched.append(id_stop)
7148
stops.launch_vehs(id_stop, id_stop_target)
7149
self.numbers_veh_arr[id_stop_target] += n_veh
7150
7151
if len(ids_stop_launched) > 0:
7152
# vehicles from at least one stop have been launched
7153
self.ids_stop_target_current[ids_stop_launched] = -1
7154
self.duration_est_target_current[ids_stop_launched] = 0.0
7155
self.numbers_veh_target_current[ids_stop_launched] = -1
7156
7157
return True
7158
else:
7159
return False
7160
7161
def equalize_empty_vehicles(self, process):
7162
"""
7163
from /home/joerg/projects/sumopy/sumopy-201022/plugins/hcprt/hcprt.py
7164
Launches empty vehicle trips from the stops with the highest
7165
vehicle supply to the station with the highest demand.
7166
"""
7167
n_move_eff_total = 0
7168
simtime = process.simtime
7169
time_update_flows = self.time_update_flows.get_value()
7170
times_stop_to_stop = self.parent.times_stop_to_stop
7171
7172
stops = self.get_stops()
7173
ids_stop = stops.get_ids()
7174
n_stops = len(ids_stop)
7175
print 'equalize_empty_vehicles of %d stops' % n_stops
7176
7177
balances_veh = np.zeros(n_stops, dtype=np.float32)
7178
demands_veh = np.zeros(n_stops, dtype=np.float32)
7179
surpluses_veh = np.zeros(n_stops, dtype=np.int32)
7180
surpluses_veh_urgent = np.zeros(n_stops, dtype=np.int32)
7181
waittimes_max = np.zeros(n_stops, dtype=np.int32)
7182
vehicles = self.get_vehicles()
7183
7184
#ids_stop_launched = []
7185
i = 0
7186
for id_stop, n_pax_wait, inflow_pax\
7187
in zip(
7188
ids_stop, stops.numbers_person_wait[ids_stop],
7189
# self.inflows_person[ids_stop]## no, not filtered
7190
stops.flows_person[ids_stop]):
7191
surplus_veh, surplus_veh_urgent = stops.get_surplus_veh(id_stop)
7192
7193
surplus_veh_future = self.numbers_veh_target_init[id_stop]
7194
#surplus_veh_future = np.sum(self.inflows_sched[id_stop, :])
7195
n_pax_future = 0.5*inflow_pax * self.n_est_max
7196
waittimes_max[i] = stops.get_waittime_max(id_stop, simtime)
7197
7198
surpluses_veh[i] = surplus_veh # this is current surplus, vehicles immediately available
7199
surpluses_veh_urgent[i] = surplus_veh_urgent # number of vehicles that need to be kicked out
7200
if self.debug > 2:
7201
print '\n sssssssssseek destinations for id_stop', id_stop
7202
7203
if self.debug > 5:
7204
self.display_flows_est(id_stop)
7205
7206
demands_veh[i] = -surplus_veh - surplus_veh_future + n_pax_wait + n_pax_future
7207
balances_veh[i] = 1000.0 * surplus_veh_urgent + 1.0 * \
7208
surplus_veh + surplus_veh_future - n_pax_wait - n_pax_future
7209
7210
if self.debug > 2:
7211
print ' surplus_veh', surplus_veh, 'surplus_future', surplus_veh_future, 'surplus_veh_urgent', surplus_veh_urgent
7212
print ' n_pax_wait ', n_pax_wait, 'n_pax_future', n_pax_future
7213
print ' balance ', balances_veh[i]
7214
print ' waittime_max ', waittimes_max[i]
7215
i += 1
7216
7217
inds_sorted = np.argsort(balances_veh)
7218
7219
#surpluses_veh_emitters = surpluses_veh[inds_sorted[::-1]]
7220
if self.debug > 2:
7221
print ' Emitters sorted:'
7222
print ' ids_stop_sorted ', ids_stop[inds_sorted[::-1]]
7223
print ' surpluses_veh', surpluses_veh[inds_sorted[::-1]]
7224
print ' balances_sorted ', balances_veh[inds_sorted[::-1]]
7225
print ' max(surpluses_veh)', max(surpluses_veh)
7226
print ' >>>max(balances_veh)', max(balances_veh)
7227
7228
if (np.max(balances_veh) > 0) & (max(surpluses_veh) > 0):
7229
7230
i = 0
7231
for id_stop_from, ind_from in zip(ids_stop[inds_sorted[::-1]], inds_sorted[::-1]):
7232
balance_from = balances_veh[ind_from]
7233
surplus_from = surpluses_veh[ind_from]
7234
surplus_veh_urgent_from = surpluses_veh_urgent[ind_from]
7235
demand_from = demands_veh[ind_from]
7236
7237
# distribute surplus on neares, most in need
7238
if (surplus_from >= 1) & (balance_from >= 1):
7239
if self.debug > 5:
7240
# ,'ind_from',ind_from,'continue?',(surplus_from >= 1) & (balance_from >= 1)
7241
print '\n potential emitter stop: id_stop_from', id_stop_from, 'surplus_from', surplus_from, 'balance_from', balance_from
7242
# there are empties to send away and positive balance
7243
utilities = np.zeros(n_stops, dtype=np.float32)
7244
numbers_move = np.zeros(n_stops, dtype=np.int32)
7245
j = 0
7246
for id_stop_to, ind_to in zip(ids_stop[inds_sorted], inds_sorted):
7247
if id_stop_to != id_stop_from:
7248
demand_to = demands_veh[ind_to]
7249
balance_to = balances_veh[ind_to]
7250
waittime_max_to = waittimes_max[ind_to]
7251
time_to = times_stop_to_stop[id_stop_from, id_stop_to]
7252
7253
if self.debug > 5:
7254
print ' j', j, 'id_stop_from ', id_stop_from, 'id_stop_to', id_stop_to
7255
print ' balance_from', balance_from, 'balance_to', balance_to, 'min', -balance_to+0.5, surplus_from
7256
print ' demand_to', demand_to, 'waittime_max_to', waittime_max_to
7257
7258
if (surplus_from >= 1) & (balance_from >= 1) & (demand_to > 0):
7259
# the demand of the station is positive
7260
# here the utility looks at the maximum waiting times
7261
7262
# move the maximum possible number of available vehicles
7263
n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))
7264
if self.debug > 5:
7265
print ' potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to
7266
#utilities[j] = n_move+ self.constant_timeweight*time_to
7267
utilities[j] = float(n_move)/float(time_to)
7268
#utilities[j] = waittime_max_to/float(time_to)
7269
numbers_move[j] = n_move
7270
if self.debug > 5:
7271
print ' =>U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)
7272
7273
elif (surplus_veh_urgent_from > 0):
7274
# we have a stop where we want to send out the maximum number of vehicles
7275
# here the utility looks mainly at the highest demand of the destination
7276
7277
# if possible, move as much possible as there is demand
7278
#n_move = min(int(demand_to+0.5), surplus_veh_urgent_from)
7279
#n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))
7280
n_move = surplus_veh_urgent_from
7281
7282
# high balance means vehicle needs to be kicked out
7283
7284
if self.debug > 5:
7285
print ' forced potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to
7286
#utilities[j] = n_move+ self.constant_timeweight*time_to
7287
#utilities[j] = float(n_move)/float(time_to)
7288
utilities[j] = n_move*(demand_to)/float(time_to)
7289
numbers_move[j] = n_move
7290
if self.debug > 5:
7291
print ' =>U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)
7292
7293
j += 1
7294
7295
ind_max = np.argmax(utilities)
7296
utility_max = utilities[ind_max]
7297
7298
# limit platoon length here
7299
# TODO: here shoulld be the max platoon length of the station??
7300
# or is this done in the platoon formation?
7301
n_move = min(numbers_move[ind_max], 8)
7302
7303
#min(numbers_move[ind_max], self.flows_stop_max[ids_stop[inds_sorted][ind_max]])
7304
if (n_move > 0) & (utility_max > 0):
7305
# there are some useful moves
7306
n_move_eff = stops.route_empties(
7307
id_stop_from, ids_stop[inds_sorted][ind_max], numbers_move[ind_max], simtime)
7308
if self.debug > 2:
7309
print ' moved', n_move_eff, 'of', numbers_move[ind_max], 'empty vehs from', id_stop_from, 'to', ids_stop[inds_sorted][ind_max], 'utility_max', utility_max
7310
7311
# continute till balance is zero?
7312
# indeed need to update balances
7313
surpluses_veh[ind_from] -= n_move_eff
7314
balances_veh[ind_from] -= n_move_eff
7315
#balances_veh[ind_max] += n_move
7316
balances_veh[inds_sorted[ind_max]] += n_move_eff
7317
demands_veh[inds_sorted[ind_max]] -= n_move_eff
7318
7319
# break
7320
else:
7321
break
7322
7323
i += 1
7324
7325
return surpluses_veh, surpluses_veh_urgent, demands_veh, balances_veh, n_move_eff_total
7326
7327
def equalize_empty_vehicles_broke(self, process):
7328
"""
7329
Launches empty vehicle trips from the stops with the highest
7330
vehicle supply to the station with the highest demand.
7331
"""
7332
simtime = process.simtime
7333
time_update_flows = self.time_update_flows.get_value()
7334
times_stop_to_stop = self.parent.times_stop_to_stop
7335
7336
stops = self.get_stops()
7337
ids_stop = stops.get_ids()
7338
n_stops = len(ids_stop)
7339
print 'equalize_empty_vehicles of %d stops' % n_stops
7340
7341
balances_veh = np.zeros(n_stops, dtype=np.float32)
7342
demands_veh = np.zeros(n_stops, dtype=np.float32)
7343
surpluses_veh = np.zeros(n_stops, dtype=np.int32)
7344
surpluses_veh_urgent = np.zeros(n_stops, dtype=np.int32)
7345
waittimes_max = np.zeros(n_stops, dtype=np.int32)
7346
vehicles = self.get_vehicles()
7347
n_move_eff_total = 0
7348
7349
#ids_stop_launched = []
7350
i = 0
7351
for id_stop, n_pax_wait, inflow_pax\
7352
in zip(
7353
ids_stop, stops.numbers_person_wait[ids_stop],
7354
# self.inflows_person[ids_stop]## no, not filtered
7355
stops.flows_person[ids_stop]):
7356
surplus_veh, surplus_veh_urgent = stops.get_surplus_veh(id_stop)
7357
7358
surplus_veh_future = self.numbers_veh_target_init[id_stop]
7359
#surplus_veh_future = np.sum(self.inflows_sched[id_stop, :])
7360
n_pax_future = 0.5*inflow_pax * self.n_est_max
7361
waittimes_max[i] = stops.get_waittime_max(id_stop, simtime)
7362
7363
surpluses_veh[i] = surplus_veh # this is current surplus, vehicles immediately available
7364
surpluses_veh_urgent[i] = surplus_veh_urgent # number of vehicles that need to be kicked out
7365
if self.debug > 2:
7366
print '\n sssssssssseek destinations for id_stop', id_stop
7367
7368
if self.debug > 5:
7369
self.display_flows_est(id_stop)
7370
7371
demands_veh[i] = -surplus_veh - surplus_veh_future + n_pax_wait + n_pax_future
7372
# factor 1000 should move station with too many vehicles to the top of the queue
7373
# but current sort by current surplus_veh
7374
#balances_veh[i] = 1000.0 *surplus_veh_urgent + 1.0*surplus_veh + surplus_veh_future - n_pax_wait - n_pax_future
7375
balances_veh[i] = 1.0*surplus_veh + surplus_veh_future - n_pax_wait - n_pax_future
7376
if self.debug > 2:
7377
print ' surplus_veh', surplus_veh, 'surplus_future', surplus_veh_future, 'surplus_veh_urgent', surplus_veh_urgent
7378
print ' n_pax_wait ', n_pax_wait, 'n_pax_future', n_pax_future
7379
print ' balance ', balances_veh[i]
7380
print ' waittime_max ', waittimes_max[i]
7381
i += 1
7382
7383
# sort per surpluses, because this is the most critical quantity
7384
# because if there are no vehicle, no vehicle cen be send
7385
#inds_sorted = np.argsort(balances_veh)
7386
inds_sorted = np.argsort(surpluses_veh*(surpluses_veh_urgent+1))
7387
#surpluses_veh_emitters = surpluses_veh[inds_sorted[::-1]]
7388
if self.debug > 2:
7389
print ' Emitters sorted:'
7390
print ' ids_stop_sorted ', ids_stop[inds_sorted[::-1]]
7391
print ' surpluses_veh', surpluses_veh[inds_sorted[::-1]]
7392
print ' surpluses_veh_urgent', surpluses_veh_urgent[inds_sorted[::-1]]
7393
7394
print ' balances_sorted ', balances_veh[inds_sorted[::-1]]
7395
print ' max(surpluses_veh)', max(surpluses_veh)
7396
print ' >>>max(balances_veh)', max(balances_veh)
7397
7398
if (np.max(balances_veh) > 0) & (max(surpluses_veh) > 0):
7399
if self.debug > 5:
7400
print ' start optimizing target', len(inds_sorted[::-1])
7401
i = 0
7402
for id_stop_from, ind_from in zip(ids_stop[inds_sorted[::-1]], inds_sorted[::-1]):
7403
balance_from = balances_veh[ind_from]
7404
surplus_from = surpluses_veh[ind_from]
7405
surplus_veh_urgent_from = surpluses_veh_urgent[ind_from]
7406
demand_from = demands_veh[ind_from]
7407
print ' surplus_from', surplus_from, 'balance_from', balance_from
7408
# distribute surplus on neares, most in need
7409
if (surplus_from >= 1) & (balance_from >= 1):
7410
if self.debug > 5:
7411
# ,'ind_from',ind_from,'continue?',(surplus_from >= 1) & (balance_from >= 1)
7412
print '\n potential emitter stop: id_stop_from', id_stop_from, 'surplus_from', surplus_from, 'balance_from', balance_from
7413
# there are empties to send away and positive balance
7414
utilities = np.zeros(n_stops, dtype=np.float32)
7415
numbers_move = np.zeros(n_stops, dtype=np.int32)
7416
j = 0
7417
for id_stop_to, ind_to in zip(ids_stop[inds_sorted], inds_sorted):
7418
demand_to = demands_veh[ind_to]
7419
balance_to = balances_veh[ind_to]
7420
waittime_max_to = waittimes_max[ind_to]
7421
time_to = times_stop_to_stop[id_stop_from, id_stop_to]
7422
7423
if self.debug > 5:
7424
print ' id_stop_from ', id_stop_from, 'id_stop_to', id_stop_to
7425
print ' balance_from', balance_from, 'balance_to', balance_to, 'min', -balance_to+0.5, surplus_from
7426
print ' demand_to', demand_to, 'waittime_max_to', waittime_max_to
7427
7428
if (surplus_from >= 1) & (balance_from >= 1) & (demand_to > 0):
7429
# the demand of the station is positive
7430
# here the utility looks at the maximum waiting times
7431
7432
# move the maximum possible number of available vehicles
7433
n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))
7434
if self.debug > 5:
7435
print ' potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to
7436
#utilities[j] = n_move+ self.constant_timeweight*time_to
7437
#utilities[j] = float(n_move)/float(time_to)
7438
utilities[j] = (waittime_max_to*demand_to)/float(time_to)
7439
numbers_move[j] = n_move
7440
if self.debug > 5:
7441
print ' ********'
7442
print ' U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)
7443
print ' ********'
7444
j += 1
7445
7446
elif 0: # (surplus_veh_urgent_from> 0 ):
7447
# we have a stop where we want to send out the maximum number of vehicles
7448
# here the utility looks mainly at the highest demand of the destination
7449
7450
# if possible, move as much possible as there is demand
7451
#n_move = min(int(demand_to+0.5), surplus_veh_urgent_from)
7452
#n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))
7453
n_move = surplus_veh_urgent_from
7454
7455
# high balance means vehicle needs to be kicked out
7456
7457
if self.debug > 5:
7458
print ' forced potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to
7459
#utilities[j] = n_move+ self.constant_timeweight*time_to
7460
#utilities[j] = float(n_move)/float(time_to)
7461
utilities[j] = n_move*(demand_to)/float(time_to)
7462
numbers_move[j] = n_move
7463
if self.debug > 5:
7464
print ' U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)
7465
j += 1
7466
7467
ind_max = np.argmax(utilities)
7468
utility_max = utilities[ind_max]
7469
7470
# limit platoon length here
7471
# TODO: here shoulld be the max platoon length of the station??
7472
# or is this done in the platoon formation?
7473
n_move = min(numbers_move[ind_max], 8)
7474
if self.debug > 2:
7475
print ' utility_max %.0f' % utility_max, 'ind_max', ind_max, 'n_move', n_move
7476
#min(numbers_move[ind_max], self.flows_stop_max[ids_stop[inds_sorted][ind_max]])
7477
if n_move > 0:
7478
# there are some useful moves
7479
n_move_eff = stops.route_empties(
7480
id_stop_from, ids_stop[inds_sorted][ind_max], numbers_move[ind_max], simtime)
7481
if self.debug > 2:
7482
print ' => moved', n_move_eff, 'of', numbers_move[ind_max], 'empty vehs from', id_stop_from, 'to', ids_stop[inds_sorted][ind_max], 'utility_max', utility_max
7483
7484
# continute till balance is zero?
7485
# indeed need to update balances
7486
surpluses_veh[ind_from] -= n_move_eff
7487
# this is done in any case , does not matter when it becomes negative
7488
surpluses_veh_urgent[ind_from] -= n_move_eff
7489
balances_veh[ind_from] -= n_move_eff
7490
#balances_veh[ind_max] += n_move
7491
balances_veh[inds_sorted[ind_max]] += n_move_eff
7492
demands_veh[inds_sorted[ind_max]] -= n_move_eff
7493
n_move_eff_total += n_move_eff
7494
# break
7495
else:
7496
break
7497
7498
i += 1
7499
7500
return surpluses_veh, surpluses_veh_urgent, demands_veh, balances_veh, n_move_eff_total
7501
7502
def display_flows_est(self, id_stop, timeind_begin=None, timeind_end=None):
7503
# print 'display_flows_est',id_stop
7504
n_char = 80
7505
disp = np.zeros(n_char, dtype='S1')
7506
disp[:] = ' '
7507
flows = self.inflows_sched[id_stop, :]
7508
factor = 1.0/self.n_est_max*n_char
7509
inds = np.flatnonzero(flows)
7510
inds_disp = np.array(inds*factor, dtype=np.int32)
7511
disp[inds_disp] = self.inflows_sched[id_stop, inds]
7512
7513
print '%03d' % id_stop+(n_char-3)*'.'
7514
print string.join(disp, '')
7515
7516
disp = None
7517
if timeind_begin is not None:
7518
disp = np.zeros(n_char, dtype='S1')
7519
disp[:] = ' '
7520
disp[int(timeind_begin*factor+0.5)] = '>'
7521
if timeind_end is not None:
7522
disp[int(timeind_end*factor+0.5)] = '<'
7523
7524
if disp is not None:
7525
print string.join(disp, '')
7526
# print ' flows',flows
7527
# print ' inds',inds
7528
# print ' inds_disp',inds_disp
7529
7530
def pull_empty_leadvehs_old(self, ids_veh_lead, process):
7531
7532
n_timeslot_offset = 2
7533
7534
#self.numbers_veh = np.zeros(np.max(ids)+1, dtype = np.int32)
7535
#self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype = np.int32)
7536
7537
# inds_valid = np.flatnonzero( (vehicles.states[ids_veh_lead] == VEHICLESTATES['waiting'])\
7538
# & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0))
7539
vehicles = self.get_vehicles()
7540
stops = self.get_stops()
7541
print 'pull_empty_leadvehs', ids_veh_lead
7542
# print ' bordingstate',vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding']
7543
# print ' nowaits stop',stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] ==0
7544
7545
times_stop_to_stop = self.parent.times_stop_to_stop
7546
7547
# get potential pull vehicles
7548
inds_valid = np.flatnonzero((vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding'])
7549
& (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0))
7550
7551
# print ' states',vehicles.states[ids_veh_lead], VEHICLESTATES['boarding']
7552
# print ' numbers_person_wait',stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]]
7553
# print ' &',(vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding'])\
7554
# & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0)
7555
# print ' origins inds_valid',inds_valid
7556
if len(inds_valid) == 0:
7557
# print ' all stops busy'
7558
return False
7559
7560
#ids_veh_lead = ids_veh_lead[inds_valid]
7561
ids_stop_current = self.ids_stop_current[ids_veh_lead[inds_valid]]
7562
7563
# print ' available for pulling ids_veh_lead',ids_veh_lead
7564
# print ' ids_stop_current',ids_stop_current
7565
# get potential target station with demand
7566
demands = stops.numbers_person_wait[self.ids_stop]\
7567
- (0.5*stops.numbers_veh[self.ids_stop]
7568
+ self.numbers_veh_arr[self.ids_stop])
7569
inds_valid = np.flatnonzero(demands > 0)
7570
# print ' targets inds_valid',inds_valid
7571
if len(inds_valid) == 0:
7572
# print ' no demand'
7573
return False
7574
7575
ids_stop_target = self.ids_stop[inds_valid]
7576
demands = demands[inds_valid]
7577
7578
print ' ids_stop_current', ids_stop_current
7579
# print ' ids_stop_target',ids_stop_target
7580
# print ' demands',demands
7581
# calculate cost matrix with id_stop_current in rows and id_stop_target
7582
7583
#n_origin = len(ids_stop_current)
7584
#n_targets = len(ids_stop_target)
7585
times = times_stop_to_stop[ids_stop_current, :][:, ids_stop_target]
7586
times[times == 0] = 99999
7587
timeweight = np.exp(-self.constant_timeweight.get_value() * times)
7588
#costs = times_stop_to_stop[ids_stop_current,:][:,ids_stop_target]
7589
#costs[costs == 0] = 99999
7590
# print ' timeweight\n',timeweight
7591
7592
costs = timeweight * demands
7593
for id_stop_target, demand, number_veh, number_veh_arr\
7594
in zip(ids_stop_target, demands, stops.numbers_veh[ids_stop_target], self.numbers_veh_arr[ids_stop_target]):
7595
print ' id_stop_target', id_stop_target, 'dem', demand, 'n_veh', number_veh, 'n_veh_arr', number_veh_arr
7596
7597
#costs = np.zeros(costs.size, np.float32)-demands
7598
7599
inds_pull = np.argmax(costs, 1)
7600
# print ' costs\n',costs
7601
# print ' ->inds_pull,ids_stop_target',inds_pull,ids_stop_target[inds_pull]
7602
7603
durations_est = times_stop_to_stop[ids_stop_current, ids_stop_target[inds_pull]]
7604
# print ' duration_est, t_est_max',durations_est,self.n_est_max*self.time_update_flows.get_value()
7605
7606
inds_time_min = n_timeslot_offset+np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value(
7607
), dtype=np.int32), 0, self.n_est_max-1-n_timeslot_offset), dtype=np.int32)
7608
inds_time_max = inds_time_min+2
7609
# print ' inds_time_min',inds_time_min
7610
# print ' inds_time_max',inds_time_max
7611
7612
is_started = False
7613
for id_veh_lead, state, id_stop_current, id_stop_target, time_order, ind_min, ind_max, duration_est\
7614
in zip(
7615
ids_veh_lead[inds_valid],
7616
vehicles.states[ids_veh_lead],
7617
ids_stop_current,
7618
ids_stop_target[inds_pull],
7619
self.times_order[ids_veh_lead],
7620
inds_time_min,
7621
inds_time_max,
7622
durations_est,
7623
):
7624
7625
print ' check veh prt.%d' % (id_veh_lead), state, 'id_stop_current', id_stop_current, 'id_stop_target', id_stop_target
7626
7627
#VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6}
7628
# if state == VEHICLESTATES['occupiedtrip']:
7629
7630
#ids_stop = list(self.ids_stop)
7631
# ids_stop.remove(id_stop)
7632
#costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop]-self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop,ids_stop]
7633
#ids_stop [np.argmax(costs)]
7634
inds_time = np.arange(ind_min, ind_max)
7635
costs = self.inflows_sched[id_stop_current, inds_time]
7636
ind_time_depart = inds_time[np.argmin(costs)]
7637
7638
self.inflows_sched[id_stop_target, ind_time_depart] += 1
7639
time_depart = process.simtime + ind_time_depart*self.time_update_flows.get_value()-duration_est
7640
7641
# this is a workarouned that vehicle does first reach the stopline
7642
# before it gets rescheduled...try with stoplinecheck
7643
7644
# if time_depart < process.simtime+15:
7645
# time_depart = process.simtime+15
7646
# print ' ind_time_depart, time_arr, duration_est',ind_time_depart,process.simtime + ind_time_depart*self.time_update_flows.get_value(),duration_est
7647
# print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order
7648
7649
stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart)
7650
self.numbers_veh_arr[id_stop_target] += 1
7651
is_started = True
7652
7653
return is_started
7654
7655
def init_trip_occupied(self, id_veh, id_stop_from, id_stop_to, time_order):
7656
"""
7657
Called from the stop when a vehicle in the berth initiate a trip with
7658
a the target destination of persons who entered
7659
"""
7660
print 'init_trip_occupied to', id_stop_to
7661
# search closest stop
7662
#self.are_emptytrips[id_veh] = False
7663
7664
self.numbers_veh_target_init[id_stop_to] += 1
7665
7666
#self.ids_stop_current[id_veh] = id_stop_from
7667
#self.ids_stop_target[id_veh] = id_stop_to
7668
#self.times_order[id_veh] = time_order
7669
7670
def init_trip(self, id_veh, id_stop, id_stop_to, time_order):
7671
"""
7672
Called from the stop when a vehicle in the berth initiate a trip with
7673
a the target destination
7674
"""
7675
print 'init_trip_empty to', id_stop_to
7676
7677
self.numbers_veh_target_init[id_stop_to] += 1
7678
7679
def init_trip_empty_old(self, id_veh, id_stop, id_stop_to, time_order):
7680
"""
7681
Called from the stop when a vehicle in the berth initiate a trip with
7682
a the target destination defined by the vehicle management
7683
"""
7684
print 'init_trip_empty to', id_stop_to
7685
7686
self.numbers_veh_target_init[id_stop_to] += 1
7687
7688
#self.ids_stop_current[id_veh] = id_stop
7689
#self.times_order[id_veh] = time_order
7690
7691
def indicate_trip_empty_old(self, id_veh, id_stop, time_order):
7692
# print 'indicate_trip_empty id_veh,id_stop',id_veh,id_stop
7693
# search closest stop
7694
self.ids_stop_current[id_veh] = id_stop
7695
self.times_order[id_veh] = time_order
7696
7697
def get_stop_emptytrip_old(self, id_stop):
7698
stops = self.get_stops()
7699
ids_stop = list(self.ids_stop)
7700
ids_stop.remove(id_stop)
7701
costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop] -
7702
self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop, ids_stop]
7703
7704
return ids_stop[np.argmax(costs)]
7705
7706
def conclude_trip(self, id_veh, id_stop, is_final_dest=False):
7707
#self.ids_stop_target[id_veh] = -1
7708
7709
if is_final_dest:
7710
# counts vehvicles to target since launche from stop
7711
self.numbers_veh_arr[id_stop] += 1
7712
7713
# counts vehicles to target since programming in berth
7714
# this count is anticipating earlier the number of vehicle going to
7715
# each stop
7716
self.numbers_veh_target_init[id_stop] -= 1
7717
7718
# measures actually arrived vehicles at stop
7719
# accumulates counts over one flow measurement interval
7720
self.log_inflows_temp[id_stop] += 1
7721
7722
7723
class HcPrtService(SimobjMixin, DemandobjMixin, cm.BaseObjman):
7724
def __init__(self, ident, simulation=None,
7725
name='HC PRT service', info='High capacity PRT service',
7726
**kwargs):
7727
# print 'PrtService.__init__',name
7728
7729
self._init_objman(ident=ident, parent=simulation,
7730
name=name, info=info, **kwargs)
7731
7732
attrsman = self.set_attrsman(cm.Attrsman(self))
7733
7734
# make PRTservice a demand object as link
7735
self.get_scenario().demand.add_demandobject(obj=self)
7736
7737
self._init_attributes()
7738
self._init_constants()
7739
7740
def get_scenario(self):
7741
return self.parent.parent
7742
7743
def _init_attributes(self):
7744
print 'HcPrtService._init_attributes'
7745
attrsman = self.get_attrsman()
7746
scenario = self.get_scenario()
7747
# here we ged classes not vehicle type
7748
# specific vehicle type within a class will be generated later
7749
modechoices = scenario.net.modes.names.get_indexmap()
7750
7751
# print ' modechoices',modechoices
7752
self.id_prtmode = attrsman.add(am.AttrConf('id_prtmode', modechoices['custom1'],
7753
groupnames=['options'],
7754
choices=modechoices,
7755
name='Mode',
7756
info='PRT transport mode (or vehicle class).',
7757
))
7758
7759
self.prtstops = attrsman.add(cm.ObjConf(PrtPlatoonStops('prtstops', self)))
7760
self.compressors = attrsman.add(cm.ObjConf(Compressors('compressors', self)))
7761
self.decompressors = attrsman.add(cm.ObjConf(Decompressors('decompressors', self)))
7762
self.mergenodes = attrsman.add(cm.ObjConf(Mergenodes('mergenodes', self)))
7763
self.prtvehicles = attrsman.add(cm.ObjConf(PrtVehicles('prtvehicles', self)))
7764
self.vehicleman = attrsman.add(cm.ObjConf(VehicleMan('vehicleman', self)))
7765
7766
#self.demo = attrsman.add( cm.ObjConf(TraciDemo('demo',self)))
7767
7768
# --------------------------------------------------------------------
7769
# prt transit table
7770
# attention: prttransits will be a child of virtual pop,
7771
# and a link from prt service
7772
7773
# if not hasattr(self,'prttransit'):
7774
virtualpop = self.get_scenario().demand.virtualpop
7775
prttransits = virtualpop.get_plans().add_stagetable('hcprttransits', HcPrtTransits)
7776
7777
print ' prttransits =', prttransits, id(prttransits)
7778
# add attribute as link
7779
# self.prttransits = attrsman.add(\
7780
# cm.ObjConf(prttransits,is_child = False ),
7781
# is_overwrite = False,)
7782
prttransits.set_prtservice(self)
7783
7784
prtstrategy = virtualpop.get_strategies().add_strategy(
7785
'hcprt', HcPrtStrategy, np.array([208, 50, 156, 230], np.float32)/255)
7786
# self.prttransits = attrsman.add(\
7787
# cm.ObjConf(prttransits,is_child = False ),
7788
# is_overwrite = False,)
7789
prtstrategy.set_prtservice(self)
7790
7791
# temporary attrfix
7792
#prtserviceconfig = self.parent.get_attrsman().prtservice
7793
#prtserviceconfig.groupnames = []
7794
#prtserviceconfig.add_groupnames(['demand objects'])
7795
7796
def _init_constants(self):
7797
# print 'PrtService._init_constants',self,self.parent
7798
attrsman = self.get_attrsman()
7799
self.times_stop_to_stop = None
7800
self.fstar = None
7801
self._results = None
7802
7803
attrsman.do_not_save_attrs(['times_stop_to_stop', 'fstar', '_results'
7804
'times_stop_to_stop', 'ids_edge_to_ids_prtstop',
7805
])
7806
7807
def get_vtypes(self):
7808
7809
ids_vtypes = set(self.prtvehicles.ids_vtype.get_value())
7810
return ids_vtypes
7811
7812
def get_writexmlinfo(self, is_route=False, is_plain=False, **kwargs):
7813
"""
7814
Returns three array where the first array is the
7815
begin time of the first vehicle and the second array is the
7816
write function to be called for the respectice vehicle and
7817
the third array contains the vehicle ids
7818
7819
Method used to sort trips when exporting to route or trip xml file
7820
"""
7821
print 'PRT.get_writexmlinfo'
7822
7823
if is_plain:
7824
return [], [], []
7825
7826
# time of first PRT vehicle(s) to be inserted
7827
virtualpop = self.get_scenario().demand.virtualpop
7828
t_start = virtualpop.get_time_depart_first()
7829
7830
#t_start = 0.0
7831
# time between insertion of consecutive vehicles at same stop
7832
t_delta = 10 # s
7833
7834
n_veh = len(self.prtvehicles)
7835
times_depart = np.zeros(n_veh, dtype=np.int32)
7836
writefuncs = np.zeros(n_veh, dtype=np.object)
7837
writefuncs[:] = self.write_prtvehicle_xml
7838
ids_veh = self.prtvehicles.get_ids()
7839
7840
id_edge_prev = -1
7841
i = 0
7842
t0 = t_start
7843
for id_edge in self.prtvehicles.ids_currentedge[ids_veh]:
7844
# print ' id_edge, t_start, id_edge_prev',id_edge, t0, id_edge_prev
7845
times_depart[i] = t0
7846
t0 += t_delta
7847
if id_edge != id_edge_prev:
7848
t0 = t_start
7849
id_edge_prev = 1*id_edge
7850
i += 1
7851
7852
return times_depart, writefuncs, ids_veh
7853
7854
def write_prtvehicle_xml(self, fd, id_veh, time_begin, indent=2):
7855
# print 'write_prtvehicle_xml',id_veh, time_begin
7856
# TODO: actually this should go in prtvehicles
7857
#time_veh_wait_after_stop = 3600
7858
scenario = self.get_scenario()
7859
net = scenario.net
7860
7861
#lanes = net.lanes
7862
edges = net.edges
7863
#ind_ride = rides.get_inds(id_stage)
7864
#id_veh = rides.ids_veh[id_stage]
7865
prtvehicles = self.prtvehicles
7866
#ptstops = net.ptstops
7867
#prtstops = self.parent.prtstops
7868
#ids_prtstop = prtstops.get_ids()
7869
#ids_ptstop = prtstops.ids_ptstop[id_stop]
7870
# lanes.ids_edge[ptstops.ids_lane[ids_ptstop]],
7871
#id_lane_from = parking.ids_lane[id_parking_from]
7872
#laneindex_from = lanes.indexes[id_lane_from]
7873
#pos_from = parking.positions[id_parking_from]
7874
7875
#id_parking_to = rides.ids_parking_to[id_stage]
7876
#id_lane_to = parking.ids_lane[id_parking_to]
7877
#laneindex_to = lanes.indexes[id_lane_to]
7878
#pos_to = parking.positions[id_parking_to]
7879
7880
# write unique veh ID to prevent confusion with other veh declarations
7881
fd.write(xm.start('vehicle id="%s"' % prtvehicles.get_id_sumo(id_veh), indent+2))
7882
7883
fd.write(xm.num('depart', '%d' % time_begin))
7884
fd.write(xm.num('type', scenario.demand.vtypes.ids_sumo[prtvehicles.ids_vtype[id_veh]]))
7885
fd.write(xm.num('line', prtvehicles.get_id_line_xml()))
7886
fd.write(xm.num('departPos', 'base'))
7887
fd.write(xm.num('departLane', 2))
7888
fd.write(xm.stop())
7889
7890
# write route
7891
fd.write(xm.start('route', indent+4))
7892
# print ' edgeindex[ids_edge]',edgeindex[ids_edge]
7893
fd.write(xm.arr('edges', [edges.ids_sumo[prtvehicles.ids_currentedge[id_veh]]]))
7894
7895
# does not seem to have an effect, always starts at base????
7896
#fd.write(xm.num('departPos', 'base'))
7897
#fd.write(xm.num('departLane', 2 ))
7898
fd.write(xm.stopit())
7899
7900
# write depart stop
7901
# fd.write(xm.start('stop',indent+4))
7902
#fd.write(xm.num('lane', edges.ids_sumo[lanes.ids_edge[id_lane_from]]+'_%d'%laneindex_from ))
7903
#fd.write(xm.num('duration', time_veh_wait_after_stop))
7904
#fd.write(xm.num('startPos', pos_from ))
7905
#fd.write(xm.num('endPos', pos_from + parking.lengths[id_parking_from]))
7906
#fd.write(xm.num('triggered', "True"))
7907
# fd.write(xm.stopit())
7908
7909
fd.write(xm.end('vehicle', indent+2))
7910
7911
# def make_stops_and_vehicles(self, n_veh = -1):
7912
# self.prtstops.make_from_net()
7913
# self.prtvehicles.make(n_veh)
7914
# self.make_times_stop_to_stop()
7915
7916
def prepare_sim(self, process):
7917
print 'prepare_sim', self.ident
7918
# print ' self.times_stop_to_stop',self.times_stop_to_stop
7919
7920
if self.fstar is None:
7921
self.make_fstar()
7922
7923
if self.times_stop_to_stop is None:
7924
print ' times_stop_to_stop'
7925
self.make_times_stop_to_stop()
7926
7927
updatedata = self.prtvehicles.prepare_sim(process)
7928
updatedata += self.prtstops.prepare_sim(process)
7929
#updatedata += self.compressors.prepare_sim(process)
7930
#updatedata += self.decompressors.prepare_sim(process)
7931
updatedata += self.mergenodes.prepare_sim(process)
7932
updatedata += self.vehicleman.prepare_sim(process)
7933
#
7934
#updatedata += self.demo.prepare_sim(process)
7935
# print 'PrtService.prepare_sim updatedata',updatedata
7936
return updatedata
7937
7938
def make_fstar(self, is_update=False):
7939
if (self.fstar is None) | is_update:
7940
self.fstar = self.get_fstar()
7941
self.edgetimes = self.get_times(self.fstar)
7942
7943
def get_route(self, id_fromedge, id_toedge):
7944
"""
7945
Centralized function to determin fastest route between
7946
PRT network edges.
7947
"""
7948
duration, route = get_mincostroute_edge2edge(id_fromedge, id_toedge,
7949
weights=self.edgetimes, fstar=self.fstar)
7950
7951
return route, duration
7952
7953
def make_times_stop_to_stop(self, fstar=None, times=None):
7954
print 'make_times_stop_to_stop'
7955
log = self.get_logger()
7956
if fstar is None:
7957
if self.fstar is None:
7958
self.make_fstar()
7959
7960
fstar = self.fstar # get_fstar()
7961
times = self.edgetimes # self.get_times(fstar)
7962
7963
if len(fstar) == 0:
7964
self.times_stop_to_stop = [[]]
7965
return
7966
7967
ids_prtstop = self.prtstops.get_ids()
7968
if len(ids_prtstop) == 0:
7969
self.get_logger().w('WARNING: no PRT stops, no plans. Generate them!')
7970
return
7971
7972
ids_edge = self.prtstops.get_edges(ids_prtstop)
7973
7974
# check if all PRT stop edges are in fstar
7975
ids_ptstop = self.prtstops.ids_ptstop[ids_prtstop] # for debug only
7976
is_incomplete_fstar = False
7977
for id_edge, id_stop, id_ptstop in zip(ids_edge, ids_prtstop, ids_ptstop):
7978
# print ' Found PRT stop %d, PT stop %d with id_edge %d '%(id_stop,id_ptstop, id_edge)
7979
if not fstar.has_key(id_edge):
7980
print 'WARNING in make_times_stop_to_stop: PRT stop %d, PT stop %d has no id_edge %d in fstar' % (id_stop, id_ptstop, id_edge)
7981
is_incomplete_fstar = True
7982
7983
# check if fstar is complete (all to edges are in keys)
7984
ids_fromedge_set = set(fstar.keys())
7985
ids_sumo = self.get_scenario().net.edges.ids_sumo
7986
for id_fromedge in ids_fromedge_set:
7987
if not ids_fromedge_set.issuperset(fstar[id_fromedge]):
7988
is_incomplete_fstar = True
7989
ids_miss = fstar[id_fromedge].difference(ids_fromedge_set)
7990
print 'WARNING in make_times_stop_to_stop: incomplete fstar of id_fromedge = %d, %s' % (id_fromedge, ids_sumo[id_fromedge])
7991
for id_edge in ids_miss:
7992
print ' missing', id_edge, ids_sumo[id_edge]
7993
7994
if is_incomplete_fstar:
7995
return
7996
7997
# print ' ids_prtstop,ids_edge',ids_prtstop,ids_edge
7998
n_elem = np.max(ids_prtstop)+1
7999
stop_to_stop = np.zeros((n_elem, n_elem), dtype=np.int32)
8000
8001
ids_edge_to_ids_prtstop = np.zeros(np.max(ids_edge)+1, dtype=np.int32)
8002
ids_edge_to_ids_prtstop[ids_edge] = ids_prtstop
8003
8004
ids_edge_target = set(ids_edge)
8005
8006
for id_stop, id_edge in zip(ids_prtstop, ids_edge):
8007
# print ' route for id_stop, id_edge',id_stop, id_edge
8008
8009
# remove origin from target
8010
ids_edge_target.discard(id_edge)
8011
8012
costs, routes = edgedijkstra(id_edge,
8013
ids_edge_target=ids_edge_target,
8014
weights=times, fstar=fstar
8015
)
8016
8017
# print ' ids_edge_target',ids_edge_target
8018
# print ' costs\n', costs
8019
# print ' routes\n', routes
8020
# for route in routes:
8021
# if len(route)==0:
8022
# print 'WARNING in make_times_stop_to_stop: empty route'
8023
# else:
8024
# print ' found route to id_edge, id_stop',route[-1],ids_edge_to_ids_prtstop[route[-1]],len(route)
8025
8026
if costs is not None:
8027
# TODO: could be vectorialized, but not so easy
8028
for id_edge_target in ids_edge_target:
8029
#stop_to_stop[id_edge,id_edge_target] = costs[id_edge_target]
8030
# print ' stop_orig,stop_target,costs ',ids_edge_to_ids_prtstop[id_edge],ids_edge_to_ids_prtstop[id_edge_target],costs[id_edge_target]
8031
# print ' stop_orig,costs ',ids_edge_to_ids_prtstop[id_edge],ids_sumo[id_edge]
8032
# print ' stop_target',ids_edge_to_ids_prtstop[id_edge_target],ids_sumo[id_edge_target]
8033
# print ' costs ',costs[id_edge_target]
8034
# stop_to_stop[ids_edge_to_ids_prtstop[[id_edge,id_edge_target]]]=costs[id_edge_target]
8035
if id_edge_target in costs:
8036
stop_to_stop[ids_edge_to_ids_prtstop[id_edge],
8037
ids_edge_to_ids_prtstop[id_edge_target]] = costs[id_edge_target]
8038
else:
8039
print 'WARNING in make_times_stop_to_stop: unreacle station id_fromedge = %d, %s' % (id_edge_target, ids_sumo[id_edge_target])
8040
is_incomplete_fstar = True
8041
8042
# put back origin to targets (probably not the best way)
8043
ids_edge_target.add(id_edge)
8044
# print ' ids_edge_target (all)',ids_edge_target
8045
8046
# print ' stop_to_stop',stop_to_stop
8047
# TODO: here we could also store the routes
8048
8049
if is_incomplete_fstar:
8050
return False
8051
8052
self.times_stop_to_stop = stop_to_stop
8053
self.ids_edge_to_ids_prtstop = ids_edge_to_ids_prtstop
8054
print ' times_stop_to_stop=\n', self.times_stop_to_stop
8055
return True
8056
8057
def get_fstar(self):
8058
"""
8059
Returns the forward star graph of the network as dictionary:
8060
fstar[id_fromedge] = set([id_toedge1, id_toedge2,...])
8061
"""
8062
print 'get_fstar'
8063
net = self.get_scenario().net
8064
# prt mode
8065
id_mode = self.id_prtmode
8066
8067
#ids_edge = self.get_ids()
8068
#fstar = np.array(np.zeros(np.max(ids_edge)+1, np.obj))
8069
fstar = {}
8070
connections = net.connections
8071
lanes = net.lanes
8072
8073
#inds_con = connections.get_inds()
8074
#ids_fromlane = connections.ids_fromlane.get_value()[inds_con]
8075
#ids_tolane = connections.ids_tolane.get_value()[inds_con]
8076
8077
ids_con = connections.get_ids()
8078
ids_fromlane = connections.ids_fromlane[ids_con]
8079
ids_tolane = connections.ids_tolane[ids_con]
8080
8081
ids_mainmode_from = lanes.ids_mode[ids_fromlane]
8082
ids_mainmode_to = lanes.ids_mode[ids_tolane]
8083
8084
#ids_modes_allow_from = lanes.ids_modes_allow[ids_fromlane]
8085
#ids_modes_allow_to = lanes.ids_modes_allow[ids_tolane]
8086
8087
ids_fromedge = lanes.ids_edge[ids_fromlane]
8088
ids_toedge = lanes.ids_edge[ids_tolane]
8089
# print ' ids_fromedge',ids_fromedge
8090
# print ' ids_modes_allow',ids_modes_allow
8091
8092
for id_fromedge, id_toedge, id_mode_allow_from, id_mode_allow_to, id_fromlane, id_tolane in\
8093
zip(ids_fromedge, ids_toedge, ids_mainmode_from, ids_mainmode_to,
8094
ids_fromlane, ids_tolane):
8095
8096
if id_mode_allow_from == id_mode:
8097
if id_mode_allow_to == id_mode:
8098
8099
if fstar.has_key(id_fromedge):
8100
fstar[id_fromedge].add(id_toedge)
8101
else:
8102
fstar[id_fromedge] = set([id_toedge])
8103
# if id_fromedge == 14048:
8104
# print ' id_fromedge, id_toedge',id_fromedge, id_toedge,fstar.has_key(id_fromedge)
8105
# print ' id_fromlane, id_tolane ',id_fromlane, id_tolane
8106
# print ' id_mode_allow_from, id_mode_allow_to',id_mode_allow_from, id_mode_allow_to
8107
8108
# for id_fromedge, id_toedge,ids_mode_allow_from,id_modes_allow_to in\
8109
# zip(ids_fromedge, ids_toedge, ids_modes_allow_from, ids_modes_allow_to):
8110
# if len(ids_mode_allow_from)>0:
8111
# if ids_mode_allow_from[-1] == id_mode:
8112
# if len(id_modes_allow_to)>0:
8113
# if id_modes_allow_to[-1] == id_mode:
8114
#
8115
# if fstar.has_key(id_fromedge):
8116
# fstar[id_fromedge].add(id_toedge)
8117
# else:
8118
# fstar[id_fromedge]=set([id_toedge])
8119
8120
return fstar
8121
8122
def get_times(self, fstar):
8123
"""
8124
Returns freeflow travel times for all edges.
8125
The returned array represents the speed and the index corresponds to
8126
edge IDs.
8127
8128
"""
8129
if len(fstar) == 0:
8130
return []
8131
8132
net = self.get_scenario().net
8133
#id_mode = net.modes.get_id_mode(mode)
8134
id_mode = self.id_prtmode
8135
# print 'get_times id_mode,is_check_lanes,speed_max',id_mode,is_check_lanes,speed_max
8136
ids_edge = np.array(fstar.keys(), dtype=np.int32)
8137
8138
times = np.array(np.zeros(np.max(ids_edge)+1, np.float32))
8139
speeds = net.edges.speeds_max[ids_edge]
8140
8141
# limit allowed speeds with max speeds of mode
8142
speeds = np.clip(speeds, 0.0, net.modes.speeds_max[id_mode])
8143
8144
times[ids_edge] = net.edges.lengths[ids_edge]/speeds
8145
8146
return times
8147
8148
def config_results(self, results):
8149
print 'HcPrtService.config_results', results, id(results)
8150
# keep a link to results here because needed to
8151
# log data during simulation
8152
# this link should not be followed during save process
8153
#self._results = results
8154
8155
tripresults = res.Tripresults('hcprttripresults', results,
8156
self.prtvehicles,
8157
self.get_scenario().net.edges,
8158
name='HC PRT trip results',
8159
info='Table with simulation results for each PRT vehicle. The results refer to the vehicle journey over the entire simulation period.',
8160
)
8161
results.add_resultobj(tripresults, groupnames=['Trip results'])
8162
8163
prtstopresults = HcPrtStopResults('hcprtstopresults', results, self.prtstops)
8164
results.add_resultobj(prtstopresults, groupnames=['HCPRT stop results'])
8165
8166
# def get_results(self):
8167
# return self._results
8168
8169
def process_results(self, results, process=None):
8170
pass
8171
8172
8173
class HcPrtStopResults(am.ArrayObjman):
8174
def __init__(self, ident, results, prtstops,
8175
name='HC PRT Stop results',
8176
info='Table with simulation results of PRT platoon stops generated from vehicle management.',
8177
**kwargs):
8178
8179
self._init_objman(ident=ident,
8180
parent=results, # main results object
8181
info=info,
8182
name=name,
8183
**kwargs)
8184
8185
self.add(cm.AttrConf('time_step', 5.0,
8186
groupnames=['parameters'],
8187
name='Step time',
8188
info="Time of one recording step.",
8189
unit='s',
8190
))
8191
8192
self.add(cm.ObjConf(prtstops, is_child=False, # groupnames = ['_private']
8193
))
8194
8195
self.add_col(am.IdsArrayConf('ids_stop', prtstops,
8196
groupnames=['state'],
8197
is_index=True,
8198
name='PRT stop ID',
8199
info='ID of PRT stop.',
8200
))
8201
8202
attrinfos = [
8203
('inflows_veh', {'name': 'Vehicle in-flows', 'unit': '1/s',
8204
'dtype': np.float32, 'info': 'Vehicle flow into the stop over time.'}),
8205
('inflows_veh_sched', {'name': 'Sched. vehicle in-flows', 'unit': '1/s',
8206
'dtype': np.float32, 'info': 'Scheduled vehicle flow into the stop over time.'}),
8207
('inflows_person', {'name': 'Person in-flows', 'unit': '1/s',
8208
'dtype': np.float32, 'info': 'Person flow into the stop over time.'}),
8209
('numbers_person_wait', {'name': 'waiting person', 'dtype': np.int32,
8210
'info': 'Number of waiting persons at stop over time.'}),
8211
('waittimes_tot', {'name': 'total wait time', 'dtype': np.float32,
8212
'info': 'Wait times of all waiting persons at a stop over time.'}),
8213
]
8214
8215
for attrname, kwargs in attrinfos:
8216
self.add_resultattr(attrname, **kwargs)
8217
8218
def get_dimensions(self):
8219
return len(self), len(self.inflows_veh.get_default())
8220
8221
def get_prtstops(self):
8222
return self.prtstops.get_value()
8223
# return self.ids_stop.get_linktab()
8224
8225
def init_recording(self, n_timesteps, time_step):
8226
print 'HC init_recording n_timesteps, time_step', n_timesteps, time_step, len(self.ids_stop.get_linktab().get_ids())
8227
print ' stops instance', self.prtstops.get_value(), self.ids_stop.get_linktab(), id(self.prtstops.get_value()), id(self.ids_stop.get_linktab())
8228
self.clear()
8229
8230
self.time_step.set_value(time_step)
8231
8232
for attrconfig in self.get_stopresultattrconfigs():
8233
# print ' reset attrconfig',attrconfig.attrname
8234
attrconfig.set_default(np.zeros(n_timesteps, dtype=attrconfig.get_dtype()))
8235
attrconfig.reset()
8236
# print ' default=',attrconfig.get_default(),attrconfig.get_default().dtype
8237
ids_stop = self.get_prtstops().get_ids()
8238
# print ' ids_stop',ids_stop
8239
self.add_rows(n=len(ids_stop), ids_stop=ids_stop)
8240
8241
def record(self, timestep, ids, **kwargs):
8242
8243
inds = self.ids_stop.get_linktab().get_inds(ids)
8244
timestep_int = int(timestep)
8245
for attrname, values in kwargs.iteritems():
8246
print ' record', attrname, 'dtype', values.dtype, values.shape, 'array', getattr(self, attrname).get_value().dtype, 'shape', getattr(self, attrname).get_value().shape
8247
# print ' inds',type(inds),inds.dtype,
8248
getattr(self, attrname).get_value()[inds, timestep_int] = values
8249
8250
def get_stopresultattrconfigs(self):
8251
return self.get_attrsman().get_group_attrs('PRT results').values()
8252
8253
def get_persons(self):
8254
return self.ids_person.get_linktab()
8255
8256
def add_resultattr(self, attrname, **kwargs):
8257
self.add_col(am.ArrayConf(attrname, 0, groupnames=['PRT results', 'results'], **kwargs))
8258
8259
def import_xml(self, sumo, datapaths):
8260
# no imports, data come from prtservice
8261
pass
8262
8263