1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo 2# Copyright (C) 2016-2019 German Aerospace Center (DLR) and others. 3# SUMOPy module 4# Copyright (C) 2012-2017 University of Bologna - DICAM 5# This program and the accompanying materials 6# are made available under the terms of the Eclipse Public License v2.0 7# which accompanies this distribution, and is available at 8# http://www.eclipse.org/legal/epl-v20.html 9# SPDX-License-Identifier: EPL-2.0 10 11# @file prt-12-berthoptok.py 12# @author Joerg Schweizer 13# @date 14# @version $Id$ 15 16""" 17This plugin provides methods to run and analyze PRT networks. 18 19 20""" 21import os 22import sys 23import numpy as np 24import random 25#from xml.sax import saxutils, parse, handler 26 27 28from coremodules.modules_common import * 29import agilepy.lib_base.classman as cm 30import agilepy.lib_base.arrayman as am 31import agilepy.lib_base.xmlman as xm 32#from agilepy.lib_base.misc import get_inversemap 33#from agilepy.lib_base.geometry import find_area 34#from agilepy.lib_base.processes import Process,CmlMixin,ff,call 35from coremodules.network.network import SumoIdsConf 36from coremodules.network.routing import edgedijkstra, get_mincostroute_edge2edge 37from coremodules.simulation import sumo 38from coremodules.simulation.sumo import traci 39#from coremodules.network import routing 40 41from coremodules.demand.virtualpop import StageTypeMixin 42 43BERTHSTATES = {'free': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3} 44VEHICLESTATES = {'init': 0, 'waiting': 1, 'boarding': 2, 45 'alighting': 3, 'emptytrip': 4, 'occupiedtrip': 5, 'forewarding': 6} 46STOPTYPES = {'person': 0, 'freight': 1, 'depot': 2, 'group': 3, 'mixed': 4} 47# def detect_entered_left(x,y): 48# """ 49# returns the enter and left elemets of list x (before) 50# and list y (after) 51# """ 52# if len(x) == 0: 53# if len(y) == 0: 54# return 55 56 57class PrtBerths(am.ArrayObjman): 58 59 def __init__(self, ident, prtstops, **kwargs): 60 # print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1') 61 self._init_objman(ident=ident, 62 parent=prtstops, 63 name='PRT Berths', 64 info='PRT Berths.', 65 **kwargs) 66 67 self._init_attributes() 68 69 def _init_attributes(self): 70 #vtypes = self.get_scenario().demand.vtypes 71 net = self.get_scenario().net 72 self.add(cm.AttrConf('length_default', 4.0, 73 groupnames=['parameters', 'options'], 74 name='Default length', 75 info='Default berth length.', 76 unit='m', 77 )) 78 79 self.add_col(am.IdsArrayConf('ids_prtstop', self.parent, 80 name='PRT stop ID', 81 info='PRT stop ID', 82 )) 83 84 # states now dynamic, see prepare_sim 85 if hasattr(self, 'states'): 86 self.delete('states') 87 # self.add_col(am.ArrayConf( 'states', default = BERTHSTATES['free'], 88 # dtype = np.int32, 89 # choices = BERTHSTATES, 90 # name = 'state', 91 # info = 'State of berth.', 92 # )) 93 94 self.add_col(am.ArrayConf('stoppositions', default=0.0, 95 dtype=np.float32, 96 name='Stop position', 97 info='Position on edge where vehicle nose stops.', 98 )) 99 100 def prepare_sim(self, process): 101 # print 'PrtBerths.prepare_sim' 102 ids = self.get_ids() 103 self.states = BERTHSTATES['free']*np.ones(np.max(ids)+1, dtype=np.int32) 104 self.ids_veh = -1*np.ones(np.max(ids)+1, dtype=np.int32) 105 return [] # berth has no update function 106 107 def get_scenario(self): 108 return self.parent.get_scenario() 109 110 def get_prtvehicles(self): 111 return self.parent.parent.prtvehicles 112 113 def make(self, id_stop, position_from=None, position_to=None, 114 n_berth=None, 115 offset_firstberth=0.0, offset_stoppos=-0.0): 116 stoplength = position_to-position_from 117 print 'Berths.make', id_stop, stoplength 118 119 # TODO: let define berth number either explicitely or through stoplength 120 121 length_berth = self.length_default.get_value() 122 positions = position_from + offset_firstberth\ 123 + np.arange(length_berth-offset_firstberth, stoplength+length_berth, length_berth) + offset_stoppos 124 n_berth = len(positions) 125 126 # force number of berth to be pair 127 if n_berth % 2 == 1: 128 positions = positions[1:] 129 n_berth -= 1 130 131 ids_berth = self.add_rows(n=n_berth, 132 stoppositions=positions, 133 ids_prtstop=id_stop * np.ones(n_berth, dtype=np.int32), 134 ) 135 return ids_berth 136 137 def set_prtvehicles(self, prtvehicles): 138 """ 139 Defines attributes which are linked with prtvehicles 140 """ 141 self.add_col(am.IdsArrayConf('ids_veh_allocated', prtvehicles, 142 name='Alloc. veh ID', 143 info='ID of vehicle which have allocated this berth. -1 means no allocation.', 144 )) 145 146 147class PrtStops(am.ArrayObjman): 148 def __init__(self, ident, prtservices, **kwargs): 149 self._init_objman(ident=ident, 150 parent=prtservices, 151 name='Public transport stops', 152 info='Contains information on PRT stops.', 153 #xmltag = ('additional','busStop','stopnames'), 154 version=0.1, 155 **kwargs) 156 self._init_attributes() 157 158 def _init_attributes(self): 159 self.add(cm.ObjConf(PrtBerths('berths', self))) 160 161 berths = self.get_berths() 162 net = self.get_scenario().net 163 164 self.add(cm.AttrConf('time_update', 0.5, 165 groupnames=['parameters'], 166 name='Update time', 167 info="Update time for station.", 168 unit='s', 169 )) 170 171 if hasattr(self, 'time_update_man'): 172 self.delete('time_update_man') 173 self.delete('timehorizon') 174 175 self.add_col(am.IdsArrayConf('ids_ptstop', net.ptstops, 176 name='ID PT stop', 177 info='ID of public transport stop. ', 178 )) 179 180 if hasattr(self, 'are_depot'): 181 self.delete('are_depot') 182 183 self.add_col(am.ArrayConf('types', default=STOPTYPES['person'], 184 dtype=np.int32, 185 perm='rw', 186 choices=STOPTYPES, 187 name='Type', 188 info='Type of stop.', 189 )) 190 191 self.add_col(am.IdlistsArrayConf('ids_berth_alight', berths, 192 #groupnames = ['_private'], 193 name='Alight berth IDs', 194 info="Alight berth IDs.", 195 )) 196 197 self.add_col(am.IdlistsArrayConf('ids_berth_board', berths, 198 #groupnames = ['_private'], 199 name='Board berth IDs', 200 info="Board berth IDs.", 201 )) 202 203 # self.add_col(am.ArrayConf( 'inds_berth_alight_allocated', default = 0, 204 # #groupnames = ['_private'], 205 # dtype = np.int32, 206 # perm = 'rw', 207 # name = 'Ind aberth lastalloc', 208 # info = 'Berth index of last allocated berth in alight zone.', 209 # )) 210 211 # self.add_col(am.ArrayConf( 'inds_berth_board_allocated', default = 0, 212 # #groupnames = ['_private'], 213 # dtype = np.int32, 214 # perm = 'rw', 215 # name = 'Ind bberth lastalloc', 216 # info = 'Berth index of last allocated berth in boarding zone.', 217 # )) 218 219 def get_edges(self, ids_prtstop): 220 net = self.get_scenario().net 221 return net.lanes.ids_edge[net.ptstops.ids_lane[self.ids_ptstop[ids_prtstop]]] 222 223 def get_berths(self): 224 return self.berths.get_value() 225 226 def get_scenario(self): 227 return self.parent.get_scenario() 228 229 def set_prtvehicles(self, prtvehicles): 230 self.get_berths().set_prtvehicles(prtvehicles) 231 232 def set_vehicleman(self, vehicleman): 233 self.add(cm.ObjConf(vehicleman, is_child=False, groups=['_private'])) 234 235 def get_vehicleman(self): 236 return self.vehicleman.get_value() 237 238 def get_closest(self, coords): 239 """ 240 Returns the closest prt stop for each coord in coords vector. 241 """ 242 net = self.get_scenario().net 243 ptstops = net.ptstops 244 lanes = net.lanes 245 n = len(coords) 246 # print 'get_closest',n 247 248 #ids_stop = self.get_ids() 249 250 ids_prtstop = self.get_ids() 251 ids_ptstop = self.ids_ptstop[ids_prtstop] 252 coords_stop = ptstops.centroids[ids_ptstop] 253 ids_edge_stop = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]] 254 255 inds_closest = np.zeros(n, dtype=np.int32) 256 257 i = 0 258 for coord in coords: 259 ind_closest = np.argmin(np.sum((coord-coords_stop)**2, 1)) 260 inds_closest[i] = ind_closest 261 i += 1 262 263 ids_prtstop_closest = ids_prtstop[inds_closest] 264 ids_edge_closest = ids_edge_stop[inds_closest] 265 266 return ids_prtstop_closest, ids_edge_closest 267 268 def get_waitpositions(self, ids, is_alight=False, offset=-0.0): 269 """ 270 Assign a wait-position for each stop in ids 271 272 offset is wait position relative to the vehicle nose. 273 """ 274 # print 'get_waitpositions min(ids),max(ids)',min(ids),is_alight,max(ids),offset 275 positions = np.zeros(len(ids), dtype=np.float32) 276 randint = random.randint 277 if is_alight: 278 ids_berths = self.ids_berth_alight[ids] 279 else: 280 ids_berths = self.ids_berth_board[ids] 281 282 stoppositions = self.get_berths().stoppositions 283 # print ' ids_berths',ids_berths 284 i = 0 285 for id_stop, ids_berth in zip(ids, ids_berths): 286 #ids_berth = ids_berths[id_stop] 287 ind_berth = randint(0, len(ids_berth)-1) 288 289 positions[i] = stoppositions[ids_berth[ind_berth]] 290 # print ' id_stop,ids_berth,posiions',id_stop,ids_berth,stoppositions[ids_berth[ind_berth]] 291 i += 1 292 #positions[i] = stoppositions[ids_berth[randint(0,len(ids_berth))]] 293 # for id_stop , pos in zip(ids, positions): 294 # print ' id_stop %d, is_alight = %s, pos %.2fm'%(id_stop, is_alight ,pos) 295 296 return positions+offset 297 298 def prepare_sim(self, process): 299 print 'PrtStops.prepare_sim' 300 net = self.get_scenario().net 301 ptstops = net.ptstops 302 ids_edge_sumo = net.edges.ids_sumo 303 304 berths = self.get_berths() 305 lanes = net.lanes 306 ids_edge_sumo = net.edges.ids_sumo 307 ids = self.get_ids() 308 309 # station management 310 self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1, dtype=np.object) 311 self.ids_stop_to_ids_edge_sumo[ids] = ids_edge_sumo[lanes.ids_edge[ptstops.ids_lane[self.ids_ptstop[ids]]]] 312 313 self.id_edge_sumo_to_id_stop = {} 314 for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]): 315 self.id_edge_sumo_to_id_stop[id_edge_sumo] = id_stop 316 317 self.inds_berth_alight_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32) 318 self.inds_berth_board_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32) 319 self.ids_vehs_alight_allocated = np.zeros(np.max(ids)+1, dtype=np.object) 320 self.ids_vehs_board_allocated = np.zeros(np.max(ids)+1, dtype=np.object) 321 322 self.ids_vehs_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object) 323 self.ids_vehs = np.zeros(np.max(ids)+1, dtype=np.object) 324 self.ids_vehs_toallocate = np.zeros(np.max(ids)+1, dtype=np.object) 325 self.times_lastboard = 10**4*np.ones(np.max(ids)+1, dtype=np.int32) 326 327 # for vehicle management 328 self.numbers_veh = np.zeros(np.max(ids)+1, dtype=np.int32) 329 self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype=np.int32) 330 331 # person management 332 self.ids_persons_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object) 333 self.ids_persons_sumo_boarded = np.zeros(np.max(ids)+1, dtype=np.object) 334 self.ids_persons_sumo_wait = np.zeros(np.max(ids)+1, dtype=np.object) 335 virtualpop = self.get_scenario().demand.virtualpop 336 stagelists = virtualpop.get_plans().stagelists 337 ids_persons = virtualpop.get_ids() 338 prttransits = self.parent.prttransits 339 id_person_to_origs_dests = {} 340 341 # if len(ids_persons)>0: 342 # TODO: move to prtservices 343 for id_person, stagelist in zip(ids_persons, stagelists[virtualpop.ids_plan[ids_persons]]): 344 for stages, id_stage in stagelist: 345 if stages.ident == 'prttransits': 346 id_fromedge_sumo = ids_edge_sumo[stages.ids_fromedge[id_stage]] 347 id_toedge_sumo = ids_edge_sumo[stages.ids_toedge[id_stage]] 348 data_orig_dest = (self.id_edge_sumo_to_id_stop[id_fromedge_sumo], 349 self.id_edge_sumo_to_id_stop[id_toedge_sumo], 350 id_fromedge_sumo, 351 id_toedge_sumo) 352 353 id_person_sumo = virtualpop.get_id_sumo_from_id(id_person) 354 if id_person_to_origs_dests.has_key(id_person_sumo): 355 id_person_to_origs_dests[id_person_sumo].append(data_orig_dest) 356 else: 357 id_person_to_origs_dests[id_person_sumo] = [data_orig_dest] 358 359 print ' id_person_to_origs_dests=\n', id_person_to_origs_dests 360 self.id_person_to_origs_dests = id_person_to_origs_dests 361 362 # this is only used for crazy person stage detection 363 # angles_stop = 364 365 # various initianilizations 366 for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]): 367 # set allocation index to last possible berth 368 self.inds_berth_alight_allocated[id_stop] = len(self.ids_berth_alight[id_stop]) 369 self.inds_berth_board_allocated[id_stop] = len(self.ids_berth_board[id_stop]) 370 371 self.ids_vehs_alight_allocated[id_stop] = [] 372 self.ids_vehs_board_allocated[id_stop] = [] 373 374 self.ids_vehs_sumo_prev[id_stop] = set([]) 375 self.ids_persons_sumo_prev[id_stop] = set([]) 376 self.ids_persons_sumo_boarded[id_stop] = [] 377 self.ids_persons_sumo_wait[id_stop] = [] 378 self.ids_vehs[id_stop] = [] 379 self.ids_vehs_toallocate[id_stop] = [] 380 381 # traci.edge.subscribe(id_edge_sumo, [traci.constants.VAR_ARRIVED_VEHICLES_IDS]) 382 updatedata_berth = berths.prepare_sim(process) 383 384 return [(self.time_update.get_value(), self.process_step), 385 ]+updatedata_berth 386 387 def process_step(self, process): 388 print 79*'_' 389 print 'PrtStops.process_step' 390 net = self.get_scenario().net 391 ptstops = net.ptstops 392 berths = self.get_berths() 393 lanes = net.lanes 394 ids_edge_sumo = net.edges.ids_sumo 395 vehicles = self.parent.prtvehicles 396 virtualpop = self.get_scenario().demand.virtualpop 397 ids = self.get_ids() 398 399 for id_stop, id_edge_sumo, ids_veh_sumo_prev, ids_person_sumo_prev in\ 400 zip(ids, self.ids_stop_to_ids_edge_sumo[ids], 401 self.ids_vehs_sumo_prev[ids], 402 self.ids_persons_sumo_prev[ids]): 403 print ' '+60*'.' 404 print ' process id_stop,id_edge_sumo', id_stop, id_edge_sumo 405 if 1: 406 407 # print ' ids_berth_alight',self.ids_berth_alight[id_stop] 408 # print ' ids_berth_board',self.ids_berth_board[id_stop] 409 print ' ids_vehs_toallocate', self.ids_vehs_toallocate[id_stop] 410 print ' ids_vehs_alight_allocated', self.ids_vehs_alight_allocated[id_stop] 411 print ' ids_vehs_board_allocated', self.ids_vehs_board_allocated[id_stop] 412 print ' inds_berth_alight_allocated', self.inds_berth_alight_allocated[id_stop] 413 print ' inds_berth_board_allocated', self.inds_berth_board_allocated[id_stop] 414 print ' numbers_person_wait', self.numbers_person_wait[id_stop] 415 print ' ids_persons_sumo_wait', self.ids_persons_sumo_wait[id_stop] 416 print ' ids_persons_sumo_boarded', self.ids_persons_sumo_boarded[id_stop] 417 print ' times_lastboard', self.times_lastboard[id_stop] 418 419 if 0: 420 for id_veh_sumo in self.ids_vehs_sumo_prev[id_stop]: 421 print ' stopstate ', id_veh_sumo, bin(traci.vehicle.getStopState(id_veh_sumo))[2:] 422 423 if 0: 424 self.get_berthqueues(id_stop) 425 426 # check for new vehicle arrivals/departures 427 ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_sumo)) 428 # print ' ids_veh_sumo_prev=',ids_veh_sumo_prev 429 # print ' ids_veh_sumo=',ids_veh_sumo 430 431 if ids_veh_sumo_prev != ids_veh_sumo: 432 ids_veh_entered = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo.difference(ids_veh_sumo_prev))) 433 ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo))) 434 for id_veh in ids_veh_entered: 435 self.enter(id_stop, id_veh) 436 437 for id_veh in ids_veh_left: 438 self.exit(id_stop, id_veh) 439 self.ids_vehs_sumo_prev[id_stop] = ids_veh_sumo 440 # print ' ids_veh_sumo_entered',ids_veh_sumo_entered 441 # print ' ids_veh_sumo_left',ids_veh_sumo_left 442 443 # check whether allocated vehicles arrived at alighting berths 444 ids_veh_remove = [] 445 for id_veh in self.ids_vehs_alight_allocated[id_stop]: 446 # TODO: here we could also check vehicle position 447 if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)): 448 ids_veh_remove.append(id_veh) 449 id_berth_alight = vehicles.ids_berth[id_veh] 450 berths.ids_veh[id_berth_alight] = id_veh 451 berths.states[id_berth_alight] = BERTHSTATES['alighting'] 452 vehicles.alight(id_veh) 453 454 for id_veh in ids_veh_remove: 455 self.ids_vehs_alight_allocated[id_stop].remove(id_veh) 456 457 # check whether we can move vehicles from alighting to 458 # boarding berths 459 460 # TODO: here we must check if berth in boarding zone are free 461 # AND if they are occupied with empty vehicles, those 462 # vehicles need to be kicked out...but only in case 463 # new vehicles are waiting to be allocated 464 465 ids_berth_alight = self.ids_berth_alight[id_stop][::-1] 466 ids_berth_board = self.ids_berth_board[id_stop][::-1] 467 for id_berth_alight, id_veh in zip( 468 ids_berth_alight, 469 berths.ids_veh[ids_berth_alight], 470 ): 471 472 print ' check alight->board veh', id_veh 473 # TODO: this could go into one vehicle method? 474 475 if id_veh >= 0: # is there a waiting vehicle 476 # print ' is_completed_alighting',vehicles.is_completed_alighting(id_veh) 477 if vehicles.is_completed_alighting(id_veh): 478 479 id_berth_board = self.allocate_board(id_stop) 480 print ' try allocate id_veh=prt.%d for berth id_berth_board=%d' % (id_veh, id_berth_board) 481 if id_berth_board >= 0: 482 # ,berths.stoppositions[id_berth_board] 483 print ' send vehicle id_veh %d to id_berth_board %d' % (id_veh, id_berth_board) 484 berths.ids_veh[id_berth_alight] = -1 485 berths.states[id_berth_alight] = BERTHSTATES['free'] 486 487 vehicles.control_stop_board(id_veh, id_stop, id_berth_board, 488 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop], 489 position=berths.stoppositions[id_berth_board], 490 ) 491 self.ids_vehs_board_allocated[id_stop].append(id_veh) 492 493 # if all allocated vehicles found their berth and all berths are free, then 494 # reset alight allocation index 495 if len(self.ids_vehs_alight_allocated[id_stop]) == 0: 496 if np.all(berths.states[ids_berth_alight] == BERTHSTATES['free']): 497 # print ' reset inds_berth_alight_allocated',self.inds_berth_alight_allocated[id_stop],'->',len(self.ids_berth_alight[id_stop]) 498 self.inds_berth_alight_allocated[id_stop] = len(self.ids_berth_alight[id_stop]) 499 500 # try to allocate unallocated vehicles 501 ids_veh_remove = [] 502 for id_veh in self.ids_vehs_toallocate[id_stop]: 503 id_berth = self.allocate_alight(id_stop) 504 if id_berth < 0: 505 # allocation failed 506 # do nothing, vehicle continues to wait for allocation 507 pass 508 else: 509 # command vehicle to go to berth for alighting 510 # print ' send waiting vehicle id_veh %d to id_berth_alight %d'%(id_veh,id_berth)#,berths.stoppositions[id_berth] 511 self.parent.prtvehicles.control_stop_alight(id_veh, id_stop, id_berth, 512 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop], 513 position=self.get_berths( 514 ).stoppositions[id_berth], 515 ) 516 self.ids_vehs_alight_allocated[id_stop].append(id_veh) 517 ids_veh_remove.append(id_veh) 518 519 for id_veh in ids_veh_remove: 520 self.ids_vehs_toallocate[id_stop].remove(id_veh) 521 522 # check whether allocated vehicles arrived at boarding berths 523 ids_veh_remove = [] 524 for id_veh in self.ids_vehs_board_allocated[id_stop]: 525 # TODO: here we could also check vehicle position 526 if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)): 527 ids_veh_remove.append(id_veh) 528 id_berth_board = vehicles.ids_berth[id_veh] 529 berths.ids_veh[id_berth_board] = id_veh 530 berths.states[id_berth_board] = BERTHSTATES['boarding'] 531 vehicles.board(id_veh, 532 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop]) 533 534 for id_veh in ids_veh_remove: 535 self.ids_vehs_board_allocated[id_stop].remove(id_veh) 536 537 # if all allocated vehicles for board area 538 # found their berth and all berths are free, then 539 # reset allocation index 540 # print ' board berth rest check', len(self.ids_vehs_board_allocated[id_stop])==0,np.all(berths.states[ids_berth_board]==BERTHSTATES['free']),berths.states[ids_berth_board] 541 if (self.inds_berth_board_allocated[id_stop] == 0) & (len(self.ids_vehs_board_allocated[id_stop]) == 0): 542 543 if np.all(berths.states[ids_berth_board] == BERTHSTATES['free']): 544 # print ' reset inds_berth_board_allocated to',len(self.ids_berth_board[id_stop]) 545 self.inds_berth_board_allocated[id_stop] = len(self.ids_berth_board[id_stop]) 546 547 # check for new person entering/left the station edge 548 ids_person_sumo = set(traci.edge.getLastStepPersonIDs(id_edge_sumo)) 549 # for id_person_sumo in ids_person_sumo: 550 # print ' id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo) 551 552 if ids_person_sumo_prev != ids_person_sumo: 553 554 # deal with persons who left the edge 555 ids_person_sumo_left = ids_person_sumo_prev.difference(ids_person_sumo) 556 for id_person_sumo in ids_person_sumo_left: 557 print ' id_person_sumo_left pers', id_person_sumo, traci.person.getRoadID(id_person_sumo) 558 # print ' ids_person_sumo',ids_person_sumo 559 # tricky: if the person who left the edge id_edge_sumo 560 # shows still id_edge_sumo then this person is in a vehicle 561 if traci.person.getRoadID(id_person_sumo) == id_edge_sumo: 562 print ' person boarded: pers', id_person_sumo, traci.person.getLanePosition(id_person_sumo) 563 self.ids_persons_sumo_boarded[id_stop].append(id_person_sumo) 564 self.ids_persons_sumo_wait[id_stop].remove(id_person_sumo) 565 self.numbers_person_wait[id_stop] -= 1 566 567 # deal with persons who entered the edge 568 ids_person_sumo_entered = ids_person_sumo.difference(ids_person_sumo_prev) 569 for id_person_sumo in ids_person_sumo_entered: 570 print ' id_person_sumo_entered pers', id_person_sumo, traci.person.getRoadID(id_person_sumo) 571 if self.id_person_to_origs_dests.has_key(id_person_sumo): 572 id_edge_sumo_dests = self.id_person_to_origs_dests[id_person_sumo] 573 # check if person still has a PRT trip 574 if len(id_edge_sumo_dests) > 0: 575 # check if next trip has origin edge equal to edge of this stop 576 if id_edge_sumo_dests[0][2] == id_edge_sumo: 577 self.ids_persons_sumo_wait[id_stop].append(id_person_sumo) 578 self.numbers_person_wait[id_stop] += 1 579 # else: 580 # print 'WARNING: person %s starts with % insted of %s.'%(id_person_sumo,id_edge_sumo_dests[0][2],id_edge_sumo) 581 582 self.ids_persons_sumo_prev[id_stop] = ids_person_sumo 583 584 if 0: 585 for id_person_sumo in ids_person_sumo_prev: 586 print ' ids_person_sumo=%s pos = %.2f ' % ( 587 id_person_sumo, traci.person.getLanePosition(id_person_sumo)) 588 print ' ids_persons_sumo_boarded', self.ids_persons_sumo_boarded[id_stop] 589 590 # check if boarding is completed in load area and program 591 ids_berth_board = self.ids_berth_board[id_stop][::-1] 592 for id_berth_board, id_veh in zip( 593 ids_berth_board, 594 berths.ids_veh[ids_berth_board], 595 ): 596 if id_veh >= 0: # is there a waiting vehicle 597 if vehicles.is_completed_boarding(id_veh): 598 self.schedule_trip_occupied(id_stop, 599 id_berth_board, 600 id_veh, 601 process.simtime) 602 603 # check if there are passengers in the vehicles which wait for 604 # alight allocate 605 # TODO: can be replaced by a single instruction 606 n_pax = 0 607 for id_veh in self.ids_vehs_alight_allocated[id_stop]+self.ids_vehs_toallocate[id_stop]: 608 if vehicles.states[id_veh] == VEHICLESTATES['occupiedtrip']: 609 n_pax += 1 610 # print ' n_pax' ,n_pax 611 # check whether to foreward vehicles in boarding berth 612 613 # no foreward if all berth are free occupied vehicles 614 if np.all(berths.states[ids_berth_board] == BERTHSTATES['free']): 615 # print ' foreward all occupied id_stop,ids_berth_board',id_stop,ids_berth_board 616 #self.foreward_boardzone(id_stop, ids_berth_board) 617 self.times_lastboard[id_stop] = 10**4 # reset clock if all are free 618 619 # foreward if there are passengers in unallocated vehicles 620 elif n_pax > 0: 621 # print ' call foreward_boardzone unblock',n_pax 622 self.foreward_boardzone(id_stop, ids_berth_board, process.simtime) 623 624 elif process.simtime - self.times_lastboard[id_stop] > 40: 625 # print ' call foreward_boardzone timeout',process.simtime,self.times_lastboard[id_stop],process.simtime - self.times_lastboard[id_stop] 626 self.foreward_boardzone(id_stop, ids_berth_board, process.simtime) 627 628 def schedule_trip_occupied(self, id_stop, id_berth, id_veh, simtime): 629 # TODO: actually a berth method?? 630 berths = self.get_berths() 631 632 print 'schedule_trip_occupied', id_stop, id_berth, id_veh 633 # identify whic of the boarding persons is in the 634 # vehicle which completed boarding 635 dist_min = np.inf 636 id_person_sumo_inveh = None 637 stoppos = berths.stoppositions[id_berth] 638 639 for id_person_sumo in self.ids_persons_sumo_boarded[id_stop]: 640 d = abs(stoppos - traci.person.getLanePosition(id_person_sumo)) 641 if d < dist_min: 642 dist_min = d 643 id_person_sumo_inveh = id_person_sumo 644 645 if id_person_sumo_inveh is not None: 646 # program vehicle to person's destination 647 id_stop_orig, id_stop_dest, id_edge_sumo_from, id_edge_sumo_to = \ 648 self.id_person_to_origs_dests[id_person_sumo_inveh].pop(0) 649 print ' found person', id_person_sumo_inveh, 'from', id_stop_orig, id_edge_sumo_from, 'to', id_edge_sumo_to, id_stop_dest 650 self.parent.vehicleman.push_occupiedtrip(id_veh, id_stop, id_stop_dest) 651 652 self.parent.prtvehicles.schedule_trip_occupied(id_veh, id_edge_sumo_to) 653 self.ids_persons_sumo_boarded[id_stop].remove(id_person_sumo_inveh) 654 self.times_lastboard[id_stop] = simtime 655 berths.states[id_berth] = BERTHSTATES['free'] 656 berths.ids_veh[id_berth] = -1 657 658 else: 659 print 'WARNING: on stop %d edge %s, berth %d no person found inside vehicle %d'( 660 id_stop, self.ids_stop_to_ids_edge_sumo[id_stop], id_berth, id_veh) 661 662 def schedule_trip_empty(self, id_stop, id_berth, id_veh, simtime): 663 664 # TODO: actually a berth method?? 665 berths = self.get_berths() 666 667 id_stop_target = self.parent.vehicleman.push_emptytrip(id_veh, id_stop) 668 669 # print 'schedule_trip_empty for',id_veh,' from',id_stop,'to',id_stop_target,id_edge_sumo_target 670 self.parent.prtvehicles.schedule_trip_empty(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target]) 671 672 berths.states[id_berth] = BERTHSTATES['free'] 673 berths.ids_veh[id_berth] = -1 674 675 def foreward_boardzone(self, id_stop, ids_berth_board, simtime): 676 print 'foreward_boardzone', id_stop, ids_berth_board 677 berths = self.get_berths() 678 #ids_berth_board = self.ids_berth_board[id_stop][::-1] 679 # inds_o berths.states[ids_berth_board] != BERTHSTATES['free'] 680 for id_berth, state in zip(ids_berth_board, berths.states[ids_berth_board]): 681 print ' id_berth,boarding?,id_veh', id_berth, state == BERTHSTATES['boarding'], berths.ids_veh[id_berth] 682 if state == BERTHSTATES['boarding']: 683 self.schedule_trip_empty(id_stop, id_berth, berths.ids_veh[id_berth], simtime) 684 685 self.times_lastboard[id_stop] = 10**4 # reset last board counter 686 687 def enter(self, id_stop, id_veh): 688 # print 'enter id_stop, id_veh',id_stop, id_veh 689 self.ids_vehs[id_stop].append(id_veh) 690 691 # tell vehman that veh arrived 692 #self.numbers_veh_arr[id_stop] -= 1 693 self.parent.vehicleman.conclude_trip(id_veh, id_stop) 694 695 self.numbers_veh[id_stop] += 1 696 id_berth = self.allocate_alight(id_stop) 697 if id_berth < 0: 698 # allocation failed 699 # command vehicle to slow down and wait for allocation 700 self.ids_vehs_toallocate[id_stop].append(id_veh) 701 self.parent.prtvehicles.control_slow_down(id_veh) 702 else: 703 # command vehicle to go to berth for alighting 704 # print ' send entering vehicle id_veh %d to id_berth_alight %d'%(id_veh,id_berth)#,self.get_berths().stoppositions[id_berth] 705 self.parent.prtvehicles.control_stop_alight(id_veh, id_stop, id_berth, 706 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop], 707 position=self.get_berths().stoppositions[id_berth], 708 ) 709 self.ids_vehs_alight_allocated[id_stop].append(id_veh) 710 711 def exit(self, id_stop, id_veh): 712 self.ids_vehs[id_stop].remove(id_veh) 713 self.numbers_veh[id_stop] -= 1 714 715 def allocate_alight(self, id_stop): 716 # print 'allocate_alight',id_stop, id_veh_sumo 717 #self.inds_berth_alight_allocated [id_stop] = len(self.ids_berth_alight[id_stop]) 718 ind_berth = self.inds_berth_alight_allocated[id_stop] 719 720 if ind_berth == 0: 721 # no free berth :( 722 return -1 723 else: 724 ind_berth -= 1 725 self.inds_berth_alight_allocated[id_stop] = ind_berth 726 return self.ids_berth_alight[id_stop][ind_berth] 727 728 def allocate_board(self, id_stop): 729 # print 'allocate_alight',id_stop, id_veh_sumo 730 #self.inds_berth_alight_allocated [id_stop] = len(self.ids_berth_alight[id_stop]) 731 ind_berth = self.inds_berth_board_allocated[id_stop] 732 733 if ind_berth == 0: 734 # no free berth :( 735 return -1 736 else: 737 ind_berth -= 1 738 self.inds_berth_board_allocated[id_stop] = ind_berth 739 return self.ids_berth_board[id_stop][ind_berth] 740 741 # def process_man(self, process): 742 # self.timehorizon.get_value() 743 744 def get_berthqueues(self, id_stop): 745 # currently not used 746 print 'get_berthqueues', id_stop 747 # TODO: use stop angle and person angle to detect waiting persons 748 ids_berth_board = self.ids_berth_board[id_stop] 749 ids_person_sumo = self.ids_persons_sumo_prev[id_stop] 750 positions = np.zeros(len(ids_person_sumo), dtype=np.float32) 751 #stages = np.zeros(len(ids_person_sumo),dtype = np.object) 752 angles = np.zeros(len(ids_person_sumo), dtype=np.float32) 753 stoppositions = self.get_berths().stoppositions[ids_berth_board] 754 bins = [stoppositions[0]-1.0]+list(stoppositions) 755 756 i = 0 757 for id_person_sumo in ids_person_sumo: 758 positions[i] = traci.person.getLanePosition(id_person_sumo) 759 #stages[i] = traci.person.getParameter(id_person_sumo,'stage') 760 angles[i] = traci.person.getAngle(id_person_sumo) 761 i += 1 762 763 queues, bins_after = np.histogram(positions, bins) 764 print ' ids_person_sumo', ids_person_sumo 765 print ' angles', angles 766 print ' stages', stages 767 print ' positions', positions 768 print ' bins', bins 769 print ' ids_berth_board=\n', ids_berth_board 770 print ' queues=\n', queues 771 return ids_berth_board, queues 772 #ids_persons_berth = np.zeros() 773 #queues_berth = np.zeros(len(ids_berth_board), dtype = np.int32) 774 # for id_berth, stopposition in stoppositions: 775 # inds_person = np.abs(positions-stopposition)<1.0 776 # 777 # #ids_persons_berth[id_berth] = ids_person_sumo[inds_person] 778 779 def make_from_net(self, mode='custom1'): 780 """ 781 Make prt stop database from PT stops in network. 782 """ 783 self.clear() 784 net = self.get_scenario().net 785 ptstops = net.ptstops 786 lanes = net.lanes 787 ids_ptstop = ptstops.get_ids() 788 id_mode_prt = net.modes.get_id_mode(mode) 789 ids_lane = ptstops.ids_lane[ids_ptstop] 790 #edgelengths = net.edges.lengths 791 792 for id_stop, modes_allow, position_from, position_to in zip( 793 ids_ptstop, 794 lanes.modes_allow[ids_lane], 795 ptstops.positions_from[ids_ptstop], 796 ptstops.positions_to[ids_ptstop], 797 ): 798 if id_mode_prt in modes_allow: 799 self.make(id_stop, 800 position_from, 801 position_to) 802 803 def make(self, id_ptstop, position_from, position_to): 804 """ 805 Initialize a new prt stop and generate berth. 806 """ 807 id_stop = self.add_row(ids_ptstop=id_ptstop) 808 ids_berth = self.get_berths().make(id_stop, position_from=position_from, 809 position_to=position_to) 810 n_berth = len(ids_berth) 811 n_berth_alight = int(0.5*n_berth) 812 n_berth_board = n_berth-n_berth_alight 813 self.ids_berth_alight[id_stop] = ids_berth[0:n_berth_alight] 814 self.ids_berth_board[id_stop] = ids_berth[n_berth_alight:n_berth] 815 return id_stop 816 817 818class PrtVehicles(am.ArrayObjman): 819 820 def __init__(self, ident, prtservices, **kwargs): 821 # print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1') 822 self._init_objman(ident=ident, 823 parent=prtservices, 824 name='PRT Veh.', 825 info='PRT vehicle database. These are shared vehicles.', 826 **kwargs) 827 828 self._init_attributes() 829 830 def _init_attributes(self): 831 vtypes = self.get_scenario().demand.vtypes 832 net = self.get_scenario().net 833 834 # TODO: add/update vtypes here 835 self.add_col(SumoIdsConf('Veh', xmltag='id')) 836 837 id_vtype = self.make_vtype() 838 839 self.add_col(am.IdsArrayConf('ids_vtype', vtypes, 840 id_default=id_vtype, 841 groupnames=['state'], 842 name='Veh. type', 843 info='PRT vehicle type.', 844 #xmltag = 'type', 845 )) 846 847 self.add_col(am.ArrayConf('states', default=VEHICLESTATES['init'], 848 dtype=np.int32, 849 choices=VEHICLESTATES, 850 name='state', 851 info='State of vehicle.', 852 )) 853 854 self.add_col(am.IdsArrayConf('ids_targetprtstop', self.parent.prtstops, 855 groupnames=['parameters'], 856 name='Target stop ID', 857 info='ID of current target PRT stop.', 858 )) 859 860 self.add_col(am.IdsArrayConf('ids_currentedge', net.edges, 861 groupnames=['state'], 862 name='Current edge ID', 863 info='Edge ID of most recent reported position.', 864 )) 865 866 self.add_col(am.IdsArrayConf('ids_targetedge', net.edges, 867 groupnames=['state'], 868 name='Target edge ID', 869 info='Target edge ID to be reached. This can be either intermediate target edges (), such as a compressor station.', 870 )) 871 872 def make_vtype(self): 873 id_vtype = self.get_scenario().demand.vtypes.add_vtype('PRT', 874 accel=2.5, 875 decel=2.5, 876 sigma=1.0, 877 length=3.5, 878 width=1.6, 879 height=1.7, 880 number_persons=1, 881 capacity_persons=1, 882 dist_min=0.5, 883 speed_max=10.0, 884 emissionclass='HBEFA3/zero', 885 mode='custom1', # specifies mode for demand 886 color=np.array((255, 240, 0, 255), np.float32)/255.0, 887 shape_gui='evehicle', 888 times_boarding=1.5, 889 times_loading=20.0, 890 sublane_alignment_lat='center', 891 sublane_speed_max_lat=0.5, 892 sublane_gap_min_lat=0.24, 893 sublane_alignment_eager=1000000.0, 894 ) 895 return id_vtype 896 897 def prepare_sim(self, process): 898 print 'PrtVehicles.prepare_sim' 899 net = self.get_scenario().net 900 ptstops = net.ptstops 901 lanes = net.lanes 902 ids_edge_sumo = net.edges.ids_sumo 903 ids = self.get_ids() 904 905 self.ids_berth = -1*np.ones(np.max(ids)+1, dtype=np.int32) 906 907 # for id_veh, id_veh_sumo in zip(ids,self.ids_sumo[ids]): 908 # traci.vehicle.subscribe(id_veh_sumo, 909 # [ traci.constants.VAR_ROAD_ID, 910 # traci.constants.VAR_POSITION, 911 # traci.constants.VAR_STOPSTATE, 912 # ]) 913 return [] # currentlu vehicles are not updated 914 915 def process_step(self, process): 916 # print 'process_step',traci.vehicle.getSubscriptionResults() 917 pass 918 # VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6} 919 920 def control_slow_down(self, id_veh, speed=1.0, time_slowdown=5): 921 traci.vehicle.slowDown(self.get_id_sumo(id_veh), speed, time_slowdown) 922 # pass 923 924 def control_stop_alight(self, id_veh, id_stop, id_berth, 925 id_edge_sumo=None, 926 position=None, 927 ): 928 id_veh_sumo = self.get_id_sumo(id_veh) 929 p = traci.vehicle.getLanePosition(id_veh_sumo) 930 print 'control_stop_alight', id_veh_sumo, p, '->', position, 'id_berth', id_berth 931 #d = position - p 932 #v = traci.vehicle.getSpeed(id_veh_sumo) 933 #d_save = 1.0/(2*2.5)*(v**2) 934 # print ' v=',v 935 # print ' d,d_save',d,d_save 936 self.states[id_veh] = VEHICLESTATES['forewarding'] 937 self.ids_berth[id_veh] = id_berth 938 traci.vehicle.setStop(self.get_id_sumo(id_veh), 939 id_edge_sumo, 940 pos=position, 941 flags=0, 942 laneIndex=1, 943 ) 944 945 def control_stop_board(self, id_veh, id_stop, id_berth, 946 id_edge_sumo=None, 947 position=None, 948 ): 949 950 print 'control_stop_board', self.get_id_sumo(id_veh), id_stop, id_berth, id_edge_sumo, position 951 952 id_veh_sumo = self.get_id_sumo(id_veh) 953 # print 'control_stop_board',id_veh_sumo,traci.vehicle.getLanePosition(id_veh_sumo),'->',position,id_berth 954 self.ids_berth[id_veh] = id_berth 955 self.states[id_veh] = VEHICLESTATES['forewarding'] 956 traci.vehicle.resume(id_veh_sumo) 957 958 traci.vehicle.setStop(id_veh_sumo, 959 id_edge_sumo, 960 startPos=position-4.0, 961 pos=position, 962 flags=2, # park and trigger 1+2,# 963 laneIndex=1, 964 ) 965 966 def alight(self, id_veh): 967 print 'alight', self.get_id_sumo(id_veh) 968 # TODO: necessary to keep copy of state? 969 self.states[id_veh] = VEHICLESTATES['alighting'] 970 # traci.vehicle.getStopState(self.get_id_sumo(id_veh)) 971 # VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting' 972 973 def board(self, id_veh, id_edge_sumo=None, position=None): 974 print 'board', self.get_id_sumo(id_veh) 975 # TODO: necessary to keep copy of state? 976 self.states[id_veh] = VEHICLESTATES['boarding'] 977 #id_veh_sumo = self.get_id_sumo(id_veh) 978 # print 'board',id_veh_sumo,'stopstate',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:] 979 # print ' ',dir(traci.vehicle) 980 # traci.vehicle.getLastStepPersonIDs() 981 # traci.vehicle.getStopState(self.get_id_sumo(id_veh)) 982 # VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting' 983 #traci.vehicle.setRoute(id_veh_sumo, [id_edge_sumo]) 984 # traci.vehicle.resume(id_veh_sumo) 985 986 # traci.vehicle.setStop( self.get_id_sumo(id_veh), 987 # traci.vehicle.getRoadID(id_veh_sumo), 988 # pos = traci.vehicle.getLanePosition(id_veh_sumo), 989 # flags= 2,# 990 # laneIndex= 1, 991 # ) 992 # print 'board ',id_veh_sumo, traci.vehicle.getStopState(id_veh_sumo )# bin(traci.vehicle.getStopState(id_veh_sumo ))[2:] 993 994 def is_completed_alighting(self, id_veh): 995 print 'is_completed_alighting', self.get_id_sumo(id_veh), self.states[id_veh], self.states[id_veh] == VEHICLESTATES['alighting'], traci.vehicle.getPersonNumber( 996 self.get_id_sumo(id_veh)), type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh))) 997 if self.states[id_veh] == VEHICLESTATES['alighting']: 998 if traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)) == 0: 999 print ' is_completed_alighting', self.get_id_sumo(id_veh), 'completed alighting' 1000 self.states[id_veh] = VEHICLESTATES['waiting'] 1001 return True 1002 else: 1003 return False 1004 1005 else: 1006 return True 1007 1008 def is_completed_boarding(self, id_veh): 1009 # 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))) 1010 if self.states[id_veh] == VEHICLESTATES['boarding']: 1011 if traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)) == 1: 1012 print 'is_completed_boarding', self.get_id_sumo(id_veh), 'completed boarding' 1013 self.states[id_veh] = VEHICLESTATES['waiting'] 1014 return True 1015 else: 1016 False 1017 1018 else: 1019 return True 1020 1021 def schedule_trip_occupied(self, id_veh, id_edge_sumo_dest): 1022 print 'schedule_trip_occupied', self.get_id_sumo(id_veh), id_edge_sumo_dest 1023 self.states[id_veh] = VEHICLESTATES['occupiedtrip'] 1024 traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest) 1025 1026 def schedule_trip_empty(self, id_veh, id_edge_sumo_to): 1027 print 'schedule_trip_empty', self.get_id_sumo(id_veh), id_edge_sumo_to 1028 self.states[id_veh] = VEHICLESTATES['emptytrip'] 1029 id_veh_sumo = self.get_id_sumo(id_veh) 1030 traci.vehicle.resume(id_veh_sumo) 1031 traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to) 1032 1033 def update_states(self, ids_veh): 1034 print 'update_states', ids_veh 1035 for id_veh in ids_veh: 1036 # getStopState 1037 # returns information in regard to stopping: 1038 # The returned integer is defined as 1 * stopped + 2 * parking 1039 # + 4 * personTriggered + 8 * containerTriggered + 16 * isBusStop 1040 # + 32 * isContainerStop 1041 1042 #isStopped, isStoppedTriggered 1043 1044 # 1045 binstate = traci.vehicle.getStopState(self.get_id_sumo(id_veh)) 1046 print ' id_veh,binstate=', id_veh, bin(binstate)[2:] 1047 1048 def make(self, n=-1, length_veh_av=4.0): 1049 """ 1050 Make n PRT vehicles 1051 If n = -1 then fill up stops with vehicles. 1052 """ 1053 print 'PrtVehicles.make', n, length_veh_av 1054 self.clear() 1055 net = self.get_scenario().net 1056 ptstops = net.ptstops 1057 prtstops = self.parent.prtstops 1058 lanes = net.lanes 1059 ids_prtstop = prtstops.get_ids() 1060 ids_ptstop = prtstops.ids_ptstop[ids_prtstop] 1061 ids_veh = [] 1062 for id_prt, id_edge, pos_from, pos_to in zip( 1063 ids_prtstop, 1064 lanes.ids_edge[ptstops.ids_lane[ids_ptstop]], 1065 ptstops.positions_from[ids_ptstop], 1066 ptstops.positions_to[ids_ptstop], 1067 ): 1068 # TODO: here we can select depos or distribute a 1069 # fixed number of vehicles or put them into berth 1070 # print ' ',pos_to,pos_from,int((pos_to-pos_from)/length_veh_av) 1071 1072 for i in range(int((pos_to-pos_from)/length_veh_av)): 1073 id_veh = self.add_row(ids_targetstop=id_prt, 1074 ids_currentedge=id_edge, 1075 ) 1076 1077 self.ids_sumo[id_veh] = self.get_id_sumo(id_veh) 1078 ids_veh.append(id_veh) 1079 1080 return ids_veh 1081 1082 # def write_veh 1083 # 1084 1085 def get_scenario(self): 1086 return self.parent.get_scenario() 1087 1088 def get_vtypes(self): 1089 """ 1090 Returns a set with all used PRT vehicle types. 1091 """ 1092 # print 'Vehicles_individual.get_vtypes',self.cols.vtype 1093 return set(self.ids_vtype.get_value()) 1094 1095 def get_id_sumo(self, id_veh): 1096 return 'prt.%s' % (id_veh) 1097 1098 def get_id_from_id_sumo(self, id_veh_sumo): 1099 prefix, idstr = id_veh_sumo.split('.') 1100 return int(idstr) 1101 1102 def get_ids_from_ids_sumo(self, ids_veh_sumo): 1103 n = len(ids_veh_sumo) 1104 ids = np.zeros(n, np.int32) 1105 for i in xrange(n): 1106 ids[i] = self.get_id_from_id_sumo(ids_veh_sumo[i]) 1107 return ids 1108 1109 def get_id_line_xml(self): 1110 return 'prt' 1111 1112 1113class PrtTransits(StageTypeMixin): 1114 def __init__(self, ident, population, name='Ride on PRT', info='Ride on Personal Rapid Transit network.'): 1115 self.init_stagetype(ident, 1116 population, name=name, 1117 info=info, 1118 ) 1119 self._init_attributes() 1120 1121 def _init_attributes(self): 1122 edges = self.parent.get_net().edges 1123 1124 self.add_col(am.IdsArrayConf('ids_fromedge', edges, 1125 groupnames=['parameters'], 1126 name='Edge ID from', 1127 info='Edge ID of departure PRT station.', 1128 )) 1129 1130 self.add_col(am.IdsArrayConf('ids_toedge', edges, 1131 groupnames=['parameters'], 1132 name='Edge ID to', 1133 info='Edge ID of destination PRT station.', 1134 )) 1135 1136 def set_prtservice(self, prtservice): 1137 self.add(cm.ObjConf(prtservice, is_child=False, groups=['_private'])) 1138 1139 def get_prtservice(self): 1140 return self.prtservice.get_value() 1141 1142 def prepare_planning(self): 1143 pass 1144 1145 def append_stage(self, id_plan, time_start=-1.0, 1146 duration=0.0, 1147 id_fromedge=-1, id_toedge=-1, **kwargs): 1148 """ 1149 Appends a PRT transit stage to plan id_plan. 1150 1151 """ 1152 # print 'PrtTransits.append_stage',id_stage 1153 1154 id_stage, time_end = StageTypeMixin.append_stage(self, 1155 id_plan, 1156 time_start, 1157 durations=duration, 1158 ids_fromedge=id_fromedge, 1159 ids_toedge=id_toedge, 1160 ) 1161 1162 # add this stage to the vehicle database 1163 # ind_ride gives the index of this ride (within the same plan??) 1164 #ind_ride = self.parent.get_individualvehicles().append_ride(id_veh, id_stage) 1165 return id_stage, time_end 1166 1167 def to_xml(self, id_stage, fd, indent=0): 1168 # <ride from="1/3to0/3" to="0/4to1/4" lines="train0"/> 1169 net = self.parent.get_net() 1170 #ids_stoplane = net.ptstops.ids_lane 1171 #ids_laneedge = net.lanes.ids_edge 1172 ids_sumoedge = net.edges.ids_sumo 1173 1174 #ind = self.get_ind(id_stage) 1175 fd.write(xm.start('ride', indent=indent)) 1176 fd.write(xm.num('from', ids_sumoedge[self.ids_fromedge[id_stage]])) 1177 fd.write(xm.num('to', ids_sumoedge[self.ids_toedge[id_stage]])) 1178 fd.write(xm.num('lines', 'prt')) 1179 # if self.cols.pos_edge_from[ind]>0: 1180 # fd.write(xm.num('departPos', self.cols.pos_edge_from[ind])) 1181 # if self.cols.pos_edge_to[ind]>0: 1182 # fd.write(xm.num('arrivalPos', self.cols.pos_edge_to[ind])) 1183 1184 fd.write(xm.stopit()) # ends stage 1185 1186 1187class VehicleMan(am.ArrayObjman): 1188 def __init__(self, ident, prtservices, **kwargs): 1189 self._init_objman(ident=ident, 1190 parent=prtservices, 1191 name='PRT vehicle management', 1192 info='PRT vehicle management.', 1193 #xmltag = ('additional','busStop','stopnames'), 1194 version=0.0, 1195 **kwargs) 1196 1197 self._init_attributes() 1198 self._init_constants() 1199 1200 def _init_attributes(self): 1201 self.add(cm.AttrConf('time_update', 30.0, 1202 groupnames=['parameters'], 1203 name='Man. update time', 1204 info="Update time for vehicle management.", 1205 unit='s', 1206 )) 1207 1208 self.add(cm.AttrConf('time_horizon', 1200, 1209 groupnames=['parameters'], 1210 name='Time horizon', 1211 info="Prediction time horizon of vehicle management.", 1212 unit='s', 1213 )) 1214 1215 # def set_stops(self,vehicleman): 1216 # self.add( cm.ObjConf( stops, is_child = False,groups = ['_private'])) 1217 1218 def get_stops(self): 1219 return self.parent.prtstops 1220 1221 def get_scenario(self): 1222 return self.parent.parent.get_scenario() 1223 1224 def prepare_sim(self, process): 1225 print 'VehicleMan.prepare_sim' 1226 net = self.get_scenario().net 1227 # station management 1228 # self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1,dtype = np.object) 1229 # vehicle management 1230 self.ids_stop = self.get_stops().get_ids() 1231 n_stoparray = np.max(self.ids_stop)+1 1232 self.numbers_veh_arr = np.zeros(n_stoparray, dtype=np.int32) 1233 return [(self.time_update.get_value(), self.process_step)] 1234 1235 def process_step(self, process): 1236 # roll time horizon 1237 pass 1238 1239 def push_occupiedtrip(self, id_veh, id_stop_from, id_stop_to): 1240 # print 'push_occupiedtrip from',id_veh, id_stop_from, id_stop_to 1241 # search closest stop 1242 stops = self.get_stops() 1243 self.numbers_veh_arr[id_stop_to] += 1 1244 # print ' to stop',id_stop 1245 return id_stop_to 1246 1247 def push_emptytrip(self, id_veh, id_stop): 1248 # print 'push_emptytrip id_veh,id_stop',id_veh,id_stop 1249 # search closest stop 1250 stops = self.get_stops() 1251 ids_stop = list(self.ids_stop) 1252 ids_stop.remove(id_stop) 1253 costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop] - 1254 self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop, ids_stop] 1255 1256 id_stop_target = ids_stop[np.argmax(costs)] 1257 self.numbers_veh_arr[id_stop_target] += 1 1258 #id_stop_target = ids_stop[random.randint(0,len(ids_stop)-1)] 1259 # print ' to stop',id_stop 1260 return id_stop_target 1261 1262 def conclude_trip(self, id_veh, id_stop): 1263 self.numbers_veh_arr[id_stop] -= 1 1264 1265 1266class PrtService(cm.BaseObjman): 1267 def __init__(self, ident, demand=None, 1268 name='PRT service', info='PRT service', 1269 **kwargs): 1270 # print 'PrtService.__init__',name 1271 1272 self._init_objman(ident=ident, parent=demand, 1273 name=name, info=info, **kwargs) 1274 1275 attrsman = self.set_attrsman(cm.Attrsman(self)) 1276 1277 self._init_attributes() 1278 self._init_constants() 1279 1280 def _init_attributes(self): 1281 print 'PrtService._init_attributes', hasattr(self, 'prttransit') 1282 attrsman = self.get_attrsman() 1283 #self.virtualpop = attrsman.add( cm.ObjConf( virtualpop, is_child = False,groups = ['_private'])) 1284 # if hasattr(self, 'prtvehicles'): 1285 # self.delete('prtvehicles') 1286 1287 self.prtstops = attrsman.add(cm.ObjConf(PrtStops('prtstops', self))) 1288 self.prtvehicles = attrsman.add(cm.ObjConf(PrtVehicles('prtvehicles', self))) 1289 self.vehicleman = attrsman.add(cm.ObjConf(VehicleMan('vehicleman', self))) 1290 1291 # -------------------------------------------------------------------- 1292 # prt rides table 1293 #self.add(cm.ObjConf(Transits('transits',self)) ) 1294 1295 # if not hasattr(self,'prttransit'): 1296 virtualpop = self.parent.virtualpop 1297 prttransits = virtualpop.add_stagetype('prttransits', PrtTransits) 1298 # print ' prttransits =',prttransits, 1299 self.prttransits = attrsman.add( 1300 cm.ObjConf(prttransits, is_child=False), 1301 is_overwrite=False, 1302 ) 1303 self.prttransits.set_prtservice(self) 1304 1305 # temporary attrfix 1306 #prtserviceconfig = self.parent.get_attrsman().prtservice 1307 #prtserviceconfig.groupnames = [] 1308 #prtserviceconfig.add_groupnames(['demand objects']) 1309 1310 def _init_constants(self): 1311 # print 'PrtService._init_constants',self,self.parent 1312 # this will ensure that PRT vtypes will be exported to routes 1313 # self.parent.add_demandobject(self) 1314 self.times_stop_to_stop = None 1315 1316 def get_vtypes(self): 1317 1318 ids_vtypes = set(self.prtvehicles.ids_vtype.get_value()) 1319 return ids_vtypes 1320 1321 def get_writexmlinfo(self, is_route=False): 1322 """ 1323 Returns three array where the first array is the 1324 begin time of the first vehicle and the second array is the 1325 write function to be called for the respectice vehicle and 1326 the third array contains the vehicle ids 1327 1328 Method used to sort trips when exporting to route or trip xml file 1329 """ 1330 print 'PRT.get_writexmlinfo' 1331 1332 # time of first PRT vehicle(s) to be inserted 1333 t_start = 0.0 1334 1335 # time betwenn insertion of consecutive vehicles at same stop 1336 t_delta = 10 # s 1337 1338 n_veh = len(self.prtvehicles) 1339 times_depart = np.zeros(n_veh, dtype=np.int32) 1340 writefuncs = np.zeros(n_veh, dtype=np.object) 1341 writefuncs[:] = self.write_prtvehicle_xml 1342 ids_veh = self.prtvehicles.get_ids() 1343 1344 id_edge_prev = -1 1345 i = 0 1346 t0 = t_start 1347 for id_edge in self.prtvehicles.ids_currentedge[ids_veh]: 1348 print ' id_edge, t_start, id_edge_prev', id_edge, t0, id_edge_prev 1349 times_depart[i] = t0 1350 t0 += t_delta 1351 if id_edge != id_edge_prev: 1352 t0 = t_start 1353 id_edge_prev = 1*id_edge 1354 i += 1 1355 1356 return times_depart, writefuncs, ids_veh 1357 1358 def write_prtvehicle_xml(self, fd, id_veh, time_begin, indent=2): 1359 print 'write_prtvehicle_xml', id_veh, time_begin 1360 # TODO: actually this should go in prtvehicles 1361 #time_veh_wait_after_stop = 3600 1362 net = self.get_scenario().net 1363 #lanes = net.lanes 1364 edges = net.edges 1365 #ind_ride = rides.get_inds(id_stage) 1366 #id_veh = rides.ids_veh[id_stage] 1367 prtvehicles = self.prtvehicles 1368 #ptstops = net.ptstops 1369 #prtstops = self.parent.prtstops 1370 #ids_prtstop = prtstops.get_ids() 1371 #ids_ptstop = prtstops.ids_ptstop[id_stop] 1372 # lanes.ids_edge[ptstops.ids_lane[ids_ptstop]], 1373 #id_lane_from = parking.ids_lane[id_parking_from] 1374 #laneindex_from = lanes.indexes[id_lane_from] 1375 #pos_from = parking.positions[id_parking_from] 1376 1377 #id_parking_to = rides.ids_parking_to[id_stage] 1378 #id_lane_to = parking.ids_lane[id_parking_to] 1379 #laneindex_to = lanes.indexes[id_lane_to] 1380 #pos_to = parking.positions[id_parking_to] 1381 1382 # write unique veh ID to prevent confusion with other veh declarations 1383 fd.write(xm.start('vehicle id="%s"' % prtvehicles.get_id_sumo(id_veh), indent+2)) 1384 1385 fd.write(xm.num('depart', '%d' % time_begin)) 1386 fd.write(xm.num('type', self.parent.vtypes.ids_sumo[prtvehicles.ids_vtype[id_veh]])) 1387 fd.write(xm.num('line', prtvehicles.get_id_line_xml())) 1388 fd.write(xm.stop()) 1389 1390 # write route 1391 fd.write(xm.start('route', indent+4)) 1392 # print ' edgeindex[ids_edge]',edgeindex[ids_edge] 1393 fd.write(xm.arr('edges', [edges.ids_sumo[prtvehicles.ids_currentedge[id_veh]]])) 1394 1395 # does not seem to have an effect, always starts at base???? 1396 fd.write(xm.num('departPos', 'base')) 1397 #fd.write(xm.num('departLane', laneindex_from )) 1398 fd.write(xm.stopit()) 1399 1400 # write depart stop 1401 # fd.write(xm.start('stop',indent+4)) 1402 #fd.write(xm.num('lane', edges.ids_sumo[lanes.ids_edge[id_lane_from]]+'_%d'%laneindex_from )) 1403 #fd.write(xm.num('duration', time_veh_wait_after_stop)) 1404 #fd.write(xm.num('startPos', pos_from )) 1405 #fd.write(xm.num('endPos', pos_from + parking.lengths[id_parking_from])) 1406 #fd.write(xm.num('triggered', "True")) 1407 # fd.write(xm.stopit()) 1408 1409 fd.write(xm.end('vehicle', indent+2)) 1410 1411 def make_stops_and_vehicles(self, n_veh=-1): 1412 self.prtstops.make_from_net() 1413 self.prtvehicles.make(n_veh) 1414 self.make_times_stop_to_stop() 1415 1416 def prepare_sim(self, process): 1417 if self.times_stop_to_stop is None: 1418 self.make_times_stop_to_stop() 1419 updatedata = self.prtvehicles.prepare_sim(process) 1420 1421 updatedata += self.prtstops.prepare_sim(process) 1422 updatedata += self.vehicleman.prepare_sim(process) 1423 print 'PrtService.prepare_sim updatedata', updatedata 1424 return updatedata 1425 1426 # def process_step(self, process): 1427 # self.prtvehicles.process_step(process) 1428 # self.prtstops.process_step(process) 1429 1430 def update(self): 1431 pass 1432 # person 1433 # http://www.sumo.dlr.de/daily/pydoc/traci._person.html 1434 # interesting 1435 #getPosition3D(self, personID) 1436 1437 # get edge id 1438 # getRoadID(self, personID) 1439 1440 # next edge or empty string at end of stage 1441 #getNextEdge(self, personID) 1442 1443 # getLanePosition(self, personID) 1444 1445 # getWaitingTime(self, personID) 1446 1447 # vehicle 1448 # http://www.sumo.dlr.de/daily/pydoc/traci._vehicle.html 1449 1450 # interesting: 1451 1452 # The vehicle's destination edge is set to the given edge id. The route is rebuilt. 1453 #changeTarget(id_sumo_veh, id_sumo_edge) 1454 1455 # getRoute 1456 # getRoute(string) -> list(string) 1457 # returns the ids of the edges the vehicle's route is made of. 1458 1459 #rerouteTraveltime(self, vehID, currentTravelTimes=True) 1460 1461 # getStopState 1462 # getStopState(string) -> integer 1463 1464 # or 1465 #'isAtBusStop', 'isAtContainerStop', 'isRouteValid', 'isStopped', 'isStoppedParking', 'isStoppedTriggered', 1466 1467 # setBusStop(self, vehID, stopID, duration=2147483647, until=-1, flags=0) 1468 1469 #setStop(self, vehID, edgeID, pos=1.0, laneIndex=0, duration=2147483647, flags=0, startPos=-1001.0, until=-1) 1470 1471 # to make it a follower or leader 1472 #setType(self, vehID, typeID) 1473 1474 # to reroute over compressors.....reroute after setting via!! 1475 # setVia(self, vehID, edgeList) 1476 1477 # slow down in stops 1478 # slowDown(self, vehID, speed, duration) 1479 1480 #traci.vehicle.setSpeed(id_veh_last, v_parking) 1481 #traci.vehicle.setRoute(id_veh_last, route_return) 1482 #traci.vehicle.setStop(id_veh_last, edgeid_return, pos= edgelength_return-20.0, laneIndex=0, duration = 15000) 1483 1484 # edge 1485 #getLastStepPersonIDs(self, edgeID) 1486 # getLastStepPersonIDs(string) -> list(string) 1487 1488 # Returns the ids of the persons on the given edge during the last time step. 1489 1490 #getLastStepVehicleIDs(self, edgeID) 1491 # getLastStepVehicleIDs(string) -> list(string) 1492 1493 def make_plans_prt(self, ids_person=None, mode='custom1'): 1494 # routing necessary? 1495 landuse = self.get_landuse() 1496 facilities = landuse.facilities 1497 1498 scenario = self.parent.get_scenario() 1499 vp = self.parent.get_scenario().demand.virtualpop 1500 1501 edges = scenario.net.edges 1502 lanes = scenario.net.lanes 1503 modes = scenario.net.modes 1504 1505 walks = vp.get_walks() 1506 prttransits = self.prttransits 1507 #transits = vp.get_transits() 1508 #ptstops = vp.get_ptstops() 1509 #ptlines = vp.get_ptlines() 1510 1511 #ptfstar = ptlinks.get_fstar() 1512 #pttimes = ptlinks.get_times() 1513 #stops_to_enter, stops_to_exit = ptlinks.get_stops_to_enter_exit() 1514 1515 #ids_stoplane = ptstops.ids_lane 1516 #ids_laneedge = scenario.net.lanes.ids_edge 1517 1518 times_est_plan = vp.plans.get_value().times_est 1519 # here we can determine edge weights for different modes 1520 1521 # centralize: 1522 walks.prepare_planning() 1523 prttransits.prepare_planning() 1524 1525 if ids_person is None: 1526 # print ' ids_mode_preferred',self.ids_mode_preferred.value 1527 # print ' private',MODES['private'] 1528 # print ' ',self.ids_mode_preferred == MODES['private'] 1529 1530 ids_person = self.select_ids( 1531 self.ids_mode_preferred.get_value() == modes.get_id_mode(mode), 1532 ) 1533 1534 ids_plan = vp.add_plans(ids_person) 1535 1536 n_plans = len(ids_plan) 1537 1538 print 'make_plans_prt n_plans=', n_plans 1539 1540 #ids_veh = self.get_individualvehicles().assign_to_persons(ids_person) 1541 inds_pers = self.get_inds(ids_person) 1542 # self.persons.cols.mode_preferred[inds_pers]='private' 1543 1544 times_start = self.times_start.value[inds_pers] 1545 inds_fac_home = facilities.get_inds(self.ids_fac_home.value[inds_pers]) 1546 inds_fac_activity = facilities.get_inds(self.ids_fac_activity.value[inds_pers]) 1547 1548 centroids_home = facilities.centroids.value[inds_fac_home] 1549 centroids_activity = facilities.centroids.value[inds_fac_activity] 1550 1551 ids_edge_home = facilities.ids_roadedge_closest.value[inds_fac_home] 1552 poss_edge_home = facilities.positions_roadedge_closest.value[inds_fac_home] 1553 1554 ids_edge_activity = facilities.ids_roadedge_closest.value[inds_fac_activity] 1555 poss_edge_activity = facilities.positions_roadedge_closest.value[inds_fac_activity] 1556 1557 # find closest prt stop!! 1558 ids_stop_home = ptstops.get_closest(centroids_home) 1559 ids_stop_activity = ptstops.get_closest(centroids_activity) 1560 1561 ids_stopedge_home = ids_laneedge[ids_stoplane[ids_stop_home]] 1562 ids_stopedge_activity = ids_laneedge[ids_stoplane[ids_stop_activity]] 1563 1564 poss_stop_home = 0.5*(ptstops.positions_from[ids_stop_home] 1565 + ptstops.positions_to[ids_stop_home]) 1566 poss_stop_activity = 0.5*(ptstops.positions_from[ids_stop_activity] 1567 + ptstops.positions_to[ids_stop_activity]) 1568 1569 i = 0 1570 for id_person, id_plan, time_start, id_edge_home, pos_edge_home, id_edge_activity, pos_edge_activity, id_stop_home, id_stopedge_home, pos_stop_home, id_stop_activity, id_stopedge_activity, pos_stop_activity\ 1571 in zip(ids_person, ids_plan, times_start, ids_edge_home, poss_edge_home, ids_edge_activity, poss_edge_activity, ids_stop_home, ids_stopedge_home, poss_stop_home, ids_stop_activity, ids_stopedge_activity, poss_stop_activity): 1572 self.plans.value.set_row(id_plan, ids_person=id_person) 1573 1574 print 79*'_' 1575 print ' id_plan=%d, id_person=%d, ' % (id_plan, id_person) 1576 1577 id_stage_walk1, time = walks.append_stage(id_plan, time_start, 1578 id_edge_from=id_edge_home, 1579 position_edge_from=pos_edge_home, 1580 id_edge_to=id_stopedge_home, 1581 position_edge_to=pos_stop_home, # -7.0, 1582 ) 1583 1584 # print ' id_stopedge_home',id_stopedge_home 1585 # print ' pos_stop_home',pos_stop_home 1586 1587 # print 1588 # print ' id_stopedge_activity',id_stopedge_activity 1589 # print ' pos_stop_activity',pos_stop_activity 1590 # print 1591 # print ' id_stop_home',id_stop_home 1592 # print ' id_stop_activity',id_stop_activity 1593 1594 durations, linktypes, ids_line, ids_fromstop, ids_tostop =\ 1595 ptlinks.route(id_stop_home, id_stop_activity, 1596 fstar=ptfstar, times=pttimes, 1597 stops_to_enter=stops_to_enter, 1598 stops_to_exit=stops_to_exit) 1599 1600 # print ' routing done. make plan..' 1601 1602 if len(linktypes) > 0: 1603 if linktypes[-1] == type_walk: # is last stage a walk? 1604 # remove it, because will go directly to destination 1605 linktypes = linktypes[:-1] 1606 ids_line = ids_line[:-1] 1607 durations = durations[:-1] 1608 ids_fromstop = ids_fromstop[:-1] 1609 ids_tostop = ids_tostop[:-1] 1610 1611 # print ' ids_line ',ids_line 1612 # print ' ids_fromstop',ids_fromstop 1613 # print ' ids_tostop ',ids_tostop 1614 1615 if len(linktypes) > 0: # is there any public transport line to take? 1616 1617 # go though PT links and generate transits and walks to trasfer 1618 ids_stopedge_from = ids_laneedge[ids_stoplane[ids_fromstop]] 1619 ids_stopedge_to = ids_laneedge[ids_stoplane[ids_tostop]] 1620 poss_stop_from = 0.5*(ptstops.positions_from[ids_fromstop] 1621 + ptstops.positions_to[ids_fromstop]) 1622 poss_stop_to = 0.5*(ptstops.positions_from[ids_tostop] 1623 + ptstops.positions_to[ids_tostop]) 1624 1625 # this is wait time buffer to be added to the successive stage 1626 # as waiting is currently not modelled as an extra stage 1627 duration_wait = 0.0 1628 1629 # create stages for PT 1630 for linktype, id_line, duration,\ 1631 id_stopedge_from, pos_fromstop,\ 1632 id_stopedge_to, pos_tostop in\ 1633 zip(linktypes, 1634 ids_line, 1635 durations, 1636 ids_stopedge_from, poss_stop_from, 1637 ids_stopedge_to, poss_stop_to, 1638 ): 1639 # print ' stage for linktype %2d fromedge %s toedge %s'%(linktype, edges.ids_sumo[id_stopedge_from],edges.ids_sumo[id_stopedge_to] ) 1640 1641 if linktype == type_transit: # transit! 1642 id_stage_transit, time = transits.append_stage( 1643 id_plan, time, 1644 id_line=id_line, 1645 duration=duration+duration_wait, 1646 id_fromedge=id_stopedge_from, 1647 id_toedge=id_stopedge_to, 1648 ) 1649 duration_wait = 0.0 1650 1651 elif linktype == type_walk: # walk to transfer 1652 1653 id_stage_transfer, time = walks.append_stage( 1654 id_plan, time, 1655 id_edge_from=id_stopedge_from, 1656 position_edge_from=pos_fromstop, 1657 id_edge_to=id_stopedge_to, 1658 position_edge_to=pos_tostop, 1659 duration=duration+duration_wait, 1660 ) 1661 duration_wait = 0.0 1662 1663 else: # all other link time are no modelld 1664 # do not do anything , just add wait time to next stage 1665 duration_wait += duration 1666 1667 # walk from final stop to activity 1668 # print ' Stage for linktype %2d fromedge %s toedge %s'%(linktype, edges.ids_sumo[id_stopedge_to],edges.ids_sumo[id_edge_activity] ) 1669 id_stage_walk2, time = walks.append_stage(id_plan, time, 1670 id_edge_from=id_stopedge_to, 1671 position_edge_from=pos_tostop, 1672 id_edge_to=id_edge_activity, 1673 position_edge_to=pos_edge_activity, 1674 ) 1675 1676 else: 1677 # there is no public transport line linking these nodes. 1678 # Modify walk directly from home to activity 1679 time = walks.modify_stage(id_stage_walk1, time_start, 1680 id_edge_from=id_edge_home, 1681 position_edge_from=pos_edge_home, 1682 id_edge_to=id_edge_activity, 1683 position_edge_to=pos_edge_activity, 1684 ) 1685 1686 # store time estimation for this plan 1687 times_est_plan[id_plan] = time-time_start 1688 1689 def make_times_stop_to_stop(self, fstar=None, times=None): 1690 # print 'make_times_stop_to_stop' 1691 if fstar is None: 1692 fstar = self.get_fstar() 1693 times = self.get_times(fstar) 1694 1695 if len(fstar) == 0: 1696 self.times_stop_to_stop = [[]] 1697 return 1698 1699 ids_prtstop = self.prtstops.get_ids() 1700 1701 ids_edge = self.prtstops.get_edges(ids_prtstop) 1702 # print ' ids_prtstop,ids_edge',ids_prtstop,ids_edge 1703 n_elem = np.max(ids_prtstop)+1 1704 stop_to_stop = np.zeros((n_elem, n_elem), dtype=np.int32) 1705 1706 ids_edge_to_ids_prtstop = np.zeros(np.max(ids_edge)+1, dtype=np.int32) 1707 ids_edge_to_ids_prtstop[ids_edge] = ids_prtstop 1708 1709 ids_edge_target = set(ids_edge) 1710 1711 for id_stop, id_edge in zip(ids_prtstop, ids_edge): 1712 # print ' id_stop, id_edge',id_stop, id_edge 1713 1714 # remove origin from target 1715 ids_edge_target.discard(id_edge) 1716 1717 costs, routes = edgedijkstra(id_edge, 1718 ids_edge_target=ids_edge_target, 1719 weights=times, fstar=fstar 1720 ) 1721 1722 # print ' ids_edge_target',ids_edge_target 1723 # print ' costs\n', costs 1724 # print ' routes\n', routes 1725 1726 # TODO: could be vectorialized, but not so easy 1727 for id_edge_target in ids_edge_target: 1728 #stop_to_stop[id_edge,id_edge_target] = costs[id_edge_target] 1729 # 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] 1730 # stop_to_stop[ids_edge_to_ids_prtstop[[id_edge,id_edge_target]]]=costs[id_edge_target] 1731 stop_to_stop[ids_edge_to_ids_prtstop[id_edge], 1732 ids_edge_to_ids_prtstop[id_edge_target]] = costs[id_edge_target] 1733 1734 # put back origin to targets (probably not the best way) 1735 ids_edge_target.add(id_edge) 1736 # print ' ids_edge_target (all)',ids_edge_target 1737 1738 # print ' stop_to_stop',stop_to_stop 1739 # TODO: here we could also store the routes 1740 1741 self.times_stop_to_stop = stop_to_stop 1742 self.ids_edge_to_ids_prtstop = ids_edge_to_ids_prtstop 1743 # print ' times_stop_to_stop=\n',self.times_stop_to_stop 1744 1745 def get_fstar(self): 1746 """ 1747 Returns the forward star graph of the network as dictionary: 1748 fstar[id_fromedge] = set([id_toedge1, id_toedge2,...]) 1749 """ 1750 # print 'get_fstar' 1751 net = self.get_scenario().net 1752 # prt mode 1753 id_mode = net.modes.get_id_mode('custom1') 1754 1755 #ids_edge = self.get_ids() 1756 #fstar = np.array(np.zeros(np.max(ids_edge)+1, np.obj)) 1757 fstar = {} 1758 connections = net.connections 1759 lanes = net.lanes 1760 inds_con = connections.get_inds() 1761 ids_fromlane = connections.ids_fromlane.get_value()[inds_con] 1762 ids_modes_allow = lanes.modes_allow[ids_fromlane] 1763 ids_fromedge = lanes.ids_edge[ids_fromlane] 1764 ids_toedge = lanes.ids_edge[connections.ids_tolane.get_value()[inds_con]] 1765 # print ' ids_fromedge',ids_fromedge 1766 # print ' ids_modes_allow',ids_modes_allow 1767 for id_fromedge, id_toedge, ids_mode_allow in\ 1768 zip(ids_fromedge, ids_toedge, ids_modes_allow): 1769 if len(ids_mode_allow) > 0: 1770 if ids_mode_allow[-1] == id_mode: 1771 if fstar.has_key(id_fromedge): 1772 fstar[id_fromedge].add(id_toedge) 1773 else: 1774 fstar[id_fromedge] = set([id_toedge]) 1775 1776 return fstar 1777 1778 def get_times(self, fstar): 1779 """ 1780 Returns freeflow travel times for all edges. 1781 The returned array represents the speed and the index corresponds to 1782 edge IDs. 1783 1784 """ 1785 if len(fstar) == 0: 1786 return [] 1787 1788 net = self.get_scenario().net 1789 #id_mode = net.modes.get_id_mode(mode) 1790 id_mode = net.modes.get_id_mode('custom1') 1791 # print 'get_times id_mode,is_check_lanes,speed_max',id_mode,is_check_lanes,speed_max 1792 ids_edge = np.array(fstar.keys(), dtype=np.int32) 1793 1794 times = np.array(np.zeros(np.max(ids_edge)+1, np.float32)) 1795 speeds = net.edges.speeds_max[ids_edge] 1796 1797 # limit allowed speeds with max speeds of mode 1798 speeds = np.clip(speeds, 0.0, net.modes.speeds_max[id_mode]) 1799 1800 times[ids_edge] = net.edges.lengths[ids_edge]/speeds 1801 1802 return times 1803 1804 def get_scenario(self): 1805 return self.parent.parent 1806 1807 def get_landuse(self): 1808 return self.get_scenario().landuse 1809 1810 def make_plans_prt(self, ids_person=None, mode='custom1'): 1811 # routing necessary? 1812 1813 scenario = self.get_scenario() 1814 edges = scenario.net.edges 1815 lanes = scenario.net.lanes 1816 modes = scenario.net.modes 1817 1818 landuse = scenario.landuse 1819 facilities = landuse.facilities 1820 1821 virtualpop = self.parent.virtualpop 1822 walks = virtualpop.get_walks() 1823 #transits = virtualpop.get_transits() 1824 1825 #ptstops = virtualpop.get_ptstops() 1826 #ptlines = virtualpop.get_ptlines() 1827 1828 #ptlinks = ptlines.ptlinks.get_value() 1829 #ptlinktypes = ptlinks.types.choices 1830 #type_enter = ptlinktypes['enter'] 1831 #type_transit = ptlinktypes['transit'] 1832 #type_board = ptlinktypes['board'] 1833 #type_alight = ptlinktypes['alight'] 1834 #type_transfer = ptlinktypes['transfer'] 1835 #type_walk = ptlinktypes['walk'] 1836 #type_exit = ptlinktypes['exit'] 1837 1838 #ptfstar = ptlinks.get_fstar() 1839 #pttimes = ptlinks.get_times() 1840 #stops_to_enter, stops_to_exit = ptlinks.get_stops_to_enter_exit() 1841 1842 #ids_prtstoplane = ptstops.ids_lane 1843 #ids_laneedge = scenario.net.lanes.ids_edge 1844 1845 if self.times_stop_to_stop is None: 1846 self.make_times_stop_to_stop() 1847 1848 times_est_plan = virtualpop.plans.get_value().times_est 1849 # here we can determine edge weights for different modes 1850 walks.prepare_planning() 1851 # transits.prepare_planning() 1852 1853 if ids_person is None: 1854 # print ' ids_mode_preferred',self.ids_mode_preferred.value 1855 # print ' private',MODES['private'] 1856 # print ' ',self.ids_mode_preferred == MODES['private'] 1857 1858 ids_person = virtualpop.select_ids( 1859 virtualpop.ids_mode_preferred.get_value() == modes.get_id_mode(mode), 1860 ) 1861 1862 ids_plan = virtualpop.add_plans(ids_person) 1863 1864 n_plans = len(ids_plan) 1865 1866 print 'make_plans_prt n_plans=', n_plans 1867 1868 #ids_veh = self.get_individualvehicles().assign_to_persons(ids_person) 1869 inds_pers = virtualpop.get_inds(ids_person) 1870 # self.persons.cols.mode_preferred[inds_pers]='private' 1871 1872 times_start = virtualpop.times_start.value[inds_pers] 1873 inds_fac_home = facilities.get_inds(virtualpop.ids_fac_home.value[inds_pers]) 1874 inds_fac_activity = facilities.get_inds(virtualpop.ids_fac_activity.value[inds_pers]) 1875 1876 centroids_home = facilities.centroids.value[inds_fac_home] 1877 centroids_activity = facilities.centroids.value[inds_fac_activity] 1878 1879 ids_edge_home = facilities.ids_roadedge_closest.value[inds_fac_home] 1880 poss_edge_home = facilities.positions_roadedge_closest.value[inds_fac_home] 1881 1882 ids_edge_activity = facilities.ids_roadedge_closest.value[inds_fac_activity] 1883 poss_edge_activity = facilities.positions_roadedge_closest.value[inds_fac_activity] 1884 1885 ids_stop_home, ids_stopedge_home = self.prtstops.get_closest(centroids_home) 1886 ids_stop_activity, ids_stopedge_activity = self.prtstops.get_closest(centroids_activity) 1887 1888 poss_stop_home = self.prtstops.get_waitpositions(ids_stop_home, is_alight=False, offset=-0.5) 1889 poss_stop_activity = self.prtstops.get_waitpositions(ids_stop_activity, is_alight=True, offset=-0.5) 1890 1891 #ids_stopedge_home = ids_laneedge[ids_stoplane[ids_stop_home]] 1892 #ids_stopedge_activity = ids_laneedge[ids_stoplane[ids_stop_activity]] 1893 1894 # poss_stop_home = 0.5*( ptstops.positions_from[ids_stop_home]\ 1895 # +ptstops.positions_to[ids_stop_home]) 1896 # poss_stop_activity = 0.5*( ptstops.positions_from[ids_stop_activity]\ 1897 # +ptstops.positions_to[ids_stop_activity]) 1898 1899 i = 0 1900 for id_person, id_plan, time_start, id_edge_home, pos_edge_home, id_edge_activity, pos_edge_activity, id_stop_home, id_stopedge_home, pos_stop_home, id_stop_activity, id_stopedge_activity, pos_stop_activity\ 1901 in zip(ids_person, ids_plan, times_start, ids_edge_home, poss_edge_home, ids_edge_activity, poss_edge_activity, ids_stop_home, ids_stopedge_home, poss_stop_home, ids_stop_activity, ids_stopedge_activity, poss_stop_activity): 1902 1903 # can be done before?? 1904 virtualpop.plans.value.set_row(id_plan, ids_person=id_person) 1905 #virtualpop.plans.value.ids_person[id_plan] = id_person 1906 print 79*'_' 1907 print ' id_plan=%d, id_person=%d, ' % (id_plan, id_person) 1908 1909 # are nearest stops different? 1910 if id_stop_home != id_stop_activity: 1911 # so walk to prt stop 1912 id_stage_walk1, time = walks.append_stage(id_plan, time_start, 1913 id_edge_from=id_edge_home, 1914 position_edge_from=pos_edge_home, 1915 id_edge_to=id_stopedge_home, 1916 position_edge_to=pos_stop_home, 1917 ) 1918 # take PRT 1919 # self.ids_edge_to_ids_prtstop 1920 id_stopedge_home, pos_stop_home 1921 id_stage_transit, time = self.prttransits.append_stage( 1922 id_plan, time, 1923 duration=self.times_stop_to_stop[id_stop_home, id_stop_activity], 1924 id_fromedge=id_stopedge_home, 1925 id_toedge=id_stopedge_activity, 1926 ) 1927 1928 # walk from PRT stop to activity 1929 id_stage_transfer, time = walks.append_stage( 1930 id_plan, time, 1931 id_edge_from=id_stopedge_activity, 1932 position_edge_from=pos_stop_activity, # should be -1 to indicate whatever position. Check in toxml 1933 id_edge_to=id_edge_activity, 1934 position_edge_to=pos_edge_activity, 1935 ) 1936 1937 else: 1938 # origin and destination stop are identical. 1939 # walk directly from home to activity 1940 time = walks.append_stage(id_plan, time_start, 1941 id_edge_from=id_edge_home, 1942 position_edge_from=pos_edge_home, 1943 id_edge_to=id_edge_activity, 1944 position_edge_to=pos_edge_activity, 1945 ) 1946 1947 # store time estimation for this plan 1948 times_est_plan[id_plan] = time-time_start 1949 1950 1951class SumoPrt(sumo.SumoTraci): 1952 """ 1953 SUMO simulation process with interactive control of PRT vehicles. 1954 """ 1955 1956 def _init_special(self, **kwargs): 1957 """ 1958 Special initializations. To be overridden. 1959 """ 1960 # prtservices = None 1961 self._prtservice = kwargs['prtservice'] 1962 1963 def run_cml(self, cml): 1964 cmllist = cml.split(' ') 1965 print 'PRT.run_cml', cmllist 1966 traci.start(cmllist) 1967 self.simtime = self.simtime_start 1968 self.duration = 1.0+self.simtime_end-self.simtime_start 1969 self.get_attrsman().status.set('running') 1970 print ' traci started', self.get_attrsman().status.get() 1971 1972 simobjects = self._prtservice.prepare_sim(self) 1973 self.simobjects = [] 1974 for time_sample, simfunc in simobjects: 1975 self.simobjects.append([0, time_sample, simfunc]) 1976 # print ' simobjects=',self.simobjects 1977 return True 1978 1979 def process_step(self): 1980 # print 'process_step time=',self.simtime 1981 # self._prtservice.process_step(self) 1982 1983 i = 0 1984 for time_last, time_sample, simfunc in self.simobjects: 1985 if self.simtime-time_last > time_sample: 1986 self.simobjects[i][0] += time_sample 1987 simfunc(self) 1988 i += 1 1989