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-25-oldmergenode.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 25from agilepy.lib_base.processes import Process 26#from xml.sax import saxutils, parse, handler 27 28 29from coremodules.modules_common import * 30import agilepy.lib_base.classman as cm 31import agilepy.lib_base.arrayman as am 32import agilepy.lib_base.xmlman as xm 33#from agilepy.lib_base.misc import get_inversemap 34#from agilepy.lib_base.geometry import find_area 35#from agilepy.lib_base.processes import Process,CmlMixin,ff,call 36from coremodules.network.network import SumoIdsConf 37from coremodules.network.routing import edgedijkstra, get_mincostroute_edge2edge 38from coremodules.simulation import sumo 39from coremodules.simulation.sumo import traci 40#from coremodules.network import routing 41from coremodules.demand.demandbase import DemandobjMixin 42from coremodules.simulation.simulationbase import SimobjMixin 43 44from coremodules.demand.virtualpop import StageTypeMixin, StrategyMixin 45from coremodules.simulation import results as res 46 47BERTHSTATES = {'free': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3} 48VEHICLESTATES = {'init': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3, 49 'emptytrip': 4, 'occupiedtrip': 5, 'forewarding': 6, 'await_forwarding': 7} 50LEADVEHICLESTATES = [VEHICLESTATES['boarding'], VEHICLESTATES['waiting'], 51 VEHICLESTATES['emptytrip'], VEHICLESTATES['occupiedtrip']] 52STOPTYPES = {'person': 0, 'freight': 1, 'depot': 2, 'group': 3, 'mixed': 4} 53# def detect_entered_left(x,y): 54# """ 55# returns the enter and left elemets of list x (before) 56# and list y (after) 57# """ 58# if len(x) == 0: 59# if len(y) == 0: 60# return 61 62 63class Mergenodes(am.ArrayObjman): 64 def __init__(self, ident, prtservices, **kwargs): 65 self._init_objman(ident=ident, 66 parent=prtservices, 67 name='Merge nodes', 68 info='Contains information and methods for merging the flow of two vehicle streams, including platoons.', 69 version=0.2, 70 **kwargs) 71 self._init_attributes() 72 73 def _init_attributes(self): 74 #self.add(cm.ObjConf(PrtBerths('berths',self)) ) 75 76 self.add(cm.AttrConf('time_update', 0.5, 77 groupnames=['parameters'], 78 name='Update time', 79 info="Update time for merges.", 80 unit='s', 81 )) 82 83 net = self.get_scenario().net 84 85 self.add_col(am.IdsArrayConf('ids_node', net.nodes, 86 name='Node ID', 87 info='Network node ID.', 88 is_index=True, 89 )) 90 91 # self.add_col(am.IdsArrayConf('ids_edge_in1', net.edges, 92 # name = 'ID edge 1', 93 # info = 'ID of edge at entrance 1.', 94 # )) 95 if self.get_version() < 0.2: 96 self.delete('ids_mergenode_in1') 97 self.delete('ids_mergenode_in2') 98 self.delete('ids_mergenodes_out') 99 self.add_col(am.IdsArrayConf('ids_mergenode_in1', self, 100 name='ID mergenode in 1', 101 info='ID of upstream mergenode at incoming line 1.', 102 )) 103 104 self.add_col(am.ArrayConf('distances_mergenode_in1', 0.0, 105 groupnames=['parameters'], 106 name='Distance mergenode in 1', 107 info="Distance to mergenode at incoming line 1.", 108 unit='m', 109 )) 110 111 # self.add_col(am.IdsArrayConf('ids_edge2', net.edges, 112 # name = 'ID edge 2', 113 # info = 'ID of edge at entrance 2.', 114 # )) 115 116 self.add_col(am.IdsArrayConf('ids_mergenode_in2', self, 117 name='ID mergenode in 2', 118 info='ID of upstream mergenode at incoming line 2.', 119 )) 120 self.add_col(am.ArrayConf('distances_mergenode_in2', 0.0, 121 groupnames=['parameters'], 122 name='Distance mergenode in 2', 123 info="Distance to mergenode at incoming line 2.", 124 unit='m', 125 )) 126 127 self.add_col(am.IdlistsArrayConf('ids_mergenodes_out', net.nodes, 128 name='IDs mergenode out', 129 info='IDs of downstream mergenodes.', 130 )) 131 132 self.add_col(am.ArrayConf('are_station', default=False, 133 groupnames=['parameters'], 134 name='is station', 135 info="Node is the exit node of a station the incoming edge of this node is a platform edge.", 136 )) 137 138 self.set_verion(0.2) 139 140 def make_from_net(self): 141 """ 142 Make merge node database from network. 143 """ 144 print 'Mergenodes.make_from_net' 145 self.clear() 146 id_prtmode = self.parent.id_prtmode 147 148 net = self.get_scenario().net 149 nodes = net.nodes 150 edges = net.edges 151 lanes = net.lanes 152 id_zippertype = nodes.types.choices['zipper'] 153 #ids_ptstop = ptstops.get_ids() 154 #id_mode_prt = self.parent.id_prtmode 155 156 #ids_edges = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]] 157 #ids_lanes = net.edges.ids_lanes[ids_edges] 158 #ids_lane = ptstops.ids_lane[ids_ptstop] 159 #edgelengths = net.edges.lengths 160 161 ids_node = nodes.get_ids() 162 for id_node, ids_edge_from, ids_edge_to, id_type in zip( 163 ids_node, 164 nodes.ids_incoming[ids_node], 165 nodes.ids_outgoing[ids_node], 166 nodes.types[ids_node], 167 ): 168 169 if id_type == id_zippertype: 170 # it is a zipper tpe node 171 172 # print 60*'-' 173 # print ' check node',id_node,id_type 174 175 if (len(ids_edge_from) == 2) & (len(ids_edge_to) == 1): 176 177 # check accesslevels 178 id_edge1, id_edge2 = ids_edge_from 179 ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_from] 180 al1 = lanes.get_accesslevel(ids_lane1, id_prtmode) 181 al2 = lanes.get_accesslevel(ids_lane2, id_prtmode) 182 # print ' 2 in, one out => merge node, access: al1,al2',al1,al2 183 if (al1 == 2) & (al2 == 2): 184 # print ' +PRT merge with 2 PRT lines entering' 185 186 id_node_up1, dist1 = self.search_upstream_merge(id_edge1, edges, lanes, id_prtmode) 187 id_node_up2, dist2 = self.search_upstream_merge(id_edge2, edges, lanes, id_prtmode) 188 189 ids_mergenode_out = self.search_downstream_merges(ids_edge_to[0], edges, lanes, id_prtmode) 190 self.add_row(ids_node=id_node, 191 ids_mergenode_in1=id_node_up1, 192 distances_mergenode_in1=dist1, 193 ids_mergenode_in2=id_node_up2, 194 distances_mergenode_in2=dist2, 195 ids_mergenodes_out=ids_mergenode_out, 196 are_station=False, 197 ) 198 199 elif (len(ids_edge_from) == 1) & (len(ids_edge_to) == 2): 200 201 id_edge_from = ids_edge_from[0] 202 al_in = lanes.get_accesslevel(edges.ids_lanes[id_edge_from], id_prtmode) 203 # print ' one in, 2 out => diverge node, access al_in',al_in 204 # check if node is outgoing node at a station 205 if al_in == 1: 206 # mixed access level of incoming edge=> platform 207 id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode) 208 209 id_edge1, id_edge2 = ids_edge_to 210 ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_to] 211 212 al1 = lanes.get_accesslevel(ids_lane1, id_prtmode) 213 al2 = lanes.get_accesslevel(ids_lane2, id_prtmode) 214 # here we could also decide on the number of lanes 215 # but this may not be robust in the future 216 217 if (al1 == 1) & (al2 == 2): 218 # print ' +share access level on outedge 1' 219 ids_mergenode_out = self.search_downstream_merges(id_edge2, edges, lanes, id_prtmode) 220 self.add_row(ids_node=id_node, 221 ids_mergenode_in1=id_node_up, 222 distances_mergenode_in1=dist, 223 ids_mergenodes_out=ids_mergenode_out, 224 are_station=True, 225 ) 226 227 elif (al1 == 2) & (al2 == 1): 228 # print ' +share access level on outedge 2' 229 ids_mergenode_out = self.search_downstream_merges(id_edge1, edges, lanes, id_prtmode) 230 self.add_row(ids_node=id_node, 231 ids_mergenode_in1=id_node_up, 232 distances_mergenode_in1=dist, 233 ids_mergenodes_out=ids_mergenode_out, 234 are_station=True, 235 ) 236 237 def get_scenario(self): 238 return self.parent.get_scenario() 239 240 def prepare_sim(self, process): 241 print 'Mergenodes.prepare_sim' 242 net = self.get_scenario().net 243 nodes = net.nodes 244 edges = net.edges 245 lanes = net.lanes 246 ids_edge_sumo = edges.ids_sumo 247 248 id_prtmode = self.parent.id_prtmode 249 ids = self.get_ids() 250 n_id_max = np.max(ids)+1 251 #self.ids_merge_to_ids_node_sumo = np.zeros(n_id_max,dtype = np.object) 252 #self.ids_merge_to_ids_node_sumo[ids] = nodes.ids_sumo[self.ids_node[ids]] 253 254 self.ids_merge_to_ids_edge_out_sumo = np.zeros(n_id_max, dtype=np.object) 255 #self.ids_node_to_ids_edge_out_sumo = np.zeros(n_id_max,dtype = np.object) 256 self.ids_node_to_ids_merge = np.zeros(np.max(self.ids_node[ids])+1, dtype=np.int32) 257 self.ids_node_to_ids_merge[self.ids_node[ids]] = ids 258 259 # this queue contains all vehicles on the outgoing edge 260 # it is used to identify whether a new vehicle has left the merge 261 self.ids_vehs_out_sumo = np.zeros(n_id_max, dtype=np.object) 262 263 # this queue contains all vehicles on line 1 between 264 # merge and id_node_in1 265 self.ids_vehs_in1 = np.zeros(n_id_max, dtype=np.object) 266 self.ids_vehs_in1_sumo = np.zeros(n_id_max, dtype=np.object) 267 268 # this queue contains all vehicles on line 2 between 269 # merge and id_node_in2 270 self.ids_vehs_in2 = np.zeros(n_id_max, dtype=np.object) 271 self.ids_vehs_in2_sumo = np.zeros(n_id_max, dtype=np.object) 272 273 # this queue contains the merged vehicles for the controlled range 274 self.ids_vehs_merged = np.zeros(n_id_max, dtype=np.object) 275 self.ids_vehs_merged_sumo = np.zeros(n_id_max, dtype=np.object) 276 277 # this queuse contains the line index (1 or 2, 0= not assigned) 278 self.lineinds_vehs_merged = np.zeros(n_id_max, dtype=np.object) 279 280 #self.ids_merge_to_ids_edge_out_sumo[ids] = edges.ids_sumo[self.ids_node[ids]] 281 ids_node = self.ids_node[ids] 282 for id_merge, id_node, ids_edge_out in zip(ids, ids_node, nodes.ids_outgoing[ids_node]): 283 if len(ids_edge_out) == 1: 284 # regular merge 285 self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[ids_edge_out[0]] 286 287 elif len(ids_edge_out) == 2: 288 # one edge is PRT, the other ped access 289 # check accesslevels 290 id_edge1, id_edge2 = ids_edge_out 291 ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_out] 292 al1 = lanes.get_accesslevel(ids_lane1, id_prtmode) 293 al2 = lanes.get_accesslevel(ids_lane2, id_prtmode) 294 if al1 == 2: 295 self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge1] 296 #self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge1] 297 if al2 == 2: 298 self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge2] 299 #self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge2] 300 301 self.ids_vehs_out_sumo[id_merge] = set() 302 303 self.ids_vehs_in1[id_merge] = list() 304 self.ids_vehs_in1_sumo[id_merge] = list() 305 self.ids_vehs_in2[id_merge] = list() 306 self.ids_vehs_in2_sumo[id_merge] = list() 307 308 self.ids_vehs_merged[id_merge] = list() 309 self.ids_vehs_merged_sumo[id_merge] = list() 310 self.lineinds_vehs_merged[id_merge] = list() 311 312 return [(self.time_update.get_value(), self.process_step), 313 ] 314 315 def process_step(self, process): 316 simtime = process.simtime 317 print 79*'_' 318 print 'Mergenodes.process_step at', simtime 319 net = self.get_scenario().net 320 vehicles = self.parent.prtvehicles 321 ids = self.get_ids() 322 for id_merge, id_node, id_edge_out, ids_mergenode_out, ids_veh_out_sumo in\ 323 zip(ids, 324 self.ids_node[ids], 325 self.ids_merge_to_ids_edge_out_sumo[ids], 326 self.ids_mergenodes_out[ids], 327 self.ids_vehs_out_sumo[ids], 328 ): 329 print ' '+60*'.' 330 print ' process id_merge,id_node', id_merge, id_node, net.nodes.ids_sumo[id_node] 331 if 0: 332 # print ' ids_veh_out_sumo',ids_veh_out_sumo 333 print ' ids_mergenode_out', ids_mergenode_out 334 335 # check for new vehicle arrivals/departures 336 ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_out)) 337 # print ' ids_veh_sumo_prev=',ids_veh_sumo_prev 338 # print ' ids_veh_sumo=',ids_veh_sumo 339 340 if ids_veh_out_sumo != ids_veh_sumo: 341 ids_veh_entered_sumo = list(ids_veh_sumo.difference(ids_veh_out_sumo)) 342 ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo) 343 #ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo))) 344 # print ' ids_veh_entered',ids_veh_entered 345 346 ids_merge_out = self.ids_node_to_ids_merge[ids_mergenode_out] 347 # print ' ids_mergenode_out',ids_mergenode_out 348 # print ' ids_merge_out',ids_merge_out 349 ids_edge_mergeout_sumo = self.ids_merge_to_ids_edge_out_sumo[ids_merge_out] 350 351 for id_veh, id_veh_sumo in zip(ids_veh_entered, ids_veh_entered_sumo): 352 # print ' >>entered vehicle',id_veh,id_veh_sumo 353 route_sumo = traci.vehicle.getRoute(id_veh_sumo) 354 # check which out mergenode are on the current route 355 # of the vehicle and inform the respectine merges 356 # then communicate vehicle with dist to merge 357 for id_merge_out, id_edge_sumo in zip(ids_merge_out, ids_edge_mergeout_sumo): 358 if id_edge_sumo in route_sumo: 359 print ' enter veh %d from merge %d to merge %d on edge %s' % ( 360 id_veh, id_merge, id_merge_out, id_edge_sumo) 361 self.enter_veh(id_veh, id_veh_sumo, id_merge, id_merge_out) 362 # measure dist to merge with traci call or precalc 363 break 364 365 self.ids_vehs_out_sumo[id_merge] = ids_veh_sumo 366 367 def enter_veh(self, id_veh, id_veh_sumo, id_merge_from, id_merge_to): 368 print 'enter_veh id_veh %d, id_merge_from %d to id_merge_to %d' % (id_veh, id_merge_from, id_merge_to) 369 370 # in id_merge_from: take vehicle out of merged queue and input queue 371 372 if id_veh in self.ids_vehs_merged[id_merge_from]: 373 # enterd veh should be in pole position in merge queue of merge_from 374 375 # pop if vehicles are properly merged 376 # id_veh_from = self.ids_vehs_merged[id_merge_from].pop() 377 # self.ids_vehs_merged_sumo.ids_vehs_merged[id_merge_from].pop() 378 # if id_veh_from != id_veh: 379 # print 'WARNING in enter_veh: veh %d instead of veh %d in polepos of merge %d'%(id_veh_from,id_veh, id_merge_from) 380 # return False 381 # lineind = self.lineinds_vehs_merged[id_merge_from].pop() 382 # for testing: just remove, no matter where 383 ind_pos = self.ids_vehs_merged[id_merge_from].index(id_veh) 384 lineind = self.lineinds_vehs_merged[id_merge_from][ind_pos] 385 386 self.ids_vehs_merged[id_merge_from].pop(ind_pos) # remove(id_veh) 387 self.ids_vehs_merged_sumo[id_merge_from].pop(ind_pos) # remove(id_veh_sumo) 388 self.lineinds_vehs_merged[id_merge_from].pop(ind_pos) 389 390 if lineind == 1: 391 self.ids_vehs_in1[id_merge_from].pop() 392 self.ids_vehs_in1_sumo[id_merge_from].pop() 393 if lineind == 2: 394 self.ids_vehs_in2[id_merge_from].pop() 395 self.ids_vehs_in2_sumo[id_merge_from].pop() 396 else: 397 pass 398 else: 399 # the entered vehicle is not in a merge queue 400 # probably a new vehicle at station 401 402 # just be sure that the vehicle is not in any queue 403 # but actually this cannot happen 404 if id_veh in self.ids_vehs_in1[id_merge_from]: 405 print 'WARNING in enter_veh: new veh %d should not be in inqueue 1' % id_veh 406 self.ids_vehs_in1[id_merge_from].remove(id_veh) 407 self.ids_vehs_in1_sumo[id_merge_from].remove(id_veh_sumo) 408 409 if id_veh in self.ids_vehs_in2[id_merge_from]: 410 print 'WARNING in enter_veh: new veh %d should not be in inqueue 1' % id_veh 411 self.ids_vehs_in2[id_merge_from].remove(id_veh) 412 self.ids_vehs_in2_sumo[id_merge_from].remove(id_veh_sumo) 413 414 # on which input line of merge id_merge_to does the vehicle approach? 415 if id_veh in self.ids_vehs_merged[id_merge_to]: 416 indpos = self.ids_vehs_merged[id_merge_to].index(id_veh) 417 lineind = self.lineinds_vehs_merged[id_merge_to][indpos] 418 419 elif self.ids_node_to_ids_merge[self.ids_mergenode_in1[id_merge_to]] == id_merge_from: 420 indpos = -1 421 lineind = 1 422 else: 423 indpos = -1 424 lineind = 2 425 426 if lineind == 1: 427 # from line 1 428 self.ids_vehs_in1[id_merge_to].append(id_veh) 429 self.ids_vehs_in1_sumo[id_merge_to].append(id_veh_sumo) 430 dist_mergenode = self.distances_mergenode_in1[id_merge_to] # correct with pos 431 432 elif lineind == 2: 433 self.ids_vehs_in2[id_merge_to].append(id_veh) 434 self.ids_vehs_in2_sumo[id_merge_to].append(id_veh_sumo) 435 dist_mergenode = self.distances_mergenode_in2[id_merge_to] # correct with pos 436 437 if indpos == -1: 438 # vehicle is new and must be merged into ids_vehs_merged 439 # print ' merge veh %d arriving from in $d at dist %.2fm'%(id_veh,lineind,dist_mergenode) 440 print ' merge veh %d arriving from in %d at dist %.2fm' % (id_veh, lineind, dist_mergenode) 441 ids_vehs_merged = self.ids_vehs_merged[id_merge_to] 442 ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge_to] 443 lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge_to] 444 id_edge_merge_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_to] 445 ind_pos_check = 0 446 is_insert_in_front = False 447 id_veh_merged = -1 448 449 print ' ids_vehs_merged_sumo', ids_vehs_merged_sumo 450 print ' lineinds_vehs_merged', lineinds_vehs_merged 451 452 for id_veh_merged, id_veh_merged_sumo in zip(ids_vehs_merged, ids_vehs_merged_sumo): 453 dist = traci.vehicle.getDrivingDistance(id_veh_merged_sumo, id_edge_merge_sumo, 0.0) 454 print ' check veh %d, dist %.2fm, dist_mergenode %.2fm, ind_pos_check = %d' % ( 455 id_veh_merged, dist, dist_mergenode, ind_pos_check) 456 if dist > dist_mergenode: 457 # distance to merge of this vehicle in queue is greater 458 # than the new vehicle 459 # inseri on copies? No break 460 461 # isert in fron of currently checked vehicle 462 is_insert_in_front = True 463 break 464 465 ind_pos_check += 1 466 467 #ind_pos_check =-1 468 if is_insert_in_front: 469 ind_insert = ind_pos_check - 1 470 print ' insert veh %d behind veh %d, index %d' % (id_veh, id_veh_merged, ind_insert) 471 else: 472 ind_insert = ind_pos_check-1 473 print ' append veh %d behind veh %d, last index %d' % (id_veh, id_veh_merged, ind_insert) 474 475 ids_vehs_merged.insert(ind_insert, id_veh) 476 ids_vehs_merged_sumo.insert(ind_insert, id_veh_sumo) 477 lineinds_vehs_merged.insert(ind_insert, lineind) 478 479 # send control info to involved vehicles 480 # inform downstream merges 481 482 def search_upstream_merge(self, id_edge_start, edges, lanes, id_prtmode): 483 """ 484 Searches next upstream merge node. 485 Returns id_node, id_mergeedge, id_platformedge 486 487 id_platformedge is positive if node is exit node 488 of a station platform. 489 """ 490 # print 'search_upstream_merge',id_edge_start 491 length = edges.lengths[id_edge_start] 492 is_merge = False 493 id_edge_platform = -1 494 id_edge = id_edge_start 495 while (not is_merge): 496 ids_edge_incoming = edges.get_incoming(id_edge) 497 # print ' search id_edge,ids_edge_incoming',id_edge,ids_edge_incoming 498 if len(ids_edge_incoming) == 2: 499 #id_edge1, id_edge2 = ids_edge_to 500 ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_incoming] 501 al1 = lanes.get_accesslevel(ids_lane1, id_prtmode) 502 al2 = lanes.get_accesslevel(ids_lane2, id_prtmode) 503 if (al1 > 0) & (al2 > 0): 504 # print ' 2 in, one out => it is a merge node' 505 is_merge = True 506 507 if len(ids_edge_incoming) == 1: 508 ids_lane = edges.ids_lanes[ids_edge_incoming[0]] 509 al = lanes.get_accesslevel(ids_lane, id_prtmode) 510 if (al == 1): 511 # print ' 2 in, one out => it is a merge node' 512 is_merge = True 513 514 if not is_merge: 515 id_edge = ids_edge_incoming[0] 516 length += edges.lengths[id_edge] 517 518 # print ' id_edge,is_merge',id_edge,is_merge 519 # print ' found node',edges.ids_fromnode[id_edge] 520 return edges.ids_fromnode[id_edge], length 521 522 def search_downstream_merges(self, id_edge_start, edges, lanes, id_prtmode): 523 """ 524 Searches next downstream merge nodes. 525 Returns array of downstream merge node IDs 526 527 """ 528 529 ids_edge = set([id_edge_start]) 530 ids_mergenode = set() 531 # print 'search_downstream_merges',id_edge_start 532 533 is_cont = True 534 #n_cont = 20 535 while (len(ids_edge) > 0) & is_cont: 536 # print ' len(ids_edge)',len(ids_edge),ids_edge 537 ids_edge_new = set() 538 539 for id_edge in ids_edge: 540 ids_edge_outgoing = edges.get_outgoing(id_edge) 541 # print ' id_edge,ids_edge_outgoing',id_edge,ids_edge_outgoing 542 for id_downedge in ids_edge_outgoing: 543 ids_lane = edges.ids_lanes[id_downedge] 544 if lanes.get_accesslevel(ids_lane, id_prtmode) == 2: 545 ids_downedge_incoming = edges.get_incoming(id_downedge) 546 # print ' id_downedge,ids_downedge_incoming',id_downedge,ids_downedge_incoming 547 is_merge = False 548 549 if len(ids_downedge_incoming) == 2: 550 ids_lane1, ids_lane2 = edges.ids_lanes[ids_downedge_incoming] 551 al1 = lanes.get_accesslevel(ids_lane1, id_prtmode) 552 al2 = lanes.get_accesslevel(ids_lane2, id_prtmode) 553 # print ' check al1,al2',al1,al2,(al1 == 2) & (al2 == 2) 554 if (al1 == 2) & (al2 == 2): # real merges 555 # print ' add mergenode',edges.ids_fromnode[id_downedge] 556 ids_mergenode.add(edges.ids_fromnode[id_downedge]) 557 is_merge = True 558 559 if not is_merge: # len(ids_downedge_incoming) == 1: 560 #ids_lane = edges.ids_lanes[ids_downedge_incoming] 561 # if lanes.get_accesslevel(ids_lane1, id_prtmode) == 2: 562 ids_edge_new.add(id_downedge) 563 564 # else: 565 # print 'WARNING in search_downstream_merges: edge %d has %d incoming edges.'%(id_downedge, len(ids_downedge_incoming)) 566 567 ids_edge = ids_edge_new.copy() 568 # print ' ids_edge_new',ids_edge_new,ids_edge,len(ids_edge) 569 # is_cont = n_cont>0 #id_edge_start not in ids_edge 570 #n_cont -= 1 571 572 # if not is_cont: 573 # print ' endless!!id_edge_start,ids_edge',id_edge_start,ids_edge 574 # print ' ids_mergenode',ids_mergenode 575 return np.array(list(ids_mergenode), dtype=np.int32) 576 577 578class PrtBerths(am.ArrayObjman): 579 580 def __init__(self, ident, prtstops, **kwargs): 581 # print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1') 582 self._init_objman(ident=ident, 583 parent=prtstops, 584 name='PRT Berths', 585 info='PRT Berths.', 586 **kwargs) 587 588 self._init_attributes() 589 590 def _init_attributes(self): 591 #vtypes = self.get_scenario().demand.vtypes 592 net = self.get_scenario().net 593 self.add(cm.AttrConf('length_default', 4.0, 594 groupnames=['parameters', 'options'], 595 name='Default length', 596 info='Default berth length.', 597 unit='m', 598 )) 599 600 self.add_col(am.IdsArrayConf('ids_prtstop', self.parent, 601 name='PRT stop ID', 602 info='PRT stop ID', 603 )) 604 605 # states now dynamic, see prepare_sim 606 # if hasattr(self,'states'): 607 # self.delete('states') 608 # self.add_col(am.ArrayConf( 'states', default = BERTHSTATES['free'], 609 # dtype = np.int32, 610 # choices = BERTHSTATES, 611 # name = 'state', 612 # info = 'State of berth.', 613 # )) 614 615 self.add_col(am.ArrayConf('stoppositions', default=0.0, 616 dtype=np.float32, 617 name='Stop position', 618 info='Position on edge where vehicle nose stops.', 619 )) 620 621 def prepare_sim(self, process): 622 # print 'PrtBerths.prepare_sim' 623 ids = self.get_ids() 624 self.states = BERTHSTATES['free']*np.ones(np.max(ids)+1, dtype=np.int32) 625 self.ids_veh = -1*np.ones(np.max(ids)+1, dtype=np.int32) 626 return [] # berth has no update function 627 628 def get_scenario(self): 629 return self.parent.get_scenario() 630 631 def get_prtvehicles(self): 632 return self.parent.parent.prtvehicles 633 634 def make(self, id_stop, position_from=None, position_to=None, 635 n_berth=None, 636 offset_firstberth=0.0, offset_stoppos=-0.0): 637 stoplength = position_to-position_from 638 # print 'Berths.make',id_stop,stoplength 639 640 # TODO: let define berth number either explicitely or through stoplength 641 642 length_berth = self.length_default.get_value() 643 positions = position_from + offset_firstberth\ 644 + np.arange(length_berth-offset_firstberth, stoplength+length_berth, length_berth) + offset_stoppos 645 n_berth = len(positions) 646 647 # force number of berth to be pair 648 if n_berth % 2 == 1: 649 positions = positions[1:] 650 n_berth -= 1 651 652 ids_berth = self.add_rows(n=n_berth, 653 stoppositions=positions, 654 ids_prtstop=id_stop * np.ones(n_berth, dtype=np.int32), 655 ) 656 return ids_berth 657 658 def set_prtvehicles(self, prtvehicles): 659 """ 660 Defines attributes which are linked with prtvehicles 661 """ 662 self.add_col(am.IdsArrayConf('ids_veh_allocated', prtvehicles, 663 name='Alloc. veh ID', 664 info='ID of vehicle which have allocated this berth. -1 means no allocation.', 665 )) 666 667 668class PrtStops(am.ArrayObjman): 669 def __init__(self, ident, prtservices, **kwargs): 670 self._init_objman(ident=ident, 671 parent=prtservices, 672 name='PRT stops', 673 info='Contains information on PRT stops.', 674 #xmltag = ('additional','busStop','stopnames'), 675 version=0.1, 676 **kwargs) 677 self._init_attributes() 678 679 def _init_attributes(self): 680 self.add(cm.ObjConf(PrtBerths('berths', self))) 681 682 berths = self.get_berths() 683 net = self.get_scenario().net 684 685 self.add(cm.AttrConf('time_update', 0.5, 686 groupnames=['parameters'], 687 name='Update time', 688 info="Update time for station.", 689 unit='s', 690 )) 691 692 self.add(cm.AttrConf('time_kickout', 30.0, 693 groupnames=['parameters'], 694 name='Kickout time', 695 info="Time to kick out empty vehicles after vehicles behing have been occupied with passengers.", 696 unit='s', 697 )) 698 self.add(cm.AttrConf('timeconst_flow', 0.98, 699 groupnames=['parameters'], 700 name='Flow time const', 701 info="Constant to update the moving average flow.", 702 )) 703 704 self.add(cm.AttrConf('stoplinegap', 12.0, 705 groupnames=['parameters'], 706 name='Stopline gap', 707 unit='m', 708 info="Distance between stopline, where vehicles get started, and the end of the lane.", 709 )) 710 711 if hasattr(self, 'time_update_man'): 712 self.delete('time_update_man') 713 self.delete('timehorizon') 714 715 self.add_col(am.IdsArrayConf('ids_ptstop', net.ptstops, 716 name='ID PT stop', 717 info='ID of public transport stop. ', 718 )) 719 720 if hasattr(self, 'are_depot'): 721 self.delete('are_depot') 722 723 self.add_col(am.ArrayConf('types', default=STOPTYPES['person'], 724 dtype=np.int32, 725 perm='rw', 726 choices=STOPTYPES, 727 name='Type', 728 info='Type of stop.', 729 )) 730 731 self.add_col(am.IdlistsArrayConf('ids_berth_alight', berths, 732 #groupnames = ['_private'], 733 name='Alight berth IDs', 734 info="Alight berth IDs.", 735 )) 736 737 self.add_col(am.IdlistsArrayConf('ids_berth_board', berths, 738 #groupnames = ['_private'], 739 name='Board berth IDs', 740 info="Board berth IDs.", 741 )) 742 743 # self.add_col(am.ArrayConf( 'inds_berth_alight_allocated', default = 0, 744 # #groupnames = ['_private'], 745 # dtype = np.int32, 746 # perm = 'rw', 747 # name = 'Ind aberth lastalloc', 748 # info = 'Berth index of last allocated berth in alight zone.', 749 # )) 750 751 # self.add_col(am.ArrayConf( 'inds_berth_board_allocated', default = 0, 752 # #groupnames = ['_private'], 753 # dtype = np.int32, 754 # perm = 'rw', 755 # name = 'Ind bberth lastalloc', 756 # info = 'Berth index of last allocated berth in boarding zone.', 757 # )) 758 759 def get_edges(self, ids_prtstop): 760 net = self.get_scenario().net 761 return net.lanes.ids_edge[net.ptstops.ids_lane[self.ids_ptstop[ids_prtstop]]] 762 763 def get_berths(self): 764 return self.berths.get_value() 765 766 def get_scenario(self): 767 return self.parent.get_scenario() 768 769 def set_prtvehicles(self, prtvehicles): 770 self.get_berths().set_prtvehicles(prtvehicles) 771 772 def set_vehicleman(self, vehicleman): 773 self.add(cm.ObjConf(vehicleman, is_child=False, groups=['_private'])) 774 775 def get_vehicleman(self): 776 return self.vehicleman.get_value() 777 778 def get_closest(self, coords): 779 """ 780 Returns the closest prt stop for each coord in coords vector. 781 """ 782 net = self.get_scenario().net 783 ptstops = net.ptstops 784 lanes = net.lanes 785 n = len(coords) 786 # print 'get_closest',n 787 788 #ids_stop = self.get_ids() 789 790 ids_prtstop = self.get_ids() 791 ids_ptstop = self.ids_ptstop[ids_prtstop] 792 coords_stop = ptstops.centroids[ids_ptstop] 793 ids_edge_stop = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]] 794 795 inds_closest = np.zeros(n, dtype=np.int32) 796 797 i = 0 798 for coord in coords: 799 ind_closest = np.argmin(np.sum((coord-coords_stop)**2, 1)) 800 inds_closest[i] = ind_closest 801 i += 1 802 803 ids_prtstop_closest = ids_prtstop[inds_closest] 804 ids_edge_closest = ids_edge_stop[inds_closest] 805 806 return ids_prtstop_closest, ids_edge_closest 807 808 def get_waitpositions(self, ids, is_alight=False, offset=-0.0): 809 """ 810 Assign randomly a wait-position for each stop in ids 811 812 offset is wait position relative to the vehicle nose. 813 """ 814 # print 'get_waitpositions min(ids),max(ids)',min(ids),is_alight,max(ids),offset 815 positions = np.zeros(len(ids), dtype=np.float32) 816 randint = random.randint 817 if is_alight: 818 ids_berths = self.ids_berth_alight[ids] 819 else: 820 ids_berths = self.ids_berth_board[ids] 821 822 stoppositions = self.get_berths().stoppositions 823 # print ' ids_berths',ids_berths 824 i = 0 825 for id_stop, ids_berth in zip(ids, ids_berths): 826 #ids_berth = ids_berths[id_stop] 827 ind_berth = randint(0, len(ids_berth)-1) 828 829 positions[i] = stoppositions[ids_berth[ind_berth]] 830 # print ' id_stop,ids_berth,posiions',id_stop,ids_berth,stoppositions[ids_berth[ind_berth]] 831 i += 1 832 #positions[i] = stoppositions[ids_berth[randint(0,len(ids_berth))]] 833 # for id_stop , pos in zip(ids, positions): 834 # print ' id_stop %d, is_alight = %s, pos %.2fm'%(id_stop, is_alight ,pos) 835 836 return positions+offset 837 838 def prepare_sim(self, process): 839 print 'PrtStops.prepare_sim' 840 net = self.get_scenario().net 841 ptstops = net.ptstops 842 ids_edge_sumo = net.edges.ids_sumo 843 844 berths = self.get_berths() 845 lanes = net.lanes 846 ids_edge_sumo = net.edges.ids_sumo 847 ids = self.get_ids() 848 get_outgoing = net.edges.get_outgoing 849 850 # station management 851 self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1, dtype=np.object) 852 self.ids_stop_to_ids_edge = np.zeros(np.max(ids)+1, dtype=np.int32) 853 854 ids_stopedge = lanes.ids_edge[ptstops.ids_lane[self.ids_ptstop[ids]]] 855 # print ' ids,self.stoplines[ids]',ids,self.stoplines[ids] 856 self.ids_stop_to_ids_edge_sumo[ids] = ids_edge_sumo[ids_stopedge] 857 self.ids_stop_to_ids_edge[ids] = ids_stopedge 858 859 # Determine stopline position where vehicles actually start 860 # running off the station 861 862 # final stop at one meter before end of stopedge 863 self.stoplines = np.zeros(np.max(ids)+1, dtype=np.float32) 864 stoplinegap = self.stoplinegap.get_value() 865 #self.stoplines[ids] = net.edges.lengths[ids_stopedge]-12.0 866 #stoplengths = net.edges.lengths[ids_stopedge] 867 for id_stop, ids_berth_board, length_stopedge in zip(ids, self.ids_berth_board[ids], net.edges.lengths[ids_stopedge]): 868 lastberthstoppos = berths.stoppositions[ids_berth_board][-1] 869 if (length_stopedge-lastberthstoppos) > stoplinegap+1: 870 self.stoplines[id_stop] = length_stopedge-stoplinegap 871 elif length_stopedge > lastberthstoppos: 872 self.stoplines[id_stop] = 0.5*(length_stopedge+lastberthstoppos) 873 874 self.ids_stop_to_ids_acceledge_sumo = np.zeros(np.max(ids)+1, dtype=np.object) 875 for id_stop, id_stopedge in zip(ids, ids_stopedge): 876 self.ids_stop_to_ids_acceledge_sumo[id_stop] = ids_edge_sumo[get_outgoing(id_stopedge)[0]] 877 878 self.id_edge_sumo_to_id_stop = {} 879 for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]): 880 self.id_edge_sumo_to_id_stop[id_edge_sumo] = id_stop 881 882 self.inds_berth_alight_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32) 883 self.inds_berth_board_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32) 884 self.ids_vehs_alight_allocated = np.zeros(np.max(ids)+1, dtype=np.object) 885 self.ids_vehs_board_allocated = np.zeros(np.max(ids)+1, dtype=np.object) 886 887 # time when last platoon vehicle accumulation started 888 # -1 means no platoon accumulation takes place 889 self.times_plat_accumulate = -1*np.ones(np.max(ids)+1, dtype=np.int32) 890 891 self.ids_vehs_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object) 892 self.ids_vehs = np.zeros(np.max(ids)+1, dtype=np.object) 893 self.ids_vehs_toallocate = np.zeros(np.max(ids)+1, dtype=np.object) 894 # 895 self.times_lastboard = 10**4*np.ones(np.max(ids)+1, dtype=np.int32) 896 897 # for vehicle management 898 self.numbers_veh = np.zeros(np.max(ids)+1, dtype=np.int32) 899 self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype=np.int32) 900 self.flows_person = np.zeros(np.max(ids)+1, dtype=np.float32) 901 self.ids_veh_lead = -1*np.ones(np.max(ids)+1, dtype=np.int32) 902 #self.ids_veh_lastdep = -1*np.ones(np.max(ids)+1,dtype = np.int32) 903 self.ids_vehs_prog = np.zeros(np.max(ids)+1, dtype=np.object) 904 905 # person management 906 self.ids_persons_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object) 907 #self.ids_persons_sumo_boarded = np.zeros(np.max(ids)+1,dtype = np.object) 908 self.waittimes_persons = np.zeros(np.max(ids)+1, dtype=np.object) 909 self.waittimes_tot = np.zeros(np.max(ids)+1, dtype=np.float32) 910 911 virtualpop = self.get_scenario().demand.virtualpop 912 913 ids_persons = virtualpop.get_ids() 914 stagelists = virtualpop.get_plans().stagelists 915 prttransits = virtualpop.get_plans().get_stagetable('prttransits') 916 id_person_to_origs_dests = {} 917 918 # create map from person id to various destination information 919 # TODO: needs to be improved for trip chains, move to prtservices 920 # idea: whu not scan prttransits? 921 for id_person, stagelist in zip(ids_persons, stagelists[virtualpop.ids_plan[ids_persons]]): 922 # print ' check dests of id_person',id_person 923 for stages, id_stage in stagelist: 924 if stages.ident == 'prttransits': 925 id_fromedge_sumo = ids_edge_sumo[stages.ids_fromedge[id_stage]] 926 id_toedge_sumo = ids_edge_sumo[stages.ids_toedge[id_stage]] 927 data_orig_dest = (self.id_edge_sumo_to_id_stop[id_fromedge_sumo], 928 self.id_edge_sumo_to_id_stop[id_toedge_sumo], 929 id_fromedge_sumo, 930 id_toedge_sumo) 931 932 id_person_sumo = virtualpop.get_id_sumo_from_id(id_person) 933 if id_person_to_origs_dests.has_key(id_person_sumo): 934 id_person_to_origs_dests[id_person_sumo].append(data_orig_dest) 935 else: 936 id_person_to_origs_dests[id_person_sumo] = [data_orig_dest] 937 # print ' prtdests = ',id_person_to_origs_dests[id_person_sumo] 938 939 # print ' id_person_to_origs_dests=\n',id_person_to_origs_dests 940 self.id_person_to_origs_dests = id_person_to_origs_dests 941 942 # this is only used for crazy person stage detection 943 # angles_stop = 944 945 # various initianilizations 946 for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]): 947 # set allocation index to last possible berth 948 self.inds_berth_alight_allocated[id_stop] = len(self.ids_berth_alight[id_stop]) 949 self.inds_berth_board_allocated[id_stop] = len(self.ids_berth_board[id_stop]) 950 951 self.ids_vehs_alight_allocated[id_stop] = [] 952 self.ids_vehs_board_allocated[id_stop] = [] 953 954 self.ids_vehs_sumo_prev[id_stop] = set([]) 955 self.ids_persons_sumo_prev[id_stop] = set([]) 956 #self.ids_persons_sumo_boarded [id_stop] = [] 957 self.waittimes_persons[id_stop] = {} 958 self.ids_vehs[id_stop] = [] 959 self.ids_vehs_toallocate[id_stop] = [] 960 961 self.ids_vehs_prog[id_stop] = [] 962 963 # traci.edge.subscribe(id_edge_sumo, [traci.constants.VAR_ARRIVED_VEHICLES_IDS]) 964 updatedata_berth = berths.prepare_sim(process) 965 966 return [(self.time_update.get_value(), self.process_step), 967 ]+updatedata_berth 968 969 def process_step(self, process): 970 simtime = process.simtime 971 # print 79*'_' 972 # print 'PrtStops.process_step at',simtime 973 net = self.get_scenario().net 974 ptstops = net.ptstops 975 berths = self.get_berths() 976 lanes = net.lanes 977 ids_edge_sumo = net.edges.ids_sumo 978 vehicles = self.parent.prtvehicles 979 virtualpop = self.get_scenario().demand.virtualpop 980 ids = self.get_ids() 981 982 for id_stop, id_edge_sumo, ids_veh_sumo_prev, ids_person_sumo_prev in\ 983 zip(ids, self.ids_stop_to_ids_edge_sumo[ids], 984 self.ids_vehs_sumo_prev[ids], 985 self.ids_persons_sumo_prev[ids]): 986 # print ' '+60*'.' 987 # print ' process id_stop,id_edge_sumo', id_stop,id_edge_sumo 988 if 0: 989 990 # print ' ids_berth_alight',self.ids_berth_alight[id_stop] 991 # print ' ids_berth_board',self.ids_berth_board[id_stop] 992 print ' ids_vehs', self.ids_vehs[id_stop] 993 print ' ids_vehs_toallocate', self.ids_vehs_toallocate[id_stop] 994 print ' ids_vehs_alight_allocated', self.ids_vehs_alight_allocated[id_stop] 995 print ' ids_vehs_board_allocated', self.ids_vehs_board_allocated[id_stop] 996 print ' id_veh_lead prt.%d' % self.ids_veh_lead[id_stop] 997 print ' ids_vehs_prog', self.ids_vehs_prog[id_stop] 998 999 print ' inds_berth_alight_allocated', self.inds_berth_alight_allocated[id_stop] 1000 print ' inds_berth_board_allocated', self.inds_berth_board_allocated[id_stop] 1001 print ' numbers_person_wait', self.numbers_person_wait[id_stop] 1002 # print ' flow_person',self.flows_person[id_stop] 1003 # print ' waittimes_persons',self.waittimes_persons[id_stop] 1004 print ' waittimes_tot', self.waittimes_tot[id_stop] 1005 # no longer print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop] 1006 print ' times_lastboard', self.times_lastboard[id_stop] 1007 1008 if 0: 1009 for id_veh_sumo in self.ids_vehs_sumo_prev[id_stop]: 1010 print ' stopstate ', id_veh_sumo, bin(traci.vehicle.getStopState(id_veh_sumo))[ 1011 2:], traci.vehicle.getRoute(id_veh_sumo) 1012 1013 if 0: 1014 self.get_berthqueues(id_stop) 1015 1016 # check for new vehicle arrivals/departures 1017 ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_sumo)) 1018 # print ' ids_veh_sumo_prev=',ids_veh_sumo_prev 1019 # print ' ids_veh_sumo=',ids_veh_sumo 1020 1021 if ids_veh_sumo_prev != ids_veh_sumo: 1022 ids_veh_entered = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo.difference(ids_veh_sumo_prev))) 1023 ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo))) 1024 for id_veh in ids_veh_entered: 1025 self.enter(id_stop, id_veh) 1026 1027 for id_veh in ids_veh_left: 1028 self.exit(id_stop, id_veh) 1029 self.ids_vehs_sumo_prev[id_stop] = ids_veh_sumo 1030 # print ' ids_veh_sumo_entered',ids_veh_sumo_entered 1031 # print ' ids_veh_sumo_left',ids_veh_sumo_left 1032 1033 # check whether allocated vehicles arrived at alighting berths 1034 ids_veh_remove = [] 1035 for id_veh in self.ids_vehs_alight_allocated[id_stop]: 1036 # TODO: here we could also check vehicle position 1037 # print ' isStopped',vehicles.get_id_sumo(id_veh),traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)) 1038 if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)): 1039 ids_veh_remove.append(id_veh) 1040 id_berth_alight = vehicles.ids_berth[id_veh] 1041 berths.ids_veh[id_berth_alight] = id_veh 1042 berths.states[id_berth_alight] = BERTHSTATES['alighting'] 1043 vehicles.alight(id_veh) 1044 1045 for id_veh in ids_veh_remove: 1046 self.ids_vehs_alight_allocated[id_stop].remove(id_veh) 1047 1048 # check whether we can move vehicles from alighting to 1049 # boarding berths 1050 1051 # TODO: here we must check if berth in boarding zone are free 1052 # AND if they are occupied with empty vehicles, those 1053 # vehicles need to be kicked out...but only in case 1054 # new vehicles are waiting to be allocated 1055 1056 ids_berth_alight = self.ids_berth_alight[id_stop][::-1] 1057 ids_berth_board = self.ids_berth_board[id_stop][::-1] 1058 1059 if True: # len(self.ids_vehs_alight_allocated[id_stop])==0: 1060 # all vehicles did arrive in alight position 1061 1062 # identify berth and vehicles ready to forward to boarding 1063 ids_veh_forward = [] 1064 ids_berth_forward = [] 1065 for id_berth_alight, id_veh in zip( 1066 ids_berth_alight, 1067 berths.ids_veh[ids_berth_alight], 1068 ): 1069 # print ' check alight->board for veh prt.%d'%id_veh,'at berth',id_berth_alight,berths.states[id_berth_alight], berths.states[id_berth_alight]==BERTHSTATES['free'] 1070 1071 if id_veh >= 0: # is there a waiting vehicle 1072 if vehicles.is_completed_alighting(id_veh): 1073 ids_veh_forward.append(id_veh) 1074 ids_berth_forward.append(id_berth_alight) 1075 else: 1076 # print ' vehicle has not finished alighting...' 1077 # stop allocating berth in board zone 1078 # to prevent allocations behind non-allocated vehicles 1079 break 1080 1081 n_veh_alloc = len(ids_veh_forward) 1082 1083 if n_veh_alloc > 0: 1084 1085 if self.inds_berth_board_allocated[id_stop] > n_veh_alloc: 1086 queues = self.get_berthqueues(id_stop) 1087 else: 1088 queues = None 1089 1090 # print ' found %d veh at id_stop=%d to berth alloc with alloc index %d'%(n_veh_alloc,id_stop, self.inds_berth_board_allocated [id_stop]) 1091 # if queues is not None: 1092 # print ' queues',queues 1093 for id_berth_alight, id_veh in zip( 1094 ids_berth_forward, 1095 ids_veh_forward, 1096 ): 1097 1098 id_berth_board = self.allocate_board(id_stop, n_veh_alloc, queues) 1099 # print ' try allocate id_veh=prt.%d for berth id_berth_board=%d'%(id_veh,id_berth_board) 1100 if id_berth_board >= 0: 1101 # print ' send vehicle id_veh %d to id_berth_board %d'%(id_veh,id_berth_board)#,berths.stoppositions[id_berth_board] 1102 n_veh_alloc -= 1 1103 berths.ids_veh[id_berth_alight] = -1 1104 1105 berths.states[id_berth_alight] = BERTHSTATES['free'] 1106 1107 vehicles.control_stop_board(id_veh, id_stop, id_berth_board, 1108 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop], 1109 position=berths.stoppositions[id_berth_board], 1110 ) 1111 self.ids_vehs_board_allocated[id_stop].append(id_veh) 1112 1113 # if all allocated vehicles found their berth and all berths are free, then 1114 # reset alight allocation index 1115 # print ' check for reset of alight allocation index' 1116 if len(self.ids_vehs_alight_allocated[id_stop]) == 0: 1117 if np.all(berths.states[ids_berth_alight] == BERTHSTATES['free']): 1118 # print ' reset inds_berth_alight_allocated',self.inds_berth_alight_allocated[id_stop],'->',len(self.ids_berth_alight[id_stop]) 1119 self.inds_berth_alight_allocated[id_stop] = len(self.ids_berth_alight[id_stop]) 1120 1121 # try to allocate unallocated vehicles 1122 ids_veh_remove = [] 1123 for id_veh in self.ids_vehs_toallocate[id_stop]: 1124 id_berth = self.allocate_alight(id_stop) 1125 if id_berth < 0: 1126 # allocation failed 1127 # do nothing, vehicle continues to wait for allocation 1128 pass 1129 else: 1130 # command vehicle to go to berth for alighting 1131 # print ' send waiting vehicle id_veh %d to id_berth_alight %d'%(id_veh,id_berth)#,berths.stoppositions[id_berth] 1132 self.parent.prtvehicles.control_stop_alight(id_veh, id_stop, id_berth, 1133 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop], 1134 position=self.get_berths( 1135 ).stoppositions[id_berth], 1136 ) 1137 self.ids_vehs_alight_allocated[id_stop].append(id_veh) 1138 ids_veh_remove.append(id_veh) 1139 1140 for id_veh in ids_veh_remove: 1141 self.ids_vehs_toallocate[id_stop].remove(id_veh) 1142 1143 # check whether allocated vehicles arrived at boarding berths 1144 ids_veh_remove = [] 1145 for id_veh in self.ids_vehs_board_allocated[id_stop]: 1146 # TODO: here we could also check vehicle position 1147 if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)): 1148 ids_veh_remove.append(id_veh) 1149 id_berth_board = vehicles.ids_berth[id_veh] 1150 berths.ids_veh[id_berth_board] = id_veh 1151 berths.states[id_berth_board] = BERTHSTATES['boarding'] 1152 vehicles.board(id_veh, 1153 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop]) 1154 1155 self.parent.vehicleman.indicate_trip_empty(id_veh, id_stop, simtime) 1156 # vehicle could become potentially the lead vehicle 1157 self.try_set_leadveh(id_stop, id_veh) 1158 1159 for id_veh in ids_veh_remove: 1160 self.ids_vehs_board_allocated[id_stop].remove(id_veh) 1161 1162 # if all allocated vehicles for board area 1163 # found their berth and all berths are free, then 1164 # reset allocation index 1165 # 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] 1166 if (self.inds_berth_board_allocated[id_stop] == 0) & (len(self.ids_vehs_board_allocated[id_stop]) == 0): 1167 1168 if np.all(berths.states[ids_berth_board] == BERTHSTATES['free']): 1169 # print ' reset inds_berth_board_allocated to',len(self.ids_berth_board[id_stop]) 1170 self.inds_berth_board_allocated[id_stop] = len(self.ids_berth_board[id_stop]) 1171 1172 # check for new person entering/left the station edge 1173 ids_person_sumo = set(traci.edge.getLastStepPersonIDs(id_edge_sumo)) 1174 1175 n_enter = 0 1176 if ids_person_sumo_prev != ids_person_sumo: 1177 1178 if 0: 1179 print ' change\n id_person_sumo', ids_person_sumo 1180 print ' ids_person_sumo_prev', ids_person_sumo_prev 1181 # print ' dir(traci.person)',dir(traci.person) 1182 # for id_person_sumo in ids_person_sumo: 1183 # print ' id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo),traci.person.getVehicle(id_person_sumo) 1184 1185 # deal with persons who left the edge 1186 # NEW: this is done later when loaded vehicles are investigated 1187 1188 #ids_person_sumo_left = ids_person_sumo_prev.difference(ids_person_sumo) 1189 # print ' ids_person_sumo_left',ids_person_sumo_left 1190 # for id_person_sumo in ids_person_sumo_left: 1191 # print ' id_person_sumo_left pers',id_person_sumo,id_edge_sumo,traci.person.getRoadID(id_person_sumo),traci.person.getVehicle(id_person_sumo) 1192 # #print ' ids_person_sumo',ids_person_sumo 1193 # # tricky: if the person who left the edge id_edge_sumo 1194 # # shows still id_edge_sumo then this person is in a vehicle 1195 # if traci.person.getRoadID(id_person_sumo) == id_edge_sumo: 1196 # #print ' person boarded: pers',id_person_sumo,traci.person.getLanePosition(id_person_sumo) 1197 # self.ids_persons_sumo_boarded[id_stop].append(id_person_sumo) 1198 # self.waittimes_tot[id_stop] -= simtime - self.waittimes_persons[id_stop][id_person_sumo] 1199 # del self.waittimes_persons[id_stop][id_person_sumo] 1200 # self.numbers_person_wait[id_stop] -= 1 1201 1202 # deal with persons who entered the edge 1203 ids_person_sumo_entered = ids_person_sumo.difference(ids_person_sumo_prev) 1204 for id_person_sumo in ids_person_sumo_entered: 1205 # print ' entered id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo) 1206 if self.id_person_to_origs_dests.has_key(id_person_sumo): 1207 id_edge_sumo_dests = self.id_person_to_origs_dests[id_person_sumo] 1208 # check if person still has a PRT trip 1209 1210 if len(id_edge_sumo_dests) > 0: 1211 # check if next trip has origin edge equal to edge of this stop 1212 if id_edge_sumo_dests[0][2] == id_edge_sumo: 1213 # print ' add to waittimes_persons',id_person_sumo 1214 self.waittimes_persons[id_stop][id_person_sumo] = simtime 1215 n_enter += 1 1216 1217 # communicate person entry to vehman 1218 self.parent.vehicleman.note_person_entered( 1219 id_stop, id_person_sumo, id_edge_sumo_dests[0][1]) 1220 1221 # else: 1222 # print 'WARNING: person %s starts with % insted of %s.'%(id_person_sumo,id_edge_sumo_dests[0][2],id_edge_sumo) 1223 1224 self.numbers_person_wait[id_stop] += n_enter 1225 self.ids_persons_sumo_prev[id_stop] = ids_person_sumo 1226 1227 self.waittimes_tot += self.numbers_person_wait*self.time_update.get_value() 1228 1229 timeconst_flow = self.timeconst_flow.get_value() 1230 self.flows_person[id_stop] = timeconst_flow*self.flows_person[id_stop] + \ 1231 (1.0-timeconst_flow)*float(n_enter)/self.time_update.get_value() 1232 1233 if 0: 1234 for id_person_sumo in ids_person_sumo_prev: 1235 print ' ids_person_sumo=%s pos = %.2f ' % ( 1236 id_person_sumo, traci.person.getLanePosition(id_person_sumo)) 1237 # nomore print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop] 1238 1239 # check if boarding is completed in load area, 1240 # starting with last vehicle 1241 ids_berth_board = self.ids_berth_board[id_stop][::-1] 1242 for id_berth_board, id_veh in zip( 1243 ids_berth_board, 1244 berths.ids_veh[ids_berth_board], 1245 ): 1246 if id_veh >= 0: # is there a waiting vehicle 1247 id_veh_sumo = vehicles.get_veh_if_completed_boarding(id_veh) 1248 if id_veh_sumo: 1249 id_person_sumo = self.init_trip_occupied(id_stop, 1250 id_berth_board, 1251 id_veh, 1252 id_veh_sumo, 1253 simtime) 1254 if id_person_sumo is not None: 1255 # do some statistics here 1256 self.waittimes_tot[id_stop] -= simtime - self.waittimes_persons[id_stop][id_person_sumo] 1257 del self.waittimes_persons[id_stop][id_person_sumo] 1258 self.numbers_person_wait[id_stop] -= 1 1259 1260 # check if there are passengers in the vehicles which wait for 1261 # alight allocate 1262 # TODO: can be replaced by a single instruction 1263 n_pax = 0 1264 for id_veh in self.ids_vehs_alight_allocated[id_stop]+self.ids_vehs_toallocate[id_stop]: 1265 if vehicles.states[id_veh] == VEHICLESTATES['occupiedtrip']: 1266 n_pax += 1 1267 # print ' n_pax' ,n_pax 1268 # check whether to foreward vehicles in boarding berth 1269 1270 # no foreward if all berth are free occupied vehicles 1271 if np.all(berths.states[ids_berth_board] == BERTHSTATES['free']): 1272 # print ' foreward all occupied id_stop,ids_berth_board',id_stop,ids_berth_board 1273 #self.foreward_boardzone(id_stop, ids_berth_board) 1274 self.times_lastboard[id_stop] = 10**4 # reset clock if all are free 1275 1276 # foreward if there are passengers in unallocated vehicles 1277 elif (self.numbers_person_wait[id_stop] == 0) & (n_pax > 0): 1278 # passengers arriving, no persons waiting 1279 # kick out immediately 1280 self.foreward_boardzone(id_stop, ids_berth_board, simtime) 1281 1282 # elif (self.numbers_person_wait[id_stop]>0) & (n_pax>0) & (self.times_lastboard[id_stop] == 10**4): 1283 elif ((self.numbers_person_wait[id_stop] > 0) | (n_pax > 0)) & (self.times_lastboard[id_stop] == 10**4): 1284 # passengers arriving but still persons boarding 1285 # reset kick-out counter 1286 self.times_lastboard[id_stop] = simtime 1287 1288 elif simtime - self.times_lastboard[id_stop] > self.time_kickout.get_value(): 1289 # print ' call foreward_boardzone timeout',process.simtime,self.times_lastboard[id_stop],process.simtime - self.times_lastboard[id_stop] 1290 self.foreward_boardzone(id_stop, ids_berth_board, simtime) 1291 1292 # check whether a programmed vehicle can be started 1293 if self.types[id_stop] == STOPTYPES['group']: 1294 self.start_vehicles_platoon(id_stop, process) 1295 else: 1296 self.start_vehicles(id_stop, process) 1297 1298 def start_vehicles(self, id_stop, process): 1299 # print 'start_vehicles=\n',self.ids_vehs_prog[id_stop] 1300 i = 0 1301 vehicles = self.parent.prtvehicles 1302 ids_vehs_prog = self.ids_vehs_prog[id_stop] 1303 for time_start, id_veh, id_stop_target, is_started in ids_vehs_prog: 1304 if process.simtime > time_start: 1305 if not is_started: 1306 if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)): 1307 route, duration = self.route_stop_to_stop(id_stop, id_stop_target) 1308 self.parent.prtvehicles.reschedule_trip(id_veh, 1309 route_sumo=self.get_scenario().net.edges.ids_sumo[route] 1310 ) 1311 ids_vehs_prog[i][3] = True 1312 i += 1 1313 1314 def route_stop_to_stop(self, id_stop_from, id_stop_to): 1315 # route 1316 return self.parent.get_route(self.ids_stop_to_ids_edge[id_stop_from], 1317 self.ids_stop_to_ids_edge[id_stop_to] 1318 ) 1319 1320 def start_vehicles_platoon(self, id_stop, process, timeout_platoon=40, n_platoon_max=8): 1321 # print 'start_vehicles_platoon id_stop, times_plat_accumulate',id_stop,self.times_plat_accumulate[id_stop] 1322 # print ' ids_vehs_prog=\n',self.ids_vehs_prog[id_stop] 1323 1324 if self.times_plat_accumulate[id_stop] < 0: 1325 # print ' accumulation has not even started' 1326 return 1327 1328 vehicles = self.parent.prtvehicles 1329 ids_vehs_prog = self.ids_vehs_prog[id_stop] 1330 inds_platoon = [] 1331 i = 0 # len(ids_vehs_prog) 1332 id_veh_nextplatoon = -1 1333 for time_start, id_veh, id_stop_target, is_started in ids_vehs_prog: # [::-1]: 1334 1335 if not is_started: 1336 if len(inds_platoon) == 0: 1337 # check if first vehicle in platoon is stopped 1338 if traci.vehicle.isStopped(vehicles.get_id_sumo(id_veh)): 1339 inds_platoon.append(i) 1340 else: 1341 break 1342 else: 1343 # append to platoon 1344 inds_platoon.append(i) 1345 1346 i += 1 1347 1348 # print ' trigger platoon?', inds_platoon,len(inds_platoon),n_platoon_max,process.simtime - self.times_plat_accumulate[id_stop],timeout_platoon 1349 if len(inds_platoon) == 0: 1350 return 1351 1352 if (process.simtime - self.times_plat_accumulate[id_stop] > timeout_platoon)\ 1353 | (len(inds_platoon) >= n_platoon_max): 1354 1355 # platoon release triggered 1356 self._trigger_platoon(id_stop, inds_platoon) 1357 1358 def _trigger_platoon(self, id_stop, inds_platoon): 1359 # print 'trigger_platoon inds_platoon',inds_platoon 1360 ids_vehs_prog = self.ids_vehs_prog[id_stop] 1361 self.times_plat_accumulate[id_stop] = -1 1362 1363 time_start, id_veh, id_stop_target, is_prog = ids_vehs_prog[inds_platoon[0]] 1364 self.parent.prtvehicles.reschedule_trip(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target]) 1365 ids_vehs_prog[inds_platoon[0]][3] = True 1366 # one vehicle platoon, no followers 1367 if len(inds_platoon) > 1: 1368 # try to concatenate followers 1369 for i in xrange(1, len(inds_platoon)): 1370 time_start_pre, id_veh_pre, id_stop_target_pre, is_prog_pre = ids_vehs_prog[inds_platoon[i-1]] 1371 time_start, id_veh, id_stop_target, is_prog = ids_vehs_prog[inds_platoon[i]] 1372 # print ' check prt.%d'%ids_vehs_prog[inds_platoon[i]][1],'with leader prt.%d'%ids_vehs_prog[inds_platoon[i-1]][1],id_stop_target == id_stop_target_pre 1373 if id_stop_target == id_stop_target_pre: 1374 self.parent.prtvehicles.concatenate(id_veh, id_veh_pre) 1375 1376 self.parent.prtvehicles.reschedule_trip(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target]) 1377 ids_vehs_prog[inds_platoon[i]][3] = True 1378 1379 def try_set_leadveh(self, id_stop, id_veh): 1380 1381 if self.ids_veh_lead[id_stop] >= 0: 1382 # print 'try_set_leadveh leader already defined',id_stop,id_veh,self.ids_veh_lead[id_stop] 1383 return False 1384 else: 1385 ind_queue = self.ids_vehs[id_stop].index(id_veh) 1386 # print 'try_set_leadveh id_stop, id_veh,ind_queue',id_stop, 'prt.%d'%id_veh,ind_queue,len(self.ids_vehs[id_stop]),len(self.ids_vehs_prog[id_stop]) 1387 1388 if ind_queue == 0: # len(self.ids_vehs[id_stop])-1: 1389 # print ' id_veh is new leader because last position',self.ids_vehs[id_stop].index(id_veh) 1390 # print ' ids_vehs',self.ids_vehs[id_stop] 1391 self.set_leadveh(id_stop, id_veh) 1392 return True 1393 1394 elif len(self.ids_vehs_prog[id_stop]) == ind_queue: 1395 # print ' id_veh is new leader because all vehicles in front are already programmed' 1396 self.set_leadveh(id_stop, id_veh) 1397 return True 1398 # elif len(self.ids_vehs_prog[id_stop])>0: 1399 # if (self.ids_vehs[id_stop][ind_queue-1] == self.ids_vehs_prog[id_stop][-1][1]) : 1400 # print ' id_veh is new leader because next vehicle %d is programmed'%(self.ids_vehs[id_stop][ind_queue-1],) 1401 # self.set_leadveh(id_stop, id_veh) 1402 # return True 1403 # else: 1404 # return False 1405 1406 else: 1407 return False 1408 1409 def set_leadveh(self, id_stop, id_veh): 1410 # print 'set_leadveh id_stop=%d, prt.%d'%( id_stop,id_veh) 1411 self.ids_veh_lead[id_stop] = id_veh 1412 1413 def program_leadveh(self, id_stop, id_veh, id_stop_target, time_start): 1414 print 'program_leadveh prt.%d from id_stop %d to id_stop_target %d at %d' % ( 1415 id_veh, id_stop, id_stop_target, time_start), 'check leader', id_veh == self.ids_veh_lead[id_stop] 1416 1417 # check also if occupied in the meanwhile?? need to know emptytrip or not... 1418 if id_veh == self.ids_veh_lead[id_stop]: 1419 # check in vehman:if self.parent.prtvehicles.is_still_empty(id_veh): 1420 1421 if self.parent.prtvehicles.states[id_veh] == VEHICLESTATES['boarding']: 1422 id_berth_board = self.parent.prtvehicles.ids_berth[id_veh] 1423 self.init_trip_empty(id_stop, id_berth_board, id_veh, time_start, is_ask_vehman=False) 1424 1425 self.ids_veh_lead[id_stop] = -1 1426 1427 # format for programmed vehicle list: 1428 # [time_start, id_veh, id_stop_target,is_started] 1429 self.ids_vehs_prog[id_stop].append([time_start, id_veh, id_stop_target, False]) 1430 1431 if self.types[id_stop] == STOPTYPES['group']: 1432 # in platoon mode... 1433 # set a stop for this vehicle if there are only started, programmed 1434 # vehicles in front , or no vehicle 1435 1436 # check if this vehicle needs to stop in front of the stopline 1437 # in order to hold up other vehicles in the platoon 1438 # print ' check stopline',len(self.ids_vehs_prog[id_stop]) 1439 # print ' ids_vehs_prog ',self.ids_vehs_prog[id_stop] 1440 is_stop = True 1441 for i in range(len(self.ids_vehs_prog[id_stop])-2, -1, -1): 1442 # print ' check prt.%d'%self.ids_vehs_prog[id_stop][i][1],'started',self.ids_vehs_prog[id_stop][i][3] 1443 if not self.ids_vehs_prog[id_stop][i][3]: # is already started 1444 is_stop = False 1445 break 1446 1447 if is_stop: 1448 # make this vehicle stop at stopline and reset platoon timer 1449 self.parent.prtvehicles.set_stop( 1450 id_veh, self.ids_stop_to_ids_edge_sumo[id_stop], self.stoplines[id_stop]) 1451 self.times_plat_accumulate[id_stop] = time_start 1452 1453 # try make previous vehicle the lead vehicle 1454 ind_queue = self.ids_vehs[id_stop].index(id_veh) 1455 1456 # print ' ind_queue,queuelen,ok',ind_queue,len(self.ids_vehs[id_stop]),len(self.ids_vehs[id_stop]) > ind_queue+1 1457 if len(self.ids_vehs[id_stop]) > ind_queue+1: 1458 id_veh_newlead = self.ids_vehs[id_stop][ind_queue+1] 1459 # print ' id_veh_newlead, state',id_veh_newlead, self.parent.prtvehicles.states[id_veh_newlead] 1460 if self.parent.prtvehicles.states[id_veh_newlead] in LEADVEHICLESTATES: 1461 self.set_leadveh(id_stop, id_veh_newlead) 1462 1463 # print ' new lead veh prt.%d'%(self.ids_veh_lead[id_stop],) 1464 return True 1465 1466 else: 1467 return False 1468 1469 def init_trip_occupied(self, id_stop, id_berth, id_veh, id_veh_sumo, simtime): 1470 # TODO: actually a berth method?? 1471 berths = self.get_berths() 1472 1473 #id_veh_sumo = self.parent.prtvehicles.get_id_sumo(id_veh) 1474 n_pax = traci.vehicle.getPersonNumber(id_veh_sumo) 1475 # print 'init_trip_occupied', id_stop, id_berth, 'veh=%s'%id_veh_sumo,'simtime',simtime,'n_pax',n_pax 1476 1477 # identify whic of the boarding persons is in the 1478 # vehicle which completed boarding 1479 dist_min = np.inf 1480 id_person_sumo_inveh = None 1481 stoppos = berths.stoppositions[id_berth] 1482 1483 for id_person_sumo in self.ids_persons_sumo_prev[id_stop]: 1484 # print ' check veh of person',id_person_sumo,traci.person.getVehicle(id_person_sumo),id_veh_sumo 1485 if traci.person.getVehicle(id_person_sumo) == id_veh_sumo: 1486 id_person_sumo_inveh = id_person_sumo 1487 1488 #d = abs(stoppos - traci.person.getLanePosition(id_person_sumo)) 1489 # if d<dist_min: 1490 # dist_min = d 1491 # id_person_sumo_inveh = id_person_sumo 1492 1493 if id_person_sumo_inveh is not None: 1494 # print ' found person %s in veh %s'%(id_person_sumo_inveh,id_veh_sumo) 1495 1496 # program vehicle to person's destination 1497 # print ' found person,origs_dests',id_person_sumo_inveh,self.id_person_to_origs_dests[id_person_sumo_inveh] 1498 id_stop_orig, id_stop_dest, id_edge_sumo_from, id_edge_sumo_to = \ 1499 self.id_person_to_origs_dests[id_person_sumo_inveh].pop(0) 1500 # print ' found person', id_person_sumo_inveh,'from', id_stop_orig, id_edge_sumo_from,' to' , id_edge_sumo_to, id_stop_dest 1501 1502 stopline = self._get_stopline(id_stop, simtime) 1503 # print ' simtime', simtime 1504 1505 self.parent.prtvehicles.init_trip_occupied( 1506 id_veh, self.ids_stop_to_ids_edge_sumo[id_stop], 1507 stopline, 1508 ) 1509 1510 # self.ids_persons_sumo_boarded[id_stop].remove(id_person_sumo_inveh) 1511 self.times_lastboard[id_stop] = simtime 1512 berths.states[id_berth] = BERTHSTATES['free'] 1513 berths.ids_veh[id_berth] = -1 1514 # self.ids_vehs_outset[id_stop].add(id_veh) 1515 self.try_set_leadveh(id_stop, id_veh) 1516 self.parent.vehicleman.init_trip_occupied(id_veh, id_stop, id_stop_dest, simtime) 1517 return id_person_sumo_inveh 1518 1519 else: 1520 print 'WARNING: on stop %d edge %s, berth %d no person found inside vehicle prt.%d' % ( 1521 id_stop, self.ids_stop_to_ids_edge_sumo[id_stop], id_berth, id_veh) 1522 return None 1523 1524 def _get_stopline(self, id_stop, simtime): 1525 if self.types[id_stop] == STOPTYPES['group']: 1526 # print ' platooning...',id_stop,simtime 1527 if self.times_plat_accumulate[id_stop] < 0: # len(self.ids_vehs_prog[id_stop]) == 0: 1528 # print ' first in platoon-> stop it at exit-line',simtime 1529 #stopline = self.stoplines[id_stop] 1530 # actually not clear who will arrive first at the stopline 1531 # therefore do not stop. Stop must be set duruing rescheduling 1532 stopline = None 1533 self.times_plat_accumulate[id_stop] = simtime 1534 # print ' times_plat_accumulate',self.times_plat_accumulate[id_stop],simtime 1535 else: 1536 # print ' not first, let it approach previous veh.' 1537 stopline = None 1538 1539 else: 1540 # print ' no platooning: all vehicles stop and wait for start' 1541 stopline = self.stoplines[id_stop] 1542 # print ' times_plat_accumulate',self.times_plat_accumulate[id_stop],'simtime',simtime 1543 # print ' stopline',stopline 1544 return stopline 1545 1546 def init_trip_empty(self, id_stop, id_berth, id_veh, simtime, is_ask_vehman=True): 1547 # print 'Stops.init_trip_empty id_stop, id_berth, id_veh, is_ask_vehman', id_stop, id_berth, 'prt.%d'%id_veh, is_ask_vehman,'simtime',simtime 1548 # TODO: actually a berth method?? 1549 berths = self.get_berths() 1550 1551 berths.states[id_berth] = BERTHSTATES['free'] 1552 berths.ids_veh[id_berth] = -1 1553 1554 # print ' proceed to stopline',self.stoplines[id_stop] 1555 stopline = self._get_stopline(id_stop, simtime) 1556 self.parent.prtvehicles.init_trip_empty( 1557 id_veh, 1558 self.ids_stop_to_ids_edge_sumo[id_stop], 1559 stopline) 1560 1561 if is_ask_vehman: 1562 self.try_set_leadveh(id_stop, id_veh) 1563 #id_stop_target = self.parent.vehicleman.init_trip_empty(id_veh, id_stop) 1564 self.parent.vehicleman.init_trip_empty(id_veh, id_stop, simtime) 1565 1566 # print 'init_trip_empty for',id_veh,' from',id_stop,'to',id_stop_target,id_edge_sumo_target 1567 #self.parent.prtvehicles.init_trip_empty(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target]) 1568 1569 # else: 1570 # self.parent.prtvehicles.init_trip_empty(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop], -1) 1571 1572 # self.ids_vehs_outset[id_stop].add(id_veh) 1573 1574 def foreward_boardzone(self, id_stop, ids_berth_board, simtime): 1575 # print 'foreward_boardzone',id_stop,ids_berth_board,'simtime',simtime 1576 berths = self.get_berths() 1577 #ids_berth_board = self.ids_berth_board[id_stop][::-1] 1578 # inds_o berths.states[ids_berth_board] != BERTHSTATES['free'] 1579 for id_berth, state in zip(ids_berth_board, berths.states[ids_berth_board]): 1580 # print ' id_berth,boarding?,id_veh',id_berth, state== BERTHSTATES['boarding'],berths.ids_veh[id_berth] 1581 if state == BERTHSTATES['boarding']: 1582 self.init_trip_empty(id_stop, id_berth, berths.ids_veh[id_berth], simtime) 1583 1584 self.times_lastboard[id_stop] = 10**4 # reset last board counter 1585 1586 def enter(self, id_stop, id_veh): 1587 print 'enter id_stop, id_veh', id_stop, 'prt.%d' % id_veh 1588 1589 self.parent.prtvehicles.decatenate(id_veh) 1590 1591 self.ids_vehs[id_stop].append(id_veh) 1592 1593 # tell vehman that veh arrived 1594 #self.numbers_veh_arr[id_stop] -= 1 1595 self.parent.vehicleman.conclude_trip(id_veh, id_stop) 1596 1597 self.numbers_veh[id_stop] += 1 1598 id_berth = self.allocate_alight(id_stop) 1599 if id_berth < 0: 1600 print ' allocation failed, command vehicle to slow down and wait for allocation' 1601 self.ids_vehs_toallocate[id_stop].append(id_veh) 1602 self.parent.prtvehicles.control_slow_down(id_veh) 1603 else: 1604 # command vehicle to go to berth for alighting 1605 print ' send entering vehicle id_veh %d to id_berth_alight %d at pos %.2fm' % ( 1606 id_veh, id_berth, self.get_berths().stoppositions[id_berth]) 1607 self.parent.prtvehicles.control_stop_alight(id_veh, id_stop, id_berth, 1608 id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop], 1609 position=self.get_berths().stoppositions[id_berth], 1610 ) 1611 self.ids_vehs_alight_allocated[id_stop].append(id_veh) 1612 1613 def exit(self, id_stop, id_veh): 1614 # print 'exit prt.%d at stop %d'%(id_veh,id_stop) 1615 self.ids_vehs[id_stop].remove(id_veh) 1616 #id_stop_target = self.parent.vehicleman.start_trip(id_veh, id_stop) 1617 #self.parent.prtvehicles.reschedule_trip(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target]) 1618 #ind_veh = -1 1619 # print ' ids_vehs_prog=\n',self.ids_vehs_prog[id_stop] 1620 i = 0 1621 for time_start, id_veh_prog, id_stop_target, is_prog in self.ids_vehs_prog[id_stop]: 1622 if id_veh_prog == id_veh: 1623 self.ids_vehs_prog[id_stop].pop(i) 1624 break 1625 i = +1 1626 1627 # self.ids_vehs_prog[id_stop].remove(id_veh) 1628 1629 self.numbers_veh[id_stop] -= 1 1630 1631 def allocate_alight(self, id_stop): 1632 1633 # print 'allocate_alight',id_stop 1634 #self.inds_berth_alight_allocated [id_stop] = len(self.ids_berth_alight[id_stop]) 1635 ind_berth = self.inds_berth_alight_allocated[id_stop] 1636 1637 if ind_berth == 0: 1638 # no free berth :( 1639 return -1 1640 else: 1641 ind_berth -= 1 1642 self.inds_berth_alight_allocated[id_stop] = ind_berth 1643 return self.ids_berth_alight[id_stop][ind_berth] 1644 1645 def allocate_board(self, id_stop, n_alloc, queues): 1646 """ 1647 Return successive berth ID to be allocated for boarding 1648 at given stop ID. 1649 n_veh_forward is the number of vehicles which remain to be 1650 allocated. 1651 """ 1652 # print 'allocate_alight',id_stop, n_alloc 1653 #self.inds_berth_alight_allocated [id_stop] = len(self.ids_berth_alight[id_stop]) 1654 ind_berth = self.inds_berth_board_allocated[id_stop] 1655 1656 if ind_berth == 0: 1657 # no free berth :( 1658 return -1 1659 else: 1660 if queues is None: 1661 1662 # less or equal allocation positions in board zone 1663 # then vehicles to be allocated 1664 ind_berth -= 1 1665 # print ' allocate in order ind_berth=',ind_berth 1666 self.inds_berth_board_allocated[id_stop] = ind_berth 1667 return self.ids_berth_board[id_stop][ind_berth] 1668 else: 1669 # there are more allocation positions in board zone 1670 # then vehicles to be allocated 1671 ind_berth -= 1 1672 id_berth = self.ids_berth_board[id_stop][ind_berth] 1673 # print ' check queue, start with ind_berth=%d,n_alloc=%d, id_berth=%d, queue=%d, pos=%.2fm'%(ind_berth,n_alloc,id_berth,queues[id_berth],self.get_berths().stoppositions[id_berth]),queues[id_berth] == 0,ind_berth >= n_alloc 1674 while (queues[id_berth] == 0) & (ind_berth >= n_alloc): 1675 ind_berth -= 1 1676 id_berth = self.ids_berth_board[id_stop][ind_berth] 1677 # print ' check queue, start with ind_berth=%d,n_alloc=%d, id_berth=%d, queue=%d, pos=%.2fm'%(ind_berth,n_alloc,id_berth,queues[id_berth],self.get_berths().stoppositions[id_berth]),queues[id_berth] == 0,ind_berth >= n_alloc 1678 1679 self.inds_berth_board_allocated[id_stop] = ind_berth 1680 return id_berth 1681 1682 def get_berthqueues(self, id_stop): 1683 # currently not used 1684 # print 'get_berthqueues',id_stop 1685 # TODO: use stop angle and person angle to detect waiting persons 1686 ids_berth_board = self.ids_berth_board[id_stop] 1687 stoppositions = self.get_berths().stoppositions[ids_berth_board] 1688 counters = np.zeros(len(stoppositions), dtype=np.int32) 1689 # print ' stoppositions',stoppositions 1690 for id_person_sumo in self.waittimes_persons[id_stop].keys(): 1691 position = traci.person.getLanePosition(id_person_sumo) 1692 # print ' position',position 1693 dists = np.abs(stoppositions-position) 1694 # print ' dists',dists,np.any(dists<5) 1695 if np.any(dists < 0.8): 1696 ind_berth = np.argmin(dists) 1697 counters[ind_berth] += 1 1698 1699 queues = {} 1700 for id_berth, count in zip(ids_berth_board, counters): 1701 queues[id_berth] = count 1702 1703 # print ' queues=\n',queues 1704 return queues 1705 1706 def make_from_net(self): 1707 """ 1708 Make prt stop database from PT stops in network. 1709 """ 1710 print 'make_from_net' 1711 self.clear() 1712 net = self.get_scenario().net 1713 ptstops = net.ptstops 1714 1715 ids_ptstop = ptstops.get_ids() 1716 id_mode_prt = self.parent.id_prtmode 1717 1718 #ids_edges = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]] 1719 #ids_lanes = net.edges.ids_lanes[ids_edges] 1720 ids_lane = ptstops.ids_lane[ids_ptstop] 1721 #edgelengths = net.edges.lengths 1722 1723 for id_stop, id_lane, position_from, position_to in zip( 1724 ids_ptstop, 1725 # ids_lanes, 1726 ids_lane, 1727 ptstops.positions_from[ids_ptstop], 1728 ptstops.positions_to[ids_ptstop], 1729 ): 1730 # get allowed modes of lane with index 1 1731 modes_allow = net.lanes.ids_modes_allow[id_lane] 1732 # print ' check id_stop, modes_allow, position_from, position_to',id_stop, modes_allow, position_from, position_to 1733 if id_mode_prt in modes_allow: 1734 self.make(id_stop, 1735 position_from, 1736 position_to) 1737 1738 self.parent.make_fstar(is_update=True) 1739 self.parent.make_times_stop_to_stop() 1740 1741 def make(self, id_ptstop, position_from, position_to): 1742 """ 1743 Initialize a new prt stop and generate berth. 1744 """ 1745 id_stop = self.add_row(ids_ptstop=id_ptstop) 1746 ids_berth = self.get_berths().make(id_stop, position_from=position_from, 1747 position_to=position_to) 1748 n_berth = len(ids_berth) 1749 n_berth_alight = int(0.5*n_berth) 1750 n_berth_board = n_berth-n_berth_alight 1751 self.ids_berth_alight[id_stop] = ids_berth[0:n_berth_alight] 1752 self.ids_berth_board[id_stop] = ids_berth[n_berth_alight:n_berth] 1753 return id_stop 1754 1755 1756class VehicleAdder(Process): 1757 def __init__(self, vehicles, logger=None, **kwargs): 1758 print 'VehicleAdder.__init__', vehicles, vehicles.parent.get_ident() 1759 self._init_common('vehicleadder', name='Vehicle adder', 1760 logger=logger, 1761 info='Add vehicles to PRT stops of network.', 1762 ) 1763 self._vehicles = vehicles 1764 1765 attrsman = self.set_attrsman(cm.Attrsman(self)) 1766 1767 self.n_vehicles = attrsman.add(cm.AttrConf('n_vehicles', kwargs.get('n_vehicles', -1), 1768 groupnames=['options'], 1769 perm='rw', 1770 name='Number of vehicles', 1771 info='Number of PRT vehicles to be added to the network. Use -1 to fill all present PRT stations.', 1772 )) 1773 1774 def do(self): 1775 # print 'VehicleAdder.do' 1776 self._vehicles.add_to_net(n=self.n_vehicles) 1777 1778 1779class PrtVehicles(am.ArrayObjman): 1780 1781 def __init__(self, ident, prtservices, **kwargs): 1782 # print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1') 1783 self._init_objman(ident=ident, 1784 parent=prtservices, 1785 name='PRT Veh.', 1786 info='PRT vehicle database. These are shared vehicles.', 1787 **kwargs) 1788 1789 self._init_attributes() 1790 1791 def _init_attributes(self): 1792 vtypes = self.get_scenario().demand.vtypes 1793 net = self.get_scenario().net 1794 1795 # TODO: add/update vtypes here 1796 self.add_col(SumoIdsConf('Veh', xmltag='id')) 1797 1798 if not hasattr(self, 'ids_vtype'): 1799 id_vtype = self.make_vtype() 1800 1801 self.add_col(am.IdsArrayConf('ids_vtype', vtypes, 1802 id_default=id_vtype, 1803 groupnames=['state'], 1804 name='Veh. type', 1805 info='PRT vehicle type.', 1806 #xmltag = 'type', 1807 )) 1808 1809 self.add_col(am.ArrayConf('states', default=VEHICLESTATES['init'], 1810 dtype=np.int32, 1811 choices=VEHICLESTATES, 1812 name='state', 1813 info='State of vehicle.', 1814 )) 1815 1816 # self.add_col(am.IdsArrayConf( 'ids_targetprtstop', self.parent.prtstops, 1817 # groupnames = ['parameters'], 1818 # name = 'Target stop ID', 1819 # info = 'ID of current target PRT stop.', 1820 # )) 1821 1822 self.add_col(am.IdsArrayConf('ids_currentedge', net.edges, 1823 groupnames=['state'], 1824 name='Current edge ID', 1825 info='Edge ID of most recent reported position.', 1826 )) 1827 1828 # self.add_col(am.IdsArrayConf( 'ids_targetedge', net.edges, 1829 # groupnames = ['state'], 1830 # name = 'Target edge ID', 1831 # info = 'Target edge ID to be reached. This can be either intermediate target edges (), such as a compressor station.', 1832 # )) 1833 1834 def get_net(self): 1835 return self.parent.get_scenario().net 1836 1837 def make_vtype(self): 1838 id_vtype = self.get_scenario().demand.vtypes.add_vtype('PRT', 1839 accel=2.5, 1840 decel=2.5, 1841 sigma=1.0, 1842 length=3.5, 1843 width=1.6, 1844 height=1.7, 1845 number_persons=1, 1846 capacity_persons=1, 1847 dist_min=0.5, 1848 tau=0.8, 1849 speed_max=10.0, 1850 deviation_speed=0.01, # slight deviation for better following 1851 emissionclass='HBEFA3/zero', 1852 id_mode=self.parent.id_prtmode, # specifies mode for demand 1853 color=np.array((255, 240, 0, 255), np.float32)/255.0, 1854 shape_gui='evehicle', 1855 times_boarding=1.5, 1856 times_loading=20.0, 1857 sublane_alignment_lat='center', 1858 sublane_speed_max_lat=0.5, 1859 sublane_gap_min_lat=0.24, 1860 sublane_alignment_eager=1000000.0, 1861 ) 1862 return id_vtype 1863 1864 def concatenate(self, id_veh, id_veh_pre): 1865 # print 'concatenate prt.%d'%id_veh, 'prt.%d'%id_veh_pre 1866 id_veh_sumo = self.get_id_sumo(id_veh) 1867 traci.vehicle.setSpeedFactor(id_veh_sumo, 2.0) # +random.uniform(-0.01,0.01) 1868 traci.vehicle.setImperfection(id_veh_sumo, 0.0) 1869 traci.vehicle.setAccel(id_veh_sumo, 3.5) 1870 traci.vehicle.setMinGap(id_veh_sumo, 0.01) 1871 traci.vehicle.setTau(id_veh_sumo, 0.2) 1872 1873 def decatenate(self, id_veh): 1874 # print 'decatenate prt.%d'%id_veh 1875 id_veh_sumo = self.get_id_sumo(id_veh) 1876 traci.vehicle.setSpeedFactor(id_veh_sumo, 1.0) # +random.uniform(-0.01,0.01) 1877 traci.vehicle.setMinGap(id_veh_sumo, 0.5) 1878 traci.vehicle.setImperfection(id_veh_sumo, 1.0) 1879 traci.vehicle.setTau(id_veh_sumo, 0.8) 1880 traci.vehicle.setAccel(id_veh_sumo, 2.5) 1881 1882 def prepare_sim(self, process): 1883 print 'PrtVehicles.prepare_sim' 1884 net = self.get_scenario().net 1885 ptstops = net.ptstops 1886 lanes = net.lanes 1887 ids_edge_sumo = net.edges.ids_sumo 1888 ids = self.get_ids() 1889 1890 self.ids_berth = -1*np.ones(np.max(ids)+1, dtype=np.int32) 1891 1892 # for id_veh, id_veh_sumo in zip(ids,self.ids_sumo[ids]): 1893 # traci.vehicle.subscribe(id_veh_sumo, 1894 # [ traci.constants.VAR_ROAD_ID, 1895 # traci.constants.VAR_POSITION, 1896 # traci.constants.VAR_STOPSTATE, 1897 # ]) 1898 return [] # currentlu vehicles are not updated 1899 1900 def process_step(self, process): 1901 # print 'process_step',traci.vehicle.getSubscriptionResults() 1902 pass 1903 # VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6} 1904 1905 def control_slow_down(self, id_veh, speed=1.0, time_slowdown=5): 1906 # print 'control_slow_down',self.get_id_sumo(id_veh) 1907 traci.vehicle.slowDown(self.get_id_sumo(id_veh), speed, time_slowdown) 1908 1909 def control_stop_alight(self, id_veh, id_stop, id_berth, 1910 id_edge_sumo=None, 1911 position=None, 1912 ): 1913 id_veh_sumo = self.get_id_sumo(id_veh) 1914 p = traci.vehicle.getLanePosition(id_veh_sumo) 1915 # print 'control_stop_alight',id_veh_sumo,p,'->',position,'id_berth',id_berth 1916 #d = position - p 1917 #v = traci.vehicle.getSpeed(id_veh_sumo) 1918 #d_save = 1.0/(2*2.5)*(v**2) 1919 # print ' v=',v 1920 # print ' d,d_save',d,d_save 1921 self.states[id_veh] = VEHICLESTATES['forewarding'] 1922 self.ids_berth[id_veh] = id_berth 1923 traci.vehicle.setStop(self.get_id_sumo(id_veh), 1924 id_edge_sumo, 1925 pos=position, 1926 flags=0, 1927 laneIndex=1, 1928 ) 1929 1930 def control_stop_board(self, id_veh, id_stop, id_berth, 1931 id_edge_sumo=None, 1932 position=None, 1933 ): 1934 1935 # print 'control_stop_board',self.get_id_sumo(id_veh),id_stop, id_berth,id_edge_sumo,position 1936 1937 id_veh_sumo = self.get_id_sumo(id_veh) 1938 # print 'control_stop_board',id_veh_sumo,traci.vehicle.getLanePosition(id_veh_sumo),'->',position,id_berth 1939 self.ids_berth[id_veh] = id_berth 1940 self.states[id_veh] = VEHICLESTATES['forewarding'] 1941 # print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:] 1942 if traci.vehicle.isStopped(id_veh_sumo): 1943 traci.vehicle.resume(id_veh_sumo) 1944 1945 traci.vehicle.setStop(id_veh_sumo, 1946 id_edge_sumo, 1947 startPos=position-4.0, 1948 pos=position, 1949 flags=2, # park and trigger 1+2,# 1950 laneIndex=1, 1951 ) 1952 1953 def alight(self, id_veh): 1954 # print 'alight',self.get_id_sumo(id_veh) 1955 # TODO: necessary to keep copy of state? 1956 self.states[id_veh] = VEHICLESTATES['alighting'] 1957 # traci.vehicle.getStopState(self.get_id_sumo(id_veh)) 1958 # VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting' 1959 1960 def board(self, id_veh, id_edge_sumo=None, position=None): 1961 # print 'board',self.get_id_sumo(id_veh) 1962 # TODO: necessary to keep copy of state? 1963 self.states[id_veh] = VEHICLESTATES['boarding'] 1964 #id_veh_sumo = self.get_id_sumo(id_veh) 1965 # print 'board',id_veh_sumo,'stopstate',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:] 1966 # print ' ',dir(traci.vehicle) 1967 # traci.vehicle.getLastStepPersonIDs() 1968 # traci.vehicle.getStopState(self.get_id_sumo(id_veh)) 1969 # VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting' 1970 #traci.vehicle.setRoute(id_veh_sumo, [id_edge_sumo]) 1971 # traci.vehicle.resume(id_veh_sumo) 1972 1973 # traci.vehicle.setStop( self.get_id_sumo(id_veh), 1974 # traci.vehicle.getRoadID(id_veh_sumo), 1975 # pos = traci.vehicle.getLanePosition(id_veh_sumo), 1976 # flags= 2,# 1977 # laneIndex= 1, 1978 # ) 1979 # print 'board ',id_veh_sumo, traci.vehicle.getStopState(id_veh_sumo )# bin(traci.vehicle.getStopState(id_veh_sumo ))[2:] 1980 1981 def set_stop(self, id_veh, id_edge_sumo, stopline): 1982 # print 'set_stop',self.get_id_sumo(id_veh),stopline 1983 traci.vehicle.setStop(self.get_id_sumo(id_veh), 1984 id_edge_sumo, 1985 pos=stopline, 1986 laneIndex=1, 1987 ) 1988 1989 def is_completed_alighting(self, id_veh): 1990 # print 'is_completed_alighting',self.get_id_sumo(id_veh),self.states[id_veh],self.states[id_veh] == VEHICLESTATES['alighting'],traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)),type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh))) 1991 if self.states[id_veh] == VEHICLESTATES['alighting']: 1992 if traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)) == 0: 1993 # print ' id_veh_sumo',self.get_id_sumo(id_veh),'completed alighting' 1994 self.states[id_veh] = VEHICLESTATES['await_forwarding'] 1995 return True 1996 else: 1997 return False 1998 elif self.states[id_veh] == VEHICLESTATES['await_forwarding']: 1999 return True 2000 else: 2001 print 'WARNING: strange vehicle state %s while alighting prt.%d' % (self.states[id_veh], id_veh) 2002 return True 2003 2004 def is_completed_boarding(self, id_veh): 2005 # 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))) 2006 if self.states[id_veh] == VEHICLESTATES['boarding']: 2007 if traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)) == 1: 2008 # print 'is_completed_boarding',self.get_id_sumo(id_veh),'completed boarding' 2009 self.states[id_veh] = VEHICLESTATES['waiting'] 2010 return True 2011 else: 2012 False 2013 2014 else: 2015 return True 2016 2017 def get_veh_if_completed_boarding(self, id_veh): 2018 # print 'get_veh_if_completed_boarding',self.get_id_sumo(id_veh),self.states[id_veh],self.states[id_veh] == VEHICLESTATES['boarding'],traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)),type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh))) 2019 2020 if self.states[id_veh] == VEHICLESTATES['boarding']: 2021 id_veh_sumo = self.get_id_sumo(id_veh) 2022 if traci.vehicle.getPersonNumber(id_veh_sumo) >= 1: 2023 # print 'get_veh_if_completed_boarding',id_veh_sumo,'completed boarding' 2024 self.states[id_veh] = VEHICLESTATES['waiting'] 2025 return id_veh_sumo 2026 else: 2027 return '' 2028 2029 else: 2030 return '' 2031 2032 def init_trip_occupied(self, id_veh, id_edge_sumo, stopline=None): 2033 id_veh_sumo = self.get_id_sumo(id_veh) 2034 # print 'init_trip_occupied',self.get_id_sumo(id_veh),id_edge_sumo, stopline 2035 # print ' current route:',traci.vehicle.getRoute(id_veh_sumo) 2036 self.states[id_veh] = VEHICLESTATES['occupiedtrip'] 2037 2038 # print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:] 2039 if traci.vehicle.isStopped(id_veh_sumo): 2040 traci.vehicle.resume(id_veh_sumo) 2041 #traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest) 2042 #traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest) 2043 if stopline is not None: 2044 traci.vehicle.setStop(id_veh_sumo, 2045 id_edge_sumo, 2046 pos=stopline, 2047 laneIndex=1, 2048 ) 2049 else: 2050 speed_crawl = 1.0 2051 time_accel = 4.0 2052 #traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel) 2053 2054 def init_trip_empty(self, id_veh, id_edge_sumo, stopline=None): 2055 print 'Vehicles.init_trip_empty', self.get_id_sumo(id_veh), id_edge_sumo, stopline 2056 self.states[id_veh] = VEHICLESTATES['emptytrip'] 2057 id_veh_sumo = self.get_id_sumo(id_veh) 2058 if traci.vehicle.isStopped(id_veh_sumo): 2059 traci.vehicle.resume(id_veh_sumo) 2060 #traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to) 2061 if stopline is not None: 2062 # if stopline>=0: 2063 # print ' Route=',traci.vehicle.getRoute(id_veh_sumo) 2064 print ' Position=', traci.vehicle.getLanePosition(id_veh_sumo), stopline 2065 # print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:] 2066 2067 traci.vehicle.setStop(id_veh_sumo, 2068 id_edge_sumo, 2069 pos=stopline, 2070 laneIndex=1, 2071 ) 2072 else: 2073 speed_crawl = 1.0 2074 time_accel = 4.0 2075 #traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel) 2076 2077 def reschedule_trip(self, id_veh, id_edge_sumo_to=None, route_sumo=None): 2078 # print 'reschedule_trip',self.get_id_sumo(id_veh),id_edge_sumo_to,route_sumo 2079 id_veh_sumo = self.get_id_sumo(id_veh) 2080 if traci.vehicle.isStopped(id_veh_sumo): 2081 traci.vehicle.resume(id_veh_sumo) 2082 2083 if route_sumo is not None: 2084 # set entire route 2085 traci.vehicle.setRoute(id_veh_sumo, route_sumo) 2086 else: 2087 # set new target and let SUMO do the routing 2088 traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to) 2089 2090 # 2091 traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0) 2092 2093 def add_to_net(self, n=-1, length_veh_av=4.0): 2094 """ 2095 Add n PRT vehicles to network 2096 If n = -1 then fill up stops with vehicles. 2097 """ 2098 # print 'PrtVehicles.make',n,length_veh_av 2099 # self.clear() 2100 net = self.get_scenario().net 2101 ptstops = net.ptstops 2102 prtstops = self.parent.prtstops 2103 lanes = net.lanes 2104 ids_prtstop = prtstops.get_ids() 2105 ids_ptstop = prtstops.ids_ptstop[ids_prtstop] 2106 ids_veh = [] 2107 n_stop = len(prtstops) 2108 2109 for id_prt, id_edge, pos_from, pos_to in zip( 2110 ids_prtstop, 2111 lanes.ids_edge[ptstops.ids_lane[ids_ptstop]], 2112 ptstops.positions_from[ids_ptstop], 2113 ptstops.positions_to[ids_ptstop], 2114 ): 2115 # TODO: here we can select depos or distribute a 2116 # fixed number of vehicles or put them into berth 2117 # print ' ',pos_to,pos_from,int((pos_to-pos_from)/length_veh_av) 2118 if n > 0: 2119 n_veh_per_stop = int(float(n)/n_stop+0.5) 2120 else: 2121 n_veh_per_stop = int((pos_to-pos_from)/length_veh_av) 2122 # print ' n,n_stop,n_veh_per_stop',n,n_stop,n_veh_per_stop 2123 for i in range(n_veh_per_stop): 2124 id_veh = self.add_row(ids_stop_target=id_prt, 2125 ids_currentedge=id_edge, 2126 ) 2127 2128 self.ids_sumo[id_veh] = self.get_id_sumo(id_veh) 2129 ids_veh.append(id_veh) 2130 2131 return ids_veh 2132 2133 # def write_veh 2134 # 2135 2136 def get_scenario(self): 2137 return self.parent.get_scenario() 2138 2139 def get_vtypes(self): 2140 """ 2141 Returns a set with all used PRT vehicle types. 2142 """ 2143 # print 'Vehicles_individual.get_vtypes',self.cols.vtype 2144 return set(self.ids_vtype.get_value()) 2145 2146 def get_id_sumo(self, id_veh): 2147 return 'prt.%s' % (id_veh) 2148 2149 def get_id_from_id_sumo(self, id_veh_sumo): 2150 if len(id_veh_sumo.split('.')) == 2: 2151 prefix, id_veh = id_veh_sumo.split('.') 2152 if prefix == 'prt': 2153 return int(id_veh) 2154 else: 2155 return -1 2156 return -1 2157 2158 def get_ids_from_ids_sumo(self, ids_veh_sumo): 2159 n = len(ids_veh_sumo) 2160 ids = np.zeros(n, np.int32) 2161 for i in xrange(n): 2162 ids[i] = self.get_id_from_id_sumo(ids_veh_sumo[i]) 2163 return ids 2164 2165 def get_id_line_xml(self): 2166 return 'prt' 2167 2168 2169class PrtStrategy(StrategyMixin): 2170 def __init__(self, ident, parent=None, 2171 name='Personal Rapid Transit Strategy', 2172 info='With this strategy, the person uses Personla Rapid Transit as main transport mode.', 2173 **kwargs): 2174 2175 self._init_objman(ident, parent, name=name, info=info, **kwargs) 2176 attrsman = self.set_attrsman(cm.Attrsman(self)) 2177 # specific init 2178 self._init_attributes() 2179 self._init_constants() 2180 2181 def _init_attributes(self): 2182 # print 'StrategyMixin._init_attributes' 2183 pass 2184 2185 def _init_constants(self): 2186 #virtualpop = self.get_virtualpop() 2187 #stagetables = virtualpop.get_stagetables() 2188 2189 #self._walkstages = stagetables.get_stagetable('walks') 2190 #self._ridestages = stagetables.get_stagetable('rides') 2191 #self._activitystages = stagetables.get_stagetable('activities') 2192 2193 #self._plans = virtualpop.get_plans() 2194 # 2195 # print 'AutoStrategy._init_constants' 2196 # print dir(self) 2197 # self.get_attrsman().do_not_save_attrs(['_activitystages','_ridestages','_walkstages','_plans']) 2198 2199 modes = self.get_virtualpop().get_scenario().net.modes 2200 self._id_mode_bike = modes.get_id_mode('bicycle') 2201 self._id_mode_auto = modes.get_id_mode('passenger') 2202 self._id_mode_moto = modes.get_id_mode('motorcycle') 2203 self._id_mode_bus = modes.get_id_mode('bus') 2204 self.get_attrsman().do_not_save_attrs([ 2205 '_id_mode_bike', '_id_mode_auto', '_id_mode_moto', '_id_mode_bus' 2206 ]) 2207 2208 def set_prtservice(self, prtservice): 2209 #self.add( cm.ObjConf( prtservice, is_child = False,groups = ['_private'])) 2210 self.prtservice = prtservice 2211 self.get_attrsman().do_not_save_attrs(['prtservice']) 2212 2213 def preevaluate(self, ids_person): 2214 """ 2215 Preevaluation strategies for person IDs in vector ids_person. 2216 2217 Returns a preevaluation vector with a preevaluation value 2218 for each person ID. The values of the preevaluation vector are as follows: 2219 -1 : Strategy cannot be applied 2220 0 : Stategy can be applied, but the preferred mode is not used 2221 1 : Stategy can be applied, and preferred mode is part of the strategy 2222 2 : Strategy uses predomunantly preferred mode 2223 2224 """ 2225 n_pers = len(ids_person) 2226 persons = self.get_virtualpop() 2227 preeval = np.zeros(n_pers, dtype=np.int32) 2228 2229 # TODO: here we could exclude by age or distance facilities-stops 2230 2231 # put 0 for persons whose preference is not public transport 2232 preeval[persons.ids_mode_preferred[ids_person] != self.prtservice.id_prtmode] = 0 2233 2234 # put 2 for persons with car access and who prefer cars 2235 preeval[persons.ids_mode_preferred[ids_person] == self.prtservice.id_prtmode] = 2 2236 2237 print ' PrtStrategy.preevaluate', len(np.flatnonzero(preeval)) 2238 return preeval 2239 2240 def plan(self, ids_person, logger=None): 2241 """ 2242 Generates a plan for these person according to this strategie. 2243 Overriden by specific strategy. 2244 """ 2245 print 'PrtStrategy.pan', len(ids_person) 2246 #make_plans_private(self, ids_person = None, mode = 'passenger') 2247 # routing necessary? 2248 virtualpop = self.get_virtualpop() 2249 scenario = virtualpop.get_scenario() 2250 plans = virtualpop.get_plans() # self._plans 2251 demand = scenario.demand 2252 #ptlines = demand.ptlines 2253 2254 walkstages = plans.get_stagetable('walks') 2255 prtstages = plans.get_stagetable('prttransits') 2256 activitystages = plans.get_stagetable('activities') 2257 2258 activities = virtualpop.get_activities() 2259 activitytypes = demand.activitytypes 2260 prtstops = self.prtservice.prtstops 2261 2262 net = scenario.net 2263 edges = net.edges 2264 lanes = net.lanes 2265 modes = net.modes 2266 landuse = scenario.landuse 2267 facilities = landuse.facilities 2268 2269 times_est_plan = plans.times_est 2270 # here we can determine edge weights for different modes 2271 2272 # this could be centralized to avoid redundance 2273 plans.prepare_stagetables(['walks', 'prttransits', 'activities']) 2274 # must be after preparation: 2275 times_stop_to_stop = self.prtservice.times_stop_to_stop 2276 2277 ids_person_act, ids_act_from, ids_act_to\ 2278 = virtualpop.get_activities_from_pattern(0, ids_person=ids_person) 2279 2280 if len(ids_person_act) == 0: 2281 print 'WARNING in TrasitStrategy.plan: no eligible persons found.' 2282 return False 2283 2284 # temporary maps from ids_person to other parameters 2285 nm = np.max(ids_person_act)+1 2286 map_ids_plan = np.zeros(nm, dtype=np.int32) 2287 #ids_plan_act = virtualpop.add_plans(ids_person_act, id_strategy = self.get_id_strategy()) 2288 map_ids_plan[ids_person_act] = virtualpop.add_plans(ids_person_act, id_strategy=self.get_id_strategy()) 2289 2290 map_times = np.zeros(nm, dtype=np.int32) 2291 map_times[ids_person_act] = activities.get_times_end(ids_act_from, pdf='unit') 2292 2293 # set start time to plans (important!) 2294 plans.times_begin[map_ids_plan[ids_person_act]] = map_times[ids_person_act] 2295 2296 map_ids_fac_from = np.zeros(nm, dtype=np.int32) 2297 map_ids_fac_from[ids_person_act] = activities.ids_facility[ids_act_from] 2298 2299 n_plans = len(ids_person_act) 2300 print 'TrasitStrategy.plan n_plans=', n_plans 2301 2302 # make initial activity stage 2303 ids_edge_from = facilities.ids_roadedge_closest[map_ids_fac_from[ids_person_act]] 2304 poss_edge_from = facilities.positions_roadedge_closest[map_ids_fac_from[ids_person_act]] 2305 # this is the time when first activity starts 2306 # first activity is normally not simulated 2307 2308 names_acttype_from = activitytypes.names[activities.ids_activitytype[ids_act_from]] 2309 durations_act_from = activities.get_durations(ids_act_from) 2310 times_from = map_times[ids_person_act]-durations_act_from 2311 #times_from = activities.get_times_end(ids_act_from, pdf = 'unit') 2312 2313 for id_plan,\ 2314 time,\ 2315 id_act_from,\ 2316 name_acttype_from,\ 2317 duration_act_from,\ 2318 id_edge_from,\ 2319 pos_edge_from \ 2320 in zip(map_ids_plan[ids_person_act], 2321 times_from, 2322 ids_act_from, 2323 names_acttype_from, 2324 durations_act_from, 2325 ids_edge_from, 2326 poss_edge_from): 2327 2328 id_stage_act, time = activitystages.append_stage( 2329 id_plan, time, 2330 ids_activity=id_act_from, 2331 names_activitytype=name_acttype_from, 2332 durations=duration_act_from, 2333 ids_lane=edges.ids_lanes[id_edge_from][0], 2334 positions=pos_edge_from, 2335 ) 2336 2337 ## 2338 2339 ind_act = 0 2340 2341 # main loop while there are persons performing 2342 # an activity at index ind_act 2343 while len(ids_person_act) > 0: 2344 ids_plan = map_ids_plan[ids_person_act] 2345 2346 times_from = map_times[ids_person_act] 2347 2348 names_acttype_to = activitytypes.names[activities.ids_activitytype[ids_act_to]] 2349 durations_act_to = activities.get_durations(ids_act_to) 2350 2351 ids_fac_from = map_ids_fac_from[ids_person_act] 2352 ids_fac_to = activities.ids_facility[ids_act_to] 2353 2354 centroids_from = facilities.centroids[ids_fac_from] 2355 centroids_to = facilities.centroids[ids_fac_to] 2356 2357 # origin edge and position 2358 ids_edge_from = facilities.ids_roadedge_closest[ids_fac_from] 2359 poss_edge_from = facilities.positions_roadedge_closest[ids_fac_from] 2360 2361 # destination edge and position 2362 ids_edge_to = facilities.ids_roadedge_closest[ids_fac_to] 2363 poss_edge_to = facilities.positions_roadedge_closest[ids_fac_to] 2364 2365 # find closest prt stop!! 2366 ids_stop_from, ids_stopedge_from = prtstops.get_closest(centroids_from) 2367 ids_stop_to, ids_stopedge_to = prtstops.get_closest(centroids_to) 2368 2369 poss_stop_from = prtstops.get_waitpositions(ids_stop_from, is_alight=False, offset=-0.5) 2370 poss_stop_to = prtstops.get_waitpositions(ids_stop_to, is_alight=True, offset=-0.5) 2371 2372 i = 0.0 2373 for id_person, id_plan, time_from, id_act_from, id_act_to, name_acttype_to, duration_act_to, id_edge_from, pos_edge_from, id_edge_to, pos_edge_to, id_stop_from, id_stopedge_from, pos_stop_from, id_stop_to, id_stopedge_to, pos_stop_to\ 2374 in zip(ids_person_act, ids_plan, times_from, ids_act_from, ids_act_to, names_acttype_to, durations_act_to, ids_edge_from, poss_edge_from, ids_edge_to, poss_edge_to, ids_stop_from, ids_stopedge_from, poss_stop_from, ids_stop_to, ids_stopedge_to, poss_stop_to): 2375 n_pers = len(ids_person_act) 2376 if logger: 2377 logger.progress(i/n_pers*100) 2378 i += 1.0 2379 print 79*'_' 2380 print ' id_plan=%d, id_person=%d, ' % (id_plan, id_person) 2381 2382 id_stage_walk1, time = walkstages.append_stage(id_plan, time_from, 2383 id_edge_from=id_edge_from, 2384 position_edge_from=pos_edge_from, 2385 id_edge_to=id_stopedge_from, 2386 position_edge_to=pos_stop_from, # -7.0, 2387 ) 2388 2389 # take PRT 2390 # self.ids_edge_to_ids_prtstop 2391 id_stage_transit, time = prtstages.append_stage( 2392 id_plan, time, 2393 duration=times_stop_to_stop[id_stop_from, id_stop_to], 2394 id_fromedge=id_stopedge_from, 2395 id_toedge=id_stopedge_to, 2396 ) 2397 2398 # walk from final prtstop to activity 2399 # print ' Stage for linktype %2d fromedge %s toedge %s'%(linktype, edges.ids_sumo[id_stopedge_to],edges.ids_sumo[id_edge_to] ) 2400 id_stage_walk2, time = walkstages.append_stage(id_plan, time, 2401 id_edge_from=id_stopedge_to, 2402 position_edge_from=pos_stop_to, 2403 id_edge_to=id_edge_to, 2404 position_edge_to=pos_edge_to, 2405 ) 2406 2407 # update time for trips estimation for this plan 2408 plans.times_est[id_plan] += time-time_from 2409 2410 # define current end time without last activity duration 2411 plans.times_end[id_plan] = time 2412 2413 id_stage_act, time = activitystages.append_stage( 2414 id_plan, time, 2415 ids_to=id_act_to, 2416 names_totype=name_acttype_to, 2417 durations=duration_act_to, 2418 ids_lane=edges.ids_lanes[id_edge_to][0], 2419 positions=pos_edge_to, 2420 ) 2421 2422 # store time for next iteration in case other activities are 2423 # following 2424 map_times[id_person] = time 2425 2426 # select persons and activities for next setp 2427 ind_act += 1 2428 ids_person_act, ids_act_from, ids_act_to\ 2429 = virtualpop.get_activities_from_pattern(ind_act, ids_person=ids_person_act) 2430 2431 2432class PrtTransits(StageTypeMixin): 2433 def __init__(self, ident, stages, 2434 name='Ride on PRT', 2435 info='Ride on Personal Rapid Transit network.', 2436 # **kwargs, 2437 ): 2438 2439 print 'PrtTransits.__init__', ident, stages 2440 self.init_stagetable(ident, 2441 stages, name=name, 2442 info=info, 2443 ) 2444 self._init_attributes() 2445 self._init_constants() 2446 2447 def _init_attributes(self): 2448 edges = self.get_virtualpop().get_net().edges 2449 2450 self.add_col(am.IdsArrayConf('ids_fromedge', edges, 2451 groupnames=['parameters'], 2452 name='Edge ID from', 2453 info='Edge ID of departure PRT station.', 2454 )) 2455 2456 self.add_col(am.IdsArrayConf('ids_toedge', edges, 2457 groupnames=['parameters'], 2458 name='Edge ID to', 2459 info='Edge ID of destination PRT station.', 2460 )) 2461 2462 def set_prtservice(self, prtservice): 2463 self.add(cm.ObjConf(prtservice, is_child=False, groups=['_private'])) 2464 2465 def get_prtservice(self): 2466 return self.prtservice.get_value() 2467 2468 def prepare_planning(self): 2469 2470 prtservice = self.get_prtservice() 2471 print 'prttransits.prepare_planning', prtservice.times_stop_to_stop 2472 if prtservice.times_stop_to_stop is None: 2473 prtservice.make_times_stop_to_stop() 2474 print prtservice.times_stop_to_stop 2475 2476 def append_stage(self, id_plan, time_start=-1.0, 2477 duration=0.0, 2478 id_fromedge=-1, id_toedge=-1, **kwargs): 2479 """ 2480 Appends a PRT transit stage to plan id_plan. 2481 2482 """ 2483 # print 'PrtTransits.append_stage',id_stage 2484 2485 id_stage, time_end = StageTypeMixin.append_stage(self, 2486 id_plan, 2487 time_start, 2488 durations=duration, 2489 ids_fromedge=id_fromedge, 2490 ids_toedge=id_toedge, 2491 ) 2492 2493 # add this stage to the vehicle database 2494 # ind_ride gives the index of this ride (within the same plan??) 2495 #ind_ride = self.parent.get_individualvehicles().append_ride(id_veh, id_stage) 2496 return id_stage, time_end 2497 2498 def to_xml(self, id_stage, fd, indent=0): 2499 # <ride from="1/3to0/3" to="0/4to1/4" lines="train0"/> 2500 net = self.get_virtualpop().get_net() 2501 #ids_stoplane = net.ptstops.ids_lane 2502 #ids_laneedge = net.lanes.ids_edge 2503 ids_sumoedge = net.edges.ids_sumo 2504 2505 #ind = self.get_ind(id_stage) 2506 fd.write(xm.start('ride', indent=indent)) 2507 fd.write(xm.num('from', ids_sumoedge[self.ids_fromedge[id_stage]])) 2508 fd.write(xm.num('to', ids_sumoedge[self.ids_toedge[id_stage]])) 2509 fd.write(xm.num('lines', 'prt')) 2510 # if self.cols.pos_edge_from[ind]>0: 2511 # fd.write(xm.num('departPos', self.cols.pos_edge_from[ind])) 2512 # if self.cols.pos_edge_to[ind]>0: 2513 # fd.write(xm.num('arrivalPos', self.cols.pos_edge_to[ind])) 2514 2515 fd.write(xm.stopit()) # ends stage 2516 2517 2518class VehicleMan(am.ArrayObjman): 2519 def __init__(self, ident, prtservices, **kwargs): 2520 self._init_objman(ident=ident, 2521 parent=prtservices, 2522 name='PRT vehicle management', 2523 info='PRT vehicle management.', 2524 #xmltag = ('additional','busStop','stopnames'), 2525 version=0.0, 2526 **kwargs) 2527 2528 self._init_attributes() 2529 self._init_constants() 2530 2531 def _init_attributes(self): 2532 self.add(cm.AttrConf('time_update', 2.0, 2533 groupnames=['parameters'], 2534 name='Man. update time', 2535 info="Update time for vehicle management.", 2536 unit='s', 2537 )) 2538 2539 # self.time_update.set(5.0) 2540 2541 self.add(cm.AttrConf('time_update_flows', 10.0, 2542 groupnames=['parameters'], 2543 name='Flow update time', 2544 info="Update time for flow estimations.", 2545 unit='s', 2546 )) 2547 # self.time_update.set(10.0) 2548 # if hasattr(self,'time_flowaverage'): 2549 # self.delete('time_flowaverage') 2550 2551 self.add(cm.AttrConf('time_est_max', 1200, 2552 groupnames=['parameters'], 2553 name='prediction interval', 2554 info="Prediction time range of vehicle management.", 2555 unit='s', 2556 )) 2557 2558 self.add(cm.AttrConf('time_search_occupied', 10.0, 2559 groupnames=['parameters'], 2560 name='Occupied search time', 2561 info="Time interval for search of optimum departure time in case of an occupied vehicle trip.", 2562 unit='s', 2563 )) 2564 2565 self.add(cm.AttrConf('time_search_empty', 20.0, 2566 groupnames=['parameters'], 2567 name='Empty search time', 2568 info="Time interval for search of optimum departure time in case of an empty vehicle trip.", 2569 unit='s', 2570 )) 2571 2572 self.add(cm.AttrConf('weight_demand', 0.01, 2573 groupnames=['parameters'], 2574 name='Demand weight', 2575 info="Weight of current demand at stations when assigning empty vehicles trips.", 2576 )) 2577 2578 self.add(cm.AttrConf('weight_flow', 1.0, 2579 groupnames=['parameters'], 2580 name='Flow weight', 2581 info="Weight of flows (changes in demand over time) at stations when assigning empty vehicles trips.", 2582 )) 2583 2584 self.add(cm.AttrConf('constant_timeweight', 0.005, 2585 groupnames=['parameters'], 2586 name='Time weight const.', 2587 info="Constant for the exponential decay function weighting the time instance in the optimization function.", 2588 unit='1/s', 2589 )) 2590 2591 # def set_stops(self,vehicleman): 2592 # self.add( cm.ObjConf( stops, is_child = False,groups = ['_private'])) 2593 2594 def get_stops(self): 2595 return self.parent.prtstops 2596 2597 def get_vehicles(self): 2598 return self.parent.prtvehicles 2599 2600 def get_scenario(self): 2601 return self.parent.parent.get_scenario() 2602 2603 def prepare_sim(self, process): 2604 print 'VehicleMan.prepare_sim' 2605 net = self.get_scenario().net 2606 # station management 2607 # self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1,dtype = np.object) 2608 2609 self.ids_stop = self.get_stops().get_ids() 2610 n_stoparray = np.max(self.ids_stop)+1 2611 self.numbers_veh_arr = np.zeros(n_stoparray, dtype=np.int32) 2612 2613 self.n_est_max = self.time_est_max.get_value()/self.time_update_flows.get_value() 2614 self.inflows_sched = np.zeros((n_stoparray, self.n_est_max), dtype=np.int32) 2615 self.inflows_person = np.zeros(n_stoparray, dtype=np.int32) 2616 self.inflows_person_last = np.zeros(n_stoparray, dtype=np.int32) 2617 # vehicle management 2618 self.ids_veh = self.get_vehicles().get_ids() 2619 n_veharray = np.max(self.ids_veh)+1 2620 2621 # could go in vehicle array 2622 self.ids_stop_target = -1*np.ones(n_veharray, dtype=np.int32) 2623 self.ids_stop_current = -1*np.ones(n_veharray, dtype=np.int32) 2624 self.times_order = 10**6*np.ones(n_veharray, dtype=np.int32) 2625 # self.occupiedtrips_new = []#?? put this is also in general time scheme with more urgency?? 2626 #self.emptytrips_new = [] 2627 2628 # from veh arrays 2629 #self.are_emptytrips = np.zeros(n_veharray, dtype = np.bool) 2630 2631 # logging 2632 results = process.get_results() 2633 if results is not None: 2634 time_update_flows = self.time_update_flows.get_value() 2635 n_timesteps = int((process.duration-process.time_warmup)/time_update_flows+1) 2636 results.prtstopresults.init_recording(n_timesteps, time_update_flows) 2637 2638 self.log_inflows_temp = np.zeros(n_stoparray, dtype=np.int32) 2639 2640 return [(self.time_update.get_value(), self.process_step), 2641 (self.time_update_flows.get_value(), self.update_flows), 2642 ] 2643 2644 def update_flows(self, process): 2645 # print 'update flow prediction' 2646 self.inflows_sched[:, 0] = 0 2647 self.inflows_sched = np.roll(self.inflows_sched, -1) 2648 time_update_flows = self.time_update_flows.get_value() 2649 2650 if process.simtime > process.time_warmup: 2651 stops = self.get_stops() 2652 ids_stop = self.ids_stop 2653 prtstopresults = process.get_results().prtstopresults 2654 const_time = 1.0/time_update_flows # np.array([1.0/time_update_flows],dtype=np.float32) 2655 timestep = (process.simtime - process.simtime_start - process.time_warmup)/time_update_flows 2656 prtstopresults.record(timestep, ids_stop, 2657 inflows_veh=np.array(const_time * self.log_inflows_temp[ids_stop], dtype=np.float32), 2658 inflows_veh_sched=np.array( 2659 const_time * self.inflows_sched[ids_stop, 0], dtype=np.float32), 2660 numbers_person_wait=stops.numbers_person_wait[ids_stop], 2661 waittimes_tot=stops.waittimes_tot[ids_stop], 2662 inflows_person=np.array(const_time * self.inflows_person[ids_stop], dtype=np.float32), 2663 #inflows_person = stops.flows_person[ids_stop], 2664 ) 2665 2666 self.inflows_person_last = self.inflows_person.copy() 2667 self.inflows_person[:] = 0 2668 self.log_inflows_temp[:] = 0 2669 2670 def process_step(self, process): 2671 print 79*'M' 2672 print 'VehicleMan.process_step' 2673 2674 stops = self.get_stops() 2675 #vehicles = self.get_vehicles() 2676 2677 has_programmed = True 2678 while has_programmed: 2679 has_programmed = False 2680 ids_veh_lead = stops.ids_veh_lead[self.ids_stop] 2681 inds_valid = np.flatnonzero(ids_veh_lead >= 0) 2682 if len(inds_valid) > 0: 2683 has_programmed |= self.push_occupied_leadvehs(ids_veh_lead[inds_valid], process) 2684 has_programmed |= self.push_empty_leadvehs(ids_veh_lead[inds_valid], process) 2685 has_programmed |= self.pull_empty_leadvehs(ids_veh_lead[inds_valid], process) 2686 else: 2687 # no more leaders 2688 has_programmed = False 2689 # print '\n terminated vehicle man n_est_max',self.n_est_max 2690 # print ' inflows_sched=\n',self.inflows_sched 2691 2692 def note_person_entered(self, id_stop, id_person_sumo, id_stop_dest): 2693 # here just estimate person flows 2694 self.inflows_person[id_stop] += 1 2695 2696 def push_occupied_leadvehs(self, ids_veh_lead, process): 2697 n_timeslot_offset = 3 2698 n_searchint = int(self.time_search_occupied.get_value()/self.time_update_flows.get_value()+0.5) 2699 stops = self.get_stops() 2700 vehicles = self.get_vehicles() 2701 2702 inds_valid = np.flatnonzero(vehicles.states[ids_veh_lead] == VEHICLESTATES['occupiedtrip']) 2703 if len(inds_valid) == 0: 2704 return False 2705 # print 'push_occupied_leadvehs ids_veh_lead',ids_veh_lead[inds_valid] 2706 times_stop_to_stop = self.parent.times_stop_to_stop 2707 ids_stop_current = self.ids_stop_current[ids_veh_lead[inds_valid]] 2708 ids_stop_target = self.ids_stop_target[ids_veh_lead[inds_valid]] 2709 durations_est = times_stop_to_stop[ids_stop_current, ids_stop_target] 2710 # print ' duration_est, t_est_max',durations_est,self.n_est_max*self.time_update_flows.get_value() 2711 2712 inds_time_min = n_timeslot_offset+np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value( 2713 ), dtype=np.int32), 0, self.n_est_max-n_searchint-n_timeslot_offset), dtype=np.int32) 2714 inds_time_max = inds_time_min+n_searchint 2715 # print ' inds_time_min unclipped',n_timeslot_offset+np.array(1.0*durations_est/self.time_update_flows.get_value(),dtype=np.int32) 2716 # print ' inds_time_min clipped',inds_time_min 2717 # print ' inds_time_max',inds_time_max, self.inflows_sched.shape 2718 2719 for id_veh_lead, state, id_stop_current, id_stop_target, time_order, ind_min, ind_max, duration_est\ 2720 in zip( 2721 ids_veh_lead[inds_valid], 2722 vehicles.states[ids_veh_lead[inds_valid]], 2723 self.ids_stop_current[ids_veh_lead[inds_valid]], 2724 self.ids_stop_target[ids_veh_lead[inds_valid]], 2725 self.times_order[ids_veh_lead[inds_valid]], 2726 inds_time_min, 2727 inds_time_max, 2728 durations_est, 2729 ): 2730 2731 # print ' check veh',id_veh_lead, state, 'id_stop_current',id_stop_current, 'id_stop_target',id_stop_target 2732 2733 #VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6} 2734 # if state == VEHICLESTATES['occupiedtrip']: 2735 2736 #ids_stop = list(self.ids_stop) 2737 # ids_stop.remove(id_stop) 2738 #costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop]-self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop,ids_stop] 2739 #ids_stop [np.argmax(costs)] 2740 inds_time = np.arange(ind_min, ind_max) 2741 costs = self.inflows_sched[id_stop_target, inds_time] 2742 # print ' inds_time',inds_time 2743 # print ' inflows_sched',costs 2744 ind_time_depart = inds_time[np.argmin(costs)] 2745 2746 time_depart = process.simtime + ind_time_depart*self.time_update_flows.get_value()-duration_est 2747 # print ' ind_time_depart, time_arr, duration_est',ind_time_depart,process.simtime + ind_time_depart*self.time_update_flows.get_value(),duration_est 2748 # print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order 2749 2750 stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart) 2751 self.numbers_veh_arr[id_stop_target] += 1 2752 self.inflows_sched[id_stop_target, ind_time_depart] += 1 2753 2754 return True # at least one vehicle assigned 2755 2756 def push_empty_leadvehs(self, ids_veh_lead, process): 2757 n_timeslot_offset = 3 2758 stops = self.get_stops() 2759 vehicles = self.get_vehicles() 2760 inds_valid = np.flatnonzero(vehicles.states[ids_veh_lead] == VEHICLESTATES['emptytrip']) 2761 if len(inds_valid) == 0: 2762 return False 2763 2764 # print 'push_empty_leadvehs ids_veh_lead',ids_veh_lead[inds_valid] 2765 times_stop_to_stop = self.parent.times_stop_to_stop 2766 ids_stop_current = self.ids_stop_current[ids_veh_lead[inds_valid]] 2767 2768 n_stop_target = len(self.ids_stop) 2769 ids_stop_target = self.ids_stop.reshape(n_stop_target, 1) 2770 flow_person_est = (stops.flows_person[ids_stop_target] * 2771 self.time_update_flows.get_value()).reshape(n_stop_target, 1) 2772 n_searchint = int(self.time_search_empty.get_value()/self.time_update_flows.get_value()+0.5) 2773 inds_search_base = n_timeslot_offset + \ 2774 np.arange(n_searchint, dtype=np.int32) * np.ones((n_stop_target, n_searchint), dtype=np.int32) 2775 2776 #self.numbers_veh = np.zeros(np.max(ids)+1, dtype = np.int32) 2777 #self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype = np.int32) 2778 #self.flows_person = np.zeros(np.max(ids)+1, dtype = np.float32) 2779 #self.ids_veh_lead = -1*np.ones(np.max(ids)+1,dtype = np.int32) 2780 #self.ids_vehs_prog = np.zeros(np.max(ids)+1,dtype = np.object) 2781 is_started = False 2782 for id_veh_lead, id_stop_current, time_order, \ 2783 in zip( 2784 ids_veh_lead[inds_valid], 2785 self.ids_stop_current[ids_veh_lead[inds_valid]], 2786 self.times_order[ids_veh_lead[inds_valid]], 2787 ): 2788 2789 #id_stop_target = self.get_stop_emptytrip(id_stop_current) 2790 2791 durations_est = times_stop_to_stop[id_stop_current, ids_stop_target] 2792 ind_stop_current = np.flatnonzero(durations_est == 0)[0] 2793 # print ' check veh',id_veh_lead, 'id_stop_current',id_stop_current,'ind_stop_current',ind_stop_current 2794 inds_time_min = np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value(), 2795 dtype=np.int32), 0, self.n_est_max-n_searchint), dtype=np.int32) 2796 inds_search = inds_search_base + inds_time_min.reshape(n_stop_target, 1) 2797 timeweight = np.exp(-self.constant_timeweight.get_value() * inds_search*self.time_update_flows.get_value()) 2798 2799 # print ' demand',stops.numbers_person_wait[ids_stop_target] 2800 if 0: 2801 print ' waittimes_tot', stops.waittimes_tot[ids_stop_target] 2802 print ' numbers_person_wait', stops.numbers_person_wait[ids_stop_target] 2803 print ' flow_person_est', flow_person_est 2804 print ' inflows_sched', self.inflows_sched[ids_stop_target, inds_search] 2805 print ' delta flow', (flow_person_est-self.inflows_sched[ids_stop_target, inds_search]) 2806 print ' demandcomp', self.weight_demand.get_value() * stops.numbers_person_wait[ids_stop_target] 2807 print ' flowcomp', self.weight_flow.get_value( 2808 ) * (flow_person_est-self.inflows_sched[ids_stop_target, inds_search]) 2809 2810 print ' flow_person_est', flow_person_est 2811 2812 # costs = ( self.weight_demand.get_value() * stops.waittimes_tot[ids_stop_target]\ 2813 # + self.weight_flow.get_value() * (flow_person_est-self.inflows_sched[ids_stop_target, inds_search])\ 2814 # )* timeweight 2815 costs = (self.weight_demand.get_value() * (stops.numbers_person_wait[ids_stop_target]) 2816 + self.weight_flow.get_value() * (flow_person_est-self.inflows_sched[ids_stop_target, inds_search]) 2817 ) * timeweight 2818 2819 #costs = np.exp(+self.inflows_sched[ids_stop_target, inds_search]-flow_person_est)*timeweight 2820 #costs = (self.inflows_sched[ids_stop_target, inds_search]-flow_person_est)*timeweight 2821 costs[ind_stop_current, :] = -999999 2822 if 0: 2823 # print ' flow_person_est',flow_person_#est 2824 print ' timeweight', timeweight 2825 print ' durations_est', durations_est 2826 print ' inds_search_base', inds_search_base 2827 print ' inds_search unclipped\n', inds_search_base + \ 2828 np.array(1.0*durations_est/self.time_update_flows.get_value(), 2829 dtype=np.int32).reshape(n_stop_target, 1) 2830 print ' inds_search clipped \n', inds_search 2831 print ' inds_time_min', inds_time_min 2832 print ' ind_stop_current', ind_stop_current, durations_est[ind_stop_current] 2833 print ' costs=\n', costs 2834 # constant_timeweight 2835 2836 # 2837 ind_target = np.argmax(costs) 2838 ind_stop_target = ind_target/n_searchint 2839 #ind_time_arrive = ind_target%n_searchint+inds_time_min[ind_stop_target] 2840 ind_time_delta = ind_target % n_searchint 2841 ind_time_arrive = inds_search[ind_stop_target, ind_time_delta] 2842 if 0: 2843 print ' ind_target,n_searchint,ind_stop_target,ind_time_delta', ind_target, n_searchint, ind_target/n_searchint, ind_time_delta 2844 print ' ind_delta_depart,c_min', costs[ind_stop_target, ind_time_delta] 2845 print ' inds_time_min,ind_time_arrive', inds_time_min[ind_stop_target], ind_time_arrive 2846 2847 id_stop_target = ids_stop_target[ind_stop_target][0] 2848 time_depart = process.simtime + ind_time_arrive * \ 2849 self.time_update_flows.get_value()-durations_est[ind_stop_target] 2850 # print '\n id_stop_target',id_stop_target 2851 # print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order 2852 2853 stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart) 2854 is_started = True 2855 2856 self.numbers_veh_arr[id_stop_target] += 1 2857 self.inflows_sched[id_stop_target, ind_time_arrive] += 1 2858 2859 return is_started 2860 2861 def pull_empty_leadvehs(self, ids_veh_lead, process): 2862 2863 n_timeslot_offset = 2 2864 2865 #self.numbers_veh = np.zeros(np.max(ids)+1, dtype = np.int32) 2866 #self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype = np.int32) 2867 2868 # inds_valid = np.flatnonzero( (vehicles.states[ids_veh_lead] == VEHICLESTATES['waiting'])\ 2869 # & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0)) 2870 # print 'pull_empty_leadvehs' 2871 stops = self.get_stops() 2872 vehicles = self.get_vehicles() 2873 times_stop_to_stop = self.parent.times_stop_to_stop 2874 2875 # get potential pull vehicles 2876 inds_valid = np.flatnonzero((vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding']) 2877 & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0)) 2878 2879 # print ' states',vehicles.states[ids_veh_lead], VEHICLESTATES['boarding'] 2880 # print ' numbers_person_wait',stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] 2881 # print ' &',(vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding'])\ 2882 # & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0) 2883 # print ' origins inds_valid',inds_valid 2884 if len(inds_valid) == 0: 2885 # print ' all stops busy' 2886 return False 2887 2888 ids_veh_lead = ids_veh_lead[inds_valid] 2889 ids_stop_current = self.ids_stop_current[ids_veh_lead] 2890 2891 # print ' available for pulling ids_veh_lead',ids_veh_lead 2892 # print ' ids_stop_current',ids_stop_current 2893 # get potential target station with demand 2894 demands = stops.numbers_person_wait[self.ids_stop]\ 2895 - (0.5*stops.numbers_veh[self.ids_stop] 2896 + self.numbers_veh_arr[self.ids_stop]) 2897 inds_valid = np.flatnonzero(demands > 0) 2898 # print ' targets inds_valid',inds_valid 2899 if len(inds_valid) == 0: 2900 # print ' no demand' 2901 return False 2902 2903 ids_stop_target = self.ids_stop[inds_valid] 2904 demands = demands[inds_valid] 2905 # print ' ids_stop_current',ids_stop_current 2906 # print ' ids_stop_target',ids_stop_target 2907 # print ' demands',demands 2908 # calculate cost matrix with id_stop_current in rows and id_stop_target 2909 2910 #n_origin = len(ids_stop_current) 2911 #n_targets = len(ids_stop_target) 2912 times = times_stop_to_stop[ids_stop_current, :][:, ids_stop_target] 2913 times[times == 0] = 99999 2914 timeweight = np.exp(-self.constant_timeweight.get_value() * times) 2915 #costs = times_stop_to_stop[ids_stop_current,:][:,ids_stop_target] 2916 #costs[costs == 0] = 99999 2917 # print ' timeweight\n',timeweight 2918 2919 costs = timeweight * demands 2920 #costs = np.zeros(costs.size, np.float32)-demands 2921 2922 inds_pull = np.argmax(costs, 1) 2923 # print ' costs\n',costs 2924 # print ' ->inds_pull,ids_stop_target',inds_pull,ids_stop_target[inds_pull] 2925 2926 durations_est = times_stop_to_stop[ids_stop_current, ids_stop_target[inds_pull]] 2927 # print ' duration_est, t_est_max',durations_est,self.n_est_max*self.time_update_flows.get_value() 2928 2929 inds_time_min = n_timeslot_offset+np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value( 2930 ), dtype=np.int32), 0, self.n_est_max-1-n_timeslot_offset), dtype=np.int32) 2931 inds_time_max = inds_time_min+2 2932 # print ' inds_time_min',inds_time_min 2933 # print ' inds_time_max',inds_time_max 2934 2935 is_started = False 2936 for id_veh_lead, state, id_stop_current, id_stop_target, time_order, ind_min, ind_max, duration_est\ 2937 in zip( 2938 ids_veh_lead, 2939 vehicles.states[ids_veh_lead], 2940 ids_stop_current, 2941 ids_stop_target[inds_pull], 2942 self.times_order[ids_veh_lead], 2943 inds_time_min, 2944 inds_time_max, 2945 durations_est, 2946 ): 2947 2948 # print ' check veh prt.%d'%(id_veh_lead), state, 'id_stop_current',id_stop_current, 'id_stop_target',id_stop_target 2949 2950 #VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6} 2951 # if state == VEHICLESTATES['occupiedtrip']: 2952 2953 #ids_stop = list(self.ids_stop) 2954 # ids_stop.remove(id_stop) 2955 #costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop]-self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop,ids_stop] 2956 #ids_stop [np.argmax(costs)] 2957 inds_time = np.arange(ind_min, ind_max) 2958 costs = self.inflows_sched[id_stop_current, inds_time] 2959 ind_time_depart = inds_time[np.argmin(costs)] 2960 2961 self.inflows_sched[id_stop_target, ind_time_depart] += 1 2962 time_depart = process.simtime + ind_time_depart*self.time_update_flows.get_value()-duration_est 2963 2964 # this is a workarouned that vehicle does first reach the stopline 2965 # before it gets rescheduled...try with stoplinecheck 2966 2967 # if time_depart < process.simtime+15: 2968 # time_depart = process.simtime+15 2969 # print ' ind_time_depart, time_arr, duration_est',ind_time_depart,process.simtime + ind_time_depart*self.time_update_flows.get_value(),duration_est 2970 # print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order 2971 2972 stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart) 2973 self.numbers_veh_arr[id_stop_target] += 1 2974 is_started = True 2975 2976 return is_started 2977 2978 def init_trip_occupied(self, id_veh, id_stop_from, id_stop_to, time_order): 2979 # print 'init_trip_occupied from',id_veh, id_stop_from, id_stop_to 2980 # search closest stop 2981 #self.are_emptytrips[id_veh] = False 2982 2983 self.ids_stop_current[id_veh] = id_stop_from 2984 self.ids_stop_target[id_veh] = id_stop_to 2985 self.times_order[id_veh] = time_order 2986 # print ' to stop',id_stop 2987 # return id_stop_to 2988 2989 def init_trip_empty(self, id_veh, id_stop, time_order): 2990 # print 'VehMan.init_trip_empty id_veh prt.%d,id_stop %d'%(id_veh,id_stop) 2991 # search closest stop 2992 self.ids_stop_current[id_veh] = id_stop 2993 self.times_order[id_veh] = time_order 2994 #self.are_emptytrips[id_veh] = True 2995 #id_stop_target = ids_stop[random.randint(0,len(ids_stop)-1)] 2996 # print ' to stop',id_stop 2997 # return id_stop_target 2998 2999 def indicate_trip_empty(self, id_veh, id_stop, time_order): 3000 # print 'indicate_trip_empty id_veh,id_stop',id_veh,id_stop 3001 # search closest stop 3002 self.ids_stop_current[id_veh] = id_stop 3003 self.times_order[id_veh] = time_order 3004 3005 def get_stop_emptytrip(self, id_stop): 3006 stops = self.get_stops() 3007 ids_stop = list(self.ids_stop) 3008 ids_stop.remove(id_stop) 3009 costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop] - 3010 self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop, ids_stop] 3011 3012 return ids_stop[np.argmax(costs)] 3013 3014 def conclude_trip(self, id_veh, id_stop): 3015 self.ids_stop_target[id_veh] = -1 3016 self.numbers_veh_arr[id_stop] -= 1 3017 3018 # measures actually arrived vehicles at stop 3019 # accumulates counts over one flow measurement interval 3020 self.log_inflows_temp[id_stop] += 1 3021 3022 3023class PrtService(SimobjMixin, DemandobjMixin, cm.BaseObjman): 3024 def __init__(self, ident, simulation=None, 3025 name='PRT service', info='PRT service', 3026 **kwargs): 3027 # print 'PrtService.__init__',name 3028 3029 self._init_objman(ident=ident, parent=simulation, 3030 name=name, info=info, **kwargs) 3031 3032 attrsman = self.set_attrsman(cm.Attrsman(self)) 3033 3034 # make PRTservice a demand object as link 3035 self.get_scenario().demand.add_demandobject(obj=self) 3036 3037 self._init_attributes() 3038 self._init_constants() 3039 3040 def get_scenario(self): 3041 return self.parent.parent 3042 3043 def _init_attributes(self): 3044 # print 'PrtService._init_attributes',hasattr(self,'prttransit') 3045 attrsman = self.get_attrsman() 3046 scenario = self.get_scenario() 3047 # here we ged classes not vehicle type 3048 # specific vehicle type within a class will be generated later 3049 modechoices = scenario.net.modes.names.get_indexmap() 3050 3051 # print ' modechoices',modechoices 3052 self.id_prtmode = attrsman.add(am.AttrConf('id_prtmode', modechoices['custom1'], 3053 groupnames=['options'], 3054 choices=modechoices, 3055 name='Mode', 3056 info='PRT transport mode (or vehicle class).', 3057 )) 3058 3059 self.prtstops = attrsman.add(cm.ObjConf(PrtStops('prtstops', self))) 3060 self.mergenodes = attrsman.add(cm.ObjConf(Mergenodes('mergenodes', self))) 3061 self.prtvehicles = attrsman.add(cm.ObjConf(PrtVehicles('prtvehicles', self))) 3062 self.vehicleman = attrsman.add(cm.ObjConf(VehicleMan('vehicleman', self))) 3063 3064 # -------------------------------------------------------------------- 3065 # prt transit table 3066 # attention: prttransits will be a child of virtual pop, 3067 # and a link from prt service 3068 3069 # if not hasattr(self,'prttransit'): 3070 virtualpop = self.get_scenario().demand.virtualpop 3071 prttransits = virtualpop.get_plans().add_stagetable('prttransits', PrtTransits) 3072 3073 # print ' prttransits =',prttransits 3074 # add attribute as link 3075 # self.prttransits = attrsman.add(\ 3076 # cm.ObjConf(prttransits,is_child = False ), 3077 # is_overwrite = False,) 3078 prttransits.set_prtservice(self) 3079 3080 prtstrategy = virtualpop.get_strategies().add_strategy('prt', PrtStrategy) 3081 # self.prttransits = attrsman.add(\ 3082 # cm.ObjConf(prttransits,is_child = False ), 3083 # is_overwrite = False,) 3084 prtstrategy.set_prtservice(self) 3085 3086 # temporary attrfix 3087 #prtserviceconfig = self.parent.get_attrsman().prtservice 3088 #prtserviceconfig.groupnames = [] 3089 #prtserviceconfig.add_groupnames(['demand objects']) 3090 3091 def _init_constants(self): 3092 # print 'PrtService._init_constants',self,self.parent 3093 attrsman = self.get_attrsman() 3094 self.times_stop_to_stop = None 3095 self.fstar = None 3096 self._results = None 3097 attrsman.do_not_save_attrs(['times_stop_to_stop', 'fstar', '_results']) 3098 3099 def get_vtypes(self): 3100 3101 ids_vtypes = set(self.prtvehicles.ids_vtype.get_value()) 3102 return ids_vtypes 3103 3104 def get_writexmlinfo(self, is_route=False): 3105 """ 3106 Returns three array where the first array is the 3107 begin time of the first vehicle and the second array is the 3108 write function to be called for the respectice vehicle and 3109 the third array contains the vehicle ids 3110 3111 Method used to sort trips when exporting to route or trip xml file 3112 """ 3113 print 'PRT.get_writexmlinfo' 3114 3115 # time of first PRT vehicle(s) to be inserted 3116 virtualpop = self.get_scenario().demand.virtualpop 3117 t_start = virtualpop.get_time_depart_first() 3118 3119 #t_start = 0.0 3120 # time betwenn insertion of consecutive vehicles at same stop 3121 t_delta = 10 # s 3122 3123 n_veh = len(self.prtvehicles) 3124 times_depart = np.zeros(n_veh, dtype=np.int32) 3125 writefuncs = np.zeros(n_veh, dtype=np.object) 3126 writefuncs[:] = self.write_prtvehicle_xml 3127 ids_veh = self.prtvehicles.get_ids() 3128 3129 id_edge_prev = -1 3130 i = 0 3131 t0 = t_start 3132 for id_edge in self.prtvehicles.ids_currentedge[ids_veh]: 3133 # print ' id_edge, t_start, id_edge_prev',id_edge, t0, id_edge_prev 3134 times_depart[i] = t0 3135 t0 += t_delta 3136 if id_edge != id_edge_prev: 3137 t0 = t_start 3138 id_edge_prev = 1*id_edge 3139 i += 1 3140 3141 return times_depart, writefuncs, ids_veh 3142 3143 def write_prtvehicle_xml(self, fd, id_veh, time_begin, indent=2): 3144 # print 'write_prtvehicle_xml',id_veh, time_begin 3145 # TODO: actually this should go in prtvehicles 3146 #time_veh_wait_after_stop = 3600 3147 scenario = self.get_scenario() 3148 net = scenario.net 3149 3150 #lanes = net.lanes 3151 edges = net.edges 3152 #ind_ride = rides.get_inds(id_stage) 3153 #id_veh = rides.ids_veh[id_stage] 3154 prtvehicles = self.prtvehicles 3155 #ptstops = net.ptstops 3156 #prtstops = self.parent.prtstops 3157 #ids_prtstop = prtstops.get_ids() 3158 #ids_ptstop = prtstops.ids_ptstop[id_stop] 3159 # lanes.ids_edge[ptstops.ids_lane[ids_ptstop]], 3160 #id_lane_from = parking.ids_lane[id_parking_from] 3161 #laneindex_from = lanes.indexes[id_lane_from] 3162 #pos_from = parking.positions[id_parking_from] 3163 3164 #id_parking_to = rides.ids_parking_to[id_stage] 3165 #id_lane_to = parking.ids_lane[id_parking_to] 3166 #laneindex_to = lanes.indexes[id_lane_to] 3167 #pos_to = parking.positions[id_parking_to] 3168 3169 # write unique veh ID to prevent confusion with other veh declarations 3170 fd.write(xm.start('vehicle id="%s"' % prtvehicles.get_id_sumo(id_veh), indent+2)) 3171 3172 fd.write(xm.num('depart', '%d' % time_begin)) 3173 fd.write(xm.num('type', scenario.demand.vtypes.ids_sumo[prtvehicles.ids_vtype[id_veh]])) 3174 fd.write(xm.num('line', prtvehicles.get_id_line_xml())) 3175 fd.write(xm.stop()) 3176 3177 # write route 3178 fd.write(xm.start('route', indent+4)) 3179 # print ' edgeindex[ids_edge]',edgeindex[ids_edge] 3180 fd.write(xm.arr('edges', [edges.ids_sumo[prtvehicles.ids_currentedge[id_veh]]])) 3181 3182 # does not seem to have an effect, always starts at base???? 3183 fd.write(xm.num('departPos', 'base')) 3184 #fd.write(xm.num('departLane', laneindex_from )) 3185 fd.write(xm.stopit()) 3186 3187 # write depart stop 3188 # fd.write(xm.start('stop',indent+4)) 3189 #fd.write(xm.num('lane', edges.ids_sumo[lanes.ids_edge[id_lane_from]]+'_%d'%laneindex_from )) 3190 #fd.write(xm.num('duration', time_veh_wait_after_stop)) 3191 #fd.write(xm.num('startPos', pos_from )) 3192 #fd.write(xm.num('endPos', pos_from + parking.lengths[id_parking_from])) 3193 #fd.write(xm.num('triggered', "True")) 3194 # fd.write(xm.stopit()) 3195 3196 fd.write(xm.end('vehicle', indent+2)) 3197 3198 # def make_stops_and_vehicles(self, n_veh = -1): 3199 # self.prtstops.make_from_net() 3200 # self.prtvehicles.make(n_veh) 3201 # self.make_times_stop_to_stop() 3202 3203 def prepare_sim(self, process): 3204 print 'prepare_sim', self.ident 3205 # print ' self.times_stop_to_stop',self.times_stop_to_stop 3206 3207 if self.fstar is None: 3208 self.make_fstar() 3209 3210 if self.times_stop_to_stop is None: 3211 print ' times_stop_to_stop' 3212 self.make_times_stop_to_stop() 3213 3214 updatedata = self.prtvehicles.prepare_sim(process) 3215 updatedata += self.prtstops.prepare_sim(process) 3216 updatedata += self.mergenodes.prepare_sim(process) 3217 updatedata += self.vehicleman.prepare_sim(process) 3218 3219 # print 'PrtService.prepare_sim updatedata',updatedata 3220 return updatedata 3221 3222 def make_fstar(self, is_update=False): 3223 if (self.fstar is None) | is_update: 3224 self.fstar = self.get_fstar() 3225 self.edgetimes = self.get_times(self.fstar) 3226 3227 def get_route(self, id_fromedge, id_toedge): 3228 """ 3229 Centralized function to determin fastest route between 3230 PRT network edges. 3231 """ 3232 duration, route = get_mincostroute_edge2edge(id_fromedge, id_toedge, 3233 weights=self.edgetimes, fstar=self.fstar) 3234 3235 return route, duration 3236 3237 def make_times_stop_to_stop(self, fstar=None, times=None): 3238 print 'make_times_stop_to_stop' 3239 log = self.get_logger() 3240 if fstar is None: 3241 if self.fstar is None: 3242 self.make_fstar() 3243 3244 fstar = self.fstar # get_fstar() 3245 times = self.edgetimes # self.get_times(fstar) 3246 3247 if len(fstar) == 0: 3248 self.times_stop_to_stop = [[]] 3249 return 3250 3251 ids_prtstop = self.prtstops.get_ids() 3252 if len(ids_prtstop) == 0: 3253 self.get_logger().w('WARNING: no PRT stops, no plans. Generate them!') 3254 return 3255 3256 ids_edge = self.prtstops.get_edges(ids_prtstop) 3257 3258 # check if all PRT stop edges are in fstar 3259 ids_ptstop = self.prtstops.ids_ptstop[ids_prtstop] # for debug only 3260 is_incomplete_fstar = False 3261 for id_edge, id_stop, id_ptstop in zip(ids_edge, ids_prtstop, ids_ptstop): 3262 # print ' Found PRT stop %d, PT stop %d with id_edge %d '%(id_stop,id_ptstop, id_edge) 3263 if not fstar.has_key(id_edge): 3264 print 'WARNING in make_times_stop_to_stop: PRT stop %d, PT stop %d has no id_edge %d in fstar' % ( 3265 id_stop, id_ptstop, id_edge) 3266 is_incomplete_fstar = True 3267 3268 # check if fstar is complete (all to edges are in keys) 3269 ids_fromedge_set = set(fstar.keys()) 3270 ids_sumo = self.get_scenario().net.edges.ids_sumo 3271 for id_fromedge in ids_fromedge_set: 3272 if not ids_fromedge_set.issuperset(fstar[id_fromedge]): 3273 is_incomplete_fstar = True 3274 ids_miss = fstar[id_fromedge].difference(ids_fromedge_set) 3275 print 'WARNING in make_times_stop_to_stop: incomplete fstar of id_fromedge = %d, %s' % ( 3276 id_fromedge, ids_sumo[id_fromedge]) 3277 for id_edge in ids_miss: 3278 print ' missing', id_edge, ids_sumo[id_edge] 3279 3280 if is_incomplete_fstar: 3281 return 3282 3283 # print ' ids_prtstop,ids_edge',ids_prtstop,ids_edge 3284 n_elem = np.max(ids_prtstop)+1 3285 stop_to_stop = np.zeros((n_elem, n_elem), dtype=np.int32) 3286 3287 ids_edge_to_ids_prtstop = np.zeros(np.max(ids_edge)+1, dtype=np.int32) 3288 ids_edge_to_ids_prtstop[ids_edge] = ids_prtstop 3289 3290 ids_edge_target = set(ids_edge) 3291 3292 for id_stop, id_edge in zip(ids_prtstop, ids_edge): 3293 # print ' route for id_stop, id_edge',id_stop, id_edge 3294 3295 # remove origin from target 3296 ids_edge_target.discard(id_edge) 3297 3298 costs, routes = edgedijkstra(id_edge, 3299 ids_edge_target=ids_edge_target, 3300 weights=times, fstar=fstar 3301 ) 3302 3303 # print ' ids_edge_target',ids_edge_target 3304 # print ' costs\n', costs 3305 # print ' routes\n', routes 3306 # for route in routes: 3307 # if len(route)==0: 3308 # print 'WARNING in make_times_stop_to_stop: empty route' 3309 # else: 3310 # print ' found route to id_edge, id_stop',route[-1],ids_edge_to_ids_prtstop[route[-1]],len(route) 3311 3312 if costs is not None: 3313 # TODO: could be vectorialized, but not so easy 3314 for id_edge_target in ids_edge_target: 3315 #stop_to_stop[id_edge,id_edge_target] = costs[id_edge_target] 3316 # 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] 3317 # print ' stop_orig,costs ',ids_edge_to_ids_prtstop[id_edge],ids_sumo[id_edge] 3318 # print ' stop_target',ids_edge_to_ids_prtstop[id_edge_target],ids_sumo[id_edge_target] 3319 # print ' costs ',costs[id_edge_target] 3320 # stop_to_stop[ids_edge_to_ids_prtstop[[id_edge,id_edge_target]]]=costs[id_edge_target] 3321 if id_edge_target in costs: 3322 stop_to_stop[ids_edge_to_ids_prtstop[id_edge], 3323 ids_edge_to_ids_prtstop[id_edge_target]] = costs[id_edge_target] 3324 else: 3325 print 'WARNING in make_times_stop_to_stop: unreacle station id_fromedge = %d, %s' % ( 3326 id_edge_target, ids_sumo[id_edge_target]) 3327 is_incomplete_fstar = True 3328 3329 # put back origin to targets (probably not the best way) 3330 ids_edge_target.add(id_edge) 3331 # print ' ids_edge_target (all)',ids_edge_target 3332 3333 # print ' stop_to_stop',stop_to_stop 3334 # TODO: here we could also store the routes 3335 3336 if is_incomplete_fstar: 3337 return False 3338 3339 self.times_stop_to_stop = stop_to_stop 3340 self.ids_edge_to_ids_prtstop = ids_edge_to_ids_prtstop 3341 # print ' times_stop_to_stop=\n',self.times_stop_to_stop 3342 return True 3343 3344 def get_fstar(self): 3345 """ 3346 Returns the forward star graph of the network as dictionary: 3347 fstar[id_fromedge] = set([id_toedge1, id_toedge2,...]) 3348 """ 3349 print 'get_fstar' 3350 net = self.get_scenario().net 3351 # prt mode 3352 id_mode = self.id_prtmode 3353 3354 #ids_edge = self.get_ids() 3355 #fstar = np.array(np.zeros(np.max(ids_edge)+1, np.obj)) 3356 fstar = {} 3357 connections = net.connections 3358 lanes = net.lanes 3359 3360 #inds_con = connections.get_inds() 3361 #ids_fromlane = connections.ids_fromlane.get_value()[inds_con] 3362 #ids_tolane = connections.ids_tolane.get_value()[inds_con] 3363 3364 ids_con = connections.get_ids() 3365 ids_fromlane = connections.ids_fromlane[ids_con] 3366 ids_tolane = connections.ids_tolane[ids_con] 3367 3368 ids_mainmode_from = lanes.ids_mode[ids_fromlane] 3369 ids_mainmode_to = lanes.ids_mode[ids_tolane] 3370 3371 #ids_modes_allow_from = lanes.ids_modes_allow[ids_fromlane] 3372 #ids_modes_allow_to = lanes.ids_modes_allow[ids_tolane] 3373 3374 ids_fromedge = lanes.ids_edge[ids_fromlane] 3375 ids_toedge = lanes.ids_edge[ids_tolane] 3376 # print ' ids_fromedge',ids_fromedge 3377 # print ' ids_modes_allow',ids_modes_allow 3378 3379 for id_fromedge, id_toedge, id_mode_allow_from, id_mode_allow_to, id_fromlane, id_tolane in\ 3380 zip(ids_fromedge, ids_toedge, ids_mainmode_from, ids_mainmode_to, 3381 ids_fromlane, ids_tolane): 3382 3383 if id_mode_allow_from == id_mode: 3384 if id_mode_allow_to == id_mode: 3385 3386 if fstar.has_key(id_fromedge): 3387 fstar[id_fromedge].add(id_toedge) 3388 else: 3389 fstar[id_fromedge] = set([id_toedge]) 3390 # if id_fromedge == 14048: 3391 # print ' id_fromedge, id_toedge',id_fromedge, id_toedge,fstar.has_key(id_fromedge) 3392 # print ' id_fromlane, id_tolane ',id_fromlane, id_tolane 3393 # print ' id_mode_allow_from, id_mode_allow_to',id_mode_allow_from, id_mode_allow_to 3394 3395 # for id_fromedge, id_toedge,ids_mode_allow_from,id_modes_allow_to in\ 3396 # zip(ids_fromedge, ids_toedge, ids_modes_allow_from, ids_modes_allow_to): 3397 # if len(ids_mode_allow_from)>0: 3398 # if ids_mode_allow_from[-1] == id_mode: 3399 # if len(id_modes_allow_to)>0: 3400 # if id_modes_allow_to[-1] == id_mode: 3401 # 3402 # if fstar.has_key(id_fromedge): 3403 # fstar[id_fromedge].add(id_toedge) 3404 # else: 3405 # fstar[id_fromedge]=set([id_toedge]) 3406 3407 return fstar 3408 3409 def get_times(self, fstar): 3410 """ 3411 Returns freeflow travel times for all edges. 3412 The returned array represents the speed and the index corresponds to 3413 edge IDs. 3414 3415 """ 3416 if len(fstar) == 0: 3417 return [] 3418 3419 net = self.get_scenario().net 3420 #id_mode = net.modes.get_id_mode(mode) 3421 id_mode = self.id_prtmode 3422 # print 'get_times id_mode,is_check_lanes,speed_max',id_mode,is_check_lanes,speed_max 3423 ids_edge = np.array(fstar.keys(), dtype=np.int32) 3424 3425 times = np.array(np.zeros(np.max(ids_edge)+1, np.float32)) 3426 speeds = net.edges.speeds_max[ids_edge] 3427 3428 # limit allowed speeds with max speeds of mode 3429 speeds = np.clip(speeds, 0.0, net.modes.speeds_max[id_mode]) 3430 3431 times[ids_edge] = net.edges.lengths[ids_edge]/speeds 3432 3433 return times 3434 3435 def config_results(self, results): 3436 # print 'config_results',results, id(results) 3437 # keep a link to results here because needed to 3438 # log data during simulation 3439 # this link should not be followed during save process 3440 #self._results = results 3441 3442 tripresults = res.Tripresults('prttripresults', results, 3443 self.prtvehicles, 3444 self.get_scenario().net.edges, 3445 name='PRT trip results', 3446 info='Table with simulation results for each PRT vehicle. The results refer to the vehicle journey over the entire simulation period.', 3447 ) 3448 results.add_resultobj(tripresults, groupnames=['Trip results']) 3449 3450 prtstopresults = Stopresults('prtstopresults', results, self.prtstops) 3451 results.add_resultobj(prtstopresults, groupnames=['PRT stop results']) 3452 3453 # def get_results(self): 3454 # return self._results 3455 3456 def process_results(self, results, process=None): 3457 pass 3458 3459 3460class Stopresults(am.ArrayObjman): 3461 def __init__(self, ident, results, prtstops, 3462 name='Stop results', 3463 info='Table with simulation results of stops generated from vehicle management.', 3464 **kwargs): 3465 3466 self._init_objman(ident=ident, 3467 parent=results, # main results object 3468 info=info, 3469 name=name, 3470 **kwargs) 3471 3472 self.add(cm.AttrConf('time_step', 5.0, 3473 groupnames=['parameters'], 3474 name='Step time', 3475 info="Time of one recording step.", 3476 unit='s', 3477 )) 3478 3479 self.add(cm.ObjConf(prtstops, is_child=False, # groupnames = ['_private'] 3480 )) 3481 3482 self.add_col(am.IdsArrayConf('ids_stop', prtstops, 3483 groupnames=['state'], 3484 is_index=True, 3485 name='PRT stop ID', 3486 info='ID of PRT stop.', 3487 )) 3488 3489 attrinfos = [ 3490 ('inflows_veh', {'name': 'Vehicle in-flows', 'unit': '1/s', 3491 'dtype': np.float32, 'info': 'Vehicle flow into the stop over time.'}), 3492 ('inflows_veh_sched', {'name': 'Sched. vehicle in-flows', 'unit': '1/s', 3493 'dtype': np.float32, 'info': 'Scheduled vehicle flow into the stop over time.'}), 3494 ('inflows_person', {'name': 'Person in-flows', 'unit': '1/s', 3495 'dtype': np.float32, 'info': 'Person flow into the stop over time.'}), 3496 ('numbers_person_wait', {'name': 'waiting person', 'dtype': np.int32, 3497 'info': 'Number of waiting persons at stop over time.'}), 3498 ('waittimes_tot', {'name': 'total wait time', 'dtype': np.float32, 3499 'info': 'Wait times of all waiting persons at a stop over time.'}), 3500 ] 3501 3502 for attrname, kwargs in attrinfos: 3503 self.add_resultattr(attrname, **kwargs) 3504 3505 def get_dimensions(self): 3506 return len(self), len(self.inflows_veh.get_default()) 3507 3508 def get_prtstops(self): 3509 return self.prtstops.get_value() 3510 # return self.ids_stop.get_linktab() 3511 3512 def init_recording(self, n_timesteps, time_step): 3513 print 'init_recording n_timesteps, time_step', n_timesteps, time_step, len( 3514 self.ids_stop.get_linktab().get_ids()) 3515 self.clear() 3516 3517 self.time_step.set_value(time_step) 3518 3519 for attrconfig in self.get_stopresultattrconfigs(): 3520 # print ' reset attrconfig',attrconfig.attrname 3521 attrconfig.set_default(np.zeros(n_timesteps, dtype=attrconfig.get_dtype())) 3522 attrconfig.reset() 3523 # print ' default=',attrconfig.get_default(),attrconfig.get_default().dtype 3524 ids_stop = self.get_prtstops().get_ids() 3525 # print ' ids_stop',ids_stop 3526 self.add_rows(n=len(ids_stop), ids_stop=ids_stop) 3527 3528 def record(self, timestep, ids, **kwargs): 3529 inds = self.ids_stop.get_linktab().get_inds(ids) 3530 for attrname, values in kwargs.iteritems(): 3531 # print 'record',attrname,values.dtype,values.shape, getattr(self,attrname).get_value().dtype, getattr(self,attrname).get_value().shape 3532 getattr(self, attrname).get_value()[inds, timestep] = values 3533 3534 def get_stopresultattrconfigs(self): 3535 return self.get_attrsman().get_group_attrs('PRT results').values() 3536 3537 def get_persons(self): 3538 return self.ids_person.get_linktab() 3539 3540 def add_resultattr(self, attrname, **kwargs): 3541 self.add_col(am.ArrayConf(attrname, 0, groupnames=['PRT results', 'results'], **kwargs)) 3542 3543 def import_xml(self, sumo, datapaths): 3544 # no imports, data come from prtservice 3545 pass 3546