Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/contributed/sumopy/coremodules/demand/demand.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 demand.py
16
# @author Joerg Schweizer
17
# @date 2012
18
19
import detectorflows
20
import turnflows
21
import virtualpop
22
import origin_to_destination
23
import vehicles
24
from coremodules.network.network import SumoIdsConf, MODES
25
from demandbase import *
26
import publictransportservices as pt
27
from coremodules.simulation import results as res
28
from coremodules.network import routing
29
from agilepy.lib_base.processes import Process
30
from agilepy.lib_base.misc import get_inversemap
31
import agilepy.lib_base.xmlman as xm
32
import agilepy.lib_base.arrayman as am
33
import agilepy.lib_base.classman as cm
34
import numpy as np
35
from coremodules.modules_common import *
36
import os
37
import sys
38
import time
39
40
41
if __name__ == '__main__':
42
try:
43
APPDIR = os.path.dirname(os.path.abspath(__file__))
44
except:
45
APPDIR = os.path.dirname(os.path.abspath(sys.argv[0]))
46
SUMOPYDIR = os.path.join(APPDIR, '..', '..')
47
sys.path.append(SUMOPYDIR)
48
49
50
# Trip depart and arrival options, see
51
# https://sumo.dlr.de/docs/Definition_of_Vehicles%2C_Vehicle_Types%2C_and_Routes.html#a_vehicles_depart_and_arrival_parameter
52
53
54
#from agilepy.lib_base.geometry import find_area
55
#from agilepy.lib_base.processes import Process,CmlMixin,ff,call
56
57
58
try:
59
try:
60
import pyproj
61
is_pyproj = True
62
except:
63
from mpl_toolkits.basemap import pyproj
64
is_pyproj = True
65
66
except:
67
is_pyproj = False
68
69
70
class Demand(cm.BaseObjman):
71
def __init__(self, scenario=None, net=None, zones=None, name='Demand', info='Transport demand', **kwargs):
72
print 'Demand.__init__', name, kwargs
73
74
# we need a network from somewhere
75
if net is None:
76
net = scenario.net
77
zones = scenario.landuse.zones
78
79
self._init_objman(ident='demand', parent=scenario, name=name, info=info, **kwargs)
80
attrsman = self.set_attrsman(cm.Attrsman(self))
81
82
self.vtypes = attrsman.add(cm.ObjConf(vehicles.VehicleTypes(self, net)))
83
84
self.activitytypes = attrsman.add(cm.ObjConf(ActivityTypes('activitytypes', self)))
85
86
self.trips = attrsman.add(cm.ObjConf(Trips(self, net), groupnames=['demand objects']))
87
88
self.odintervals = attrsman.add(cm.ObjConf(
89
origin_to_destination.OdIntervals('odintervals', self, net, zones),
90
))
91
92
self.turnflows = attrsman.add(cm.ObjConf(turnflows.Turnflows('turnflows', self, net),
93
))
94
self._init_attributes()
95
self._init_constants()
96
97
def _init_attributes(self):
98
attrsman = self.get_attrsman()
99
100
scenario = self.parent
101
print 'Demand._init_attributes', scenario
102
103
if scenario is not None:
104
self.detectorflows = attrsman.add(cm.ObjConf(detectorflows.Detectorflows('detectorflows', self),
105
))
106
107
self.ptlines = attrsman.add(cm.ObjConf(pt.PtLines('ptlines', self),
108
groupnames=['demand objects'])
109
)
110
self.virtualpop = attrsman.add(cm.ObjConf(virtualpop.Virtualpopulation('virtualpop', self),
111
groupnames=['demand objects'])
112
)
113
# if hasattr(self,'virtualpolulation'):
114
# #Virtualpolulation
115
# self.delete('virtualpolulation')
116
117
# update
118
119
# if hasattr(self,'trips'):
120
#attrsman.trips.add_groupnames(['demand objects'])
121
122
# if hasattr(self,'ptlines'):
123
#attrsman.ptlines.add_groupnames(['demand objects'])
124
125
# if hasattr(self,'virtualpop'):
126
#attrsman.virtualpop.add_groupnames(['demand objects'])
127
# print attrsman.get_
128
129
def _init_constants(self):
130
self._xmltag_routes = "routes"
131
self._xmltag_trips = "trips"
132
#self._demandobjects = set([self.trips, self.ptlines, self.virtualpop])
133
134
def get_vtypes(self):
135
return self.vtypes
136
137
def get_scenario(self):
138
return self.parent
139
140
def get_net(self):
141
return self.parent.net
142
143
def get_tripfilepath(self):
144
return self.get_scenario().get_rootfilepath()+'.trip.xml'
145
146
def get_routefilepath(self):
147
return self.get_scenario().get_rootfilepath()+'.rou.xml'
148
149
def update_netoffset(self, deltaoffset):
150
"""
151
Called when network offset has changed.
152
Children may need to adjust their coordinates.
153
"""
154
# self.odintervals.update_netoffset(deltaoffset)
155
pass
156
157
def add_demandobject(self, obj=None, ident=None, DemandClass=None, **kwargs):
158
if obj is not None:
159
ident = obj.get_ident()
160
161
if not hasattr(self, ident):
162
if obj is None:
163
# make demandobject a child of demand
164
165
# if ident is None:
166
# ident = obj.get_ident()
167
obj = DemandClass(ident, self, **kwargs)
168
is_child = True
169
#is_save = True
170
else:
171
# link to simobject, which must be a child of another object
172
is_child = False # will not be saved but linked
173
#is_save = False
174
175
attrsman = self.get_attrsman()
176
177
attrsman.add(cm.ObjConf(obj,
178
groupnames=['demand objects'],
179
is_child=is_child,
180
#is_save = is_save,
181
))
182
183
setattr(self, ident, obj)
184
185
return getattr(self, ident)
186
187
def get_demandobjects(self):
188
#demandobjects = set([])
189
# for ident, conf in self.get_group_attrs('').iteritems():
190
# demandobjects.add(conf.get_value())
191
demandobjects_clean = []
192
for attrname, demandobject in self.get_attrsman().get_group_attrs('demand objects').iteritems():
193
if demandobject is not None:
194
demandobjects_clean.append(demandobject)
195
else:
196
print 'WARNING in get_demandobjects: found None as object', attrname
197
self.get_attrsman().delete(attrname)
198
return demandobjects_clean
199
200
def get_time_depart_first(self):
201
# print 'get_time_depart_first'
202
time = 10**10
203
for obj in self.get_demandobjects():
204
# print ' obj',obj.ident,obj.get_time_depart_first()
205
time = min(time, obj.get_time_depart_first())
206
return time
207
208
def get_time_depart_last(self):
209
time = 0
210
for obj in self.get_demandobjects():
211
time = max(time, obj.get_time_depart_last())
212
return time
213
214
def remove_demandobject(self, demandobject):
215
# self._demandobjects.discard(demandobject)
216
self.get_attrsman().delete(demandobject.ident)
217
218
def import_routes_xml(self, filepath=None, demandobjects=None,
219
is_clear_trips=False, is_generate_ids=False,
220
is_overwrite_only=True):
221
222
if demandobjects is None:
223
demandobjects = self.get_demandobjects()
224
225
# is_route = True # add edge ids, if available
226
227
if filepath is None:
228
filepath = self.get_routefilepath()
229
print 'import_routes_xml', filepath, demandobjects
230
try:
231
fd = open(filepath, 'r')
232
except:
233
print 'WARNING in import_routes_xml: could not open', filepath
234
return False
235
236
for demandobj in demandobjects:
237
print ' try to import routes from demandobj', demandobj
238
demandobj.import_routes_xml(filepath,
239
is_clear_trips=is_clear_trips,
240
is_generate_ids=is_generate_ids,
241
is_overwrite_only=is_overwrite_only)
242
243
return True
244
245
def export_routes_xml(self, filepath=None, encoding='UTF-8',
246
demandobjects=None, is_route=True,
247
vtypeattrs_excluded=[],
248
is_plain=False,
249
is_exclude_pedestrians=False,):
250
"""
251
Export routes available from the demand to SUMO xml file.
252
Method takes care of sorting trips by departure time.
253
"""
254
255
if demandobjects is None:
256
demandobjects = self.get_demandobjects()
257
258
# is_route = True # add edge ids, if available
259
260
if filepath is None:
261
filepath = self.get_routefilepath()
262
print 'export_routes_xml', filepath, demandobjects
263
try:
264
fd = open(filepath, 'w')
265
except:
266
print 'WARNING in export_routes_xml: could not open', filepath
267
return False
268
269
fd.write('<?xml version="1.0" encoding="%s"?>\n' % encoding)
270
fd.write(xm.begin(self._xmltag_routes))
271
indent = 2
272
273
times_begin = np.zeros((0), dtype=np.int32)
274
writefuncs = np.zeros((0), dtype=np.object)
275
ids_trip = [] # use list here to accomodate different id stuctures
276
#ids_trip =np.zeros((0),dtype = np.int32)
277
278
ids_vtype = set()
279
for exportobj in demandobjects:
280
print ' exportobj', exportobj
281
times, funcs, ids = exportobj.get_writexmlinfo(is_route=is_route,
282
is_plain=is_plain,
283
is_exclude_pedestrians=is_exclude_pedestrians)
284
print ' n_trips', len(times), 'has vtypes', hasattr(exportobj, 'get_vtypes')
285
if len(times) > 0:
286
times_begin = np.concatenate((times_begin, times), 0)
287
writefuncs = np.concatenate((writefuncs, funcs), 0)
288
#ids_trip = np.concatenate((ids_trip, ids),0)
289
ids_trip = ids_trip + list(ids)
290
if hasattr(exportobj, 'get_vtypes'):
291
# TODO:all export objects have get_vtypes except mapmatching
292
ids_vtype.update(exportobj.get_vtypes())
293
294
# convert back to array to allow proper indexing
295
ids_trip = np.array(ids_trip, dtype=np.object)
296
297
attrconfigs_excluded = []
298
for attrname in vtypeattrs_excluded:
299
attrconfigs_excluded.append(self.vtypes.get_config(attrname))
300
301
self.vtypes.write_xml(fd, indent=indent,
302
ids=ids_vtype,
303
is_print_begin_end=False,
304
attrconfigs_excluded=attrconfigs_excluded,
305
)
306
307
# sort trips
308
inds_trip = np.argsort(times_begin)
309
310
#time0 = times_begin[inds_trip[0]]
311
# write trips
312
for writefunc, id_trip, time_begin in zip(
313
writefuncs[inds_trip],
314
ids_trip[inds_trip],
315
times_begin[inds_trip]):
316
317
writefunc(fd, id_trip, time_begin, indent)
318
319
fd.write(xm.end(self._xmltag_routes))
320
fd.close()
321
return filepath
322
323
def import_xml(self, rootname, dirname=''):
324
"""
325
Import trips and/or routes, if available.
326
"""
327
328
filepath = os.path.join(dirname, rootname+'.trip.xml')
329
if os.path.isfile(filepath):
330
# import trips
331
self.trips.import_trips_xml(filepath, is_generate_ids=False)
332
333
# now try to add routes to existing trips
334
filepath = os.path.join(dirname, rootname+'.rou.xml')
335
if os.path.isfile(filepath):
336
self.trips.import_routes_xml(filepath, is_generate_ids=False, is_add=True)
337
338
else:
339
self.get_logger().w('import_xml: files not found:'+filepath, key='message')
340
341
else:
342
self.get_logger().w('import_xml: files not found:'+filepath, key='message')
343
344
# no trip file exists, but maybe just a route file with trips
345
filepath = os.path.join(dirname, rootname+'.rou.xml')
346
if os.path.isfile(filepath):
347
self.trips.import_routes_xml(filepath, is_generate_ids=False, is_add=False)
348
349
else:
350
self.get_logger().w('import_xml: files not found:'+filepath, key='message')
351
352
353
class Routes(am.ArrayObjman):
354
def __init__(self, ident, trips, net, **kwargs):
355
356
self._init_objman(ident=ident,
357
parent=trips,
358
name='Routes',
359
info='Table with route info.',
360
xmltag=('routes', 'route', None),
361
**kwargs)
362
363
#self.add_col(SumoIdsConf('Route', xmltag = 'id'))
364
365
self.add_col(am.IdsArrayConf('ids_trip', trips,
366
groupnames=['state'],
367
name='Trip ID',
368
info='Route for this trip ID.',
369
))
370
371
self.add_col(am.IdlistsArrayConf('ids_edges', net.edges,
372
name='Edge IDs',
373
info='List of edge IDs constituting the route.',
374
xmltag='edges',
375
))
376
377
self.add_col(am.ArrayConf('costs', 0.0,
378
dtype=np.float32,
379
perm='r',
380
name='Costs',
381
info="Route costs.",
382
xmltag='cost',
383
))
384
385
self.add_col(am.ArrayConf('probabilities', 1.0,
386
dtype=np.float32,
387
perm='r',
388
name='Probab.',
389
info="Route route choice probability.",
390
xmltag='probability',
391
))
392
393
self.add_col(am.ArrayConf('colors', np.ones(4, np.float32),
394
dtype=np.float32,
395
metatype='color',
396
perm='rw',
397
name='Color',
398
info="Route color. Color as RGBA tuple with values from 0.0 to 1.0",
399
xmltag='color',
400
))
401
402
def clear_routes(self):
403
self.clear()
404
405
def get_shapes(self, ids=None):
406
if ids is None:
407
ids = self.get_ids()
408
n = len(ids)
409
edges = self.ids_edges.get_linktab()
410
shapes = np.zeros(n, dtype=np.object)
411
i = 0
412
# TODO: if edge shapes were a list, the following would be possible:
413
# np.sum(shapes)
414
for ids_edge in self.ids_edges[ids]:
415
routeshape = []
416
# print ' ids_edge',ids_edge
417
for shape in edges.shapes[ids_edge]:
418
# print ' routeshape',routeshape
419
# print ' shape',shape,type(shape)
420
routeshape += list(shape)
421
shapes[i] = routeshape
422
i += 1
423
424
return shapes
425
426
427
class Trips(DemandobjMixin, am.ArrayObjman):
428
def __init__(self, demand, net=None, **kwargs):
429
# print 'Trips.__init__'
430
self._init_objman(ident='trips',
431
parent=demand,
432
name='Trips',
433
info='Table with trip and route info.',
434
xmltag=('trips', 'trip', 'ids_sumo'),
435
version=0.2,
436
**kwargs)
437
438
self._init_attributes()
439
self._init_constants()
440
441
def _init_attributes(self):
442
scenario = self.get_scenario()
443
net = self.get_net()
444
self.add_col(SumoIdsConf('Trip', xmltag='id'))
445
446
self.add_col(am.IdsArrayConf('ids_vtype', self.get_obj_vtypes(),
447
groupnames=['state'],
448
name='Type',
449
info='Vehicle type.',
450
xmltag='type',
451
))
452
453
self.add_col(am.ArrayConf('times_depart', 0,
454
dtype=np.int32,
455
perm='rw',
456
name='Depart time',
457
info="Departure time of vehicle in seconds. Must be an integer!",
458
xmltag='depart',
459
))
460
461
self.add_col(am.IdsArrayConf('ids_edge_depart', net.edges,
462
groupnames=['state'],
463
name='ID from-edge',
464
info='ID of network edge where trip starts.',
465
xmltag='from',
466
))
467
468
self.add_col(am.IdsArrayConf('ids_edge_arrival', net.edges,
469
groupnames=['state'],
470
name='ID to-edge',
471
info='ID of network edge where trip ends.',
472
xmltag='to',
473
))
474
475
self.add_col(am.ArrayConf('inds_lane_depart', OPTIONMAP_LANE_DEPART["free"],
476
dtype=np.int32,
477
#choices = OPTIONMAP_LANE_DEPART,
478
perm='r',
479
name='Depart lane',
480
info="Departure lane index. 0 is rightmost lane or sidewalk, if existant.",
481
xmltag='departLane',
482
xmlmap=get_inversemap(OPTIONMAP_LANE_DEPART),
483
))
484
485
self.add_col(am.ArrayConf('positions_depart', OPTIONMAP_POS_DEPARTURE["random_free"],
486
dtype=np.float32,
487
#choices = OPTIONMAP_POS_DEPARTURE,
488
perm='r',
489
name='Depart pos',
490
unit='m',
491
info="Position on edge at the moment of departure.",
492
xmltag='departPos',
493
xmlmap=get_inversemap(OPTIONMAP_POS_DEPARTURE),
494
))
495
496
self.add_col(am.ArrayConf('speeds_depart', 0.0,
497
dtype=np.float32,
498
#choices = OPTIONMAP_SPEED_DEPARTURE,
499
perm='r',
500
name='Depart speed',
501
unit='m/s',
502
info="Speed at the moment of departure.",
503
xmltag='departSpeed',
504
xmlmap=get_inversemap(OPTIONMAP_SPEED_DEPARTURE),
505
))
506
self.add_col(am.ArrayConf('inds_lane_arrival', OPTIONMAP_LANE_ARRIVAL["current"],
507
dtype=np.int32,
508
#choices = OPTIONMAP_LANE_ARRIVAL,
509
perm='r',
510
name='Arrival lane',
511
info="Arrival lane index. 0 is rightmost lane or sidewalk, if existant.",
512
xmltag='arrivalLane',
513
xmlmap=get_inversemap(OPTIONMAP_LANE_ARRIVAL),
514
))
515
516
self.add_col(am.ArrayConf('positions_arrival', OPTIONMAP_POS_ARRIVAL["random"],
517
dtype=np.float32,
518
#choices = OPTIONMAP_POS_ARRIVAL,
519
perm='r',
520
name='Arrival pos',
521
unit='m',
522
info="Position on edge at the moment of arrival.",
523
xmltag='arrivalPos',
524
xmlmap=get_inversemap(OPTIONMAP_POS_ARRIVAL),
525
))
526
527
self.add_col(am.ArrayConf('speeds_arrival', 0.0,
528
dtype=np.float32,
529
#choices = OPTIONMAP_SPEED_ARRIVAL,
530
perm='r',
531
name='Arrival speed',
532
unit='m/s',
533
info="Arrival at the moment of departure.",
534
xmltag='arrivalSpeed',
535
xmlmap=get_inversemap(OPTIONMAP_SPEED_ARRIVAL),
536
))
537
538
self.add(cm.ObjConf(Routes('routes', self, net)))
539
540
# this could be extended to a list with more plans
541
self.add_col(am.IdsArrayConf('ids_route_current', self.routes.get_value(),
542
name='Route ID ',
543
info='Currently chosen route ID.',
544
))
545
546
# print ' self.routes.get_value()',self.routes.get_value()
547
self.add_col(am.IdlistsArrayConf('ids_routes', self.routes.get_value(),
548
name='IDs route alt.',
549
info='IDs of route alternatives for this trip.',
550
))
551
552
if 1: # self.get_version()<0.2:
553
# self.inds_lane_depart.set_xmltag(None)
554
# self.inds_lane_arrival.set_xmltag(None)
555
self.inds_lane_depart.set_xmltag('departLane', xmlmap=get_inversemap(OPTIONMAP_LANE_DEPART))
556
self.inds_lane_arrival.set_xmltag('arrivalLane', xmlmap=get_inversemap(OPTIONMAP_LANE_ARRIVAL))
557
558
self.set_version(0.2)
559
560
def _init_constants(self):
561
#self._method_routechoice = self.get_route_first
562
563
self._xmltag_routes = "routes"
564
self._xmltag_veh = "vehicle"
565
self._xmltag_id = "id"
566
self._xmltag_trip = "trip"
567
self._xmltag_rou = "route"
568
self._xmltag_person = 'person'
569
570
def clear_trips(self):
571
self.routes.get_value().clear_routes()
572
self.clear()
573
574
def clear_routes(self):
575
self.routes.get_value().clear_routes()
576
self.ids_route_current.reset()
577
self.ids_routes.reset()
578
579
def clear_route_alternatves(self):
580
ids_route_del = []
581
ids_trip = self.get_ids()
582
#ids_routes = self.ids_routes[self.get_ids()]
583
for id_trip, id_route_current in zip(ids_trip, self.ids_route_current[ids_trip]):
584
if self.ids_routes[id_trip] is not None:
585
ids_route = set(self.ids_routes[id_trip])
586
ids_route_del += list(ids_route.difference([id_route_current]))
587
self.ids_routes[id_trip] = [id_route_current]
588
589
self.routes.get_value().del_rows(ids_route_del)
590
591
def get_id_from_id_sumo(self, id_veh_sumo):
592
# print 'get_id_from_id_sumo',id_veh_sumo,len(id_veh_sumo.split('.')) == 1
593
if len(id_veh_sumo.split('.')) == 1:
594
return int(id_veh_sumo)
595
return -1
596
597
def get_routes(self):
598
return self.routes.get_value()
599
600
def get_obj_vtypes(self):
601
return self.parent.vtypes
602
603
def get_net(self):
604
return self.get_scenario().net
605
606
def get_scenario(self):
607
return self.parent.get_scenario()
608
609
def get_time_depart_first(self):
610
if len(self) > 0:
611
return float(np.min(self.times_depart.get_value()))
612
else:
613
return np.inf
614
615
def get_time_depart_last(self):
616
if len(self) > 0:
617
return float(np.max(self.times_depart.get_value()))+600.0
618
else:
619
return 0.0
620
621
def get_tripfilepath(self):
622
return self.parent.get_tripfilepath()
623
624
def get_routefilepath(self):
625
return self.parent.get_routefilepath()
626
627
def duaroute(self, is_export_net=False, is_export_trips=True,
628
routefilepath=None, weights=None, weightfilepath=None,
629
**kwargs):
630
"""
631
Simple fastest path routing using duarouter.
632
"""
633
print 'duaroute'
634
exectime_start = time.clock()
635
636
#routesattrname = self.get_routesattrname(routesindex)
637
vtypes = self.parent.vtypes
638
if (not os.path.isfile(self.get_tripfilepath())) | is_export_trips:
639
ids_vtype_pedestrian = vtypes.select_by_mode(mode='pedestrian', is_sumoid=False)
640
self.export_trips_xml(ids_vtype_exclude=ids_vtype_pedestrian)
641
642
if (not os.path.isfile(self.get_net().get_filepath())) | is_export_net:
643
self.get_net().export_netxml()
644
645
if routefilepath is None:
646
routefilepath = self.get_routefilepath()
647
648
if weights is not None:
649
weightfilepath = self.get_net().edges.export_edgeweights_xml(
650
filepath=weightfilepath,
651
weights=weights,
652
time_begin=self.get_time_depart_first(),
653
time_end=self.get_time_depart_last())
654
655
if routing.duaroute(self.get_tripfilepath(), self.get_net().get_filepath(),
656
routefilepath, weightfilepath=weightfilepath, **kwargs):
657
658
self.import_routes_xml(routefilepath,
659
is_clear_trips=False,
660
is_generate_ids=False,
661
is_overwrite_only=True,
662
is_add=False)
663
664
print ' exectime', time.clock()-exectime_start
665
return routefilepath
666
667
else:
668
return None
669
670
def get_trips_for_vtype(self, id_vtype):
671
return self.select_ids(self.ids_vtype.get_value() == id_vtype)
672
673
def get_vtypes(self):
674
return set(self.ids_vtype.get_value())
675
676
def route(self, is_check_lanes=True, is_del_disconnected=False, is_set_current=False):
677
"""
678
Fastest path python router.
679
"""
680
print 'route is_check_lanes', is_check_lanes
681
# TODO: if too mant vtypes, better go through id_modes
682
exectime_start = time.clock()
683
684
net = self.get_scenario().net
685
edges = net.edges
686
vtypes = self.parent.vtypes
687
688
ids_edges = []
689
ids_trip = []
690
costs = []
691
692
ids_trip_disconnected = []
693
694
for id_vtype in self.get_vtypes():
695
id_mode = vtypes.ids_mode[id_vtype]
696
697
# no routing for pedestrians
698
if id_mode != net.modes.get_id_mode('pedestrian'):
699
ids_trip_vtype = self.get_trips_for_vtype(id_vtype)
700
print ' id_vtype, id_mode', id_vtype, id_mode # ,ids_trip_vtype
701
702
weights = edges.get_times(id_mode=id_mode,
703
speed_max=vtypes.speeds_max[id_vtype],
704
is_check_lanes=is_check_lanes,
705
modeconst_excl=-10.0, modeconst_mix=-5.0,
706
)
707
708
fstar = edges.get_fstar(id_mode=id_mode)
709
710
ids_alledges = edges.get_ids()
711
# for id_edge,id_edge_sumo, weight in zip(ids_alledges,edges.ids_sumo[ids_alledges],weights[ids_alledges]):
712
# print ' id_edge',id_edge,id_edge_sumo,'weight',weights[id_edge_sumo]
713
ids_edge_depart = self.ids_edge_depart[ids_trip_vtype]
714
ids_edge_arrival = self.ids_edge_arrival[ids_trip_vtype]
715
716
for id_trip, id_edge_depart, id_edge_arrival in zip(ids_trip_vtype, ids_edge_depart, ids_edge_arrival):
717
718
cost, route = routing.get_mincostroute_edge2edge(id_edge_depart,
719
id_edge_arrival,
720
weights=weights,
721
fstar=fstar)
722
723
# if id_trip == 1:
724
# print ' id_trip',id_trip,'id_edge_depart',id_edge_depart,'id_edge_arrival',id_edge_arrival
725
# print ' route',route
726
# print ' ids_sumo',edges.ids_sumo[route]
727
if len(route) > 0:
728
ids_edges.append(route)
729
ids_trip.append(id_trip)
730
costs.append(cost)
731
732
else:
733
ids_trip_disconnected.append(id_trip)
734
735
ids_route = self.routes.get_value().add_rows(ids_trip=ids_trip,
736
ids_edges=ids_edges,
737
costs=costs,
738
)
739
if is_set_current:
740
self.ids_route_current[ids_trip] = ids_route
741
else:
742
self.add_routes(ids_trip, ids_route)
743
744
print ' exectime', time.clock()-exectime_start
745
746
if is_del_disconnected:
747
self.del_rows(ids_trip_disconnected)
748
749
return ids_trip, ids_route
750
751
def estimate_entered(self, method_routechoice=None):
752
"""
753
Estimates the entered number of vehicles for each edge.
754
returns ids_edge and entered_vec
755
"""
756
# TODO: we could specify a mode
757
if method_routechoice is None:
758
method_routechoice = self.get_route_first
759
760
ids_edges = self.routes.get_value().ids_edges
761
counts = np.zeros(np.max(self.get_net().edges.get_ids())+1, int)
762
763
for id_trip in self.get_ids():
764
id_route = method_routechoice(id_trip)
765
if id_route >= 0:
766
# here the [1:] eliminates first edge as it is not entered
767
counts[ids_edges[id_route][1:]] += 1
768
769
ids_edge = np.flatnonzero(counts)
770
entered_vec = counts[ids_edge].copy()
771
return ids_edge, entered_vec
772
773
def import_trips_from_scenario(self, scenario2):
774
"""
775
Import trips from another scenario.
776
"""
777
print 'import_trips_from_scenario', scenario2.ident
778
if not is_pyproj:
779
print("WARNING in import_trips_from_scenario: pyproj module not installed")
780
return None
781
782
scenario = self.get_scenario()
783
demand = scenario.demand
784
net = scenario.net
785
edges = net.edges
786
ids_edge_depart = demand.trips.ids_edge_depart
787
ids_edge_arrival = demand.trips.ids_edge_arrival
788
789
demand2 = scenario2.demand
790
net2 = scenario2.net
791
792
# copy all vtypes from scenario2
793
794
# get vtypes of demand2 that are not in demand
795
ids_veh2 = demand2.vtypes.get_ids()
796
ids_vtype_sumo2 = demand2.vtypes.ids_sumo[ids_veh2]
797
# print ' ids_vtype_sumo2',ids_vtype_sumo2
798
# print ' ids_vtype_sumo',demand.vtypes.ids_sumo.get_value()
799
ids_vtype_sumo_diff = list(set(ids_vtype_sumo2).difference(demand.vtypes.ids_sumo.get_value()))
800
# print ' ids_vtype_sumo_diff',ids_vtype_sumo_diff
801
# for id_sumo2 in demand2.vtypes.ids_sumo.get_value():
802
# if demand.vtypes.has_index(id_sumo2):
803
# for attrconf in demand2.vtypes.get_group('parameters'):
804
805
# copy all attributes from ids_vtype_sumo_diff
806
ids_vtype_diff = demand.vtypes.copy_cols(
807
demand2.vtypes, ids=demand2.vtypes.ids_sumo.get_ids_from_indices(ids_vtype_sumo_diff))
808
#ids_vtype_sumo = demand.vtypes.ids_sumo.get_value()
809
#ids_vtype = demand.vtypes.get_ids_from_indices(ids_vtype_sumo)
810
#ids_vtype2 = demand2.vtypes.ids_sumoget_ids_from_indices(ids_vtype_sumo)
811
812
# map id_vtypes from scenario2 to present scenario
813
vtypemap = np.zeros(np.max(ids_veh2)+1)
814
vtypemap[ids_veh2] = demand.vtypes.ids_sumo.get_ids_from_indices(ids_vtype_sumo2)
815
816
# print ' vtypemap',vtypemap
817
# copy trip parameters, by mapping trip types
818
ids_trip2 = demand2.trips.get_ids()
819
820
ids_trips = self.copy_cols(demand2.trips) # ids_trip in present scenrio
821
822
# delete routes, that cannot be transferred (at the moment)
823
self.ids_route_current[ids_trips] = -1
824
self.ids_routes[ids_trips] = len(ids_trips) * [None]
825
826
self.ids_vtype[ids_trips] = vtypemap[demand2.trips.ids_vtype[ids_trip2]]
827
828
# print ' ids_trip2,ids_trips',ids_trip2,ids_trips
829
830
ids_mode = demand.vtypes.ids_mode[self.ids_vtype[ids_trips]]
831
# for each used mode, we need to select the network edges that are accessible by this mode
832
ids_modeset = set(ids_mode)
833
834
#maps_edge_laneind = {}
835
# for id_mode in ids_modeset:
836
# ids_edge, inds_lane = edges.select_accessible(id_mode)
837
# maps_edge_laneind[id_mode] = dict(zip(ids_edge,inds_lane))
838
839
# project depart points and arrival points
840
proj_params = str(net.get_projparams())
841
proj_params2 = str(net2.get_projparams())
842
843
if (proj_params == '!') | (proj_params2 == '!'):
844
print 'WARNING in import_trips_from_scenario: unknown projections, use only offsets.', proj_params, proj_params2
845
is_proj = False
846
847
elif proj_params == proj_params2:
848
# with identical projections, projecting is useless
849
is_proj = False
850
851
else:
852
is_proj = True
853
proj = pyproj.Proj(proj_params)
854
proj2 = pyproj.Proj(proj_params2)
855
856
offset = net.get_offset()
857
offset2 = net2.get_offset()
858
859
# if self._proj is None:
860
# self._proj, self._offset = self.parent.get_proj_and_offset()
861
#x,y = self._proj(lons, lats)
862
# return np.transpose(np.concatenate(([x+self._offset[0]],[y+self._offset[1]]),axis=0))
863
864
# adjust edge ids check lane access
865
n_failed = 0
866
ids_trip_failed = set()
867
868
for id_mode in ids_modeset:
869
# make_segment_edge_map for all edges of this mode
870
print ' make segment_edge_map for mode', id_mode
871
ids_edge_access, inds_lane_access = edges.select_accessible_mode(id_mode)
872
print ' found accessible edges', len(ids_edge_access), len(edges.get_ids())
873
# dict(zip(ids_edge,inds_lane))
874
edges.make_segment_edge_map(ids_edge_access)
875
876
# select trips with id_mode
877
ind_trips = np.flatnonzero(ids_mode == id_mode)
878
879
print ' number of trips for this mode:', len(ind_trips)
880
for id_trip, id_edge_depart2, id_edge_arrival2 in zip(ids_trips[ind_trips],
881
demand2.trips.ids_edge_depart[ids_trip2[ind_trips]],
882
demand2.trips.ids_edge_arrival[ids_trip2[ind_trips]]
883
):
884
885
# match departure edge
886
887
# treat special numbers of position
888
pos2 = 0.0
889
890
# get coordinate in scenario2
891
x2, y2, z2 = net2.edges.get_coord_from_pos(id_edge_depart2, pos2)
892
893
# project coord from scenario2 in present scenario
894
if is_proj:
895
xp, yp = pyproj.transform(proj2, proj, x2-offset2[0], y2-offset2[1])
896
else:
897
xp, yp = x2-offset2[0], y2-offset2[1]
898
899
coord = (xp+offset[0], yp+offset[1], z2)
900
# print ' coord2 = ',(x2,y2,z2)
901
# print ' coord = ',coord
902
# get edge id in present scenario
903
id_edge_depart = edges.get_closest_edge(coord)
904
905
# check eucledian distance
906
#d = edges.get_dist_point_to_edge(coord, id_edge_depart)
907
# print ' id_edge_depart,d,id_mode',id_edge_depart,d,id_mode
908
print ' id_edge_depart', id_edge_depart, id_edge_depart in ids_edge_access
909
910
ids_edge_depart[id_trip] = id_edge_depart
911
912
# match arrival edge
913
914
# treat special numbers of position
915
pos2 = 0.0
916
917
# get coordinate in scenario2
918
x2, y2, z2 = net2.edges.get_coord_from_pos(id_edge_arrival2, pos2)
919
920
# project coord from scenario2 in present scenario
921
if is_proj:
922
xp, yp = pyproj.transform(proj2, proj, x2-offset2[0], y2-offset2[1])
923
else:
924
xp, yp = x2-offset2[0], y2-offset2[1]
925
926
coord = (xp+offset[0], yp+offset[1], z2)
927
# print ' coord2 = ',(x2,y2,z2)
928
# print ' coord = ',coord
929
# get edge id in present scenario
930
id_edge_arrival = edges.get_closest_edge(coord)
931
932
# check eucledian distance
933
#d = edges.get_dist_point_to_edge(coord, id_edge_arrival)
934
print ' id_edge_arrival', id_edge_arrival, id_edge_arrival in ids_edge_access
935
936
ids_edge_arrival[id_trip] = id_edge_arrival
937
938
# redo segment map
939
edges.make_segment_edge_map()
940
941
def make_trip(self, is_generate_ids=True, **kwargs):
942
id_trip = self.add_row(ids_vtype=kwargs.get('id_vtype', None),
943
times_depart=kwargs.get('time_depart', None),
944
ids_edge_depart=kwargs.get('id_edge_depart', None),
945
ids_edge_arrival=kwargs.get('id_edge_arrival', None),
946
inds_lane_depart=kwargs.get('ind_lane_depart', None),
947
positions_depart=kwargs.get('position_depart', None),
948
speeds_depart=kwargs.get('speed_depart', None),
949
inds_lane_arrival=kwargs.get('ind_lane_arrival', None),
950
positions_arrival=kwargs.get('position_arrival', None),
951
speeds_arrival=kwargs.get('speed_arrival', None),
952
ids_routes=[],
953
)
954
955
if is_generate_ids:
956
self.ids_sumo[id_trip] = str(id_trip)
957
else:
958
self.ids_sumo[id_trip] = kwargs.get('id_sumo', str(id_trip)) # id
959
960
if kwargs.has_key('route'):
961
route = kwargs['route']
962
if len(route) > 0:
963
id_route = self.routes.get_value().add_row(ids_trip=id_trip,
964
ids_edges=kwargs['route']
965
)
966
self.ids_route_current[id_trip] = id_route
967
self.ids_routes[id_trip] = [id_route]
968
969
return id_trip
970
971
def make_trips(self, ids_vtype, is_generate_ids=True, **kwargs):
972
print 'make_trips len(ids_vtype) =', len(ids_vtype)
973
# print ' kwargs=',kwargs
974
ids_trip = self.add_rows(n=len(ids_vtype),
975
ids_vtype=ids_vtype,
976
times_depart=kwargs.get('times_depart', None),
977
ids_edge_depart=kwargs.get('ids_edge_depart', None),
978
ids_edge_arrival=kwargs.get('ids_edge_arrival', None),
979
inds_lane_depart=kwargs.get('inds_lane_depart', None),
980
positions_depart=kwargs.get('positions_depart', None),
981
speeds_depart=kwargs.get('speeds_depart', None),
982
inds_lane_arrival=kwargs.get('inds_lane_arrival', None),
983
positions_arrival=kwargs.get('positions_arrival', None),
984
speeds_arrival=kwargs.get('speeds_arrival', None),
985
#ids_routes = len(ids_vtype)*[[]],
986
)
987
988
if is_generate_ids:
989
self.ids_sumo[ids_trip] = np.array(ids_trip, np.str)
990
else:
991
self.ids_sumo[ids_trip] = kwargs.get('ids_sumo', np.array(ids_trip, np.str))
992
return ids_trip
993
994
def make_routes(self, ids_vtype, is_generate_ids=True, routes=None, ids_trip=None, is_add=True, **kwargs):
995
"""Generates or sets routes of trips, generates also trips if necessary
996
ids_trip: trip IDs,
997
if None then trip ID and route ID will be generated for each given route
998
if a list then routes will be associated with these trip IDs and routes will be replaced
999
but generated if route ID does not exist for given trip ID
1000
is_add: if True then routes are added to the alternative route list
1001
if False then current routes will be set
1002
1003
is_generate_ids: depricated, fully controlled by ids_trip
1004
"""
1005
print 'make_routes is_generate_ids', ids_trip is None, 'is_add', is_add
1006
# print ' ids_trip',ids_trip
1007
1008
if ids_trip is None: # is_generate_ids = is_generate_ids,
1009
print ' generate new trip IDs'
1010
ids_trip = self.make_trips(ids_vtype, is_generate_ids=is_generate_ids, **kwargs)
1011
is_generate_ids = True
1012
else:
1013
if not is_add:
1014
print ' replace current route and create if not existent'
1015
ids_routes = self.ids_route_current[ids_trip]
1016
inds_new = np.flatnonzero(ids_routes == -1)
1017
# print ' inds_new',inds_new
1018
if len(inds_new) > 0:
1019
print ' complete %d non pre-existant route ids of %d trips' % (len(inds_new), len(ids_trip))
1020
# create new routes
1021
ids_routes[inds_new] = self.routes.get_value().add_rows(n=len(inds_new),
1022
ids_trip=ids_trip[inds_new],
1023
#ids_edges = routes[inds_new],
1024
)
1025
else:
1026
print ' all new routes have pre-existing routes'
1027
else:
1028
# make new route IDs
1029
ids_routes = self.routes.get_value().add_rows(n=len(ids_trip),
1030
ids_trip=ids_trip,
1031
# ids_edges = routes[inds_new],# later!!
1032
)
1033
1034
is_generate_ids = False
1035
print ' set new routes to routes database', len(ids_routes), 'routes set'
1036
self.routes.get_value().ids_edges[ids_routes] = routes
1037
1038
if not is_add:
1039
print ' replace current route IDs', len(inds_new), 'routes replaced'
1040
self.ids_route_current[ids_trip[inds_new]] = ids_routes[inds_new]
1041
else:
1042
print ' add new route IDs to alternatives', len(ids_trip), 'routes added'
1043
self.add_routes(ids_trip, ids_routes)
1044
1045
# if np.any(ids_routes == -1):
1046
# is_generate_ids = True
1047
1048
# print ' ids_trip =',ids_trip
1049
if is_generate_ids:
1050
print ' generate new route IDs'
1051
ids_routes = self.routes.get_value().add_rows(n=len(ids_trip),
1052
ids_trip=ids_trip,
1053
#ids_edges = routes,
1054
)
1055
self.routes.get_value().ids_edges[ids_routes] = routes
1056
1057
# print ' ids_routes',ids_routes
1058
if not is_add:
1059
print ' set new current routes'
1060
self.ids_route_current[ids_trip] = ids_routes
1061
else:
1062
print ' add new route IDs to alternatives'
1063
self.add_routes(ids_trip, ids_routes)
1064
1065
# no!:self.ids_routes[ids_trip] = ids_routes.reshape((-1,1)).tolist()# this makes an array of lists
1066
# print ' self.ids_routes.get_value()',self.ids_routes[ids_trip]
1067
# print ' ids_routes.reshape((-1,1)).tolist()',ids_routes.reshape((-1,1)).tolist()
1068
# print ' make_routes DONE'
1069
return ids_routes, ids_trip
1070
1071
def add_routes(self, ids_trip, ids_routes):
1072
for id_trip, id_route in zip(ids_trip, ids_routes):
1073
# no!: self.ids_routes[id_trip].append(id_route)
1074
# print ' self.ids_routes[id_trip]',self.ids_routes[id_trip],id_route
1075
if self.ids_routes[id_trip] is None:
1076
self.ids_routes[id_trip] = [id_route] # this works!
1077
1078
else:
1079
self.ids_routes[id_trip].append(id_route)
1080
1081
# if self.ids_route_current[id_trip] == -1:
1082
# self.ids_route_current[id_trip] = id_route
1083
1084
def prepare_sim(self, process):
1085
return [] # [(steptime1,func1),(steptime2,func2),...]
1086
1087
def export_trips_xml(self, filepath=None, encoding='UTF-8',
1088
ids_vtype_exclude=[], ids_vtype_include=[],
1089
vtypeattrs_excluded=[]):
1090
"""
1091
Export trips to SUMO xml file.
1092
Method takes care of sorting trips by departure time.
1093
"""
1094
if filepath is None:
1095
filepath = self.get_tripfilepath()
1096
print 'export_trips_xml', filepath
1097
try:
1098
fd = open(filepath, 'w')
1099
except:
1100
print 'WARNING in write_obj_to_xml: could not open', filepath
1101
return False
1102
1103
xmltag, xmltag_item, attrname_id = self.xmltag
1104
fd.write('<?xml version="1.0" encoding="%s"?>\n' % encoding)
1105
fd.write(xm.begin(xmltag))
1106
indent = 2
1107
1108
ids_trip = self.times_depart.get_ids_sorted()
1109
ids_vtype = self.ids_vtype[ids_trip]
1110
#ids_vtypes_exclude = self.ids_vtype.get_ids_from_indices(vtypes_exclude)
1111
1112
inds_selected = np.ones(len(ids_vtype), np.bool)
1113
for id_vtype in ids_vtype_exclude:
1114
inds_selected[ids_vtype == id_vtype] = False
1115
ids_trip_selected = ids_trip[inds_selected]
1116
ids_vtype_selected = set(ids_vtype[inds_selected])
1117
ids_vtype_selected.union(ids_vtype_include)
1118
#ids_vtypes_selected = set(ids_vtypes).difference(ids_vtypes_exclude)
1119
1120
attrconfigs_excluded = []
1121
for attrname in vtypeattrs_excluded:
1122
attrconfigs_excluded.append(self.parent.vtypes.get_config(attrname))
1123
1124
self.parent.vtypes.write_xml(fd, indent=indent,
1125
ids=ids_vtype_selected,
1126
is_print_begin_end=False,
1127
attrconfigs_excluded=attrconfigs_excluded)
1128
1129
self.write_xml(fd, indent=indent,
1130
ids=ids_trip_selected,
1131
attrconfigs_excluded=[self.routes,
1132
self.ids_routes,
1133
self.ids_route_current,
1134
# self.inds_lane_depart,
1135
# self.inds_lane_arrival
1136
],
1137
is_print_begin_end=False)
1138
1139
fd.write(xm.end(xmltag))
1140
fd.close()
1141
return filepath
1142
1143
def get_vtypes(self):
1144
return set(self.ids_vtype.get_value())
1145
1146
def get_trips(self):
1147
# returns trip object, method common to all demand objects
1148
return self
1149
1150
def get_writexmlinfo(self, is_route=False, is_exclude_pedestrians=False, **kwargs):
1151
"""
1152
Returns three array where the first array is the
1153
begin time of the first vehicle and the second array is the
1154
write function to be called for the respectice vehicle and
1155
the third array contains the vehicle ids
1156
1157
Method used to sort trips when exporting to route or trip xml file
1158
"""
1159
1160
ids = self.get_ids()
1161
1162
if not is_exclude_pedestrians:
1163
# define different route write functions for pedestriand and vehicles
1164
n = len(ids)
1165
writefuncs = np.zeros(n, dtype=np.object)
1166
inds_ped = self.parent.vtypes.ids_mode[self.ids_vtype[ids]] == MODES['pedestrian']
1167
writefuncs[inds_ped] = self.write_persontrip_xml
1168
if is_route:
1169
writefuncs[np.logical_not(inds_ped) & (self.ids_route_current[ids] > -1)] = self.write_vehroute_xml
1170
1171
# vehicles must have a route, this makes sure that OD are connected
1172
writefuncs[np.logical_not(inds_ped) & (self.ids_route_current[ids] == -1)] = self.write_missingroute_xml
1173
else:
1174
# here we write vehicle trip, without explicit route export
1175
# routing will be performed during simulation
1176
writefuncs[np.logical_not(inds_ped) & (self.ids_route_current[ids] > -1)] = self.write_vehtrip_xml
1177
1178
# vehicles must have a route, this makes sure that OD are connected
1179
writefuncs[np.logical_not(inds_ped) & (self.ids_route_current[ids] == -1)] = self.write_missingroute_xml
1180
else:
1181
# only vehicle types without peds
1182
inds_noped = self.parent.vtypes.ids_mode[self.ids_vtype[ids]] != MODES['pedestrian']
1183
ids = ids[inds_noped]
1184
n = len(ids)
1185
writefuncs = np.zeros(n, dtype=np.object)
1186
if is_route:
1187
writefuncs[self.ids_route_current[ids] > -1] = self.write_vehroute_xml
1188
1189
# vehicles must have a route, this makes sure that OD are connected
1190
writefuncs[self.ids_route_current[ids] == -1] = self.write_missingroute_xml
1191
else:
1192
# here we write vehicle trip, without explicit route export
1193
# routing will be performed during simulation
1194
writefuncs[self.ids_route_current[ids] > -1] = self.write_vehtrip_xml
1195
1196
# vehicles must have a route, this makes sure that OD are connected
1197
writefuncs[self.ids_route_current[ids] == -1] = self.write_missingroute_xml
1198
1199
return self.times_depart[ids], writefuncs, ids
1200
1201
def write_missingroute_xml(self, fd, id_trip, time_begin, indent=2):
1202
"""
1203
Function called when respective vehicle has an invalid route
1204
"""
1205
pass
1206
1207
def write_vehroute_xml(self, fd, id_trip, time_begin, indent=2):
1208
# print 'write_vehroute_xml',id_trip,time_begin
1209
id_route = self.ids_route_current[id_trip] # self.get_route_first(id_trip)#self._method_routechoice(id_trip)#
1210
1211
if id_route >= 0: # a valid route has been found
1212
# init vehicle route only if valid route exists
1213
fd.write(xm.start(self._xmltag_veh, indent))
1214
else:
1215
# init trip instead of route
1216
fd.write(xm.start(self._xmltag_trip, indent))
1217
1218
# print ' make tag and id',_id
1219
fd.write(xm.num(self._xmltag_id, self.ids_sumo[id_trip]))
1220
1221
# print ' write columns',len(scalarcolconfigs)>0,len(idcolconfig_include_tab)>0,len(objcolconfigs)>0
1222
for attrconfig in [self.ids_vtype,
1223
self.times_depart,
1224
self.ids_edge_depart,
1225
self.ids_edge_arrival,
1226
self.inds_lane_depart,
1227
self.positions_depart,
1228
self.speeds_depart,
1229
self.inds_lane_arrival,
1230
self.positions_arrival,
1231
self.speeds_arrival, ]:
1232
# print ' attrconfig',attrconfig.attrname
1233
attrconfig.write_xml(fd, id_trip)
1234
1235
if (id_route >= 0): # a valid route has been found
1236
# write route id
1237
#fd.write(xm.num('route', id_route ))
1238
1239
# instead of route id we write entire route here
1240
fd.write(xm.stop())
1241
fd.write(xm.start(self._xmltag_rou, indent+2))
1242
1243
routes = self.routes.get_value()
1244
for attrconfig in [routes.ids_edges, routes.colors]:
1245
# print ' attrconfig',attrconfig.attrname
1246
attrconfig.write_xml(fd, id_route)
1247
1248
# end route and vehicle
1249
fd.write(xm.stopit())
1250
fd.write(xm.end(self._xmltag_veh, indent+2))
1251
1252
else:
1253
# end trip without route
1254
fd.write(xm.stopit())
1255
1256
def write_vehtrip_xml(self, fd, id_trip, time_begin, indent=2):
1257
# vehicle trip write function
1258
# no route is written, even if it exisis
1259
1260
# init trip instead of route
1261
fd.write(xm.start(self._xmltag_trip, indent))
1262
1263
# print ' make tag and id',_id
1264
fd.write(xm.num(self._xmltag_id, self.ids_sumo[id_trip]))
1265
1266
# print ' write columns',len(scalarcolconfigs)>0,len(idcolconfig_include_tab)>0,len(objcolconfigs)>0
1267
for attrconfig in [self.ids_vtype,
1268
self.times_depart,
1269
self.ids_edge_depart,
1270
self.ids_edge_arrival,
1271
self.inds_lane_depart,
1272
self.positions_depart,
1273
self.speeds_depart,
1274
self.inds_lane_arrival,
1275
self.positions_arrival,
1276
self.speeds_arrival, ]:
1277
# print ' attrconfig',attrconfig.attrname
1278
attrconfig.write_xml(fd, id_trip)
1279
1280
# end trip without route
1281
fd.write(xm.stopit())
1282
1283
def write_persontrip_xml(self, fd, id_trip, time_begin, indent=2):
1284
# currently no routes are exported, only origin and destination edges
1285
1286
fd.write(xm.start(self._xmltag_person, indent))
1287
1288
self.ids_sumo.write_xml(fd, id_trip)
1289
self.times_depart.write_xml(fd, id_trip)
1290
self.ids_vtype.write_xml(fd, id_trip)
1291
fd.write(xm.stop())
1292
1293
fd.write(xm.start('walk', indent=indent+2))
1294
# print 'write walk',id_trip,self.positions_depart[id_trip],self.positions_arrival[id_trip]
1295
self.ids_edge_depart.write_xml(fd, id_trip)
1296
if self.positions_depart[id_trip] > 0:
1297
self.positions_depart.write_xml(fd, id_trip)
1298
1299
self.ids_edge_arrival.write_xml(fd, id_trip)
1300
if self.positions_arrival[id_trip] > 0:
1301
self.positions_arrival.write_xml(fd, id_trip)
1302
1303
fd.write(xm.stopit()) # ends walk
1304
fd.write(xm.end(self._xmltag_person, indent=indent))
1305
1306
def get_route_first(self, id_trip):
1307
ids_route = self.ids_routes[id_trip]
1308
if ids_route is None:
1309
return -1
1310
elif len(ids_route) > 0:
1311
return ids_route[0]
1312
else:
1313
return -1 # no route found
1314
1315
def import_routes_xml(self, filepath, is_clear_trips=False,
1316
is_generate_ids=True, is_add=False,
1317
is_overwrite_only=False):
1318
print 'import_routes_xml from %s generate new routes %s, clear trips %s add trips %s' % (filepath, is_generate_ids, is_clear_trips, is_add)
1319
if is_clear_trips:
1320
self.clear_trips()
1321
1322
counter = RouteCounter()
1323
parse(filepath, counter)
1324
reader = RouteReader(self, counter)
1325
try:
1326
parse(filepath, reader)
1327
print ' call insert_routes', is_generate_ids, 'is_add', is_add, 'is_overwrite_only', is_overwrite_only
1328
reader.insert_routes(is_generate_ids=is_generate_ids,
1329
is_add=is_add, is_overwrite_only=is_overwrite_only)
1330
except KeyError:
1331
print >> sys.stderr, "Error: Problems with reading routes!"
1332
raise
1333
1334
def import_trips_xml(self, filepath, is_clear_trips=False, is_generate_ids=True):
1335
print 'import_trips_xml from %s generate own trip ' % (filepath)
1336
if is_clear_trips:
1337
self.clear_trips()
1338
1339
counter = TripCounter()
1340
parse(filepath, counter)
1341
reader = TripReader(self, counter.n_trip)
1342
print ' n_trip=', counter.n_trip
1343
1344
try:
1345
parse(filepath, reader)
1346
reader.insert_trips(is_generate_ids=is_generate_ids)
1347
except KeyError:
1348
print >> sys.stderr, "Error: Problems with reading trips!"
1349
raise
1350
1351
def config_results(self, results):
1352
# print 'DEMAND.config_results'
1353
tripresults = res.Tripresults('tripresults', results,
1354
self,
1355
self.get_net().edges
1356
)
1357
1358
results.add_resultobj(tripresults, groupnames=['Trip results'])
1359
1360
def process_results(self, results, process=None):
1361
pass
1362
1363
1364
class TaxiGenerator(Process):
1365
def __init__(self, demand, logger=None, **kwargs):
1366
1367
self._init_common('taxigenerator', name='Taxi generator',
1368
parent=demand,
1369
logger=logger,
1370
info='Generates taxi trips on specific zones.',
1371
)
1372
1373
attrsman = self.get_attrsman()
1374
scenario = self.parent.get_scenario()
1375
zones = scenario.landuse.zones
1376
1377
self.n_taxi = attrsman.add(cm.AttrConf('n_taxi', 100,
1378
groupnames=['options'],
1379
name='Number of taxi',
1380
info="Number of taxis to be generated.",
1381
))
1382
1383
self.priority_max = attrsman.add(cm.AttrConf('priority_max', 8,
1384
groupnames=['options'],
1385
name='Max. edge priority',
1386
perm='rw',
1387
info="Maximum edge priority for which edges in a zone are considered departure or arrival edges.",
1388
))
1389
1390
self.speed_max = attrsman.add(cm.AttrConf('speed_max', 14.0,
1391
groupnames=['options'],
1392
name='Max. edge speed',
1393
perm='rw',
1394
unit='m/s',
1395
info="Maximum edge speed for which edges in a zone are considered departure or arrival edges.",
1396
))
1397
1398
time_start = self.parent.get_time_depart_first()
1399
1400
self.time_start = attrsman.add(cm.AttrConf('time_start', kwargs.get('time_start', time_start),
1401
groupnames=['options', 'timing'],
1402
name='Start time',
1403
perm='rw',
1404
info='Start time when first taxi appears, in seconds after midnight.',
1405
unit='s',
1406
))
1407
1408
# default is to insert all taxis within the first 60s
1409
self.time_end = attrsman.add(cm.AttrConf('time_end', kwargs.get('time_end', time_start+60.0),
1410
groupnames=['options', 'timing'],
1411
name='End time',
1412
perm='rw',
1413
info='Time when last taxi appears in seconds after midnight.',
1414
unit='s',
1415
))
1416
1417
self.n_edges_min_length = attrsman.add(cm.AttrConf('n_edges_min_length', 1,
1418
groupnames=['options'],
1419
name='Min. edge number length prob.',
1420
perm='rw',
1421
info="Minimum number of edges for with the departure/arrival probability is proportional to the edge length.",
1422
))
1423
1424
self.n_edges_max_length = attrsman.add(cm.AttrConf('n_edges_max_length', 500,
1425
groupnames=['options'],
1426
name='Max. edge number length prob.',
1427
perm='rw',
1428
info="Maximum number of edges for with the departure/arrival probability is proportional to the edge length.",
1429
))
1430
1431
self.is_selected_zones = attrsman.add(cm.AttrConf('is_selected_zones', False,
1432
groupnames=['options'],
1433
name='Selected zones',
1434
info="Place taxis only on edges of specified zone list.",
1435
))
1436
1437
ids_zone = zones.get_ids()
1438
zonechoices = {}
1439
for id_zone, name_zone in zip(ids_zone, zones.ids_sumo[ids_zone]):
1440
zonechoices[name_zone] = id_zone
1441
# print ' zonechoices',zonechoices
1442
# make for each possible pattern a field for prob
1443
# if len(zonechoices) > 0:
1444
self.ids_zone = attrsman.add(cm.ListConf('ids_zone', [],
1445
groupnames=['options'],
1446
choices=zonechoices,
1447
name='Zones',
1448
info="""Zones where to place taxis. Taxis are distributed proportional to road lengths in zones.""",
1449
))
1450
1451
# self.is_refresh_zoneedges = attrsman.add(am.AttrConf( 'is_refresh_zoneedges', True,
1452
# groupnames = ['options'],
1453
# perm='rw',
1454
# name = 'Refresh zone edges',
1455
# info = """Identify all edges in all zones before generating the trips.
1456
# Dependent on the will take some time.""",
1457
# ))
1458
1459
def generate_taxi(self):
1460
"""
1461
Generate taxis as trips in the trip database.
1462
"""
1463
tripnumber = self.n_taxi
1464
time_start = self.time_start
1465
time_end = self.time_end
1466
id_mode_ped = MODES['pedestrian']
1467
id_mode_taxi = MODES['taxi']
1468
scenario = self.parent.get_scenario()
1469
zones = scenario.landuse.zones
1470
trips = scenario.demand.trips
1471
edges = scenario.net.edges
1472
edgelengths = edges.lengths
1473
1474
# define taxi and secondary mode, if appropriate
1475
ids_vtype_mode_taxi, prob_vtype_mode_taxi = scenario.demand.vtypes.select_by_mode(
1476
id_mode_taxi, is_share=True)
1477
1478
# print ' ids_vtype_mode', ids_vtype_mode
1479
n_vtypes_taxi = len(ids_vtype_mode_taxi)
1480
1481
# update edge probabilities with suitable parameters
1482
# edge departure probabilities of all edges in all zones
1483
edgeprops_all = {}
1484
1485
if self.is_selected_zones:
1486
ids_zone = self.ids_zone
1487
else:
1488
ids_zone = zones.get_ids()
1489
for id_zone in ids_zone:
1490
edgeprops_all.update(zones.get_egdeprobs(id_zone, self.n_edges_min_length, self.n_edges_max_length,
1491
self.priority_max, self.speed_max, is_normalize=False, is_dict=True))
1492
1493
fstar = edges.get_fstar(is_ignor_connections=False)
1494
times_taxi = edges.get_times(id_mode=id_mode_taxi, is_check_lanes=True)
1495
1496
n_trips_generated = 0
1497
n_trips_failed = 0
1498
1499
if self.is_selected_zones:
1500
# tale selected zones
1501
ids_zone = self.ids_zone
1502
else:
1503
# take all zones
1504
ids_zone = zones.get_ids()
1505
1506
ids_edges_orig = [] # all accessible edges in all zones
1507
n_edges_orig = 0
1508
for id_zone in ids_zone:
1509
#id_orig = self.ids_orig[id_od]
1510
#id_dest = self.ids_dest[id_od]
1511
1512
print ' check id_zone', id_zone
1513
ids_edges_orig_raw = zones.ids_edges_orig[id_zone]
1514
1515
#prob_edges_orig_raw = zones.probs_edges_orig[id_orig]
1516
1517
# check accessibility of origin edges
1518
1519
#prob_edges_orig = []
1520
#inds_lane_orig = []
1521
1522
for i in xrange(len(ids_edges_orig_raw)):
1523
id_edge = ids_edges_orig_raw[i]
1524
# if check accessibility...
1525
ind_lane_depart_taxi = edges.get_laneindex_allowed(id_edge, id_mode_taxi)
1526
ind_lane_depart_ped = edges.get_laneindex_allowed(id_edge, id_mode_ped)
1527
1528
# print ' O get_laneindex_allowed id_mode_taxi',id_mode_taxi,id_edge,edges.ids_sumo[id_edge],'ind_lane',ind_lane_depart
1529
if (ind_lane_depart_taxi >= 0) & (ind_lane_depart_ped >= 0):
1530
ids_edges_orig.append(id_edge)
1531
# prob_edges_orig.append(prob_edges_orig_raw[i])
1532
# are_fallback_orig.append(False)
1533
# inds_lane_orig.append(ind_lane_depart)
1534
1535
n_edges_orig = len(ids_edges_orig)
1536
1537
print '\n found', n_edges_orig, 'valid zone edges'
1538
1539
# now create taxi trips
1540
if (n_edges_orig > 0) & (tripnumber > 0):
1541
# normalize weights
1542
edgeprops = np.zeros(n_edges_orig, dtype=np.float32)
1543
1544
for i, id_edge in zip(xrange(n_edges_orig), ids_edges_orig):
1545
edgeprops[i] = edgeprops_all[id_edge]
1546
1547
edgeprops = edgeprops/np.sum(edgeprops)
1548
1549
# debug
1550
if 0:
1551
for id_edge, prob in zip(ids_edges_orig, edgeprops):
1552
print ' orig id_edge', id_edge, 'has prob', prob
1553
1554
for d in xrange(int(tripnumber+0.5)):
1555
# print ' ------------'
1556
# print ' generte trip',d
1557
time_depart = np.random.uniform(time_start, time_end)
1558
1559
i_orig = np.argmax(np.random.rand(n_edges_orig)*edgeprops)
1560
id_edge_orig = ids_edges_orig[i_orig]
1561
1562
# destination edge is origin edge
1563
# this is no problem as taxis will never leave the sim
1564
id_edge_dest = id_edge_orig
1565
route = [id_edge_orig]
1566
1567
# Destination is next edge
1568
#
1569
#is_accessible = False
1570
# for id_edge_dest in fstar[id_edge_orig]:
1571
# # if check accessibility...
1572
# ind_lane_depart_taxi = edges.get_laneindex_allowed(id_edge_dest, id_mode_taxi)
1573
# ind_lane_depart_ped = edges.get_laneindex_allowed(id_edge_dest, id_mode_ped)
1574
# if (ind_lane_depart_taxi >= 0)&(ind_lane_depart_ped >= 0):
1575
# is_accessible = True
1576
# break
1577
# if not is_accessible:
1578
# id_edge_dest = id_edge_orig
1579
# route = [id_edge_orig]
1580
# else:
1581
# route = [id_edge_orig,id_edge_dest]
1582
1583
id_vtype = ids_vtype_mode_taxi[np.argmax(
1584
np.random.rand(n_vtypes_taxi)*prob_vtype_mode_taxi)]
1585
1586
# trip is from beginning to end of edge
1587
# however, taxi will not be eliminated at the
1588
# end of edge but continue to next client
1589
id_trip = trips.make_trip(id_vtype=id_vtype,
1590
time_depart=time_depart,
1591
id_edge_depart=id_edge_orig,
1592
id_edge_arrival=id_edge_dest,
1593
ind_lane_depart=-5, # "first":
1594
ind_lane_arrival=-1, # "current",
1595
position_depart=-4, # "base",
1596
position_arrival=-2, # "max",
1597
speed_depart=0.0,
1598
speed_arrival=0.0,
1599
route=route,
1600
)
1601
1602
n_trips_generated += 1
1603
1604
print ' n_trips_generated', n_trips_generated, 'of', self.n_taxi
1605
return True
1606
1607
else:
1608
print ' no taxi created n_edges_orig', n_edges_orig, 'tripnumber', tripnumber
1609
return False
1610
1611
def do(self):
1612
1613
return self.generate_taxi()
1614
1615
1616
if __name__ == '__main__':
1617
###############################################################################
1618
# print 'sys.path',sys.path
1619
from agilepy.lib_wx.objpanel import objbrowser
1620
from agilepy.lib_base.logger import Logger
1621
#from coremodules.scenario import scenario
1622
from coremodules.network import network
1623
logger = Logger()
1624
NETPATH = os.path.join(SUMOPYDIR, 'coremodules', 'network', 'testnet')
1625
net = network.Network(logger=logger)
1626
rootname = 'facsp2'
1627
net.import_xml(rootname, NETPATH)
1628
# net.read_sumonodes(os.path.join(NETPATH,'facsp2.nod.xml'))
1629
# net.read_sumoedges(os.path.join(NETPATH,'facsp2.edg.xml'))
1630
demand = Demand(net=net, logger=logger)
1631
# demand.set_net(net)
1632
# landuse.facilities.import_poly(os.path.join(NETPATH,'facsp2.poly.xml'))
1633
#landuse.import_xml(rootname, NETPATH)
1634
objbrowser(demand)
1635
1636