Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/contributed/sumopy/plugins/prt/prt.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 prt.py
16
# @author Joerg Schweizer
17
# @date 2012
18
19
"""
20
This plugin provides methods to run and analyze PRT networks.
21
22
23
"""
24
import os
25
import sys
26
import numpy as np
27
import random
28
from agilepy.lib_base.processes import Process
29
#from xml.sax import saxutils, parse, handler
30
from collections import OrderedDict
31
32
33
from coremodules.modules_common import *
34
import agilepy.lib_base.classman as cm
35
import agilepy.lib_base.arrayman as am
36
import agilepy.lib_base.xmlman as xm
37
#from agilepy.lib_base.misc import get_inversemap
38
#from agilepy.lib_base.geometry import find_area
39
#from agilepy.lib_base.processes import Process,CmlMixin,ff,call
40
from coremodules.network.network import SumoIdsConf
41
from coremodules.network.routing import edgedijkstra, get_mincostroute_edge2edge
42
from coremodules.simulation import sumo
43
from coremodules.simulation.sumo import traci
44
#from coremodules.network import routing
45
from coremodules.demand.demandbase import DemandobjMixin
46
from coremodules.simulation.simulationbase import SimobjMixin
47
48
from coremodules.demand.virtualpop import StageTypeMixin, StrategyMixin
49
from coremodules.simulation import results as res
50
51
#from demo import TraciDemo
52
53
BERTHSTATES = {'free': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3}
54
VEHICLESTATES = {'init': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3,
55
'emptytrip': 4, 'occupiedtrip': 5, 'forewarding': 6, 'await_forwarding': 7}
56
LEADVEHICLESTATES = [VEHICLESTATES['boarding'], VEHICLESTATES['waiting'],
57
VEHICLESTATES['emptytrip'], VEHICLESTATES['occupiedtrip']]
58
STOPTYPES = {'person': 0, 'freight': 1, 'depot': 2, 'group': 3, 'mixed': 4}
59
60
get_traci_odo = traci.vehicle.getDistance
61
get_traci_velocity = traci.vehicle.getSpeed
62
get_traci_route_all = traci.vehicle.getRoute
63
get_traci_routeindex = traci.vehicle.getRouteIndex
64
get_traci_distance = traci.vehicle.getDrivingDistance
65
66
67
def get_traci_route(id_veh_sumo):
68
return get_traci_route_all(id_veh_sumo)[get_traci_routeindex(id_veh_sumo):]
69
70
71
def get_entered_vehs(ids_veh_sumo_current, ids_veh_sumo_before):
72
ids_veh_entered_sumo = np.array(list(ids_veh_sumo_current.difference(ids_veh_sumo_before)), dtype=np.object)
73
n_entered = len(ids_veh_entered_sumo)
74
positions = np.zeros(n_entered, dtype=np.float32)
75
for i, id_veh_sumo in zip(xrange(n_entered), ids_veh_entered_sumo):
76
positions[i] = traci.vehicle.getLanePosition(id_veh_sumo)
77
78
return list(ids_veh_entered_sumo[positions.argsort()])[::-1]
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
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 0:
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
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_sumo = get_entered_vehs(ids_veh_sumo, ids_veh_detect_sumo)
601
ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)
602
603
if 0:
604
print ' ids_veh_entered', ids_veh_entered, type(ids_veh_entered)
605
# print ' poss',poss
606
print ' ids_veh_entered_sumo', ids_veh_entered_sumo
607
print ' ids_leader', vehicles.ids_leader[ids_veh_entered]
608
print ' ids_follower', vehicles.ids_follower[ids_veh_entered]
609
print ' lengths_plat', vehicles.lengths_plat[ids_veh_entered]
610
611
for id_veh_entered, id_veh_entered_sumo, id_leader, length_plat\
612
in zip(ids_veh_entered, ids_veh_entered_sumo,
613
vehicles.ids_leader[ids_veh_entered],
614
vehicles.lengths_plat[ids_veh_entered]):
615
616
# we cannot deconcatenate here, vehicles are in movement
617
# instead, measure if there is enough room for the platoon
618
# otherwise send platoon through bypass
619
if (length_plat > 0.001) & (id_leader == -1):
620
# vehicle is a platoon leader:
621
# find a queue that fits the platoon
622
id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]
623
# print ' dispatch id_veh_entered_sumo %s with target %s'%(id_veh_entered_sumo,id_targetedge_sumo)
624
625
is_found_queue = False
626
costs = np.zeros(n_queues, dtype=np.float32)
627
for ind_queue, queue, is_avail, capa in zip(range(n_queues), queues, are_queue_avail, capacities):
628
629
dl = (capa - len(queue)) * self.length_veh - 2*length_plat
630
# print ' ceck queue %d with capa %d, len = %d, dl=%d'%(ind_queue,capa,len(queue),dl)
631
if (dl > 0) & is_avail:
632
costs[ind_queue] = dl
633
else:
634
costs[ind_queue] = np.inf
635
636
ind_queue = np.argmin(costs)
637
# print ' ind_queue,costs',ind_queue,costs
638
# if costs[ind_queue] <10000:# OK queue has been found
639
#ind_queue = ids_edge_sumo_target.index(id_targetedge_sumo)
640
#ind_queue = inds_queue[0]
641
queue = queues[ind_queue]
642
capa_queue = capacities[ind_queue]
643
len_queue = len(queue)
644
# print ' found ind_queue,len_queue,capa_queue',ind_queue,len_queue,capa_queue
645
# if len_queue < capa_queue:
646
self._alloc_queue(queue, queues_alloc[ind_queue],
647
ids_targetedges_sumo[ind_queue],
648
capa_queue,
649
id_veh_entered,
650
id_veh_entered_sumo,
651
id_targetedge_sumo,
652
ids_shuntedge[ind_queue],
653
ids_shuntedge_sumo[ind_queue],
654
vehicles, edges)
655
656
elif (id_leader > -1):
657
# this is a follower:
658
# shunt it to the same edge as its leader
659
id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]
660
id_platoonleader = vehicles.get_platoonleader(id_leader)
661
for ind_queue, queue, capa_queue, in zip(range(n_queues), queues, capacities):
662
if id_platoonleader in queue:
663
# print ' found id_platoonleader prt.%d of prt.%d at queue %d'%(id_platoonleader,id_veh_entered,ind_queue)
664
self._alloc_queue_follower(
665
queue, queues_alloc[ind_queue],
666
ids_targetedges_sumo[ind_queue],
667
capa_queue,
668
id_veh_entered,
669
id_veh_entered_sumo,
670
id_targetedge_sumo,
671
ids_shuntedge_sumo[ind_queue],
672
vehicles)
673
break
674
else:
675
# individual vehicle
676
pass
677
678
# update veh on detector edge
679
self.ids_vehs_detect_sumo[id_comp] = ids_veh_sumo
680
681
# (simtime - self.releasetimes[id_comp]> self.time_release_min.get_value()): # do this later ...simtime - self.releasetimes[id_comp]> 10:
682
if 1:
683
# now check if any of the vehicle in any of the queues has arrived
684
# and if a queue is complete, create a platoon, send it off and
685
# reset the queue
686
# print ' Deal with queues...'
687
is_released = False
688
for ind_queue, queue, queue_alloc,\
689
ids_targetedge_sumo, capacity,\
690
id_shuntedge_sumo, releasetime_queue\
691
in zip(
692
range(n_queues), queues, queues_alloc,
693
ids_targetedges_sumo, capacities,
694
edges.ids_sumo[ids_shuntedge], releasetime_queues):
695
if 0:
696
print ' QQQQQQQQQQQ shunt %s ' % (id_shuntedge_sumo)
697
print ' simtime-releasetime_queue', simtime-releasetime_queue, (simtime - releasetime_queue > self.time_accumulation_max.get_value()), (simtime - self.releasetimes[id_comp] > 10)
698
print ' queue', queue, id(queue)
699
print ' ids_targetedge_sumo', ids_targetedge_sumo
700
print ' queue_alloc', queue_alloc
701
print ' releasetime_queue', releasetime_queue, simtime - releasetime_queue, simtime - releasetime_queue > self.time_accumulation_max.get_value()
702
# here we could also test timeout conditions
703
if (simtime - self.releasetimes[id_comp] > self.time_release_min.get_value()) & (simtime - releasetime_queue > self.time_accumulation_max.get_value()):
704
# if (simtime - self.releasetimes[id_comp]> self.time_release_min.get_value()):
705
706
# check if allocated arrived
707
id_veh_arrived = -1
708
# for id_vehinfo,id_veh_sumo, length_plat in zip(range(),queue_alloc, vehicles.ids_sumo[queue_alloc],vehicles.lengths_plat[queue_alloc]):
709
710
for id_veh in queue_alloc:
711
if vehicles.reached_stop_sumo(vehicles.ids_sumo[id_veh]):
712
id_veh_arrived = id_veh
713
break
714
715
# print ' allocated prt.%d reached stop (-1 means no vehicle)'%(id_veh_arrived)
716
717
if id_veh_arrived > -1:
718
# a platoon leader id_veh_arrived has arrived
719
720
# print ' check if entire platoon arrived at the queue'
721
length_plat = vehicles.lengths_plat[id_veh_arrived]
722
ind_pl = queue.index(id_veh_arrived)
723
len_queue = len(queue)
724
ids_platoon = []
725
#ids_targetedge_plat_sumo= []
726
727
if len_queue > ind_pl+1:
728
729
for i, id_veh in zip(range(ind_pl+1, len_queue), queue[ind_pl+1:]):
730
# print ' check prt.%d with leader prt.%d'%(id_veh,vehicles.ids_leader[id_veh])
731
if vehicles.ids_leader[id_veh] != -1:
732
# 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)
733
# if vehicles.ids_leader[id_veh] == queue[i-1]:
734
# print ' add'
735
# ids_platoon.append(id_veh)
736
#
737
if vehicles.get_platoonleader(id_veh) == id_veh_arrived:
738
# TODO: this is very inefficient, by happens
739
# when platoon has ben broken up during a merge operation
740
# idea: use a pointer to follower
741
ids_platoon.append(id_veh)
742
# ids_targetedge_plat_sumo.append(id_targetedge_sumo)
743
# print ' add'
744
else:
745
# is not a follower
746
pass
747
length_plat_arrived = len(ids_platoon)*self.length_veh + 0.5
748
# print ' arrived id_veh_arrived prt.%d at queue pos ind_pl=%d (should be 0)'%(id_veh_arrived,ind_pl)
749
# print ' with platoon length %.2fm > %.2fm?'%(length_plat_arrived,length_plat),(length_plat_arrived >= length_plat)& (not is_released),'is_released',is_released
750
751
if (length_plat_arrived >= length_plat) & (not is_released):
752
# print ' entire platoon length in queue, now release...',ids_platoon
753
is_released = True
754
# reschedule leader
755
756
vehicles.reschedule_trip(id_veh_arrived, ids_targetedge_sumo[id_veh_arrived])
757
id_veh_sumo = vehicles.get_id_sumo(id_veh_arrived)
758
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
759
#vehicles.control_slow_down( id_veh_arrived, speed = 6.0/3.6)
760
# print ' queue_alloc',queue_alloc
761
# print ' queue',queue
762
# deconcatenate and reschedule followers
763
for id_veh, id_veh_sumo in zip(ids_platoon[::-1], vehicles.ids_sumo[ids_platoon[::-1]]):
764
vehicles.decatenate(id_veh)
765
vehicles.reschedule_trip_sumo(id_veh_sumo, ids_targetedge_sumo[id_veh])
766
#vehicles.control_slow_down( id_veh, speed = 6.0/3.6)
767
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
768
queue.remove(id_veh)
769
del ids_targetedge_sumo[id_veh]
770
771
releasetime_queues[ind_queue] = int(simtime)
772
self.releasetimes[id_comp] = int(simtime)
773
774
# remove platoon leader
775
queue_alloc.remove(id_veh_arrived)
776
queue.remove(id_veh_arrived)
777
del ids_targetedge_sumo[id_veh_arrived]
778
779
else:
780
# print ' platoon incomplete'
781
pass
782
else:
783
# print ' no leaders arrived in this quque'
784
pass
785
786
def _alloc_queue(self, queue, queue_alloc, ids_targetedge_sumo, capa_queue,
787
id_veh, id_veh_sumo, id_targetedge_sumo,
788
id_shuntedge, id_shuntedge_sumo, vehicles, edges):
789
"""Queue allocation for platoon leader only."""
790
queue.append(id_veh)
791
792
# store here also the target necessary to reprogram
793
queue_alloc.append(id_veh)
794
# TODO: idea, the original target should be stored in the vehicles db
795
ids_targetedge_sumo[id_veh] = id_targetedge_sumo
796
len_queue = len(queue)
797
798
# make platoon leder always stop at the foremost position
799
pos_stop = 1.0 + capa_queue*(self.length_veh)
800
# print '_alloc_queue',id_veh_sumo,id_shuntedge_sumo,capa_queue-len_queue,pos_stop
801
vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)
802
vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex=0)
803
804
# Forced exit of vehicle from merge conrol
805
self.parent.mergenodes.exit_veh_forced(id_veh, id_veh_sumo, vehicles)
806
807
def _alloc_queue_follower(self, queue, queue_alloc, ids_targetedge_sumo,
808
capa_queue,
809
id_veh, id_veh_sumo, id_targetedge_sumo,
810
id_shuntedge_sumo, vehicles):
811
"""Queue allocation for follower only."""
812
queue.append(id_veh)
813
# TODO: idea, the original target should be stored in the vehicles db
814
ids_targetedge_sumo[id_veh] = id_targetedge_sumo
815
# queue_alloc.append(id_veh)
816
#len_queue = len(queue)
817
818
# make platoon leder always stop at the foremost position
819
#pos_stop = 1.0 + capa_queue*(self.length_veh + 0.5)
820
# print '_alloc_queue_follower',id_veh_sumo,id_shuntedge_sumo,id_targetedge_sumo
821
vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)
822
#vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex = 0)
823
824
825
# class Shortmergenodes(Mergenodes):
826
827
class Mergenodes(am.ArrayObjman):
828
def __init__(self, ident, prtservices, **kwargs):
829
self._init_objman(ident=ident,
830
parent=prtservices,
831
name='Merge nodes',
832
info='Contains information and methods for merging the flow of two vehicle streams, including platoons.',
833
version=0.2,
834
**kwargs)
835
self._init_attributes()
836
837
def _init_attributes(self):
838
#self.add(cm.ObjConf(PrtBerths('berths',self)) )
839
840
self.add(cm.AttrConf('time_update', 0.5,
841
groupnames=['parameters'],
842
name='Update time',
843
info="Update time for merges.",
844
unit='s',
845
))
846
847
net = self.get_scenario().net
848
849
self.add_col(am.IdsArrayConf('ids_node', net.nodes,
850
name='Node ID',
851
info='Network node ID.',
852
is_index=True,
853
))
854
855
# self.add_col(am.IdsArrayConf('ids_edge_in1', net.edges,
856
# name = 'ID edge 1',
857
# info = 'ID of edge at entrance 1.',
858
# ))
859
if self.get_version() < 0.2:
860
self.delete('ids_mergenode_in1')
861
self.delete('ids_mergenode_in2')
862
self.delete('ids_mergenodes_out')
863
self.delete('distances_mergenode_in1')
864
self.delete('distances_mergenode_in2')
865
866
self.add_col(am.IdsArrayConf('ids_node_in1', net.nodes,
867
name='ID node in 1',
868
info='ID of upstream network node at incoming line 1.',
869
))
870
871
self.add_col(am.ArrayConf('distances_node_in1', 0.0,
872
groupnames=['parameters'],
873
name='Distance node in 1',
874
info="Distance to network node at incoming line 1.",
875
unit='m',
876
))
877
878
# self.add_col(am.IdsArrayConf('ids_edge2', net.edges,
879
# name = 'ID edge 2',
880
# info = 'ID of edge at entrance 2.',
881
# ))
882
883
self.add_col(am.IdsArrayConf('ids_node_in2', net.nodes,
884
name='ID node in 2',
885
info='ID of upstream network node at incoming line 2.',
886
))
887
888
self.add_col(am.ArrayConf('distances_node_in2', 0.0,
889
groupnames=['parameters'],
890
name='Distance mergenode in 2',
891
info="Distance to upstream network node at incoming line 2.",
892
unit='m',
893
))
894
895
self.add_col(am.IdlistsArrayConf('ids_nodes_out', net.nodes,
896
name='IDs nodes out',
897
info='IDs of downstream network nodes.',
898
))
899
900
self.add_col(am.ArrayConf('are_station', default=False,
901
groupnames=['parameters'],
902
name='is station',
903
info="Node is the exit node of a station, comressor or decompressor. The incoming edge of this are internal and are not considered.",
904
))
905
906
self.add_col(am.ArrayConf('are_entry', default=False,
907
groupnames=['parameters'],
908
name='is entry',
909
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.",
910
))
911
912
self.set_version(0.2)
913
914
def _init_constants(self):
915
self.do_not_save_attrs([
916
'ids_merge_to_ids_node_sumo', 'ids_merge_to_ids_edge_out_sumo',
917
'ids_node_to_ids_merge', 'ids_vehs_out_sumo,'
918
'ids_vehs_in1', 'ids_vehs_in1_sumo',
919
'ids_vehs_in2', 'ids_vehs_in2_sumo',
920
'ids_vehs_merged', 'ids_vehs_merged_sumo',
921
'lineinds_vehs_merged', 'vehicle_to_merge',
922
'vehicles_entries', 'vehicles_mains',
923
])
924
925
def make_from_net(self):
926
"""
927
Make merge node database from network.
928
"""
929
print 'Mergenodes.make_from_net'
930
self.clear()
931
id_prtmode = self.parent.id_prtmode
932
933
net = self.get_scenario().net
934
nodes = net.nodes
935
edges = net.edges
936
lanes = net.lanes
937
id_zippertype = nodes.types.choices['zipper']
938
939
compressors = self.parent.compressors
940
decompressors = self.parent.decompressors
941
ids_detectoredges = set(compressors.ids_detectoredge.get_value())
942
ids_detectoredges.update(decompressors.ids_detectoredge.get_value())
943
944
ids_shuntedges = set()
945
ids_mainlinedges = set()
946
947
ids = compressors.get_ids()
948
for id_unit, ids_edge in zip(ids, compressors.ids_shuntedges[ids]):
949
# put in all shunts except for the bypass
950
print ' bypass of compressor', id_unit, '=', ids_edge[0]
951
ids_mainlinedges.add(ids_edge[0])
952
print ' update ids_shuntedges with compressors', ids_edge[1:]
953
ids_shuntedges.update(ids_edge[1:])
954
955
# collect decompressornodes, wich will not become entry merges
956
ids = decompressors.get_ids()
957
ids_node_decompressorout = []
958
for id_unit, ids_edge in zip(ids, decompressors.ids_shuntedges[ids]):
959
# put in all shunts except for the bypass
960
print ' bypass of decompressor', id_unit, '=', ids_edge[0], 'id_tonode', edges.ids_tonode[ids_edge[0]]
961
ids_mainlinedges.add(ids_edge[0])
962
ids_node_decompressorout.append(edges.ids_tonode[ids_edge[0]])
963
print ' update ids_shuntedges with decompressors', ids_edge[1:]
964
ids_shuntedges.update(ids_edge[1:])
965
print ' ids_node_decompressorout', ids_node_decompressorout
966
ids_node_compressorout = edges.ids_tonode[list(ids_mainlinedges)]
967
ids_mainlinefromnodes = edges.ids_fromnode[list(ids_mainlinedges)]
968
969
# now put also all incoming edges of main lines as shunts
970
# in order to cut of compressor entrance from downstrem search
971
# for id_edge in ids_mainlinedges:
972
# print ' update ids_shuntedges with mainline incoming',edges.get_incoming(id_edge)
973
# ids_shuntedges.update(edges.get_incoming(id_edge))
974
975
print ' ids_shuntedges', ids_shuntedges
976
#ids_ptstop = ptstops.get_ids()
977
#id_mode_prt = self.parent.id_prtmode
978
979
#ids_edges = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]
980
#ids_lanes = net.edges.ids_lanes[ids_edges]
981
#ids_lane = ptstops.ids_lane[ids_ptstop]
982
#edgelengths = net.edges.lengths
983
984
ids_node = nodes.get_ids()
985
print ' ids_node', ids_node
986
for id_node, ids_edge_from, ids_edge_to, id_type in zip(
987
ids_node,
988
nodes.ids_incoming[ids_node],
989
nodes.ids_outgoing[ids_node],
990
nodes.types[ids_node],
991
):
992
993
if True:
994
#
995
996
print 60*'-'
997
print ' check node', id_node, nodes.ids_sumo[id_node], id_type, id_zippertype == id_type
998
999
# id merge to be created, for debugging
1000
id_merge = -1
1001
1002
if (ids_edge_from is None):
1003
print ' WARNING: isolate node: ids_edge_from,ids_edge_to', ids_edge_from, ids_edge_to
1004
pass
1005
1006
elif (len(ids_edge_from) == 2) & (len(ids_edge_to) == 1):
1007
1008
# ids_mainlinedges.add(ids_edge[0])
1009
# ids_shuntedges.update(ids_edge[1:])
1010
1011
# check accesslevels
1012
id_edge1, id_edge2 = ids_edge_from
1013
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_from]
1014
print ' id_edge1', id_edge1, 'ids_lane1', ids_lane1, self.is_prt_only(ids_lane1, lanes)
1015
print ' id_edge2', id_edge2, 'ids_lane2', ids_lane2, self.is_prt_only(ids_lane2, lanes)
1016
if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
1017
print ' +PRT merge with 2 PRT lines entering'
1018
1019
if id_type != id_zippertype:
1020
print 'WARNING: PRT network node %d %s is NOT in zipper mode!' % (id_node, nodes.ids_sumo[id_node])
1021
1022
if not ids_shuntedges.isdisjoint(ids_edge_from):
1023
print ' one incoming edge is a shunt edge. Detect last shunt node.'
1024
1025
# TODO: this should be a function of the compressor class
1026
id_tonode_out = edges.ids_tonode[ids_edge_to[0]]
1027
if id_tonode_out in ids_node_compressorout:
1028
print ' output node of compressor => station merge node with output node', id_tonode_out
1029
# model this node as a platform end node of a station
1030
id_merge = self.add_row(ids_node=id_node,
1031
ids_nodes_out=[id_tonode_out],
1032
are_station=True,
1033
)
1034
else:
1035
print ' compressor internal node'
1036
pass
1037
1038
# elif not ids_mainlinedges.isdisjoint(ids_edge_from):
1039
# print ' one incoming line is the bypass'
1040
# ids_node_out = self.search_downstream_merges(ids_edge_to[0], edges, lanes, id_prtmode)
1041
#
1042
# # model this node as a station output
1043
# self.add_row( ids_node = id_node,
1044
# ids_nodes_out = ids_node_out,
1045
# are_station = True,
1046
# )
1047
1048
else:
1049
print ' regular merge'
1050
id_node_up1, dist1 = self.search_upstream_merge(id_edge1, edges, lanes, id_prtmode)
1051
id_node_up2, dist2 = self.search_upstream_merge(id_edge2, edges, lanes, id_prtmode)
1052
1053
ids_node_out = self.search_downstream_merges(
1054
ids_edge_to[0], edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)
1055
id_merge = self.add_row(ids_node=id_node,
1056
ids_node_in1=id_node_up1,
1057
distances_node_in1=dist1,
1058
ids_node_in2=id_node_up2,
1059
distances_node_in2=dist2,
1060
ids_nodes_out=ids_node_out,
1061
are_station=False,
1062
)
1063
1064
elif (len(ids_edge_from) == 1) & (len(ids_edge_to) == 2):
1065
1066
id_edge_from = ids_edge_from[0]
1067
ids_lane_in = edges.ids_lanes[id_edge_from]
1068
#al_in = lanes.get_accesslevel(edges.ids_lanes[id_edge_from], id_prtmode)
1069
#is_prt_in = lanes.ids_modes_allow[edges.ids_lanes[id_edge_from]] == id_prtmode
1070
is_prt_in = self.is_prt_only(ids_lane_in, lanes)
1071
print ' one in, 2 out => diverge node, access is_prt_in', is_prt_in, 'is_platform_in', self.is_platform(ids_lane_in, lanes)
1072
1073
# if id_edge_from in ids_detectoredges:
1074
# print ' fromnode is a detectoredge of a compressor'
1075
# id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1076
# self.add_row( ids_node = id_node,
1077
# ids_node_in1 = id_node_up,
1078
# distances_node_in1 = dist,
1079
# #ids_nodes_out = ids_node_out,
1080
# are_station = True,
1081
# )
1082
1083
# check if node is outgoing node at a station
1084
if 0: # no longer considered
1085
if is_prt_in & (id_node in ids_mainlinefromnodes):
1086
print ' Diverge node in front of a compressor/decompressorr.'
1087
id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1088
1089
id_edge1, id_edge2 = ids_edge_to
1090
if id_edge1 in ids_mainlinedges:
1091
id_edge = id_edge1
1092
else:
1093
id_edge = id_edge2
1094
1095
#ids_node_out = self.search_downstream_merges(id_edge, edges, lanes, id_prtmode, ids_sinkedge = ids_shuntedges)
1096
ids_node_out = [edges.ids_tonode[id_edge]]
1097
self.add_row(ids_node=id_node,
1098
ids_node_in1=id_node_up,
1099
distances_node_in1=dist,
1100
ids_nodes_out=ids_node_out,
1101
are_station=True,
1102
)
1103
1104
if self.is_platform(ids_lane_in, lanes):
1105
print ' mixed access level of incoming edge, check for platform exit node'
1106
1107
id_edge1, id_edge2 = ids_edge_to
1108
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_to]
1109
1110
# here we could also decide on the number of lanes
1111
# but this may not be robust in the future
1112
print ' out id_edge1', id_edge1, 'ids_lane1', ids_lane1, 'is_prt_only', self.is_prt_only(ids_lane1, lanes)
1113
print ' out id_edge2', id_edge2, 'ids_lane2', ids_lane2, 'is_prt_only', self.is_prt_only(ids_lane2, lanes)
1114
# if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
1115
if self.is_prt_only(ids_lane2, lanes):
1116
1117
print ' Ped exit on outedge 1'
1118
#id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1119
ids_node_out = self.search_downstream_merges(
1120
id_edge2, edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)
1121
id_merge = self.add_row(ids_node=id_node,
1122
#ids_node_in1 = id_node_up,
1123
#distances_node_in1 = dist,
1124
ids_nodes_out=ids_node_out,
1125
are_station=True,
1126
)
1127
1128
elif self.is_prt_only(ids_lane1, lanes):
1129
print ' Ped exit on outedge 2'
1130
#id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)
1131
ids_node_out = self.search_downstream_merges(
1132
id_edge1, edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)
1133
id_merge = self.add_row(ids_node=id_node,
1134
#ids_node_in1 = id_node_up,
1135
#distances_node_in1 = dist,
1136
ids_nodes_out=ids_node_out,
1137
are_station=True,
1138
)
1139
1140
if id_merge >= 0:
1141
self.print_attrs(ids=[id_merge, ])
1142
1143
# now check if merge has entry line form stations or compressors'#,self.ids_node._index_to_id
1144
ids = self.get_ids()
1145
i = 0
1146
while i < len(ids):
1147
id_merge = ids[i]
1148
1149
id_node_in1 = self.ids_node_in1[id_merge]
1150
id_node_in2 = self.ids_node_in2[id_merge]
1151
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
1152
if (id_node_in1 > -1) & (id_node_in2 > -1)\
1153
& (self.ids_node[id_merge] not in ids_node_decompressorout):
1154
1155
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])
1156
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])
1157
if 1:
1158
id_merge_in1 = self.ids_node.get_id_from_index(self.ids_node_in1[id_merge])
1159
id_merge_in2 = self.ids_node.get_id_from_index(self.ids_node_in2[id_merge])
1160
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]
1161
1162
if self.are_station[id_merge_in2]:
1163
self.are_entry[id_merge] = True
1164
# in line 2 is already entry line
1165
pass
1166
1167
elif self.are_station[id_merge_in1]:
1168
self.are_entry[id_merge] = True
1169
# move entry line from inline 1 to inline 2
1170
1171
id_node_in2 = self.ids_node_in2[id_merge]
1172
dist2 = self.distances_node_in2[id_merge]
1173
1174
self.ids_node_in2[id_merge] = self.ids_node_in1[id_merge]
1175
self.distances_node_in2[id_merge] = self.distances_node_in1[id_merge]
1176
1177
self.ids_node_in1[id_merge] = id_node_in2
1178
self.distances_node_in1[id_merge] = dist2
1179
1180
i += 1
1181
1182
def get_scenario(self):
1183
return self.parent.get_scenario()
1184
1185
def prepare_sim(self, process):
1186
print 'Mergenodes.prepare_sim'
1187
net = self.get_scenario().net
1188
nodes = net.nodes
1189
edges = net.edges
1190
lanes = net.lanes
1191
ids_edge_sumo = edges.ids_sumo
1192
1193
id_prtmode = self.parent.id_prtmode
1194
self.decel = self.parent.prtvehicles.decel_emergency
1195
1196
ids = self.get_ids()
1197
if len(ids) == 0:
1198
return []
1199
n_id_max = np.max(ids)+1
1200
1201
# database with vehicle id as key and controlling merge as value
1202
self.vehicle_to_merge = {}
1203
1204
# vehicle database for merge operation
1205
self.vehicles_entries = {}
1206
self.vehicles_mains = {}
1207
1208
#self.ids_merge_to_ids_node_sumo = np.zeros(n_id_max,dtype = np.object)
1209
#self.ids_merge_to_ids_node_sumo[ids] = nodes.ids_sumo[self.ids_node[ids]]
1210
1211
self.ids_merge_to_ids_edge_out_sumo = np.zeros(n_id_max, dtype=np.object)
1212
#self.ids_node_to_ids_edge_out_sumo = np.zeros(n_id_max,dtype = np.object)
1213
self.ids_node_to_ids_merge = np.zeros(np.max(self.ids_node[ids])+1, dtype=np.int32)
1214
self.ids_node_to_ids_merge[self.ids_node[ids]] = ids
1215
1216
# this queue contains all vehicles on the outgoing edge
1217
# it is used to identify whether a new vehicle has left the merge
1218
self.ids_vehs_out_sumo = np.zeros(n_id_max, dtype=np.object)
1219
1220
# this queue contains all vehicles on line 1 between
1221
# merge and id_node_in1
1222
self.ids_vehs_in1 = np.zeros(n_id_max, dtype=np.object)
1223
self.ids_vehs_in1_sumo = np.zeros(n_id_max, dtype=np.object)
1224
1225
# this queue contains all vehicles on line 2 between
1226
# merge and id_node_in2
1227
self.ids_vehs_in2 = np.zeros(n_id_max, dtype=np.object)
1228
self.ids_vehs_in2_sumo = np.zeros(n_id_max, dtype=np.object)
1229
1230
# this queue contains the merged vehicles for the controlled range
1231
self.ids_vehs_merged = np.zeros(n_id_max, dtype=np.object)
1232
self.ids_vehs_merged_sumo = np.zeros(n_id_max, dtype=np.object)
1233
1234
# this queuse contains the line index (1 or 2, 0= not assigned)
1235
self.lineinds_vehs_merged = np.zeros(n_id_max, dtype=np.object)
1236
1237
#self.ids_merge_to_ids_edge_out_sumo[ids] = edges.ids_sumo[self.ids_node[ids]]
1238
ids_node = self.ids_node[ids]
1239
for id_merge, id_node, ids_edge_out in zip(ids, ids_node, nodes.ids_outgoing[ids_node]):
1240
if len(ids_edge_out) == 1:
1241
# regular merge
1242
self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[ids_edge_out[0]]
1243
1244
elif len(ids_edge_out) == 2:
1245
# one edge is PRT, the other ped access
1246
# check accesslevels
1247
id_edge1, id_edge2 = ids_edge_out
1248
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_out]
1249
al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)
1250
al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)
1251
if al1 == 2:
1252
self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge1]
1253
#self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge1]
1254
if al2 == 2:
1255
self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge2]
1256
#self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge2]
1257
1258
self.ids_vehs_out_sumo[id_merge] = set()
1259
1260
self.ids_vehs_in1[id_merge] = list()
1261
self.ids_vehs_in1_sumo[id_merge] = list()
1262
self.ids_vehs_in2[id_merge] = list()
1263
self.ids_vehs_in2_sumo[id_merge] = list()
1264
1265
self.ids_vehs_merged[id_merge] = list()
1266
self.ids_vehs_merged_sumo[id_merge] = list()
1267
self.lineinds_vehs_merged[id_merge] = list()
1268
1269
self.vehicles_entries[id_merge] = OrderedDict()
1270
self.vehicles_mains[id_merge] = OrderedDict()
1271
1272
return [(self.time_update.get_value(), self.process_step),
1273
]
1274
1275
def process_step(self, process):
1276
simtime = process.simtime
1277
print 79*'_'
1278
print 'Mergenodes.process_step at', simtime
1279
net = self.get_scenario().net
1280
vehicles = self.parent.prtvehicles
1281
ids = self.get_ids()
1282
for id_merge, id_node, id_edge_out, ids_node_out, ids_veh_out_sumo, is_entry in\
1283
zip(ids,
1284
self.ids_node[ids],
1285
self.ids_merge_to_ids_edge_out_sumo[ids],
1286
self.ids_nodes_out[ids],
1287
self.ids_vehs_out_sumo[ids],
1288
self.are_entry[ids],
1289
):
1290
print ' '+60*'.'
1291
print ' process id_merge', id_merge, ',id_node', id_node, net.nodes.ids_sumo[id_node]
1292
1293
####
1294
debug = 0 # id_merge in [3,4]
1295
# debug = (id_merge==1)|('gneJ1' in net.nodes.ids_sumo[ids_node_out])#'gneJ29':#'gneJ1':
1296
#debug = debug | (id_merge==17)| ('gneJ29' in net.nodes.ids_sumo[ids_node_out])
1297
###
1298
1299
if debug > 0:
1300
print ' ids_vehs_merged_sumo', self.ids_vehs_merged_sumo[id_merge]
1301
1302
# check for new vehicle arrivals/departures
1303
ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_out))
1304
1305
if debug:
1306
print ' ids_veh_sumo_prev=', ids_veh_out_sumo
1307
print ' ids_veh_sumo=', ids_veh_sumo
1308
1309
if ids_veh_out_sumo != ids_veh_sumo:
1310
1311
# attention, this is a list, not an array with numpy indexing
1312
#ids_veh_entered_sumo = list(ids_veh_sumo.difference(ids_veh_out_sumo))
1313
ids_veh_entered_sumo = get_entered_vehs(ids_veh_sumo, ids_veh_out_sumo)
1314
# this is an array
1315
ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)
1316
#ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo)))
1317
if debug > 0:
1318
print ' ids_veh_entered', ids_veh_entered, type(ids_veh_entered)
1319
# print ' ids_veh_entered_sumo',ids_veh_entered_sumo
1320
# print ' ids_leader',vehicles.ids_leader[ids_veh_entered]
1321
1322
if ids_node_out is None:
1323
# the present merge is an end node example at a station
1324
ids_merge_out = []
1325
else:
1326
# determine id merge according to given output node
1327
ids_merge_out = self.ids_node_to_ids_merge[ids_node_out]
1328
# if debug>0:
1329
# print ' ids_node_out',ids_node_out
1330
# print ' ids_merge_out',ids_merge_out
1331
ids_edge_mergeout_sumo = self.ids_merge_to_ids_edge_out_sumo[ids_merge_out]
1332
1333
# merge only vehicle without a leader (individual or first in a platoon)
1334
inds_entered = np.flatnonzero(vehicles.ids_leader[ids_veh_entered] == -1)
1335
1336
if len(inds_entered) > 0:
1337
for ind_entered, id_veh in zip(inds_entered, ids_veh_entered[inds_entered]):
1338
1339
id_veh_sumo = ids_veh_entered_sumo[ind_entered]
1340
if debug > 0:
1341
print ' >>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
1342
1343
# print ' route_sumo',route_sumo
1344
1345
if ids_node_out is not None:
1346
if debug > 0:
1347
print ' check which out mergenode are on the current route of the vehicle'
1348
1349
# exit from previous merge
1350
# if debug:
1351
# print ' vehicle',id_veh_sumo,'exits id_merge',id_merge
1352
self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles)
1353
1354
if len(ids_merge_out) > 0:
1355
1356
# inform the respectine merges
1357
# then communicate vehicle with dist to merge
1358
# attention, we need the first hit in the route
1359
# check which downstream merge to enter
1360
route_sumo = get_traci_route(id_veh_sumo)
1361
1362
routeinds = [INFINT]*len(ids_merge_out)
1363
# print ' ids_merge_out',ids_merge_out
1364
i = 0
1365
for id_edge_sumo in ids_edge_mergeout_sumo:
1366
1367
if id_edge_sumo in route_sumo:
1368
routeinds[i] = route_sumo.index(id_edge_sumo)
1369
i += 1
1370
1371
mergeind = np.argmin(routeinds)
1372
1373
if debug > 0:
1374
print ' route_sumo', route_sumo
1375
print ' routeinds', routeinds, 'downstream merge', routeinds[mergeind] < INFINT
1376
print ' ids_edge_mergeout_sumo', ids_edge_mergeout_sumo
1377
print ' mergeind,routeinds', mergeind, routeinds
1378
print ' ids_merge_out[mergeind]', ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind]
1379
1380
if routeinds[mergeind] < INFINT:
1381
if debug > 0:
1382
print ' merge %d is on the route is_entry' % (ids_merge_out[mergeind])
1383
if self.are_entry[ids_merge_out[mergeind]]:
1384
if debug > 0:
1385
print ' call enter_veh_entry'
1386
self.enter_veh_entry(
1387
id_veh, id_veh_sumo, id_merge, ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind], vehicles, debug=debug)
1388
else:
1389
if debug > 0:
1390
print ' call enter_veh'
1391
self.enter_veh(
1392
id_veh, id_veh_sumo, id_merge, ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind], vehicles, debug=debug)
1393
else:
1394
# no downstream merge, vehicle goes into a station
1395
pass
1396
else:
1397
# print ' ids_node_out is empty means that there is a station or compressor'
1398
pass
1399
1400
else:
1401
if debug:
1402
print ' ids_node_out is None means that there is a station or compressor'
1403
# shunt edges behind.
1404
# completely disconnect from all merge controlls
1405
# including ghosts
1406
1407
# exit from previous merge
1408
self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles)
1409
1410
# update vehicles on detection edge
1411
self.ids_vehs_out_sumo[id_merge] = ids_veh_sumo
1412
1413
# process special merge decisions and processes for entry merge types
1414
if is_entry:
1415
self.process_step_entry(id_merge, vehicles, debug)
1416
if 0:
1417
print '========check mergeprocess'
1418
for id_merge, id_node_sumo, ids_veh_merged_sumo, ids_veh_merged in\
1419
zip(ids,
1420
net.nodes.ids_sumo[self.ids_node[ids]],
1421
self.ids_vehs_merged_sumo[ids],
1422
self.ids_vehs_merged[ids]
1423
):
1424
1425
print ' ', id_merge, id_node_sumo, ids_veh_merged_sumo
1426
# print ' ids_veh_merged',ids_veh_merged
1427
1428
def exit_veh(self, id_veh, id_veh_sumo, id_merge_from, vehicles, is_remove_from_control=False, debug=0):
1429
print 'exit_veh id_veh %s, id_merge_from %d ' % (id_veh_sumo, id_merge_from), 'entry', self.are_entry[id_merge_from]
1430
# print ' check for platooned vehicles:'
1431
# vehicles.get_platoon(id_veh)
1432
# in id_merge_from: take vehicle out of merged queue and input queue
1433
1434
if id_veh in self.ids_vehs_merged[id_merge_from]:
1435
# enterd veh should be in pole position in merge queue of merge_from
1436
1437
# pop if vehicles are properly merged
1438
# id_veh_from = self.ids_vehs_merged[id_merge_from].pop()
1439
# self.ids_vehs_merged_sumo.ids_vehs_merged[id_merge_from].pop()
1440
# if id_veh_from != id_veh:
1441
# print 'WARNING in enter_veh: veh %d instead of veh %d in polepos of merge %d'%(id_veh_from,id_veh, id_merge_from)
1442
# return False
1443
# lineind = self.lineinds_vehs_merged[id_merge_from].pop()
1444
# for testing: just remove, no matter where
1445
ind_pos = self.ids_vehs_merged[id_merge_from].index(id_veh)
1446
lineind = self.lineinds_vehs_merged[id_merge_from][ind_pos]
1447
1448
if len(self.ids_vehs_merged[id_merge_from]) > ind_pos+1:
1449
# there is a vehicle behind=> remove ghost
1450
id_veh_behind = self.ids_vehs_merged[id_merge_from][ind_pos+1]
1451
id_veh_tail = vehicles.get_platoontail(id_veh) # get last in platoon
1452
vehicles.del_ghost(id_veh_behind, id_veh_tail)
1453
if debug > 0:
1454
print ' del ghost from veh', id_veh_behind, 'ghost', id_veh_tail
1455
print ' check ghosts:', vehicles.ids_ghosts[id_veh_behind]
1456
# is there a vehicle in fron of the removed vehicle
1457
# this happens if a vehicle is interactively deviated
1458
if ind_pos > 0:
1459
1460
id_veh_infront = self.ids_vehs_merged[id_merge_from][ind_pos-1]
1461
id_veh_tail = vehicles.get_platoontail(id_veh_infront) # get last in platoon
1462
1463
id_edge_mergeout_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_from]
1464
dist_to_merge_behind = get_traci_distance(
1465
vehicles.get_id_sumo(id_veh_behind), id_edge_mergeout_sumo, 3.0)
1466
dist_to_merge_infront = get_traci_distance(
1467
vehicles.get_id_sumo(id_veh_infront), id_edge_mergeout_sumo, 3.0)
1468
# 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)
1469
1470
vehicles.add_ghost(id_veh_behind, id_veh_tail, dist_to_merge_behind, dist_to_merge_infront)
1471
1472
# remove any possible ghosts from this vehicle to vehicles behind
1473
# this can happen if this vehicle passed by its ghost vehicle
1474
vehicles.del_ghosts(id_veh)
1475
1476
self.ids_vehs_merged[id_merge_from].pop(ind_pos) # remove(id_veh)
1477
self.ids_vehs_merged_sumo[id_merge_from].pop(ind_pos) # remove(id_veh_sumo)
1478
self.lineinds_vehs_merged[id_merge_from].pop(ind_pos)
1479
if debug > 0:
1480
print ' vehicle has been on line index', lineind
1481
# remove vehicle from line buffers
1482
if lineind == 1:
1483
self.ids_vehs_in1[id_merge_from].remove(id_veh) # pop()
1484
self.ids_vehs_in1_sumo[id_merge_from].remove(id_veh_sumo) # .pop()
1485
if self.are_entry[id_merge_from]:
1486
if debug > 0:
1487
print ' vehicle is involved in entry merge processes?', self.vehicles_mains[id_merge_from].has_key(id_veh)
1488
if self.vehicles_mains[id_merge_from].has_key(id_veh):
1489
#
1490
#id_veh_entry = self.vehicles_mains[id_merge_from][id_veh]
1491
1492
# TODO: this is still a lousy method, vehicles_mains neds to be improved
1493
for id_veh_entry, state in zip(self.vehicles_entries[id_merge_from].keys(), self.vehicles_entries[id_merge_from].values()):
1494
#state = self.vehicles_entries[id_merge_from][id_veh_entry]
1495
# print ' state before',state
1496
if state.has_key('id_veh_infront'):
1497
if state['id_veh_infront'] == id_veh:
1498
del state['id_veh_infront']
1499
if state.has_key('id_veh_behind'):
1500
if state['id_veh_behind'] == id_veh:
1501
del state['id_veh_behind']
1502
# print ' state after',state
1503
1504
del self.vehicles_mains[id_merge_from][id_veh]
1505
1506
if lineind == 2:
1507
self.ids_vehs_in2[id_merge_from].remove(id_veh) # .pop()
1508
self.ids_vehs_in2_sumo[id_merge_from].remove(id_veh_sumo) # .pop()
1509
1510
if self.are_entry[id_merge_from]:
1511
if debug > 0:
1512
print ' del veh prt.%s from vehicles_entries' % id_veh
1513
del self.vehicles_entries[id_merge_from][id_veh]
1514
else:
1515
pass
1516
1517
# remove from centralized database
1518
del self.vehicle_to_merge[id_veh]
1519
1520
else:
1521
# the entered vehicle is not in a merge queue
1522
# probably a new vehicle at station
1523
1524
# just be sure that the vehicle is not in any queue
1525
# but actually this cannot happen
1526
if id_veh in self.ids_vehs_in1[id_merge_from]:
1527
print 'WARNING in exit_veh: new veh %d should not be in inqueue 1' % id_veh
1528
self.ids_vehs_in1[id_merge_from].remove(id_veh)
1529
self.ids_vehs_in1_sumo[id_merge_from].remove(id_veh_sumo)
1530
1531
if id_veh in self.ids_vehs_in2[id_merge_from]:
1532
print 'WARNING in exit_veh: new veh %d should not be in inqueue 2' % id_veh
1533
self.ids_vehs_in2[id_merge_from].remove(id_veh)
1534
self.ids_vehs_in2_sumo[id_merge_from].remove(id_veh_sumo)
1535
1536
if self.vehicle_to_merge.has_key(id_veh):
1537
del self.vehicle_to_merge[id_veh]
1538
1539
if is_remove_from_control:
1540
# remove any merge control operations
1541
vehicles.del_all_ghosts(id_veh)
1542
1543
def exit_veh_forced(self, id_veh, id_veh_sumo, vehicles):
1544
if self.vehicle_to_merge.has_key(id_veh):
1545
# exit vehicle from respective merge
1546
self.exit_veh(id_veh, id_veh_sumo, self.vehicle_to_merge[id_veh], vehicles, is_remove_from_control=True)
1547
else:
1548
# id_veh not under any merge conrol
1549
pass
1550
1551
def print_vehs(self, id_veh1, id_veh2, dist1_min, dist1_max, dist2_min, dist2_max,
1552
lineind1, lineind2, pos_max=79):
1553
dist_max = max(dist1_min, dist1_max, dist2_min, dist2_max)+1
1554
#dist_min = min(dist1_min, dist1_max, dist2_min, dist2_max)
1555
#dist_diff = dist_max-dist_min+10.0
1556
if np.all([dist1_min, dist1_max, dist2_min, dist2_max]) > 0:
1557
f = float(pos_max)/dist_max
1558
print '________________________'
1559
print 'vehicle %s from line %d: %.f--%2f' % (id_veh1, lineind1, dist1_min, dist1_max)
1560
pos_min = int(dist1_min*f)
1561
pos_max = int(dist1_max*f)
1562
print max(pos_min-1, 0)*' '+'<'+(pos_max-pos_min)*'X'+'|'
1563
1564
pos_min = int(dist2_min*f)
1565
pos_max = int(dist2_max*f)
1566
print max(pos_min-1, 0)*' '+'<'+(pos_max-pos_min)*'X'+'|'
1567
print 'vehicle %s from line %d: %.f--%2f' % (id_veh2, lineind2, dist2_min, dist2_max)
1568
print '________________________'
1569
else:
1570
print 'WARNING: some negative distances:'
1571
print 'vehicle %s from line %d: %.f--%2f' % (id_veh1, lineind1, dist1_min, dist1_max)
1572
print 'vehicle %s from line %d: %.f--%2f' % (id_veh2, lineind2, dist2_min, dist2_max)
1573
1574
def enter_veh(self, id_veh, id_veh_sumo, id_merge_from, id_merge_to, id_edge_merge_sumo, vehicles, debug=0):
1575
print 'enter_veh id_veh %s, id_merge_from %d to id_merge_to %d' % (id_veh_sumo, id_merge_from, id_merge_to)
1576
1577
# in id_merge_from: take vehicle out of merged queue and input queue
1578
1579
# put vehicle in centralized database
1580
self.vehicle_to_merge[id_veh] = id_merge_to
1581
1582
# on which input line of merge id_merge_to does the vehicle approach?
1583
if id_veh in self.ids_vehs_merged[id_merge_to]:
1584
# vehicle is in merge queue and input line can be retrived from it
1585
indpos = self.ids_vehs_merged[id_merge_to].index(id_veh)
1586
1587
# on which input line is the vehicle at position index indpos
1588
lineind = self.lineinds_vehs_merged[id_merge_to][indpos]
1589
1590
elif self.ids_node_to_ids_merge[self.ids_node_in1[id_merge_to]] == id_merge_from:
1591
# vehicle not in merge queue, detect input line 1 with nodes db
1592
indpos = -1
1593
lineind = 1
1594
else:
1595
# vehicle not in merge queue, detect input line 2 with nodes db
1596
indpos = -1
1597
lineind = 2
1598
1599
if lineind == 1:
1600
# from line 1
1601
self.ids_vehs_in1[id_merge_to].append(id_veh)
1602
self.ids_vehs_in1_sumo[id_merge_to].append(id_veh_sumo)
1603
dist_tomerge_head_new = self.distances_node_in1[id_merge_to] # correct with pos
1604
1605
elif lineind == 2:
1606
self.ids_vehs_in2[id_merge_to].append(id_veh)
1607
self.ids_vehs_in2_sumo[id_merge_to].append(id_veh_sumo)
1608
dist_tomerge_head_new = self.distances_node_in2[id_merge_to] # correct with pos
1609
1610
if indpos == -1:
1611
# vehicle is new and must be merged into ids_vehs_merged
1612
if debug > 0:
1613
print ' merge veh %d arriving from in %d at dist %.2fm' % (id_veh, lineind, dist_tomerge_head_new)
1614
1615
ids_vehs_merged = self.ids_vehs_merged[id_merge_to]
1616
ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge_to]
1617
lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge_to]
1618
#id_edge_merge_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_to]
1619
ind_insert = len(ids_vehs_merged)
1620
is_insert = False
1621
id_veh_merged = -1
1622
1623
# print ' ids_vehs_merged_sumo[%d]'%id_merge_to,ids_vehs_merged_sumo
1624
# print ' lineinds_vehs_merged[%d]'%id_merge_to,lineinds_vehs_merged
1625
if (ind_insert == 0) | self.are_station[id_merge_to]:
1626
if debug > 0:
1627
print ' new vehicle is the only vehicle or station', ind_insert, self.are_station[id_merge_to]
1628
1629
# vehicles heading toward a station merge are not
1630
# really merged because only one incoming line
1631
ids_vehs_merged.append(id_veh)
1632
ids_vehs_merged_sumo.append(id_veh_sumo)
1633
lineinds_vehs_merged.append(lineind)
1634
1635
elif ind_insert > 0: # there is at least another vehicle
1636
# slower, but more precise than self.distances_node_inX[id_merge_to]
1637
#dist_tomerge_head_new2 = get_traci_distance(id_veh_sumo,id_edge_merge_sumo, 3.0)
1638
#dist_tomerge_tail_new = dist_tomerge_head_new-0.5/ get_traci_velocity(id_veh_sumo)**2+vehicles.lengths_plat[id_veh]
1639
#dist_tomerge_tail_new = dist_tomerge_head_new+vehicles.lengths_plat[id_veh]
1640
id_veh_tail_new = vehicles.get_platoontail(id_veh)
1641
id_veh_tail_new_sumo = vehicles.ids_sumo[id_veh_tail_new]
1642
dist_tomerge_tail_new = get_traci_distance(id_veh_tail_new_sumo, id_edge_merge_sumo, 3.0)
1643
if debug > 0:
1644
# print ' new veh %d arriving from in %d at dist head %.2f /__| tail %.2fm'%(id_veh,lineind,dist_tomerge_head_new,dist_tomerge_tail_new)
1645
print ' ids_vehs_merged_sumo', ids_vehs_merged_sumo
1646
for id_veh_merged, id_veh_merged_sumo in zip(ids_vehs_merged[::-1], ids_vehs_merged_sumo[::-1]):
1647
dist_tomerge_head = get_traci_distance(id_veh_merged_sumo, id_edge_merge_sumo, 3.0)
1648
#stoppeddist_tomerge = dist-0.5/self.decel*get_traci_velocity(id_veh_merged_sumo)**2+vehicles.lengths_plat[id_veh]
1649
#stoppeddist_tomerge = dist+vehicles.lengths_plat[id_veh]
1650
id_veh_tail = vehicles.get_platoontail(id_veh_merged)
1651
id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
1652
dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_merge_sumo, 3.0)
1653
1654
if debug > 0:
1655
self.print_vehs(id_veh, id_veh_merged,
1656
dist_tomerge_head_new, dist_tomerge_tail_new,
1657
dist_tomerge_head, dist_tomerge_tail,
1658
lineind, lineinds_vehs_merged[ind_insert-1])
1659
# 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)
1660
# print ' check veh %d, d %.2fm, d_new %.2fm, ind_insert = %d'%(id_veh_merged,dist,dist_tomerge_head_new,ind_insert)
1661
# 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),)
1662
# print ' tail veh %d, ds %.2fm'%(id_veh_tail,dist_tomerge_tail)
1663
1664
if lineind == lineinds_vehs_merged[ind_insert-1]:
1665
is_insert = True
1666
break
1667
1668
if dist_tomerge_tail_new > dist_tomerge_tail:
1669
# distance to merge of this vehicle in queue is greater
1670
# than the new vehicle
1671
# inseri on copies? No break
1672
1673
# isert in fron of currently checked vehicle
1674
is_insert = True
1675
break
1676
dist_last = dist_tomerge_head
1677
ind_insert -= 1
1678
1679
if is_insert:
1680
# at least one vehicle is in front
1681
if debug > 0:
1682
print ' insert veh %d behind veh %d, index %d' % (id_veh, id_veh_merged, ind_insert)
1683
# send control info to involved vehicles
1684
if ind_insert == len(ids_vehs_merged):
1685
if debug > 0:
1686
print ' appended vehicle after veh', id_veh_tail_sumo, 'with leader', ids_vehs_merged_sumo[ind_insert-1], 'dtm=%.2fm' % dist_tomerge_tail
1687
# V
1688
# |
1689
# G ind_insert-1
1690
1691
# is vehicle and ghost in the same input line?
1692
if lineinds_vehs_merged[ind_insert-1] != lineind:
1693
# id_ghost = ids_vehs_merged[ind_insert-1]# last veh in queue
1694
#vehicles.add_ghost(id_veh, id_ghost, dist_tomerge_head_new, dist)
1695
1696
vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge_head_new, dist_tomerge_tail)
1697
1698
elif ind_insert > 0:
1699
# there is at least 1 other veh in front
1700
if debug > 0:
1701
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
1702
# G1
1703
# |
1704
# V
1705
# |
1706
# G2
1707
id_ghost1 = ids_vehs_merged[ind_insert]
1708
#id_ghost2 = ids_vehs_merged[ind_insert-1]
1709
id_ghost2 = id_veh_tail
1710
1711
vehicles.del_ghost(id_ghost1, id_ghost2)
1712
if lineinds_vehs_merged[ind_insert] != lineind:
1713
vehicles.add_ghost(id_ghost1, id_veh_tail_new, dist_last, dist_tomerge_tail_new)
1714
1715
if lineinds_vehs_merged[ind_insert-1] != lineind:
1716
#vehicles.add_ghost(id_veh, id_ghost2, dist_tomerge_head_new, dist)
1717
vehicles.add_ghost(id_veh, id_ghost2, dist_tomerge_head_new, dist_tomerge_tail)
1718
1719
else:
1720
if debug > 0:
1721
print ' prepend veh %d in front of veh %d, first index %d' % (id_veh, id_veh_merged, ind_insert)
1722
# is vehicle and ghost in the same input line?
1723
if lineinds_vehs_merged[ind_insert] != lineind:
1724
id_veh_behind = ids_vehs_merged[ind_insert] # last veh in queue
1725
vehicles.add_ghost(id_veh_behind, id_veh_tail_new, dist_tomerge_head, dist_tomerge_tail_new)
1726
1727
# finally insert vehicle in merge queue
1728
ids_vehs_merged.insert(ind_insert, id_veh)
1729
ids_vehs_merged_sumo.insert(ind_insert, id_veh_sumo)
1730
lineinds_vehs_merged.insert(ind_insert, lineind)
1731
1732
# inform downstream merges
1733
1734
# else:
1735
# # new vehicle is the only vehicle
1736
# ids_vehs_merged[0] = id_veh
1737
# ids_vehs_merged_sumo[0] = id_veh_sumo
1738
# lineinds_vehs_merged[0] = lineind
1739
1740
def enter_veh_entry(self, id_veh, id_veh_sumo, id_merge_from, id_merge_to, id_edge_merge_sumo, vehicles, debug=0):
1741
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)
1742
1743
# in id_merge_from: take vehicle out of merged queue and input queue
1744
1745
# put vehicle in centralized database
1746
self.vehicle_to_merge[id_veh] = id_merge_to
1747
1748
# on which input line of merge id_merge_to does the vehicle approach?
1749
if id_veh in self.ids_vehs_merged[id_merge_to]:
1750
# vehicle is in merge queue and input line can be retrived from it
1751
indpos = self.ids_vehs_merged[id_merge_to].index(id_veh)
1752
1753
# on which input line is the vehicle at position index indpos
1754
lineind = self.lineinds_vehs_merged[id_merge_to][indpos]
1755
1756
elif self.ids_node_to_ids_merge[self.ids_node_in1[id_merge_to]] == id_merge_from:
1757
# vehicle not in merge queue, detect input line 1 with nodes db
1758
indpos = -1
1759
lineind = 1
1760
else:
1761
# vehicle not in merge queue, detect input line 2 with nodes db
1762
indpos = -1
1763
lineind = 2
1764
1765
# put vehicle in respective line queue
1766
ids_vehs_merged = self.ids_vehs_merged[id_merge_to]
1767
ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge_to]
1768
lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge_to]
1769
1770
if lineind == 1:
1771
# from line 1 (main line)
1772
if debug > 0:
1773
print ' Detected veh', id_veh_sumo, 'on mainline. Is new', indpos == -1
1774
print ' check for platooned vehicles:'
1775
vehicles.get_platoon(id_veh)
1776
1777
id_edge_out_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_to]
1778
dist_tomerge = get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)
1779
ids_vehs_in1 = self.ids_vehs_in1[id_merge_to]
1780
if len(ids_vehs_in1) > 0:
1781
id_veh1_last = self.ids_vehs_in1[id_merge_to][-1]
1782
else:
1783
id_veh1_last = -1
1784
1785
id_veh2, state2 = self.get_mergeveh_entry(id_merge_to)
1786
if id_veh2 == -1:
1787
# no vehicle to merge
1788
if id_veh1_last != -1:
1789
# make ghost to last vehicle
1790
#id_veh_tail = vehicles.get_platoontail(id_veh1_last)
1791
#id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
1792
#dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)
1793
#vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge, dist_tomerge_tail)
1794
1795
# let SUMO do the distances
1796
pass
1797
1798
else:
1799
# merge is empty
1800
pass
1801
1802
elif state2['status'] != 'wait':
1803
# there is an approaching vehicle on entry line
1804
if state2['status'] == 'accelerate':
1805
# vehicle in acceleration mode
1806
if state2.has_key('id_veh_behind'):
1807
# accelerating vehicle has already a vehicle
1808
# in front of which to merge
1809
# => look at last vehicle
1810
1811
# let SUMO do the distances
1812
pass
1813
1814
else:
1815
# let the entering vehicle see the new vehicle
1816
state2['id_veh_behind'] = id_veh
1817
1818
if state2['status'] == 'sync':
1819
if state2.has_key('id_veh_behind'):
1820
# accelerating vehicle has already a vehicle
1821
# in front of which to merge
1822
# => look at last vehicle
1823
1824
# let SUMO do the distances
1825
pass
1826
1827
else:
1828
# speed is already synchonized, but has not yet
1829
# a vehicle behind
1830
# let look the new vehicle look at
1831
# the tail of the entering vehicle
1832
id_veh_tail = vehicles.get_platoontail(id_veh2)
1833
id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
1834
dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)
1835
vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge, dist_tomerge_tail)
1836
1837
self.ids_vehs_in1[id_merge_to].append(id_veh)
1838
self.ids_vehs_in1_sumo[id_merge_to].append(id_veh_sumo)
1839
1840
# append to main merge queue
1841
ids_vehs_merged.append(id_veh)
1842
ids_vehs_merged_sumo.append(id_veh_sumo)
1843
lineinds_vehs_merged.append(lineind)
1844
1845
elif lineind == 2:
1846
# from line 2 (entry line)
1847
if debug > 0:
1848
print ' Detected veh', id_veh_sumo, 'on entry line. Is new', indpos == -1
1849
1850
self.ids_vehs_in2[id_merge_to].append(id_veh)
1851
self.ids_vehs_in2_sumo[id_merge_to].append(id_veh_sumo)
1852
if debug > 0:
1853
print ' command vehicle to stop and wait further instructions'
1854
#vehicles.control_slow_down(id_veh, speed = 6.0/3.6)
1855
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
1856
# print ' set speed to',traci.vehicle.getMaxSpeed(id_veh_sumo)
1857
#traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0)
1858
1859
vehicles.control_stop(id_veh)
1860
1861
# prevent SUMO from reaccelerating vehicle
1862
# vehicles.switch_off_control(id_veh)
1863
if debug > 0:
1864
print ' set veh id_veh prt.%d' % id_veh
1865
self.vehicles_entries[id_merge_to][id_veh] = {'status': 'wait'}
1866
if debug > 0:
1867
print ' vehicles_entries[', id_merge_to, ']=', self.vehicles_entries[id_merge_to]
1868
#
1869
# self.vehicles_mains[id_merge_to][id_veh] = {}# later when used
1870
1871
# Attention: Vehicle on entry line not yet in queue.
1872
# this needs to be fixed later when it becomes clear where to insert
1873
# ids_vehs_merged.append(id_veh)
1874
# ids_vehs_merged_sumo.append(id_veh_sumo)
1875
# lineinds_vehs_merged.append(lineind)
1876
1877
def get_mergeveh_entry(self, id_merge):
1878
"""Returns ID and state of vehicle that is about to merege from
1879
the entry line. ID is -1 if no vehicle starts.
1880
"""
1881
vehicles_entries = self.vehicles_entries[id_merge]
1882
if len(vehicles_entries) == 0:
1883
return -1, {'status': 'wait'}
1884
else:
1885
return vehicles_entries.keys()[0], vehicles_entries.values()[0]
1886
1887
def process_step_entry(self, id_merge, vehicles, debug):
1888
print 'process_step_entry id_merge', id_merge
1889
if debug > 0:
1890
print ' vehicles_entries=', self.vehicles_entries[id_merge]
1891
print ' vehicles_mains', self.vehicles_mains[id_merge]
1892
# print ' self.vehicles_entries',self.vehicles_entries
1893
#self.vehicles_entries[id_merge]= OrderedDict()
1894
# self.vehicles_mains[id_merge] = OrderedDict()
1895
id_veh_del = -1
1896
1897
# for id_veh, state in zip(self.vehicles_entries[id_merge].keys()[::-1],self.vehicles_entries[id_merge].values()[::-1]):
1898
# for id_veh, state in self.vehicles_entries.iteritems():
1899
# for id_veh, state in zip(self.vehicles_entries[id_merge].keys(),self.vehicles_entries[id_merge].values()):
1900
ids_veh_entry = self.vehicles_entries[id_merge].keys()
1901
states_veh_entry = self.vehicles_entries[id_merge].values()
1902
id_edge_out_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge]
1903
ids_veh_in1 = self.ids_vehs_in1[id_merge]
1904
time_update = self.time_update.get_value()
1905
i = 0
1906
#is_cont = len(ids_veh_entry)>0
1907
# while is_cont:
1908
if len(ids_veh_entry) > 0:
1909
id_veh = ids_veh_entry[0]
1910
id_veh_sumo = vehicles.get_id_sumo(id_veh)
1911
state = states_veh_entry[0]
1912
1913
ids_vehs_merged = self.ids_vehs_merged[id_merge]
1914
ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge]
1915
lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge]
1916
if debug > 0:
1917
print ' check id_veh_sumo', id_veh_sumo, 'status', state['status'], 'n vehs on main', len(ids_veh_in1)
1918
if state['status'] == 'wait':
1919
if traci.vehicle.isStopped(id_veh_sumo):
1920
# check potential conflict vehicle on main line
1921
1922
n1 = len(ids_veh_in1)
1923
if n1 == 0:
1924
if debug > 0:
1925
print ' main line is empty => accelerate immediately'
1926
for id_veh_plat in vehicles.get_platoon(id_veh):
1927
vehicles.control_speedup(id_veh_plat)
1928
state['status'] = 'accelerate'
1929
1930
ids_vehs_merged.append(id_veh)
1931
ids_vehs_merged_sumo.append(id_veh_sumo)
1932
lineinds_vehs_merged.append(2)
1933
1934
else:
1935
ids_veh_in1_sumo = self.ids_vehs_in1_sumo[id_merge]
1936
vehicles_main = self.vehicles_mains[id_merge]
1937
dist_in1 = self.distances_node_in1[id_merge]
1938
dist_in2 = self.distances_node_in2[id_merge]
1939
1940
i = 0 # n1-1
1941
is_found = False
1942
while (i < n1) & (not is_found):
1943
id_veh1_sumo = ids_veh_in1_sumo[i]
1944
id_veh1 = ids_veh_in1[i]
1945
if debug > 0:
1946
print ' check', id_veh1_sumo # ,'free',id_veh1 not in vehicles_main
1947
1948
if True: # id_veh1 not in vehicles_main:
1949
1950
# get tail position of id_veh_main
1951
id_veh1_tail = vehicles.get_platoontail(id_veh1)
1952
id_veh1_tail_sumo = vehicles.ids_sumo[id_veh1_tail]
1953
pos1 = dist_in1-get_traci_distance(id_veh1_sumo, id_edge_out_sumo, 3.0)
1954
pos1_tail = dist_in1-get_traci_distance(id_veh1_tail_sumo, id_edge_out_sumo, 3.0)
1955
pos2 = dist_in2 - get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)
1956
p_from, p_to = self.get_pos_crit_entry(pos2,
1957
vehicles.lengths_plat[id_veh],
1958
get_traci_velocity(id_veh1_sumo),
1959
dist_in1, dist_in2,
1960
vehicles)
1961
if debug > 0:
1962
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
1963
1964
print ' i=%d, n1=%d' % (i, n1), 'last vehicle on main', i == n1-1, 'more', i < n1-1
1965
1966
#self.print_vehs(id_veh1, id_veh2, dist1_min, dist1_max, dist2_min, dist2_max,lineind1, lineind2, pos_max = 79)
1967
1968
# here we check whether the tail of the vehicle on the main line
1969
# has passed the critical point p_to
1970
1971
if pos1_tail > p_to:
1972
1973
if i == n1-1: # last vehicle on main
1974
if debug > 0:
1975
print ' insert id_veh', id_veh_sumo, 'behind id_veh1', id_veh1_sumo, 'the only veh on main'
1976
state['id_veh_infront'] = id_veh1
1977
vehicles_main[id_veh1] = id_veh # no, it does not get a ghost
1978
# vehicles_main[id_veh1] = { 'id_veh':id_veh,
1979
# 'delta':pos1_tail-p_to
1980
# }
1981
is_found = True
1982
ids_vehs_merged.append(id_veh)
1983
ids_vehs_merged_sumo.append(id_veh_sumo)
1984
lineinds_vehs_merged.append(2)
1985
1986
elif i < n1-1: # there are others behind on main
1987
# ensure that gap is big enough
1988
id_veh_behind = ids_veh_in1[i+1]
1989
id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]
1990
pos1 = dist_in1 - get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)
1991
if debug > 0:
1992
print ' vehicle behind', id_veh_behind_sumo, 'pos=%.1f, p_from=%.1f' % (pos1, p_from), 'ok', pos1 < p_from
1993
if pos1 < p_from:
1994
state['id_veh_infront'] = id_veh1
1995
state['id_veh_behind'] = id_veh_behind
1996
1997
vehicles_main[id_veh_behind] = id_veh
1998
#vehicles_main[id_veh1] = { 'id_veh_infront':id_veh}
1999
is_found = True
2000
j = ids_vehs_merged.index(id_veh1)+1
2001
# print ' j=',j
2002
ids_vehs_merged.insert(j, id_veh)
2003
ids_vehs_merged_sumo.insert(j, id_veh_sumo)
2004
lineinds_vehs_merged.insert(j, 2)
2005
2006
# here we check whether the vehicle on the main line
2007
# has not yet reached the critical point p_from
2008
elif pos1 < p_from:
2009
if i == 0: # first vehicle on main
2010
if debug > 0:
2011
print ' insert id_veh', id_veh_sumo, 'in front of id_veh1', id_veh1_sumo, 'the only veh on main'
2012
state['id_veh_behind'] = id_veh1
2013
vehicles_main[id_veh1] = id_veh
2014
is_found = True
2015
# determine insert position
2016
j = ids_vehs_merged.index(id_veh1)
2017
# print ' j=',j
2018
ids_vehs_merged.insert(j, id_veh)
2019
ids_vehs_merged_sumo.insert(j, id_veh_sumo)
2020
lineinds_vehs_merged.insert(j, 2)
2021
2022
# elif i < n1-1: # there are others behind on main
2023
# # ensure that gap is big enough
2024
# id_veh_behind = ids_veh_in1[i+1]
2025
# id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]
2026
# pos1 = dist_in1 - get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)
2027
# print ' vehicle behind',id_veh_behind_sumo,'pos=%.1f, p_from=%.1f'%(pos1,p_from),'ok',pos1<p_from
2028
# if pos1<p_from:
2029
# state['id_veh_infront'] = id_veh1
2030
# state['id_veh_behind'] = id_veh_behind
2031
# is_found = True
2032
2033
i += 1
2034
2035
if is_found:
2036
if debug > 0:
2037
print ' suitable vehicle after which entry vehicle can run has been found'
2038
# Note: if no vehicle has been found then
2039
# nothing will happen and the vehicle will
2040
# wait until the righ moment has arrived
2041
for id_veh_plat in vehicles.get_platoon(id_veh):
2042
vehicles.control_speedup(id_veh_plat)
2043
state['status'] = 'accelerate'
2044
2045
else:
2046
if debug > 0:
2047
print ' nothing will happen and the vehicle will wait until the righ moment has arrived'
2048
2049
elif state['status'] == 'accelerate':
2050
# test if speed reached
2051
if traci.vehicle.getSpeed(id_veh_sumo) > 0.9*vehicles.speed_max:
2052
if debug > 0:
2053
print ' synchronization reached for veh', id_veh_sumo
2054
state['status'] = 'sync'
2055
#id_veh_del = id_veh
2056
# now create ghosts
2057
# id_veh -> id_veh_infront_tail:
2058
if state.has_key('id_veh_infront'):
2059
id_veh_in_front = state['id_veh_infront']
2060
id_veh_infront_tail = vehicles.get_platoontail(id_veh_in_front)
2061
id_veh_infront_tail_sumo = vehicles.ids_sumo[id_veh_infront_tail]
2062
dist_tomerge = get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)
2063
dist_tomerge_tail = get_traci_distance(id_veh_infront_tail_sumo, id_edge_out_sumo, 3.0)
2064
if debug > 0:
2065
print ' add ghost to entering veh', id_veh_sumo, ' behind', id_veh_infront_tail_sumo, 'with leader', id_veh_in_front
2066
vehicles.add_ghost(id_veh, id_veh_infront_tail, dist_tomerge,
2067
dist_tomerge_tail, is_substitute=True)
2068
2069
if state.has_key('id_veh_behind'):
2070
id_veh_behind = state['id_veh_behind']
2071
id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]
2072
2073
dist_tomerge_behind = get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)
2074
2075
id_veh_tail = vehicles.get_platoontail(id_veh)
2076
id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]
2077
dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)
2078
# print ' add ghost to mainline veh',id_veh_behind_sumo,' behind',id_veh_tail_sumo,'with leader',id_veh_sumo
2079
vehicles.add_ghost(id_veh_behind, id_veh_tail, dist_tomerge_behind,
2080
dist_tomerge_tail, is_substitute=True)
2081
2082
else:
2083
if debug > 0:
2084
speed = traci.vehicle.getSpeed(id_veh_sumo)
2085
print ' sync of veh', id_veh_sumo, ',v=%.1f, not yet reached: %.2f' % (speed, speed/vehicles.speed_max)
2086
2087
if state.has_key('id_veh_behind'):
2088
id_veh_behind_sumo = vehicles.ids_sumo[state['id_veh_behind']]
2089
info = traci.vehicle.getLeader(id_veh_behind_sumo, dist=200.0)
2090
if (info is not None):
2091
# extract lead vehicle ID and distance from info
2092
id_leader_sumo, dist_leader = info
2093
#speed = vehicles.speed_max
2094
speed = get_traci_velocity(id_veh_behind_sumo)
2095
dist_safe = vehicles.tau*speed + 0.5*speed**2/vehicles.decel_emergency
2096
dist_target = 2*dist_safe+vehicles.lengths_plat[id_veh]
2097
if debug > 0:
2098
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
2099
if dist_leader < dist_target:
2100
dv = time_update*vehicles.decel
2101
if (speed-dv) > 0:
2102
if debug > 0:
2103
print ' slowdown', id_veh_behind_sumo, 'from speed %.2f to %.2f' % (speed, speed-dv)
2104
traci.vehicle.slowDown(id_veh_behind_sumo, speed-dv, time_update)
2105
else:
2106
dv = time_update*vehicles.decel
2107
if debug > 0:
2108
print ' accel', id_veh_behind_sumo, 'from speed %.2f to %.2f' % (speed, speed+dv)
2109
traci.vehicle.slowDown(id_veh_behind_sumo, speed+dv, time_update)
2110
2111
elif state['status'] == 'sync':
2112
pass
2113
2114
# if id_veh_del > -1:
2115
# del self.vehicles_entries[id_merge][id_veh_del]
2116
2117
def get_pos_crit_entry(self, pos2, len_veh2, speed, dist1, dist2, vehicles):
2118
"""
2119
Returns critical position interval of vehicle-platoon on main line
2120
with respect to the starting position of a vehicle at entry line.
2121
The returned critical position interval(pos_from, pos_to), which should
2122
ideally be free of vehicles.
2123
pos_from refers to the position of the nose of a vehicle on the main line
2124
pos_to refers to the position of the tail of the platoon on the main line.
2125
2126
"""
2127
# print 'get_pos_crit_entry pos2=%.1f, v=%.1f, d1=%.1f, d2=%.1f'%(pos2, speed, dist1, dist2)
2128
# see 191030
2129
decel_emergency = vehicles.decel_emergency
2130
decel_comfort = vehicles.decel
2131
time_emergency = vehicles.tau
2132
s2 = 0.5*speed**2/decel_comfort
2133
delta2 = dist2 - pos2 - s2
2134
2135
s1 = speed**2/decel_comfort
2136
s_safe = time_emergency*speed + 0.5*speed**2/decel_emergency
2137
p_to = dist1 - delta2 - s1 + s_safe
2138
p_from = p_to-len_veh2-2*s_safe
2139
# print ' delta2=%.1f, s2=%.1f, s1=%.1f, ss=%.1f, CI=(%.1f,%.1f)'%(delta2,s2,s1,s_safe,p_from,p_to)
2140
return p_from, p_to
2141
2142
def search_upstream_merge(self, id_edge_start, edges, lanes, id_prtmode, ids_mainline=set()):
2143
"""
2144
Searches next upstream merge node.
2145
Returns id_node, length to node
2146
2147
"""
2148
# print 'search_upstream_merge id_edge_start',id_edge_start
2149
length = edges.lengths[id_edge_start]
2150
is_merge = False
2151
id_edge_platform = -1
2152
id_edge = id_edge_start
2153
while (not is_merge):
2154
ids_edge_incoming = edges.get_incoming(id_edge)
2155
2156
# print ' search id_edge,ids_edge_incoming',id_edge,ids_edge_incoming
2157
if len(ids_edge_incoming) == 2:
2158
#id_edge1, id_edge2 = ids_edge_to
2159
ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_incoming]
2160
#al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)
2161
#al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)
2162
# print ' check: '
2163
# print ' id_edge1',ids_edge_incoming[0],'ids_lane1',ids_lane1,self.is_prt_only(ids_lane1, lanes)
2164
# print ' id_edge2',ids_edge_incoming[1],'ids_lane2',ids_lane2,self.is_prt_only(ids_lane2, lanes)
2165
if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
2166
# print ' 2 in, one out => it is a merge node'
2167
is_merge = True
2168
2169
elif len(ids_edge_incoming) == 1:
2170
ids_lane = edges.ids_lanes[ids_edge_incoming[0]]
2171
#al = lanes.get_accesslevel(ids_lane, id_prtmode)
2172
if self.is_prt_only(ids_lane, lanes) & (id_edge in ids_mainline):
2173
# print ' mainline input node
2174
is_merge = True
2175
2176
if self.is_platform(ids_lane, lanes):
2177
# print ' 1 in, with multiple access => it is a station output node'
2178
is_merge = True
2179
2180
if not is_merge:
2181
id_edge = ids_edge_incoming[0]
2182
length += edges.lengths[id_edge]
2183
2184
# print ' id_edge,is_merge',id_edge,is_merge
2185
# print ' found node',edges.ids_fromnode[id_edge]
2186
return edges.ids_fromnode[id_edge], length
2187
2188
def search_downstream_merges(self, id_edge_start, edges, lanes, id_prtmode, ids_sinkedge=set()):
2189
"""
2190
Searches next downstream merge nodes.
2191
Returns array of downstream merge node IDs
2192
2193
"""
2194
2195
ids_edge = set([id_edge_start])
2196
ids_mergenode = set()
2197
# print 'search_downstream_merges id_edge_start',id_edge_start,'is sinkedge', id_edge_start in ids_sinkedge
2198
2199
if id_edge_start in ids_sinkedge:
2200
return None # np.array([], dtype = np.int32)
2201
2202
is_cont = True
2203
#n_cont = 20
2204
while (len(ids_edge) > 0) & is_cont:
2205
# print ' len(ids_edge)',len(ids_edge),ids_edge
2206
ids_edge_new = set()
2207
2208
for id_edge in ids_edge:
2209
ids_edge_outgoing = edges.get_outgoing(id_edge)
2210
# print ' id_edge,ids_edge_outgoing',id_edge,ids_edge_outgoing
2211
for id_downedge in ids_edge_outgoing:
2212
ids_lane = edges.ids_lanes[id_downedge]
2213
if id_downedge in ids_sinkedge:
2214
# print ' sinkedge id_downedge',id_downedge
2215
pass
2216
2217
elif self.is_prt_only(ids_lane, lanes):
2218
ids_downedge_incoming = edges.get_incoming(id_downedge)
2219
# print ' id_downedge,ids_downedge_incoming',id_downedge,ids_downedge_incoming
2220
is_merge = False
2221
2222
if len(ids_downedge_incoming) == 2:
2223
ids_lane1, ids_lane2 = edges.ids_lanes[ids_downedge_incoming]
2224
#al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)
2225
#al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)
2226
# print ' check al1,al2',al1,al2,(al1 == 2) & (al2 == 2)
2227
# if (al1 == 2) & (al2 == 2):# real merges
2228
if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):
2229
# print ' add mergenode',edges.ids_fromnode[id_downedge]
2230
ids_mergenode.add(edges.ids_fromnode[id_downedge])
2231
is_merge = True
2232
2233
if not is_merge: # len(ids_downedge_incoming) == 1:
2234
#ids_lane = edges.ids_lanes[ids_downedge_incoming]
2235
# if lanes.get_accesslevel(ids_lane1, id_prtmode) == 2:
2236
# print ' no merge detected, add edge',id_downedge
2237
ids_edge_new.add(id_downedge)
2238
2239
# else:
2240
# print 'WARNING in search_downstream_merges: edge %d has %d incoming edges.'%(id_downedge, len(ids_downedge_incoming))
2241
2242
ids_edge = ids_edge_new.copy()
2243
# print ' ids_edge_new',ids_edge_new,ids_edge,len(ids_edge)
2244
# is_cont = n_cont>0 #id_edge_start not in ids_edge
2245
#n_cont -= 1
2246
2247
# if not is_cont:
2248
# print ' endless!!id_edge_start,ids_edge',id_edge_start,ids_edge
2249
# print ' found ids_mergenode',ids_mergenode
2250
return np.array(list(ids_mergenode), dtype=np.int32)
2251
2252
def is_prt_only(self, ids_lane, lanes):
2253
if len(ids_lane) > 1:
2254
return False
2255
else:
2256
if len(lanes.ids_modes_allow[ids_lane[0]]) > 0:
2257
return lanes.ids_modes_allow[ids_lane[0]][0] == self.parent.id_prtmode
2258
else:
2259
return False
2260
2261
def is_platform(self, ids_lane, lanes):
2262
if len(ids_lane) > 1:
2263
if len(lanes.ids_modes_allow[ids_lane[1]]) > 0:
2264
# we could also chech ped on lane 0
2265
return lanes.ids_modes_allow[ids_lane[1]][0] == self.parent.id_prtmode
2266
else:
2267
return False
2268
else:
2269
return False
2270
2271
2272
class PrtBerths(am.ArrayObjman):
2273
2274
def __init__(self, ident, prtstops, **kwargs):
2275
# print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1')
2276
self._init_objman(ident=ident,
2277
parent=prtstops,
2278
name='PRT Berths',
2279
info='PRT Berths.',
2280
**kwargs)
2281
2282
self._init_attributes()
2283
2284
def _init_attributes(self):
2285
#vtypes = self.get_scenario().demand.vtypes
2286
net = self.get_scenario().net
2287
self.add(cm.AttrConf('length_default', 4.0,
2288
groupnames=['parameters', 'options'],
2289
name='Default length',
2290
info='Default berth length.',
2291
unit='m',
2292
))
2293
2294
self.add_col(am.IdsArrayConf('ids_prtstop', self.parent,
2295
name='PRT stop ID',
2296
info='PRT stop ID',
2297
))
2298
2299
# states now dynamic, see prepare_sim
2300
# if hasattr(self,'states'):
2301
# self.delete('states')
2302
# self.add_col(am.ArrayConf( 'states', default = BERTHSTATES['free'],
2303
# dtype = np.int32,
2304
# choices = BERTHSTATES,
2305
# name = 'state',
2306
# info = 'State of berth.',
2307
# ))
2308
2309
self.add_col(am.ArrayConf('stoppositions', default=0.0,
2310
dtype=np.float32,
2311
name='Stop position',
2312
info='Position on edge where vehicle nose stops.',
2313
))
2314
2315
def _init_constants(self):
2316
self.do_not_save_attrs([
2317
'states', 'ids_veh',
2318
])
2319
2320
def prepare_sim(self, process):
2321
# print 'PrtBerths.prepare_sim'
2322
ids = self.get_ids()
2323
if len(ids) == 0:
2324
return []
2325
self.states = BERTHSTATES['free']*np.ones(np.max(ids)+1, dtype=np.int32)
2326
self.ids_veh = -1*np.ones(np.max(ids)+1, dtype=np.int32)
2327
return [] # berth has no update function
2328
2329
def get_scenario(self):
2330
return self.parent.get_scenario()
2331
2332
def get_prtvehicles(self):
2333
return self.parent.parent.prtvehicles
2334
2335
def make(self, id_stop, position_from=None, position_to=None,
2336
n_berth=None,
2337
offset_firstberth=0.0, offset_stoppos=-0.0):
2338
stoplength = position_to-position_from
2339
# print 'Berths.make',id_stop,stoplength
2340
2341
# TODO: let define berth number either explicitely or through stoplength
2342
2343
length_berth = self.length_default.get_value()
2344
positions = position_from + offset_firstberth\
2345
+ np.arange(length_berth-offset_firstberth, stoplength+length_berth, length_berth) + offset_stoppos
2346
n_berth = len(positions)
2347
2348
# force number of berth to be pair
2349
if n_berth % 2 == 1:
2350
positions = positions[1:]
2351
n_berth -= 1
2352
2353
ids_berth = self.add_rows(n=n_berth,
2354
stoppositions=positions,
2355
ids_prtstop=id_stop * np.ones(n_berth, dtype=np.int32),
2356
)
2357
return ids_berth
2358
2359
def set_prtvehicles(self, prtvehicles):
2360
"""
2361
Defines attributes which are linked with prtvehicles
2362
"""
2363
self.add_col(am.IdsArrayConf('ids_veh_allocated', prtvehicles,
2364
name='Alloc. veh ID',
2365
info='ID of vehicle which have allocated this berth. -1 means no allocation.',
2366
))
2367
2368
2369
class PrtPlatoonStops(am.ArrayObjman):
2370
"""
2371
This class is only for backwardscompatibility with some scenarios.
2372
Is to be depricated
2373
"""
2374
2375
def __init__(self, ident, prtservices, **kwargs):
2376
pass
2377
2378
def get_edges(self, ids_prtstop):
2379
net = self.get_scenario().net
2380
return net.lanes.ids_edge[net.ptstops.ids_lane[self.ids_ptstop[ids_prtstop]]]
2381
2382
def get_berths(self):
2383
return self.berths.get_value()
2384
2385
def get_scenario(self):
2386
return self.parent.get_scenario()
2387
2388
def set_prtvehicles(self, prtvehicles):
2389
self.get_berths().set_prtvehicles(prtvehicles)
2390
2391
def set_vehicleman(self, vehicleman):
2392
self.add(cm.ObjConf(vehicleman, is_child=False, groups=['_private']))
2393
2394
def get_vehicleman(self):
2395
return self.vehicleman.get_value()
2396
2397
2398
class PrtStops(am.ArrayObjman):
2399
def __init__(self, ident, prtservices, **kwargs):
2400
self._init_objman(ident=ident,
2401
parent=prtservices,
2402
name='PRT stops',
2403
info='Contains information on PRT stops.',
2404
#xmltag = ('additional','busStop','stopnames'),
2405
version=0.1,
2406
**kwargs)
2407
self._init_attributes()
2408
2409
def _init_attributes(self):
2410
self.add(cm.ObjConf(PrtBerths('berths', self)))
2411
2412
berths = self.get_berths()
2413
net = self.get_scenario().net
2414
2415
self.add(cm.AttrConf('time_update', 0.5,
2416
groupnames=['parameters'],
2417
name='Update time',
2418
info="Update time for station.",
2419
unit='s',
2420
))
2421
2422
self.add(cm.AttrConf('time_kickout', 30.0,
2423
groupnames=['parameters'],
2424
name='Kickout time',
2425
info="Time to kick out empty vehicles after vehicles behing have been occupied with passengers.",
2426
unit='s',
2427
))
2428
self.add(cm.AttrConf('timeconst_flow', 0.98,
2429
groupnames=['parameters'],
2430
name='Flow time const',
2431
info="Constant to update the moving average flow.",
2432
))
2433
2434
self.add(cm.AttrConf('stoplinegap', 12.0,
2435
groupnames=['parameters'],
2436
name='Stopline gap',
2437
unit='m',
2438
info="Distance between stopline, where vehicles get started, and the end of the lane.",
2439
))
2440
2441
if hasattr(self, 'time_update_man'):
2442
self.delete('time_update_man')
2443
self.delete('timehorizon')
2444
2445
self.add_col(am.IdsArrayConf('ids_ptstop', net.ptstops,
2446
name='ID PT stop',
2447
info='ID of public transport stop. ',
2448
))
2449
2450
if hasattr(self, 'are_depot'):
2451
self.delete('are_depot')
2452
2453
self.add_col(am.ArrayConf('types', default=STOPTYPES['person'],
2454
dtype=np.int32,
2455
perm='rw',
2456
choices=STOPTYPES,
2457
name='Type',
2458
info='Type of stop.',
2459
))
2460
2461
self.add_col(am.IdlistsArrayConf('ids_berth_alight', berths,
2462
#groupnames = ['_private'],
2463
name='Alight berth IDs',
2464
info="Alight berth IDs.",
2465
))
2466
2467
self.add_col(am.IdlistsArrayConf('ids_berth_board', berths,
2468
#groupnames = ['_private'],
2469
name='Board berth IDs',
2470
info="Board berth IDs.",
2471
))
2472
2473
# self.add_col(am.ArrayConf( 'inds_berth_alight_allocated', default = 0,
2474
# #groupnames = ['_private'],
2475
# dtype = np.int32,
2476
# perm = 'rw',
2477
# name = 'Ind aberth lastalloc',
2478
# info = 'Berth index of last allocated berth in alight zone.',
2479
# ))
2480
2481
# self.add_col(am.ArrayConf( 'inds_berth_board_allocated', default = 0,
2482
# #groupnames = ['_private'],
2483
# dtype = np.int32,
2484
# perm = 'rw',
2485
# name = 'Ind bberth lastalloc',
2486
# info = 'Berth index of last allocated berth in boarding zone.',
2487
# ))
2488
2489
def _init_constants(self):
2490
self.do_not_save_attrs([
2491
'ids_stop_to_ids_edge_sumo', 'ids_stop_to_ids_edge',
2492
'stoplines', 'ids_stop_to_ids_acceledge_sumo',
2493
'id_edge_sumo_to_id_stop', 'inds_berth_alight_allocated',
2494
'inds_berth_board_allocated', 'ids_vehs_alight_allocated',
2495
'ids_vehs_board_allocated', 'times_plat_accumulate',
2496
'ids_vehs_sumo_prev', 'ids_vehs',
2497
'ids_vehs_toallocate', 'times_lastboard',
2498
'numbers_veh', 'numbers_person_wait',
2499
'flows_person', 'ids_veh_lead',
2500
'ids_veh_lastdep', 'ids_vehs_prog',
2501
'ids_persons_sumo_prev', 'ids_persons_sumo_boarded',
2502
'waittimes_persons', 'waittimes_tot',
2503
'id_person_to_origs_dests',
2504
'ids_detectoredge_decompr'
2505
])
2506
2507
def get_edges(self, ids_prtstop):
2508
net = self.get_scenario().net
2509
return net.lanes.ids_edge[net.ptstops.ids_lane[self.ids_ptstop[ids_prtstop]]]
2510
2511
def get_berths(self):
2512
return self.berths.get_value()
2513
2514
def get_scenario(self):
2515
return self.parent.get_scenario()
2516
2517
def set_prtvehicles(self, prtvehicles):
2518
self.get_berths().set_prtvehicles(prtvehicles)
2519
2520
def set_vehicleman(self, vehicleman):
2521
self.add(cm.ObjConf(vehicleman, is_child=False, groups=['_private']))
2522
2523
def get_vehicleman(self):
2524
return self.vehicleman.get_value()
2525
2526
def get_closest(self, coords):
2527
"""
2528
Returns the closest prt stop for each coord in coords vector.
2529
"""
2530
net = self.get_scenario().net
2531
ptstops = net.ptstops
2532
lanes = net.lanes
2533
n = len(coords)
2534
# print 'get_closest',n
2535
2536
#ids_stop = self.get_ids()
2537
2538
ids_prtstop = self.get_ids()
2539
ids_ptstop = self.ids_ptstop[ids_prtstop]
2540
coords_stop = ptstops.centroids[ids_ptstop]
2541
ids_edge_stop = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]
2542
2543
inds_closest = np.zeros(n, dtype=np.int32)
2544
2545
i = 0
2546
for coord in coords:
2547
ind_closest = np.argmin(np.sum((coord-coords_stop)**2, 1))
2548
inds_closest[i] = ind_closest
2549
i += 1
2550
2551
ids_prtstop_closest = ids_prtstop[inds_closest]
2552
ids_edge_closest = ids_edge_stop[inds_closest]
2553
2554
return ids_prtstop_closest, ids_edge_closest
2555
2556
def get_waitpositions(self, ids, is_alight=False, offset=-0.0):
2557
"""
2558
Assign randomly a wait-position for each stop in ids
2559
2560
offset is wait position relative to the vehicle nose.
2561
"""
2562
# print 'get_waitpositions min(ids),max(ids)',min(ids),is_alight,max(ids),offset
2563
positions = np.zeros(len(ids), dtype=np.float32)
2564
randint = random.randint
2565
if is_alight:
2566
ids_berths = self.ids_berth_alight[ids]
2567
else:
2568
ids_berths = self.ids_berth_board[ids]
2569
2570
stoppositions = self.get_berths().stoppositions
2571
# print ' ids_berths',ids_berths
2572
i = 0
2573
for id_stop, ids_berth in zip(ids, ids_berths):
2574
#ids_berth = ids_berths[id_stop]
2575
ind_berth = randint(0, len(ids_berth)-1)
2576
2577
positions[i] = stoppositions[ids_berth[ind_berth]]
2578
# print ' id_stop,ids_berth,posiions',id_stop,ids_berth,stoppositions[ids_berth[ind_berth]]
2579
i += 1
2580
#positions[i] = stoppositions[ids_berth[randint(0,len(ids_berth))]]
2581
# for id_stop , pos in zip(ids, positions):
2582
# print ' id_stop %d, is_alight = %s, pos %.2fm'%(id_stop, is_alight ,pos)
2583
2584
return positions+offset
2585
2586
def prepare_sim(self, process):
2587
print 'PrtStops.prepare_sim'
2588
net = self.get_scenario().net
2589
ptstops = net.ptstops
2590
ids_edge_sumo = net.edges.ids_sumo
2591
2592
berths = self.get_berths()
2593
lanes = net.lanes
2594
ids_edge_sumo = net.edges.ids_sumo
2595
ids = self.get_ids()
2596
2597
if len(ids) == 0: # np PRT stops in network
2598
return []
2599
2600
get_outgoing = net.edges.get_outgoing
2601
2602
# station management
2603
self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1, dtype=np.object)
2604
self.ids_stop_to_ids_edge = np.zeros(np.max(ids)+1, dtype=np.int32)
2605
2606
ids_stopedge = lanes.ids_edge[ptstops.ids_lane[self.ids_ptstop[ids]]]
2607
# print ' ids,self.stoplines[ids]',ids,self.stoplines[ids]
2608
self.ids_stop_to_ids_edge_sumo[ids] = ids_edge_sumo[ids_stopedge]
2609
self.ids_stop_to_ids_edge[ids] = ids_stopedge
2610
2611
# Determine stopline position where vehicles actually start
2612
# running off the station
2613
2614
# final stop at one meter before end of stopedge
2615
self.stoplines = np.zeros(np.max(ids)+1, dtype=np.float32)
2616
stoplinegap = self.stoplinegap.get_value()
2617
#self.stoplines[ids] = net.edges.lengths[ids_stopedge]-12.0
2618
#stoplengths = net.edges.lengths[ids_stopedge]
2619
for id_stop, ids_berth_board, length_stopedge in zip(ids, self.ids_berth_board[ids], net.edges.lengths[ids_stopedge]):
2620
lastberthstoppos = berths.stoppositions[ids_berth_board][-1]
2621
if (length_stopedge-lastberthstoppos) > stoplinegap+1:
2622
self.stoplines[id_stop] = length_stopedge-stoplinegap
2623
print ' LI:id_stop', id_stop, 'length_stopedge', length_stopedge, 'stopline', self.stoplines[id_stop]
2624
2625
elif length_stopedge > lastberthstoppos:
2626
self.stoplines[id_stop] = 0.5*(length_stopedge+lastberthstoppos)
2627
print ' AV:id_stop', id_stop, 'length_stopedge', length_stopedge, 'stopline', self.stoplines[id_stop]
2628
2629
self.ids_stop_to_ids_acceledge_sumo = np.zeros(np.max(ids)+1, dtype=np.object)
2630
for id_stop, id_stopedge in zip(ids, ids_stopedge):
2631
self.ids_stop_to_ids_acceledge_sumo[id_stop] = ids_edge_sumo[get_outgoing(id_stopedge)[0]]
2632
2633
self.id_edge_sumo_to_id_stop = {}
2634
for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]):
2635
self.id_edge_sumo_to_id_stop[id_edge_sumo] = id_stop
2636
2637
self.inds_berth_alight_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32)
2638
self.inds_berth_board_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32)
2639
self.ids_vehs_alight_allocated = np.zeros(np.max(ids)+1, dtype=np.object)
2640
self.ids_vehs_board_allocated = np.zeros(np.max(ids)+1, dtype=np.object)
2641
2642
# time when last platoon vehicle accumulation started
2643
# -1 means no platoon accumulation takes place
2644
self.times_plat_accumulate = -1*np.ones(np.max(ids)+1, dtype=np.int32)
2645
2646
self.ids_vehs_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object)
2647
self.ids_vehs = np.zeros(np.max(ids)+1, dtype=np.object)
2648
self.ids_vehs_toallocate = np.zeros(np.max(ids)+1, dtype=np.object)
2649
#
2650
self.times_lastboard = 10**4*np.ones(np.max(ids)+1, dtype=np.int32)
2651
2652
# for vehicle management
2653
self.numbers_veh = np.zeros(np.max(ids)+1, dtype=np.int32)
2654
self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype=np.int32)
2655
self.flows_person = np.zeros(np.max(ids)+1, dtype=np.float32)
2656
self.ids_veh_lead = -1*np.ones(np.max(ids)+1, dtype=np.int32)
2657
#self.ids_veh_lastdep = -1*np.ones(np.max(ids)+1,dtype = np.int32)
2658
self.ids_vehs_prog = np.zeros(np.max(ids)+1, dtype=np.object)
2659
2660
# person management
2661
self.ids_persons_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object)
2662
#self.ids_persons_sumo_boarded = np.zeros(np.max(ids)+1,dtype = np.object)
2663
self.waittimes_persons = np.zeros(np.max(ids)+1, dtype=np.object)
2664
self.waittimes_tot = np.zeros(np.max(ids)+1, dtype=np.float32)
2665
2666
virtualpop = self.get_scenario().demand.virtualpop
2667
2668
ids_persons = virtualpop.get_ids()
2669
stagelists = virtualpop.get_plans().stagelists
2670
prttransits = virtualpop.get_plans().get_stagetable('prttransits')
2671
id_person_to_origs_dests = {}
2672
2673
# create map from person id to various destination information
2674
# TODO: needs to be improved for trip chains, move to prtservices
2675
# idea: whu not scan prttransits?
2676
for id_person, stagelist in zip(ids_persons, stagelists[virtualpop.ids_plan[ids_persons]]):
2677
# print ' check dests of id_person',id_person
2678
for stages, id_stage in stagelist:
2679
if stages.ident == 'prttransits':
2680
id_fromedge_sumo = ids_edge_sumo[stages.ids_fromedge[id_stage]]
2681
id_toedge_sumo = ids_edge_sumo[stages.ids_toedge[id_stage]]
2682
data_orig_dest = (self.id_edge_sumo_to_id_stop[id_fromedge_sumo],
2683
self.id_edge_sumo_to_id_stop[id_toedge_sumo],
2684
id_fromedge_sumo,
2685
id_toedge_sumo)
2686
2687
id_person_sumo = virtualpop.get_id_sumo_from_id(id_person)
2688
if id_person_to_origs_dests.has_key(id_person_sumo):
2689
id_person_to_origs_dests[id_person_sumo].append(data_orig_dest)
2690
else:
2691
id_person_to_origs_dests[id_person_sumo] = [data_orig_dest]
2692
# print ' prtdests = ',id_person_to_origs_dests[id_person_sumo]
2693
2694
# print ' id_person_to_origs_dests=\n',id_person_to_origs_dests
2695
self.id_person_to_origs_dests = id_person_to_origs_dests
2696
2697
# this is only used for crazy person stage detection
2698
# angles_stop =
2699
2700
# various initianilizations
2701
for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]):
2702
# set allocation index to last possible berth
2703
self.inds_berth_alight_allocated[id_stop] = len(self.ids_berth_alight[id_stop])
2704
self.inds_berth_board_allocated[id_stop] = len(self.ids_berth_board[id_stop])
2705
2706
self.ids_vehs_alight_allocated[id_stop] = []
2707
self.ids_vehs_board_allocated[id_stop] = []
2708
2709
self.ids_vehs_sumo_prev[id_stop] = set([])
2710
self.ids_persons_sumo_prev[id_stop] = set([])
2711
#self.ids_persons_sumo_boarded [id_stop] = []
2712
self.waittimes_persons[id_stop] = {}
2713
self.ids_vehs[id_stop] = []
2714
self.ids_vehs_toallocate[id_stop] = []
2715
2716
self.ids_vehs_prog[id_stop] = []
2717
2718
# decompressor detector edge set
2719
self.ids_detectoredge_decompr = set(self.parent.decompressors.ids_detectoredge.get_value())
2720
2721
# traci.edge.subscribe(id_edge_sumo, [traci.constants.VAR_ARRIVED_VEHICLES_IDS])
2722
updatedata_berth = berths.prepare_sim(process)
2723
2724
return [(self.time_update.get_value(), self.process_step),
2725
]+updatedata_berth
2726
2727
def process_step(self, process):
2728
simtime = process.simtime
2729
print 79*'_'
2730
print 'PrtStops.process_step at', simtime
2731
net = self.get_scenario().net
2732
ptstops = net.ptstops
2733
berths = self.get_berths()
2734
lanes = net.lanes
2735
ids_edge_sumo = net.edges.ids_sumo
2736
vehicles = self.parent.prtvehicles
2737
virtualpop = self.get_scenario().demand.virtualpop
2738
ids = self.get_ids()
2739
2740
for id_stop, id_edge_sumo, ids_veh_sumo_prev, ids_person_sumo_prev in\
2741
zip(ids, self.ids_stop_to_ids_edge_sumo[ids],
2742
self.ids_vehs_sumo_prev[ids],
2743
self.ids_persons_sumo_prev[ids]):
2744
print ' '+60*'.'
2745
print ' process id_stop,id_edge_sumo', id_stop, id_edge_sumo
2746
if 0: # id_stop==1:
2747
2748
# print ' ids_berth_alight',self.ids_berth_alight[id_stop]
2749
# print ' ids_berth_board',self.ids_berth_board[id_stop]
2750
print ' ids_vehs', self.ids_vehs[id_stop]
2751
print ' ids_vehs_toallocate', self.ids_vehs_toallocate[id_stop]
2752
print ' inds_berth_alight_allocated', self.inds_berth_alight_allocated[id_stop]
2753
print ' ids_vehs_alight_allocated', self.ids_vehs_alight_allocated[id_stop]
2754
print ' ids_vehs_board_allocated', self.ids_vehs_board_allocated[id_stop]
2755
# print ' id_veh_lead prt.%d'%self.ids_veh_lead[id_stop]
2756
# print ' ids_vehs_prog',self.ids_vehs_prog[id_stop]
2757
2758
print ' iiinds_berth_alight_allocated', self.inds_berth_alight_allocated[id_stop]
2759
print ' iiinds_berth_board_allocated', self.inds_berth_board_allocated[id_stop]
2760
# print ' numbers_person_wait',self.numbers_person_wait[id_stop]
2761
2762
# print ' flow_person',self.flows_person[id_stop]
2763
# print ' waittimes_persons',self.waittimes_persons[id_stop]
2764
2765
# print ' waittimes_tot',self.waittimes_tot[id_stop]
2766
2767
# no longer print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop]
2768
# print ' times_lastboard',self.times_lastboard[id_stop]
2769
2770
if 0:
2771
for id_veh_sumo in self.ids_vehs_sumo_prev[id_stop]:
2772
print ' stopstate ', id_veh_sumo, bin(traci.vehicle.getStopState(id_veh_sumo))[2:], traci.vehicle.getRoute(id_veh_sumo)
2773
2774
if 0:
2775
self.get_berthqueues(id_stop)
2776
2777
# check for new vehicle arrivals/departures
2778
ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_sumo))
2779
# print ' ids_veh_sumo_prev=',ids_veh_sumo_prev
2780
# print ' ids_veh_sumo=',ids_veh_sumo
2781
2782
if ids_veh_sumo_prev != ids_veh_sumo:
2783
ids_veh_entered = vehicles.get_ids_from_ids_sumo(get_entered_vehs(ids_veh_sumo, ids_veh_sumo_prev))
2784
ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo)))
2785
for id_veh in ids_veh_entered:
2786
self.enter(id_stop, id_veh)
2787
2788
for id_veh in ids_veh_left:
2789
self.exit(id_stop, id_veh)
2790
self.ids_vehs_sumo_prev[id_stop] = ids_veh_sumo
2791
# print ' ids_veh_sumo_entered',ids_veh_sumo_entered
2792
# print ' ids_veh_sumo_left',ids_veh_sumo_left
2793
2794
# check whether allocated vehicles arrived at alighting berths
2795
ids_veh_remove = []
2796
for id_veh in self.ids_vehs_alight_allocated[id_stop]:
2797
# TODO: here we could also check vehicle position
2798
# print ' isStopped',vehicles.get_id_sumo(id_veh),traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh))
2799
if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)):
2800
ids_veh_remove.append(id_veh)
2801
id_berth_alight = vehicles.ids_berth[id_veh]
2802
berths.ids_veh[id_berth_alight] = id_veh
2803
berths.states[id_berth_alight] = BERTHSTATES['alighting']
2804
vehicles.alight(id_veh)
2805
2806
for id_veh in ids_veh_remove:
2807
self.ids_vehs_alight_allocated[id_stop].remove(id_veh)
2808
2809
# check whether we can move vehicles from alighting to
2810
# boarding berths
2811
2812
# TODO: here we must check if berth in boarding zone are free
2813
# AND if they are occupied with empty vehicles, those
2814
# vehicles need to be kicked out...but only in case
2815
# new vehicles are waiting to be allocated
2816
2817
ids_berth_alight = self.ids_berth_alight[id_stop][::-1]
2818
ids_berth_board = self.ids_berth_board[id_stop][::-1]
2819
2820
if True: # len(self.ids_vehs_alight_allocated[id_stop])==0:
2821
# all vehicles did arrive in alight position
2822
2823
# identify berth and vehicles ready to forward to boarding
2824
ids_veh_forward = []
2825
ids_berth_forward = []
2826
has_not_arrived = False
2827
for id_berth_alight, id_veh in zip(
2828
ids_berth_alight,
2829
berths.ids_veh[ids_berth_alight],
2830
):
2831
# print ' check alight->board for veh prt.%d'%id_veh,'at berth',id_berth_alight,berths.states[id_berth_alight], berths.states[id_berth_alight]==BERTHSTATES['free']
2832
2833
if id_veh >= 0: # is there a waiting vehicle
2834
2835
# make sure, that there are no vehicles which are
2836
# allocated for alight in front of the present vehicle
2837
ind = self.ids_vehs[id_stop].index(id_veh)
2838
# print ' check alloc veh in front',self.ids_vehs[id_stop][:ind],self.ids_vehs_alight_allocated[id_stop]
2839
2840
if not set(self.ids_vehs[id_stop][:ind]).isdisjoint(self.ids_vehs_alight_allocated[id_stop]):
2841
# print ' allocated veh in front! Stop forwarding'
2842
break
2843
2844
elif vehicles.is_completed_alighting(id_veh):
2845
ids_veh_forward.append(id_veh)
2846
ids_berth_forward.append(id_berth_alight)
2847
else:
2848
# print ' vehicle has prt.%d not finished alighting...'%id_veh
2849
# stop allocating berth in board zone
2850
# to prevent allocations behind non-allocated vehicles
2851
break
2852
2853
n_veh_alloc = len(ids_veh_forward)
2854
2855
if n_veh_alloc > 0:
2856
2857
if self.inds_berth_board_allocated[id_stop] > n_veh_alloc:
2858
queues = self.get_berthqueues(id_stop)
2859
else:
2860
queues = None
2861
2862
# print ' found %d veh at id_stop=%d to berth alloc with board alloc index %d'%(n_veh_alloc,id_stop, self.inds_berth_board_allocated [id_stop])
2863
# if queues is not None:
2864
# print ' queues',queues
2865
for id_berth_alight, id_veh in zip(
2866
ids_berth_forward,
2867
ids_veh_forward,
2868
):
2869
2870
id_berth_board = self.allocate_board(id_stop, n_veh_alloc, queues)
2871
# print ' try allocate id_veh=prt.%d for berth id_berth_board=%d'%(id_veh,id_berth_board)
2872
if id_berth_board >= 0:
2873
# print ' send vehicle id_veh %d to id_berth_board %d'%(id_veh,id_berth_board)#,berths.stoppositions[id_berth_board]
2874
n_veh_alloc -= 1
2875
berths.ids_veh[id_berth_alight] = -1
2876
2877
berths.states[id_berth_alight] = BERTHSTATES['free']
2878
2879
vehicles.control_stop_board(id_veh, id_stop, id_berth_board,
2880
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],
2881
position=berths.stoppositions[id_berth_board],
2882
)
2883
self.ids_vehs_board_allocated[id_stop].append(id_veh)
2884
2885
# if all allocated vehicles found their berth and all berths are free, then
2886
# reset alight allocation index
2887
# print ' check for reset of alight allocation index',self.inds_berth_alight_allocated[id_stop], len(self.ids_vehs_alight_allocated[id_stop])==0, np.all(berths.states[ids_berth_alight]==BERTHSTATES['free'])
2888
2889
if (len(self.ids_vehs_alight_allocated[id_stop]) == 0) & np.all(berths.states[ids_berth_alight] == BERTHSTATES['free']):
2890
2891
# print ' reset inds_berth_alight_allocated',self.inds_berth_alight_allocated[id_stop],'->',len(self.ids_berth_alight[id_stop])
2892
self.inds_berth_alight_allocated[id_stop] = len(self.ids_berth_alight[id_stop])
2893
2894
# try to allocate unallocated vehicles
2895
ids_veh_remove = []
2896
for id_veh in self.ids_vehs_toallocate[id_stop]:
2897
id_berth = self.allocate_alight(id_stop)
2898
if id_berth < 0:
2899
# allocation failed
2900
# print ' do nothing, vehicle %d continues to wait for allocation'%id_veh
2901
pass
2902
else:
2903
# command vehicle to go to berth for alighting
2904
# print ' send waiting vehicle id_veh %d to id_berth_alight %d'%(id_veh,id_berth)#,berths.stoppositions[id_berth]
2905
self.parent.prtvehicles.control_stop_alight(id_veh, id_stop, id_berth,
2906
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],
2907
position=self.get_berths().stoppositions[id_berth],
2908
)
2909
self.ids_vehs_alight_allocated[id_stop].append(id_veh)
2910
ids_veh_remove.append(id_veh)
2911
2912
for id_veh in ids_veh_remove:
2913
self.ids_vehs_toallocate[id_stop].remove(id_veh)
2914
2915
# else:
2916
# if len(self.ids_vehs_toallocate[id_stop])>0:
2917
# print ' HUSTON: there are vehs to allocate but cannot reset berthind'
2918
# print ' ids_vehs_toallocate',vehicles.ids_sumo[self.ids_vehs_toallocate[id_stop]]
2919
# print ' ids_vehs_toallocate',vehicles.ids_sumo[self.ids_vehs_toallocate[id_stop]]
2920
# print ' self.ids_vehs_alight_allocated[id_stop]',self.ids_vehs_alight_allocated[id_stop]
2921
# print ' berths.ids_veh',berths.ids_veh[ids_berth_alight]
2922
# print ' berths.states[ids_berth_alight]',berths.states[ids_berth_alight]
2923
2924
# check whether allocated vehicles arrived at boarding berths
2925
ids_veh_remove = []
2926
for id_veh in self.ids_vehs_board_allocated[id_stop]:
2927
# TODO: here we could also check vehicle position
2928
if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)):
2929
ids_veh_remove.append(id_veh)
2930
id_berth_board = vehicles.ids_berth[id_veh]
2931
berths.ids_veh[id_berth_board] = id_veh
2932
berths.states[id_berth_board] = BERTHSTATES['boarding']
2933
vehicles.board(id_veh,
2934
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop])
2935
2936
self.parent.vehicleman.indicate_trip_empty(id_veh, id_stop, simtime)
2937
# vehicle could become potentially the lead vehicle
2938
self.try_set_leadveh(id_stop, id_veh)
2939
2940
for id_veh in ids_veh_remove:
2941
self.ids_vehs_board_allocated[id_stop].remove(id_veh)
2942
2943
# if all allocated vehicles for board area
2944
# found their berth and all berths are free, then
2945
# reset allocation index
2946
# print ' check for reset of board berth', (self.inds_berth_board_allocated[id_stop] == 0),(len(self.ids_vehs_board_allocated[id_stop])==0), np.all(berths.states[ids_berth_board]==BERTHSTATES['free'])
2947
if (self.inds_berth_board_allocated[id_stop] == 0) & (len(self.ids_vehs_board_allocated[id_stop]) == 0):
2948
2949
if np.all(berths.states[ids_berth_board] == BERTHSTATES['free']):
2950
# print ' reset inds_berth_board_allocated to',len(self.ids_berth_board[id_stop])
2951
self.inds_berth_board_allocated[id_stop] = len(self.ids_berth_board[id_stop])
2952
# else:
2953
# print ' unfree boarding zone',berths.states[ids_berth_board]
2954
else:
2955
# print ' no reset: ids_vehs_board_allocated',self.ids_vehs_board_allocated[id_stop]
2956
# print ' berths.ids_veh',berths.ids_veh[ids_berth_board]
2957
# print ' berths.states[ids_berth_alight]',berths.states[ids_berth_board]
2958
pass
2959
# check for new person entering/left the station edge
2960
ids_person_sumo = set(traci.edge.getLastStepPersonIDs(id_edge_sumo))
2961
2962
n_enter = 0
2963
if ids_person_sumo_prev != ids_person_sumo:
2964
2965
if 0:
2966
print ' change\n id_person_sumo', ids_person_sumo
2967
print ' ids_person_sumo_prev', ids_person_sumo_prev
2968
# print ' dir(traci.person)',dir(traci.person)
2969
# for id_person_sumo in ids_person_sumo:
2970
# print ' id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo),traci.person.getVehicle(id_person_sumo)
2971
2972
# deal with persons who left the edge
2973
# NEW: this is done later when loaded vehicles are investigated
2974
2975
#ids_person_sumo_left = ids_person_sumo_prev.difference(ids_person_sumo)
2976
# print ' ids_person_sumo_left',ids_person_sumo_left
2977
# for id_person_sumo in ids_person_sumo_left:
2978
# print ' id_person_sumo_left pers',id_person_sumo,id_edge_sumo,traci.person.getRoadID(id_person_sumo),traci.person.getVehicle(id_person_sumo)
2979
# #print ' ids_person_sumo',ids_person_sumo
2980
# # tricky: if the person who left the edge id_edge_sumo
2981
# # shows still id_edge_sumo then this person is in a vehicle
2982
# if traci.person.getRoadID(id_person_sumo) == id_edge_sumo:
2983
# #print ' person boarded: pers',id_person_sumo,traci.person.getLanePosition(id_person_sumo)
2984
# self.ids_persons_sumo_boarded[id_stop].append(id_person_sumo)
2985
# self.waittimes_tot[id_stop] -= simtime - self.waittimes_persons[id_stop][id_person_sumo]
2986
# del self.waittimes_persons[id_stop][id_person_sumo]
2987
# self.numbers_person_wait[id_stop] -= 1
2988
2989
# deal with persons who entered the edge
2990
ids_person_sumo_entered = ids_person_sumo.difference(ids_person_sumo_prev)
2991
for id_person_sumo in ids_person_sumo_entered:
2992
# print ' entered id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo)
2993
if self.id_person_to_origs_dests.has_key(id_person_sumo):
2994
id_edge_sumo_dests = self.id_person_to_origs_dests[id_person_sumo]
2995
# check if person still has a PRT trip
2996
2997
if len(id_edge_sumo_dests) > 0:
2998
# check if next trip has origin edge equal to edge of this stop
2999
if id_edge_sumo_dests[0][2] == id_edge_sumo:
3000
# print ' add to waittimes_persons',id_person_sumo
3001
self.waittimes_persons[id_stop][id_person_sumo] = simtime
3002
n_enter += 1
3003
3004
# communicate person entry to vehman
3005
self.parent.vehicleman.note_person_entered(
3006
id_stop, id_person_sumo, id_edge_sumo_dests[0][1])
3007
3008
# else:
3009
# print 'WARNING: person %s starts with % insted of %s.'%(id_person_sumo,id_edge_sumo_dests[0][2],id_edge_sumo)
3010
3011
self.numbers_person_wait[id_stop] += n_enter
3012
self.ids_persons_sumo_prev[id_stop] = ids_person_sumo
3013
3014
self.waittimes_tot += self.numbers_person_wait*self.time_update.get_value()
3015
3016
timeconst_flow = self.timeconst_flow.get_value()
3017
self.flows_person[id_stop] = timeconst_flow*self.flows_person[id_stop] + \
3018
(1.0-timeconst_flow)*float(n_enter)/self.time_update.get_value()
3019
3020
if 0:
3021
for id_person_sumo in ids_person_sumo_prev:
3022
print ' ids_person_sumo=%s pos = %.2f ' % (id_person_sumo, traci.person.getLanePosition(id_person_sumo))
3023
# nomore print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop]
3024
3025
# check if boarding is completed in load area,
3026
# starting with last vehicle
3027
ids_berth_board = self.ids_berth_board[id_stop][::-1]
3028
for id_berth_board, id_veh in zip(
3029
ids_berth_board,
3030
berths.ids_veh[ids_berth_board],
3031
):
3032
if id_veh >= 0: # is there a waiting vehicle
3033
id_veh_sumo = vehicles.get_veh_if_completed_boarding(id_veh)
3034
if id_veh_sumo:
3035
id_person_sumo = self.init_trip_occupied(id_stop,
3036
id_berth_board,
3037
id_veh,
3038
id_veh_sumo,
3039
simtime)
3040
if id_person_sumo is not None:
3041
# do some statistics here
3042
self.waittimes_tot[id_stop] -= simtime - self.waittimes_persons[id_stop][id_person_sumo]
3043
del self.waittimes_persons[id_stop][id_person_sumo]
3044
self.numbers_person_wait[id_stop] -= 1
3045
3046
# check if there are passengers in the vehicles which wait for
3047
# alight allocate
3048
# TODO: can be replaced by a single instruction
3049
n_pax = 0
3050
for id_veh in self.ids_vehs_alight_allocated[id_stop]+self.ids_vehs_toallocate[id_stop]:
3051
if vehicles.states[id_veh] == VEHICLESTATES['occupiedtrip']:
3052
n_pax += 1
3053
# print ' n_pax' ,n_pax
3054
# check whether to foreward vehicles in boarding berth
3055
3056
# no foreward if all berth are free occupied vehicles
3057
if np.all(berths.states[ids_berth_board] == BERTHSTATES['free']):
3058
# print ' foreward all occupied id_stop,ids_berth_board',id_stop,ids_berth_board
3059
#self.foreward_boardzone(id_stop, ids_berth_board)
3060
self.times_lastboard[id_stop] = 10**4 # reset clock if all are free
3061
3062
# foreward if there are passengers in unallocated vehicles
3063
elif (self.numbers_person_wait[id_stop] == 0) & (n_pax > 0):
3064
# passengers arriving, no persons waiting
3065
# kick out immediately
3066
self.foreward_boardzone(id_stop, ids_berth_board, simtime)
3067
3068
# elif (self.numbers_person_wait[id_stop]>0) & (n_pax>0) & (self.times_lastboard[id_stop] == 10**4):
3069
elif ((self.numbers_person_wait[id_stop] > 0) | (n_pax > 0)) & (self.times_lastboard[id_stop] == 10**4):
3070
# passengers arriving but still persons boarding
3071
# reset kick-out counter
3072
self.times_lastboard[id_stop] = simtime
3073
3074
elif simtime - self.times_lastboard[id_stop] > self.time_kickout.get_value():
3075
# print ' call foreward_boardzone timeout',process.simtime,self.times_lastboard[id_stop],process.simtime - self.times_lastboard[id_stop]
3076
self.foreward_boardzone(id_stop, ids_berth_board, simtime)
3077
3078
# check whether a programmed vehicle can be started
3079
if self.types[id_stop] == STOPTYPES['group']:
3080
self.start_vehicles_platoon(id_stop, process)
3081
else:
3082
self.start_vehicles(id_stop, process)
3083
3084
def start_vehicles(self, id_stop, process):
3085
print 'start_vehicles=\n', self.ids_vehs_prog[id_stop]
3086
i = 0
3087
vehicles = self.parent.prtvehicles
3088
ids_vehs_prog = self.ids_vehs_prog[id_stop]
3089
for time_start, id_veh, id_stop_target, is_started in ids_vehs_prog:
3090
if process.simtime > time_start:
3091
if not is_started:
3092
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3093
if traci.vehicle.isStopped(id_veh_sumo):
3094
# print ' route prt.%d from stop %d to %d'%(id_veh,id_stop, id_stop_target)
3095
route, duration = self.route_stop_to_stop(id_stop, id_stop_target)
3096
# print ' route prt.%d from %d to %d'%(id_veh,self.ids_stop_to_ids_edge[id_stop],self.ids_stop_to_ids_edge[id_stop_target]),route
3097
vehicles.reschedule_trip(id_veh,
3098
route_sumo=self.get_scenario().net.edges.ids_sumo[route]
3099
)
3100
ids_vehs_prog[i][3] = True
3101
#self.parent.prtvehicles.control_slow_down( id_veh, speed = 6.0/3.6)
3102
# print ' limit MaxSpeed',id_veh_sumo
3103
traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
3104
i += 1
3105
3106
def route_stop_to_stop(self, id_stop_from, id_stop_to):
3107
# route
3108
return self.parent.get_route(self.ids_stop_to_ids_edge[id_stop_from],
3109
self.ids_stop_to_ids_edge[id_stop_to]
3110
)
3111
3112
def start_vehicles_platoon(self, id_stop, process, timeout_platoon=40, n_platoon_max=8):
3113
# print 'start_vehicles_platoon id_stop, times_plat_accumulate',id_stop,self.times_plat_accumulate[id_stop]
3114
# print ' ids_vehs_prog=\n',self.ids_vehs_prog[id_stop]
3115
3116
if self.times_plat_accumulate[id_stop] < 0:
3117
# print ' accumulation has not even started'
3118
return
3119
3120
vehicles = self.parent.prtvehicles
3121
ids_vehs_prog = self.ids_vehs_prog[id_stop]
3122
inds_platoon = []
3123
i = 0 # len(ids_vehs_prog)
3124
id_veh_nextplatoon = -1
3125
for time_start, id_veh, id_stop_target, is_started in ids_vehs_prog: # [::-1]:
3126
3127
if not is_started:
3128
if len(inds_platoon) == 0:
3129
# check if first vehicle in platoon is stopped
3130
if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)):
3131
inds_platoon.append(i)
3132
else:
3133
break
3134
else:
3135
# append to platoon
3136
inds_platoon.append(i)
3137
3138
i += 1
3139
3140
# print ' trigger platoon?', inds_platoon,len(inds_platoon),n_platoon_max,process.simtime - self.times_plat_accumulate[id_stop],timeout_platoon
3141
if len(inds_platoon) == 0:
3142
return
3143
3144
if (process.simtime - self.times_plat_accumulate[id_stop] > timeout_platoon)\
3145
| (len(inds_platoon) >= n_platoon_max):
3146
3147
# platoon release triggered
3148
self._trigger_platoon(id_stop, inds_platoon)
3149
3150
def get_decompressoredge(self, route):
3151
"""
3152
Returns first occurance of a decompressoredge edge route from
3153
id_stop to id_stop_target.
3154
Returns -1 if nor decompressoredge is found.
3155
"""
3156
# print 'get_decompressoredge route',route
3157
# print ' self.ids_detectoredge_decompr',self.ids_detectoredge_decompr
3158
set_detectoredge = self.ids_detectoredge_decompr.intersection(set(route))
3159
# print ' set_detectoredge',set_detectoredge
3160
if len(set_detectoredge) == 0:
3161
return -1
3162
else:
3163
#ids_detectoredge = list(set_detectoredge)
3164
id_detectoredge_first = -1
3165
ind_min = 10**8
3166
for id_detectoredge in set_detectoredge:
3167
if route.index(id_detectoredge) < ind_min:
3168
id_detectoredge_first = id_detectoredge
3169
return id_detectoredge_first
3170
3171
def _trigger_platoon(self, id_stop, inds_platoon):
3172
# print 'trigger_platoon inds_platoon',inds_platoon
3173
ids_vehs_prog = self.ids_vehs_prog[id_stop]
3174
vehicles = self.parent.prtvehicles
3175
3176
self.times_plat_accumulate[id_stop] = -1
3177
3178
time_start_pre, id_veh_pre, id_stop_target_pre, is_prog_pre = ids_vehs_prog[inds_platoon[0]]
3179
vehicles.reschedule_trip(id_veh_pre, self.ids_stop_to_ids_edge_sumo[id_stop_target_pre])
3180
#self.parent.prtvehicles.control_slow_down( id_veh_pre, speed = 6.0/3.6)
3181
id_veh_pre_sumo = vehicles.get_id_sumo(id_veh_pre)
3182
3183
traci.vehicle.setMaxSpeed(id_veh_pre_sumo, 6.0/3.6)
3184
3185
ids_vehs_prog[inds_platoon[0]][3] = True
3186
# one vehicle platoon, no followers
3187
if len(inds_platoon) > 1:
3188
# try to concatenate followers
3189
3190
# search first detectoredge in route
3191
route_pre, traveltime = self.route_stop_to_stop(id_stop, id_stop_target_pre)
3192
id_detectoredge_pre = self.get_decompressoredge(route_pre)
3193
3194
for i in xrange(1, len(inds_platoon)):
3195
#time_start_pre, id_veh_pre, id_stop_target_pre, is_prog_pre = ids_vehs_prog[inds_platoon[i-1]]
3196
time_start, id_veh, id_stop_target, is_prog = ids_vehs_prog[inds_platoon[i]]
3197
route, traveltime = self.route_stop_to_stop(id_stop, id_stop_target)
3198
id_detectoredge = self.get_decompressoredge(route)
3199
id_veh_sumo = vehicles.get_id_sumo(id_veh)
3200
3201
# print ' check prt.%d'%ids_vehs_prog[inds_platoon[i]][1],'with leader prt.%d'%ids_vehs_prog[inds_platoon[i-1]][1],'same target',id_stop_target == id_stop_target_pre
3202
3203
# print ' route',route,'route_pre',route_pre
3204
# print ' id_detectoredge',id_detectoredge,'id_detectoredge_pre',id_detectoredge_pre
3205
# if id_stop_target == id_stop_target_pre:
3206
3207
# for platooning either same decompressor or same target
3208
if ((id_detectoredge == id_detectoredge_pre) & (id_detectoredge_pre != -1))\
3209
| (id_stop_target == id_stop_target_pre):
3210
# check also if leader stands immediately in from of follower
3211
3212
info = traci.vehicle.getLeader(id_veh_sumo, dist=10.0)
3213
# print ' check vehicle in front info',info
3214
if info is not None:
3215
id_veh_pre_sumo, dist = info
3216
if dist < 5.0:
3217
# print ' concatenate',id_veh,'with',id_veh_pre
3218
self.parent.prtvehicles.concatenate(id_veh, id_veh_pre)
3219
3220
# schedule and tell that vehicle has been scheduled
3221
self.parent.prtvehicles.reschedule_trip(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target])
3222
ids_vehs_prog[inds_platoon[i]][3] = True
3223
3224
id_detectoredge_pre = id_detectoredge
3225
route_pre = route
3226
#time_start_pre = time_start
3227
id_veh_pre = id_veh
3228
id_stop_target_pre = id_stop_target
3229
#is_prog_pre = is_prog
3230
3231
# print ' limit MaxSpeed',id_veh_sumo
3232
traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
3233
#self.parent.prtvehicles.control_slow_down( id_veh, speed = 6.0/3.6)
3234
3235
def try_set_leadveh(self, id_stop, id_veh):
3236
3237
if self.ids_veh_lead[id_stop] >= 0:
3238
# print 'try_set_leadveh leader already defined',id_stop,id_veh,self.ids_veh_lead[id_stop]
3239
return False
3240
else:
3241
ind_queue = self.ids_vehs[id_stop].index(id_veh)
3242
# print 'try_set_leadveh id_stop, id_veh,ind_queue',id_stop, 'prt.%d'%id_veh,ind_queue,len(self.ids_vehs[id_stop]),len(self.ids_vehs_prog[id_stop])
3243
3244
if ind_queue == 0: # len(self.ids_vehs[id_stop])-1:
3245
# print ' id_veh is new leader because last position',self.ids_vehs[id_stop].index(id_veh)
3246
# print ' ids_vehs',self.ids_vehs[id_stop]
3247
self.set_leadveh(id_stop, id_veh)
3248
return True
3249
3250
elif len(self.ids_vehs_prog[id_stop]) == ind_queue:
3251
# print ' id_veh is new leader because all vehicles in front are already programmed'
3252
self.set_leadveh(id_stop, id_veh)
3253
return True
3254
# elif len(self.ids_vehs_prog[id_stop])>0:
3255
# if (self.ids_vehs[id_stop][ind_queue-1] == self.ids_vehs_prog[id_stop][-1][1]) :
3256
# print ' id_veh is new leader because next vehicle %d is programmed'%(self.ids_vehs[id_stop][ind_queue-1],)
3257
# self.set_leadveh(id_stop, id_veh)
3258
# return True
3259
# else:
3260
# return False
3261
3262
else:
3263
return False
3264
3265
def set_leadveh(self, id_stop, id_veh):
3266
# print 'set_leadveh id_stop=%d, prt.%d'%( id_stop,id_veh)
3267
self.ids_veh_lead[id_stop] = id_veh
3268
3269
def program_leadveh(self, id_stop, id_veh, id_stop_target, time_start):
3270
# print 'program_leadveh prt.%d from id_stop %d to id_stop_target %d at %d'%(id_veh, id_stop,id_stop_target,time_start),'check leader',id_veh == self.ids_veh_lead[id_stop]
3271
3272
# check also if occupied in the meanwhile?? need to know emptytrip or not...
3273
if id_veh == self.ids_veh_lead[id_stop]:
3274
# check in vehman:if self.parent.prtvehicles.is_still_empty(id_veh):
3275
3276
if self.parent.prtvehicles.states[id_veh] == VEHICLESTATES['boarding']:
3277
id_berth_board = self.parent.prtvehicles.ids_berth[id_veh]
3278
self.init_trip_empty(id_stop, id_berth_board, id_veh, time_start, is_ask_vehman=False)
3279
3280
self.ids_veh_lead[id_stop] = -1
3281
3282
# format for programmed vehicle list:
3283
# [time_start, id_veh, id_stop_target,is_started]
3284
self.ids_vehs_prog[id_stop].append([time_start, id_veh, id_stop_target, False])
3285
3286
if self.types[id_stop] == STOPTYPES['group']:
3287
# in platoon mode...
3288
# set a stop for this vehicle if there are only started, programmed
3289
# vehicles in front , or no vehicle
3290
3291
# check if this vehicle needs to stop in front of the stopline
3292
# in order to hold up other vehicles in the platoon
3293
# print ' check stopline',len(self.ids_vehs_prog[id_stop])
3294
# print ' ids_vehs_prog ',self.ids_vehs_prog[id_stop]
3295
is_stop = True
3296
for i in range(len(self.ids_vehs_prog[id_stop])-2, -1, -1):
3297
# print ' check prt.%d'%self.ids_vehs_prog[id_stop][i][1],'started',self.ids_vehs_prog[id_stop][i][3]
3298
if not self.ids_vehs_prog[id_stop][i][3]: # is already started
3299
is_stop = False
3300
break
3301
3302
if is_stop:
3303
# make this vehicle stop at stopline and reset platoon timer
3304
self.parent.prtvehicles.set_stop(
3305
id_veh, self.ids_stop_to_ids_edge_sumo[id_stop], self.stoplines[id_stop])
3306
self.times_plat_accumulate[id_stop] = time_start
3307
3308
# try make previous vehicle the lead vehicle
3309
ind_queue = self.ids_vehs[id_stop].index(id_veh)
3310
# print ' ids_vehs',self.ids_vehs[id_stop]
3311
# print ' ind_queue,queuelen,ok',ind_queue,len(self.ids_vehs[id_stop]),len(self.ids_vehs[id_stop]) > ind_queue+1
3312
if len(self.ids_vehs[id_stop]) > ind_queue+1:
3313
id_veh_newlead = self.ids_vehs[id_stop][ind_queue+1]
3314
# print ' id_veh_newlead, state',id_veh_newlead, self.parent.prtvehicles.states[id_veh_newlead]
3315
if self.parent.prtvehicles.states[id_veh_newlead] in LEADVEHICLESTATES:
3316
self.set_leadveh(id_stop, id_veh_newlead)
3317
3318
# print ' new lead veh prt.%d'%(self.ids_veh_lead[id_stop],)
3319
return True
3320
3321
else:
3322
print ' no leader prt.%d exists' % (id_veh,)
3323
return False
3324
3325
def init_trip_occupied(self, id_stop, id_berth, id_veh, id_veh_sumo, simtime):
3326
# TODO: actually a berth method??
3327
berths = self.get_berths()
3328
3329
#id_veh_sumo = self.parent.prtvehicles.get_id_sumo(id_veh)
3330
n_pax = traci.vehicle.getPersonNumber(id_veh_sumo)
3331
# print 'init_trip_occupied', id_stop, id_berth, 'veh=%s'%id_veh_sumo,'simtime',simtime,'n_pax',n_pax
3332
3333
# identify whic of the boarding persons is in the
3334
# vehicle which completed boarding
3335
dist_min = np.inf
3336
id_person_sumo_inveh = None
3337
stoppos = berths.stoppositions[id_berth]
3338
3339
for id_person_sumo in self.ids_persons_sumo_prev[id_stop]:
3340
# print ' check veh of person',id_person_sumo,traci.person.getVehicle(id_person_sumo),id_veh_sumo
3341
3342
# here we check whether person id_person_sumo at stop id_stop
3343
# is already sitting in vehicle id_veh_sumo
3344
if traci.person.getVehicle(id_person_sumo) == id_veh_sumo:
3345
id_person_sumo_inveh = id_person_sumo
3346
3347
#d = abs(stoppos - traci.person.getLanePosition(id_person_sumo))
3348
# if d<dist_min:
3349
# dist_min = d
3350
# id_person_sumo_inveh = id_person_sumo
3351
3352
if id_person_sumo_inveh is not None:
3353
print ' found person %s in veh %s' % (id_person_sumo_inveh, id_veh_sumo)
3354
3355
# program vehicle to person's destination
3356
# print ' found person,origs_dests',id_person_sumo_inveh,self.id_person_to_origs_dests[id_person_sumo_inveh]
3357
id_stop_orig, id_stop_dest, id_edge_sumo_from, id_edge_sumo_to = \
3358
self.id_person_to_origs_dests[id_person_sumo_inveh].pop(0)
3359
# print ' found person', id_person_sumo_inveh,'from', id_stop_orig, id_edge_sumo_from,' to' , id_edge_sumo_to, id_stop_dest
3360
3361
stopline = self._get_stopline(id_stop, simtime)
3362
# print ' simtime', simtime
3363
3364
self.parent.prtvehicles.init_trip_occupied(
3365
id_veh, self.ids_stop_to_ids_edge_sumo[id_stop],
3366
stopline,
3367
)
3368
3369
# self.ids_persons_sumo_boarded[id_stop].remove(id_person_sumo_inveh)
3370
self.times_lastboard[id_stop] = simtime
3371
berths.states[id_berth] = BERTHSTATES['free']
3372
berths.ids_veh[id_berth] = -1
3373
# self.ids_vehs_outset[id_stop].add(id_veh)
3374
self.try_set_leadveh(id_stop, id_veh)
3375
self.parent.vehicleman.init_trip_occupied(id_veh, id_stop, id_stop_dest, simtime)
3376
return id_person_sumo_inveh
3377
3378
else:
3379
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)
3380
return None
3381
3382
def _get_stopline(self, id_stop, simtime):
3383
if self.types[id_stop] == STOPTYPES['group']:
3384
# print ' platooning...',id_stop,simtime
3385
if self.times_plat_accumulate[id_stop] < 0: # len(self.ids_vehs_prog[id_stop]) == 0:
3386
# print ' first in platoon-> stop it at exit-line',simtime
3387
#stopline = self.stoplines[id_stop]
3388
# actually not clear who will arrive first at the stopline
3389
# therefore do not stop. Stop must be set duruing rescheduling
3390
stopline = None
3391
self.times_plat_accumulate[id_stop] = simtime
3392
# print ' times_plat_accumulate',self.times_plat_accumulate[id_stop],simtime
3393
else:
3394
# print ' not first, let it approach previous veh.'
3395
stopline = None
3396
3397
else:
3398
# print ' no platooning: all vehicles stop and wait for start'
3399
stopline = self.stoplines[id_stop]
3400
# print ' times_plat_accumulate',self.times_plat_accumulate[id_stop],'simtime',simtime
3401
# print ' stopline',stopline
3402
return stopline
3403
3404
def init_trip_empty(self, id_stop, id_berth, id_veh, simtime, is_ask_vehman=True):
3405
# print 'Stops.init_trip_empty id_stop, id_berth, id_veh, is_ask_vehman', id_stop, id_berth, 'prt.%d'%id_veh, is_ask_vehman,'simtime',simtime
3406
# TODO: actually a berth method??
3407
berths = self.get_berths()
3408
3409
berths.states[id_berth] = BERTHSTATES['free']
3410
berths.ids_veh[id_berth] = -1
3411
3412
# print ' proceed to stopline',self.stoplines[id_stop]
3413
stopline = self._get_stopline(id_stop, simtime)
3414
self.parent.prtvehicles.init_trip_empty(
3415
id_veh,
3416
self.ids_stop_to_ids_edge_sumo[id_stop],
3417
stopline)
3418
3419
if is_ask_vehman:
3420
self.try_set_leadveh(id_stop, id_veh)
3421
#id_stop_target = self.parent.vehicleman.init_trip_empty(id_veh, id_stop)
3422
self.parent.vehicleman.init_trip_empty(id_veh, id_stop, simtime)
3423
3424
# print 'init_trip_empty for',id_veh,' from',id_stop,'to',id_stop_target,id_edge_sumo_target
3425
#self.parent.prtvehicles.init_trip_empty(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target])
3426
3427
# else:
3428
# self.parent.prtvehicles.init_trip_empty(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop], -1)
3429
3430
# self.ids_vehs_outset[id_stop].add(id_veh)
3431
3432
def foreward_boardzone(self, id_stop, ids_berth_board, simtime):
3433
print 'foreward_boardzone', id_stop, ids_berth_board, 'simtime', simtime
3434
berths = self.get_berths()
3435
#ids_berth_board = self.ids_berth_board[id_stop][::-1]
3436
# inds_o berths.states[ids_berth_board] != BERTHSTATES['free']
3437
for id_berth, state in zip(ids_berth_board, berths.states[ids_berth_board]):
3438
# print ' id_berth,boarding?,id_veh',id_berth, state== BERTHSTATES['boarding'],berths.ids_veh[id_berth]
3439
if state == BERTHSTATES['boarding']:
3440
self.init_trip_empty(id_stop, id_berth, berths.ids_veh[id_berth], simtime)
3441
3442
self.times_lastboard[id_stop] = 10**4 # reset last board counter
3443
3444
def enter(self, id_stop, id_veh):
3445
print 'enter id_stop, id_veh', id_stop, 'prt.%d' % id_veh
3446
3447
self.parent.prtvehicles.decatenate(id_veh)
3448
3449
self.ids_vehs[id_stop].append(id_veh)
3450
3451
# tell vehman that veh arrived
3452
#self.numbers_veh_arr[id_stop] -= 1
3453
self.parent.vehicleman.conclude_trip(id_veh, id_stop)
3454
3455
self.numbers_veh[id_stop] += 1
3456
id_berth = self.allocate_alight(id_stop)
3457
if id_berth < 0:
3458
# print ' allocation failed, command vehicle to slow down and wait for allocation'
3459
self.ids_vehs_toallocate[id_stop].append(id_veh)
3460
self.parent.prtvehicles.control_slow_down(id_veh)
3461
else:
3462
# command vehicle to go to berth for alighting
3463
id_veh_sumo = self.parent.prtvehicles.ids_sumo[id_veh] # for debug only
3464
# print ' id_veh_sumo',id_veh_sumo
3465
#pos = traci.vehicle.getLanePosition(id_veh_sumo)
3466
if 0:
3467
print ' send entering vehicle id_veh %d, pos=%.2f to id_berth_alight %d at pos %.2fm' % (id_veh, traci.vehicle.getLanePosition(id_veh_sumo), id_berth, self.get_berths().stoppositions[id_berth])
3468
print ' ids_ghost', self.parent.prtvehicles.ids_ghosts[id_veh]
3469
print ' ids_leader', self.parent.prtvehicles.ids_leader[id_veh]
3470
print ' ids_follower', self.parent.prtvehicles.ids_follower[id_veh]
3471
3472
self.parent.prtvehicles.control_stop_alight(id_veh, id_stop, id_berth,
3473
id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],
3474
position=self.get_berths().stoppositions[id_berth],
3475
)
3476
self.ids_vehs_alight_allocated[id_stop].append(id_veh)
3477
3478
def exit(self, id_stop, id_veh):
3479
# print 'exit prt.%d at stop %d'%(id_veh,id_stop)
3480
self.ids_vehs[id_stop].remove(id_veh)
3481
#id_stop_target = self.parent.vehicleman.start_trip(id_veh, id_stop)
3482
#self.parent.prtvehicles.reschedule_trip(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target])
3483
#ind_veh = -1
3484
# print ' ids_vehs_prog=\n',self.ids_vehs_prog[id_stop]
3485
i = 0
3486
for time_start, id_veh_prog, id_stop_target, is_prog in self.ids_vehs_prog[id_stop]:
3487
if id_veh_prog == id_veh:
3488
self.ids_vehs_prog[id_stop].pop(i)
3489
break
3490
i = +1
3491
3492
# self.ids_vehs_prog[id_stop].remove(id_veh)
3493
3494
self.numbers_veh[id_stop] -= 1
3495
3496
def allocate_alight(self, id_stop):
3497
3498
# print 'allocate_alight',id_stop
3499
#self.inds_berth_alight_allocated [id_stop] = len(self.ids_berth_alight[id_stop])
3500
ind_berth = self.inds_berth_alight_allocated[id_stop]
3501
3502
if ind_berth == 0:
3503
# no free berth :(
3504
return -1
3505
else:
3506
ind_berth -= 1
3507
self.inds_berth_alight_allocated[id_stop] = ind_berth
3508
return self.ids_berth_alight[id_stop][ind_berth]
3509
3510
def allocate_board(self, id_stop, n_alloc, queues):
3511
"""
3512
Return successive berth ID to be allocated for boarding
3513
at given stop ID.
3514
n_alloc is the number of vehicles which remain to be
3515
allocated.
3516
"""
3517
3518
#self.inds_berth_alight_allocated [id_stop] = len(self.ids_berth_alight[id_stop])
3519
ind_berth = self.inds_berth_board_allocated[id_stop]
3520
# print 'allocate_board id_stop, n_alloc,ind_berth',id_stop, n_alloc,ind_berth
3521
if ind_berth == 0:
3522
# no free berth :(
3523
return -1
3524
else:
3525
if queues is None:
3526
3527
# less or equal allocation positions in board zone
3528
# then vehicles to be allocated
3529
ind_berth -= 1
3530
# print ' allocate in order ind_berth=',ind_berth
3531
self.inds_berth_board_allocated[id_stop] = ind_berth
3532
return self.ids_berth_board[id_stop][ind_berth]
3533
else:
3534
# there are more allocation positions in board zone
3535
# then vehicles to be allocated
3536
ind_berth -= 1
3537
id_berth = self.ids_berth_board[id_stop][ind_berth]
3538
# print ' check queue, start with ind_berth=%d,n_alloc=%d, id_berth=%d, queue=%d, pos=%.2fm'%(ind_berth,n_alloc,id_berth,queues[id_berth],self.get_berths().stoppositions[id_berth]),queues[id_berth] == 0,ind_berth >= n_alloc
3539
while (queues[id_berth] == 0) & (ind_berth >= n_alloc):
3540
ind_berth -= 1
3541
id_berth = self.ids_berth_board[id_stop][ind_berth]
3542
# print ' check queue, start with ind_berth=%d,n_alloc=%d, id_berth=%d, queue=%d, pos=%.2fm'%(ind_berth,n_alloc,id_berth,queues[id_berth],self.get_berths().stoppositions[id_berth]),queues[id_berth] == 0,ind_berth >= n_alloc
3543
3544
self.inds_berth_board_allocated[id_stop] = ind_berth
3545
return id_berth
3546
3547
def get_berthqueues(self, id_stop):
3548
# currently not used
3549
# print 'get_berthqueues',id_stop
3550
# TODO: use stop angle and person angle to detect waiting persons
3551
ids_berth_board = self.ids_berth_board[id_stop]
3552
stoppositions = self.get_berths().stoppositions[ids_berth_board]
3553
counters = np.zeros(len(stoppositions), dtype=np.int32)
3554
# print ' stoppositions',stoppositions
3555
for id_person_sumo in self.waittimes_persons[id_stop].keys():
3556
position = traci.person.getLanePosition(id_person_sumo)
3557
# print ' position',position
3558
dists = np.abs(stoppositions-position)
3559
# print ' dists',dists,np.any(dists<5)
3560
if np.any(dists < 0.8):
3561
ind_berth = np.argmin(dists)
3562
counters[ind_berth] += 1
3563
3564
queues = {}
3565
for id_berth, count in zip(ids_berth_board, counters):
3566
queues[id_berth] = count
3567
3568
# print ' queues=\n',queues
3569
return queues
3570
3571
def make_from_net(self):
3572
"""
3573
Make prt stop database from PT stops in network.
3574
"""
3575
print 'make_from_net'
3576
self.clear()
3577
net = self.get_scenario().net
3578
ptstops = net.ptstops
3579
3580
ids_ptstop = ptstops.get_ids()
3581
id_mode_prt = self.parent.id_prtmode
3582
3583
#ids_edges = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]
3584
#ids_lanes = net.edges.ids_lanes[ids_edges]
3585
ids_lane = ptstops.ids_lane[ids_ptstop]
3586
#edgelengths = net.edges.lengths
3587
3588
for id_stop, id_lane, position_from, position_to in zip(
3589
ids_ptstop,
3590
# ids_lanes,
3591
ids_lane,
3592
ptstops.positions_from[ids_ptstop],
3593
ptstops.positions_to[ids_ptstop],
3594
):
3595
# get allowed modes of lane with index 1
3596
modes_allow = net.lanes.ids_modes_allow[id_lane]
3597
# print ' check id_stop, modes_allow, position_from, position_to',id_stop, modes_allow, position_from, position_to
3598
if id_mode_prt in modes_allow:
3599
self.make(id_stop,
3600
position_from,
3601
position_to)
3602
3603
self.parent.make_fstar(is_update=True)
3604
self.parent.make_times_stop_to_stop()
3605
3606
def make(self, id_ptstop, position_from, position_to):
3607
"""
3608
Initialize a new prt stop and generate berth.
3609
"""
3610
id_stop = self.add_row(ids_ptstop=id_ptstop)
3611
ids_berth = self.get_berths().make(id_stop, position_from=position_from,
3612
position_to=position_to)
3613
n_berth = len(ids_berth)
3614
n_berth_alight = int(0.5*n_berth)
3615
n_berth_board = n_berth-n_berth_alight
3616
self.ids_berth_alight[id_stop] = ids_berth[0:n_berth_alight]
3617
self.ids_berth_board[id_stop] = ids_berth[n_berth_alight:n_berth]
3618
return id_stop
3619
3620
3621
class VehicleAdder(Process):
3622
def __init__(self, vehicles, logger=None, **kwargs):
3623
print 'VehicleAdder.__init__', vehicles, vehicles.parent.get_ident()
3624
self._init_common('vehicleadder', name='Vehicle adder',
3625
logger=logger,
3626
info='Add vehicles to PRT stops of network.',
3627
)
3628
self._vehicles = vehicles
3629
3630
attrsman = self.set_attrsman(cm.Attrsman(self))
3631
3632
self.n_vehicles = attrsman.add(cm.AttrConf('n_vehicles', kwargs.get('n_vehicles', -1),
3633
groupnames=['options'],
3634
perm='rw',
3635
name='Number of vehicles',
3636
info='Number of PRT vehicles to be added to the network. Use -1 to fill all present PRT stations.',
3637
))
3638
3639
def do(self):
3640
# print 'VehicleAdder.do'
3641
self._vehicles.add_to_net(n=self.n_vehicles)
3642
return True
3643
3644
3645
class PrtVehicles(am.ArrayObjman):
3646
3647
def __init__(self, ident, prtservices, **kwargs):
3648
# print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1')
3649
self._init_objman(ident=ident,
3650
parent=prtservices,
3651
name='PRT Veh.',
3652
info='PRT vehicle database. These are shared vehicles.',
3653
version=0.1,
3654
**kwargs)
3655
3656
self._init_attributes()
3657
3658
def _init_attributes(self):
3659
vtypes = self.get_scenario().demand.vtypes
3660
net = self.get_scenario().net
3661
3662
version = self.get_version()
3663
if version < 0.1:
3664
self.delete('speed_max')
3665
self.delete('time_emergency')
3666
self.delete('decel_comfort')
3667
self.delete('decel_emergency')
3668
self.delete('speed_max')
3669
3670
self.add(cm.AttrConf('time_update', 0.5,
3671
groupnames=['parameters'],
3672
name='Update time',
3673
info="Update time for traci controlled vehicles, es. at merge points.",
3674
unit='s',
3675
))
3676
3677
self.add(cm.AttrConf('speedmode_follower', 1,
3678
groupnames=['parameters'],
3679
name='Follower speed mode',
3680
info="""Follower speed mode. The single bits have the following meaning:
3681
bit0: Regard safe speed
3682
bit1: Regard maximum acceleration
3683
bit2: Regard maximum deceleration -
3684
bit3: Regard right of way at intersections
3685
bit4: Brake hard to avoid passing a red light
3686
""",
3687
))
3688
3689
self.add(cm.AttrConf('factor_speed_follower', 2.0,
3690
groupnames=['parameters'],
3691
name='Follower speed factor',
3692
info="""Follower speed factor.""",
3693
))
3694
3695
self.add(cm.AttrConf('accel_follower', 5.0,
3696
groupnames=['parameters'],
3697
name='Follower acceleration',
3698
info="Follower acceleration.",
3699
unit='m/s^2',
3700
))
3701
3702
self.add(cm.AttrConf('decel_follower', 5.0,
3703
groupnames=['parameters'],
3704
name='Follower deceleration',
3705
info="Follower deceleration.",
3706
unit='m/s^2',
3707
))
3708
3709
self.add(cm.AttrConf('decel_emergency_follower', 5.0,
3710
groupnames=['parameters'],
3711
name='Follower Emergency deceleration',
3712
info="Follower Emergency deceleration.",
3713
unit='m/s^2',
3714
))
3715
3716
self.add(cm.AttrConf('dist_min_follower', 0.0,
3717
groupnames=['parameters'],
3718
name='Follower min. distance',
3719
info="Follower minimum distance",
3720
unit='m',
3721
))
3722
3723
self.add(cm.AttrConf('tau_follower', 0.0,
3724
groupnames=['parameters'],
3725
name='Follower reaction time',
3726
info="Follower reaction time.",
3727
unit='s',
3728
))
3729
3730
self.add(cm.AttrConf('n_ghosts_max', 4,
3731
groupnames=['parameters'],
3732
name='Max ghosts',
3733
info="Maximum number of ghost vehicles. Ghost vehicles are used in merge controls.",
3734
))
3735
3736
# TODO: add/update vtypes here
3737
self.add_col(SumoIdsConf('Veh', xmltag='id'))
3738
3739
id_vtype = self.make_vtype(is_renew=version < 0.1)
3740
3741
if not hasattr(self, 'ids_vtype'):
3742
3743
self.add_col(am.IdsArrayConf('ids_vtype', vtypes,
3744
id_default=id_vtype,
3745
groupnames=['state'],
3746
name='Veh. type',
3747
info='PRT vehicle type.',
3748
#xmltag = 'type',
3749
))
3750
else:
3751
# this imposes parameters to alresdy existing data
3752
self.ids_vtype[self.get_ids()] = id_vtype
3753
3754
self.add_col(am.ArrayConf('states', default=VEHICLESTATES['init'],
3755
groupnames=['_private'],
3756
dtype=np.int32,
3757
choices=VEHICLESTATES,
3758
name='state',
3759
info='State of vehicle.',
3760
))
3761
3762
# self.add_col(am.IdsArrayConf( 'ids_targetprtstop', self.parent.prtstops,
3763
# groupnames = ['parameters'],
3764
# name = 'Target stop ID',
3765
# info = 'ID of current target PRT stop.',
3766
# ))
3767
3768
self.add_col(am.IdsArrayConf('ids_currentedge', net.edges,
3769
groupnames=['state'],
3770
name='Current edge ID',
3771
info='Edge ID of most recent reported position.',
3772
))
3773
3774
# self.add_col(am.IdsArrayConf( 'ids_targetedge', net.edges,
3775
# groupnames = ['state'],
3776
# name = 'Target edge ID',
3777
# info = 'Target edge ID to be reached. This can be either intermediate target edges (), such as a compressor station.',
3778
# ))
3779
3780
self.set_version(0.1)
3781
3782
def _init_constants(self):
3783
3784
self.do_not_save_attrs([
3785
'length',
3786
'tau', 'ids_berth',
3787
'are_update', 'velocities',
3788
'odos', 'ids_ghosts',
3789
'diststomerge0', 'diststomerge0_ghosts',
3790
'dists0', 'odos0_vehicles', 'odos0_ghosts',
3791
'ids_leader', 'ids_follower', 'lengths_plat',
3792
])
3793
3794
def get_net(self):
3795
return self.parent.get_scenario().net
3796
3797
def make_vtype(self, is_renew=False):
3798
print 'make_vtype PRT'
3799
vtypes = self.get_scenario().demand.vtypes
3800
prttype = 'PRT'
3801
3802
if (not vtypes.ids_sumo.has_index(prttype)) | is_renew:
3803
if vtypes.ids_sumo.has_index(prttype):
3804
vtypes.del_row(vtypes.ids_sumo.get_id_from_index(prttype))
3805
id_vtype = vtypes.add_vtype(prttype,
3806
accel=2.5,
3807
decel=2.5,
3808
decel_apparent=2.5, # followe should not be freightened
3809
decel_emergency=5.0,
3810
sigma=0.0,
3811
length=3.5,
3812
width=1.6,
3813
height=1.7,
3814
number_persons=1,
3815
capacity_persons=1,
3816
dist_min=0.3,
3817
tau=0.5,
3818
speed_max=60.0/3.6,
3819
factor_speed=0.9,
3820
deviation_speed=0.1, # slight deviation for better following
3821
# emissionclass= 'HBEFA3/zero',# defined in electricity model
3822
id_mode=self.parent.id_prtmode, # specifies mode for demand
3823
color=np.array((255, 240, 0, 255), np.float32)/255.0,
3824
shape_gui='evehicle',
3825
times_boarding=1.5,
3826
times_loading=20.0,
3827
sublane_alignment_lat='center',
3828
sublane_speed_max_lat=0.5,
3829
sublane_gap_min_lat=0.24,
3830
sublane_alignment_eager=1000000.0,
3831
#
3832
power_max=5000.0,
3833
mass=800.0,
3834
area_front_surface=3.5*1.6,
3835
coefficient_drag_air=0.4,
3836
moment_inertia_internal=0.01,
3837
coefficient_drag_radial=0.5,
3838
coefficient_drag_roll=0.005,
3839
efficiency_propulsion=0.9,
3840
#
3841
eprofile='prt',
3842
capacity_battery=2000.0,
3843
efficiency_reuperation=0.4,
3844
speed_charging=0.03,
3845
)
3846
3847
else:
3848
id_vtype = vtypes.ids_sumo.get_id_from_index(prttype)
3849
3850
# speedmode
3851
# https://sumo.dlr.de/docs/TraCI/Change_Vehicle_State.html
3852
# bit0: Regard safe speed
3853
# bit1: Regard maximum acceleration
3854
# bit2: Regard maximum deceleration -
3855
# bit3: Regard right of way at intersections
3856
# bit4: Brake hard to avoid passing a red light
3857
3858
#self._speedmode_leader = 7
3859
#self._speedmode_follower = 6
3860
3861
# leader and follower parameters are used when switching
3862
# between leader and follower in concatenate/deconcatenate
3863
self._speedmode_leader = 7
3864
self._speedmode_follower = self.speedmode_follower.get_value()
3865
3866
self._factor_speed_leader = vtypes.factors_speed[id_vtype]
3867
self._factor_speed_follower = self.factor_speed_follower.get_value()
3868
3869
self._accel_leader = vtypes.accels[id_vtype]
3870
self._accel_follower = self.accel_follower.get_value()
3871
3872
self._decel_leader = vtypes.decels[id_vtype]
3873
self._decel_follower = self.decel_follower.get_value()
3874
3875
self._decel_emergency_leader = vtypes.decels_emergency[id_vtype]
3876
self._decel_emergency_follower = self.decel_emergency_follower.get_value()
3877
3878
self._dist_min_leader = vtypes.dists_min[id_vtype]
3879
self._dist_min_follower = self.dist_min_follower.get_value()
3880
3881
self._tau_leader = vtypes.taus[id_vtype]
3882
self._tau_follower = self.tau_follower.get_value()
3883
3884
# these are additional, somehow parameters
3885
# TODO: redundant parameters with leader and follower parameters
3886
# should be removed
3887
3888
self.length = vtypes.lengths[id_vtype]
3889
self.speed_max = vtypes.speeds_max[id_vtype]
3890
self.accel = vtypes.accels[id_vtype]
3891
self.decel = vtypes.decels[id_vtype]
3892
3893
self.decel_emergency = vtypes.decels_emergency[id_vtype]
3894
self.tau = vtypes.taus[id_vtype]
3895
self.dist_min = vtypes.dists_min[id_vtype]
3896
self.factor_speed = vtypes.factors_speed[id_vtype]
3897
3898
return id_vtype
3899
3900
def get_length(self):
3901
return self.length
3902
3903
def prepare_sim(self, process):
3904
print 'PrtVehicles.prepare_sim'
3905
if len(self) == 0:
3906
return []
3907
3908
ids = self.get_ids()
3909
net = self.get_scenario().net
3910
#nodes = net.nodes
3911
#edges = net.edges
3912
#lanes = net.lanes
3913
#ids_edge_sumo = edges.ids_sumo
3914
3915
id_prtmode = self.parent.id_prtmode
3916
3917
# here take parameters from first vtype and assume that all are the same
3918
# this call ensures that most recent parameters are considered
3919
id_vtype = self.make_vtype()
3920
3921
#ptstops = net.ptstops
3922
lanes = net.lanes
3923
#ids_edge_sumo = net.edges.ids_sumo
3924
3925
n_id_max = np.max(ids)+1
3926
n_ghosts_max = self.n_ghosts_max.get_value()
3927
self.ids_berth = -1*np.ones(n_id_max, dtype=np.int32)
3928
3929
self.are_update = np.zeros(n_id_max, dtype=np.bool)
3930
self.velocities = np.zeros(n_id_max, dtype=np.float32)
3931
self.odos = np.zeros(n_id_max, dtype=np.float32)
3932
3933
self.ids_ghosts = -1*np.ones((n_id_max, n_ghosts_max), dtype=np.int32)
3934
3935
self.diststomerge0 = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
3936
self.diststomerge0_ghosts = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
3937
self.dists0 = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
3938
3939
self.odos0_vehicles = -1 * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
3940
self.odos0_ghosts = -np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)
3941
3942
# platooning
3943
# id of leader of this vehicle (vehicle in front), -1 = platoonleader
3944
self.ids_leader = -1 * np.ones(n_id_max, dtype=np.int32)
3945
3946
# id of follower of this vehicle (vehicle behind), -1 = last veh
3947
self.ids_follower = -1 * np.ones(n_id_max, dtype=np.int32)
3948
3949
# total length of platoon
3950
self.lengths_plat = np.zeros(n_id_max, dtype=np.float32)
3951
3952
return [(self.time_update.get_value(), self.process_step), ]
3953
3954
def add_ghost(self, id_veh, id_ghost, dist_to_merge_veh, dist_to_merge_ghost,
3955
is_substitute=False):
3956
ids_ghosts = list(self.ids_ghosts[id_veh])
3957
# if id_ghost in ids_ghosts:
3958
# # reconfigure existing
3959
# ind_ghost = self.ids_ghosts[id_veh].index(id_ghost)
3960
# id_ghost_old = self.ids_ghosts[id_veh][ind_ghost]
3961
# # try to delete old ghost
3962
# self.del_ghost(id_veh, id_ghost_old)
3963
# else:
3964
# add new ghost
3965
print 'add_ghost id_veh %d id_ghost %d' % (id_veh, id_ghost) # ,self.ids_ghosts.shape
3966
3967
if -1 not in ids_ghosts:
3968
# print 'ERROR: no more ghosts available, ids_ghosts',ids_ghosts
3969
# sys.exit(1)
3970
# print ' overwrite last ghost'
3971
# here we could sunstitute the ghost with the longest distance
3972
ind_ghost = len(ids_ghosts)-1
3973
else:
3974
ind_ghost = ids_ghosts.index(-1)
3975
3976
if is_substitute:
3977
id_ghost_prev = ids_ghosts[ind_ghost]
3978
if id_ghost_prev > -1:
3979
self.stop_update(id_ghost_prev)
3980
if ind_ghost > 0:
3981
ind_ghost -= 1
3982
3983
if ind_ghost > 0:
3984
print 'WARNING: unusual number of ghosts, ids_ghosts', ids_ghosts
3985
# sys.exit(1)
3986
3987
self.ids_ghosts[id_veh][ind_ghost] = id_ghost
3988
self.diststomerge0[id_veh][ind_ghost] = dist_to_merge_veh
3989
self.diststomerge0_ghosts[id_veh][ind_ghost] = dist_to_merge_ghost
3990
3991
# nose to nose distances
3992
self.dists0[id_veh][ind_ghost] = dist_to_merge_veh - dist_to_merge_ghost
3993
3994
# get absolute running distances
3995
self.odos0_vehicles[id_veh][ind_ghost] = get_traci_odo(self.get_id_sumo(id_veh))
3996
self.odos0_ghosts[id_veh][ind_ghost] = get_traci_odo(self.get_id_sumo(id_ghost))
3997
3998
# both ghosts and vehicles need update
3999
self.start_update(id_veh)
4000
self.start_update(id_ghost)
4001
4002
def del_ghosts(self, id_veh):
4003
if self.ids_ghosts[id_veh][0] == -1:
4004
# id_veh has no ghosts
4005
return
4006
else:
4007
for id_ghost in self.ids_ghosts[id_veh]:
4008
if id_ghost > -1:
4009
self.del_ghost(id_veh, id_ghost)
4010
4011
def del_ghost(self, id_veh, id_ghost):
4012
# print 'del_ghost id_veh %d id_ghost %d'%(id_veh, id_ghost)
4013
if id_ghost in self.ids_ghosts[id_veh]:
4014
4015
ind_ghost = list(self.ids_ghosts[id_veh]).index(id_ghost)
4016
self.ids_ghosts[id_veh][ind_ghost] = -1
4017
4018
self.diststomerge0[id_veh][ind_ghost] = np.inf
4019
self.diststomerge0_ghosts[id_veh][ind_ghost] = np.inf
4020
self.dists0[id_veh][ind_ghost] = np.inf
4021
4022
self.odos0_vehicles[id_veh][ind_ghost] = -1.0
4023
self.odos0_ghosts[id_veh][ind_ghost] = -np.inf
4024
4025
self.stop_update(id_veh)
4026
self.stop_update(id_ghost)
4027
else:
4028
# veh has not such ghost
4029
pass
4030
4031
def del_all_ghosts(self, id_veh):
4032
if self.ids_ghosts[id_veh][0] == -1:
4033
# id_veh has no ghosts
4034
return
4035
4036
for id_ghost in self.ids_ghosts[id_veh]:
4037
if id_ghost > -1:
4038
self.del_ghost(id_veh, id_ghost)
4039
4040
# just to be sure ...
4041
self.stop_update(id_veh)
4042
4043
def switch_off_control(self, id_veh):
4044
"""Direct way to switch of SUMO control of vehicles"""
4045
# print 'switch_off_control id_veh',id_veh
4046
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], 6) # 6=respect max accel/decel
4047
4048
def switch_on_control(self, id_veh):
4049
"""Direct way to switch of SUMO control of vehicles"""
4050
# print 'switch_on_control id_veh',id_veh
4051
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], self._speedmode_leader)
4052
4053
def start_update(self, id_veh):
4054
"""Start updating control by ghosts"""
4055
self.are_update[id_veh] = True
4056
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], 6) # 6=respect max accel/decel
4057
4058
def stop_update(self, id_veh):
4059
"""Stop updating control by ghosts"""
4060
if np.all(self.ids_ghosts[id_veh] == -1): # id_veh has no ghosts?
4061
4062
# attention stopping from being conrolled by merge means
4063
# handing control back to SUMO.
4064
# followers are not controlled by the merge process
4065
traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], self._speedmode_leader)
4066
if id_veh not in self.ids_ghosts: # id_veh is no ghost ?
4067
self.are_update[id_veh] = False # stop updating
4068
4069
def process_step(self, process):
4070
simtime = process.simtime
4071
print 79*'_'
4072
print 'PrtVehicles.process_step at', simtime
4073
net = self.get_scenario().net
4074
vehicles = self.parent.prtvehicles
4075
ids = self.get_ids()
4076
if len(ids) == 0:
4077
return
4078
time_update = self.time_update.get_value()
4079
decel_emergency = self.decel_emergency
4080
# print ' update',len(np.flatnonzero(self.are_update[ids])),'vehicles'
4081
ids_update = ids[self.are_update[ids]]
4082
# print ' ids_update',ids_update
4083
4084
# print ' *Debug:'
4085
#ids_debug = [307, 236, 41, 231, 208, 44, 249, 229, 136]
4086
#ids_debug = [276,277,278]
4087
#
4088
# for id_veh, id_follower, id_leader in zip(ids_debug,self.ids_follower[ids_debug], self.ids_leader[ids_debug]):
4089
# print ' *id_veh',id_veh,'id_follower',id_follower,'id_leader',id_leader
4090
4091
# loop through vehicles that need speed modifications
4092
# these are vehicles which have ghosts or vehicles which are
4093
# in merge processes
4094
for id_veh, id_veh_sumo in zip(ids_update, self.ids_sumo[ids_update]):
4095
# update odometer and speed
4096
self.velocities[id_veh] = get_traci_velocity(id_veh_sumo)
4097
self.odos[id_veh] = get_traci_odo(id_veh_sumo)
4098
4099
if 0:
4100
ids_ghost = self.ids_ghosts[id_veh]
4101
print ' %7s' % id_veh_sumo, 'ghosts', ids_ghost, self.ids_leader[id_veh], "lp=%.1fm" % self.lengths_plat[id_veh]
4102
#odo = self.odos[id_veh]
4103
#delta_vehs = odo-self.odos0_vehicles[id_veh]
4104
#delta_ghosts = self.odos[ids_ghost] - self.odos0_ghosts[id_veh]
4105
# print ' delta_vehs, delta_ghosts',min(delta_vehs), min(delta_ghosts)#, self.dists0[id_veh]
4106
# print ' dists', min(self.dists0[id_veh] + delta_ghosts - delta_vehs)
4107
4108
#self.diststomerge0[id_veh][ind_ghost] = np.inf
4109
#self.diststomerge0_ghosts[id_veh][ind_ghost] = np.inf
4110
4111
# pick vehicle ids that must be controlled due to a present ghost
4112
ids_contr = ids_update[self.ids_ghosts[ids_update][:, 0] > -1]
4113
# print ' ids_contr',ids_contr
4114
# print ' self.ids_ghosts[ids_update][:,0]',self.ids_ghosts[ids_update][:,0]
4115
# print ' inds',self.ids_ghosts[ids_update][:,0]>-1
4116
n_contr = len(ids_contr)
4117
n_ghosts_max = self.n_ghosts_max.get_value()
4118
4119
# no vehicles with ghost, nothing to control
4120
if n_contr == 0:
4121
return
4122
4123
# get gosts
4124
ids_ghosts = self.ids_ghosts[ids_contr]
4125
4126
# print ' self.odos[ids_contr]',self.odos[ids_contr].reshape(n_contr,1)
4127
# print ' self.odos0_vehicles[ids_contr]',self.odos0_vehicles[ids_contr]
4128
4129
# distance made since merge zone is entered
4130
deltas_vehs = self.odos[ids_contr].reshape(n_contr, 1)-self.odos0_vehicles[ids_contr]
4131
deltas_ghosts = self.odos[ids_ghosts] - self.odos0_ghosts[ids_contr]
4132
4133
#dists = self.dists0[ids_contr] + deltas_ghosts - deltas_vehs
4134
# print ' dists',dists
4135
#dists_min = np.min(self.dists0[ids_contr] + deltas_ghosts - deltas_vehs, 1) - (self.length+self.lengths_plat[ids_contr])
4136
4137
# get distance between nose of vehicle and tail of ghost which is closest
4138
dists_min = np.min(self.dists0[ids_contr] + deltas_ghosts - deltas_vehs -
4139
self.lengths_plat[ids_ghosts], 1) - self.length
4140
4141
# ??????? minimum dist to merge over all vehicles -> remove, not in use
4142
#diststomerge_min = np.min(self.diststomerge0[ids_contr] - deltas_vehs , 1)
4143
#self.diststomerge0[id_veh][ind_ghost] = dist_to_merge_veh
4144
# self.diststomerge0_ghosts[id_veh][ind_ghost] =
4145
4146
# print ' dists_min',dists_min
4147
velocities = self.velocities[ids_contr]
4148
4149
# print ' velocities_ghosts masked\n',self.velocities[ids_ghosts]
4150
4151
#mask_ghosts = INF*(ids_ghosts==-1).astype(np.float32)
4152
# print ' mask_ghosts\n',mask_ghosts
4153
velocities_ghosts = self.velocities[ids_ghosts] + INF*(ids_ghosts == -1)
4154
4155
# print ' velocities_ghosts masked\n',velocities_ghosts
4156
#
4157
# velocities of slowest ghosts
4158
velocities_ghost_min = np.min(self.velocities[ids_ghosts] + INF*(ids_ghosts == -1), 1)
4159
# print ' velocities_ghost_min\n',velocities_ghost_min
4160
dists_safe = self.tau*velocities + 0.5/decel_emergency*velocities*velocities
4161
dists_comf = self.tau*velocities + 0.5/self.decel * \
4162
(velocities*velocities-velocities_ghost_min*velocities_ghost_min)
4163
4164
# print ' dists_safe',dists_safe
4165
# print ' dists_comf',dists_comf
4166
#dists_crit = np.max(np.concatenate((dists_safe.reshape(n_contr,1),dists_comf.reshape(n_contr,1)),1),1)
4167
# print ' dists_crit',dists_crit
4168
4169
deltas_crit = dists_min-np.max(np.concatenate((dists_safe.reshape(n_contr, 1),
4170
dists_comf.reshape(n_contr, 1)), 1), 1)
4171
#deltas_crit = dists_min-dists_safe
4172
# print ' deltas_crit',deltas_crit
4173
inds_slow = deltas_crit < 0
4174
inds_accel = (deltas_crit > 0) & (velocities < 0.8*velocities_ghost_min)
4175
# print ' inds_slow',inds_slow
4176
4177
if 0:
4178
for id_sumo, velocity, velocitiy_ghost_min,\
4179
dist_safe, dist_comf, dist_min, delta_crit,\
4180
is_slow, is_accel, length_plat\
4181
in zip(self.ids_sumo[ids_contr],
4182
velocities,
4183
velocities_ghost_min,
4184
dists_safe,
4185
dists_comf,
4186
dists_min,
4187
deltas_crit,
4188
inds_slow, inds_accel, self.lengths_plat[ids_contr],
4189
# diststomerge_min,
4190
):
4191
4192
if is_slow:
4193
a = '-'
4194
elif is_accel:
4195
a = '+'
4196
else:
4197
a = '='
4198
# print 'id_sumo, velocity, velocitiy_ghost_min,dist_safe,dist_comf,dist_min,delta_crit,is_slow,is_accel, length_plat\n',\
4199
# id_sumo, velocity, velocitiy_ghost_min,\
4200
# dist_safe,dist_comf,dist_min,delta_crit,\
4201
#is_slow,is_accel, length_plat
4202
4203
th = (dist_min + self.length)/velocity
4204
ds_check = self.tau*velocity + 0.5/decel_emergency*velocity*velocity
4205
# 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)
4206
4207
fact_urgent = np.ones(dists_safe.shape, dtype=np.float32) # np.clip(dists_safe/diststomerge_min,0.0,1.0)
4208
4209
v_delta_brake = time_update*self.decel*fact_urgent
4210
for id_sumo, velocity, dv in zip(self.ids_sumo[ids_contr[inds_slow]], velocities[inds_slow], v_delta_brake):
4211
# print ' deccel %s from %.2f to %.2fm/s dv = %.2fm/s'%(id_sumo, velocity, velocity-dv,dv)
4212
if velocity-dv > 0: # upset when negative velocities
4213
traci.vehicle.slowDown(id_sumo, velocity-dv, time_update)
4214
4215
v_delta_accel = time_update*self.accel*fact_urgent
4216
for id_sumo, velocity, dv in zip(self.ids_sumo[ids_contr[inds_accel]], velocities[inds_accel], v_delta_accel):
4217
#dv = time_update*self.accel
4218
# print ' accel %s from %.2f to %.2fm/s dv = %.2fm/s'%(id_sumo, velocity, velocity+dv,dv)
4219
traci.vehicle.slowDown(id_sumo, velocity+dv, time_update)
4220
4221
# print ' deltas_vehs',deltas_vehs
4222
# print ' self.ids_ghosts[ids_contr]',self.ids_ghosts[ids_contr]
4223
# print ' self.odos[self.ids_ghosts[ids_contr]]',self.odos[self.ids_ghosts[ids_contr]]
4224
# print ' self.odos0_ghosts[id_veh]',self.odos0_ghosts[ids_contr]
4225
# print ' deltas_ghosts',deltas_ghosts
4226
# print ' dists',dists
4227
# for id_contr, delta_vehs, delta_ghosts,dist in zip(ids_contr,deltas_vehs,deltas_ghosts,dists):
4228
# print ' veh',id_contr,'dist',dist
4229
4230
#self.length = vtypes.lengths[id_vtype]
4231
#self.speed_max = vtypes.speeds_max[id_vtype]
4232
#self.accel = vtypes.accels[id_vtype]
4233
#self.decel = vtypes.decels[id_vtype]
4234
#self.tau = vtypes.taus[id_vtype]
4235
4236
def reset_speedmode(self, id_veh_sumo):
4237
print 'reset_speedmode', id_veh_sumo
4238
# speed mode (0xb3)
4239
# 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:
4240
# 1 bit0: Regard safe speed
4241
# 2 bit1: Regard maximum acceleration
4242
# 4 bit2: Regard maximum deceleration
4243
# 8 bit3: Regard right of way at intersections
4244
# 16 bit4: Brake hard to avoid passing a red light
4245
# 1+2+4
4246
# traci.vehicle.setSpeedMode(id_veh_sumo,7)
4247
#self.speed_max = vtypes.speeds_max[id_vtype]
4248
#self.accel = vtypes.accels[id_vtype]
4249
traci.vehicle.slowDown(id_veh_sumo, self.speed_max, self.speed_max/self.accel)
4250
# pass
4251
4252
def concatenate(self, id_veh, id_veh_pre):
4253
print 'concatenate prt.%d' % id_veh, 'behind prt.%d' % id_veh_pre
4254
# print ' >>'
4255
self.ids_leader[id_veh] = id_veh_pre
4256
self.ids_follower[id_veh_pre] = id_veh
4257
4258
id_veh_sumo = self.get_id_sumo(id_veh)
4259
4260
if 0:
4261
print 'follower params'
4262
print ' speedmode', self._speedmode_follower
4263
print ' factor_speed', self._factor_speed_follower
4264
print ' decel', self._decel_emergency_follower, '= decel_emergency'
4265
print ' accel_follower', self._accel_follower
4266
print ' dist_min', self._dist_min_follower
4267
print ' tau', self._tau_follower
4268
4269
# if 0:
4270
# traci.vehicle.setSpeedFactor(id_veh_sumo,2.0)# +random.uniform(-0.01,0.01)
4271
# traci.vehicle.setImperfection(id_veh_sumo,0.0)
4272
# traci.vehicle.setAccel(id_veh_sumo,3.5)
4273
# traci.vehicle.setMinGap(id_veh_sumo,0.01)
4274
# traci.vehicle.setTau(id_veh_sumo,0.2)
4275
4276
# if 1:
4277
traci.vehicle.setSpeedMode(id_veh_sumo, self._speedmode_follower)
4278
traci.vehicle.setSpeedFactor(id_veh_sumo, self._factor_speed_follower)
4279
# traci.vehicle.setImperfection(id_veh_sumo,0.0)
4280
traci.vehicle.setDecel(id_veh_sumo, self._decel_emergency_follower)
4281
traci.vehicle.setAccel(id_veh_sumo, self._accel_follower)
4282
traci.vehicle.setMinGap(id_veh_sumo, self._dist_min_follower)
4283
traci.vehicle.setTau(id_veh_sumo, self._tau_follower)
4284
4285
if self.lengths_plat[id_veh] > 0.1:
4286
self._update_concatenate(id_veh, self.lengths_plat[id_veh])
4287
else:
4288
self._update_concatenate(id_veh, 0.0)
4289
4290
def _update_concatenate(self, id_veh, length_plat):
4291
"""
4292
Propagates length to the first vehicle of the platoon
4293
"""
4294
# print '_update_concatenate prt.%s, length_plat=%.1f, length=%.1f,'%(id_veh,length_plat,self.length),'id_leader',self.ids_leader[id_veh]
4295
if self.ids_leader[id_veh] == -1:
4296
# first vehicle
4297
# print ' first vehicle prt.%s'%id_veh,length_plat
4298
self.lengths_plat[id_veh] = length_plat
4299
else:
4300
# propagate platoon length
4301
self.lengths_plat[id_veh] = 0.0
4302
self._update_concatenate(self.ids_leader[id_veh], length_plat + self.length)
4303
4304
def decatenate(self, id_veh):
4305
print 'decatenate prt.%d' % id_veh
4306
4307
id_leader = self.ids_leader[id_veh]
4308
# print ' id_leader',id_leader
4309
if id_leader > -1:
4310
id_veh_sumo = self.get_id_sumo(id_veh)
4311
if self.ids_leader[id_leader] == -1:
4312
# leader of this vehicle is first in platoon
4313
# this should be normally the case if a platoon is
4314
# broken up from the first vehicle backwards
4315
4316
# calculate new shortened platoon length
4317
# TODO
4318
self.lengths_plat[id_veh] = self.lengths_plat[id_leader]-self.length
4319
else:
4320
print 'WARNING in decatenate: platoon broken up in the middel at', id_veh_sumo
4321
self.lengths_plat[id_veh] = 0.0
4322
4323
# this vehicle will become first in the platoon
4324
self.ids_leader[id_veh] = -1
4325
self.ids_follower[id_leader] = -1
4326
# if 0:
4327
# traci.vehicle.setSpeedFactor(id_veh_sumo, 1.5)#+random.uniform(-0.01,0.01)
4328
# traci.vehicle.setMinGap(id_veh_sumo,0.3)
4329
# traci.vehicle.setImperfection(id_veh_sumo,0.0)
4330
# traci.vehicle.setTau(id_veh_sumo,0.8)
4331
# traci.vehicle.setAccel(id_veh_sumo,2.5)
4332
4333
# if 1:
4334
# reset parameters
4335
traci.vehicle.setSpeedMode(id_veh_sumo, self._speedmode_leader)
4336
4337
# rest are leader values taken from type def
4338
traci.vehicle.setSpeedFactor(id_veh_sumo, self.factor_speed) # +random.uniform(-0.01,0.01)
4339
traci.vehicle.setMinGap(id_veh_sumo, self.dist_min)
4340
# traci.vehicle.setImperfection(id_veh_sumo,1.0)
4341
traci.vehicle.setTau(id_veh_sumo, self.tau)
4342
traci.vehicle.setDecel(id_veh_sumo, self.decel)
4343
traci.vehicle.setAccel(id_veh_sumo, self.accel)
4344
else:
4345
# it is a leader itself and does not need to decatenate
4346
# remove platoon length
4347
self.lengths_plat[id_veh] = 0.0
4348
4349
def get_platoonleader(self, id_veh):
4350
while self.ids_leader[id_veh] > -1:
4351
id_veh = self.ids_leader[id_veh]
4352
return id_veh
4353
4354
def get_platoontail(self, id_veh):
4355
while self.ids_follower[id_veh] > -1:
4356
id_veh = self.ids_follower[id_veh]
4357
return id_veh
4358
4359
def get_platoon(self, id_veh):
4360
print 'get_platoon', id_veh
4361
ids_veh = [id_veh, ]
4362
id_veh = self.ids_follower[id_veh]
4363
# print ' id_veh',id_veh
4364
while id_veh > -1:
4365
ids_veh.append(id_veh)
4366
id_veh = self.ids_follower[id_veh]
4367
print ' id_veh', id_veh
4368
4369
print ' ids_veh', ids_veh
4370
return ids_veh
4371
4372
def get_entered_left(self, id_edge_sumo, ids_veh_previous_sumo):
4373
"""
4374
Returns:
4375
array with SUMO IDs of entered vehicles during last poll
4376
array with SUMO IDs of left vehicles during last poll
4377
array with SUMO IDs current vehicles on id_edge_sumo
4378
Attention: in the returned entered/left lists,
4379
the first vehicle in the list entered/left first
4380
"""
4381
ids_veh_new_sumo = traci.edge.getLastStepVehicleIDs(id_edge_sumo)
4382
# print 'get_entered_left ids_veh_new_sumo=',ids_veh_new_sumo
4383
len_prev = len(ids_veh_previous_sumo)
4384
len_new = len(ids_veh_new_sumo)
4385
4386
if len_prev == 0:
4387
return ids_veh_new_sumo, [], ids_veh_new_sumo
4388
4389
if len_new == 0:
4390
return [], ids_veh_previous_sumo, []
4391
4392
ind_enter = 0
4393
4394
for id_veh_sumo in ids_veh_new_sumo:
4395
4396
# if ind_enter+1 == len_prev:
4397
# ind_enter = len_new -1
4398
# break
4399
4400
if id_veh_sumo == ids_veh_previous_sumo[0]:
4401
break
4402
4403
ind_enter += 1
4404
# print ' ind_enter',ind_enter,ids_veh_new_sumo[0:ind_enter],ids_veh_new_sumo[ind_enter-1::-1]
4405
#ids_entered_sumo = ids_veh_new_sumo[0:ind_enter]
4406
4407
ind_leave = len_prev
4408
for id_veh_sumo in ids_veh_previous_sumo[::-1]:
4409
4410
if id_veh_sumo == ids_veh_new_sumo[-1]:
4411
break
4412
4413
ind_leave -= 1
4414
# print ' ind_leave',ind_leave, ids_veh_previous_sumo[ind_leave:],ids_veh_previous_sumo[:ind_leave:-1]
4415
#ids_leave_sumo = ids_veh_previous_sumo[ind_leave:]
4416
4417
# return ids_entered_sumo, ids_leave_sumo, ids_veh_new_sumo
4418
# return reversed lists
4419
return ids_veh_new_sumo[0:ind_enter][::-1], ids_veh_previous_sumo[ind_leave:][::-1], ids_veh_new_sumo
4420
4421
# TODO: optimize!!!
4422
# return ids_veh_new_sumo[ind_enter-1::-1], ids_veh_previous_sumo[:ind_leave:-1], ids_veh_new_sumo
4423
4424
def control_stop(self, id_veh, laneindex=0):
4425
4426
id_veh_sumo = self.get_id_sumo(id_veh)
4427
speed = traci.vehicle.getSpeed(id_veh_sumo)
4428
pos = traci.vehicle.getLanePosition(id_veh_sumo)
4429
stopline = pos + 3.0 + 0.5/self.decel*speed**2
4430
#time_slowdown = np.abs((speed0-speed)/self.decel)
4431
4432
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))
4433
traci.vehicle.setStop(id_veh_sumo,
4434
traci.vehicle.getRoadID(id_veh_sumo),
4435
pos=stopline,
4436
laneIndex=laneindex,
4437
)
4438
4439
def control_speedup(self, id_veh):
4440
4441
id_veh_sumo = self.get_id_sumo(id_veh)
4442
print 'control_speedup', id_veh_sumo, 'isStopped', traci.vehicle.isStopped(id_veh_sumo), self.speed_max
4443
4444
if traci.vehicle.isStopped(id_veh_sumo):
4445
traci.vehicle.resume(id_veh_sumo)
4446
4447
traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max)
4448
#self.control_slow_down(id_veh, self.speed_max)
4449
4450
def control_slow_down(self, id_veh, speed=1.0, time_slowdown=None):
4451
print 'control_slow_down', self.get_id_sumo(id_veh), speed, time_slowdown
4452
id_veh_sumo = self.get_id_sumo(id_veh)
4453
if time_slowdown is None:
4454
speed0 = traci.vehicle.getSpeed(id_veh_sumo)
4455
4456
time_slowdown = np.abs((speed0-speed)/self.decel)
4457
# print ' speed0=%.2fm/s, time_slowdown = %.2fs, dv=%.2fm/s'%(speed0,time_slowdown,speed0-speed)
4458
4459
traci.vehicle.slowDown(id_veh_sumo, speed, time_slowdown)
4460
#self.speed_max = vtypes.speeds_max[id_vtype]
4461
#self.accel = vtypes.accels[id_vtype]
4462
#self.decel = vtypes.decels[id_vtype]
4463
4464
def control_stop_alight(self, id_veh, id_stop, id_berth,
4465
id_edge_sumo=None,
4466
position=None,
4467
):
4468
id_veh_sumo = self.get_id_sumo(id_veh)
4469
p = traci.vehicle.getLanePosition(id_veh_sumo)
4470
print 'control_stop_alight', id_veh_sumo, p, '->', position, 'id_berth', id_berth
4471
#d = position - p
4472
#v = traci.vehicle.getSpeed(id_veh_sumo)
4473
#d_save = 1.0/(2*2.5)*(v**2)
4474
# print ' v=',v
4475
# print ' d,d_save',d,d_save
4476
self.states[id_veh] = VEHICLESTATES['forewarding']
4477
self.ids_berth[id_veh] = id_berth
4478
traci.vehicle.setStop(self.get_id_sumo(id_veh),
4479
id_edge_sumo,
4480
pos=position,
4481
flags=0,
4482
laneIndex=1,
4483
)
4484
4485
def control_stop_board(self, id_veh, id_stop, id_berth,
4486
id_edge_sumo=None,
4487
position=None,
4488
):
4489
4490
id_veh_sumo = self.get_id_sumo(id_veh)
4491
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)
4492
# print ' v=',traci.vehicle.getSpeed(id_veh_sumo)
4493
4494
# print 'control_stop_board',id_veh_sumo,traci.vehicle.getLanePosition(id_veh_sumo),'->',position,id_berth
4495
self.ids_berth[id_veh] = id_berth
4496
self.states[id_veh] = VEHICLESTATES['forewarding']
4497
# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
4498
if traci.vehicle.isStopped(id_veh_sumo):
4499
traci.vehicle.resume(id_veh_sumo)
4500
4501
traci.vehicle.setStop(id_veh_sumo,
4502
id_edge_sumo,
4503
startPos=position-4.0,
4504
pos=position,
4505
flags=2, # park and trigger 1+2,#
4506
laneIndex=1,
4507
)
4508
4509
def alight(self, id_veh):
4510
# print 'alight',self.get_id_sumo(id_veh)
4511
# TODO: necessary to keep copy of state?
4512
self.states[id_veh] = VEHICLESTATES['alighting']
4513
# traci.vehicle.getStopState(self.get_id_sumo(id_veh))
4514
# VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting'
4515
4516
def board(self, id_veh, id_edge_sumo=None, position=None):
4517
# print 'board',self.get_id_sumo(id_veh)
4518
# TODO: necessary to keep copy of state?
4519
self.states[id_veh] = VEHICLESTATES['boarding']
4520
#id_veh_sumo = self.get_id_sumo(id_veh)
4521
# print 'board',id_veh_sumo,'stopstate',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
4522
# print ' ',dir(traci.vehicle)
4523
# traci.vehicle.getLastStepPersonIDs()
4524
# traci.vehicle.getStopState(self.get_id_sumo(id_veh))
4525
# VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting'
4526
#traci.vehicle.setRoute(id_veh_sumo, [id_edge_sumo])
4527
# traci.vehicle.resume(id_veh_sumo)
4528
4529
# traci.vehicle.setStop( self.get_id_sumo(id_veh),
4530
# traci.vehicle.getRoadID(id_veh_sumo),
4531
# pos = traci.vehicle.getLanePosition(id_veh_sumo),
4532
# flags= 2,#
4533
# laneIndex= 1,
4534
# )
4535
# print 'board ',id_veh_sumo, traci.vehicle.getStopState(id_veh_sumo )# bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
4536
4537
def set_stop(self, id_veh, id_edge_sumo, stopline, laneindex=1):
4538
print 'set_stop', self.get_id_sumo(id_veh), stopline
4539
traci.vehicle.setStop(self.get_id_sumo(id_veh),
4540
id_edge_sumo,
4541
pos=stopline,
4542
laneIndex=laneindex,
4543
)
4544
4545
def reached_stop_sumo(self, id_veh_sumo):
4546
state = traci.vehicle.getStopState(id_veh_sumo)
4547
# print 'reached_stop',id_veh_sumo,bin(state),bin(state)[-1] == '1'
4548
return bin(state)[-1] == '1'
4549
4550
def is_completed_alighting(self, id_veh):
4551
# print 'is_completed_alighting',self.get_id_sumo(id_veh),self.states[id_veh],self.states[id_veh] == VEHICLESTATES['alighting'],traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)),type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)))
4552
if self.states[id_veh] == VEHICLESTATES['alighting']:
4553
if traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)) == 0:
4554
# print ' id_veh_sumo',self.get_id_sumo(id_veh),'completed alighting'
4555
self.states[id_veh] = VEHICLESTATES['await_forwarding']
4556
return True
4557
else:
4558
# somebody is still in the vehicle
4559
return False
4560
elif self.states[id_veh] == VEHICLESTATES['await_forwarding']:
4561
return True
4562
else:
4563
print 'WARNING: strange vehicle state %s while alighting prt.%d' % (self.states[id_veh], id_veh)
4564
return True
4565
4566
def is_completed_boarding(self, id_veh):
4567
# print 'is_completed_boarding',self.get_id_sumo(id_veh),self.states[id_veh],self.states[id_veh] == VEHICLESTATES['boarding'],traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)),type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)))
4568
if self.states[id_veh] == VEHICLESTATES['boarding']:
4569
if traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)) == 1:
4570
# print 'is_completed_boarding',self.get_id_sumo(id_veh),'completed boarding'
4571
self.states[id_veh] = VEHICLESTATES['waiting']
4572
return True
4573
else:
4574
False
4575
4576
else:
4577
return True
4578
4579
def get_veh_if_completed_boarding(self, id_veh):
4580
# print 'get_veh_if_completed_boarding',self.get_id_sumo(id_veh),self.states[id_veh],self.states[id_veh] == VEHICLESTATES['boarding'],traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)),type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)))
4581
4582
if self.states[id_veh] == VEHICLESTATES['boarding']:
4583
id_veh_sumo = self.get_id_sumo(id_veh)
4584
if traci.vehicle.getPersonNumber(id_veh_sumo) >= 1:
4585
# print 'get_veh_if_completed_boarding',id_veh_sumo,'completed boarding'
4586
self.states[id_veh] = VEHICLESTATES['waiting']
4587
return id_veh_sumo
4588
else:
4589
return ''
4590
4591
else:
4592
return ''
4593
4594
def init_trip_occupied(self, id_veh, id_edge_sumo, stopline=None):
4595
id_veh_sumo = self.get_id_sumo(id_veh)
4596
print 'init_trip_occupied', self.get_id_sumo(id_veh), 'from edge', id_edge_sumo, stopline
4597
# print ' current route:',traci.vehicle.getRoute(id_veh_sumo)
4598
self.states[id_veh] = VEHICLESTATES['occupiedtrip']
4599
4600
# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
4601
if traci.vehicle.isStopped(id_veh_sumo):
4602
traci.vehicle.resume(id_veh_sumo)
4603
#traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest)
4604
#traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest)
4605
if stopline is not None:
4606
traci.vehicle.setStop(id_veh_sumo,
4607
id_edge_sumo,
4608
pos=stopline,
4609
laneIndex=1,
4610
)
4611
else:
4612
speed_crawl = 1.0
4613
time_accel = 4.0
4614
#traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel)
4615
4616
def init_trip_empty(self, id_veh, id_edge_sumo, stopline=None):
4617
print 'Vehicles.init_trip_empty', self.get_id_sumo(id_veh), id_edge_sumo, stopline
4618
self.states[id_veh] = VEHICLESTATES['emptytrip']
4619
id_veh_sumo = self.get_id_sumo(id_veh)
4620
if traci.vehicle.isStopped(id_veh_sumo):
4621
traci.vehicle.resume(id_veh_sumo)
4622
#traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to)
4623
if stopline is not None:
4624
# if stopline>=0:
4625
# print ' Route=',traci.vehicle.getRoute(id_veh_sumo)
4626
# print ' Position=',traci.vehicle.getLanePosition(id_veh_sumo),stopline
4627
# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]
4628
4629
traci.vehicle.setStop(id_veh_sumo,
4630
id_edge_sumo,
4631
pos=stopline,
4632
laneIndex=1,
4633
)
4634
else:
4635
speed_crawl = 1.0
4636
time_accel = 4.0
4637
#traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel)
4638
4639
def reschedule_trip_sumo(self, id_veh_sumo, id_edge_sumo_to=None, route_sumo=None):
4640
print 'reschedule_trip_sumo', id_veh_sumo, id_edge_sumo_to, route_sumo
4641
if traci.vehicle.isStopped(id_veh_sumo):
4642
traci.vehicle.resume(id_veh_sumo)
4643
4644
if route_sumo is not None:
4645
# set entire route
4646
traci.vehicle.setRoute(id_veh_sumo, route_sumo)
4647
else:
4648
# set new target and let SUMO do the routing
4649
traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to)
4650
4651
#
4652
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
4653
# self.reset_speedmode(id_veh_sumo)
4654
#traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0)
4655
4656
def reschedule_trip(self, id_veh, id_edge_sumo_to=None, route_sumo=None):
4657
print 'reschedule_trip', self.get_id_sumo(id_veh), id_edge_sumo_to, route_sumo
4658
id_veh_sumo = self.get_id_sumo(id_veh)
4659
if traci.vehicle.isStopped(id_veh_sumo):
4660
traci.vehicle.resume(id_veh_sumo)
4661
4662
if route_sumo is not None:
4663
# set entire route
4664
traci.vehicle.setRoute(id_veh_sumo, route_sumo)
4665
else:
4666
# set new target and let SUMO do the routing
4667
traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to)
4668
4669
#
4670
# self.reset_speedmode(id_veh_sumo)
4671
# limit speed to run slowly on exit line
4672
# the merge will take over speed control
4673
4674
#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)
4675
# print ' set speed to',traci.vehicle.getMaxSpeed(id_veh_sumo)
4676
#traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0)
4677
4678
def add_to_net(self, n=-1, length_veh_av=4.0):
4679
"""
4680
Add n PRT vehicles to network
4681
If n = -1 then fill up stops with vehicles.
4682
"""
4683
# print 'PrtVehicles.make',n,length_veh_av
4684
# self.clear()
4685
net = self.get_scenario().net
4686
ptstops = net.ptstops
4687
prtstops = self.parent.prtstops
4688
lanes = net.lanes
4689
ids_prtstop = prtstops.get_ids()
4690
ids_ptstop = prtstops.ids_ptstop[ids_prtstop]
4691
ids_veh = []
4692
n_stop = len(prtstops)
4693
4694
for id_prt, id_edge, pos_from, pos_to in zip(
4695
ids_prtstop,
4696
lanes.ids_edge[ptstops.ids_lane[ids_ptstop]],
4697
ptstops.positions_from[ids_ptstop],
4698
ptstops.positions_to[ids_ptstop],
4699
):
4700
# TODO: here we can select depos or distribute a
4701
# fixed number of vehicles or put them into berth
4702
# print ' ',pos_to,pos_from,int((pos_to-pos_from)/length_veh_av)
4703
if n > 0:
4704
n_veh_per_stop = int(float(n)/n_stop+0.5)
4705
else:
4706
n_veh_per_stop = int((pos_to-pos_from)/length_veh_av)
4707
# print ' n,n_stop,n_veh_per_stop',n,n_stop,n_veh_per_stop
4708
for i in range(n_veh_per_stop):
4709
id_veh = self.add_row(ids_stop_target=id_prt,
4710
ids_currentedge=id_edge,
4711
)
4712
4713
self.ids_sumo[id_veh] = self.get_id_sumo(id_veh)
4714
ids_veh.append(id_veh)
4715
4716
return ids_veh
4717
4718
# def write_veh
4719
#
4720
4721
def get_scenario(self):
4722
return self.parent.get_scenario()
4723
4724
def get_vtypes(self):
4725
"""
4726
Returns a set with all used PRT vehicle types.
4727
"""
4728
# print 'Vehicles_individual.get_vtypes',self.cols.vtype
4729
return set(self.ids_vtype.get_value())
4730
4731
def get_id_sumo(self, id_veh):
4732
return 'prt.%s' % (id_veh)
4733
4734
def get_id_from_id_sumo(self, id_veh_sumo):
4735
if len(id_veh_sumo.split('.')) == 2:
4736
prefix, id_veh = id_veh_sumo.split('.')
4737
if prefix == 'prt':
4738
return int(id_veh)
4739
else:
4740
return -1
4741
return -1
4742
4743
def get_ids_from_ids_sumo(self, ids_veh_sumo):
4744
n = len(ids_veh_sumo)
4745
ids = np.zeros(n, np.int32)
4746
for i in xrange(n):
4747
ids[i] = self.get_id_from_id_sumo(ids_veh_sumo[i])
4748
return ids
4749
4750
def get_id_line_xml(self):
4751
return 'prt'
4752
4753
4754
class PrtStrategy(StrategyMixin):
4755
def __init__(self, ident, parent=None,
4756
name='Personal Rapid Transit Strategy',
4757
info='With this strategy, the person uses Personla Rapid Transit as main transport mode.',
4758
**kwargs):
4759
4760
self._init_objman(ident, parent, name=name, info=info, **kwargs)
4761
attrsman = self.set_attrsman(cm.Attrsman(self))
4762
# specific init
4763
self._init_attributes()
4764
self._init_constants()
4765
4766
def _init_attributes(self):
4767
# print 'StrategyMixin._init_attributes'
4768
pass
4769
4770
def _init_constants(self):
4771
#virtualpop = self.get_virtualpop()
4772
#stagetables = virtualpop.get_stagetables()
4773
4774
#self._walkstages = stagetables.get_stagetable('walks')
4775
#self._ridestages = stagetables.get_stagetable('rides')
4776
#self._activitystages = stagetables.get_stagetable('activities')
4777
4778
#self._plans = virtualpop.get_plans()
4779
#
4780
# print 'AutoStrategy._init_constants'
4781
# print dir(self)
4782
# self.get_attrsman().do_not_save_attrs(['_activitystages','_ridestages','_walkstages','_plans'])
4783
4784
modes = self.get_virtualpop().get_scenario().net.modes
4785
self._id_mode_bike = modes.get_id_mode('bicycle')
4786
self._id_mode_auto = modes.get_id_mode('passenger')
4787
self._id_mode_moto = modes.get_id_mode('motorcycle')
4788
self._id_mode_bus = modes.get_id_mode('bus')
4789
self.get_attrsman().do_not_save_attrs([
4790
'_id_mode_bike', '_id_mode_auto', '_id_mode_moto', '_id_mode_bus'
4791
])
4792
4793
def set_prtservice(self, prtservice):
4794
#self.add( cm.ObjConf( prtservice, is_child = False,groups = ['_private']))
4795
self.prtservice = prtservice
4796
self.get_attrsman().do_not_save_attrs(['prtservice'])
4797
4798
def preevaluate(self, ids_person):
4799
"""
4800
Preevaluation strategies for person IDs in vector ids_person.
4801
4802
Returns a preevaluation vector with a preevaluation value
4803
for each person ID. The values of the preevaluation vector are as follows:
4804
-1 : Strategy cannot be applied
4805
0 : Stategy can be applied, but the preferred mode is not used
4806
1 : Stategy can be applied, and preferred mode is part of the strategy
4807
2 : Strategy uses predomunantly preferred mode
4808
4809
"""
4810
n_pers = len(ids_person)
4811
persons = self.get_virtualpop()
4812
preeval = np.zeros(n_pers, dtype=np.int32)
4813
4814
# TODO: here we could exclude by age or distance facilities-stops
4815
4816
# put 0 for persons whose preference is not public transport
4817
preeval[persons.ids_mode_preferred[ids_person] != self.prtservice.id_prtmode] = 0
4818
4819
# put 2 for persons with car access and who prefer cars
4820
preeval[persons.ids_mode_preferred[ids_person] == self.prtservice.id_prtmode] = 2
4821
4822
print ' PrtStrategy.preevaluate', len(np.flatnonzero(preeval))
4823
return preeval
4824
4825
def plan(self, ids_person, logger=None):
4826
"""
4827
Generates a plan for these person according to this strategie.
4828
Overriden by specific strategy.
4829
"""
4830
print 'PrtStrategy.pan', len(ids_person)
4831
#make_plans_private(self, ids_person = None, mode = 'passenger')
4832
# routing necessary?
4833
virtualpop = self.get_virtualpop()
4834
scenario = virtualpop.get_scenario()
4835
plans = virtualpop.get_plans() # self._plans
4836
demand = scenario.demand
4837
#ptlines = demand.ptlines
4838
4839
walkstages = plans.get_stagetable('walks')
4840
prtstages = plans.get_stagetable('prttransits')
4841
activitystages = plans.get_stagetable('activities')
4842
4843
activities = virtualpop.get_activities()
4844
activitytypes = demand.activitytypes
4845
prtstops = self.prtservice.prtstops
4846
4847
if len(prtstops) == 0:
4848
# no prt stops, no prt plans
4849
return True
4850
4851
net = scenario.net
4852
edges = net.edges
4853
lanes = net.lanes
4854
modes = net.modes
4855
landuse = scenario.landuse
4856
facilities = landuse.facilities
4857
4858
times_est_plan = plans.times_est
4859
# here we can determine edge weights for different modes
4860
4861
# this could be centralized to avoid redundance
4862
plans.prepare_stagetables(['walks', 'prttransits', 'activities'])
4863
# must be after preparation:
4864
if self.prtservice.times_stop_to_stop is None:
4865
self.prtservice.make_times_stop_to_stop()
4866
times_stop_to_stop = self.prtservice.times_stop_to_stop
4867
4868
ids_person_act, ids_act_from, ids_act_to\
4869
= virtualpop.get_activities_from_pattern(0, ids_person=ids_person)
4870
4871
if len(ids_person_act) == 0:
4872
print 'WARNING in TrasitStrategy.plan: no eligible persons found.'
4873
return False
4874
4875
# temporary maps from ids_person to other parameters
4876
nm = np.max(ids_person_act)+1
4877
map_ids_plan = np.zeros(nm, dtype=np.int32)
4878
#ids_plan_act = virtualpop.add_plans(ids_person_act, id_strategy = self.get_id_strategy())
4879
map_ids_plan[ids_person_act] = virtualpop.add_plans(ids_person_act, id_strategy=self.get_id_strategy())
4880
4881
map_times = np.zeros(nm, dtype=np.int32)
4882
map_times[ids_person_act] = activities.get_times_end(ids_act_from, pdf='unit')
4883
4884
# set start time to plans (important!)
4885
plans.times_begin[map_ids_plan[ids_person_act]] = map_times[ids_person_act]
4886
4887
map_ids_fac_from = np.zeros(nm, dtype=np.int32)
4888
map_ids_fac_from[ids_person_act] = activities.ids_facility[ids_act_from]
4889
4890
n_plans = len(ids_person_act)
4891
print 'TrasitStrategy.plan n_plans=', n_plans
4892
4893
# make initial activity stage
4894
ids_edge_from = facilities.ids_roadedge_closest[map_ids_fac_from[ids_person_act]]
4895
poss_edge_from = facilities.positions_roadedge_closest[map_ids_fac_from[ids_person_act]]
4896
# this is the time when first activity starts
4897
# first activity is normally not simulated
4898
4899
names_acttype_from = activitytypes.names[activities.ids_activitytype[ids_act_from]]
4900
durations_act_from = activities.get_durations(ids_act_from)
4901
times_from = map_times[ids_person_act]-durations_act_from
4902
#times_from = activities.get_times_end(ids_act_from, pdf = 'unit')
4903
4904
for id_plan,\
4905
time,\
4906
id_act_from,\
4907
name_acttype_from,\
4908
duration_act_from,\
4909
id_edge_from,\
4910
pos_edge_from \
4911
in zip(map_ids_plan[ids_person_act],
4912
times_from,
4913
ids_act_from,
4914
names_acttype_from,
4915
durations_act_from,
4916
ids_edge_from,
4917
poss_edge_from):
4918
4919
id_stage_act, time = activitystages.append_stage(
4920
id_plan, time,
4921
ids_activity=id_act_from,
4922
names_activitytype=name_acttype_from,
4923
durations=duration_act_from,
4924
ids_lane=edges.ids_lanes[id_edge_from][0],
4925
positions=pos_edge_from,
4926
)
4927
4928
##
4929
4930
ind_act = 0
4931
4932
# main loop while there are persons performing
4933
# an activity at index ind_act
4934
while len(ids_person_act) > 0:
4935
ids_plan = map_ids_plan[ids_person_act]
4936
4937
times_from = map_times[ids_person_act]
4938
4939
names_acttype_to = activitytypes.names[activities.ids_activitytype[ids_act_to]]
4940
durations_act_to = activities.get_durations(ids_act_to)
4941
4942
ids_fac_from = map_ids_fac_from[ids_person_act]
4943
ids_fac_to = activities.ids_facility[ids_act_to]
4944
4945
centroids_from = facilities.centroids[ids_fac_from]
4946
centroids_to = facilities.centroids[ids_fac_to]
4947
dists_from_to = np.sqrt(np.sum((centroids_to - centroids_from)**2, 1))
4948
dists_walk_max = virtualpop.dists_walk_max[ids_person_act]
4949
4950
# origin edge and position
4951
ids_edge_from = facilities.ids_roadedge_closest[ids_fac_from]
4952
poss_edge_from = facilities.positions_roadedge_closest[ids_fac_from]
4953
4954
# destination edge and position
4955
# attention, this methods assumes that all stops are reachable by foot
4956
ids_edge_to = facilities.ids_roadedge_closest[ids_fac_to]
4957
poss_edge_to = facilities.positions_roadedge_closest[ids_fac_to]
4958
4959
# find closest prt stop!!
4960
ids_stop_from, ids_stopedge_from = prtstops.get_closest(centroids_from)
4961
ids_stop_to, ids_stopedge_to = prtstops.get_closest(centroids_to)
4962
4963
poss_stop_from = prtstops.get_waitpositions(ids_stop_from, offset=-0.5)
4964
poss_stop_to = prtstops.get_waitpositions(ids_stop_to, offset=-0.5)
4965
4966
i = 0.0
4967
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\
4968
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):
4969
n_pers = len(ids_person_act)
4970
if logger:
4971
logger.progress(i/n_pers*100)
4972
i += 1.0
4973
print 79*'_'
4974
print ' id_plan=%d, id_person=%d, ' % (id_plan, id_person)
4975
4976
if (dist_from_to < dist_walk_max) | (id_edge_from == -1) | (id_edge_to == -1) | (id_stop_from == id_stop_to):
4977
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
4978
4979
id_stage_walk1, time = walkstages.append_stage(
4980
id_plan, time_from,
4981
id_edge_from=id_edge_from,
4982
position_edge_from=pos_edge_from,
4983
id_edge_to=id_edge_to,
4984
position_edge_to=pos_edge_to,
4985
)
4986
else:
4987
id_stage_walk1, time = walkstages.append_stage(id_plan, time_from,
4988
id_edge_from=id_edge_from,
4989
position_edge_from=pos_edge_from,
4990
id_edge_to=id_stopedge_from,
4991
position_edge_to=pos_stop_from, # -7.0,
4992
)
4993
4994
# take PRT
4995
# self.ids_edge_to_ids_prtstop
4996
id_stage_transit, time = prtstages.append_stage(
4997
id_plan, time,
4998
duration=times_stop_to_stop[id_stop_from, id_stop_to],
4999
id_fromedge=id_stopedge_from,
5000
id_toedge=id_stopedge_to,
5001
)
5002
5003
# walk from final prtstop to activity
5004
# print ' Stage for linktype %2d fromedge %s toedge %s'%(linktype, edges.ids_sumo[id_stopedge_to],edges.ids_sumo[id_edge_to] )
5005
id_stage_walk2, time = walkstages.append_stage(id_plan, time,
5006
id_edge_from=id_stopedge_to,
5007
position_edge_from=pos_stop_to,
5008
id_edge_to=id_edge_to,
5009
position_edge_to=pos_edge_to,
5010
)
5011
5012
# update time for trips estimation for this plan
5013
plans.times_est[id_plan] += time-time_from
5014
5015
# define current end time without last activity duration
5016
plans.times_end[id_plan] = time
5017
5018
id_stage_act, time = activitystages.append_stage(
5019
id_plan, time,
5020
ids_to=id_act_to,
5021
names_totype=name_acttype_to,
5022
durations=duration_act_to,
5023
ids_lane=edges.ids_lanes[id_edge_to][0],
5024
positions=pos_edge_to,
5025
)
5026
5027
# store time for next iteration in case other activities are
5028
# following
5029
map_times[id_person] = time
5030
5031
# select persons and activities for next setp
5032
ind_act += 1
5033
ids_person_act, ids_act_from, ids_act_to\
5034
= virtualpop.get_activities_from_pattern(ind_act, ids_person=ids_person_act)
5035
5036
5037
class PrtTransits(StageTypeMixin):
5038
def __init__(self, ident, stages,
5039
name='Ride on PRT',
5040
info='Ride on Personal Rapid Transit network.',
5041
# **kwargs,
5042
):
5043
5044
print 'PrtTransits.__init__', ident, stages
5045
self.init_stagetable(ident,
5046
stages, name=name,
5047
info=info,
5048
)
5049
self._init_attributes()
5050
self._init_constants()
5051
5052
def _init_attributes(self):
5053
edges = self.get_virtualpop().get_net().edges
5054
5055
self.add_col(am.IdsArrayConf('ids_fromedge', edges,
5056
groupnames=['parameters'],
5057
name='Edge ID from',
5058
info='Edge ID of departure PRT station.',
5059
))
5060
5061
self.add_col(am.IdsArrayConf('ids_toedge', edges,
5062
groupnames=['parameters'],
5063
name='Edge ID to',
5064
info='Edge ID of destination PRT station.',
5065
))
5066
5067
def set_prtservice(self, prtservice):
5068
self.add(cm.ObjConf(prtservice, is_child=False, groups=['_private']))
5069
5070
def get_prtservice(self):
5071
return self.prtservice.get_value()
5072
5073
def prepare_planning(self):
5074
5075
prtservice = self.get_prtservice()
5076
print 'prttransits.prepare_planning', prtservice.times_stop_to_stop
5077
if prtservice.times_stop_to_stop is None:
5078
prtservice.make_times_stop_to_stop()
5079
print prtservice.times_stop_to_stop
5080
5081
def append_stage(self, id_plan, time_start=-1.0,
5082
duration=0.0,
5083
id_fromedge=-1, id_toedge=-1, **kwargs):
5084
"""
5085
Appends a PRT transit stage to plan id_plan.
5086
5087
"""
5088
# print 'PrtTransits.append_stage',id_stage
5089
5090
id_stage, time_end = StageTypeMixin.append_stage(self,
5091
id_plan,
5092
time_start,
5093
durations=duration,
5094
ids_fromedge=id_fromedge,
5095
ids_toedge=id_toedge,
5096
)
5097
5098
# add this stage to the vehicle database
5099
# ind_ride gives the index of this ride (within the same plan??)
5100
#ind_ride = self.parent.get_individualvehicles().append_ride(id_veh, id_stage)
5101
return id_stage, time_end
5102
5103
def to_xml(self, id_stage, fd, indent=0):
5104
# <ride from="1/3to0/3" to="0/4to1/4" lines="train0"/>
5105
net = self.get_virtualpop().get_net()
5106
#ids_stoplane = net.ptstops.ids_lane
5107
#ids_laneedge = net.lanes.ids_edge
5108
ids_sumoedge = net.edges.ids_sumo
5109
5110
#ind = self.get_ind(id_stage)
5111
fd.write(xm.start('ride', indent=indent))
5112
fd.write(xm.num('from', ids_sumoedge[self.ids_fromedge[id_stage]]))
5113
fd.write(xm.num('to', ids_sumoedge[self.ids_toedge[id_stage]]))
5114
fd.write(xm.num('lines', 'prt'))
5115
# if self.cols.pos_edge_from[ind]>0:
5116
# fd.write(xm.num('departPos', self.cols.pos_edge_from[ind]))
5117
# if self.cols.pos_edge_to[ind]>0:
5118
# fd.write(xm.num('arrivalPos', self.cols.pos_edge_to[ind]))
5119
5120
fd.write(xm.stopit()) # ends stage
5121
5122
5123
class VehicleMan(am.ArrayObjman):
5124
def __init__(self, ident, prtservices, **kwargs):
5125
self._init_objman(ident=ident,
5126
parent=prtservices,
5127
name='PRT vehicle management',
5128
info='PRT vehicle management.',
5129
#xmltag = ('additional','busStop','stopnames'),
5130
version=0.0,
5131
**kwargs)
5132
5133
self._init_attributes()
5134
self._init_constants()
5135
5136
def _init_attributes(self):
5137
self.add(cm.AttrConf('time_update', 2.0,
5138
groupnames=['parameters'],
5139
name='Man. update time',
5140
info="Update time for vehicle management.",
5141
unit='s',
5142
))
5143
5144
# self.time_update.set(5.0)
5145
5146
self.add(cm.AttrConf('time_update_flows', 10.0,
5147
groupnames=['parameters'],
5148
name='Flow update time',
5149
info="Update time for flow estimations.",
5150
unit='s',
5151
))
5152
# self.time_update.set(10.0)
5153
# if hasattr(self,'time_flowaverage'):
5154
# self.delete('time_flowaverage')
5155
5156
self.add(cm.AttrConf('time_est_max', 1200,
5157
groupnames=['parameters'],
5158
name='prediction interval',
5159
info="Prediction time range of vehicle management.",
5160
unit='s',
5161
))
5162
5163
self.add(cm.AttrConf('time_search_occupied', 10.0,
5164
groupnames=['parameters'],
5165
name='Occupied search time',
5166
info="Time interval for search of optimum departure time in case of an occupied vehicle trip.",
5167
unit='s',
5168
))
5169
5170
self.add(cm.AttrConf('time_search_empty', 20.0,
5171
groupnames=['parameters'],
5172
name='Empty search time',
5173
info="Time interval for search of optimum departure time in case of an empty vehicle trip.",
5174
unit='s',
5175
))
5176
5177
self.add(cm.AttrConf('weight_demand', 0.01,
5178
groupnames=['parameters'],
5179
name='Demand weight',
5180
info="Weight of current demand at stations when assigning empty vehicles trips.",
5181
))
5182
5183
self.add(cm.AttrConf('weight_flow', 1.0,
5184
groupnames=['parameters'],
5185
name='Flow weight',
5186
info="Weight of flows (changes in demand over time) at stations when assigning empty vehicles trips.",
5187
))
5188
5189
self.add(cm.AttrConf('constant_timeweight', 0.005,
5190
groupnames=['parameters'],
5191
name='Time weight const.',
5192
info="Constant for the exponential decay function weighting the time instance in the optimization function.",
5193
unit='1/s',
5194
))
5195
5196
# def set_stops(self,vehicleman):
5197
# self.add( cm.ObjConf( stops, is_child = False,groups = ['_private']))
5198
5199
def _init_constants(self):
5200
self.do_not_save_attrs([
5201
'ids_stop', 'numbers_veh_arr', 'n_est_max',
5202
'inflows_sched', 'inflows_person', 'inflows_person_last',
5203
'ids_veh', 'ids_stop_target', 'ids_stop_current',
5204
'times_order', 'occupiedtrips_new', 'emptytrips_new',
5205
'are_emptytrips',
5206
'log_inflows_temp',
5207
])
5208
5209
def get_stops(self):
5210
return self.parent.prtstops
5211
5212
def get_vehicles(self):
5213
return self.parent.prtvehicles
5214
5215
def get_scenario(self):
5216
return self.parent.parent.get_scenario()
5217
5218
def prepare_sim(self, process):
5219
print 'VehicleMan.prepare_sim'
5220
net = self.get_scenario().net
5221
# station management
5222
# self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1,dtype = np.object)
5223
5224
self.ids_stop = self.get_stops().get_ids()
5225
5226
if len(self.ids_stop) == 0:
5227
return []
5228
5229
n_stoparray = np.max(self.ids_stop)+1
5230
self.numbers_veh_arr = np.zeros(n_stoparray, dtype=np.int32)
5231
5232
#self.n_est_max = self.time_est_max.get_value()/self.time_update_flows.get_value()
5233
self.n_est_max = int(self.time_est_max.get_value()/self.time_update_flows.get_value())
5234
self.inflows_sched = np.zeros((n_stoparray, self.n_est_max), dtype=np.int32)
5235
self.inflows_person = np.zeros(n_stoparray, dtype=np.int32)
5236
self.inflows_person_last = np.zeros(n_stoparray, dtype=np.int32)
5237
# vehicle management
5238
self.ids_veh = self.get_vehicles().get_ids()
5239
5240
if len(self.ids_veh) == 0:
5241
print 'WARNING: no PRT vehicles, please add PRT vehicles.'
5242
return []
5243
5244
n_veharray = np.max(self.ids_veh)+1
5245
5246
# could go in vehicle array
5247
self.ids_stop_target = -1*np.ones(n_veharray, dtype=np.int32)
5248
self.ids_stop_current = -1*np.ones(n_veharray, dtype=np.int32)
5249
self.times_order = 10**6*np.ones(n_veharray, dtype=np.int32)
5250
# self.occupiedtrips_new = []#?? put this is also in general time scheme with more urgency??
5251
#self.emptytrips_new = []
5252
5253
# from veh arrays
5254
#self.are_emptytrips = np.zeros(n_veharray, dtype = np.bool)
5255
5256
# logging
5257
results = process.get_results()
5258
if results is not None:
5259
time_update_flows = self.time_update_flows.get_value()
5260
n_timesteps = int((process.duration-process.time_warmup)/time_update_flows+1)
5261
results.prtstopresults.init_recording(n_timesteps, time_update_flows)
5262
5263
self.log_inflows_temp = np.zeros(n_stoparray, dtype=np.int32)
5264
5265
return [(self.time_update.get_value(), self.process_step),
5266
(self.time_update_flows.get_value(), self.update_flows),
5267
]
5268
5269
def update_flows(self, process):
5270
# print 'update flow prediction'
5271
self.inflows_sched[:, 0] = 0
5272
self.inflows_sched = np.roll(self.inflows_sched, -1)
5273
time_update_flows = self.time_update_flows.get_value()
5274
5275
if process.simtime > process.time_warmup:
5276
stops = self.get_stops()
5277
ids_stop = self.ids_stop
5278
prtstopresults = process.get_results().prtstopresults
5279
const_time = 1.0/time_update_flows # np.array([1.0/time_update_flows],dtype=np.float32)
5280
timestep = (process.simtime - process.simtime_start - process.time_warmup)/time_update_flows
5281
prtstopresults.record(timestep, ids_stop,
5282
inflows_veh=np.array(const_time * self.log_inflows_temp[ids_stop], dtype=np.float32),
5283
inflows_veh_sched=np.array(
5284
const_time * self.inflows_sched[ids_stop, 0], dtype=np.float32),
5285
numbers_person_wait=stops.numbers_person_wait[ids_stop],
5286
waittimes_tot=stops.waittimes_tot[ids_stop],
5287
inflows_person=np.array(const_time * self.inflows_person[ids_stop], dtype=np.float32),
5288
#inflows_person = stops.flows_person[ids_stop],
5289
)
5290
5291
self.inflows_person_last = self.inflows_person.copy()
5292
self.inflows_person[:] = 0
5293
self.log_inflows_temp[:] = 0
5294
5295
def process_step(self, process):
5296
print 79*'M'
5297
print 'VehicleMan.process_step'
5298
5299
stops = self.get_stops()
5300
#vehicles = self.get_vehicles()
5301
5302
has_programmed = True
5303
ids_veh_lead = stops.ids_veh_lead[self.ids_stop]
5304
inds_valid = np.flatnonzero(ids_veh_lead >= 0)
5305
while has_programmed:
5306
has_programmed = False
5307
5308
if len(inds_valid) > 0:
5309
5310
has_programmed |= self.push_occupied_leadvehs(ids_veh_lead[inds_valid], process)
5311
ids_veh_lead = stops.ids_veh_lead[self.ids_stop]
5312
inds_valid = np.flatnonzero(ids_veh_lead >= 0)
5313
# print ' self.ids_stop',self.ids_stop
5314
# print ' ids_veh_lead',ids_veh_lead
5315
has_programmed |= self.push_empty_leadvehs(ids_veh_lead[inds_valid], process)
5316
ids_veh_lead = stops.ids_veh_lead[self.ids_stop]
5317
inds_valid = np.flatnonzero(ids_veh_lead >= 0)
5318
5319
#has_programmed |= self.pull_empty_leadvehs(ids_veh_lead[inds_valid],process)
5320
#ids_veh_lead = stops.ids_veh_lead[self.ids_stop]
5321
#inds_valid = np.flatnonzero(ids_veh_lead >= 0)
5322
# print ' main:ids_veh_lead',has_programmed,len(inds_valid), stops.ids_veh_lead[self.ids_stop]
5323
else:
5324
# no more leaders
5325
has_programmed = False
5326
# print '\n terminated vehicle man n_est_max',self.n_est_max
5327
# print ' inflows_sched=\n',self.inflows_sched
5328
5329
def note_person_entered(self, id_stop, id_person_sumo, id_stop_dest):
5330
# here just estimate person flows
5331
self.inflows_person[id_stop] += 1
5332
5333
def push_occupied_leadvehs(self, ids_veh_lead, process):
5334
n_timeslot_offset = 3
5335
n_searchint = int(self.time_search_occupied.get_value()/self.time_update_flows.get_value()+0.5)
5336
stops = self.get_stops()
5337
vehicles = self.get_vehicles()
5338
5339
inds_valid = np.flatnonzero(vehicles.states[ids_veh_lead] == VEHICLESTATES['occupiedtrip'])
5340
if len(inds_valid) == 0:
5341
return False
5342
print 'push_occupied_leadvehs ids_veh_lead', ids_veh_lead[inds_valid]
5343
times_stop_to_stop = self.parent.times_stop_to_stop
5344
ids_stop_current = self.ids_stop_current[ids_veh_lead[inds_valid]]
5345
ids_stop_target = self.ids_stop_target[ids_veh_lead[inds_valid]]
5346
durations_est = times_stop_to_stop[ids_stop_current, ids_stop_target]
5347
# print ' duration_est, t_est_max',durations_est,self.n_est_max*self.time_update_flows.get_value()
5348
5349
inds_time_min = n_timeslot_offset+np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value(
5350
), dtype=np.int32), 0, self.n_est_max-n_searchint-n_timeslot_offset), dtype=np.int32)
5351
inds_time_max = inds_time_min+n_searchint
5352
# print ' inds_time_min unclipped',n_timeslot_offset+np.array(1.0*durations_est/self.time_update_flows.get_value(),dtype=np.int32)
5353
# print ' inds_time_min clipped',inds_time_min
5354
# print ' inds_time_max',inds_time_max, self.inflows_sched.shape
5355
5356
for id_veh_lead, state, id_stop_current, id_stop_target, time_order, ind_min, ind_max, duration_est\
5357
in zip(
5358
ids_veh_lead[inds_valid],
5359
vehicles.states[ids_veh_lead[inds_valid]],
5360
self.ids_stop_current[ids_veh_lead[inds_valid]],
5361
self.ids_stop_target[ids_veh_lead[inds_valid]],
5362
self.times_order[ids_veh_lead[inds_valid]],
5363
inds_time_min,
5364
inds_time_max,
5365
durations_est,
5366
):
5367
5368
print ' check veh', id_veh_lead, state, 'id_stop_current', id_stop_current, 'id_stop_target', id_stop_target
5369
5370
#VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6}
5371
# if state == VEHICLESTATES['occupiedtrip']:
5372
5373
#ids_stop = list(self.ids_stop)
5374
# ids_stop.remove(id_stop)
5375
#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]
5376
#ids_stop [np.argmax(costs)]
5377
inds_time = np.arange(ind_min, ind_max)
5378
costs = self.inflows_sched[id_stop_target, inds_time]
5379
# print ' inds_time',inds_time
5380
# print ' inflows_sched',costs
5381
ind_time_depart = inds_time[np.argmin(costs)]
5382
5383
time_depart = process.simtime + ind_time_depart*self.time_update_flows.get_value()-duration_est
5384
# print ' ind_time_depart, time_arr, duration_est',ind_time_depart,process.simtime + ind_time_depart*self.time_update_flows.get_value(),duration_est
5385
# print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order
5386
5387
stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart)
5388
self.numbers_veh_arr[id_stop_target] += 1
5389
self.inflows_sched[id_stop_target, ind_time_depart] += 1
5390
5391
return True # at least one vehicle assigned
5392
5393
def push_empty_leadvehs(self, ids_veh_lead, process):
5394
n_timeslot_offset = 3
5395
stops = self.get_stops()
5396
vehicles = self.get_vehicles()
5397
inds_valid = np.flatnonzero(vehicles.states[ids_veh_lead] == VEHICLESTATES['emptytrip'])
5398
if len(inds_valid) == 0:
5399
return False
5400
5401
print 'push_empty_leadvehs ids_veh_lead', ids_veh_lead[inds_valid]
5402
times_stop_to_stop = self.parent.times_stop_to_stop
5403
ids_stop_current = self.ids_stop_current[ids_veh_lead[inds_valid]]
5404
5405
n_stop_target = len(self.ids_stop)
5406
ids_stop_target = self.ids_stop.reshape(n_stop_target, 1)
5407
flow_person_est = (stops.flows_person[ids_stop_target] *
5408
self.time_update_flows.get_value()).reshape(n_stop_target, 1)
5409
n_searchint = int(self.time_search_empty.get_value()/self.time_update_flows.get_value()+0.5)
5410
inds_search_base = n_timeslot_offset + \
5411
np.arange(n_searchint, dtype=np.int32) * np.ones((n_stop_target, n_searchint), dtype=np.int32)
5412
5413
#self.numbers_veh = np.zeros(np.max(ids)+1, dtype = np.int32)
5414
#self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype = np.int32)
5415
#self.flows_person = np.zeros(np.max(ids)+1, dtype = np.float32)
5416
#self.ids_veh_lead = -1*np.ones(np.max(ids)+1,dtype = np.int32)
5417
#self.ids_vehs_prog = np.zeros(np.max(ids)+1,dtype = np.object)
5418
is_started = False
5419
for id_veh_lead, id_stop_current, time_order, \
5420
in zip(
5421
ids_veh_lead[inds_valid],
5422
self.ids_stop_current[ids_veh_lead[inds_valid]],
5423
self.times_order[ids_veh_lead[inds_valid]],
5424
):
5425
5426
#id_stop_target = self.get_stop_emptytrip(id_stop_current)
5427
5428
durations_est = times_stop_to_stop[id_stop_current, ids_stop_target]
5429
ind_stop_current = np.flatnonzero(durations_est == 0)[0]
5430
print ' check veh', id_veh_lead, 'id_stop_current', id_stop_current, 'ind_stop_current', ind_stop_current
5431
inds_time_min = np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value(),
5432
dtype=np.int32), 0, self.n_est_max-n_searchint), dtype=np.int32)
5433
inds_search = inds_search_base + inds_time_min.reshape(n_stop_target, 1)
5434
timeweight = np.exp(-self.constant_timeweight.get_value() * inds_search*self.time_update_flows.get_value())
5435
5436
# print ' demand',stops.numbers_person_wait[ids_stop_target]
5437
5438
costs = (self.weight_demand.get_value() * stops.waittimes_tot[ids_stop_target]
5439
+ self.weight_flow.get_value() * (flow_person_est-self.inflows_sched[ids_stop_target, inds_search])
5440
) * timeweight
5441
# costs = ( self.weight_demand.get_value() * ( stops.numbers_person_wait[ids_stop_target])\
5442
# + self.weight_flow.get_value() * (flow_person_est-self.inflows_sched[ids_stop_target, inds_search])\
5443
# )* timeweight
5444
5445
#costs = np.exp(+self.inflows_sched[ids_stop_target, inds_search]-flow_person_est)*timeweight
5446
#costs = (self.inflows_sched[ids_stop_target, inds_search]-flow_person_est)*timeweight
5447
costs[ind_stop_current, :] = -999999
5448
if 0:
5449
for ind, id_stop in zip(range(n_stop_target), ids_stop_target):
5450
print 40*'.'
5451
print ' id_stop', id_stop
5452
print ' waittimes_tot', stops.waittimes_tot[id_stop]
5453
print ' numbers_person_wait', stops.numbers_person_wait[id_stop]
5454
print ' flow_person_est', flow_person_est[ind]
5455
print ' inflows_sched', self.inflows_sched[id_stop, inds_search[ind]]
5456
print ' delta flow', (flow_person_est[ind]-self.inflows_sched[id_stop, inds_search[ind]])
5457
print ' demandcomp', self.weight_demand.get_value() * stops.numbers_person_wait[id_stop]
5458
print ' flowcomp', self.weight_flow.get_value() * (flow_person_est[ind]-self.inflows_sched[id_stop, inds_search[ind]])
5459
print ' arrivaltime est', inds_search[ind]*self.time_update_flows.get_value()
5460
print ' flow_person_est', flow_person_est[ind]
5461
print
5462
5463
# print ' flow_person_est',flow_person_#est
5464
print ' timeweight', timeweight[ind]
5465
print ' durations_est', durations_est[ind]
5466
print ' inds_search_base', inds_search_base[ind]
5467
# print ' inds_search unclipped\n',inds_search_base +np.array(1.0*durations_est/self.time_update_flows.get_value(),dtype=np.int32).reshape(n_stop_target,1)
5468
print ' inds_search clipped \n', inds_search[ind]
5469
print ' inds_time_min', inds_time_min[ind]
5470
# print ' ind_stop_current',ind_stop_current,durations_est[ind_stop_current]
5471
print ' costs=\n', costs[ind]
5472
# constant_timeweight
5473
5474
#
5475
ind_target = np.argmax(costs)
5476
ind_stop_target = ind_target/n_searchint
5477
#ind_time_arrive = ind_target%n_searchint+inds_time_min[ind_stop_target]
5478
ind_time_delta = ind_target % n_searchint
5479
ind_time_arrive = inds_search[ind_stop_target, ind_time_delta]
5480
if 0:
5481
print ' ind_target,n_searchint,ind_stop_target,ind_time_delta', ind_target, n_searchint, ind_target/n_searchint, ind_time_delta
5482
print ' ind_delta_depart,c_min', costs[ind_stop_target, ind_time_delta]
5483
print ' inds_time_min,ind_time_arrive', inds_time_min[ind_stop_target], ind_time_arrive
5484
5485
id_stop_target = ids_stop_target[ind_stop_target][0]
5486
time_depart = process.simtime + ind_time_arrive * \
5487
self.time_update_flows.get_value()-durations_est[ind_stop_target]
5488
# print '\n id_stop_target',id_stop_target
5489
# print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order
5490
5491
is_started = stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart)
5492
if is_started:
5493
self.numbers_veh_arr[id_stop_target] += 1
5494
self.inflows_sched[id_stop_target, ind_time_arrive] += 1
5495
else:
5496
print 'WARNING in push_empty_leadvehs: no vehicle prt.%d in stop %d' % (id_veh_lead, id_stop_target)
5497
return is_started
5498
5499
def pull_empty_leadvehs(self, ids_veh_lead, process):
5500
5501
n_timeslot_offset = 2
5502
5503
#self.numbers_veh = np.zeros(np.max(ids)+1, dtype = np.int32)
5504
#self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype = np.int32)
5505
5506
# inds_valid = np.flatnonzero( (vehicles.states[ids_veh_lead] == VEHICLESTATES['waiting'])\
5507
# & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0))
5508
vehicles = self.get_vehicles()
5509
stops = self.get_stops()
5510
print 'pull_empty_leadvehs', ids_veh_lead
5511
# print ' bordingstate',vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding']
5512
# print ' nowaits stop',stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] ==0
5513
5514
times_stop_to_stop = self.parent.times_stop_to_stop
5515
5516
# get potential pull vehicles
5517
inds_valid = np.flatnonzero((vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding'])
5518
& (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0))
5519
5520
# print ' states',vehicles.states[ids_veh_lead], VEHICLESTATES['boarding']
5521
# print ' numbers_person_wait',stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]]
5522
# print ' &',(vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding'])\
5523
# & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0)
5524
# print ' origins inds_valid',inds_valid
5525
if len(inds_valid) == 0:
5526
# print ' all stops busy'
5527
return False
5528
5529
#ids_veh_lead = ids_veh_lead[inds_valid]
5530
ids_stop_current = self.ids_stop_current[ids_veh_lead[inds_valid]]
5531
5532
# print ' available for pulling ids_veh_lead',ids_veh_lead
5533
# print ' ids_stop_current',ids_stop_current
5534
# get potential target station with demand
5535
demands = stops.numbers_person_wait[self.ids_stop]\
5536
- (0.5*stops.numbers_veh[self.ids_stop]
5537
+ self.numbers_veh_arr[self.ids_stop])
5538
inds_valid = np.flatnonzero(demands > 0)
5539
# print ' targets inds_valid',inds_valid
5540
if len(inds_valid) == 0:
5541
# print ' no demand'
5542
return False
5543
5544
ids_stop_target = self.ids_stop[inds_valid]
5545
demands = demands[inds_valid]
5546
5547
print ' ids_stop_current', ids_stop_current
5548
# print ' ids_stop_target',ids_stop_target
5549
# print ' demands',demands
5550
# calculate cost matrix with id_stop_current in rows and id_stop_target
5551
5552
#n_origin = len(ids_stop_current)
5553
#n_targets = len(ids_stop_target)
5554
times = times_stop_to_stop[ids_stop_current, :][:, ids_stop_target]
5555
times[times == 0] = 99999
5556
timeweight = np.exp(-self.constant_timeweight.get_value() * times)
5557
#costs = times_stop_to_stop[ids_stop_current,:][:,ids_stop_target]
5558
#costs[costs == 0] = 99999
5559
# print ' timeweight\n',timeweight
5560
5561
costs = timeweight * demands
5562
for id_stop_target, demand, number_veh, number_veh_arr\
5563
in zip(ids_stop_target, demands, stops.numbers_veh[ids_stop_target], self.numbers_veh_arr[ids_stop_target]):
5564
print ' id_stop_target', id_stop_target, 'dem', demand, 'n_veh', number_veh, 'n_veh_arr', number_veh_arr
5565
5566
#costs = np.zeros(costs.size, np.float32)-demands
5567
5568
inds_pull = np.argmax(costs, 1)
5569
# print ' costs\n',costs
5570
# print ' ->inds_pull,ids_stop_target',inds_pull,ids_stop_target[inds_pull]
5571
5572
durations_est = times_stop_to_stop[ids_stop_current, ids_stop_target[inds_pull]]
5573
# print ' duration_est, t_est_max',durations_est,self.n_est_max*self.time_update_flows.get_value()
5574
5575
inds_time_min = n_timeslot_offset+np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value(
5576
), dtype=np.int32), 0, self.n_est_max-1-n_timeslot_offset), dtype=np.int32)
5577
inds_time_max = inds_time_min+2
5578
# print ' inds_time_min',inds_time_min
5579
# print ' inds_time_max',inds_time_max
5580
5581
is_started = False
5582
for id_veh_lead, state, id_stop_current, id_stop_target, time_order, ind_min, ind_max, duration_est\
5583
in zip(
5584
ids_veh_lead[inds_valid],
5585
vehicles.states[ids_veh_lead],
5586
ids_stop_current,
5587
ids_stop_target[inds_pull],
5588
self.times_order[ids_veh_lead],
5589
inds_time_min,
5590
inds_time_max,
5591
durations_est,
5592
):
5593
5594
print ' check veh prt.%d' % (id_veh_lead), state, 'id_stop_current', id_stop_current, 'id_stop_target', id_stop_target
5595
5596
#VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6}
5597
# if state == VEHICLESTATES['occupiedtrip']:
5598
5599
#ids_stop = list(self.ids_stop)
5600
# ids_stop.remove(id_stop)
5601
#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]
5602
#ids_stop [np.argmax(costs)]
5603
inds_time = np.arange(ind_min, ind_max)
5604
costs = self.inflows_sched[id_stop_current, inds_time]
5605
ind_time_depart = inds_time[np.argmin(costs)]
5606
5607
self.inflows_sched[id_stop_target, ind_time_depart] += 1
5608
time_depart = process.simtime + ind_time_depart*self.time_update_flows.get_value()-duration_est
5609
5610
# this is a workarouned that vehicle does first reach the stopline
5611
# before it gets rescheduled...try with stoplinecheck
5612
5613
# if time_depart < process.simtime+15:
5614
# time_depart = process.simtime+15
5615
# print ' ind_time_depart, time_arr, duration_est',ind_time_depart,process.simtime + ind_time_depart*self.time_update_flows.get_value(),duration_est
5616
# print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order
5617
5618
stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart)
5619
self.numbers_veh_arr[id_stop_target] += 1
5620
is_started = True
5621
5622
return is_started
5623
5624
def init_trip_occupied(self, id_veh, id_stop_from, id_stop_to, time_order):
5625
# print 'init_trip_occupied from',id_veh, id_stop_from, id_stop_to
5626
# search closest stop
5627
#self.are_emptytrips[id_veh] = False
5628
5629
self.ids_stop_current[id_veh] = id_stop_from
5630
self.ids_stop_target[id_veh] = id_stop_to
5631
self.times_order[id_veh] = time_order
5632
# print ' to stop',id_stop
5633
# return id_stop_to
5634
5635
def init_trip_empty(self, id_veh, id_stop, time_order):
5636
# print 'VehMan.init_trip_empty id_veh prt.%d,id_stop %d'%(id_veh,id_stop)
5637
# search closest stop
5638
self.ids_stop_current[id_veh] = id_stop
5639
self.times_order[id_veh] = time_order
5640
#self.are_emptytrips[id_veh] = True
5641
#id_stop_target = ids_stop[random.randint(0,len(ids_stop)-1)]
5642
# print ' to stop',id_stop
5643
# return id_stop_target
5644
5645
def indicate_trip_empty(self, id_veh, id_stop, time_order):
5646
# print 'indicate_trip_empty id_veh,id_stop',id_veh,id_stop
5647
# search closest stop
5648
self.ids_stop_current[id_veh] = id_stop
5649
self.times_order[id_veh] = time_order
5650
5651
def get_stop_emptytrip(self, id_stop):
5652
stops = self.get_stops()
5653
ids_stop = list(self.ids_stop)
5654
ids_stop.remove(id_stop)
5655
costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop] -
5656
self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop, ids_stop]
5657
5658
return ids_stop[np.argmax(costs)]
5659
5660
def conclude_trip(self, id_veh, id_stop):
5661
self.ids_stop_target[id_veh] = -1
5662
self.numbers_veh_arr[id_stop] -= 1
5663
5664
# measures actually arrived vehicles at stop
5665
# accumulates counts over one flow measurement interval
5666
self.log_inflows_temp[id_stop] += 1
5667
5668
5669
class PrtService(SimobjMixin, DemandobjMixin, cm.BaseObjman):
5670
def __init__(self, ident, simulation=None,
5671
name='PRT service', info='PRT service',
5672
**kwargs):
5673
# print 'PrtService.__init__',name
5674
5675
self._init_objman(ident=ident, parent=simulation,
5676
name=name, info=info, **kwargs)
5677
5678
attrsman = self.set_attrsman(cm.Attrsman(self))
5679
5680
# make PRTservice a demand object as link
5681
self.get_scenario().demand.add_demandobject(obj=self)
5682
5683
self._init_attributes()
5684
self._init_constants()
5685
5686
def get_scenario(self):
5687
return self.parent.parent
5688
5689
def _init_attributes(self):
5690
# print 'PrtService._init_attributes',hasattr(self,'prttransit')
5691
attrsman = self.get_attrsman()
5692
scenario = self.get_scenario()
5693
# here we ged classes not vehicle type
5694
# specific vehicle type within a class will be generated later
5695
modechoices = scenario.net.modes.names.get_indexmap()
5696
5697
# print ' modechoices',modechoices
5698
self.id_prtmode = attrsman.add(am.AttrConf('id_prtmode', modechoices['custom1'],
5699
groupnames=['options'],
5700
choices=modechoices,
5701
name='Mode',
5702
info='PRT transport mode (or vehicle class).',
5703
))
5704
5705
self.prtstops = attrsman.add(cm.ObjConf(PrtStops('prtstops', self)))
5706
self.compressors = attrsman.add(cm.ObjConf(Compressors('compressors', self)))
5707
self.decompressors = attrsman.add(cm.ObjConf(Decompressors('decompressors', self)))
5708
self.mergenodes = attrsman.add(cm.ObjConf(Mergenodes('mergenodes', self)))
5709
self.prtvehicles = attrsman.add(cm.ObjConf(PrtVehicles('prtvehicles', self)))
5710
self.vehicleman = attrsman.add(cm.ObjConf(VehicleMan('vehicleman', self)))
5711
5712
#self.demo = attrsman.add( cm.ObjConf(TraciDemo('demo',self)))
5713
5714
# --------------------------------------------------------------------
5715
# prt transit table
5716
# attention: prttransits will be a child of virtual pop,
5717
# and a link from prt service
5718
5719
# if not hasattr(self,'prttransit'):
5720
virtualpop = self.get_scenario().demand.virtualpop
5721
prttransits = virtualpop.get_plans().add_stagetable('prttransits', PrtTransits)
5722
5723
# print ' prttransits =',prttransits
5724
# add attribute as link
5725
# self.prttransits = attrsman.add(\
5726
# cm.ObjConf(prttransits,is_child = False ),
5727
# is_overwrite = False,)
5728
prttransits.set_prtservice(self)
5729
5730
prtstrategy = virtualpop.get_strategies().add_strategy(
5731
'prt', PrtStrategy, np.array([208, 50, 156, 230], np.float32)/255)
5732
# self.prttransits = attrsman.add(\
5733
# cm.ObjConf(prttransits,is_child = False ),
5734
# is_overwrite = False,)
5735
prtstrategy.set_prtservice(self)
5736
5737
# temporary attrfix
5738
#prtserviceconfig = self.parent.get_attrsman().prtservice
5739
#prtserviceconfig.groupnames = []
5740
#prtserviceconfig.add_groupnames(['demand objects'])
5741
5742
def _init_constants(self):
5743
# print 'PrtService._init_constants',self,self.parent
5744
attrsman = self.get_attrsman()
5745
self.times_stop_to_stop = None
5746
self.fstar = None
5747
self._results = None
5748
5749
attrsman.do_not_save_attrs(['times_stop_to_stop', 'fstar', '_results'
5750
'times_stop_to_stop', 'ids_edge_to_ids_prtstop',
5751
])
5752
5753
def get_vtypes(self):
5754
5755
ids_vtypes = set(self.prtvehicles.ids_vtype.get_value())
5756
return ids_vtypes
5757
5758
def get_writexmlinfo(self, is_route=False, is_plain=False, **kwargs):
5759
"""
5760
Returns three array where the first array is the
5761
begin time of the first vehicle and the second array is the
5762
write function to be called for the respectice vehicle and
5763
the third array contains the vehicle ids
5764
5765
Method used to sort trips when exporting to route or trip xml file
5766
"""
5767
print 'PRT.get_writexmlinfo'
5768
5769
# time of first PRT vehicle(s) to be inserted
5770
virtualpop = self.get_scenario().demand.virtualpop
5771
t_start = virtualpop.get_time_depart_first()
5772
5773
#t_start = 0.0
5774
# time between insertion of consecutive vehicles at same stop
5775
t_delta = 10 # s
5776
5777
n_veh = len(self.prtvehicles)
5778
times_depart = np.zeros(n_veh, dtype=np.int32)
5779
writefuncs = np.zeros(n_veh, dtype=np.object)
5780
writefuncs[:] = self.write_prtvehicle_xml
5781
ids_veh = self.prtvehicles.get_ids()
5782
5783
id_edge_prev = -1
5784
i = 0
5785
t0 = t_start
5786
for id_edge in self.prtvehicles.ids_currentedge[ids_veh]:
5787
# print ' id_edge, t_start, id_edge_prev',id_edge, t0, id_edge_prev
5788
times_depart[i] = t0
5789
t0 += t_delta
5790
if id_edge != id_edge_prev:
5791
t0 = t_start
5792
id_edge_prev = 1*id_edge
5793
i += 1
5794
5795
return times_depart, writefuncs, ids_veh
5796
5797
def write_prtvehicle_xml(self, fd, id_veh, time_begin, indent=2):
5798
# print 'write_prtvehicle_xml',id_veh, time_begin
5799
# TODO: actually this should go in prtvehicles
5800
#time_veh_wait_after_stop = 3600
5801
scenario = self.get_scenario()
5802
net = scenario.net
5803
5804
#lanes = net.lanes
5805
edges = net.edges
5806
#ind_ride = rides.get_inds(id_stage)
5807
#id_veh = rides.ids_veh[id_stage]
5808
prtvehicles = self.prtvehicles
5809
#ptstops = net.ptstops
5810
#prtstops = self.parent.prtstops
5811
#ids_prtstop = prtstops.get_ids()
5812
#ids_ptstop = prtstops.ids_ptstop[id_stop]
5813
# lanes.ids_edge[ptstops.ids_lane[ids_ptstop]],
5814
#id_lane_from = parking.ids_lane[id_parking_from]
5815
#laneindex_from = lanes.indexes[id_lane_from]
5816
#pos_from = parking.positions[id_parking_from]
5817
5818
#id_parking_to = rides.ids_parking_to[id_stage]
5819
#id_lane_to = parking.ids_lane[id_parking_to]
5820
#laneindex_to = lanes.indexes[id_lane_to]
5821
#pos_to = parking.positions[id_parking_to]
5822
5823
# write unique veh ID to prevent confusion with other veh declarations
5824
fd.write(xm.start('vehicle id="%s"' % prtvehicles.get_id_sumo(id_veh), indent+2))
5825
5826
fd.write(xm.num('depart', '%d' % time_begin))
5827
fd.write(xm.num('type', scenario.demand.vtypes.ids_sumo[prtvehicles.ids_vtype[id_veh]]))
5828
fd.write(xm.num('line', prtvehicles.get_id_line_xml()))
5829
fd.write(xm.stop())
5830
5831
# write route
5832
fd.write(xm.start('route', indent+4))
5833
# print ' edgeindex[ids_edge]',edgeindex[ids_edge]
5834
fd.write(xm.arr('edges', [edges.ids_sumo[prtvehicles.ids_currentedge[id_veh]]]))
5835
5836
# does not seem to have an effect, always starts at base????
5837
fd.write(xm.num('departPos', 'base'))
5838
#fd.write(xm.num('departLane', laneindex_from ))
5839
fd.write(xm.stopit())
5840
5841
# write depart stop
5842
# fd.write(xm.start('stop',indent+4))
5843
#fd.write(xm.num('lane', edges.ids_sumo[lanes.ids_edge[id_lane_from]]+'_%d'%laneindex_from ))
5844
#fd.write(xm.num('duration', time_veh_wait_after_stop))
5845
#fd.write(xm.num('startPos', pos_from ))
5846
#fd.write(xm.num('endPos', pos_from + parking.lengths[id_parking_from]))
5847
#fd.write(xm.num('triggered', "True"))
5848
# fd.write(xm.stopit())
5849
5850
fd.write(xm.end('vehicle', indent+2))
5851
5852
# def make_stops_and_vehicles(self, n_veh = -1):
5853
# self.prtstops.make_from_net()
5854
# self.prtvehicles.make(n_veh)
5855
# self.make_times_stop_to_stop()
5856
5857
def prepare_sim(self, process):
5858
print 'prepare_sim', self.ident
5859
# print ' self.times_stop_to_stop',self.times_stop_to_stop
5860
5861
if self.fstar is None:
5862
self.make_fstar()
5863
5864
if self.times_stop_to_stop is None:
5865
print ' times_stop_to_stop'
5866
self.make_times_stop_to_stop()
5867
5868
updatedata = self.prtvehicles.prepare_sim(process)
5869
updatedata += self.prtstops.prepare_sim(process)
5870
updatedata += self.compressors.prepare_sim(process)
5871
updatedata += self.decompressors.prepare_sim(process)
5872
updatedata += self.mergenodes.prepare_sim(process)
5873
updatedata += self.vehicleman.prepare_sim(process)
5874
#
5875
#updatedata += self.demo.prepare_sim(process)
5876
# print 'PrtService.prepare_sim updatedata',updatedata
5877
return updatedata
5878
5879
def make_fstar(self, is_update=False):
5880
if (self.fstar is None) | is_update:
5881
self.fstar = self.get_fstar()
5882
self.edgetimes = self.get_times(self.fstar)
5883
5884
def get_route(self, id_fromedge, id_toedge):
5885
"""
5886
Centralized function to determin fastest route between
5887
PRT network edges.
5888
"""
5889
duration, route = get_mincostroute_edge2edge(id_fromedge, id_toedge,
5890
weights=self.edgetimes, fstar=self.fstar)
5891
5892
return route, duration
5893
5894
def make_times_stop_to_stop(self, fstar=None, times=None):
5895
print 'make_times_stop_to_stop'
5896
log = self.get_logger()
5897
if fstar is None:
5898
if self.fstar is None:
5899
self.make_fstar()
5900
5901
fstar = self.fstar # get_fstar()
5902
times = self.edgetimes # self.get_times(fstar)
5903
5904
if len(fstar) == 0:
5905
self.times_stop_to_stop = [[]]
5906
return
5907
5908
ids_prtstop = self.prtstops.get_ids()
5909
if len(ids_prtstop) == 0:
5910
self.get_logger().w('WARNING: no PRT stops, no plans. Generate them!')
5911
return
5912
5913
ids_edge = self.prtstops.get_edges(ids_prtstop)
5914
5915
# check if all PRT stop edges are in fstar
5916
ids_ptstop = self.prtstops.ids_ptstop[ids_prtstop] # for debug only
5917
is_incomplete_fstar = False
5918
for id_edge, id_stop, id_ptstop in zip(ids_edge, ids_prtstop, ids_ptstop):
5919
# print ' Found PRT stop %d, PT stop %d with id_edge %d '%(id_stop,id_ptstop, id_edge)
5920
if not fstar.has_key(id_edge):
5921
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)
5922
is_incomplete_fstar = True
5923
5924
# check if fstar is complete (all to edges are in keys)
5925
ids_fromedge_set = set(fstar.keys())
5926
ids_sumo = self.get_scenario().net.edges.ids_sumo
5927
for id_fromedge in ids_fromedge_set:
5928
if not ids_fromedge_set.issuperset(fstar[id_fromedge]):
5929
is_incomplete_fstar = True
5930
ids_miss = fstar[id_fromedge].difference(ids_fromedge_set)
5931
print 'WARNING in make_times_stop_to_stop: incomplete fstar of id_fromedge = %d, %s' % (id_fromedge, ids_sumo[id_fromedge])
5932
for id_edge in ids_miss:
5933
print ' missing', id_edge, ids_sumo[id_edge]
5934
5935
if is_incomplete_fstar:
5936
return
5937
5938
# print ' ids_prtstop,ids_edge',ids_prtstop,ids_edge
5939
n_elem = np.max(ids_prtstop)+1
5940
stop_to_stop = np.zeros((n_elem, n_elem), dtype=np.int32)
5941
5942
ids_edge_to_ids_prtstop = np.zeros(np.max(ids_edge)+1, dtype=np.int32)
5943
ids_edge_to_ids_prtstop[ids_edge] = ids_prtstop
5944
5945
ids_edge_target = set(ids_edge)
5946
5947
for id_stop, id_edge in zip(ids_prtstop, ids_edge):
5948
# print ' route for id_stop, id_edge',id_stop, id_edge
5949
5950
# remove origin from target
5951
ids_edge_target.discard(id_edge)
5952
5953
costs, routes = edgedijkstra(id_edge,
5954
ids_edge_target=ids_edge_target,
5955
weights=times, fstar=fstar
5956
)
5957
5958
# print ' ids_edge_target',ids_edge_target
5959
# print ' costs\n', costs
5960
# print ' routes\n', routes
5961
# for route in routes:
5962
# if len(route)==0:
5963
# print 'WARNING in make_times_stop_to_stop: empty route'
5964
# else:
5965
# print ' found route to id_edge, id_stop',route[-1],ids_edge_to_ids_prtstop[route[-1]],len(route)
5966
5967
if costs is not None:
5968
# TODO: could be vectorialized, but not so easy
5969
for id_edge_target in ids_edge_target:
5970
#stop_to_stop[id_edge,id_edge_target] = costs[id_edge_target]
5971
# 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]
5972
# print ' stop_orig,costs ',ids_edge_to_ids_prtstop[id_edge],ids_sumo[id_edge]
5973
# print ' stop_target',ids_edge_to_ids_prtstop[id_edge_target],ids_sumo[id_edge_target]
5974
# print ' costs ',costs[id_edge_target]
5975
# stop_to_stop[ids_edge_to_ids_prtstop[[id_edge,id_edge_target]]]=costs[id_edge_target]
5976
if id_edge_target in costs:
5977
stop_to_stop[ids_edge_to_ids_prtstop[id_edge],
5978
ids_edge_to_ids_prtstop[id_edge_target]] = costs[id_edge_target]
5979
else:
5980
print 'WARNING in make_times_stop_to_stop: unreacle station id_fromedge = %d, %s' % (id_edge_target, ids_sumo[id_edge_target])
5981
is_incomplete_fstar = True
5982
5983
# put back origin to targets (probably not the best way)
5984
ids_edge_target.add(id_edge)
5985
# print ' ids_edge_target (all)',ids_edge_target
5986
5987
# print ' stop_to_stop',stop_to_stop
5988
# TODO: here we could also store the routes
5989
5990
if is_incomplete_fstar:
5991
return False
5992
5993
self.times_stop_to_stop = stop_to_stop
5994
self.ids_edge_to_ids_prtstop = ids_edge_to_ids_prtstop
5995
print ' times_stop_to_stop=\n', self.times_stop_to_stop
5996
return True
5997
5998
def get_fstar(self):
5999
"""
6000
Returns the forward star graph of the network as dictionary:
6001
fstar[id_fromedge] = set([id_toedge1, id_toedge2,...])
6002
"""
6003
print 'get_fstar'
6004
net = self.get_scenario().net
6005
# prt mode
6006
id_mode = self.id_prtmode
6007
6008
#ids_edge = self.get_ids()
6009
#fstar = np.array(np.zeros(np.max(ids_edge)+1, np.obj))
6010
fstar = {}
6011
connections = net.connections
6012
lanes = net.lanes
6013
6014
#inds_con = connections.get_inds()
6015
#ids_fromlane = connections.ids_fromlane.get_value()[inds_con]
6016
#ids_tolane = connections.ids_tolane.get_value()[inds_con]
6017
6018
ids_con = connections.get_ids()
6019
ids_fromlane = connections.ids_fromlane[ids_con]
6020
ids_tolane = connections.ids_tolane[ids_con]
6021
6022
ids_mainmode_from = lanes.ids_mode[ids_fromlane]
6023
ids_mainmode_to = lanes.ids_mode[ids_tolane]
6024
6025
#ids_modes_allow_from = lanes.ids_modes_allow[ids_fromlane]
6026
#ids_modes_allow_to = lanes.ids_modes_allow[ids_tolane]
6027
6028
ids_fromedge = lanes.ids_edge[ids_fromlane]
6029
ids_toedge = lanes.ids_edge[ids_tolane]
6030
# print ' ids_fromedge',ids_fromedge
6031
# print ' ids_modes_allow',ids_modes_allow
6032
6033
for id_fromedge, id_toedge, id_mode_allow_from, id_mode_allow_to, id_fromlane, id_tolane in\
6034
zip(ids_fromedge, ids_toedge, ids_mainmode_from, ids_mainmode_to,
6035
ids_fromlane, ids_tolane):
6036
6037
if id_mode_allow_from == id_mode:
6038
if id_mode_allow_to == id_mode:
6039
6040
if fstar.has_key(id_fromedge):
6041
fstar[id_fromedge].add(id_toedge)
6042
else:
6043
fstar[id_fromedge] = set([id_toedge])
6044
# if id_fromedge == 14048:
6045
# print ' id_fromedge, id_toedge',id_fromedge, id_toedge,fstar.has_key(id_fromedge)
6046
# print ' id_fromlane, id_tolane ',id_fromlane, id_tolane
6047
# print ' id_mode_allow_from, id_mode_allow_to',id_mode_allow_from, id_mode_allow_to
6048
6049
# for id_fromedge, id_toedge,ids_mode_allow_from,id_modes_allow_to in\
6050
# zip(ids_fromedge, ids_toedge, ids_modes_allow_from, ids_modes_allow_to):
6051
# if len(ids_mode_allow_from)>0:
6052
# if ids_mode_allow_from[-1] == id_mode:
6053
# if len(id_modes_allow_to)>0:
6054
# if id_modes_allow_to[-1] == id_mode:
6055
#
6056
# if fstar.has_key(id_fromedge):
6057
# fstar[id_fromedge].add(id_toedge)
6058
# else:
6059
# fstar[id_fromedge]=set([id_toedge])
6060
6061
return fstar
6062
6063
def get_times(self, fstar):
6064
"""
6065
Returns freeflow travel times for all edges.
6066
The returned array represents the speed and the index corresponds to
6067
edge IDs.
6068
6069
"""
6070
if len(fstar) == 0:
6071
return []
6072
6073
net = self.get_scenario().net
6074
#id_mode = net.modes.get_id_mode(mode)
6075
id_mode = self.id_prtmode
6076
# print 'get_times id_mode,is_check_lanes,speed_max',id_mode,is_check_lanes,speed_max
6077
ids_edge = np.array(fstar.keys(), dtype=np.int32)
6078
6079
times = np.array(np.zeros(np.max(ids_edge)+1, np.float32))
6080
speeds = net.edges.speeds_max[ids_edge]
6081
6082
# limit allowed speeds with max speeds of mode
6083
speeds = np.clip(speeds, 0.0, net.modes.speeds_max[id_mode])
6084
6085
times[ids_edge] = net.edges.lengths[ids_edge]/speeds
6086
6087
return times
6088
6089
def config_results(self, results):
6090
print 'PrtService.config_results', results, id(results)
6091
# keep a link to results here because needed to
6092
# log data during simulation
6093
# this link should not be followed during save process
6094
#self._results = results
6095
6096
tripresults = res.Tripresults('prttripresults', results,
6097
self.prtvehicles,
6098
self.get_scenario().net.edges,
6099
name='PRT trip results',
6100
info='Table with simulation results for each PRT vehicle. The results refer to the vehicle journey over the entire simulation period.',
6101
)
6102
results.add_resultobj(tripresults, groupnames=['Trip results'])
6103
6104
prtstopresults = Stopresults('prtstopresults', results, self.prtstops)
6105
results.add_resultobj(prtstopresults, groupnames=['PRT stop results'])
6106
6107
# def get_results(self):
6108
# return self._results
6109
6110
def process_results(self, results, process=None):
6111
pass
6112
6113
6114
class Stopresults(am.ArrayObjman):
6115
def __init__(self, ident, results, prtstops,
6116
name='Stop results',
6117
info='Table with simulation results of stops generated from vehicle management.',
6118
**kwargs):
6119
6120
self._init_objman(ident=ident,
6121
parent=results, # main results object
6122
info=info,
6123
name=name,
6124
**kwargs)
6125
6126
self.add(cm.AttrConf('time_step', 5.0,
6127
groupnames=['parameters'],
6128
name='Step time',
6129
info="Time of one recording step.",
6130
unit='s',
6131
))
6132
6133
self.add(cm.ObjConf(prtstops, is_child=False, # groupnames = ['_private']
6134
))
6135
6136
self.add_col(am.IdsArrayConf('ids_stop', prtstops,
6137
groupnames=['state'],
6138
is_index=True,
6139
name='PRT stop ID',
6140
info='ID of PRT stop.',
6141
))
6142
6143
attrinfos = [
6144
('inflows_veh', {'name': 'Vehicle in-flows', 'unit': '1/s',
6145
'dtype': np.float32, 'info': 'Vehicle flow into the stop over time.'}),
6146
('inflows_veh_sched', {'name': 'Sched. vehicle in-flows', 'unit': '1/s',
6147
'dtype': np.float32, 'info': 'Scheduled vehicle flow into the stop over time.'}),
6148
('inflows_person', {'name': 'Person in-flows', 'unit': '1/s',
6149
'dtype': np.float32, 'info': 'Person flow into the stop over time.'}),
6150
('numbers_person_wait', {'name': 'waiting person', 'dtype': np.int32,
6151
'info': 'Number of waiting persons at stop over time.'}),
6152
('waittimes_tot', {'name': 'total wait time', 'dtype': np.float32,
6153
'info': 'Wait times of all waiting persons at a stop over time.'}),
6154
]
6155
6156
for attrname, kwargs in attrinfos:
6157
self.add_resultattr(attrname, **kwargs)
6158
6159
def get_dimensions(self):
6160
return len(self), len(self.inflows_veh.get_default())
6161
6162
def get_prtstops(self):
6163
return self.prtstops.get_value()
6164
# return self.ids_stop.get_linktab()
6165
6166
def init_recording(self, n_timesteps, time_step):
6167
print 'init_recording n_timesteps, time_step', n_timesteps, time_step, len(self.ids_stop.get_linktab().get_ids())
6168
self.clear()
6169
6170
self.time_step.set_value(time_step)
6171
6172
for attrconfig in self.get_stopresultattrconfigs():
6173
# print ' reset attrconfig',attrconfig.attrname
6174
attrconfig.set_default(np.zeros(n_timesteps, dtype=attrconfig.get_dtype()))
6175
attrconfig.reset()
6176
# print ' default=',attrconfig.get_default(),attrconfig.get_default().dtype
6177
ids_stop = self.get_prtstops().get_ids()
6178
# print ' ids_stop',ids_stop
6179
self.add_rows(n=len(ids_stop), ids_stop=ids_stop)
6180
6181
def record(self, timestep, ids, **kwargs):
6182
inds = self.ids_stop.get_linktab().get_inds(ids)
6183
timestep_int = int(timestep)
6184
for attrname, values in kwargs.iteritems():
6185
# print ' record',attrname,'dtype',values.dtype,values.shape, 'array',getattr(self,attrname).get_value().dtype,'shape', getattr(self,attrname).get_value().shape
6186
# print ' inds',type(inds),inds.dtype,
6187
getattr(self, attrname).get_value()[inds, timestep_int] = values
6188
6189
def get_stopresultattrconfigs(self):
6190
return self.get_attrsman().get_group_attrs('PRT results').values()
6191
6192
def get_persons(self):
6193
return self.ids_person.get_linktab()
6194
6195
def add_resultattr(self, attrname, **kwargs):
6196
self.add_col(am.ArrayConf(attrname, 0, groupnames=['PRT results', 'results'], **kwargs))
6197
6198
def import_xml(self, sumo, datapaths):
6199
# no imports, data come from prtservice
6200
pass
6201
6202