Path: blob/main/tools/contributed/sumopy/plugins/hcprt/hcprt.py
169689 views
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo1# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.2# SUMOPy module3# Copyright (C) 2012-2021 University of Bologna - DICAM4# This program and the accompanying materials are made available under the5# terms of the Eclipse Public License 2.0 which is available at6# https://www.eclipse.org/legal/epl-2.0/7# This Source Code may also be made available under the following Secondary8# Licenses when the conditions for such availability set forth in the Eclipse9# Public License 2.0 are satisfied: GNU General Public License, version 210# or later which is available at11# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html12# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1314# @file hcprt.py15# @author Joerg Schweizer16# @date 20121718"""19This plugin provides methods to run and analyze HCPRT networks.202122"""23import os24import sys25import numpy as np26import random27import string # for debugging used in display_flows_est28from agilepy.lib_base.processes import Process29#from xml.sax import saxutils, parse, handler30from collections import OrderedDict, Counter313233from coremodules.modules_common import *34import agilepy.lib_base.classman as cm35import agilepy.lib_base.arrayman as am36import agilepy.lib_base.xmlman as xm37#from agilepy.lib_base.misc import get_inversemap38#from agilepy.lib_base.geometry import find_area39#from agilepy.lib_base.processes import Process,CmlMixin,ff,call40from coremodules.network.network import SumoIdsConf41from coremodules.network.routing import edgedijkstra, get_mincostroute_edge2edge42from coremodules.simulation import sumo43from coremodules.simulation.sumo import traci44#from coremodules.network import routing45from coremodules.demand.demandbase import DemandobjMixin46from coremodules.simulation.simulationbase import SimobjMixin4748from coremodules.demand.virtualpop import StageTypeMixin, StrategyMixin49from coremodules.simulation import results as res5051np.set_printoptions(0, linewidth=180)5253#from demo import TraciDemo5455BERTHSTATES = {'free': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3,56'allocated': 4, 'waiting_occupied': 5, 'waiting_routed': 6}5758#59VEHICLESTATES = {'init': 0, 'waiting': 1, 'boarding': 2, 'alighting': 3, 'emptytrip': 4, 'occupiedtrip': 5, 'forewarding': 6, 'await_forwarding': 7,60'forewarding_enter': 8, 'boarding_completed': 9, 'forewarding_exit': 10, 'forewarding_passthrough': 11, 'forewarding_exit_kickout': 12, 'kickout_berth': 13}6162LEADVEHICLESTATES = [VEHICLESTATES['boarding'], VEHICLESTATES['waiting'],63VEHICLESTATES['emptytrip'], VEHICLESTATES['occupiedtrip']]64STOPTYPES = {'person': 0, 'freight': 1, 'depot': 2, 'group': 3, 'mixed': 4}6566FASE_MOVE_IN = 067FASE_MOVE_OUT = 16869get_traci_odo = traci.vehicle.getDistance70get_traci_velocity = traci.vehicle.getSpeed71get_traci_route_all = traci.vehicle.getRoute72get_traci_routeindex = traci.vehicle.getRouteIndex73get_traci_distance = traci.vehicle.getDrivingDistance747576def get_traci_route(id_veh_sumo):77return get_traci_route_all(id_veh_sumo)[get_traci_routeindex(id_veh_sumo):]787980INF = 10.0**1081INFINT = 10**1082# def detect_entered_left(x,y):83# """84# returns the enter and left elemets of list x (before)85# and list y (after)86# """87# if len(x) == 0:88# if len(y) == 0:89# return909192class Compressors(am.ArrayObjman):93def __init__(self, ident, prtservices, **kwargs):94self._init_objman(ident=ident,95parent=prtservices,96name='Compressors',97info='Comressors try to create platoons by shunting vehicles with common destination in a common shunt edge. Contains information and methods for compressors to create platoons.',98version=0.1,99**kwargs)100self._init_attributes()101102def _init_attributes(self):103#self.add(cm.ObjConf(PrtBerths('berths',self)) )104105self.add(cm.AttrConf('time_update', 1.0,106groupnames=['parameters'],107name='Update time',108info="Simulation update time.",109unit='s',110))111112self.add(cm.AttrConf('time_accumulation_max', 29.0,113groupnames=['parameters'],114name='Maximum accumulation time',115info="Maximum accumulation time in a buffer. After this time the buffer is trying to release the vehicles.",116unit='s',117))118119self.add(cm.AttrConf('time_release_min', 40.0,120groupnames=['parameters'],121name='Minimum realease time',122info="Minimum time that must pass between successive releases.",123unit='s',124))125126net = self.get_scenario().net127128self.add_col(am.IdsArrayConf('ids_detectoredge', net.edges,129name='Detector edge ID',130info='Detector edge ID is the edge from where vehicles are deviated into the compressor.',131is_index=True,132))133134self.add_col(am.IdlistsArrayConf('ids_shuntedges', net.edges,135name='Shunt edge IDs',136info='Shunt edge IDs where PRT vehicles with common destination are sorted.',137))138139self.set_version(0.1)140141def _init_constants(self):142self.do_not_save_attrs([143'decel', 'ids_comp_to_ids_detectedge_sumo', 'queuess',144'queuess_alloc', 'capacitiess', 'ids_edge_sumo_targets',145'are_queues_avail', 'releasetimes', 'releasetimes_queues',146'length_veh',147])148149def make(self, id_detectoredge=None, **kwargs):150print 'make', kwargs151# print ' ids_shuntedge',kwargs.get('ids_shuntedge',None),type(kwargs.get('ids_shuntedge',None)[0])152id_comp = self.add_row(ids_shuntedges=kwargs.get('ids_shuntedge', None),153ids_detectoredge=id_detectoredge154)155if id_detectoredge is None:156self.update(id_comp)157return id_comp158159def update(self, id_comp):160print 'update id_comp', id_comp161edges = self.get_scenario().net.edges162163self.ids_detectoredge[id_comp] = edges.get_incoming(self.ids_shuntedges[id_comp][0])[0]164165def update_all(self):166print 'update_all'167for id_comp in self.get_ids():168self.update(id_comp)169170def get_scenario(self):171return self.parent.get_scenario()172173def prepare_sim(self, process):174print 'Compressors.prepare_sim'175net = self.get_scenario().net176nodes = net.nodes177edges = net.edges178lanes = net.lanes179ids_edge_sumo = edges.ids_sumo180181id_prtmode = self.parent.id_prtmode182self.decel = self.parent.prtvehicles.decel_emergency.get_value()183184ids = self.get_ids()185186if len(ids) == 0:187return []188189n_id_max = np.max(ids)+1190191self.ids_comp_to_ids_detectedge_sumo = np.zeros(n_id_max, dtype=np.object)192self.ids_comp_to_ids_detectedge_sumo[ids] = edges.ids_sumo[self.ids_detectoredge[ids]]193194# this is list of queues for all shunt lines for each compressor195self.queuess = np.zeros(n_id_max, dtype=np.object)196197# thses queus are the same as queuess but contains the allocated, but not yet arrived vehicles198self.queuess_alloc = np.zeros(n_id_max, dtype=np.object)199200# this is list of maximum queue length for all shunt lines for each compressor201self.capacitiess = np.zeros(n_id_max, dtype=np.object)202203# list with target edges for each queue for each compressor204self.ids_edge_sumo_targets = np.zeros(n_id_max, dtype=np.object)205206# list with availabilities for each queue for each compressor207self.are_queues_avail = np.zeros(n_id_max, dtype=np.object)208209# releasetimes for each compressor210self.releasetimes = np.zeros(n_id_max, dtype=np.int32)211212# releasetimes for each queue for each compressor213self.releasetimes_queues = np.zeros(n_id_max, dtype=np.object)214215self.length_veh = self.parent.prtvehicles.get_length()216217# this queue contains all vehicles on the detect edge218# it is used to identify whether a new vehicle has left the merge219self.ids_vehs_detect_sumo = np.zeros(n_id_max, dtype=np.object)220221for id_comp, ids_shuntedge in zip(ids, self.ids_shuntedges[ids]):222print ' id_comp', id_comp223n_shunts = len(ids_shuntedge) # first edge is not a real shunt!!224225queues = n_shunts*[None]226queues_alloc = n_shunts*[None]227capacities = n_shunts*[None]228229for i, length_edge in zip(range(n_shunts), edges.lengths[ids_shuntedge]):230capacities[i] = max(2, int((length_edge-30.0)/(self.length_veh+0.5)))231queues[i] = []232queues_alloc[i] = []233234self.queuess[id_comp] = queues235self.queuess_alloc[id_comp] = queues_alloc236self.capacitiess[id_comp] = capacities237self.ids_edge_sumo_targets[id_comp] = n_shunts*['']238self.are_queues_avail[id_comp] = n_shunts*[True]239self.releasetimes_queues[id_comp] = n_shunts*[0]240241self.ids_vehs_detect_sumo[id_comp] = set()242print ' capacities', self.capacitiess[id_comp]243print ' queues', self.queuess[id_comp]244245return [(self.time_update.get_value(), self.process_step),246]247248def process_step(self, process):249simtime = process.simtime250print 79*'_'251print 'Compressors.process_step at', simtime252net = self.get_scenario().net253edges = net.edges254vehicles = self.parent.prtvehicles255ids = self.get_ids()256for id_comp,\257id_detectedge_sumo,\258ids_veh_detect_sumo,\259ids_shuntedge,\260ids_edge_sumo_target,\261queues,\262queues_alloc,\263capacities,\264are_queue_avail,\265releasetime_queues\266in zip(ids,267self.ids_comp_to_ids_detectedge_sumo[ids],268self.ids_vehs_detect_sumo[ids],269self.ids_shuntedges[ids],270self.ids_edge_sumo_targets[ids],271self.queuess[ids],272self.queuess_alloc[ids],273self.capacitiess[ids],274self.are_queues_avail[ids],275self.releasetimes_queues[ids],276):277n_queues = len(queues)278print ' '+30*'><'279print ' Compressor id_comp', id_comp, 'n_queues', n_queues280# check for new vehicle arrivals/departures281282ids_veh_entered_sumo, ids_veh_left_sumo, ids_veh_new_sumo = vehicles.get_entered_left(283id_detectedge_sumo, ids_veh_detect_sumo)284285if 1:286print ' id_detectedge_sumo', id_detectedge_sumo287print ' ids_veh_detect_sumo', ids_veh_detect_sumo288print ' ids_veh_new_sumo', ids_veh_new_sumo289print ' ids_veh_entered_sumo=', ids_veh_entered_sumo290print ' ids_veh_left_sumo=', ids_veh_left_sumo291292if len(ids_veh_entered_sumo) > 0:293294ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)295296for id_veh_entered, id_veh_entered_sumo, id_leader, length_plat\297in zip(ids_veh_entered, ids_veh_entered_sumo,298vehicles.ids_leader[ids_veh_entered],299vehicles.lengths_plat[ids_veh_entered]):300301# we cannot deconcatenate here, vehicles are in movement302# instead, measure if there is enough room for the platoon303# otherwise send platoon through bypass304if (length_plat < 0.001) & (id_leader == -1):305# no platoon, it is a single vehicle306id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]307ids_shuntedge_sumo = edges.ids_sumo[ids_shuntedge]308print ' dispatch id_veh_entered_sumo %s' % id_veh_entered_sumo, id_targetedge_sumo, ids_edge_sumo_target309310is_found_queue = False311inds_queue = np.flatnonzero((np.array(ids_edge_sumo_target, object)312== id_targetedge_sumo) & np.array(are_queue_avail, dtype=np.bool))313# print ' inds_queue',inds_queue314if len(inds_queue) > 0:315#ind_queue = ids_edge_sumo_target.index(id_targetedge_sumo)316ind_queue = inds_queue[0]317queue = queues[ind_queue]318capa_queue = capacities[ind_queue]319len_queue = len(queue)320# print ' found ind_queue,len_queue,capa_queue',ind_queue,len_queue,capa_queue321# if len_queue < capa_queue:322self._alloc_queue(queue, queues_alloc[ind_queue],323capa_queue,324id_veh_entered,325id_veh_entered_sumo,326ids_shuntedge[ind_queue],327ids_shuntedge_sumo[ind_queue],328vehicles, edges)329330# queue is full now, remove target331# no, otherwise th target is lost to program the vehicles332if len_queue+1 == capa_queue:333are_queue_avail[ind_queue] = False334335is_found_queue = True336337if not is_found_queue:338# print ' no queue with target or specific queue is full, search for a new queue'339340is_found_queue = False341for ind_queue, queue in zip(range(1, n_queues), queues[1:]):342if len(queue) == 0:343is_found_queue = True344break345# ind_queue = 1 # start with 1 because 0 is bypass346#is_queueend = False347# while len(queues[ind_queue])>0 & (not is_queueend):348# is_queueend = ind_queue == n_queues-1349# if not350# ind_queue += 1351352if not is_found_queue:353# print ' all queues are busy, let vehicle %s go ahead'%id_veh_entered_sumo354pass355else:356print ' configure target of new queue', ind_queue, id_targetedge_sumo357ids_edge_sumo_target[ind_queue] = id_targetedge_sumo358self._alloc_queue(queues[ind_queue],359queues_alloc[ind_queue],360capacities[ind_queue],361id_veh_entered,362id_veh_entered_sumo,363ids_shuntedge[ind_queue],364ids_shuntedge_sumo[ind_queue],365vehicles, edges)366367else:368# let platoon pass369pass370else:371# nothing happened372pass373374# update veh on detector edge375self.ids_vehs_detect_sumo[id_comp] = ids_veh_new_sumo376377if True: # do this later ...simtime - self.releasetimes[id_comp]> 10:378# now check if any of the vehicle in any of the queues has arrived379# and if a queue is complete, create a platoon, send it off and380# reset the queue381# print ' Deal with queues...'382for ind_queue, queue, queue_alloc,\383capacity, id_edge_sumo_target,\384id_shuntedge_sumo, releasetime_queue\385in zip(386range(n_queues), queues, queues_alloc,387capacities, ids_edge_sumo_target,388edges.ids_sumo[ids_shuntedge], releasetime_queues):389if 0:390print ' OOOO shunt %s --> target %s' % (id_shuntedge_sumo, id_edge_sumo_target)391print ' simtime-releasetime_queue', simtime-releasetime_queue392print ' queue', queue, id(queue)393print ' queue_alloc', queue_alloc394395# check if allocated arrived396ids_veh_arrived = []397for id_veh, id_veh_sumo in zip(queue_alloc, vehicles.ids_sumo[queue_alloc]):398if vehicles.reached_stop_sumo(id_veh_sumo):399ids_veh_arrived.append(id_veh)400401for id_veh in ids_veh_arrived:402queue_alloc.remove(id_veh)403404# check if queue reached capacity limit405len_queue = len(queue)406if (len(queue_alloc) == 0) & (len_queue > 0):407# no allocations for this queue408len_queue = len(queue)409# print ' rtq,rtc',releasetime_queue,self.releasetimes[id_comp], len_queue == capacity,simtime - releasetime_queue,simtime - self.releasetimes[id_comp]410# here we coukd also test timeout conditions411if ((len_queue == capacity) | ((simtime - releasetime_queue) > self.time_accumulation_max.get_value())) & (simtime - self.releasetimes[id_comp] > self.time_release_min.get_value()):412# queue is full413print ' platoon and send vehicles:', queue414# action 1415# platoon all vehicles in queue, starting from last in queue416for i in range(len_queue-1, 0, -1):417vehicles.concatenate(queue[i], queue[i-1])418419# print ' check platooned vehicles:'420vehicles.get_platoon(queue[0])421# reprogram destination and start422for id_veh, id_veh_sumo in zip(queue, vehicles.ids_sumo[queue]):423vehicles.reschedule_trip_sumo(id_veh_sumo, id_edge_sumo_target)424#vehicles.control_slow_down( id_veh, speed = 6.0/3.6)425traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)426427# reset queue428del queue[:]429ids_edge_sumo_target[ind_queue] = ""430are_queue_avail[ind_queue] = True431releasetime_queues[ind_queue] = int(simtime)432self.releasetimes[id_comp] = int(simtime)433434def _alloc_queue(self, queue, queue_alloc, capa_queue,435id_veh, id_veh_sumo,436id_shuntedge, id_shuntedge_sumo, vehicles, edges):437438queue.append(id_veh)439queue_alloc.append(id_veh)440len_queue = len(queue)441#pos_stop = 1.0+(capa_queue-len_queue)*(self.length_veh+0.5)442pos_stop = edges.lengths[id_shuntedge]-10-len_queue*(self.length_veh+0.5)443# print '_alloc_queue',id_veh_sumo,id_shuntedge_sumo,capa_queue-len_queue,pos_stop444vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)445446vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex=0)447# print ' get_traci_route',get_traci_route(id_veh_sumo)448# print ' get_traci_route_all',get_traci_route_all(id_veh_sumo)449# print ' get_traci_routeindex',get_traci_routeindex(id_veh_sumo)450#get_traci_route_all = traci.vehicle.getRoute451#get_traci_routeindex = traci.vehicle.getRouteIndex452# def get_traci_route453454455class Decompressors(Compressors):456def __init__(self, ident, prtservices, **kwargs):457self._init_objman(ident=ident,458parent=prtservices,459name='Decompressors',460info='Decomressors dissolve platoons by stopping and decatenating vehicles in parallel shunt edges. Contains information and methods for decompressors to create platoons.',461version=0.1,462**kwargs)463self._init_attributes()464465def _init_constants(self):466self.do_not_save_attrs([467'decel', 'ids_comp_to_ids_detectedge_sumo', 'queuess',468'queuess_alloc', 'capacitiess', # 'ids_edge_sumo_targets',469'are_queues_avail', 'releasetimes', 'releasetimes_queues',470'length_veh', 'ids_vehs_detect_sumo',471])472473def prepare_sim(self, process):474print 'Decompressors.prepare_sim'475net = self.get_scenario().net476nodes = net.nodes477edges = net.edges478lanes = net.lanes479ids_edge_sumo = edges.ids_sumo480481id_prtmode = self.parent.id_prtmode482self.decel = self.parent.prtvehicles.decel_emergency.get_value()483484ids = self.get_ids()485if len(ids) == 0:486return []487n_id_max = np.max(ids)+1488489self.ids_comp_to_ids_detectedge_sumo = np.zeros(n_id_max, dtype=np.object)490self.ids_comp_to_ids_detectedge_sumo[ids] = edges.ids_sumo[self.ids_detectoredge[ids]]491492# this is list of queues for all shunt lines for each compressor493self.queuess = np.zeros(n_id_max, dtype=np.object)494495# this is list of target edges for all shunt lines for each compressor496self.ids_targetedgess_sumo = np.zeros(n_id_max, dtype=np.object)497498# thses queus are the same as queuess but contains the allocated, but not yet arrived vehicles499self.queuess_alloc = np.zeros(n_id_max, dtype=np.object)500501# this is list of maximum queue length for all shunt lines for each compressor502self.capacitiess = np.zeros(n_id_max, dtype=np.object)503504# list with target edges for each queue for each compressor505#self.ids_edge_sumo_targets = np.zeros(n_id_max,dtype = np.object)506507# list with availabilities for each queue for each compressor508self.are_queues_avail = np.zeros(n_id_max, dtype=np.object)509510# releasetimes for each compressor511self.releasetimes = np.zeros(n_id_max, dtype=np.int32)512513# releasetimes for each queue for each compressor514self.releasetimes_queues = np.zeros(n_id_max, dtype=np.object)515516self.length_veh = self.parent.prtvehicles.get_length()517518# this queue contains all vehicles on the detect edge519# it is used to identify whether a new vehicle has left the merge520self.ids_vehs_detect_sumo = np.zeros(n_id_max, dtype=np.object)521522for id_comp, ids_shuntedge in zip(ids, self.ids_shuntedges[ids]):523print ' id_comp', id_comp524n_shunts = len(ids_shuntedge) # first edge is not a real shunt!!525526queues = n_shunts*[None]527queues_alloc = n_shunts*[None]528capacities = n_shunts*[None]529ids_targetedges_sumo = n_shunts*[None]530for i, length_edge in zip(range(n_shunts), edges.lengths[ids_shuntedge]):531capacities[i] = int((length_edge-25.0)/(self.length_veh+0.5))532queues[i] = []533queues_alloc[i] = []534ids_targetedges_sumo[i] = {}535536self.queuess[id_comp] = queues537self.queuess_alloc[id_comp] = queues_alloc538self.capacitiess[id_comp] = capacities539self.ids_targetedgess_sumo[id_comp] = ids_targetedges_sumo540#self.ids_edge_sumo_targets [id_comp] = n_shunts*['']541self.are_queues_avail[id_comp] = n_shunts*[True]542self.releasetimes_queues[id_comp] = np.arange(n_shunts)*int(self.time_accumulation_max.get_value()/n_shunts)543544self.ids_vehs_detect_sumo[id_comp] = set()545# print ' capacities',self.capacitiess[id_comp]546# print ' queues',self.queuess[id_comp]547548return [(self.time_update.get_value(), self.process_step),549]550551def process_step(self, process):552simtime = process.simtime553print 79*'_'554print 'Deompressors.process_step at', simtime555net = self.get_scenario().net556edges = net.edges557vehicles = self.parent.prtvehicles558ids = self.get_ids()559for id_comp,\560id_detectedge_sumo,\561ids_veh_detect_sumo,\562ids_shuntedge,\563queues,\564queues_alloc,\565capacities,\566are_queue_avail,\567releasetime_queues,\568ids_targetedges_sumo\569in zip(ids,570self.ids_comp_to_ids_detectedge_sumo[ids],571self.ids_vehs_detect_sumo[ids],572self.ids_shuntedges[ids],573self.queuess[ids],574self.queuess_alloc[ids],575self.capacitiess[ids],576self.are_queues_avail[ids],577self.releasetimes_queues[ids],578self.ids_targetedgess_sumo[ids]579):580n_queues = len(queues)581ids_shuntedge_sumo = edges.ids_sumo[ids_shuntedge]582print ' '+60*'|'583print ' Decompressor id_comp', id_comp, 'n_queues', n_queues584# check for new vehicle arrivals/departures585586ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_detectedge_sumo))587if 0:588print ' id_detectedge_sumo', id_detectedge_sumo589print ' ids_veh_detect_sumo', ids_veh_detect_sumo, ids_veh_detect_sumo != ids_veh_sumo590print ' ids_veh_sumo=', ids_veh_sumo591ids_veh_sumo_raw = traci.edge.getLastStepVehicleIDs(id_detectedge_sumo)592print ' ids_veh_sumo_raw=', ids_veh_sumo_raw593594if ids_veh_detect_sumo != ids_veh_sumo:595# there are new vehicles596597#ids_veh_entered_sumo, poss = vehicles.get_ids_sumo_sorted(ids_veh_sumo.difference(ids_veh_detect_sumo))598ids_veh_entered_sumo = list(ids_veh_sumo.difference(ids_veh_detect_sumo))599ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)600601if 1:602print ' ids_veh_entered', ids_veh_entered, type(ids_veh_entered)603# print ' poss',poss604print ' ids_veh_entered_sumo', ids_veh_entered_sumo605print ' ids_leader', vehicles.ids_leader[ids_veh_entered]606print ' ids_follower', vehicles.ids_follower[ids_veh_entered]607print ' lengths_plat', vehicles.lengths_plat[ids_veh_entered]608609for id_veh_entered, id_veh_entered_sumo, id_leader, length_plat\610in zip(ids_veh_entered, ids_veh_entered_sumo,611vehicles.ids_leader[ids_veh_entered],612vehicles.lengths_plat[ids_veh_entered]):613614# we cannot deconcatenate here, vehicles are in movement615# instead, measure if there is enough room for the platoon616# otherwise send platoon through bypass617if (length_plat > 0.001) & (id_leader == -1):618# vehicle is a platoon leader:619# find a queue that fits the platoon620id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]621# print ' dispatch id_veh_entered_sumo %s with target %s'%(id_veh_entered_sumo,id_targetedge_sumo)622623is_found_queue = False624costs = np.zeros(n_queues, dtype=np.float32)625for ind_queue, queue, is_avail, capa in zip(range(n_queues), queues, are_queue_avail, capacities):626627dl = (capa - len(queue)) * self.length_veh - 2*length_plat628# print ' ceck queue %d with capa %d, len = %d, dl=%d'%(ind_queue,capa,len(queue),dl)629if (dl > 0) & is_avail:630costs[ind_queue] = dl631else:632costs[ind_queue] = np.inf633634ind_queue = np.argmin(costs)635# print ' ind_queue,costs',ind_queue,costs636# if costs[ind_queue] <10000:# OK queue has been found637#ind_queue = ids_edge_sumo_target.index(id_targetedge_sumo)638#ind_queue = inds_queue[0]639queue = queues[ind_queue]640capa_queue = capacities[ind_queue]641len_queue = len(queue)642# print ' found ind_queue,len_queue,capa_queue',ind_queue,len_queue,capa_queue643# if len_queue < capa_queue:644self._alloc_queue(queue, queues_alloc[ind_queue],645ids_targetedges_sumo[ind_queue],646capa_queue,647id_veh_entered,648id_veh_entered_sumo,649id_targetedge_sumo,650ids_shuntedge[ind_queue],651ids_shuntedge_sumo[ind_queue],652vehicles, edges)653654elif (id_leader > -1):655# this is a follower:656# shunt it to the same edge as its leader657id_targetedge_sumo = traci.vehicle.getRoute(id_veh_entered_sumo)[-1]658id_platoonleader = vehicles.get_platoonleader(id_leader)659for ind_queue, queue, capa_queue, in zip(range(n_queues), queues, capacities):660if id_platoonleader in queue:661# print ' found id_platoonleader prt.%d of prt.%d at queue %d'%(id_platoonleader,id_veh_entered,ind_queue)662self._alloc_queue_follower(663queue, queues_alloc[ind_queue],664ids_targetedges_sumo[ind_queue],665capa_queue,666id_veh_entered,667id_veh_entered_sumo,668id_targetedge_sumo,669ids_shuntedge_sumo[ind_queue],670vehicles)671break672else:673# individual vehicle674pass675676# update veh on detector edge677self.ids_vehs_detect_sumo[id_comp] = ids_veh_sumo678679# (simtime - self.releasetimes[id_comp]> self.time_release_min.get_value()): # do this later ...simtime - self.releasetimes[id_comp]> 10:680if 1:681# now check if any of the vehicle in any of the queues has arrived682# and if a queue is complete, create a platoon, send it off and683# reset the queue684# print ' Deal with queues...'685is_released = False686for ind_queue, queue, queue_alloc,\687ids_targetedge_sumo, capacity,\688id_shuntedge_sumo, releasetime_queue\689in zip(690range(n_queues), queues, queues_alloc,691ids_targetedges_sumo, capacities,692edges.ids_sumo[ids_shuntedge], releasetime_queues):693if 0:694print ' QQQQQQQQQQQ shunt %s ' % (id_shuntedge_sumo)695print ' simtime-releasetime_queue', simtime-releasetime_queue, (simtime - releasetime_queue > 15), (simtime - self.releasetimes[id_comp] > 10)696print ' queue', queue, id(queue)697print ' ids_targetedge_sumo', ids_targetedge_sumo698print ' queue_alloc', queue_alloc699print ' releasetime_queue', releasetime_queue, simtime - releasetime_queue, simtime - releasetime_queue > self.time_accumulation_max.get_value()700# here we could also test timeout conditions701if (simtime - self.releasetimes[id_comp] > self.time_release_min.get_value()) & (simtime - releasetime_queue > self.time_accumulation_max.get_value()):702# if (simtime - self.releasetimes[id_comp]> self.time_release_min.get_value()):703704# check if allocated arrived705id_veh_arrived = -1706# for id_vehinfo,id_veh_sumo, length_plat in zip(range(),queue_alloc, vehicles.ids_sumo[queue_alloc],vehicles.lengths_plat[queue_alloc]):707708for id_veh in queue_alloc:709if vehicles.reached_stop_sumo(vehicles.ids_sumo[id_veh]):710id_veh_arrived = id_veh711break712713# print ' allocated prt.%d reached stop (-1 means no vehicle)'%(id_veh_arrived)714715if id_veh_arrived > -1:716# a platoon leader id_veh_arrived has arrived717718# print ' check if entire platoon arrived at the queue'719length_plat = vehicles.lengths_plat[id_veh_arrived]720ind_pl = queue.index(id_veh_arrived)721len_queue = len(queue)722ids_platoon = []723#ids_targetedge_plat_sumo= []724725if len_queue > ind_pl+1:726727for i, id_veh in zip(range(ind_pl+1, len_queue), queue[ind_pl+1:]):728# print ' check prt.%d with leader prt.%d'%(id_veh,vehicles.ids_leader[id_veh])729if vehicles.ids_leader[id_veh] != -1:730# print ' real lead prt.%d qlead prt.%d | plat lead prt.%d plat qlead prt.%d '%(vehicles.ids_leader[id_veh],queue[i-1],vehicles.get_platoonleader(id_veh),id_veh_arrived)731# if vehicles.ids_leader[id_veh] == queue[i-1]:732# print ' add'733# ids_platoon.append(id_veh)734#735if vehicles.get_platoonleader(id_veh) == id_veh_arrived:736# TODO: this is very inefficient, by happens737# when platoon has ben broken up during a merge operation738# idea: use a pointer to follower739ids_platoon.append(id_veh)740# ids_targetedge_plat_sumo.append(id_targetedge_sumo)741# print ' add'742else:743# is not a follower744pass745length_plat_arrived = len(ids_platoon)*self.length_veh + 0.5746# print ' arrived id_veh_arrived prt.%d at queue pos ind_pl=%d (should be 0)'%(id_veh_arrived,ind_pl)747# print ' with platoon length %.2fm greater %.2fm?'%(length_plat_arrived,length_plat)748749if (length_plat_arrived >= length_plat) & (not is_released):750# print ' entire platoon length in queue, now release...',ids_platoon751is_released = True752# reschedule leader753754vehicles.reschedule_trip(id_veh_arrived, ids_targetedge_sumo[id_veh_arrived])755id_veh_sumo = vehicles.get_id_sumo(id_veh_arrived)756#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)757#vehicles.control_slow_down( id_veh_arrived, speed = 6.0/3.6)758# print ' queue_alloc',queue_alloc759# print ' queue',queue760# deconcatenate and reschedule followers761for id_veh, id_veh_sumo in zip(ids_platoon[::-1], vehicles.ids_sumo[ids_platoon[::-1]]):762vehicles.decatenate(id_veh)763vehicles.reschedule_trip_sumo(id_veh_sumo, ids_targetedge_sumo[id_veh])764#vehicles.control_slow_down( id_veh, speed = 6.0/3.6)765#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)766queue.remove(id_veh)767del ids_targetedge_sumo[id_veh]768769releasetime_queues[ind_queue] = int(simtime)770self.releasetimes[id_comp] = int(simtime)771772# remove platoon leader773queue_alloc.remove(id_veh_arrived)774queue.remove(id_veh_arrived)775del ids_targetedge_sumo[id_veh_arrived]776777else:778print ' platoon incomplete'779else:780# print ' no leaders arrived in this quque'781pass782783def _alloc_queue(self, queue, queue_alloc, ids_targetedge_sumo, capa_queue,784id_veh, id_veh_sumo, id_targetedge_sumo,785id_shuntedge, id_shuntedge_sumo, vehicles, edges):786"""Queue allocation for platoon leader only."""787queue.append(id_veh)788789# store here also the target necessary to reprogram790queue_alloc.append(id_veh)791# TODO: idea, the original target should be stored in the vehicles db792ids_targetedge_sumo[id_veh] = id_targetedge_sumo793len_queue = len(queue)794795# make platoon leder always stop at the foremost position796pos_stop = 1.0 + capa_queue*(self.length_veh)797# print '_alloc_queue',id_veh_sumo,id_shuntedge_sumo,capa_queue-len_queue,pos_stop798vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)799vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex=0)800801# Forced exit of vehicle from merge conrol802self.parent.mergenodes.exit_veh_forced(id_veh, id_veh_sumo, vehicles)803804def _alloc_queue_follower(self, queue, queue_alloc, ids_targetedge_sumo,805capa_queue,806id_veh, id_veh_sumo, id_targetedge_sumo,807id_shuntedge_sumo, vehicles):808"""Queue allocation for follower only."""809queue.append(id_veh)810# TODO: idea, the original target should be stored in the vehicles db811ids_targetedge_sumo[id_veh] = id_targetedge_sumo812# queue_alloc.append(id_veh)813#len_queue = len(queue)814815# make platoon leder always stop at the foremost position816#pos_stop = 1.0 + capa_queue*(self.length_veh + 0.5)817# print '_alloc_queue_follower',id_veh_sumo,id_shuntedge_sumo,id_targetedge_sumo818vehicles.reschedule_trip_sumo(id_veh_sumo, id_shuntedge_sumo)819#vehicles.set_stop(id_veh, id_shuntedge_sumo, pos_stop, laneindex = 0)820821822# class Shortmergenodes(Mergenodes):823824class Mergenodes(am.ArrayObjman):825def __init__(self, ident, prtservices, **kwargs):826self._init_objman(ident=ident,827parent=prtservices,828name='Merge nodes',829info='Contains information and methods for merging the flow of two vehicle streams, including platoons.',830version=0.2,831**kwargs)832self._init_attributes()833834def _init_attributes(self):835#self.add(cm.ObjConf(PrtBerths('berths',self)) )836837self.add(cm.AttrConf('time_update', 0.5,838groupnames=['parameters'],839name='Update time',840info="Update time for merges.",841unit='s',842))843844net = self.get_scenario().net845846self.add_col(am.IdsArrayConf('ids_node', net.nodes,847name='Node ID',848info='Network node ID.',849is_index=True,850))851852# self.add_col(am.IdsArrayConf('ids_edge_in1', net.edges,853# name = 'ID edge 1',854# info = 'ID of edge at entrance 1.',855# ))856if self.get_version() < 0.2:857self.delete('ids_mergenode_in1')858self.delete('ids_mergenode_in2')859self.delete('ids_mergenodes_out')860self.delete('distances_mergenode_in1')861self.delete('distances_mergenode_in2')862863self.add_col(am.IdsArrayConf('ids_node_in1', net.nodes,864name='ID node in 1',865info='ID of upstream network node at incoming line 1.',866))867868self.add_col(am.ArrayConf('distances_node_in1', 0.0,869groupnames=['parameters'],870name='Distance node in 1',871info="Distance to network node at incoming line 1.",872unit='m',873))874875# self.add_col(am.IdsArrayConf('ids_edge2', net.edges,876# name = 'ID edge 2',877# info = 'ID of edge at entrance 2.',878# ))879880self.add_col(am.IdsArrayConf('ids_node_in2', net.nodes,881name='ID node in 2',882info='ID of upstream network node at incoming line 2.',883))884885self.add_col(am.ArrayConf('distances_node_in2', 0.0,886groupnames=['parameters'],887name='Distance mergenode in 2',888info="Distance to upstream network node at incoming line 2.",889unit='m',890))891892self.add_col(am.IdlistsArrayConf('ids_nodes_out', net.nodes,893name='IDs nodes out',894info='IDs of downstream network nodes.',895))896897self.add_col(am.ArrayConf('are_station', default=False,898groupnames=['parameters'],899name='is station',900info="Node is the exit node of a station, comressor or decompressor. The incoming edge of this are internal and are not considered.",901))902903self.add_col(am.ArrayConf('are_entry', default=False,904groupnames=['parameters'],905name='is entry',906info="Node is a merge wich receives an entry line from a station, comressor or decompressor. This shorter line is always input line 1 and expects that vehicles have a speed close to zero.",907))908909self.set_version(0.2)910911def _init_constants(self):912self.do_not_save_attrs([913'ids_merge_to_ids_node_sumo', 'ids_merge_to_ids_edge_out_sumo',914'ids_node_to_ids_merge', 'ids_vehs_out_sumo,'915'ids_vehs_in1', 'ids_vehs_in1_sumo',916'ids_vehs_in2', 'ids_vehs_in2_sumo',917'ids_vehs_merged', 'ids_vehs_merged_sumo', 'odos_vehs_merged',918'lineinds_vehs_merged', 'vehicle_to_merge',919'vehicles_entries', 'vehicles_mains',920])921922def make_from_net(self):923"""924Make merge node database from network.925"""926print 'Mergenodes.make_from_net'927self.clear()928id_prtmode = self.parent.id_prtmode929930net = self.get_scenario().net931nodes = net.nodes932edges = net.edges933lanes = net.lanes934id_zippertype = nodes.types.choices['zipper']935936compressors = self.parent.compressors937decompressors = self.parent.decompressors938ids_detectoredges = set(compressors.ids_detectoredge.get_value())939ids_detectoredges.update(decompressors.ids_detectoredge.get_value())940941distances = edges.get_distances(is_precise=True)942943# debug944ids_edge = edges.get_ids()945print 'distances:'946for id_edge, id_edge_sumo, length, dist in zip(ids_edge, edges.ids_sumo[ids_edge], edges.lengths[ids_edge], distances[ids_edge]):947print ' id_edge=%d id_edge_sumo=%s length=%.1f dist=%.1f' % (id_edge, id_edge_sumo, length, dist)948949ids_shuntedges = set()950ids_mainlinedges = set()951952ids = compressors.get_ids()953for id_unit, ids_edge in zip(ids, compressors.ids_shuntedges[ids]):954# put in all shunts except for the bypass955print ' bypass of compressor', id_unit, '=', ids_edge[0]956ids_mainlinedges.add(ids_edge[0])957print ' update ids_shuntedges with compressors', ids_edge[1:]958ids_shuntedges.update(ids_edge[1:])959960# collect decompressornodes, wich will not become entry merges961ids = decompressors.get_ids()962ids_node_decompressorout = []963for id_unit, ids_edge in zip(ids, decompressors.ids_shuntedges[ids]):964# put in all shunts except for the bypass965print ' bypass of decompressor', id_unit, '=', ids_edge[0], 'id_tonode', edges.ids_tonode[ids_edge[0]]966ids_mainlinedges.add(ids_edge[0])967ids_node_decompressorout.append(edges.ids_tonode[ids_edge[0]])968print ' update ids_shuntedges with decompressors', ids_edge[1:]969ids_shuntedges.update(ids_edge[1:])970print ' ids_node_decompressorout', ids_node_decompressorout971ids_node_compressorout = edges.ids_tonode[list(ids_mainlinedges)]972ids_mainlinefromnodes = edges.ids_fromnode[list(ids_mainlinedges)]973974# now put also all incoming edges of main lines as shunts975# in order to cut of compressor entrance from downstrem search976# for id_edge in ids_mainlinedges:977# print ' update ids_shuntedges with mainline incoming',edges.get_incoming(id_edge)978# ids_shuntedges.update(edges.get_incoming(id_edge))979980print ' ids_shuntedges', ids_shuntedges981#ids_ptstop = ptstops.get_ids()982#id_mode_prt = self.parent.id_prtmode983984#ids_edges = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]985#ids_lanes = net.edges.ids_lanes[ids_edges]986#ids_lane = ptstops.ids_lane[ids_ptstop]987#edgelengths = net.edges.lengths988989ids_node = nodes.get_ids()990print ' ids_node', ids_node991for id_node, ids_edge_from, ids_edge_to, id_type in zip(992ids_node,993nodes.ids_incoming[ids_node],994nodes.ids_outgoing[ids_node],995nodes.types[ids_node],996):997998if True:999#10001001print 79*'-'1002print ' check node', id_node, nodes.ids_sumo[id_node], id_type, id_zippertype == id_type1003print ' ids_edge_from', ids_edge_from1004print ' ids_edge_to', ids_edge_to1005# id merge to be created, for debugging1006id_merge = -110071008if (ids_edge_from is None) | (ids_edge_to is None):1009print ' WARNING: isolate node: ids_edge_from,ids_edge_to', ids_edge_from, ids_edge_to1010pass10111012elif (len(ids_edge_from) == 2) & (len(ids_edge_to) == 1):10131014# ids_mainlinedges.add(ids_edge[0])1015# ids_shuntedges.update(ids_edge[1:])10161017# check accesslevels1018id_edge1, id_edge2 = ids_edge_from1019ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_from]1020print ' id_edge1', id_edge1, 'ids_lane1', ids_lane1, self.is_prt_only(ids_lane1, lanes)1021print ' id_edge2', id_edge2, 'ids_lane2', ids_lane2, self.is_prt_only(ids_lane2, lanes)1022if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):1023print ' +PRT merge with 2 PRT lines entering'10241025if id_type != id_zippertype:1026print 'WARNING: PRT network node %d %s is NOT in zipper mode!' % (id_node, nodes.ids_sumo[id_node])10271028# elif not ids_mainlinedges.isdisjoint(ids_edge_from):1029# print ' one incoming line is the bypass'1030# ids_node_out = self.search_downstream_merges(ids_edge_to[0], edges, lanes, id_prtmode)1031#1032# # model this node as a station output1033# self.add_row( ids_node = id_node,1034# ids_nodes_out = ids_node_out,1035# are_station = True,1036# )10371038else:1039print ' make regular merge'1040print ' branch 1:'1041id_node_up1, dist1 = self.search_upstream_merge(1042id_edge1, edges, lanes, id_prtmode, distances=distances)1043print ' id_node_up1', id_node_up1, 'dist1', dist110441045print '\n branch 2:'1046id_node_up2, dist2 = self.search_upstream_merge(1047id_edge2, edges, lanes, id_prtmode, distances=distances)1048print ' id_node_up2', id_node_up1, 'dist2', dist2, '\n'10491050ids_node_out = self.search_downstream_merges(1051ids_edge_to[0], edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)1052id_merge = self.add_row(ids_node=id_node,1053ids_node_in1=id_node_up1,1054distances_node_in1=dist1,1055ids_node_in2=id_node_up2,1056distances_node_in2=dist2,1057ids_nodes_out=ids_node_out,1058are_station=False,1059)10601061elif (len(ids_edge_from) == 1) & (len(ids_edge_to) == 2):10621063id_edge_from = ids_edge_from[0]1064ids_lane_in = edges.ids_lanes[id_edge_from]1065#al_in = lanes.get_accesslevel(edges.ids_lanes[id_edge_from], id_prtmode)1066#is_prt_in = lanes.ids_modes_allow[edges.ids_lanes[id_edge_from]] == id_prtmode1067is_prt_in = self.is_prt_only(ids_lane_in, lanes)1068print ' one in, 2 out => diverge node, access is_prt_in', is_prt_in, 'is_platform_in', self.is_platform(ids_lane_in, lanes)10691070# if id_edge_from in ids_detectoredges:1071# print ' fromnode is a detectoredge of a compressor'1072# id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)1073# self.add_row( ids_node = id_node,1074# ids_node_in1 = id_node_up,1075# distances_node_in1 = dist,1076# #ids_nodes_out = ids_node_out,1077# are_station = True,1078# )10791080# check if node is outgoing node at a station1081if 0: # no longer considered1082if is_prt_in & (id_node in ids_mainlinefromnodes):1083print ' Diverge node in front of a compressor/decompressorr.'1084id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)10851086id_edge1, id_edge2 = ids_edge_to1087if id_edge1 in ids_mainlinedges:1088id_edge = id_edge11089else:1090id_edge = id_edge210911092#ids_node_out = self.search_downstream_merges(id_edge, edges, lanes, id_prtmode, ids_sinkedge = ids_shuntedges)1093ids_node_out = [edges.ids_tonode[id_edge]]1094self.add_row(ids_node=id_node,1095ids_node_in1=id_node_up,1096distances_node_in1=dist,1097ids_nodes_out=ids_node_out,1098are_station=True,1099)11001101if self.is_platform(ids_lane_in, lanes):1102print ' mixed access level of incoming edge, check for platform exit node'11031104id_edge1, id_edge2 = ids_edge_to1105ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_to]11061107# here we could also decide on the number of lanes1108# but this may not be robust in the future1109print ' out id_edge1', id_edge1, 'ids_lane1', ids_lane1, 'is_prt_only', self.is_prt_only(ids_lane1, lanes)1110print ' out id_edge2', id_edge2, 'ids_lane2', ids_lane2, 'is_prt_only', self.is_prt_only(ids_lane2, lanes)1111# if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):1112if self.is_prt_only(ids_lane2, lanes):11131114print ' Ped exit on outedge 1'1115#id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)1116ids_node_out = self.search_downstream_merges(1117id_edge2, edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)1118id_merge = self.add_row(ids_node=id_node,1119#ids_node_in1 = id_node_up,1120#distances_node_in1 = dist,1121ids_nodes_out=ids_node_out,1122are_station=True,1123)11241125elif self.is_prt_only(ids_lane1, lanes):1126print ' Ped exit on outedge 2'1127#id_node_up, dist = self.search_upstream_merge(id_edge_from, edges, lanes, id_prtmode)1128ids_node_out = self.search_downstream_merges(1129id_edge1, edges, lanes, id_prtmode, ids_sinkedge=ids_shuntedges)1130id_merge = self.add_row(ids_node=id_node,1131#ids_node_in1 = id_node_up,1132#distances_node_in1 = dist,1133ids_nodes_out=ids_node_out,1134are_station=True,1135)11361137if id_merge >= 0:1138self.print_attrs(ids=[id_merge, ])1139print '\n now check if merge has entry line form stations or compressors'11401141ids = self.get_ids()1142i = 01143while i < len(ids):1144id_merge = ids[i]11451146id_node_in1 = self.ids_node_in1[id_merge]1147id_node_in2 = self.ids_node_in2[id_merge]1148print 79*'-'1149print ' check entry of id_merge', id_merge, 'id_node', self.ids_node[id_merge], ' no decomp', self.ids_node[id_merge] not in ids_node_decompressorout1150if (id_node_in1 > -1) & (id_node_in2 > -1)\1151& (self.ids_node[id_merge] not in ids_node_decompressorout):11521153print ' id_node_in1', self.ids_node_in1[id_merge], nodes.ids_sumo[self.ids_node_in1[id_merge]], self.ids_node.has_index(self.ids_node_in1[id_merge])1154print ' id_node_in2', self.ids_node_in2[id_merge], nodes.ids_sumo[self.ids_node_in2[id_merge]], self.ids_node.has_index(self.ids_node_in2[id_merge])1155if 1:11561157print ' self.ids_node._index_to_id', self.ids_node._index_to_id11581159id_merge_in1 = self.ids_node.get_id_from_index(self.ids_node_in1[id_merge])1160id_merge_in2 = self.ids_node.get_id_from_index(self.ids_node_in2[id_merge])11611162print ' station check id_merge', id_merge, 'id_merge_in1', id_merge_in1, 'station', self.are_station[id_merge_in1], 'id_merge_in2', id_merge_in2, 'station', self.are_station[id_merge_in2]11631164if self.are_station[id_merge_in2]:1165self.are_entry[id_merge] = True1166# in line 2 is already entry line1167pass11681169elif self.are_station[id_merge_in1]:1170self.are_entry[id_merge] = True1171# move entry line from inline 1 to inline 211721173id_node_in2 = self.ids_node_in2[id_merge]1174dist2 = self.distances_node_in2[id_merge]11751176self.ids_node_in2[id_merge] = self.ids_node_in1[id_merge]1177self.distances_node_in2[id_merge] = self.distances_node_in1[id_merge]11781179self.ids_node_in1[id_merge] = id_node_in21180self.distances_node_in1[id_merge] = dist211811182i += 111831184def get_scenario(self):1185return self.parent.get_scenario()11861187def prepare_sim(self, process):1188print 'Mergenodes.prepare_sim'1189net = self.get_scenario().net1190nodes = net.nodes1191edges = net.edges1192lanes = net.lanes1193ids_edge_sumo = edges.ids_sumo11941195id_prtmode = self.parent.id_prtmode1196self.decel = self.parent.prtvehicles.decel_emergency.get_value()11971198ids = self.get_ids()1199if len(ids) == 0:1200return []1201n_id_max = np.max(ids)+112021203# database with vehicle id as key and controlling merge as value1204self.vehicle_to_merge = {}12051206# vehicle database for merge operation1207self.vehicles_entries = {}12081209# TODO: this is only used to indicate that a vehicle on main1210# is involved in merging with entry line.1211# A simple set per merge would suffice1212self.vehicles_mains = {}12131214#self.ids_merge_to_ids_node_sumo = np.zeros(n_id_max,dtype = np.object)1215#self.ids_merge_to_ids_node_sumo[ids] = nodes.ids_sumo[self.ids_node[ids]]12161217self.ids_merge_to_ids_edge_out_sumo = np.zeros(n_id_max, dtype=np.object)1218#self.ids_node_to_ids_edge_out_sumo = np.zeros(n_id_max,dtype = np.object)1219self.ids_node_to_ids_merge = np.zeros(np.max(self.ids_node[ids])+1, dtype=np.int32)1220self.ids_node_to_ids_merge[self.ids_node[ids]] = ids12211222# this queue contains all vehicles on the outgoing edge1223# it is used to identify whether a new vehicle has left the merge1224self.ids_vehs_out_sumo = np.zeros(n_id_max, dtype=np.object)12251226# this queue contains all vehicles on line 1 between1227# merge and id_node_in11228self.ids_vehs_in1 = np.zeros(n_id_max, dtype=np.object)1229self.ids_vehs_in1_sumo = np.zeros(n_id_max, dtype=np.object)12301231# this queue contains all vehicles on line 2 between1232# merge and id_node_in21233self.ids_vehs_in2 = np.zeros(n_id_max, dtype=np.object)1234self.ids_vehs_in2_sumo = np.zeros(n_id_max, dtype=np.object)12351236# this queue contains the merged vehicles for the controlled range1237self.ids_vehs_merged = np.zeros(n_id_max, dtype=np.object)1238self.ids_vehs_merged_sumo = np.zeros(n_id_max, dtype=np.object)12391240# this queuse contains the line index (1 or 2, 0= not assigned)1241self.lineinds_vehs_merged = np.zeros(n_id_max, dtype=np.object)12421243# odometer of vehicle when vehicle enters merge1244self.odos_vehs_merged = np.zeros(n_id_max, dtype=np.object)12451246# this is the first and last vehicle of a platoon that is about to exit th merge1247# the platoon will wait for exit from merge until the entire platoon1248# passed the merge node. This means the last vehicle of the platoon1249# must be detected on the exit edge.1250self.ids_plat_wait_exit = -1*np.ones((n_id_max, 2), dtype=np.int32)12511252#self.ids_merge_to_ids_edge_out_sumo[ids] = edges.ids_sumo[self.ids_node[ids]]1253ids_node = self.ids_node[ids]1254for id_merge, id_node, ids_edge_out in zip(ids, ids_node, nodes.ids_outgoing[ids_node]):1255if len(ids_edge_out) == 1:1256# regular merge1257self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[ids_edge_out[0]]12581259elif len(ids_edge_out) == 2:1260# one edge is PRT, the other ped access1261# check accesslevels1262id_edge1, id_edge2 = ids_edge_out1263ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_out]1264al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)1265al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)1266if al1 == 2:1267self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge1]1268#self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge1]1269if al2 == 2:1270self.ids_merge_to_ids_edge_out_sumo[id_merge] = ids_edge_sumo[id_edge2]1271#self.ids_node_to_ids_edge_out_sumo[id_node] = ids_edge_sumo[id_edge2]12721273self.ids_vehs_out_sumo[id_merge] = set()12741275self.ids_vehs_in1[id_merge] = list()1276self.ids_vehs_in1_sumo[id_merge] = list()12771278self.ids_vehs_in2[id_merge] = list()1279self.ids_vehs_in2_sumo[id_merge] = list()12801281self.ids_vehs_merged[id_merge] = list()1282self.ids_vehs_merged_sumo[id_merge] = list()1283self.lineinds_vehs_merged[id_merge] = list()1284self.odos_vehs_merged[id_merge] = list()12851286self.vehicles_entries[id_merge] = OrderedDict()12871288# A simple set per merge would suffice1289self.vehicles_mains[id_merge] = OrderedDict()12901291return [(self.time_update.get_value(), self.process_step),1292]12931294def process_step(self, process):1295simtime = process.simtime1296print 79*'_'1297print 'Mergenodes.process_step at', simtime1298net = self.get_scenario().net1299vehicles = self.parent.prtvehicles13001301# if vehicles.id_follower_probe != vehicles.ids_follower[271]:1302# print 'MERGE WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]13031304ids = self.get_ids()1305for id_merge, id_node, id_edge_out, ids_node_out, ids_veh_out_sumo, is_entry in\1306zip(ids,1307self.ids_node[ids],1308self.ids_merge_to_ids_edge_out_sumo[ids],1309self.ids_nodes_out[ids],1310self.ids_vehs_out_sumo[ids],1311self.are_entry[ids],1312):1313print ' '+60*'.'13141315####1316debug = False # id_merge in [24,22,19]1317# debug = id_merge in [59,18,15,16] #(id_merge==2)|(id_merge==7)1318# debug = (id_merge==1)|('gneJ1' in net.nodes.ids_sumo[ids_node_out])#'gneJ29':#'gneJ1':1319#debug = debug | (id_merge==17)| ('gneJ29' in net.nodes.ids_sumo[ids_node_out])13201321###1322print ' process id_merge', id_merge, ',id_node', id_node, net.nodes.ids_sumo[id_node], 'debug', debug13231324# check for new vehicle arrivals/departures1325ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_out))13261327# if debug:1328# print ' check id_edge_out',id_edge_out1329# print ' ids_veh_out_sumo=',ids_veh_out_sumo1330# print ' ids_veh_sumo=',ids_veh_sumo1331# print ' ids_node_out',ids_node_out1332# print ' ids_vehs_merged_sumo',self.ids_vehs_merged_sumo[id_merge]13331334if ids_veh_out_sumo != ids_veh_sumo:13351336# attention, this is a list, not an array with numpy indexing1337ids_veh_entered_sumo = list(ids_veh_sumo.difference(ids_veh_out_sumo))13381339# this is an array1340ids_veh_entered = vehicles.get_ids_from_ids_sumo(ids_veh_entered_sumo)1341#ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo)))13421343if debug:1344print ' ids_veh_entered', ids_veh_entered, type(ids_veh_entered)1345# print ' ids_veh_entered_sumo',ids_veh_entered_sumo1346# print ' ids_leader',vehicles.ids_leader[ids_veh_entered]13471348if ids_node_out is None:1349# the present merge is an end node example at a station1350ids_merge_out = []1351else:1352# determine id merge according to given output node1353ids_merge_out = self.ids_node_to_ids_merge[ids_node_out]13541355ids_edge_mergeout_sumo = self.ids_merge_to_ids_edge_out_sumo[ids_merge_out]1356# if debug:1357# print ' ids_node_out',ids_node_out1358# print ' ids_merge_out',ids_merge_out1359# print ' ids_edge_mergeout_sumo',ids_edge_mergeout_sumo1360# print ' ids_leader',vehicles.ids_leader[ids_veh_entered]1361# merge only vehicle without a leader (individual or first in a platoon)13621363# check first if the last vehicle of an exiting platoon1364# entered the out edge13651366id_veh_first, id_veh_last = self.ids_plat_wait_exit[id_merge]1367if id_veh_first > -1:1368if debug > 0:1369print ' platoon waiting for exit: id_veh_first prt.%d, id_veh_last prt.%d' % (id_veh_first, id_veh_last)1370inds_entered = np.flatnonzero(vehicles.ids_leader[ids_veh_entered] > -1)1371if np.any(id_veh_last == ids_veh_entered[inds_entered]):1372if debug > 0:1373print ' last vehicle of platoon left merge -> exit leader prt.%d' % id_veh_first1374self.exit_veh(id_veh_first, vehicles.get_id_sumo(id_veh_first), id_merge, vehicles, debug=debug)1375self.ids_plat_wait_exit[id_merge] = [-1, -1]13761377if self.ids_plat_wait_exit[id_merge][0] == -1:1378# no platoon waiting for exit1379inds_entered = np.flatnonzero(vehicles.ids_leader[ids_veh_entered] == -1)1380else:1381# platoon waiting for exit, so do not check for new leaders1382inds_entered = []13831384if debug:1385print ' inds_entered', inds_entered1386if len(inds_entered) > 0:1387for ind_entered, id_veh in zip(inds_entered, ids_veh_entered[inds_entered]):13881389id_veh_sumo = ids_veh_entered_sumo[ind_entered]1390if debug > 0:1391print ' >>try exiting vehicle', id_veh_sumo, 'is_leader', vehicles.ids_leader[id_veh] == -1, 'ids_node_out', ids_node_out, 'ids_merge_out', ids_merge_out13921393# print ' route_sumo',route_sumo13941395if ids_node_out is not None:13961397# check whether all platoon vehicles are on out edge1398id_veh_last = vehicles.get_platoontail(id_veh)1399if (id_veh_last != id_veh):1400if id_veh_last not in ids_veh_entered:1401if debug:1402print ' wait for last plat vehicle', id_veh_last1403self.ids_plat_wait_exit[id_merge] = [id_veh, id_veh_last]1404else:1405if debug:1406print ' last plat vehicle', id_veh_last, 'after merge node, exit', id_veh_sumo1407self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles, debug=debug)1408else:1409if debug:1410print ' vehicle', id_veh, 'has no platoon, exit', id_veh_sumo1411self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles, debug=debug)14121413# exit from previous merge1414# if debug:1415# print ' vehicle',id_veh_sumo,'exits id_merge',id_merge14161417if debug > 0:1418print ' check which out mergenode are on the current route of the vehicle'14191420if len(ids_merge_out) > 0:14211422# inform the respectine merges1423# then communicate vehicle with dist to merge1424# attention, we need the first hit in the route1425# check which downstream merge to enter1426route_sumo = get_traci_route(id_veh_sumo)14271428routeinds = [INFINT]*len(ids_merge_out)1429# print ' ids_merge_out',ids_merge_out1430i = 01431for id_edge_sumo in ids_edge_mergeout_sumo:14321433if id_edge_sumo in route_sumo:1434routeinds[i] = route_sumo.index(id_edge_sumo)1435i += 114361437mergeind = np.argmin(routeinds)14381439if debug: # debug>0:1440print ' route_sumo', route_sumo1441print ' routeinds', routeinds, 'downstream merge', routeinds[mergeind] < INFINT1442# print ' ids_edge_mergeout_sumo',ids_edge_mergeout_sumo1443# print ' mergeind,routeinds',mergeind,routeinds1444# print ' ids_merge_out[mergeind]',ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind]14451446if routeinds[mergeind] < INFINT:1447if debug:1448print ' next merge is on the route'1449if self.are_entry[ids_merge_out[mergeind]]:1450if debug:1451print ' call enter_veh_entry id_merge_out', ids_merge_out[mergeind]1452self.enter_veh_entry(1453id_veh, id_veh_sumo, id_merge, ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind], vehicles, debug=debug)1454else:1455if debug:1456print ' call enter_veh id_merge_out', ids_merge_out[mergeind]1457self.enter_veh(1458id_veh, id_veh_sumo, id_merge, ids_merge_out[mergeind], ids_edge_mergeout_sumo[mergeind], vehicles, debug=debug)1459else:1460# no downstream merge, vehicle goes into a station1461pass1462else:1463# print ' ids_node_out is empty means that there is a station or compressor'1464pass14651466else:1467# ids_node_out is None1468if debug:1469print ' There is a station or compressor shunt edges next'1470print ' completely disconnect from all merge and ghost controlls'14711472# exit from previous merge1473self.exit_veh(id_veh, id_veh_sumo, id_merge, vehicles)14741475# update vehicles on detection edge1476self.ids_vehs_out_sumo[id_merge] = ids_veh_sumo14771478# process special merge decisions and processes for entry merge types1479if is_entry:1480self.process_step_entry(id_merge, vehicles, debug)14811482if 0:1483print '========check mergeprocess'1484for id_merge, id_node_sumo, ids_veh_merged_sumo, ids_veh_merged in\1485zip(ids,1486net.nodes.ids_sumo[self.ids_node[ids]],1487self.ids_vehs_merged_sumo[ids],1488self.ids_vehs_merged[ids]1489):14901491print ' ', id_merge, id_node_sumo, ids_veh_merged_sumo1492# print ' ids_veh_merged',ids_veh_merged14931494def exit_veh(self, id_veh, id_veh_sumo, id_merge_from, vehicles, is_remove_from_control=False, debug=0):1495print 'exit_veh id_veh %s, id_merge_from %d ' % (id_veh_sumo, id_merge_from), 'entry', self.are_entry[id_merge_from], 'is_remove_from_control', is_remove_from_control14961497# print ' check for platooned vehicles:'1498# vehicles.get_platoon(id_veh)1499# in id_merge_from: take vehicle out of merged queue and input queue15001501if id_veh in self.ids_vehs_merged[id_merge_from]:1502# enterd veh should be in pole position in merge queue of merge_from15031504# pop if vehicles are properly merged1505# id_veh_from = self.ids_vehs_merged[id_merge_from].pop()1506# self.ids_vehs_merged_sumo.ids_vehs_merged[id_merge_from].pop()1507# if id_veh_from != id_veh:1508# print 'WARNING in enter_veh: veh %d instead of veh %d in polepos of merge %d'%(id_veh_from,id_veh, id_merge_from)1509# return False1510# lineind = self.lineinds_vehs_merged[id_merge_from].pop()1511# for testing: just remove, no matter where1512ind_pos = self.ids_vehs_merged[id_merge_from].index(id_veh)1513lineind = self.lineinds_vehs_merged[id_merge_from][ind_pos]15141515if len(self.ids_vehs_merged[id_merge_from]) > ind_pos+1:1516# there is a vehicle behind=> remove ghost from vehicle behind to tail veh15171518id_veh_behind = self.ids_vehs_merged[id_merge_from][ind_pos+1]1519id_veh_tail = vehicles.get_platoontail(id_veh) # get last in platoon1520if debug > 0:1521print ' del ghost from veh behind prt.%d to platoon tail prt.%d' % (id_veh_behind, id_veh_tail)1522vehicles.del_ghost(id_veh_behind, id_veh_tail)1523if debug > 0:1524print ' check ghosts of behind prt.%d:' % id_veh_behind, vehicles.ids_ghosts[id_veh_behind]1525# is there a vehicle in front of the removed vehicle1526# this happens if a vehicle is interactively deviated1527if ind_pos > 0:15281529id_veh_infront = self.ids_vehs_merged[id_merge_from][ind_pos-1]1530id_veh_tail = vehicles.get_platoontail(id_veh_infront) # get last in platoon15311532id_edge_mergeout_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_from]1533dist_to_merge_behind = get_traci_distance(1534vehicles.get_id_sumo(id_veh_behind), id_edge_mergeout_sumo, 3.0)1535dist_to_merge_infront = get_traci_distance(1536vehicles.get_id_sumo(id_veh_infront), id_edge_mergeout_sumo, 3.0)1537if debug:1538print ' now let the vehicle behind %d, d=%.2f' % (id_veh_behind, dist_to_merge_behind), 'see the vehicle in front %d, d=%.2f' % (id_veh_infront, dist_to_merge_infront)15391540vehicles.add_ghost(id_veh_behind, id_veh_tail, dist_to_merge_behind, dist_to_merge_infront)1541if debug > 0:1542print ' check ghosts of behind prt.%d:' % id_veh_behind, vehicles.ids_ghosts[id_veh_behind]15431544# remove any possible ghosts from this vehicle to vehicles behind1545# this can happen if this vehicle passed by its ghost vehicle1546# should no longer happen1547# vehicles.del_ghosts(id_veh)1548if debug > 0:1549print ' check ghosts of prt.%d (no ghosts from this merge?):' % id_veh, vehicles.ids_ghosts[id_veh]15501551self.ids_vehs_merged[id_merge_from].pop(ind_pos) # remove(id_veh)1552self.ids_vehs_merged_sumo[id_merge_from].pop(ind_pos) # remove(id_veh_sumo)1553self.lineinds_vehs_merged[id_merge_from].pop(ind_pos)1554self.odos_vehs_merged[id_merge_from].pop(ind_pos)15551556# remove vehicle from line buffers1557if lineind == 1:1558# vehicle in main line1559self.ids_vehs_in1[id_merge_from].remove(id_veh) # pop()1560self.ids_vehs_in1_sumo[id_merge_from].remove(id_veh_sumo) # .pop()1561if self.are_entry[id_merge_from]:1562if debug:1563print ' vehicle is involved in entry merge processes?', self.vehicles_mains[id_merge_from].has_key(id_veh)15641565if self.vehicles_mains[id_merge_from].has_key(id_veh):1566if self.vehicles_entries[id_merge_from].has_key(id_veh):1567state_veh = self.vehicles_entries[id_merge_from][id_veh]1568if state.has_key('id_veh_infront'):1569id_veh_infront = state['id_veh_infront']1570id_veh_infront_sumo = vehicles.ids_sumo[id_veh_infront]1571id_veh_infront_sumo_eff, dist_eff = getLeader(id_veh_infront_sumo)1572print ' should have this veh in front:', id_veh_infront_sumo, 'leader', id_veh_infront_sumo_eff, 'd=%.1fm' % dist_eff1573if id_veh_infront_sumo_eff != id_veh_infront_sumo:1574print 'ERROR: faled merge of ', id_veh_sumo, 'exiting merge', id_merge_from1575sys.exit(1)1576#1577#id_veh_entry = self.vehicles_mains[id_merge_from][id_veh]15781579# TODO: this is still a lousy method, vehicles_mains neds to be improved1580for id_veh_entry, state in zip(self.vehicles_entries[id_merge_from].keys(), self.vehicles_entries[id_merge_from].values()):1581#state = self.vehicles_entries[id_merge_from][id_veh_entry]1582# if debug:1583# print ' state before',state1584if state.has_key('id_veh_infront'):1585if state['id_veh_infront'] == id_veh:1586del state['id_veh_infront']1587if state.has_key('id_veh_behind'):1588if state['id_veh_behind'] == id_veh:1589del state['id_veh_behind']1590# if debug:1591# print ' state after',state15921593del self.vehicles_mains[id_merge_from][id_veh]15941595if lineind == 2:1596# vehicle in entry line1597self.ids_vehs_in2[id_merge_from].remove(id_veh) # .pop()1598self.ids_vehs_in2_sumo[id_merge_from].remove(id_veh_sumo) # .pop()15991600if self.are_entry[id_merge_from]:1601if debug:1602print ' del veh prt.%s from vehicles_entries' % id_veh1603del self.vehicles_entries[id_merge_from][id_veh]1604else:1605pass16061607# remove from centralized database1608#del self.vehicle_to_merge[id_veh]16091610else:1611# the entered vehicle is not in a merge queue1612# probably a new vehicle at station16131614# just be sure that the vehicle is not in any queue1615# but actually this cannot happen1616if id_veh in self.ids_vehs_in1[id_merge_from]:1617print 'WARNING in exit_veh: new veh %d should not be in inqueue 1' % id_veh1618self.ids_vehs_in1[id_merge_from].remove(id_veh)1619self.ids_vehs_in1_sumo[id_merge_from].remove(id_veh_sumo)16201621if id_veh in self.ids_vehs_in2[id_merge_from]:1622print 'WARNING in exit_veh: new veh %d should not be in inqueue 2' % id_veh1623self.ids_vehs_in2[id_merge_from].remove(id_veh)1624self.ids_vehs_in2_sumo[id_merge_from].remove(id_veh_sumo)16251626# if self.vehicle_to_merge.has_key(id_veh):1627# del self.vehicle_to_merge[id_veh]16281629if is_remove_from_control:1630# remove any merge control operations1631vehicles.del_all_ghosts(id_veh)16321633def exit_veh_forced(self, id_veh, id_veh_sumo, vehicles):1634"""Used by decompressors to remove a vehicle from merge control"""1635if self.vehicle_to_merge.has_key(id_veh):1636# exit vehicle from respective merge1637self.exit_veh(id_veh, id_veh_sumo, self.vehicle_to_merge[id_veh], vehicles, is_remove_from_control=True)1638else:1639# id_veh not under any merge conrol1640pass16411642def print_vehs(self, id_veh1, id_veh2, dist1_min, dist1_max, dist2_min, dist2_max,1643lineind1, lineind2, pos_max=79):1644dist_max = max(dist1_min, dist1_max, dist2_min, dist2_max)+11645#dist_min = min(dist1_min, dist1_max, dist2_min, dist2_max)1646#dist_diff = dist_max-dist_min+10.01647print 'print_vehs id_veh1', id_veh1, 'id_veh2', id_veh21648# print ' dist1_min',dist1_min,'dist1_max',dist1_max1649# print ' dist2_min',dist2_min,'dist2_max',dist2_max1650# print ' min[dist1_min, dist1_max, dist2_min, dist2_max]>0.01',np.min([dist1_min, dist1_max, dist2_min, dist2_max])>0.011651if np.min([dist1_min, dist1_max, dist2_min, dist2_max]) > 0.01:1652f = float(pos_max)/dist_max1653# print ' f',f1654print '________________________'1655print 'vehicle %s from line %d: %.f--%2f' % (id_veh1, lineind1, dist1_min, dist1_max)1656pos_min = int(dist1_min*f)1657pos_max = int(dist1_max*f)1658print max(pos_min-1, 0)*' '+'<'+(pos_max-pos_min)*'X'+'|'16591660pos_min = int(dist2_min*f)1661pos_max = int(dist2_max*f)1662# print ' pos_min',pos_min1663# print ' pos_max',pos_max1664# print ' max(pos_min-1,0)',max(pos_min-1,0),'(pos_max-pos_min)',(pos_max-pos_min)1665print max(pos_min-1, 0)*' '+'<'+(pos_max-pos_min)*'X'+'|'1666print 'vehicle %s from line %d: %.f--%2f' % (id_veh2, lineind2, dist2_min, dist2_max)1667print '________________________'1668else:1669print 'WARNING: some negative distances:'1670print 'vehicle %s from line %d: %.f--%2f' % (id_veh1, lineind1, dist1_min, dist1_max)1671print 'vehicle %s from line %d: %.f--%2f' % (id_veh2, lineind2, dist2_min, dist2_max)16721673def enter_veh(self, id_veh, id_veh_sumo, id_merge_from, id_merge_to, id_edge_merge_sumo, vehicles, debug=0):1674print 'enter_veh id_veh %s, id_merge_from %d to id_merge_to %d' % (id_veh_sumo, id_merge_from, id_merge_to)16751676# in id_merge_from: take vehicle out of merged queue and input queue16771678# put vehicle in centralized database1679self.vehicle_to_merge[id_veh] = id_merge_to16801681# on which input line of merge id_merge_to does the vehicle approach?1682if id_veh in self.ids_vehs_merged[id_merge_to]:1683# vehicle is in merge queue and input line can be retrived from it1684indpos = self.ids_vehs_merged[id_merge_to].index(id_veh)16851686# on which input line is the vehicle at position index indpos1687lineind = self.lineinds_vehs_merged[id_merge_to][indpos]16881689elif self.ids_node_to_ids_merge[self.ids_node_in1[id_merge_to]] == id_merge_from:1690# vehicle not in merge queue, detect input line 1 with nodes db1691indpos = -11692lineind = 11693else:1694# vehicle not in merge queue, detect input line 2 with nodes db1695indpos = -11696lineind = 216971698if lineind == 1:1699# from line 11700self.ids_vehs_in1[id_merge_to].append(id_veh)1701self.ids_vehs_in1_sumo[id_merge_to].append(id_veh_sumo)1702dist_tomerge_head_new = self.distances_node_in1[id_merge_to] - traci.vehicle.getLanePosition(id_veh_sumo)17031704elif lineind == 2:1705self.ids_vehs_in2[id_merge_to].append(id_veh)1706self.ids_vehs_in2_sumo[id_merge_to].append(id_veh_sumo)1707dist_tomerge_head_new = self.distances_node_in2[id_merge_to]-traci.vehicle.getLanePosition(id_veh_sumo)17081709if indpos == -1:1710# vehicle is new and must be merged into ids_vehs_merged1711print ' merge prt.%d' % id_veh, 'lineind', lineind, 'dtm %.1fm' % dist_tomerge_head_new, 'n_plat', vehicles.get_platoonsize(id_veh), vehicles.lengths_plat[id_veh]/vehicles.length17121713ids_vehs_merged = self.ids_vehs_merged[id_merge_to]1714ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge_to]1715lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge_to]1716odos_veh_merged = self.odos_vehs_merged[id_merge_to]1717#id_edge_merge_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_to]1718ind_insert = len(ids_vehs_merged)1719is_insert = False1720id_veh_merged = -11721if debug > 0:1722print ' ids_vehs_merged_sumo[%d]' % id_merge_to, ids_vehs_merged_sumo1723print ' lineinds_vehs_merged[%d]' % id_merge_to, lineinds_vehs_merged1724if (ind_insert == 0) | self.are_station[id_merge_to]:1725if debug > 0:1726print ' new vehicle is the only vehicle or station', ind_insert, self.are_station[id_merge_to]17271728# vehicles heading toward a station merge are not1729# really merged because only one incoming line1730ids_vehs_merged.append(id_veh)1731ids_vehs_merged_sumo.append(id_veh_sumo)1732lineinds_vehs_merged.append(lineind)1733odos_veh_merged.append(get_traci_odo(id_veh_sumo))17341735elif ind_insert > 0: # there is at least another vehicle1736# slower, but more precise than self.distances_node_inX[id_merge_to]1737id_veh_tail_new = vehicles.get_platoontail(id_veh)1738id_veh_tail_new_sumo = vehicles.ids_sumo[id_veh_tail_new]17391740if debug > 0:1741dist_tomerge_head_new2 = get_traci_distance(id_veh_sumo, id_edge_merge_sumo, 3.0)1742print ' compare dist_tomerge_head_new', dist_tomerge_head_new, 'dist_tomerge_head_new2', dist_tomerge_head_new217431744# get back to traci distance measurement1745dist_tomerge_head_new = get_traci_distance(id_veh_sumo, id_edge_merge_sumo, 3.0)17461747#dist_tomerge_tail_new = dist_tomerge_head_new-0.5/ get_traci_velocity(id_veh_sumo)**2+vehicles.lengths_plat[id_veh]1748dist_tomerge_tail_new = dist_tomerge_head_new+vehicles.lengths_plat[id_veh]+vehicles.length17491750#dist_tomerge_tail_new = dist_tomerge_head_new+vehicles.get_platoonsize(id_veh)*vehicles.get_length()1751#dist_tomerge_tail_new = get_traci_distance(id_veh_tail_new_sumo, id_edge_merge_sumo, 3.0)17521753if debug > 0:1754print ' new prt.%d arriving from in %d at dist head %.2f /__| tail prt.%d %.2fm' % (id_veh, lineind, dist_tomerge_head_new, id_veh_tail_new, dist_tomerge_tail_new)1755print ' ids_vehs_merged_sumo', ids_vehs_merged_sumo1756for id_veh_merged, id_veh_merged_sumo, odo, lineind_merge in zip(ids_vehs_merged[::-1], ids_vehs_merged_sumo[::-1], odos_veh_merged[::-1], lineinds_vehs_merged[::-1]):1757if debug > 0:1758print ' id_veh_merged_sumo', id_veh_merged_sumo1759# unprecise1760#dist_tomerge_head2 = get_traci_distance(id_veh_merged_sumo, id_edge_merge_sumo, 3.0)17611762if lineind_merge == 1:1763dist_tomerge_head = self.distances_node_in1[id_merge_to] - \1764(get_traci_odo(id_veh_merged_sumo)-odo)1765else:1766dist_tomerge_head = self.distances_node_in2[id_merge_to] - \1767(get_traci_odo(id_veh_merged_sumo)-odo)17681769if debug > 0:1770dist_tomerge_head2 = get_traci_distance(id_veh_merged_sumo, id_edge_merge_sumo, 3.0)1771print ' compare', id_veh_merged_sumo, ' dist_tomerge_head %.1f' % dist_tomerge_head, 'dist_tomerge_head2 %.1f' % dist_tomerge_head217721773# get back to traci distance measurement1774dist_tomerge_head = get_traci_distance(id_veh_merged_sumo, id_edge_merge_sumo, 3.0)1775if lineind_merge == 1:1776dist_node = self.distances_node_in1[id_merge_to]1777else:1778dist_node = self.distances_node_in2[id_merge_to]1779if debug > 0:1780print ' M:odo_enter=%.1f odo=%.1f delta=%.f dist_node=%.1f line%d platl=%d' % (odo, get_traci_odo(id_veh_merged_sumo), get_traci_odo(id_veh_merged_sumo)-odo, dist_node, lineind_merge, vehicles.lengths_plat[id_veh_merged])17811782#stoppeddist_tomerge = dist-0.5/self.decel*get_traci_velocity(id_veh_merged_sumo)**2+vehicles.lengths_plat[id_veh]1783#stoppeddist_tomerge = dist+vehicles.lengths_plat[id_veh]1784id_veh_tail = vehicles.get_platoontail(id_veh_merged)1785id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]17861787#dist_tomerge_tail = dist_tomerge_head +vehicles.get_platoonsize(id_veh_merged)*vehicles.get_length()1788dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_merge_sumo, 3.0)1789#dist_tomerge_tail = dist_tomerge_head + vehicles.lengths_plat[id_veh_merged]+vehicles.length1790if debug > 0:1791print ' compare lineind_merge', lineind_merge, '=?', lineinds_vehs_merged[ind_insert-1]17921793if debug > 0:1794self.print_vehs(id_veh, id_veh_merged,1795dist_tomerge_head_new, dist_tomerge_tail_new,1796dist_tomerge_head, dist_tomerge_tail,1797lineind, lineinds_vehs_merged[ind_insert-1])1798# print ' check veh %d arriving from in %d at dist head %.2f /__| tail %.2fm'%(id_veh,lineind,dist_tomerge_head_new,dist_tomerge_tail_new)1799# print ' check veh %d, d %.2fm, d_new %.2fm, ind_insert = %d'%(id_veh_merged,dist,dist_tomerge_head_new,ind_insert)1800# print ' ds %.2fm, ds_new %.2fm, v %.2f, v_new =%.2fm, '%(stoppeddist_tomerge,dist_tomerge_tail_new,get_traci_velocity(id_veh_merged_sumo),get_traci_velocity(id_veh_sumo),)1801# print ' tail veh %d, ds %.2fm'%(id_veh_tail,dist_tomerge_tail)18021803if lineind == lineinds_vehs_merged[ind_insert-1]: # get this from1804if debug > 0:1805print ' vehicle in front on same branch'1806is_insert = True1807break18081809if dist_tomerge_tail_new > dist_tomerge_tail:1810if debug > 0:1811print ' distance of tail to merge of new vehicle is greater than existing'1812# print ' =>insert new %s after existing %s'%(id_veh_sumo,id_veh_merged_sumo)1813is_insert = True1814break1815dist_last = dist_tomerge_head1816ind_insert -= 118171818if is_insert:1819# at least one vehicle is in front1820if debug > 0:1821print ' insert veh %d behind veh %d, index %d' % (id_veh, id_veh_merged, ind_insert)1822# send control info to involved vehicles1823if ind_insert == len(ids_vehs_merged):1824if debug > 0:1825print ' appended vehicle after veh', id_veh_tail_sumo, 'with leader', ids_vehs_merged_sumo[ind_insert-1], 'dtm=%.2fm' % dist_tomerge_tail1826# V1827# |1828# G ind_insert-118291830# is vehicle and ghost in the same input line?1831if lineinds_vehs_merged[ind_insert-1] != lineind:1832# id_ghost = ids_vehs_merged[ind_insert-1]# last veh in queue1833#vehicles.add_ghost(id_veh, id_ghost, dist_tomerge_head_new, dist)18341835vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge_head_new, dist_tomerge_tail)18361837elif ind_insert > 0:1838# there is at least 1 other veh in front18391840# G11841# |1842# V1843# |1844# G21845id_ghost1 = ids_vehs_merged[ind_insert]1846#id_ghost2 = ids_vehs_merged[ind_insert-1]1847id_ghost2 = id_veh_tail1848if debug > 0:1849print ' vehicle will be inserted in front of', ids_vehs_merged_sumo[ind_insert], 'and in behind', id_veh_tail_sumo, 'with leader', ids_vehs_merged_sumo[ind_insert-1], 'dtm=%.2fm' % dist_tomerge_tail18501851vehicles.del_ghost(id_ghost1, id_ghost2)1852if lineinds_vehs_merged[ind_insert] != lineind:1853vehicles.add_ghost(id_ghost1, id_veh_tail_new, dist_last, dist_tomerge_tail_new)18541855if lineinds_vehs_merged[ind_insert-1] != lineind:1856#vehicles.add_ghost(id_veh, id_ghost2, dist_tomerge_head_new, dist)1857vehicles.add_ghost(id_veh, id_ghost2, dist_tomerge_head_new, dist_tomerge_tail)18581859else:1860if debug > 0:1861print ' prepend prt.%d in front of prt.%d, first index %d' % (id_veh, id_veh_merged, ind_insert)1862# is vehicle and ghost in the same input line?1863if lineinds_vehs_merged[ind_insert] != lineind:1864id_veh_behind = ids_vehs_merged[ind_insert] # last veh in queue1865vehicles.add_ghost(id_veh_behind, id_veh_tail_new, dist_tomerge_head, dist_tomerge_tail_new)18661867# finally insert vehicle in merge queue1868ids_vehs_merged.insert(ind_insert, id_veh)1869ids_vehs_merged_sumo.insert(ind_insert, id_veh_sumo)1870lineinds_vehs_merged.insert(ind_insert, lineind)1871odos_veh_merged.insert(ind_insert, get_traci_odo(id_veh_sumo))18721873# inform downstream merges18741875# else:1876# # new vehicle is the only vehicle1877# ids_vehs_merged[0] = id_veh1878# ids_vehs_merged_sumo[0] = id_veh_sumo1879# lineinds_vehs_merged[0] = lineind18801881def enter_veh_entry(self, id_veh, id_veh_sumo, id_merge_from, id_merge_to, id_edge_merge_sumo, vehicles, debug=0):1882print 'enter_veh_entry id_veh %s, id_merge_from %d to id_merge_to %d' % (id_veh_sumo, id_merge_from, id_merge_to)18831884# in id_merge_from: take vehicle out of merged queue and input queue18851886# put vehicle in centralized database1887self.vehicle_to_merge[id_veh] = id_merge_to18881889# on which input line of merge id_merge_to does the vehicle approach?1890if id_veh in self.ids_vehs_merged[id_merge_to]:1891# vehicle is in merge queue and input line can be retrived from it1892indpos = self.ids_vehs_merged[id_merge_to].index(id_veh)18931894# on which input line is the vehicle at position index indpos1895lineind = self.lineinds_vehs_merged[id_merge_to][indpos]18961897elif self.ids_node_to_ids_merge[self.ids_node_in1[id_merge_to]] == id_merge_from:1898# vehicle not in merge queue, detect input line 1 with nodes db1899indpos = -11900lineind = 11901else:1902# vehicle not in merge queue, detect input line 2 with nodes db1903indpos = -11904lineind = 219051906# put vehicle in respective line queue1907ids_vehs_merged = self.ids_vehs_merged[id_merge_to]1908ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge_to]1909lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge_to]1910odos_veh_merged = self.odos_vehs_merged[id_merge_to]19111912if lineind == 1:1913# from line 1 (main line)1914if debug > 0:1915print ' Detected veh', id_veh_sumo, 'on mainline. Is new', indpos == -11916print ' check for platooned vehicles:', vehicles.get_platoon(id_veh)19171918id_edge_out_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge_to]1919dist_tomerge = get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)1920ids_vehs_in1 = self.ids_vehs_in1[id_merge_to]1921if len(ids_vehs_in1) > 0:1922id_veh1_last = self.ids_vehs_in1[id_merge_to][-1]1923else:1924id_veh1_last = -119251926id_veh2, state2 = self.get_mergeveh_entry(id_merge_to, debug)1927if debug > 0:1928print ' Conflict vehicle from entry line: prt.%d state' % (id_veh2,), state21929print ' Main line: ids_vehs_in1', ids_vehs_in11930print ' id_veh1_last', id_veh1_last1931print ' dist_tomerge', dist_tomerge19321933if id_veh2 == -1:1934if debug > 0:1935print ' no vehicle to merge'19361937if id_veh1_last != -1:1938if debug > 0:1939print ' control distance to last vehicle in main...by SUMO'1940pass1941#1942#id_veh_tail = vehicles.get_platoontail(id_veh1_last)1943#id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]1944#dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)1945#vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge, dist_tomerge_tail)19461947# let SUMO do the distances19481949else:1950if debug > 0:1951print ' merge is empty'1952pass19531954elif state2['status'] != 'wait':1955# there is an approaching vehicle on entry line1956if state2['status'] == 'accelerate':1957if debug > 0:1958print ' conflict vehicle in acceleration mode', 'is veh behind', state2.has_key('id_veh_behind')1959if state2.has_key('id_veh_behind'):1960# accelerating vehicle has already a vehicle1961# in front of which to merge1962# => look at last vehicle19631964# let SUMO do the distances1965pass19661967else:1968# let the entering vehicle see the new vehicle1969state2['id_veh_behind'] = id_veh19701971if state2['status'] == 'sync':1972if debug > 0:1973print ' conflict vehicle in sync mode'1974if state2.has_key('id_veh_behind'):1975# accelerating vehicle has already a vehicle1976# in front of which to merge1977# => look at last vehicle19781979# let SUMO do the distances1980pass19811982else:1983# speed is already synchonized, but has not yet1984# a vehicle behind19851986id_veh_tail = vehicles.get_platoontail(id_veh2)1987id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]1988dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)1989print ' let look the new vehicle prt.%d look at the tail of the entering vehicle prt.%d' % (id_veh, id_veh_tail)1990vehicles.add_ghost(id_veh, id_veh_tail, dist_tomerge, dist_tomerge_tail)19911992# let the entering vehicle see the new vehicle1993state2['id_veh_behind'] = id_veh19941995self.ids_vehs_in1[id_merge_to].append(id_veh)1996self.ids_vehs_in1_sumo[id_merge_to].append(id_veh_sumo)19971998# append to main merge queue1999ids_vehs_merged.append(id_veh)2000ids_vehs_merged_sumo.append(id_veh_sumo)2001lineinds_vehs_merged.append(lineind)2002odos_veh_merged.append(get_traci_odo(id_veh_sumo))20032004elif lineind == 2:2005# from line 2 (entry line)2006print ' Detected veh', id_veh_sumo, 'on entry line. Is new', indpos == -120072008self.ids_vehs_in2[id_merge_to].append(id_veh)2009self.ids_vehs_in2_sumo[id_merge_to].append(id_veh_sumo)20102011print ' command vehicle to stop and wait further instructions'2012#vehicles.control_slow_down(id_veh, speed = 6.0/3.6)2013#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)2014# print ' set speed to',traci.vehicle.getMaxSpeed(id_veh_sumo)2015#traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0)20162017vehicles.control_stop(id_veh)20182019# prevent SUMO from reaccelerating vehicle2020# vehicles.switch_off_control(id_veh)2021print ' set veh id_veh prt.%d' % id_veh2022self.vehicles_entries[id_merge_to][id_veh] = {'status': 'wait'}2023print ' vehicles_entries[', id_merge_to, ']=', self.vehicles_entries[id_merge_to]2024#2025# self.vehicles_mains[id_merge_to][id_veh] = {}# later when used20262027# Attention: Vehicle on entry line not yet in queue.2028# this needs to be fixed later when it becomes clear where to insert2029# ids_vehs_merged.append(id_veh)2030# ids_vehs_merged_sumo.append(id_veh_sumo)2031# lineinds_vehs_merged.append(lineind)20322033def get_mergeveh_entry(self, id_merge, debug):2034"""Returns ID and state of vehicle that is about to merege from2035the entry line. ID is -1 if no vehicle starts.2036"""20372038vehicles_entries = self.vehicles_entries[id_merge]2039if debug > 0:2040print 'get_mergeveh_entry vehicles_entries', vehicles_entries2041if len(vehicles_entries) == 0:2042return -1, {'status': 'wait'}2043else:2044return vehicles_entries.keys()[0], vehicles_entries.values()[0]20452046def process_step_entry(self, id_merge, vehicles, debug):2047print 'process_step_entry id_merge', id_merge20482049#self.vehicles_entries[id_merge]= OrderedDict()2050# self.vehicles_mains[id_merge] = OrderedDict()2051id_veh_del = -120522053# for id_veh, state in zip(self.vehicles_entries[id_merge].keys()[::-1],self.vehicles_entries[id_merge].values()[::-1]):2054# for id_veh, state in self.vehicles_entries.iteritems():2055# for id_veh, state in zip(self.vehicles_entries[id_merge].keys(),self.vehicles_entries[id_merge].values()):2056ids_veh_entry = self.vehicles_entries[id_merge].keys()2057states_veh_entry = self.vehicles_entries[id_merge].values()2058id_edge_out_sumo = self.ids_merge_to_ids_edge_out_sumo[id_merge]2059ids_veh_in1 = self.ids_vehs_in1[id_merge]2060time_update = self.time_update.get_value()20612062if debug:2063print ' vehicles_entries=', self.vehicles_entries[id_merge]2064print ' vehicles_mains', self.vehicles_mains[id_merge]2065print ' ids_veh_in1', ids_veh_in120662067i = 02068#is_cont = len(ids_veh_entry)>02069# while is_cont:2070if len(ids_veh_entry) > 0:2071id_veh = ids_veh_entry[0]2072id_veh_sumo = vehicles.get_id_sumo(id_veh)2073state = states_veh_entry[0]20742075ids_vehs_merged = self.ids_vehs_merged[id_merge]2076ids_vehs_merged_sumo = self.ids_vehs_merged_sumo[id_merge]2077lineinds_vehs_merged = self.lineinds_vehs_merged[id_merge]2078odos_veh_merged = self.odos_vehs_merged[id_merge]2079if debug:2080print ' check id_veh_sumo', id_veh_sumo, 'status', state['status'], 'n vehs on main', len(ids_veh_in1)2081if state['status'] == 'wait':2082if traci.vehicle.isStopped(id_veh_sumo):2083# check potential conflict vehicle on main line20842085n1 = len(ids_veh_in1)2086if n1 == 0:2087if debug:2088print ' main line is empty => accelerate immediately'2089for id_veh_plat in vehicles.get_platoon(id_veh):2090vehicles.control_speedup(id_veh_plat)2091state['status'] = 'accelerate'20922093ids_vehs_merged.append(id_veh)2094ids_vehs_merged_sumo.append(id_veh_sumo)2095lineinds_vehs_merged.append(2)2096odos_veh_merged.append(get_traci_odo(id_veh_sumo))20972098else:2099ids_veh_in1_sumo = self.ids_vehs_in1_sumo[id_merge]2100vehicles_main = self.vehicles_mains[id_merge]2101dist_in1 = self.distances_node_in1[id_merge]2102dist_in2 = self.distances_node_in2[id_merge]21032104i = 0 # n1-12105is_found = False2106while (i < n1) & (not is_found):2107id_veh1_sumo = ids_veh_in1_sumo[i]2108id_veh1 = ids_veh_in1[i]2109if debug:2110print ' check', id_veh1_sumo, 'free', id_veh1 not in vehicles_main21112112if True: # id_veh1 not in vehicles_main:21132114# get tail position of id_veh_main2115id_veh1_tail = vehicles.get_platoontail(id_veh1)2116id_veh1_tail_sumo = vehicles.ids_sumo[id_veh1_tail]2117pos1 = dist_in1-get_traci_distance(id_veh1_sumo, id_edge_out_sumo, 3.0)2118pos1_tail = dist_in1-get_traci_distance(id_veh1_tail_sumo, id_edge_out_sumo, 3.0)2119pos2 = dist_in2 - get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)2120p_from, p_to = self.get_pos_crit_entry(pos2,2121vehicles.lengths_plat[id_veh],2122get_traci_velocity(id_veh1_sumo),2123dist_in1, dist_in2,2124vehicles)2125if debug:2126print ' potential veh %s (tail %s)' % (id_veh1_sumo, id_veh1_tail_sumo), 'at pos1_tail=%.1f>p_to=%.1f' % (pos1_tail, p_to), pos1_tail > p_to21272128# here we check whether the tail of the vehicle on the main line2129# has passed the critical point p_to21302131if pos1_tail > p_to:21322133if i == n1-1: # last vehicle on main2134if debug:2135print ' insert id_veh', id_veh_sumo, 'behind id_veh1', id_veh1_sumo, 'the only veh on main'2136state['id_veh_infront'] = id_veh12137if vehicles_main.has_key(id_veh1):2138vehicles_main[id_veh1]['id_veh_behind'] = id_veh2139else:2140vehicles_main[id_veh1] = {'id_veh_behind': id_veh}2141is_found = True2142ids_vehs_merged.append(id_veh)2143ids_vehs_merged_sumo.append(id_veh_sumo)2144lineinds_vehs_merged.append(2)2145odos_veh_merged.append(get_traci_odo(id_veh_sumo))21462147elif i < n1-1: # there are others behind on main2148# ensure that gap is big enough2149id_veh_behind = ids_veh_in1[i+1]2150id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]2151pos1 = dist_in1 - get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)2152if debug:2153print ' vehicle behind', id_veh_behind_sumo, 'pos=%.1f, p_from=%.1f' % (pos1, p_from), 'ok', pos1 < p_from2154if pos1 < p_from:2155state['id_veh_infront'] = id_veh12156state['id_veh_behind'] = id_veh_behind21572158#vehicles_main[id_veh_behind] = id_veh2159if vehicles_main.has_key(id_veh1):2160vehicles_main[id_veh1]['id_veh_behind'] = id_veh2161else:2162vehicles_main[id_veh1] = {'id_veh_behind': id_veh}2163#vehicles_main[id_veh1] = id_veh2164if vehicles_main.has_key(id_veh_behind):2165vehicles_main[id_veh_behind]['id_veh_infront'] = id_veh2166else:2167vehicles_main[id_veh_behind] = {'id_veh_infront': id_veh}21682169is_found = True2170j = ids_vehs_merged.index(id_veh1)+12171if debug:2172print ' j=', j2173ids_vehs_merged.insert(j, id_veh)2174ids_vehs_merged_sumo.insert(j, id_veh_sumo)2175lineinds_vehs_merged.insert(j, 2)2176odos_veh_merged.insert(j, get_traci_odo(id_veh_sumo))21772178# here we check whether the vehicle on the main line2179# has not yet reached the critical point p_from2180elif pos1 < p_from:2181if i == 0: # first vehicle on main2182if debug:2183print ' insert id_veh', id_veh_sumo, 'in front of id_veh1', id_veh1_sumo, 'the only veh on main'2184state['id_veh_behind'] = id_veh12185#vehicles_main[id_veh1] = id_veh2186if vehicles_main.has_key(id_veh1):2187vehicles_main[id_veh1]['id_veh_infront'] = id_veh2188else:2189vehicles_main[id_veh1] = {'id_veh_infront': id_veh}2190is_found = True2191# determine insert position2192j = ids_vehs_merged.index(id_veh1)2193# if debug:2194# print ' j=',j2195ids_vehs_merged.insert(j, id_veh)2196ids_vehs_merged_sumo.insert(j, id_veh_sumo)2197lineinds_vehs_merged.insert(j, 2)2198odos_veh_merged.insert(j, get_traci_odo(id_veh_sumo))2199if debug:2200print ' ids_vehs_merged_sumo', ids_vehs_merged_sumo2201# elif i < n1-1: # there are others behind on main2202# # ensure that gap is big enough2203# id_veh_behind = ids_veh_in1[i+1]2204# id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]2205# pos1 = dist_in1 - get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)2206# print ' vehicle behind',id_veh_behind_sumo,'pos=%.1f, p_from=%.1f'%(pos1,p_from),'ok',pos1<p_from2207# if pos1<p_from:2208# state['id_veh_infront'] = id_veh12209# state['id_veh_behind'] = id_veh_behind2210# is_found = True22112212i += 122132214if is_found:2215if debug:2216print ' suitable vehicle after which entry vehicle can run has been found'2217# Note: if no vehicle has been found then2218# nothing will happen and the vehicle will2219# wait until the righ moment has arrived2220for id_veh_plat in vehicles.get_platoon(id_veh):2221vehicles.control_speedup(id_veh_plat)2222state['status'] = 'accelerate'22232224elif state['status'] == 'accelerate':2225# test if speed reached2226if traci.vehicle.getSpeed(id_veh_sumo) > 0.9*vehicles.speed_max.get_value():2227if debug > 0:2228print ' synchronization reached for veh', id_veh_sumo2229state['status'] = 'sync'2230#id_veh_del = id_veh2231# now create ghosts2232# id_veh -> id_veh_infront_tail:2233if state.has_key('id_veh_infront'):2234id_veh_in_front = state['id_veh_infront']2235id_veh_infront_tail = vehicles.get_platoontail(id_veh_in_front)2236id_veh_infront_tail_sumo = vehicles.ids_sumo[id_veh_infront_tail]2237dist_tomerge = get_traci_distance(id_veh_sumo, id_edge_out_sumo, 3.0)2238dist_tomerge_tail = get_traci_distance(id_veh_infront_tail_sumo, id_edge_out_sumo, 3.0)22392240if debug > 0:2241print ' add ghost to entering veh', id_veh_sumo, ' behind', id_veh_infront_tail_sumo, 'with leader', id_veh_in_front2242vehicles.add_ghost(id_veh, id_veh_infront_tail, dist_tomerge,2243dist_tomerge_tail, is_substitute=True)22442245if state.has_key('id_veh_behind'):2246id_veh_behind = state['id_veh_behind']2247id_veh_behind_sumo = vehicles.ids_sumo[id_veh_behind]22482249dist_tomerge_behind = get_traci_distance(id_veh_behind_sumo, id_edge_out_sumo, 3.0)22502251id_veh_tail = vehicles.get_platoontail(id_veh)2252id_veh_tail_sumo = vehicles.ids_sumo[id_veh_tail]2253dist_tomerge_tail = get_traci_distance(id_veh_tail_sumo, id_edge_out_sumo, 3.0)22542255if debug > 0:2256print ' add ghost to mainline veh', id_veh_behind_sumo, ' behind', id_veh_tail_sumo, 'with leader', id_veh_sumo2257vehicles.add_ghost(id_veh_behind, id_veh_tail, dist_tomerge_behind,2258dist_tomerge_tail, is_substitute=True)22592260else:2261if 0:2262speed = traci.vehicle.getSpeed(id_veh_sumo)2263print ' sync of veh', id_veh_sumo, ',v=%.1f, not yet reached: %.2f' % (speed, speed/vehicles.speed_max.get_value())22642265if state.has_key('id_veh_behind'):2266id_veh_behind_sumo = vehicles.ids_sumo[state['id_veh_behind']]2267info = traci.vehicle.getLeader(id_veh_behind_sumo, dist=200.0)2268if (info is not None):2269# extract lead vehicle ID and distance from info2270id_leader_sumo, dist_leader = info2271#speed = vehicles.speed_max.get_value()2272speed = get_traci_velocity(id_veh_behind_sumo)2273dist_safe = vehicles.time_emergency.get_value()*speed + 0.5*speed**2/vehicles.decel_emergency.get_value()2274dist_target = 2*dist_safe+vehicles.lengths_plat[id_veh]2275# print ' behind',id_veh_behind_sumo,'with infront',id_leader_sumo,'at dist=%.2f'%dist_leader,'at ds=%.2f'%dist_safe,'is_brake',dist_leader<dist_target2276if dist_leader < dist_target:2277dv = time_update*vehicles.decel2278if (speed-dv) > 0:2279# print ' slowdown',id_veh_behind_sumo,'from speed %.2f to %.2f'%(speed,speed-dv)2280traci.vehicle.slowDown(id_veh_behind_sumo, speed-dv, time_update)2281else:2282dv = time_update*vehicles.decel2283# print ' accel',id_veh_behind_sumo,'from speed %.2f to %.2f'%(speed,speed+dv)2284traci.vehicle.slowDown(id_veh_behind_sumo, speed+dv, time_update)22852286elif state['status'] == 'sync':2287pass22882289# if id_veh_del > -1:2290# del self.vehicles_entries[id_merge][id_veh_del]22912292def get_pos_crit_entry(self, pos2, len_veh2, speed, dist1, dist2, vehicles):2293"""2294Returns critical position interval of vehicle-platoon on main line2295with respect to the starting position of a vehicle at entry line.2296The returned critical position interval(pos_from, pos_to), which should2297ideally be free of vehicles.2298pos_from refers to the position of the nose of a vehicle on the main line2299pos_to refers to the position of the tail of the platoon on the main line.23002301"""2302print 'get_pos_crit_entry pos2=%.1f, v=%.1f, d1=%.1f, d2=%.1f' % (pos2, speed, dist1, dist2)2303# see 1910302304decel_emergency = vehicles.decel_emergency.get_value()2305decel_comfort = vehicles.decel_comfort.get_value()2306time_emergency = vehicles.time_emergency.get_value()2307s2 = 0.5*speed**2/decel_comfort2308delta2 = dist2 - pos2 - s223092310s1 = speed**2/decel_comfort2311s_safe = time_emergency*speed + 0.5*speed**2/decel_emergency2312p_to = dist1 - delta2 - s1 + s_safe2313p_from = p_to-len_veh2-2*s_safe2314# print ' delta2=%.1f, s2=%.1f, s1=%.1f, ss=%.1f, CI=(%.1f,%.1f)'%(delta2,s2,s1,s_safe,p_from,p_to)2315return p_from, p_to23162317def search_upstream_merge(self, id_edge_start, edges, lanes, id_prtmode, ids_mainline=set(), distances=None):2318"""2319Searches next upstream merge node.2320Returns id_node, length to node23212322"""2323print 'search_upstream_merge id_edge_start', id_edge_start2324length = distances[id_edge_start]2325print ' added id_edge', id_edge_start, 'dist', distances[id_edge_start], '=', length2326is_merge = False2327id_edge_platform = -12328id_edge = id_edge_start2329while (not is_merge):2330ids_edge_incoming = edges.get_incoming(id_edge)23312332# print ' search id_edge,ids_edge_incoming',id_edge,ids_edge_incoming2333if len(ids_edge_incoming) == 2:2334#id_edge1, id_edge2 = ids_edge_to2335ids_lane1, ids_lane2 = edges.ids_lanes[ids_edge_incoming]2336#al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)2337#al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)2338# print ' check: '2339# print ' id_edge1',ids_edge_incoming[0],'ids_lane1',ids_lane1,self.is_prt_only(ids_lane1, lanes)2340# print ' id_edge2',ids_edge_incoming[1],'ids_lane2',ids_lane2,self.is_prt_only(ids_lane2, lanes)2341if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):2342# print ' 2 in, one out => it is a merge node'2343is_merge = True23442345elif len(ids_edge_incoming) == 1:2346ids_lane = edges.ids_lanes[ids_edge_incoming[0]]2347#al = lanes.get_accesslevel(ids_lane, id_prtmode)2348if self.is_prt_only(ids_lane, lanes) & (id_edge in ids_mainline):2349# print ' mainline input node2350is_merge = True23512352if self.is_platform(ids_lane, lanes):2353# print ' 1 in, with multiple access => it is a station output node'2354is_merge = True23552356if not is_merge:2357id_edge = ids_edge_incoming[0]2358length += distances[id_edge]2359print ' added id_edge', id_edge, 'dist', distances[id_edge], '=', length23602361# print ' id_edge,is_merge',id_edge,is_merge2362print ' found node', edges.ids_fromnode[id_edge]2363return edges.ids_fromnode[id_edge], length23642365def search_downstream_merges(self, id_edge_start, edges, lanes, id_prtmode, ids_sinkedge=set()):2366"""2367Searches next downstream merge nodes.2368Returns array of downstream merge node IDs23692370"""23712372ids_edge = set([id_edge_start])2373ids_mergenode = set()2374print 'search_downstream_merges id_edge_start', id_edge_start, 'is sinkedge', id_edge_start in ids_sinkedge23752376if id_edge_start in ids_sinkedge:2377return None # np.array([], dtype = np.int32)23782379is_cont = True2380#n_cont = 202381while (len(ids_edge) > 0) & is_cont:2382# print ' len(ids_edge)',len(ids_edge),ids_edge2383ids_edge_new = set()23842385for id_edge in ids_edge:2386ids_edge_outgoing = edges.get_outgoing(id_edge)2387# print ' id_edge,ids_edge_outgoing',id_edge,ids_edge_outgoing2388for id_downedge in ids_edge_outgoing:2389ids_lane = edges.ids_lanes[id_downedge]2390if id_downedge in ids_sinkedge:2391# print ' sinkedge id_downedge',id_downedge2392pass23932394elif self.is_prt_only(ids_lane, lanes):2395ids_downedge_incoming = edges.get_incoming(id_downedge)2396# print ' id_downedge,ids_downedge_incoming',id_downedge,ids_downedge_incoming2397is_merge = False23982399if len(ids_downedge_incoming) == 2:2400ids_lane1, ids_lane2 = edges.ids_lanes[ids_downedge_incoming]2401#al1 = lanes.get_accesslevel(ids_lane1, id_prtmode)2402#al2 = lanes.get_accesslevel(ids_lane2, id_prtmode)2403# print ' check al1,al2',al1,al2,(al1 == 2) & (al2 == 2)2404# if (al1 == 2) & (al2 == 2):# real merges2405if self.is_prt_only(ids_lane1, lanes) & self.is_prt_only(ids_lane2, lanes):2406# print ' add mergenode',edges.ids_fromnode[id_downedge]2407ids_mergenode.add(edges.ids_fromnode[id_downedge])2408is_merge = True24092410if not is_merge: # len(ids_downedge_incoming) == 1:2411#ids_lane = edges.ids_lanes[ids_downedge_incoming]2412# if lanes.get_accesslevel(ids_lane1, id_prtmode) == 2:2413# print ' no merge detected, add edge',id_downedge2414ids_edge_new.add(id_downedge)24152416# else:2417# print 'WARNING in search_downstream_merges: edge %d has %d incoming edges.'%(id_downedge, len(ids_downedge_incoming))24182419ids_edge = ids_edge_new.copy()2420# print ' ids_edge_new',ids_edge_new,ids_edge,len(ids_edge)2421# is_cont = n_cont>0 #id_edge_start not in ids_edge2422#n_cont -= 124232424# if not is_cont:2425# print ' endless!!id_edge_start,ids_edge',id_edge_start,ids_edge2426print ' found ids_mergenode', ids_mergenode2427return np.array(list(ids_mergenode), dtype=np.int32)24282429def is_prt_only(self, ids_lane, lanes):2430if len(ids_lane) > 1:2431return False2432else:2433if len(lanes.ids_modes_allow[ids_lane[0]]) > 0:2434return lanes.ids_modes_allow[ids_lane[0]][0] == self.parent.id_prtmode2435else:2436return False24372438def is_platform(self, ids_lane, lanes):2439if len(ids_lane) > 1:2440if len(lanes.ids_modes_allow[ids_lane[1]]) > 0:2441# we could also chech ped on lane 02442return lanes.ids_modes_allow[ids_lane[1]][0] == self.parent.id_prtmode2443else:2444return False2445else:2446return False244724482449class PrtBerths(am.ArrayObjman):24502451def __init__(self, ident, prtstops, **kwargs):2452# print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1')2453self._init_objman(ident=ident,2454parent=prtstops,2455name='PRT Berths',2456info='PRT Berths.',2457**kwargs)24582459self._init_attributes()24602461def _init_attributes(self):2462#vtypes = self.get_scenario().demand.vtypes2463net = self.get_scenario().net2464self.add(cm.AttrConf('length_default', 4.0,2465groupnames=['parameters', 'options'],2466name='Default length',2467info='Default berth length.',2468unit='m',2469))24702471self.add_col(am.IdsArrayConf('ids_prtstop', self.parent,2472name='PRT stop ID',2473info='PRT stop ID',2474))24752476# states now dynamic, see prepare_sim2477# if hasattr(self,'states'):2478# self.delete('states')2479# self.add_col(am.ArrayConf( 'states', default = BERTHSTATES['free'],2480# dtype = np.int32,2481# choices = BERTHSTATES,2482# name = 'state',2483# info = 'State of berth.',2484# ))24852486self.add_col(am.ArrayConf('stoppositions', default=0.0,2487dtype=np.float32,2488name='Stop position',2489info='Position on edge where vehicle nose stops.',2490))24912492def _init_constants(self):2493self.do_not_save_attrs([2494'states', 'ids_veh',2495])24962497def prepare_sim(self, process):2498# print 'PrtBerths.prepare_sim'2499ids = self.get_ids()2500if len(ids) == 0:2501return []2502self.states = BERTHSTATES['free']*np.ones(np.max(ids)+1, dtype=np.int32)25032504# current vehicle at berth2505self.ids_veh = -1*np.ones(np.max(ids)+1, dtype=np.int32)25062507# last time when vehicle got boaded at this berth2508self.times_routes = 0.0 * np.ones(np.max(ids)+1, dtype=np.float32)2509return [] # berth has no update function25102511def get_scenario(self):2512return self.parent.get_scenario()25132514def get_prtvehicles(self):2515return self.parent.parent.prtvehicles25162517def get_length(self):2518return self.length_default.get_value()25192520def make(self, id_stop, position_from=None, position_to=None,2521n_berth=None,2522offset_firstberth=0.0, offset_stoppos=-0.0):2523stoplength = position_to-position_from2524# print 'Berths.make',id_stop,stoplength25252526# TODO: let define berth number either explicitely or through stoplength25272528length_berth = self.length_default.get_value()2529positions = position_from + offset_firstberth\2530+ np.arange(length_berth-offset_firstberth, stoplength+length_berth, length_berth) + offset_stoppos2531n_berth = len(positions)25322533# print ' n_berth,positions',n_berth,positions2534# force number of berth to be pair2535if n_berth % 2 == 1:2536positions = positions[1:]2537n_berth -= 125382539ids_berth = self.add_rows(n=n_berth,2540stoppositions=positions,2541ids_prtstop=id_stop * np.ones(n_berth, dtype=np.int32),2542)2543return ids_berth25442545def set_prtvehicles(self, prtvehicles):2546"""2547Defines attributes which are linked with prtvehicles2548"""2549self.add_col(am.IdsArrayConf('ids_veh', prtvehicles,2550is_save=False,2551name='Vehicle ID',2552info='ID of vehicle currently alighting/boarding at this berth. -1 means no vehicle.',2553))25542555def set_allocate(self, ids_berth):2556print 'set_allocate ids_berth', ids_berth, self.ids_veh[ids_berth]2557self.states[ids_berth] = BERTHSTATES['allocated']25582559def set_alighting(self, id_berth, id_veh):2560self.states[id_berth] = BERTHSTATES['alighting']2561self.ids_veh[id_berth] = id_veh25622563def set_boarding(self, id_berth):2564self.states[id_berth] = BERTHSTATES['boarding']25652566def set_waiting_empty(self, id_berth):2567self.states[id_berth] = BERTHSTATES['waiting']25682569# def set_waiting_occupied(self, id_berth):2570# self.states[id_berth] = BERTHSTATES['waiting_occupied']25712572def set_waiting_routed(self, id_berth, simtime):25732574print 'set_waiting_routed', id_berth, 'prt.%d' % (self.ids_veh[id_berth]), 'simtime', simtime2575self.states[id_berth] = BERTHSTATES['waiting_routed']2576self.times_routes[id_berth] = simtime25772578def set_free(self, id_berth):2579self.states[id_berth] = BERTHSTATES['free']2580self.ids_veh[id_berth] = -1258125822583class PrtStops(am.ArrayObjman):2584"""2585This is just a dummy to prevent errors with old PRT plugin2586"""25872588def __init__(self, ident, prtservices, **kwargs):2589self._init_objman(ident=ident,2590parent=prtservices,2591name='PRT Platoon stops',2592info='Contains methods and information on PRT stops, able to sort vehicles and create platoons.',2593#xmltag = ('additional','busStop','stopnames'),2594version=0.0,2595**kwargs)2596# self._init_attributes()25972598def get_scenario(self):2599return self.parent.get_scenario()260026012602class PrtPlatoonStops(am.ArrayObjman):2603def __init__(self, ident, prtservices, **kwargs):2604self._init_objman(ident=ident,2605parent=prtservices,2606name='PRT Platoon stops',2607info='Contains methods and information on PRT stops, able to sort vehicles and create platoons.',2608#xmltag = ('additional','busStop','stopnames'),2609version=0.1,2610**kwargs)2611self._init_attributes()26122613def _init_attributes(self):2614self.add(cm.ObjConf(PrtBerths('berths', self)))26152616berths = self.get_berths()2617net = self.get_scenario().net26182619self.add(cm.AttrConf('time_update', 0.5,2620groupnames=['parameters'],2621name='Update time',2622info="Update time for station.",2623unit='s',2624))26252626# self.add(cm.AttrConf( 'time_kickout', 30.0,2627# groupnames = ['parameters'],2628# name = 'Kickout time',2629# info = "Time to kick out empty vehicles after vehicles behing have been occupied with passengers.",2630# unit = 's',2631# ))26322633self.add(cm.AttrConf('time_fase_in_max', 30.0,2634groupnames=['parameters'],2635name='Max. move in time',2636info="Maximum move in phase duration.",2637unit='s',2638))26392640self.add(cm.AttrConf('time_fase_out_max', 30.0,2641groupnames=['parameters'],2642name='Max. move out time',2643info="Maximum move out phase duration.",2644unit='s',2645))26462647self.add(cm.AttrConf('time_wait_berth_max', 60.0,2648groupnames=['parameters'],2649name='Max. berth wait time',2650info="Maximum time that an occupied vehicle can remain in the berth before getting moved out.",2651unit='s',2652))26532654self.add(cm.AttrConf('timeconst_flow', 0.98,2655groupnames=['parameters'],2656name='Flow time const',2657info="Constant to update the moving average flow.",2658))26592660self.add(cm.AttrConf('stoplinegap', 12.0,2661groupnames=['parameters'],2662name='Stopline gap',2663unit='m',2664info="Distance between stopline, where vehicles get started, and the end of the lane.",2665))26662667self.add(cm.AttrConf('capacity_per_berth', 80.0,2668groupnames=['parameters'],2669name='Capacity per berth',2670info="Capacity in processed vehicles per berth. This is to estimate the capacity limit of stops which are supposed to increase linearly with the number of berths",2671))26722673self.add_col(am.IdsArrayConf('ids_ptstop', net.ptstops,2674name='ID PT stop',2675info='ID of public transport stop. ',2676))26772678self.add_col(am.ArrayConf('types', default=STOPTYPES['person'],2679dtype=np.int32,2680perm='rw',2681choices=STOPTYPES,2682name='Type',2683info='Type of stop.',2684))26852686self.add_col(am.IdlistsArrayConf('ids_berths', berths,2687#groupnames = ['_private'],2688name='Berth IDs',2689info="Berth IDs. These berth can be used for both, boarding and alighting.",2690))26912692if self.get_version() < 0.1:2693self.delete('time_kickout')26942695self.set_version(0.1)26962697# will be determined automatically in function of stop and berth geometry2698# self.add_col(am.ArrayConf( 'numbers_veh_in_max', 12,2699# groupnames = ['parameters'],2700# name = 'Max. veh. input buffer',2701# info = "Maximum vehicles in input buffer. If this buffer at the entrance of the stop is ful then a move in face is triggered.",2702# ))2703#2704# self.add_col(am.ArrayConf( 'numbers_veh_out_max', 12,2705# groupnames = ['parameters'],2706# name = 'Max. veh. output buffer',2707# info = "Maximum vehicles in output buffer. This buffer at the exit of the stop limits the length of platoon formation.",2708# ))27092710def _init_constants(self):2711self.do_not_save_attrs([2712'fases',2713'ids_stop_to_ids_edge_sumo', 'ids_stop_to_ids_edge',2714'stoplines', 'ids_stop_to_ids_acceledge_sumo',2715'id_edge_sumo_to_id_stop',2716'inds_berth_allocated',2717'times_plat_accumulate', # time when last platoon vehicle accumulation started2718'ids_vehs_sumo_prev', 'ids_vehs',2719'ids_vehs_to_allocate',2720'times_lastboard',2721'numbers_veh', 'numbers_person_wait',2722'flows_person', 'ids_veh_lead',2723'ids_veh_lastdep', 'ids_vehs_prog',2724'ids_persons_sumo_prev', 'ids_persons_sumo_boarded',2725'waittimes_persons', 'waittimes_tot',2726'id_person_to_origs_dests',2727'ids_detectoredge_decompr'2728])27292730def get_edges(self, ids_prtstop):2731net = self.get_scenario().net2732return net.lanes.ids_edge[net.ptstops.ids_lane[self.ids_ptstop[ids_prtstop]]]27332734def get_berths(self):2735return self.berths.get_value()27362737def get_scenario(self):2738return self.parent.get_scenario()27392740def set_prtvehicles(self, prtvehicles):2741self.get_berths().set_prtvehicles(prtvehicles)27422743def set_vehicleman(self, vehicleman):2744self.add(cm.ObjConf(vehicleman, is_child=False, groups=['_private']))27452746def get_vehicleman(self):2747return self.vehicleman.get_value()27482749def get_closest_for_trip(self, coords_from, coords_to, walkspeeds=None, ids_person=None):2750"""2751Returns the prt stops and stop edges that minimize2752door to door trip time.2753Door from and to positions of each trip are given as coordinates.2754"""2755net = self.get_scenario().net2756ptstops = net.ptstops2757lanes = net.lanes2758n = len(coords_from)2759print 'get_closest_for_trip', n27602761times_stop_to_stop = self.parent.times_stop_to_stop[1:, 1:]27622763ids_prtstop = self.get_ids()2764n_stops = len(self)2765ids_ptstop = self.ids_ptstop[ids_prtstop]2766coords_stop = ptstops.centroids[ids_ptstop]2767ids_edge_stop = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]27682769inds_closest_from = np.zeros(n, dtype=np.int32)2770inds_closest_to = np.zeros(n, dtype=np.int32)2771if walkspeeds is None:2772# default walk speed in m/s2773walkspeeds = 0.8*np.ones(n, dtype=np.float32)27742775i = 02776for coord_from, coord_to, walkspeed in zip(coords_from, coords_to, walkspeeds):2777walktimes_from = 1.0/walkspeed*np.sqrt(np.sum((coord_from-coords_stop)**2, 1))2778walktimes_to = 1.0/walkspeed*np.sqrt(np.sum((coord_to-coords_stop)**2, 1))27792780times_door_to_door = times_stop_to_stop+np.array([walktimes_from]).transpose()2781times_door_to_door += walktimes_to2782ind_from, ind_to = np.divmod(np.argmin(times_door_to_door), n_stops)27832784inds_closest_from[i] = ind_from2785inds_closest_to[i] = ind_to27862787if 0: # ids_person is not None:2788id_person = ids_person[i]2789if id_person == 17214:2790# print ' walktimes_from',(np.array([walktimes_from]).transpose()).shape2791# print ' walktimes_to',walktimes_to.shape2792# print ' times_stop_to_stop',times_stop_to_stop.shape27932794print ' id_person', id_person2795print ' coord_from, coord_to', coord_from, coord_to2796print ' times_door_to_door\n', times_door_to_door2797print ' ind_from, ind_to', ind_from, ind_to2798print ' id_stop_from, id_stop_to', ids_prtstop[ind_from], ids_prtstop[ind_to]27992800i += 128012802ids_prtstop_closest_from = ids_prtstop[inds_closest_from]2803ids_edge_closest_from = ids_edge_stop[inds_closest_from]2804ids_prtstop_closest_to = ids_prtstop[inds_closest_to]2805ids_edge_closest_to = ids_edge_stop[inds_closest_to]2806return ids_prtstop_closest_from, ids_edge_closest_from, ids_prtstop_closest_to, ids_edge_closest_to28072808def get_closest(self, coords):2809"""2810Returns the closest prt stop for each coord in coords vector.2811"""2812net = self.get_scenario().net2813ptstops = net.ptstops2814lanes = net.lanes2815n = len(coords)2816# print 'get_closest',n28172818#ids_stop = self.get_ids()28192820ids_prtstop = self.get_ids()2821ids_ptstop = self.ids_ptstop[ids_prtstop]2822coords_stop = ptstops.centroids[ids_ptstop]2823ids_edge_stop = net.lanes.ids_edge[ptstops.ids_lane[ids_ptstop]]28242825inds_closest = np.zeros(n, dtype=np.int32)28262827i = 02828for coord in coords:2829ind_closest = np.argmin(np.sum((coord-coords_stop)**2, 1))2830inds_closest[i] = ind_closest2831i += 128322833ids_prtstop_closest = ids_prtstop[inds_closest]2834ids_edge_closest = ids_edge_stop[inds_closest]28352836return ids_prtstop_closest, ids_edge_closest28372838def get_waitpositions(self, ids, offset=-0.0):2839"""2840Assign randomly a wait-position for each stop in ids28412842offset is wait position relative to the vehicle nose.2843"""2844# print 'get_waitpositions min(ids),max(ids)',min(ids),is_alight,max(ids),offset2845positions = np.zeros(len(ids), dtype=np.float32)2846randint = random.randint2847ids_berths = self.ids_berths[ids]28482849stoppositions = self.get_berths().stoppositions2850# print ' ids_berths',ids_berths2851i = 02852for id_stop, ids_berth in zip(ids, ids_berths):2853#ids_berth = ids_berths[id_stop]2854ind_berth = randint(0, len(ids_berth)-1)28552856positions[i] = stoppositions[ids_berth[ind_berth]]2857# print ' id_stop,ids_berth,posiions',id_stop,ids_berth,stoppositions[ids_berth[ind_berth]]2858i += 12859#positions[i] = stoppositions[ids_berth[randint(0,len(ids_berth))]]2860# for id_stop , pos in zip(ids, positions):2861# print ' id_stop %d, is_alight = %s, pos %.2fm'%(id_stop, is_alight ,pos)28622863return positions+offset28642865def get_capacity(self, id_stop):2866"""2867Returns capacity in processed vehicles per hour for stop id_stop2868"""2869return self.capacity_per_berth.get_value() * len(self.ids_berths[id_stop])28702871def prepare_sim(self, process):2872simtime = process.simtime2873print 'PrtStops.prepare_sim', simtime2874self.debug = True2875net = self.get_scenario().net2876ptstops = net.ptstops2877ids_edge_sumo = net.edges.ids_sumo2878vehicles = self.parent.prtvehicles2879berths = self.get_berths()2880lanes = net.lanes2881ids_edge_sumo = net.edges.ids_sumo2882ids = self.get_ids()28832884if len(ids) == 0: # np PRT stops in network2885return []28862887get_outgoing = net.edges.get_outgoing28882889# station management2890# fase = 0: move in2891# fase = 1: move out2892self.fases = np.zeros(np.max(ids)+1, dtype=np.int32)2893# are_back_to_move_in allows a mechanism to switch back to move in fase2894self.are_back_to_move_in = np.zeros(np.max(ids)+1, dtype=np.bool)28952896self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1, dtype=np.object)2897self.ids_stop_to_ids_edge = np.zeros(np.max(ids)+1, dtype=np.int32)28982899ids_stopedge = lanes.ids_edge[ptstops.ids_lane[self.ids_ptstop[ids]]]2900# print ' ids,self.stoplines[ids]',ids,self.stoplines[ids]2901self.ids_stop_to_ids_edge_sumo[ids] = ids_edge_sumo[ids_stopedge]2902self.ids_stop_to_ids_edge[ids] = ids_stopedge29032904self.id_edge_to_id_stop = {}2905for id_stop, id_edge in zip(ids, ids_stopedge):2906self.id_edge_to_id_stop[id_edge] = id_stop29072908# Determine te position where vehicles are stopped while waiting for the2909# move in fase.2910# stop position at stoplinegap meters2911# before the beginning of the berth area2912self.stoplines_in = np.zeros(np.max(ids)+1, dtype=np.float32)29132914# input queue capacity2915self.capas_inqueue = np.zeros(np.max(ids)+1, dtype=np.int32)2916# output queue capacity2917self.capas_outqueue = np.zeros(np.max(ids)+1, dtype=np.int32)29182919stoplinegap = 1.02920#self.stoplines[ids] = net.edges.lengths[ids_stopedge]-12.02921#stoplengths = net.edges.lengths[ids_stopedge]2922for id_stop, ids_board, length_stopedge in zip(ids, self.ids_berths[ids], net.edges.lengths[ids_stopedge]):2923# print ' berthposs:',berths.stoppositions[ids_board]2924firstberthpos = berths.stoppositions[ids_board][0]-berths.get_length()29252926if (firstberthpos-stoplinegap) > 0:2927self.stoplines_in[id_stop] = firstberthpos-stoplinegap29282929print ' OK:id_stop', id_stop, 'stoplines_in', self.stoplines_in[id_stop]2930self.capas_inqueue[id_stop] = int(self.stoplines_in[id_stop]/vehicles.length)2931print ' capa_inqueue', self.capas_inqueue[id_stop]2932else:2933print 'WARNING in PrtStops.prepare_sim: stop ID %d has not enough space at before berth area.' % id_stop29342935# Determine stopline position where vehicles actually start2936# running off the station29372938# final stop at stoplinegap meters before end of stopedge2939self.stoplines = np.zeros(np.max(ids)+1, dtype=np.float32)2940stoplinegap = self.stoplinegap.get_value()29412942#self.stoplines[ids] = net.edges.lengths[ids_stopedge]-12.02943#stoplengths = net.edges.lengths[ids_stopedge]2944for id_stop, ids_board, length_stopedge in zip(ids, self.ids_berths[ids], net.edges.lengths[ids_stopedge]):2945lastberthstoppos = berths.stoppositions[ids_board][-1]2946if (length_stopedge-lastberthstoppos) > stoplinegap+1:2947self.stoplines[id_stop] = length_stopedge-stoplinegap2948print ' OK:id_stop', id_stop, 'length_stopedge', length_stopedge, 'stopline', self.stoplines[id_stop]29492950elif length_stopedge > lastberthstoppos:2951self.stoplines[id_stop] = 0.5*(length_stopedge+lastberthstoppos)2952print ' Limit:id_stop', id_stop, 'length_stopedge', length_stopedge, 'stopline', self.stoplines[id_stop]29532954self.capas_outqueue[id_stop] = int((self.stoplines[id_stop]-lastberthstoppos)/vehicles.length)2955print ' capa_outqueue', self.capas_outqueue[id_stop]29562957self.ids_stop_to_ids_acceledge_sumo = np.zeros(np.max(ids)+1, dtype=np.object)2958for id_stop, id_stopedge in zip(ids, ids_stopedge):2959self.ids_stop_to_ids_acceledge_sumo[id_stop] = ids_edge_sumo[get_outgoing(id_stopedge)[0]]29602961self.id_edge_sumo_to_id_stop = {}2962for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]):2963self.id_edge_sumo_to_id_stop[id_edge_sumo] = id_stop29642965# current berth ready to be newly allocated by vehicles during move in fase2966self.ids_berths_to_allocate = np.ones(np.max(ids)+1, dtype=np.object)29672968# vehicles that are currently allocated for a berth for alighting2969# and are forwarded to the correct position of the berth2970self.ids_vehs_alight_forward = np.zeros(np.max(ids)+1, dtype=np.object)29712972# vehicles that are arrived at the stopline of the berth for alighting2973# and are moving into the berth2974self.ids_vehs_alight_aproach = np.zeros(np.max(ids)+1, dtype=np.object)29752976# sets of vehicles routed and ready to leave station2977# this is the set to search for vehicles for platooning2978# TODO: check if this variable is still in use2979self.ids_vehs_routed = np.zeros(np.max(ids)+1, dtype=np.object)29802981# berth with routed and started vehicles,2982# that are waiting for their turn to exit2983# theiy will leave the berth, sorted by destinatiom2984# this is managed in try_start_vehicles2985self.ids_berths_veh_wait_exit = np.zeros(np.max(ids)+1, dtype=np.object)29862987# pass through vehicles in input queue waiting for exit2988self.ids_vehs_pass_wait_exit = np.zeros(np.max(ids)+1, dtype=np.object)29892990# vehicles which move sidewards out of the berth2991self.ids_vehs_berth_exit = np.zeros(np.max(ids)+1, dtype=np.object)29922993# vehicles in the output queue ready for departure2994self.ids_vehs_out = np.zeros(np.max(ids)+1, dtype=np.object)29952996# should positions of vehicles in output queue be updated2997self.are_reposition_out = np.zeros(np.max(ids)+1, dtype=np.bool)29982999# vehicles in output queue already concatenated and ready for departure3000# and waiting for vehicle management to be lauched3001self.ids_vehs_ready_for_departure = np.zeros(np.max(ids)+1, dtype=np.object)30023003# current berth allocation index for departing vehicles during move out fase3004#3005self.inds_berth_allocated = -1*np.ones(np.max(ids)+1, dtype=np.int32)30063007#self.ids_vehs_alight_forward = np.zeros(np.max(ids)+1,dtype = np.object)3008self.ids_vehs_board_allocated = np.zeros(np.max(ids)+1, dtype=np.object)30093010self.times_phase_in = simtime*np.ones(np.max(ids)+1, dtype=np.int32)3011self.times_phase_out = simtime*np.ones(np.max(ids)+1, dtype=np.int32)30123013# time when last platoon vehicle accumulation started3014# -1 means no platoon accumulation takes place3015self.times_plat_accumulate = -1*np.ones(np.max(ids)+1, dtype=np.int32)30163017self.ids_vehs_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object)3018self.ids_vehs = np.zeros(np.max(ids)+1, dtype=np.object)3019self.ids_vehs_inqueue = np.zeros(np.max(ids)+1, dtype=np.object)3020#3021self.times_lastboard = 10**4*np.ones(np.max(ids)+1, dtype=np.int32)30223023# for vehicle management3024self.numbers_veh = np.zeros(np.max(ids)+1, dtype=np.int32)3025self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype=np.int32)3026self.flows_person = np.zeros(np.max(ids)+1, dtype=np.float32)3027self.ids_veh_lead = -1*np.ones(np.max(ids)+1, dtype=np.int32)3028#self.ids_veh_lastdep = -1*np.ones(np.max(ids)+1,dtype = np.int32)3029self.ids_vehs_prog = np.zeros(np.max(ids)+1, dtype=np.object)30303031# person management3032self.ids_persons_sumo_prev = np.zeros(np.max(ids)+1, dtype=np.object)3033#self.ids_persons_sumo_boarded = np.zeros(np.max(ids)+1,dtype = np.object)3034self.waittimes_persons = np.zeros(np.max(ids)+1, dtype=np.object)3035self.waittimes_tot = np.zeros(np.max(ids)+1, dtype=np.float32)30363037virtualpop = self.get_scenario().demand.virtualpop30383039ids_persons = virtualpop.get_ids()3040stagelists = virtualpop.get_plans().stagelists3041prttransits = virtualpop.get_plans().get_stagetable('hcprttransits')3042id_person_to_origs_dests = {}30433044# create map from person id to various destination information3045# TODO: needs to be improved for trip chains, move to prtservices3046# idea: whu not scan prttransits?3047for id_person, stagelist in zip(ids_persons, stagelists[virtualpop.ids_plan[ids_persons]]):3048# print ' check dests of id_person',id_person3049for stages, id_stage in stagelist:3050if stages.ident == 'hcprttransits':3051id_fromedge_sumo = ids_edge_sumo[stages.ids_fromedge[id_stage]]3052id_toedge_sumo = ids_edge_sumo[stages.ids_toedge[id_stage]]3053data_orig_dest = (self.id_edge_sumo_to_id_stop[id_fromedge_sumo],3054self.id_edge_sumo_to_id_stop[id_toedge_sumo],3055id_fromedge_sumo,3056id_toedge_sumo)30573058id_person_sumo = virtualpop.get_id_sumo_from_id(id_person)3059if id_person_to_origs_dests.has_key(id_person_sumo):3060id_person_to_origs_dests[id_person_sumo].append(data_orig_dest)3061else:3062id_person_to_origs_dests[id_person_sumo] = [data_orig_dest]3063# print ' prtdests = ',id_person_to_origs_dests[id_person_sumo]30643065# print ' id_person_to_origs_dests=\n',id_person_to_origs_dests3066self.id_person_to_origs_dests = id_person_to_origs_dests30673068# this is only used for crazy person stage detection3069# angles_stop =30703071# various initianilizations3072for id_stop, id_edge_sumo in zip(ids, self.ids_stop_to_ids_edge_sumo[ids]):3073print ' initialize stop', id_stop30743075# initially all berth are avalable for allocation3076# print ' type(self.ids_berths[id_stop])',type(self.ids_berths[id_stop])3077self.ids_berths_to_allocate[id_stop] = 1 * self.ids_berths[id_stop]3078self.inds_berth_allocated[id_stop] = len(self.ids_berths[id_stop])3079# print ' type(self.ids_berths_to_allocate [id_stop])',type(self.ids_berths_to_allocate [id_stop])3080self.ids_vehs_alight_forward[id_stop] = []3081self.ids_vehs_alight_aproach[id_stop] = set([])3082# print ' type(self.ids_vehs_alight_aproach[id_stop])',type(self.ids_vehs_alight_aproach[id_stop])30833084self.ids_vehs_board_allocated[id_stop] = []30853086self.ids_vehs_sumo_prev[id_stop] = set([])3087self.ids_persons_sumo_prev[id_stop] = set([])30883089self.ids_vehs_routed[id_stop] = set([])3090self.ids_berths_veh_wait_exit[id_stop] = []3091self.ids_vehs_pass_wait_exit[id_stop] = []3092self.ids_vehs_berth_exit[id_stop] = []3093self.ids_vehs_out[id_stop] = []3094self.ids_vehs_ready_for_departure[id_stop] = []30953096#self.ids_persons_sumo_boarded [id_stop] = []3097self.waittimes_persons[id_stop] = {}3098self.ids_vehs[id_stop] = []3099self.ids_vehs_inqueue[id_stop] = []31003101self.ids_vehs_prog[id_stop] = []31023103# decompressor detector edge set3104#self.ids_detectoredge_decompr = set(self.parent.decompressors.ids_detectoredge.get_value())31053106# traci.edge.subscribe(id_edge_sumo, [traci.constants.VAR_ARRIVED_VEHICLES_IDS])3107updatedata_berth = berths.prepare_sim(process)31083109return [(self.time_update.get_value(), self.process_step),3110]+updatedata_berth31113112def get_waittime_max(self, id_stop, simtime):3113if len(self.waittimes_persons[id_stop]) > 0:3114return np.max(simtime - np.array(self.waittimes_persons[id_stop].values(), dtype=np.float32))3115else:3116return 0.031173118def process_step(self, process):3119simtime = process.simtime3120print 79*'_'3121print 'PrtStops.process_step at', simtime31223123# vehicle station process:3124# >forewarding (def enter)3125# >alighting (def process_step)3126# >boarding (def process_step) > ?boarding_completed > occupiedtrip3127# >waiting_empty (def process_step)3128# > emptytrip3129# > boarding (def process_step) > ?boarding_completed > occupiedtrip31303131net = self.get_scenario().net3132ptstops = net.ptstops3133berths = self.get_berths()3134lanes = net.lanes3135ids_edge_sumo = net.edges.ids_sumo3136vehicles = self.parent.prtvehicles3137virtualpop = self.get_scenario().demand.virtualpop3138ids = self.get_ids()31393140for id_stop, id_edge_sumo, ids_veh_sumo_prev, ids_person_sumo_prev in\3141zip(ids, self.ids_stop_to_ids_edge_sumo[ids],3142self.ids_vehs_sumo_prev[ids],3143self.ids_persons_sumo_prev[ids]):3144print ' '+60*'.'3145fase = self.fases[id_stop]3146print ' process id_stop', id_stop, 'id_edge_sumo', id_edge_sumo, 'fase', fase31473148if id_stop in [3]:3149self.debug = 13150else:3151self.debug = 031523153# if vehicles.id_follower_probe != vehicles.ids_follower[271]:3154# print 'PRE STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]31553156if self.debug:31573158print ' ids_berths_to_allocate', type(self.ids_berths_to_allocate[id_stop]), self.ids_berths_to_allocate[id_stop]3159print ' ind_berth_allocated', self.inds_berth_allocated[id_stop]3160print ' ids_vehs_inqueue', self.ids_vehs_inqueue[id_stop]3161print ' Capa', self.get_capacity(id_stop), 'per 10 seconds', self.get_capacity(id_stop)/3600*10316231633164print ' ids_vehs_alight_forward', self.ids_vehs_alight_forward[id_stop]3165print ' ids_vehs_alight_aproach', self.ids_vehs_alight_aproach[id_stop]316631673168print ' ids_vehs_routed', self.ids_vehs_routed[id_stop]3169print ' ids_berths_veh_wait_exit ', self.ids_berths_veh_wait_exit[id_stop]3170print ' ids_vehs_pass_wait_exit ', self.ids_vehs_pass_wait_exit[id_stop]3171print ' ids_vehs_berth_exit', self.ids_vehs_berth_exit[id_stop]3172print ' ids_vehs_out', self.ids_vehs_out[id_stop]3173print ' ids_veh_ready_for_departure', self.ids_vehs_ready_for_departure[id_stop]31743175print ' Vehicles:'3176ids_veh = self.ids_vehs[id_stop]3177for id_veh, state, id_berth, route in zip(ids_veh, vehicles.states[ids_veh], vehicles.ids_berth[ids_veh], vehicles.routes[ids_veh]):3178# ,'len(route)',len(route)3179print ' id_veh', id_veh, 'state', state, 'id_berth', id_berth, 'route', route31803181print ' Berths:'31823183ids_berth = self.ids_berths[id_stop]3184for id_berth, state, id_veh in zip(ids_berth, berths.states[ids_berth], berths.ids_veh[ids_berth]):3185print ' id_berth', id_berth, 'state', state, 'id_veh', id_veh3186# print ' flow_person',self.flows_person[id_stop]3187# print ' waittimes_persons',self.waittimes_persons[id_stop]31883189# print ' waittimes_tot',self.waittimes_tot[id_stop]31903191# no longer print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop]3192# print ' times_lastboard',self.times_lastboard[id_stop]319331943195if 0:3196for id_veh_sumo in self.ids_vehs_sumo_prev[id_stop]:3197print ' stopstate ', id_veh_sumo, bin(traci.vehicle.getStopState(id_veh_sumo))[2:], traci.vehicle.getRoute(id_veh_sumo)31983199# check for new vehicle arrivals/departures3200ids_veh_sumo = set(traci.edge.getLastStepVehicleIDs(id_edge_sumo))3201# print ' ids_veh_sumo_prev=',ids_veh_sumo_prev3202# print ' ids_veh_sumo=',ids_veh_sumo32033204if ids_veh_sumo_prev != ids_veh_sumo:3205ids_veh_entered = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo.difference(ids_veh_sumo_prev)))3206ids_veh_left = vehicles.get_ids_from_ids_sumo(list(ids_veh_sumo_prev.difference(ids_veh_sumo)))3207# print ' ids_veh_entered',ids_veh_entered3208# print ' ids_veh_left',ids_veh_left3209# for id_veh in ids_veh_entered:3210self.enter(id_stop, ids_veh_entered, fase, simtime)32113212for id_veh in ids_veh_left:3213self.exit(id_stop, id_veh, fase)3214self.ids_vehs_sumo_prev[id_stop] = ids_veh_sumo3215# print ' ids_veh_sumo_entered',ids_veh_sumo_entered3216# print ' ids_veh_sumo_left',ids_veh_sumo_left32173218# check whether allocated vehicles arrived at stopline3219# of alighting berths and move sidewards into the berth3220ids_veh_remove = []3221for id_veh in self.ids_vehs_alight_forward[id_stop]:3222# TODO: here we could also check vehicle position3223id_veh_sumo = vehicles.get_id_sumo(id_veh)32243225# print ' isStopped',id_veh_sumo,traci.vehicle.isStopped(id_veh_sumo)32263227if traci.vehicle.isStopped(id_veh_sumo):32283229id_berth_alight = vehicles.ids_berth[id_veh]3230pos_berth = berths.stoppositions[id_berth_alight]3231# print ' pos_berth',pos_berth,'pos_current',traci.vehicle.getLanePosition(id_veh_sumo)3232if abs(pos_berth-traci.vehicle.getLanePosition(id_veh_sumo)) < 1.0:3233# stop at berth reached, proceed with moving in3234ids_veh_remove.append(id_veh)3235self.ids_vehs_alight_aproach[id_stop].add(id_veh) # ??????? no further use32363237traci.vehicle.resume(id_veh_sumo)3238#traci.vehicle.changeLane(id_veh_sumo, 1, 3600.0)3239#pos = traci.vehicle.getLanePosition(id_veh_sumo)32403241# print ' vehicle moving into id_berth_alight',id_berth_alight,'pos',berths.stoppositions[id_berth_alight]3242# this will cause the vehicle to slip sidewards into the berth3243# upon arrival alighting and boarding can take place3244vehicles.control_berth_stop(3245id_veh,3246id_edge_sumo=id_edge_sumo,3247position=pos_berth,3248laneindex=1,3249)3250traci.vehicle.changeLane(id_veh_sumo, 1, 10.0)32513252else:3253# print ' vehicle is stopped but did not reach alight bearth'3254# ->remove stop3255traci.vehicle.resume(id_veh_sumo)32563257for id_veh in ids_veh_remove:3258self.ids_vehs_alight_forward[id_stop].remove(id_veh)32593260# if vehicles.id_follower_probe != vehicles.ids_follower[271]:3261# print 'PRE APPROACH STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]3262# check whether allocated vehicles arrived at berth3263# and alight passengers32643265ids_veh_remove = []3266for id_veh in self.ids_vehs_alight_aproach[id_stop]:3267# TODO: here we could also check vehicle position3268id_veh_sumo = vehicles.get_id_sumo(id_veh)3269# print ' %s'%id_veh_sumo,'isStopped',traci.vehicle.isStopped(id_veh_sumo)32703271if traci.vehicle.isStopped(id_veh_sumo):3272ids_veh_remove.append(id_veh)3273id_berth_alight = vehicles.ids_berth[id_veh]3274if self.debug:3275print ' %s stopped inside berth %d and alights' % (id_veh_sumo, id_berth_alight)32763277# vehicles.set_stop( id_veh,3278# id_edge_sumo,3279# berths.stoppositions[id_berth_alight],3280# laneindex = 1)3281#32823283# this assigns a vehicle to a station berth in the berth db3284berths.set_alighting(id_berth_alight, id_veh)32853286# set vehicle in alight mode3287vehicles.alight(id_veh)32883289for id_veh in ids_veh_remove:3290self.ids_vehs_alight_aproach[id_stop].discard(id_veh)32913292# if vehicles.id_follower_probe != vehicles.ids_follower[271]:3293# print 'PRE PERS STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]32943295# check for new person entering/left the station edge3296ids_person_sumo = set(traci.edge.getLastStepPersonIDs(id_edge_sumo))32973298n_enter = 03299if ids_person_sumo_prev != ids_person_sumo:33003301if 0:3302print ' change\n id_person_sumo', ids_person_sumo3303print ' ids_person_sumo_prev', ids_person_sumo_prev3304# print ' dir(traci.person)',dir(traci.person)3305# for id_person_sumo in ids_person_sumo:3306# print ' id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo),traci.person.getVehicle(id_person_sumo)33073308# deal with persons who entered the edge3309ids_person_sumo_entered = ids_person_sumo.difference(ids_person_sumo_prev)3310for id_person_sumo in ids_person_sumo_entered:3311# print ' entered id_person_sumo',id_person_sumo,traci.person.getRoadID(id_person_sumo)3312if self.id_person_to_origs_dests.has_key(id_person_sumo):3313id_edge_sumo_dests = self.id_person_to_origs_dests[id_person_sumo]33143315# id_edge_sumo_dests[i] = ( id_stop_from,3316# id_stop_to,3317# id_fromedge_sumo,3318# id_toedge_sumo)33193320# check if person still has a PRT trip33213322if len(id_edge_sumo_dests) > 0: # valid dest3323# check if next trip has origin edge equal to edge of this stop3324if id_edge_sumo_dests[0][2] == id_edge_sumo:3325if self.debug:3326print ' add to waittimes_persons', id_person_sumo, 'id_stop_dest', id_edge_sumo_dests[0][1], 'id_toedge_sumo', id_edge_sumo_dests[0][3]3327self.waittimes_persons[id_stop][id_person_sumo] = simtime3328n_enter += 133293330# else:3331# print 'WARNING: person %s starts with % insted of %s.'%(id_person_sumo,id_edge_sumo_dests[0][2],id_edge_sumo)33323333# communicate person entry to vehman3334# this is used for person flow measurements3335self.parent.vehicleman.note_person_entered(id_stop, n_enter)33363337self.numbers_person_wait[id_stop] += n_enter3338self.ids_persons_sumo_prev[id_stop] = ids_person_sumo33393340self.waittimes_tot += self.numbers_person_wait*self.time_update.get_value()33413342timeconst_flow = self.timeconst_flow.get_value()3343self.flows_person[id_stop] = timeconst_flow*self.flows_person[id_stop] + \3344(1.0-timeconst_flow)*float(n_enter)/self.time_update.get_value()33453346if 0:3347for id_person_sumo in ids_person_sumo_prev:3348print ' ids_person_sumo=%s pos = %.2f ' % (id_person_sumo, traci.person.getLanePosition(id_person_sumo))3349# nomore print ' ids_persons_sumo_boarded',self.ids_persons_sumo_boarded[id_stop]33503351# if vehicles.id_follower_probe != vehicles.ids_follower[271]:3352# print 'PRE BOARD STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]33533354# check berth if alighting is completed in load area,3355# starting with last vehicle3356ids_berth_board = self.ids_berths[id_stop][::-1]3357for id_berth_board, id_veh in zip(3358ids_berth_board,3359berths.ids_veh[ids_berth_board],3360):3361# print ' before: berth',id_berth_board,'state',berths.states[id_berth_board],'id_veh',id_veh33623363if (id_veh > -1): # is there a waiting vehicle3364id_veh_sumo = vehicles.get_id_sumo(id_veh)3365if (berths.states[id_berth_board] == BERTHSTATES['alighting']):33663367# this will put the vehicle in waiting or boarding mode3368if vehicles.is_completed_alighting(id_veh):3369if self.debug:3370print ' state of prt.%d: %d' % (id_veh, vehicles.states[id_veh])3371if vehicles.states[id_veh] == VEHICLESTATES['boarding']:3372# print ' set id_berth_board',id_berth_board,'to state boarding'3373berths.set_boarding(id_berth_board)33743375else:3376berths.set_waiting_empty(id_berth_board)33773378elif (berths.states[id_berth_board] in [BERTHSTATES['waiting'], BERTHSTATES['boarding']]):33793380if vehicles.states[id_veh] != VEHICLESTATES['boarding_completed']:3381if vehicles.is_completed_boarding(id_veh):3382# has just completed boarding3383self.route_trip_occupied(id_stop,3384id_berth_board,3385id_veh,3386id_veh_sumo,3387simtime)33883389# print ' after alighting: berth',id_berth_board,'state',berths.states[id_berth_board]33903391ids_veh_to_allocate = self.get_ids_veh_to_allocate(id_stop)3392ids_veh_to_pass = self.get_ids_veh_to_pass(id_stop)33933394# check whether to change phases3395if fase == FASE_MOVE_IN:3396# stop is in move in fase3397if self.debug:3398print ' >>timeout fase 0: dt=%.2f timeout=%.2f' % ((simtime - self.times_phase_in[id_stop]), self.time_fase_in_max.get_value()),\3399'TOUT', ((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value()3400), '|ALLOC', (len(self.ids_vehs_inqueue[id_stop]) > 0)3401# print ' ap',(len(self.ids_vehs_alight_aproach[id_stop]) == 0)3402print ' no forward, all vehicles moved into berth', (len(self.ids_vehs_alight_forward[id_stop]) == 0)3403print ' ids_vehs_inqueue', self.ids_vehs_inqueue[id_stop]3404print ' ids_veh_to_allocate', ids_veh_to_allocate3405print ' ids_veh_to_pass', ids_veh_to_pass3406print ' is_back_to_move_in ', self.are_back_to_move_in[id_stop]3407# if np.isnan(self.times_phase_in[id_stop]):3408# # only for initialization3409# self.times_phase_in[id_stop] = simtime - self.time_fase_in_max.get_value()34103411if (((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value())3412| (self.inds_berth_allocated[id_stop] == -1)3413| (len(ids_veh_to_pass) > 0))\3414& (len(self.ids_vehs_alight_forward[id_stop]) == 0):34153416# if len(ids_veh_to_pass)>0 then passthrough vehicles are in pole position3417# to be handeled and required by try_start_vehicles method3418# in order to start them and create platoons3419# in this case the move in fase should continue as soon as the3420# pass through vehicles are processed3421self.are_back_to_move_in[id_stop] = len(ids_veh_to_pass) > 034223423# if (((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value()) | (len(ids_berth_to_allocate)==0))\3424# &(len(self.ids_vehs_alight_forward[id_stop]) == 0):34253426# &(len(self.ids_vehs_alight_aproach[id_stop]) == 0)34273428# time out for fase in reached or allocation queue starts growing3429# which means that there are no more free berth to allocate3430# and all forwarded vehicles reached their berth to alight3431if self.debug:3432print ' Switch from fase %d to fase %d' % (self.fases[id_stop], FASE_MOVE_OUT)3433self.fases[id_stop] = FASE_MOVE_OUT3434self.times_phase_out[id_stop] = simtime34353436elif fase == FASE_MOVE_OUT:3437# stop is in move out fase3438if self.debug:3439print ' >>timeout fase 1: dt=%.2f timeout=%.2f' % ((simtime - self.times_phase_out[id_stop]), self.time_fase_out_max.get_value()), 'move out of berth', len(self.ids_vehs_berth_exit[id_stop])3440print ' n_berth_exit', len(self.ids_vehs_berth_exit[id_stop]), 'n_veh_pass', len(ids_veh_to_pass), 'ids_veh_to_pass', ids_veh_to_pass3441# check fase transition3442# if np.isnan(self.times_phase_out[id_stop]):3443# # only for initialization3444# self.times_phase_in[id_stop] = simtime - self.time_fase_out_max.get_value()34453446if (((simtime-self.times_phase_out[id_stop]) > self.time_fase_out_max.get_value()) | (len(self.ids_vehs_inqueue[id_stop]) >= self.capas_inqueue[id_stop]) | self.are_back_to_move_in[id_stop])\3447& (len(self.ids_vehs_berth_exit[id_stop]) == 0) & (len(ids_veh_to_pass) == 0) & (len(self.ids_berths_veh_wait_exit[id_stop]) == 0) & (len(self.ids_vehs_pass_wait_exit[id_stop]) == 0):3448# time out and no vehicles are about to exit berth3449# if len(ids_veh_to_pass) == 0 then this is to ensure that3450# there are no longer passthrough vehicles in the3451# input queue3452self.are_back_to_move_in[id_stop] = False34533454if self.debug:3455print ' Switch from fase %d to fase %d' % (self.fases[id_stop], FASE_MOVE_IN), 'ind_berth_allocated', self.inds_berth_allocated[id_stop]34563457self.fases[id_stop] = FASE_MOVE_IN3458self.times_phase_in[id_stop] = simtime34593460# check if bert allocation index arrver at -1 and reset3461if self.inds_berth_allocated[id_stop] == -1:3462# identify currently free berth3463# current available berth to allocate3464ids_berth_to_allocate = self.get_berths_with_state(id_stop, BERTHSTATES['free'])3465self.ids_berths_to_allocate[id_stop] = list(ids_berth_to_allocate)3466# reset counter3467self.inds_berth_allocated[id_stop] = len(self.ids_berths_to_allocate[id_stop])34683469# allocate vehicles accumulated in input queue34703471if (len(ids_veh_to_allocate) > 0) & (len(ids_veh_to_pass) == 0) & (self.inds_berth_allocated[id_stop] > -1):3472ids_veh_remove = []3473# print ' before:ids_vehs_to_allocate',self.ids_vehs_inqueue[id_stop]3474ids_berths = self.allocate_alight(id_stop, len(ids_veh_to_allocate))3475for id_veh, id_berth in zip(ids_veh_to_allocate, ids_berths):3476#id_berth = self.allocate_alight(id_stop)3477# command vehicle to go to berth for alighting3478if id_berth > -1:3479if self.debug:3480print ' foreward queued vehicle id_veh prt.%d to id_berth %d at pos %.2fm' % (id_veh, id_berth, berths.stoppositions[id_berth])3481vehicles.control_berth_position_enter(id_veh, id_berth,3482id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],3483# needs to stop a bit before to move in3484position=berths.stoppositions[id_berth]-0.3,3485laneindex=2,3486)3487self.ids_vehs_alight_forward[id_stop].append(id_veh)3488ids_veh_remove.append(id_veh)3489# print ' after:ids_vehs_to_allocate',self.ids_vehs_inqueue[id_stop]3490for id_veh in ids_veh_remove:3491self.ids_vehs_inqueue[id_stop].remove(id_veh)34923493# print ' New fase:',self.fases[id_stop],'FASE_MOVE_OUT',self.fases[id_stop] == FASE_MOVE_OUT34943495# if vehicles.id_follower_probe != vehicles.ids_follower[271]:3496# print 'POST PHASECHANGE STOP WARNING: prt.271 changed follower',vehicles.id_follower_probe,vehicles.ids_follower[271]34973498if self.fases[id_stop] == FASE_MOVE_IN:3499# specific tasks during move in fase3500pass35013502elif self.fases[id_stop] == FASE_MOVE_OUT:3503# specific tasks during move out fase35043505# check which vehicles to start3506self.try_start_vehicles(id_stop, simtime, n_plat_min=3)3507self.foreward_vehicles_exit(id_stop)35083509# try to release vehicles3510ids_veh = self.get_vehicles_ready_for_departure(id_stop)3511if len(ids_veh) > 0: # there are new vehicles ready for departure3512self.prepare_vehs_for_departure(id_stop, ids_veh)35133514if self.are_reposition_out[id_stop]:3515self._reposition_outqueue(id_stop)35163517def route_trip_occupied(self, id_stop, id_berth, id_veh, id_veh_sumo, simtime):35183519berths = self.get_berths()3520vehicles = self.parent.prtvehicles3521#id_veh_sumo = self.parent.prtvehicles.get_id_sumo(id_veh)3522n_pax = traci.vehicle.getPersonNumber(id_veh_sumo)3523if self.debug:3524print 'route_trip_occupied id_stop', id_stop, 'id_berth', id_berth, 'veh=%s' % id_veh_sumo, 'simtime', simtime, 'n_pax', n_pax35253526# identify which of the boarding persons is in the3527# vehicle which completed boarding3528dist_min = np.inf3529id_person_sumo_inveh = None3530stoppos = berths.stoppositions[id_berth]35313532# identify person(s) in vehicle3533ids_person_sumo_inveh = traci.vehicle.getPersonIDList(id_veh_sumo)3534if len(ids_person_sumo_inveh) > 0:3535id_person_sumo_inveh = ids_person_sumo_inveh[0]3536if self.debug:3537print ' found person %s in veh prt.%s' % (id_person_sumo_inveh, id_veh_sumo)35383539# program vehicle to person's destination3540# print ' found person,origs_dests',id_person_sumo_inveh,self.id_person_to_origs_dests[id_person_sumo_inveh]3541id_stop_orig, id_stop_dest, id_edge_sumo_from, id_edge_sumo_to = \3542self.id_person_to_origs_dests[id_person_sumo_inveh].pop(0)3543if self.debug:3544print ' found person %s' % id_person_sumo_inveh, 'from', id_stop_orig, id_edge_sumo_from, ' to', id_edge_sumo_to, id_stop_dest35453546route, duration = self.route_stop_to_stop(id_stop_orig, id_stop_dest)35473548# print ' found route',route3549# print ' found duration',duration35503551# this is setting the target route which3552# used to set the effective route and to identify possible3553# platoon cooperations3554vehicles.set_route_target(id_veh, route, id_stop_target=id_stop_dest, is_disengage_from_berth=True)3555#stopline = self._get_stopline(id_stop, simtime)3556# print ' simtime', simtime35573558# self.parent.prtvehicles.init_trip_occupied(\3559# id_veh, self.ids_stop_to_ids_edge_sumo[id_stop],3560# stopline,3561# )35623563# self.ids_persons_sumo_boarded[id_stop].remove(id_person_sumo_inveh)3564self.times_lastboard[id_stop] = simtime3565berths.set_waiting_routed(id_berth, simtime)3566#berths.ids_veh[id_berth] = -13567self.ids_vehs_routed[id_stop].add(id_veh)3568#self.try_set_leadveh(id_stop, id_veh)3569self.parent.vehicleman.init_trip_occupied(id_veh, id_stop, id_stop_dest, simtime)35703571for id_person_sumo in ids_person_sumo_inveh:3572self.waittimes_tot[id_stop] -= simtime - self.waittimes_persons[id_stop][id_person_sumo]3573del self.waittimes_persons[id_stop][id_person_sumo]35743575self.numbers_person_wait[id_stop] -= len(ids_person_sumo_inveh)35763577else:3578print 'WARNING: on stop %d edge %s, berth %d no person found inside vehicle prt.%d' % (id_stop, self.ids_stop_to_ids_edge_sumo[id_stop], id_berth, id_veh)3579return None35803581def get_surplus_veh(self, id_stop):3582# all waiting vehicles35833584# use this method instead of self.get_vehs_waiting because it is faster3585# however in self.route_empties the method self.get_vehs_waiting3586# must be used to ensure that no vehicle has been occupied in the meanwhile3587n_veh_waiting = len(self.get_berths_with_state(id_stop, BERTHSTATES['waiting']))35883589# waiting vehicles that need to make room for arriving vehicles3590n_berth = len(self.ids_berths[id_stop])3591surplus_veh_urgent = max(len(self.ids_vehs_inqueue[id_stop])-(n_berth-n_veh_waiting), 0)3592return n_veh_waiting, surplus_veh_urgent35933594def get_vehs_waiting(self, id_stop):3595"""Returns lists of empty and occupied waiting vehicles, as well as their respective berth IDs."""3596print 'get_vehs_waiting id_stop', id_stop3597ids_berth_waiting = self.get_berths_with_state(id_stop, BERTHSTATES['waiting'])35983599ids_veh_waiting = self.get_berths().ids_veh[ids_berth_waiting]3600ids_veh_waiting_empty = []3601ids_veh_waiting_occup = []3602ids_berth_empty = []3603ids_berth_occup = []3604for id_berth, id_veh, id_veh_sumo in zip(ids_berth_waiting, ids_veh_waiting, self.parent.prtvehicles.ids_sumo[ids_veh_waiting]):3605# check here if these vehicles are still waiting or if3606# there has bee a person sitting in3607print ' check id_veh_sumo', id_veh_sumo, 'n_pers', traci.vehicle.getPersonNumber(id_veh_sumo)3608if traci.vehicle.getPersonNumber(id_veh_sumo) == 0:3609ids_veh_waiting_empty.append(id_veh)3610ids_berth_empty.append(id_berth)3611else:3612ids_veh_waiting_occup.append(id_veh)3613ids_berth_occup.append(id_berth)36143615print ' ids_veh_waiting_empty', ids_veh_waiting_empty3616return ids_veh_waiting_empty, ids_veh_waiting_occup, ids_berth_empty, ids_berth_occup36173618def route_empties(self, id_stop, id_stop_target, n_move, simtime):3619"""3620Route n_move empty vehicles to ids_stop_target.3621Route also newly occupied vehicles if present.3622Called by vehman3623"""3624print 'route_empties id_stop', id_stop, '>id_stop_target', id_stop_target, 'n_move', n_move3625berths = self.get_berths()3626vehicles = self.parent.prtvehicles3627ids_veh_empty, ids_veh_waiting_occup, ids_berth, ids_berth_occup = self.get_vehs_waiting(id_stop)3628n_veh_empty = len(ids_veh_empty)3629n_move_eff = min(n_move, n_veh_empty)3630print ' =>n_veh_empty', n_veh_empty, 'n_move_eff', n_move_eff36313632# if n_move <= n_veh_empty:36333634for id_berth, id_veh in zip(ids_berth[:n_move], ids_veh_empty[:n_move]):3635if self.debug:3636print ' route empty veh prt.%d' % id_veh, 'at berth', id_berth, 'from stop', id_stop, ' to', id_stop_target36373638route, duration = self.route_stop_to_stop(id_stop, id_stop_target)36393640# print ' found route',route3641# print ' found duration',duration36423643vehicles.set_route_target(id_veh, route, id_stop_target=id_stop_target,3644is_disengage_from_berth=True, is_emptytrip=True)3645#stopline = self._get_stopline(id_stop, simtime)3646# print ' simtime', simtime36473648berths.set_waiting_routed(id_berth, simtime)3649#berths.ids_veh[id_berth] = -13650self.ids_vehs_routed[id_stop].add(id_veh)36513652# inform vehicle man when started and next destination is determined3653# self.parent.vehicleman.init_trip_empty(id_veh, id_stop, id_stop_target, simtime)36543655if 0: # not necessary, process step will take care of it3656for id_berth, id_veh in zip(ids_berth_occup, ids_veh_waiting_occup):3657if self.debug:3658print ' route occupied veh prt.%d' % id_veh, 'at berth', id_berth, 'from stop', id_stop, ' to', id_stop_target36593660route, duration = self.route_stop_to_stop(id_stop, id_stop_target)36613662# print ' found route',route3663# print ' found duration',duration36643665vehicles.set_route_target(id_veh, route, id_stop_target=id_stop_target,3666is_disengage_from_berth=True)3667#stopline = self._get_stopline(id_stop, simtime)3668# print ' simtime', simtime36693670berths.set_waiting_routed(id_berth, simtime)3671#berths.ids_veh[id_berth] = -13672self.ids_vehs_routed[id_stop].add(id_veh)36733674# else:3675# print 'WARNING: on stop %d edge insufficient empty vehicles. Veh Man requested more than present.'%(id_stop)3676# return False36773678# return the effectively sent number of vrhicles to inform3679# vehicle management3680return n_move_eff36813682def route_stop_to_stop(self, id_stop_from, id_stop_to):3683# route3684return self.parent.get_route(self.ids_stop_to_ids_edge[id_stop_from],3685self.ids_stop_to_ids_edge[id_stop_to])36863687def foreward_vehicles_exit(self, id_stop):3688"""3689Check whether all vehicles moved out of the berth.3690If yes, then forward vehicles to the exit.3691"""3692# Here is the sequance of vehicle control calls and the change3693# of states3694# vehicles.control_berth_position_exit -> VEHICLESTATES['kickout_berth']3695# vehicles.control_berth_position_exit_slowdown -> VEHICLESTATES['forewarding_exit']3696# vehicles.control_forewarding_exit -> VEHICLESTATES['forewarding_exit_kickout']36973698ids_veh_berth_exit = self.ids_vehs_berth_exit[id_stop]3699ids_veh_out = self.ids_vehs_out[id_stop]3700capa_out = self.capas_outqueue[id_stop]3701n_veh = len(ids_veh_berth_exit)3702print 'foreward_vehicles_exit check', n_veh37033704if n_veh == 0:3705return False37063707berths = self.get_berths()3708vehicles = self.parent.prtvehicles37093710are_stopped = np.zeros(n_veh, dtype=np.bool)3711for i, id_veh, state in zip(xrange(n_veh), ids_veh_berth_exit, vehicles.states[ids_veh_berth_exit]):37123713# TODO: here we could also check vehicle position3714id_veh_sumo = vehicles.get_id_sumo(id_veh)3715# if self.debug:3716# print ' ',id_veh_sumo,'state',state,'is_stopped',traci.vehicle.isStopped(id_veh_sumo),'ind_lane',traci.vehicle.getLaneIndex(id_veh_sumo)3717# now this is the workaround to prevent passengers3718# from jumping on board while the vehicle is stopped3719# on the third lane: vehicles that stopped on the 3rd lane3720# must be immediately put in (slow) motion3721if state == VEHICLESTATES['kickout_berth']:3722if traci.vehicle.isStopped(id_veh_sumo) & (traci.vehicle.getLaneIndex(id_veh_sumo) == 2):3723vehicles.control_berth_position_exit_slowdown(id_veh) # set VEHICLESTATES['forewarding_exit']3724is_stopped = False3725else:3726# vehicle has been previously stopped to slow speed3727is_stopped = state == VEHICLESTATES['forewarding_exit']37283729are_stopped[i] = is_stopped | (state == VEHICLESTATES['forewarding_passthrough'])3730if self.debug:3731print ' %s' % id_veh_sumo, 'are_stopped', are_stopped[i], 'stop', traci.vehicle.isStopped(id_veh_sumo), 'state', state, 'laneindex', traci.vehicle.getLaneIndex(id_veh_sumo)37323733if self.debug:3734print ' are_stopped', are_stopped37353736if np.all(are_stopped):3737if self.debug:3738print ' all vehicles are moved out of the berth'37393740# foreward to exit3741#ids_veh_out = self.ids_vehs_out[id_stop]3742# for id_veh in ids_veh_berth_exit:3743# self.append_to_outqueue(id_stop, id_veh)37443745# here we move to outqueue only if output lenth is not exceeded3746# this fixes the problem where passegers jump into vehicles3747# when stopping inside the platform range3748while (len(ids_veh_berth_exit) > 0) & (len(ids_veh_out) < capa_out):3749self.append_to_outqueue(id_stop, ids_veh_berth_exit.pop(0))37503751if self.debug:3752if (len(ids_veh_out) < capa_out):3753print ' Out buffer capacity exceeded, left veh:', ids_veh_berth_exit37543755#self.ids_vehs_berth_exit[id_stop] = []37563757return True37583759def append_to_outqueue(self, id_stop, id_veh):3760vehicles = self.parent.prtvehicles3761ids_veh_out = self.ids_vehs_out[id_stop]3762if len(ids_veh_out) == 0:3763stoppos = self.stoplines[id_stop]3764else:3765id_veh_pre, stoppos_pre = ids_veh_out[-1]3766stoppos = stoppos_pre - vehicles.length - 1.5*vehicles.dist_min37673768vehicles.control_forewarding_exit(id_veh,3769id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],3770position=stoppos,3771laneindex=2,3772)3773if self.debug:3774print ' append prt.%d to output queue' % id_veh3775ids_veh_out.append((id_veh, stoppos))37763777def get_vehicles_ready_for_departure(self, id_stop):3778"""3779Check whether vehicles are in the output buffer ready for release.3780Theses are all stopped vehicles with identical destination3781at the exit of the output queue.3782"""3783ids_veh_out = self.ids_vehs_out[id_stop]3784n_veh = len(ids_veh_out)3785ids_veh_ready = self.ids_vehs_ready_for_departure[id_stop]3786is_veh_ready = len(ids_veh_ready) > 03787print 'get_vehicles_ready_for_departure check id_stop', id_stop, ' len(ids_vehs_out)', n_veh, 'capa', self.capas_outqueue[id_stop]3788if is_veh_ready:3789if self.debug:3790print ' there are still vehicles ready to be launched'3791print ' ids_veh_ready', ids_veh_ready3792return []37933794berths = self.get_berths()3795vehicles = self.parent.prtvehicles3796if self.debug:3797print ' ids_berths_veh_wait_exit', type(self.ids_berths_veh_wait_exit[id_stop]), self.ids_berths_veh_wait_exit[id_stop], 'ids_veh_berth_wait', berths.ids_veh[self.ids_berths_veh_wait_exit[id_stop]]37983799if (n_veh == 0):3800if self.debug:3801print ' no vehicles in output queue'3802return []38033804# search after ready vehicles, that will be launched shortly38053806i = 0 # len(ids_veh_ready)3807ids_veh_platoon = []3808is_cont = True3809id_stopedge_target = -13810while is_cont & (i < n_veh):3811id_veh, stoppos = ids_veh_out[i]3812if id_stopedge_target == -1: # target not yet defined3813id_stopedge_target = vehicles.routes[id_veh][-1]3814if self.debug:3815# ,'is_stopped',is_stopped3816print ' %d Leader prt.%d' % (i, id_veh), 'id_stopedge_target', id_stopedge_target38173818else:3819if self.debug:3820print ' %d Follower prt.%d' % (i, id_veh), 'is_cont next', vehicles.routes[id_veh][-1] == id_stopedge_target38213822if vehicles.routes[id_veh][-1] == id_stopedge_target:3823ids_veh_platoon.append((id_veh, stoppos))3824i += 13825else:3826is_cont = False38273828if (i == n_veh):3829if ((len(self.ids_berths_veh_wait_exit[id_stop]) > 0) | (len(self.ids_vehs_pass_wait_exit[id_stop]) > 0))\3830& (i < self.capas_outqueue[id_stop]-1):3831if self.debug:3832print ' Maybe incomplete platoon, wait till all vehicles are kicked out of berths'3833print ' len(ids_berths_veh_wait_exit)', len(self.ids_berths_veh_wait_exit[id_stop]), 'len(ids_vehs_pass_wait_exit)', len(self.ids_vehs_pass_wait_exit[id_stop]), "i", i3834return []3835else:3836# the entire out queue has the same destination3837# and will leave the stop3838if self.debug:3839print ' entire out queue same dest and ready for departure'3840#is_update_outqueue = False3841else:3842# only a part of te out-queue departs, update position of rest3843if self.debug:3844print ' partial out queue ready for departure'3845#is_update_outqueue = True38463847# Check if all vehicles in the platoon are stopped at the3848# defined stopline3849id_stopedge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop]3850are_stopped = True3851are_finalpos = True3852ids_veh_ready_new = []3853if self.debug:3854print ' position check/update ids_veh_platoon', ids_veh_platoon3855for id_veh, stoppos in ids_veh_platoon:38563857id_veh_sumo = vehicles.get_id_sumo(id_veh)3858is_stopped = traci.vehicle.isStopped(id_veh_sumo)3859if self.debug:3860print ' stopcheck ', id_veh_sumo, 'are_stopped', are_stopped, 'is_stopped', is_stopped38613862if is_stopped:3863# check if stopposition is correct3864pos_veh = traci.vehicle.getLanePosition(id_veh_sumo)3865are_finalpos &= abs(pos_veh-stoppos) < 0.13866are_stopped &= are_finalpos38673868if 0: # be done for all in _reposition_outqueue3869if not is_stopped:3870# vehicle is stopped but not at correct position3871are_stopped = False3872if self.debug:3873print ' update stoppos of prt.%s:' % id_veh_sumo, 'from curpos', pos_veh, 'stoppos', stoppos3874# vehicle has stopped but not at the correct stop position3875# =>foreward vehicle to the correct position3876vehicles.control_forewarding_exit(id_veh,3877id_edge_sumo=id_stopedge_sumo,3878position=stoppos,3879laneindex=2,3880)3881else:3882are_stopped = False38833884#is_pos_correct = traci.vehicle.get3885# print ' Veh',id_veh_sumo,'is_stopped',is_stopped3886# if not is_veh_ready:# means that there are not already vehicles ready3887if self.debug:3888print ' append prt.%d to ids_veh_ready_new' % (id_veh)3889ids_veh_ready_new.append(id_veh)38903891if self.debug:3892print ' ready? are_stopped %s,' % (are_stopped), 'ids_veh_ready_new', ids_veh_ready_new38933894# value if platoon is ready to leave3895if (not is_veh_ready) & are_stopped:3896if self.debug:3897print ' all vehicles of the platoon are stopped, platoon ready.'3898return ids_veh_ready_new38993900else:3901if not are_finalpos:3902self.are_reposition_out[id_stop] = True3903if self.debug:3904print ' vehicles of platoon not stopped at coorect position or previous ready vehicles not launched.'3905else:3906if self.debug:3907print ' not all vehicles of platoon stopped or previous ready vehicles not launched.'3908return []39093910def _reposition_outqueue(self, id_stop):3911# print '_reposition_outqueue id_stop',id_stop3912vehicles = self.parent.prtvehicles3913id_stopedge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop]3914is_reposition = False3915for id_veh, stoppos in self.ids_vehs_out[id_stop]:3916id_veh_sumo = vehicles.get_id_sumo(id_veh)3917pos_veh = traci.vehicle.getLanePosition(id_veh_sumo)3918is_correct_pos = abs(pos_veh-stoppos) < 0.13919# print ' update stopcheck ',id_veh_sumo,'is_correct_pos',is_correct_pos39203921# check if stopposition is corrent3922if not is_correct_pos:39233924if traci.vehicle.isStopped(id_veh_sumo):39253926# vehicle is stopped but not at correct position3927# print ' update stoppos of rem prt.%s:'%id_veh_sumo,'from curpos',pos_veh,'stoppos',stoppos3928# vehicle has stopped but not at the correct stop position3929# =>foreward vehicle to the correct position3930vehicles.control_forewarding_exit(id_veh,3931id_edge_sumo=id_stopedge_sumo,3932position=stoppos,3933laneindex=2,3934)3935else:3936# vehicle needs correction but still in movement3937# print ' update stoppos when vehicle is stopped'3938is_reposition = True39393940self.are_reposition_out[id_stop] = is_reposition39413942def prepare_vehs_for_departure(self, id_stop, ids_veh):3943"""3944Concatenate vehicles ids_veh with identical destination3945and signals ready for departure to vehicle management .3946The vehicle management will the check capacity availability3947and launch the vehicles with the launch_vehs method.3948"""3949#ids_veh_out = self.ids_vehs_out[id_stop]3950n_veh = len(ids_veh)3951print 'prepare_vehs_for_departure id_stop', id_stop, 'n_veh', n_veh3952ids_veh_out = self.ids_vehs_out[id_stop]3953if n_veh == 0:3954return False39553956vehicles = self.parent.prtvehicles39573958if n_veh > 1:3959# concatenate platoon3960for id_veh_infront, id_veh in zip(ids_veh[:-1], ids_veh[1:]):3961vehicles.concatenate(id_veh, id_veh_infront)39623963if self.debug:3964print ' prepared:'3965for id_veh, route in zip(ids_veh, vehicles.routes[ids_veh]):3966id_stopedge = route[-1]3967print ' prep. prt.%d' % id_veh, 'with id_stopedge', id_stopedge, 'id_stop', self.id_edge_to_id_stop[id_stopedge]39683969id_veh_lead = ids_veh[0]3970id_stopedge_target = vehicles.routes[id_veh_lead][-1]3971id_stop_target = self.id_edge_to_id_stop[id_stopedge_target]3972time_est = np.sum(self.parent.edgetimes[vehicles.routes[id_veh_lead]])3973self.ids_vehs_ready_for_departure[id_stop] = list(ids_veh)39743975self.parent.vehicleman.note_vehs_ready_for_departure(id_stop, id_stop_target, time_est, n_veh)39763977for i in xrange(n_veh):3978ids_veh_out.pop(0)39793980if len(ids_veh_out) > 0:3981if self.debug:3982print ' position update for remaining ids_veh_out', ids_veh_out3983# move foreward stoplines of remaining vehicles in output queue3984stopline = self.stoplines[id_stop]3985id_edge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop]3986for ind in xrange(len(ids_veh_out)):3987id_veh, stoppos_prev = ids_veh_out[ind]3988stoppos = stopline - ind * (vehicles.length+1.5*vehicles.dist_min)3989# vehicles.control_forewarding_exit(id_veh,\3990# id_edge_sumo = id_edge_sumo,3991# position = stoppos,3992# laneindex = 2,3993# )39943995if self.debug:3996id_veh_sumo = 'prt.%s' % id_veh3997print ' update stoppos of prt.%s:' % id_veh_sumo, 'from curpos', traci.vehicle.getLanePosition(id_veh_sumo), 'to stoppos', stoppos3998# print ' stopinfo:',traci.vehicle.getNextStops(id_veh_sumo)3999ids_veh_out[ind] = (id_veh, stoppos)40004001# signal repositioning necessary4002self.are_reposition_out[id_stop] = True40034004def launch_vehs(self, id_stop, id_stop_target):4005"""4006Method called from vehicle management when vehicles are allowed to depart.4007"""4008print 'launch_vehs at id_stop', id_stop4009ids_veh = self.ids_vehs_ready_for_departure[id_stop]4010#ids_veh_out = self.ids_vehs_out[id_stop]4011vehicles = self.parent.prtvehicles4012#ids_veh = self.ids_vehs_ready_for_departure[id_stop]4013# if self.debug:4014print ' to launch: ids_veh', ids_veh # ,'with ids_stopedge_next',vehicles.routes[ids_veh]40154016if len(ids_veh) == 0:4017print 'WARNING in launch_vehs: there are no vehicles to lauche at id_stop', id_stop40184019# here may check if destination stop is correct40204021for id_veh in ids_veh:4022vehicles.launch_from_stop(id_veh)40234024#id_veh_out, stoppos = ids_veh_out.pop(0)4025# if self.debug:4026print ' launched prt.%d to id_stopedge_target %d' % (id_veh, vehicles.routes[id_veh][-1])4027# if id_veh_out != id_veh:4028# print 'WARNING: wrong vehicle from output queue'4029# sys.exit(0)4030# ids_veh_out.remove(id_veh)40314032# make sure that first vehicle in remaining out-queue stops at stopline4033# if len(ids_veh_out)>0:4034# id_veh = ids_veh_out[0]4035# vehicles.control_forewarding_exit(id_veh,\4036# id_edge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop],4037# position = self.stoplines[id_stop],4038# laneindex = 2,4039# )40404041return True40424043def is_outputqueue_compact(self, id_stop):4044"""Returns True if all vehicles in the output queue are beyond4045the last berth of the stop"""40464047pos_lastberth = self.get_berths().stoppositions[self.ids_berths[id_stop]][-1]4048print 'is_outputqueue_compact n_outqueue', len(self.ids_vehs_out[id_stop]), 'pos_lastberth %.2f' % pos_lastberth40494050vehicles = self.parent.prtvehicles4051is_compact = True4052if len(self.ids_vehs_out[id_stop]) > 0:4053for id_veh, stoppos in self.ids_vehs_out[id_stop]:4054id_veh_sumo = vehicles.get_id_sumo(id_veh)4055pos = traci.vehicle.pos = traci.vehicle.getLanePosition(id_veh_sumo)40564057is_compact &= pos > pos_lastberth4058# print ' %s'%id_veh_sumo,'pos %.1f'%pos,is_compact4059if not is_compact:4060break4061else:4062for id_veh in self.ids_vehs_ready_for_departure[id_stop]:4063id_veh_sumo = vehicles.get_id_sumo(id_veh)4064pos = traci.vehicle.pos = traci.vehicle.getLanePosition(id_veh_sumo)40654066is_compact &= pos > pos_lastberth4067# print ' %s'%id_veh_sumo,'pos %.1f'%pos,is_compact4068if not is_compact:4069break40704071if self.debug:4072print ' is_compact', is_compact4073return is_compact40744075def try_start_vehicles(self, id_stop, simtime, n_plat_min=-1):4076"""4077Look into already routed vehicles and start vehicles4078while maximizing platooning.4079"""40804081print 'try_start_vehicles id_stop', id_stop, 'veh exiting', len(self.ids_vehs_berth_exit[id_stop]),\4082'wait from berth', len(self.ids_berths_veh_wait_exit[id_stop]), 'wait to pass', len(4083self.ids_vehs_pass_wait_exit[id_stop])40844085n_plat_max = self.capas_inqueue[id_stop] - \4086(len(self.ids_vehs_out[id_stop])+len(self.ids_vehs_ready_for_departure[id_stop]))4087if self.debug:4088print ' n_plat_max', n_plat_max4089if n_plat_max == 0:4090if self.debug:4091print ' insufficient sapce in output queue'4092return False40934094if len(self.ids_vehs_berth_exit[id_stop]) > 0:4095if self.debug:4096print ' there are still vehicles moving out of berth'4097return False40984099elif not self.is_outputqueue_compact(id_stop):4100if self.debug:4101print ' there are still vehicles in berth area toward exit queue'4102return False41034104if self.debug:4105print ' len(ids_veh_inqueue)', len(self.ids_vehs_inqueue[id_stop])4106if len(self.ids_vehs_inqueue[id_stop]) > 0:4107ids_veh_pass = self.get_ids_veh_to_pass(id_stop)4108if self.debug:4109print ' found ids_veh_pass', ids_veh_pass, 'not yet started!'4110else:4111ids_veh_pass = []41124113n_veh_pass = len(ids_veh_pass)4114n_veh_pass_wait = len(self.ids_vehs_pass_wait_exit[id_stop])4115if self.debug:4116print ' n_veh_pass', n_veh_pass, 'n_veh_pass_wait', n_veh_pass_wait41174118berths = self.get_berths()4119vehicles = self.parent.prtvehicles4120vehicleman = self.parent.vehicleman41214122# ids_veh_ready = self.ids_vehs_routed# no let's build this vector41234124#ids_veh_pass_wait_exit = self.get_ids_veh_pass_wait_exit(id_stop)41254126if n_veh_pass_wait > 0:4127if self.debug:4128print ' there are passthrough vehicle in the input queue waiting to get started', self.ids_vehs_pass_wait_exit[id_stop]4129print ' ids_veh_pass_wait_exit', self.ids_vehs_pass_wait_exit[id_stop]4130# these vehicles have a common target4131ids_veh_pass_wait_exit = self.ids_vehs_pass_wait_exit[id_stop]4132while len(ids_veh_pass_wait_exit) > 0:4133id_veh = ids_veh_pass_wait_exit.pop(0)4134vehicles.foreward_passthrough(id_veh)4135self.ids_vehs_berth_exit[id_stop].append(id_veh)4136# remove from input queue4137self.ids_vehs_inqueue[id_stop].remove(id_veh)41384139return True41404141elif len(self.ids_berths_veh_wait_exit[id_stop]) > 0:4142ids_berth_veh_wait_exit = self.ids_berths_veh_wait_exit[id_stop]4143if self.debug:4144print ' there are vehicles in berth which are listed to start.', ids_berth_veh_wait_exit4145# do start them, sorted by final destination41464147# print ' ids_berth_veh_wait_exit',ids_berth_veh_wait_exit4148ids_veh = berths.ids_veh[ids_berth_veh_wait_exit]4149# print ' ids_veh',ids_veh4150#ids_targetedge = vehicles.ids_stopedge_target[ids_veh]4151# print ' ids_targetedge',ids_targetedge4152#id_targetedge_start = vehicles.get_targetedge_current(ids_veh[0])4153ids_stop_target = vehicles.ids_stop_target[ids_veh]4154inds_start = ids_stop_target == ids_stop_target[0]4155if self.debug:4156print ' start waiting vehicles', ids_veh[inds_start], 'to final id_stop_target', ids_stop_target[0]4157self._kick_out_of_berth(id_stop, ids_veh[inds_start], np.array(4158ids_berth_veh_wait_exit, dtype=np.int32)[inds_start], vehicles, berths)4159for id_berth in np.array(ids_berth_veh_wait_exit, dtype=np.int32)[inds_start]:4160ids_berth_veh_wait_exit.remove(id_berth)4161return True41624163if ((simtime - self.times_phase_out[id_stop]) > self.time_fase_out_max.get_value()) & (n_veh_pass == 0):4164# stop starting if move in phase is timed out4165if self.debug:4166print ' fase move out timeout, stop starting'4167return False41684169# berth in reverse order means that the berth closest to the exit comes first4170ids_berth = np.array(self.ids_berths[id_stop][::-1], dtype=np.int32)41714172inds_berth_ready = np.flatnonzero(berths.states[ids_berth] == BERTHSTATES['waiting_routed'])4173ids_berth_ready = ids_berth[inds_berth_ready].copy()4174ids_veh_ready = berths.ids_veh[ids_berth[inds_berth_ready]]4175n_veh = len(ids_veh_ready)41764177# deal with vehicle in input queue creating a list of consecutive vehicles4178# with common destination41794180if n_veh_pass > 0:4181ids_veh_ready_all = np.concatenate((ids_veh_ready, ids_veh_pass))4182else:4183ids_veh_ready_all = ids_veh_ready41844185n_veh_all = n_veh+n_veh_pass41864187n_edge_max = 04188for i, id_veh, route in zip(xrange(n_veh_all), ids_veh_ready_all, vehicles.routes[ids_veh_ready_all]):4189#ids_edge_target[i] = route[-1]4190if len(route) > n_edge_max:4191n_edge_max = len(route)41924193ids_stop_target = vehicles.ids_stop_target[ids_veh_ready]41944195if n_veh_all > 0:41964197overtime = simtime - berths.times_routes[ids_berth_ready]-self.time_wait_berth_max.get_value()4198overtime_berth_ready = overtime * (overtime > 0)4199if self.debug:4200print ' vehicles ready to leave berth n_veh %d including input n_veh_all %d' % (n_veh, n_veh_all)4201print ' ids_stop_target from berths', ids_stop_target4202print ' ids_berth', berths.states[ids_berth]4203print ' berths.state', berths.states[ids_berth]4204print ' ids_berth_ready', ids_berth_ready4205print ' ids_veh_ready', ids_veh_ready4206print ' ids_veh_ready_all', ids_veh_ready_all42074208print ' simtime', simtime4209print ' overtime_berth_ready', overtime_berth_ready4210print ' berths.times_routes[ids_berth_ready]', berths.times_routes[ids_berth_ready]4211print ' time_wait_berth_max', self.time_wait_berth_max.get_value()42124213# if 0: # deal with this case in platoon optimizarion4214# print ' there are vehhicles in the input queue'4215# # check if there are passthrough vehicles in search4216# # for vehicles with same dest42174218if n_veh_pass > 0:4219if self.debug:4220print ' There is at least one passthrough vehicle which needs to get launched'4221#id_edge_target_max = vehicles.get_targetedge_current(ids_veh_pass[0])4222id_stop_target_max = vehicles.ids_stop_target[ids_veh_pass[0]]42234224# other vehicles with id_edge_target_max4225inds_veh_plat = ids_stop_target == id_stop_target_max4226ids_veh_plat = ids_veh_ready[inds_veh_plat]4227ids_berth_plat = ids_berth_ready[inds_veh_plat]4228if len(ids_veh_plat) > n_plat_max-n_veh_pass:4229if n_plat_max-n_veh_pass > 0:4230ids_veh_plat = ids_veh_plat[:n_plat_max-n_veh_pass]4231ids_berth_plat = ids_berth_plat[:n_plat_max-n_veh_pass]4232else:4233ids_veh_plat = np.array([])4234ids_berth_plat = np.array([])42354236if self.debug:4237print ' vehs with same dest as pass', ids_veh_plat42384239self._kick_out_of_berth(id_stop, ids_veh_plat, ids_berth_plat, vehicles, berths)42404241# add pass.through vehices to the waiting list4242# these vehicles will be started as soon as all berth vehicles4243# have been started and removed from the ids_vehs_berth_exit list4244self.ids_vehs_pass_wait_exit[id_stop] += ids_veh_pass42454246for id_veh in np.concatenate((ids_veh_plat, ids_veh_pass)):4247vehicleman.init_trip(id_veh, id_stop, id_stop_target_max, simtime)42484249elif (np.any(overtime_berth_ready) > 0) & (n_veh_pass == 0):4250if self.debug:4251print ' at some berth maximum wait time has been exceeded'42524253# TODO: launche all vehicles with overtime putting them into self.ids_berths_veh_wait_exit[id_stop]4254# take vehicle with maximum wait time and try to create a platoon42554256id_stop_target_max = ids_stop_target[np.argmax(overtime_berth_ready)]42574258# other vehicles with id_edge_target_max4259inds_veh_plat = ids_stop_target == id_stop_target_max4260ids_veh_plat = ids_veh_ready[inds_veh_plat]4261ids_berth_plat = ids_berth_ready[inds_veh_plat]4262if len(ids_veh_plat) > n_plat_max:4263ids_veh_plat = ids_veh_plat[:n_plat_max]4264ids_berth_plat = ids_berth_plat[:n_plat_max]42654266# here next stop is identical with final route4267# this may be different for platoons where only4268# a subroute is common.4269#vehicles.ids_stopedge_next[ids_veh_plat] = id_edge_target_max4270# print ' id_edge_target_max',id_edge_target_max,'n_veh_plat',len(ids_veh_plat)42714272# vehicles leave berth, programming later when platoon is completed4273# if destination of platoon are not4274self._kick_out_of_berth(id_stop, ids_veh_plat, ids_berth_plat, vehicles, berths)42754276# for id_veh, id_berth in zip(ids_veh_plat, ids_berth_plat):4277# print ' overtime: kick veh %d out of berth %d'%(id_veh, id_berth)4278# berths.set_free(id_berth)4279# vehicles.control_berth_position_exit( id_veh,\4280# id_edge_sumo = self.ids_stop_to_ids_edge_sumo[id_stop],\4281# position = berths.stoppositions[id_berth]+0.3,# needs to move sidewards4282# laneindex = 24283# )4284# # first vehicle in this queue is closest to exit4285# self.ids_vehs_berth_exit[id_stop].append(id_veh)4286# self.ids_vehs_routed[id_stop].discard(id_veh)42874288for id_veh in ids_veh_plat:4289vehicleman.init_trip(id_veh, id_stop, id_stop_target_max, simtime)42904291else: # if n_veh > n_plat_min:42924293print ' Maximize platoon length'42944295edgeutilities = self.get_scenario().net.edges.lengths4296# utilities = np.sum(edgeutilities[routes_common],1)*counts_common42974298# array with all routes4299# is one element longer than longest route because4300# -1 is required to detect stop4301ids_edges = -1*np.ones((n_veh_all, n_edge_max+1), dtype=np.int32)43024303for i, id_veh, route in zip(xrange(n_veh_all), ids_veh_ready_all, vehicles.routes[ids_veh_ready_all]):4304# print ' get route prt.%d'%id_veh,'i',i,'route',route4305ids_edges[i, :len(route)] = route43064307if self.debug > 9:4308print ' ids_edges=\n', ids_edges4309n_veh_all, n_edge_max = ids_edges.shape43104311is_cont = True # not used4312j = 343134314utility_max = 0.04315route_common_max = []4316counts_common_max = 043174318while is_cont & (j < n_edge_max):43194320id_edge_probe = ids_edges[0, j]43214322inds_stop = np.flatnonzero(ids_edges[:, j] == -1)4323if self.debug:4324print ' j=', j, 'inds_stop', inds_stop4325if len(inds_stop) > 0:4326if self.debug:4327print ' create set of routes that lead to one of the stops'4328occurencies = OrderedDict()43294330for ids_edge, ind_stop in zip(ids_edges[inds_stop, 0:j-2], inds_stop):4331# print ' ind_stop',ind_stop,'ids_edge',ids_edge4332occurencies[tuple(ids_edge)] = 043334334for ind, ids_edge in zip(xrange(n_veh_all), ids_edges[:, :]):4335ids_edge_tuple = tuple(ids_edge[0:j-2])4336# print ' check ids_edge',ids_edge4337# print ' common?',ids_edge_tuple4338# print ' stopinds',np.flatnonzero(ids_edge== -1),(ids_edge== -1)4339#j_stop = np.flatnonzero(ids_edge== -1)[0]4340#4341# here we want at least 50% gain in4342# terms of number of edges if the vehicle makes4343# an intermediate stop.4344# TODO: can be improved by counting the additional km4345if ids_edge_tuple in occurencies:4346if self._is_stop(j, ids_edge):4347occurencies[ids_edge_tuple] += 143484349# print ' occurencies',occurencies4350routes_common = np.array(occurencies.keys(), dtype=np.int32)4351counts_common = occurencies.values()4352utilities = np.sum(edgeutilities[routes_common], 1)*counts_common4353ind_max = np.argmax(utilities)43544355# print ' routes_common',routes_common4356# print ' counts_common',counts_common4357# print ' utilities',utilities4358# print ' route_common_max',route_common_max4359# print ' utilities[ind_max]',utilities[ind_max]4360if utilities[ind_max] > utility_max:4361route_common_max = routes_common[ind_max]4362# print ' new route_common_max',route_common_max43634364utility_max = utilities[ind_max]4365counts_common_max = counts_common[ind_max]43664367j += 143684369# print '-'*104370if self.debug:4371print ' utility_max', utility_max4372print ' route_common_max', route_common_max, type(route_common_max)43734374j_max = len(route_common_max)+243754376#ids_edges_out = ids_edges.copy()43774378inds_stop = np.flatnonzero(ids_edges[:, j_max] == -1)4379for ind, ids_edge in zip(inds_stop, ids_edges[inds_stop, 0:j_max-2]):4380# print ' ids_edge',ids_edge,np.array_equal(ids_edge, route_common_max)4381if np.array_equal(ids_edge, route_common_max):4382route_max = ids_edges[ind, :j_max]4383break43844385if self.debug:4386print ' route_max', route_max43874388inds_veh_plat_deviate = []4389inds_veh_plat_nodeviate = []4390inds_veh_plat = []4391for ind, ids_edge, is_stop in zip(xrange(n_veh_all), ids_edges[:, :], ids_edges[:, j_max] == -1):4392if np.array_equal(ids_edge[0:j_max-2], route_common_max):4393if self._is_stop(j_max, ids_edge):4394inds_veh_plat.append(ind)43954396if not is_stop:4397#ids_edges_out[ind, :] = route_max4398inds_veh_plat_deviate.append(ind)4399else:4400inds_veh_plat_nodeviate.append(ind)44014402# limit platoonlength4403if len(inds_veh_plat) > n_plat_max:4404if len(inds_veh_plat_nodeviate) > n_plat_max:4405inds_veh_plat_nodeviate = inds_veh_plat_nodeviate[:n_plat_max]4406inds_veh_plat_deviate = []4407else:4408inds_veh_plat_deviate = inds_veh_plat_deviate[:n_plat_max-len(inds_veh_plat_nodeviate)]44094410inds_veh_plat = np.array(inds_veh_plat, dtype=np.int32)4411inds_veh_plat_deviate = np.array(inds_veh_plat_deviate, dtype=np.int32)4412inds_veh_plat_nodeviate = np.array(inds_veh_plat_nodeviate, dtype=np.int32)4413iinds_plat_deviate_berth = inds_veh_plat_deviate < n_veh4414iinds_plat_nodeviate_berth = inds_veh_plat_nodeviate < n_veh4415iinds_plat_passthrough = inds_veh_plat >= n_veh4416# print ' ids_edges_out\n',ids_edges_out4417if self.debug:4418print ' inds_veh_plat\n', inds_veh_plat4419print ' inds_veh_plat_deviate\n', inds_veh_plat_deviate4420print ' inds_veh_plat_nodeviate\n', inds_veh_plat_nodeviate4421print ' inds_veh_plat_deviate_berth\n', inds_veh_plat_deviate[iinds_plat_deviate_berth]4422print ' inds_veh_plat_nodeviate_berth\n', inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]4423print ' iinds_plat_passthrough\n', iinds_plat_passthrough4424print ' inds_veh_plat_passthrough\n', inds_veh_plat[iinds_plat_passthrough]44254426n_veh_plat = len(inds_veh_plat)4427# print ' id_edge_target_max',id_edge_target_max,'n_veh_plat',n_veh_plat,n_veh_plat >= n_plat_min44284429if (n_veh_plat >= n_plat_min) | (np.max(inds_veh_plat) >= n_veh):4430if self.debug:4431print ' platoon formation long enough n_veh_plat', n_veh_plat, 'or passthrough', (np.max(inds_veh_plat) >= n_veh)44324433print ' deviate vehicles berth', ids_veh_ready_all[inds_veh_plat_deviate[iinds_plat_deviate_berth]]4434for id_veh in ids_veh_ready_all[inds_veh_plat_deviate[iinds_plat_deviate_berth]]:4435# note that all routed vehicles are already disengaged4436vehicles.set_route_target(id_veh, route_max, is_disengage_from_berth=False)4437if self.debug:4438print ' deviate vehicles passthrough', ids_veh_ready_all[inds_veh_plat_deviate[np.logical_not(iinds_plat_deviate_berth)]]4439for id_veh in ids_veh_ready_all[inds_veh_plat_deviate[np.logical_not(iinds_plat_deviate_berth)]]:4440vehicles.set_route_target(id_veh, route_max)4441# ?here next stop is identical with final route4442# ?this may be different for platoons where only4443# ?a subroute is common.4444# ?vehicles.ids_stopedge_next[ids_veh_plat] = id_edge_target_max44454446# start immediately vehicles with final destination from berths4447if self.debug:4448print ' kick out ids_veh', ids_veh_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]]4449print ' from berths ', ids_berth_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]]4450self._kick_out_of_berth(id_stop, ids_veh_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]],4451ids_berth_ready[inds_veh_plat_nodeviate[iinds_plat_nodeviate_berth]], vehicles, berths)44524453# add vehicles which require deviation to a waiting list4454# they will be started later while being sorted by final4455# destination4456if self.debug:4457print ' ids_berths_veh_wait_exit before', self.ids_berths_veh_wait_exit[id_stop]4458self.ids_berths_veh_wait_exit[id_stop] += ids_berth_ready[inds_veh_plat_deviate[iinds_plat_deviate_berth]].tolist()4459if self.debug:4460print ' ids_berths_veh_wait_exit after ', self.ids_berths_veh_wait_exit[id_stop]4461print ' ids_berth_ready', ids_berth_ready4462# ATTENTION: vehicles waiting in input queue cannot be sorted by destination...4463# but they are supposed to be sorted already?44644465self.ids_vehs_pass_wait_exit[id_stop] += ids_veh_ready_all[inds_veh_plat[iinds_plat_passthrough]].tolist()4466if self.debug:4467print ' ids_vehs_pass_wait_exit after ', self.ids_vehs_pass_wait_exit[id_stop]44684469# get the destination stop from final stop of the undevieted winner4470id_stop_target_max = vehicles.ids_stop_target[ids_veh_ready_all[inds_veh_plat_nodeviate[0]]]4471for id_veh in ids_veh_ready_all[inds_veh_plat]:4472vehicleman.init_trip(id_veh, id_stop, id_stop_target_max, simtime)4473return True44744475else:4476if self.debug:4477print ' platoon too short'4478return False44794480else:4481if self.debug:4482print ' no vehicles finished boarding'4483return False44844485def _is_stop(self, j, ids_edge):4486j_stop = np.flatnonzero(ids_edge == -1)[0]4487# TODO: measure gain in distance4488ans = (j == j_stop) | (j_stop > 1.1*j)4489# print ' _is_stop:',ans,'j',j, 'j_stop',j_stop,'===', (j_stop == j),'|', ( j_stop > 1.5*j)44904491return ans44924493def _kick_out_of_berth(self, id_stop, ids_veh_plat, ids_berth_plat, vehicles, berths):4494for id_veh, id_berth in zip(ids_veh_plat, ids_berth_plat):4495print ' kick veh %d out of berth %d and set berth free' % (id_veh, id_berth)4496berths.set_free(id_berth)4497vehicles.control_berth_position_exit(id_veh,4498id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],\4499# position = berths.stoppositions[id_berth]+0.3,# needs to move sidewards4500laneindex=24501)4502# first vehicle in this queue is closest to exit??4503self.ids_vehs_berth_exit[id_stop].append(id_veh)4504self.ids_vehs_routed[id_stop].discard(id_veh)45054506# print ' ids_vehs_berth_exit',self.ids_vehs_berth_exit[id_stop]4507# print ' freed berth %d state %d'%(id_berth,berths.states[id_berth])45084509def get_berths_with_state(self, id_stop, state):45104511ids_berth = np.array(self.ids_berths[id_stop], dtype=np.int32)4512#inds = np.flatnonzero(self.get_berths().states[ids_berth] == state)4513# if len(inds)>0:4514# return ids_berth[inds]4515# else:4516# return []4517return ids_berth[self.get_berths().states[ids_berth] == state]45184519def enter(self, id_stop, ids_veh, fase, simtime):4520print 'enter ids_veh', ids_veh45214522vehicles = self.parent.prtvehicles45234524# print ' ids_vehs',self.ids_vehs[id_stop],type(self.ids_vehs[id_stop])4525#ids_veh_current = self.ids_vehs[id_stop]4526# print ' ids_veh_current',ids_veh_current,'ids_veh',ids_veh,type(ids_veh)4527#ids_veh_current += ids_veh4528# print ' ids_veh_current',ids_veh_current4529self.ids_vehs[id_stop] += ids_veh.tolist()4530# self.ids_vehs[id_stop].append(id_veh)4531# print ' ids_vehs',self.ids_vehs[id_stop],type(self.ids_vehs[id_stop])4532id_stopedge = self.ids_stop_to_ids_edge[id_stop]4533n_veh = len(ids_veh)45344535self.numbers_veh[id_stop] += n_veh4536are_completed = np.zeros(n_veh, dtype=np.bool)4537for id_veh, i in zip(ids_veh, xrange(n_veh)):45384539vehicles.decatenate(id_veh)4540# here we should check whether the vehicle needs to alight4541# or wether it is a pass through4542route = vehicles.routes[id_veh]4543if self.debug:4544print ' enter prt.%d' % id_veh, 'with id_stop_target', vehicles.ids_stop_target[id_veh], 'route', route4545if len(route) == 0:4546# vehicle just initialized4547are_completed[i] = True4548else:4549if vehicles.ids_stop_target[id_veh] == id_stop:4550# vehicle reached destination stop4551are_completed[i] = True45524553# tell vehman that veh arrived4554self.parent.vehicleman.conclude_trip(id_veh, id_stop, is_final_dest=True)45554556# tell veicle that trip is completed4557# TODO: could be performed by vehman4558vehicles.set_route_completed(id_veh)45594560else:4561# stop is not final desination4562are_completed[i] = False4563# tell vehman that veh arrived, but trip not concluded4564self.parent.vehicleman.conclude_trip(id_veh, id_stop, is_final_dest=False)45654566if np.all(are_completed):4567ids_veh_completed = ids_veh.copy()45684569else:4570ind_first_passthrough = np.flatnonzero(np.logical_not(are_completed))[0]4571ids_veh_completed = ids_veh[:ind_first_passthrough]45724573n_veh_completed = len(ids_veh_completed)4574ids_berth = -1*np.ones(n_veh, dtype=np.int32)4575if self.debug:4576print ' n_veh_completed', n_veh_completed, 'no Timeout', ((simtime - self.times_phase_in[id_stop]) < self.time_fase_in_max.get_value()), 'veh input', self.ids_vehs_inqueue[id_stop]4577# if fase == FASE_MOVE_IN:4578# print ' timeout fase 0: dt=%.2f timeout=%.2f'%((simtime - self.times_phase_in[id_stop]), self.time_fase_in_max.get_value())4579if n_veh_completed > 0:4580# (simtime - self.times_phase_in[id_stop]), self.time_fase_in_max.get_value())4581if self.debug:4582# ,(len(self.ids_vehs_inqueue[id_stop]) == 0),((simtime - self.times_phase_in[id_stop]) > self.time_fase_in_max.get_value())4583print ' fase', fase4584if (fase == FASE_MOVE_IN) & (len(self.ids_vehs_inqueue[id_stop]) == 0)\4585& ((simtime - self.times_phase_in[id_stop]) < self.time_fase_in_max.get_value()):4586# here vehicles are sent to berth, if available4587# bit only in move in fase, there are no other vehicles4588# to allocate in the ids_vehs_to_allocate queue4589# and if move in fase time out has not been reached45904591# allocate berth only for vehicles which completed trip at this stop4592ids_berth_completed = self.allocate_alight(id_stop, n_veh_completed)4593if self.debug:4594print ' ids_berth_completed', ids_berth_completed4595ids_berth[are_completed] = ids_berth_completed45964597is_stop_moving_in = False4598for id_veh, state, id_berth, is_completed in zip(ids_veh, vehicles.states[ids_veh], ids_berth, are_completed):4599if self.debug:4600print ' check id_veh', id_veh, 'id_berth', id_berth, 'is_completed', is_completed, 'state', state46014602if not is_completed:4603# will be send directly to output queue4604if self.debug:4605print ' passthrough, not final destination of vehicle.'46064607is_stop_moving_in = True4608if self.debug:4609print ' stop before first berths, wait for try_start at %.1fm' % (self.stoplines_in[id_stop])46104611# this vehicle does not get allocated to a berth4612# but will wait until vehicles with same destination move out4613# if len(self.ids_vehs_inqueue[id_stop])>0:4614# id_veh_infront = self.ids_vehs_inqueue[id_stop][-1]4615# else:4616# id_veh_infront = -146174618self.ids_vehs_inqueue[id_stop].append(id_veh)4619vehicles.init_passthrough(id_veh,4620self.ids_stop_to_ids_edge_sumo[id_stop],4621self.stoplines_in[id_stop],4622laneindex=2,4623#id_veh_infront = id_veh_infront,4624)4625# vehicle needs also to be rerouted to its target4626# TODO: this is a little bit crazy, routing could be done in vehicles46274628route, duration = self.parent.get_route(4629id_stopedge, self.ids_stop_to_ids_edge[vehicles.ids_stop_target[id_veh]])4630vehicles.set_route_target(id_veh, route)4631#stopline = self._get_stopline(id_stop, simtime)4632# print ' simtime', simtime46334634#berths.set_waiting_routed(id_berth, simtime)4635#berths.ids_veh[id_berth] = -14636# todo: is this necessary? no further use...4637self.ids_vehs_routed[id_stop].add(id_veh)46384639elif id_berth == -1:4640if self.debug:4641print ' trip is completed but no berth => stop vehicles from moving in'4642is_stop_moving_in = True4643if self.debug:4644print ' stop before first berths and wait for allocation at %.1fm' % (self.stoplines_in[id_stop])4645self.ids_vehs_inqueue[id_stop].append(id_veh)4646vehicles.control_stopline_enter(id_veh,4647self.ids_stop_to_ids_edge_sumo[id_stop],4648self.stoplines_in[id_stop],4649laneindex=2)46504651elif (not is_stop_moving_in) & (id_berth != -1):4652if self.debug:4653print ' forewrard entering vehicle id_veh %d to id_berth_alight %d at pos %.2fm' % (id_veh, id_berth, self.get_berths().stoppositions[id_berth])4654self.ids_vehs_alight_forward[id_stop].append(id_veh)4655vehicles.control_berth_position_enter(4656id_veh, id_berth,4657id_edge_sumo=self.ids_stop_to_ids_edge_sumo[id_stop],4658position=self.get_berths().stoppositions[id_berth]-0.3, # needs to stop a bit before to move in4659laneindex=2,4660)4661if self.debug:4662print ' ids_vehs_inqueue (after)', self.ids_vehs_inqueue[id_stop]46634664def get_ids_veh_to_allocate(self, id_stop):4665"""Returns vehicle in input queue that needs berth allocation.4666But only vehicles in front of passthrough vehicles are considered.4667"""4668# print 'get_ids_veh_to_allocate id_stop',id_stop4669ids_veh = np.array(self.ids_vehs_inqueue[id_stop], dtype=np.int32)4670if len(ids_veh) > 0:4671are_forewarding = (self.parent.prtvehicles.states[ids_veh] == VEHICLESTATES['forewarding'])4672# print ' ids_veh in queue',ids_veh4673# print ' are_forewarding',are_forewarding4674if np.all(are_forewarding):4675return ids_veh.tolist()4676else:4677# print ' inds',np.flatnonzero(np.logical_not(are_forewarding))4678return ids_veh[0:np.flatnonzero(np.logical_not(are_forewarding))[0]].tolist()4679else:4680return []46814682def get_ids_veh_to_pass(self, id_stop):4683"""Retuns a list of vehicle IDs which are in pass through vehicles4684at the pole position of the input queue. All vehicles have the same destinaton.4685"""4686ids_veh_inqueue = np.array(self.ids_vehs_inqueue[id_stop], dtype=np.int32)4687# print 'get_ids_veh_to_pass id_stop',id_stop,len(ids_veh_inqueue),ids_veh_inqueue4688if len(ids_veh_inqueue) > 0:4689are_pass = self.parent.prtvehicles.states[ids_veh_inqueue] == VEHICLESTATES['forewarding_passthrough']4690# print ' are_pass[0]',are_pass[0],are_pass4691if are_pass[0]:4692# print ' ids_veh_inqueue',ids_veh_inqueue4693# print ' are_pass',are_pass4694# there is a pass through vehicle in pole position4695ids_stop_target = self.parent.prtvehicles.ids_stop_target[ids_veh_inqueue]4696# print ' ids_stopedge_target',ids_stopedge_target4697# algorithm to identify a cosecutive sequence of4698# passthrough vehicles4699are_firststop = ids_stop_target == ids_stop_target[0]4700# print ' are_firststop',are_firststop4701if np.all(are_firststop):4702ind_firststop = len(are_firststop)-14703else:4704ind_firststop = np.flatnonzero(np.logical_xor(are_firststop[:-1], are_firststop[1:]))[0]47054706if np.all(are_pass):4707ind_pass = len(are_pass)-14708else:4709ind_pass = np.flatnonzero(np.logical_xor(are_pass[:-1], are_pass[1:]))[0]47104711ind = min(ind_firststop, ind_pass)+14712# print ' ind_firststop',ind_firststop,'ind_pass',ind_pass,'ind',ind4713return ids_veh_inqueue[:ind].tolist()47144715else:4716# first veh is not passthrough4717return []47184719else:4720return []47214722def exit(self, id_stop, id_veh, fase):4723print 'exit prt.%d at stop %d fase %d' % (id_veh, id_stop, fase)4724self.ids_vehs[id_stop].remove(id_veh)4725self.ids_vehs_ready_for_departure[id_stop].remove(id_veh)4726#id_stop_target = self.parent.vehicleman.start_trip(id_veh, id_stop)4727#self.parent.prtvehicles.reschedule_trip(id_veh, self.ids_stop_to_ids_edge_sumo[id_stop_target])4728#ind_veh = -14729# print ' ids_vehs_prog=\n',self.ids_vehs_prog[id_stop]4730# i=04731# for time_start, id_veh_prog, id_stop_target, is_prog in self.ids_vehs_prog[id_stop]:4732# if id_veh_prog == id_veh:4733# self.ids_vehs_prog[id_stop].pop(i)4734# break4735# i =+147364737# self.ids_vehs_prog[id_stop].remove(id_veh)47384739self.numbers_veh[id_stop] -= 147404741def allocate_alight(self, id_stop, n_alloc):4742"""4743Return a vector of n_alloc berth IDs to be allocated for alighting/boarding4744at given stop ID.4745-1 means no berth could be allocated4746"""47474748# here we want that vehicles allocate berth with person queues4749# but we also want to allocate all vehicles if this is possible47504751# current berth allocation index running from4752# n_berth_to_allocate-1 to 04753ind_berth_to_allocate = self.inds_berth_allocated[id_stop]47544755# get berth available for allocation4756ids_berth_to_allocate = self.ids_berths_to_allocate[id_stop][:ind_berth_to_allocate]4757# ids_berth_to_allocate.reverse()# index 0 is first to be allocated47584759# number of berth available for allocation4760n_berth_to_allocate = len(ids_berth_to_allocate)47614762# allocated berth vector4763# default berth ID is -1 means no merth available4764ids_berth_alloc = -1*np.ones(n_alloc, dtype=np.int32)47654766print 'allocate_alight n_alloc', n_alloc, 'n_berth_to_allocate', n_berth_to_allocate, 'ind_berth_to_allocate', ind_berth_to_allocate4767if self.debug:4768print ' ids_berth_to_allocate', ids_berth_to_allocate47694770if ind_berth_to_allocate == -1:4771if self.debug:4772print ' no free berth :('4773return ids_berth_alloc47744775elif n_berth_to_allocate <= n_alloc:4776if self.debug:4777print ' there is a less or equal number of free berth than requested'4778# => use all berth available for allocatation4779ids_berth_alloc[0:n_berth_to_allocate] = ids_berth_to_allocate[0:n_berth_to_allocate]4780self.inds_berth_allocated[id_stop] = -147814782else:4783if self.debug:4784print ' there are more berths available than vehicles to allocate'4785# -> prefer berth with person queues4786queues = self.get_berthqueues(id_stop, ids_berth_to_allocate)4787#inds_nonzeroqueues = np.flatnonzero(ids_berth_to_allocate[::-1])47884789ind_alloc_eff = -1 # effective allocation index for result vector4790for i, queue, id_berth in zip(xrange(n_berth_to_allocate), queues[::-1], ids_berth_to_allocate[::-1]):4791print ' index i', i, 'id_berth', id_berth, 'queue', queue4792self.inds_berth_allocated[id_stop] -= 14793if queue == 0:4794if self.debug:4795print ' no passengers waiting'47964797# allocate this berth only if the number of the remaining4798# available berth is less or equal the number of berth4799# that remain to be allocated4800is_allzero = not np.any(queues[::-1][i:])4801if self.debug:4802print ' remaining berth to alloc', ids_berth_to_allocate[::-1][i:]4803print ' remaining queus to alloc', queues[::-1][i:]4804print ' rem avail', n_berth_to_allocate-(i+1), 'rem to alloc', n_alloc-(ind_alloc_eff + 1), 'is_allzero', is_allzero4805if is_allzero | ((n_berth_to_allocate-(i+1)) < (n_alloc-(ind_alloc_eff + 1))):4806ind_alloc_eff += 14807ids_berth_alloc[ind_alloc_eff] = id_berth4808if self.debug:4809print ' allocate id_berth', id_berth, 'at index', i4810else:4811if self.debug:4812print ' passengers waiting, allocate'4813ind_alloc_eff += 14814ids_berth_alloc[ind_alloc_eff] = id_berth48154816if self.debug:4817print ' allocate id_berth', id_berth, 'at index', i48184819if n_alloc == ind_alloc_eff + 1:4820if self.debug:4821print ' all vehicles allocated. Stop allocating.'4822break48234824if self.debug:4825print ' finished allocating i', i, 'ind_berth_to_allocate', ind_berth_to_allocate, 'rem', n_berth_to_allocate-(i+1)48264827# print ' inds_berth_allocated',self.inds_berth_allocated [id_stop],n_berth_to_allocate-(i+1)4828#self.inds_berth_allocated [id_stop] = n_berth_to_allocate-(i+1)4829if self.debug:4830print ' ids_berth_alloc', ids_berth_alloc4831# set allocated to found berth only4832self.get_berths().set_allocate(ids_berth_alloc[ids_berth_alloc > -1])48334834return ids_berth_alloc48354836def is_queue(self, id_stop, id_berth):4837"""4838Returns True if there is at least 1 person detected at id_berth at id_stop4839"""4840# print 'get_berthqueues',id_stop4841# TODO: use stop angle and person angle to detect waiting persons4842# problem: persons just passing by are detected as queue4843stopposition = self.get_berths().stoppositions[id_berth]4844# print ' stopposition',stopposition4845is_queue = False4846for id_person_sumo in self.waittimes_persons[id_stop].keys():4847is_queue = np.abs(stopposition-traci.person.getLanePosition(id_person_sumo)) < 0.84848if is_queue:4849break48504851return is_queue48524853def get_berthqueues(self, id_stop, ids_berth):4854print 'get_berthqueues ids_berth', ids_berth4855# currently not used4856# print 'get_berthqueues',id_stop4857# TODO: use stop angle and person angle to detect waiting persons4858stoppositions = self.get_berths().stoppositions[ids_berth]4859queues = np.zeros(len(ids_berth), dtype=np.int32)4860# print ' stoppositions',stoppositions4861for id_person_sumo in self.waittimes_persons[id_stop].keys():4862stage = traci.person.getStage(id_person_sumo, 0)4863if self.debug:4864print ' check id_person_sumo', id_person_sumo, 'Stagetype', stage.type, 'pos', traci.person.getLanePosition(id_person_sumo)4865# check if person is in wait pos! Actually this is stage type driving = 34866if stage.type == 3:4867position = traci.person.getLanePosition(id_person_sumo)4868# print ' position',position4869dists = np.abs(stoppositions-position)4870# print ' dists',dists,np.any(dists<5)4871if np.any(dists < 0.8):4872ind_berth = np.argmin(dists)4873queues[ind_berth] += 148744875# print ' queues=\n',queues4876return queues48774878def make_from_net(self):4879"""4880Make prt stop database from PT stops in network.4881"""4882print 'make_from_net'4883self.clear()4884net = self.get_scenario().net4885ptstops = net.ptstops48864887ids_ptstop = ptstops.get_ids()48884889id_mode_prt = self.parent.id_prtmode4890id_mode_ped = net.modes.get_id_mode('pedestrian')48914892ids_modes_allow = net.lanes.ids_modes_allow4893#get_accesslevel = net.lanes.get_accesslevel48944895ids_stoplane = ptstops.ids_lane[ids_ptstop]4896ids_stopedges = net.lanes.ids_edge[ids_stoplane]4897ids_stoplanes = net.edges.ids_lanes[ids_stopedges]4898edgelengths = net.edges.lengths[ids_stopedges]48994900for id_stop, ids_lane, id_lane, position_from, position_to, edgelength in zip(4901ids_ptstop,4902ids_stoplanes,4903ids_stoplane,4904ptstops.positions_from[ids_ptstop],4905ptstops.positions_to[ids_ptstop],4906edgelengths4907):4908print ' check', id_stop, 'number of lanes', len(ids_lane), ids_lane49094910ids_mode_allow = ids_modes_allow[ids_lane]4911if len(ids_lane) == 3:4912# check access of all lanes:4913# lane 0: at least ped access4914# lane 1: exclusive PRT access4915# lane 2: exclusive PRT access4916# print ' ids_modes_allow:',ids_mode_allow[0],ids_mode_allow[1],ids_mode_allow[2]49174918if (len(ids_mode_allow[1]) == 1) & (len(ids_mode_allow[2]) == 1):4919# print ' ids_mode_allow[1][0],ids_mode_allow[2][0]',ids_mode_allow[1][0],ids_mode_allow[2][0],id_mode_prt4920# print ' ',id_mode_ped in ids_mode_allow[0],id_mode_prt == ids_mode_allow[1][0],(id_mode_prt == ids_mode_allow[2][0])49214922if (id_mode_ped in ids_mode_allow[0]) & (id_mode_prt == ids_mode_allow[1][0]) & (id_mode_prt == ids_mode_allow[2][0]):4923self.make(id_stop,4924position_from,4925position_to)49264927self.parent.make_fstar(is_update=True)4928self.parent.make_times_stop_to_stop()49294930def make(self, id_ptstop, position_from, position_to):4931"""4932Initialize a new prt stop and generate berth.4933"""4934id_stop = self.add_row(ids_ptstop=id_ptstop)4935ids_berth = self.get_berths().make(id_stop, position_from=position_from,4936position_to=position_to)4937self.ids_berths[id_stop] = list(ids_berth) # IDs must be in a list4938return id_stop493949404941class VehicleAdder(Process):4942def __init__(self, vehicles, logger=None, **kwargs):4943print 'VehicleAdder.__init__', vehicles, vehicles.parent.get_ident()4944self._init_common('vehicleadder', name='Vehicle adder',4945logger=logger,4946info='Add vehicles to PRT stops of network.',4947)4948self._vehicles = vehicles49494950attrsman = self.set_attrsman(cm.Attrsman(self))49514952self.n_vehicles = attrsman.add(cm.AttrConf('n_vehicles', kwargs.get('n_vehicles', -1),4953groupnames=['options'],4954perm='rw',4955name='Number of vehicles',4956info='Number of PRT vehicles to be added to the network. Use -1 to fill all present PRT stations.',4957))49584959def do(self):4960# print 'VehicleAdder.do'4961self._vehicles.add_to_net(n=self.n_vehicles)4962return True496349644965class PrtVehicles(am.ArrayObjman):49664967def __init__(self, ident, prtservices, **kwargs):4968# print 'PrtVehicles vtype id_default',vtypes.ids_sumo.get_id_from_index('passenger1')4969self._init_objman(ident=ident,4970parent=prtservices,4971name='PRT Veh.',4972info='PRT vehicle database. These are shared vehicles.',4973version=0.2,4974**kwargs)49754976self._init_attributes()49774978def _init_attributes(self):4979vtypes = self.get_scenario().demand.vtypes4980net = self.get_scenario().net49814982self.add(cm.AttrConf('time_update', 0.5,4983groupnames=['parameters'],4984name='Update time',4985info="Update time for traci controlled vehicles, es. at merge points.",4986unit='s',4987))49884989self.add(cm.AttrConf('speed_max', 10.0,4990groupnames=['parameters'],4991name='Maximum speed',4992info="Maximum achievable speed.",4993unit='m/s',4994))49954996self.add(cm.AttrConf('time_emergency', 0.5,4997groupnames=['parameters'],4998name='Emergency reaction time',4999info="Time to react to emergency situations.",5000unit='s',5001))50025003self.add(cm.AttrConf('decel_comfort', 2.5,5004groupnames=['parameters'],5005name='Comfort deceleration',5006info="Comfort deceleration.",5007unit='m/s^2',5008))50095010self.add(cm.AttrConf('decel_emergency', 5.0,5011groupnames=['parameters'],5012name='Emergency deceleration',5013info="Emergency deceleration.",5014unit='m/s^2',5015))50165017self.add(cm.AttrConf('n_ghosts_max', 4,5018groupnames=['parameters'],5019name='Max ghosts',5020info="Maximum number of ghost vehicles. Ghost vehicles are used in merge controls.",5021))50225023# TODO: add/update vtypes here5024self.add_col(SumoIdsConf('Veh', xmltag='id'))50255026id_vtype = self.make_vtype()50275028if not hasattr(self, 'ids_vtype'):50295030self.add_col(am.IdsArrayConf('ids_vtype', vtypes,5031id_default=id_vtype,5032groupnames=['parameters'],5033name='Veh. type',5034info='PRT vehicle type.',5035#xmltag = 'type',5036))5037else:5038# this imposes parameters to alresdy existing data5039self.ids_vtype[self.get_ids()] = id_vtype50405041if self.get_version() < 0.2:50425043self.ids_vtype._default = id_vtype50445045self.add_col(am.ArrayConf('states', default=VEHICLESTATES['init'],5046dtype=np.int32,5047groupnames=['state'],5048choices=VEHICLESTATES,5049name='state',5050info='State of vehicle.',5051))50525053# self.add_col(am.IdsArrayConf( 'ids_targetprtstop', self.parent.prtstops,5054# groupnames = ['parameters'],5055# name = 'Target stop ID',5056# info = 'ID of current target PRT stop.',5057# ))50585059self.add_col(am.IdsArrayConf('ids_currentedge', net.edges,5060groupnames=['state'],5061name='Current edge ID',5062info='Edge ID of most recent reported position.',5063))50645065# self.add_col(am.IdsArrayConf( 'ids_targetedge', net.edges,5066# groupnames = ['state'],5067# name = 'Target edge ID',5068# info = 'Target edge ID to be reached. This can be either intermediate target edges (), such as a compressor station.',5069# ))50705071self.set_version(0.2)50725073def _init_constants(self):50745075self.do_not_save_attrs([5076'length',5077'tau', 'ids_berth',5078'are_update', 'velocities',5079'odos', 'ids_ghosts',5080'diststomerge0', 'diststomerge0_ghosts',5081'dists0', 'odos0_vehicles', 'odos0_ghosts',5082'ids_leader', 'ids_follower', 'lengths_plat',5083'ids_persons_sumo',5084])50855086def get_net(self):5087return self.parent.get_scenario().net50885089def make_vtype(self, is_reset_vtype=False):50905091vtypes = self.get_scenario().demand.vtypes5092prttype = 'HCPRT'5093print 'make_vtype HPRT', prttype5094# speedmode5095# https://sumo.dlr.de/docs/TraCI/Change_Vehicle_State.html5096# bit0: Regard safe speed5097# bit1: Regard maximum acceleration5098# bit2: Regard maximum deceleration -5099# bit3: Regard right of way at intersections5100# bit4: Brake hard to avoid passing a red light51015102#self._speedmode_leader = 75103#self._speedmode_follower = 651045105self._speedmode_leader = 75106self._speedmode_follower = 151075108self._factor_speed_leader = 0.95109self._factor_speed_follower = 2.051105111self._accel_leader = 2.55112self._accel_follower = 5.051135114self._decel_leader = self.decel_comfort.get_value()5115self._decel_follower = self.decel_comfort.get_value()51165117self._decel_emergency_leader = self.decel_emergency.get_value()5118self._decel_emergency_follower = self.decel_emergency.get_value()51195120self._dist_min_leader = 0.35121self._dist_min_follower = 0.051225123self._tau_leader = self.time_emergency.get_value()5124self._tau_follower = 0.051255126# this is not very nice deleting the present type5127# but it is done to fully control parameters from here5128if vtypes.ids_sumo.has_index(prttype):5129id_vtype = vtypes.ids_sumo.get_id_from_index(prttype)5130vtypes.del_row(id_vtype)5131print ' deleted', prttype, 'id_vtype', id_vtype51325133if (not vtypes.ids_sumo.has_index(prttype)) | is_reset_vtype:5134print ' set default PRT values decel', self._decel_leader, 'decel_emergency', self._decel_emergency_leader5135id_vtype = vtypes.add_vtype(prttype,5136accel=self._accel_leader,5137decel=self._decel_leader,5138decel_apparent=self._decel_leader, # followe should not be freightened5139decel_emergency=self._decel_emergency_leader,5140sigma=0.0,5141length=3.5,5142width=1.6,5143height=1.7,5144number_persons=1,5145capacity_persons=1,5146dist_min=self._dist_min_leader,5147tau=self._tau_leader,5148speed_max=self.speed_max.get_value(),5149factor_speed=self._factor_speed_leader,5150deviation_speed=0.1, # slight deviation for better following5151id_mode=self.parent.id_prtmode, # specifies mode for demand5152color=np.array((255, 240, 0, 255), np.float32)/255.0,5153shape_gui='evehicle',5154times_boarding=1.5,5155times_loading=20.0,5156#lanechange = 0.0,5157lanechange_strategy=0.0,5158lanechange_coop=1.0,5159lanechange_gain=0.0,5160lanechange_rightkeeping=-1.0,5161sublane_alignment_lat='right',5162sublane_speed_max_lat=0.5,5163sublane_gap_min_lat=0.0,5164sublane_alignment_eager=0.0,5165sublane_pushyfactor=0.0,5166sublane_impatience=0.0,5167sublane_time_to_impatience=99999999,5168#5169power_max=50.0,5170mass=800.0,5171coefficient_drag_air=0.4,5172moment_inertia_internal=0.01,5173coefficient_drag_radial=0.5,5174coefficient_drag_roll=0.005,5175efficiency_propulsion=0.9,5176#5177eprofile='hcprt',5178capacity_battery=2000.0,5179efficiency_reuperation=0.4,5180speed_charging=0.03,5181)5182else:5183print ' PRT type existing'5184id_vtype = vtypes.ids_sumo.get_id_from_index(prttype)5185return id_vtype51865187def get_length(self):5188vtypes = self.ids_vtype.get_linktab()51895190# here take parameters from first vtype and assume that all are the same5191id_vtype = self.ids_vtype[self.get_ids()[0]]51925193return vtypes.lengths[id_vtype]51945195def prepare_sim(self, process):5196print 'PrtVehicles.prepare_sim'5197if len(self) == 0:5198return []51995200self.id_follower_probe = -152015202ids = self.get_ids()5203net = self.get_scenario().net5204#nodes = net.nodes5205#edges = net.edges5206#lanes = net.lanes5207#ids_edge_sumo = edges.ids_sumo52085209id_prtmode = self.parent.id_prtmode52105211vtypes = self.ids_vtype.get_linktab()52125213# TODO: transfer vehicle parameters to vtype...but do not generate a new id_type5214# THIS IS A BIG MESS, WHY ARE PAPAMETERS TAKEN BACK FROM VTYPES?5215# self.make_vtype()52165217# here take parameters from first vtype and assume that all are the same5218id_vtype = self.ids_vtype[ids[0]]52195220self.length = vtypes.lengths[id_vtype]5221#self.speed_max = vtypes.speeds_max[id_vtype]5222self.dist_min = vtypes.dists_min[id_vtype]5223self.accel = vtypes.accels[id_vtype]5224self.decel = vtypes.decels[id_vtype]5225self.tau = vtypes.taus[id_vtype]5226self.dist_min = vtypes.dists_min[id_vtype]5227self.factor_speed = vtypes.factors_speed[id_vtype]52285229#ptstops = net.ptstops5230lanes = net.lanes5231#ids_edge_sumo = net.edges.ids_sumo52325233n_id_max = np.max(ids)+152345235# current route5236self.routes = np.zeros(n_id_max, dtype=np.object)5237for id_veh in ids:5238self.routes[id_veh] = []52395240#self.ids_stopedge_target = -1*np.ones(n_id_max, dtype = np.int32)5241self.ids_stop_target = -1*np.ones(n_id_max, dtype=np.int32)52425243# persons5244self.ids_persons_sumo = np.zeros(n_id_max, dtype=np.object)5245for id_veh in ids:5246self.ids_persons_sumo[id_veh] = set()52475248# vehicle control parameters5249n_ghosts_max = self.n_ghosts_max.get_value()52505251self.ids_berth = -1*np.ones(n_id_max, dtype=np.int32)52525253self.are_update = np.zeros(n_id_max, dtype=np.bool)5254self.velocities = np.zeros(n_id_max, dtype=np.float32)5255self.odos = np.zeros(n_id_max, dtype=np.float32)52565257self.ids_ghosts = -1*np.ones((n_id_max, n_ghosts_max), dtype=np.int32)52585259self.diststomerge0 = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)5260self.diststomerge0_ghosts = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)5261self.dists0 = np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)52625263self.odos0_vehicles = -1 * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)5264self.odos0_ghosts = -np.inf * np.ones((n_id_max, n_ghosts_max), dtype=np.float32)52655266# platooning5267# id of leader of this vehicle (vehicle in front), -1 = platoonleader5268self.ids_leader = -1 * np.ones(n_id_max, dtype=np.int32)52695270# id of follower of this vehicle (vehicle behind), -1 = last veh5271self.ids_follower = -1 * np.ones(n_id_max, dtype=np.int32)52725273# total length of platoon5274self.lengths_plat = np.zeros(n_id_max, dtype=np.float32)52755276return [(self.time_update.get_value(), self.process_step), ]52775278def add_ghost(self, id_veh, id_ghost, dist_to_merge_veh, dist_to_merge_ghost,5279is_substitute=False):5280ids_ghosts = list(self.ids_ghosts[id_veh])5281# if id_ghost in ids_ghosts:5282# # reconfigure existing5283# ind_ghost = self.ids_ghosts[id_veh].index(id_ghost)5284# id_ghost_old = self.ids_ghosts[id_veh][ind_ghost]5285# # try to delete old ghost5286# self.del_ghost(id_veh, id_ghost_old)5287# else:5288# add new ghost5289# ,self.ids_ghosts.shape5290print 'add_ghost veh prt.%d ghost prt.%d dtm = %.1f dtmg = %.1f d0=%.1f' % (id_veh, id_ghost, dist_to_merge_veh, dist_to_merge_ghost, dist_to_merge_veh - dist_to_merge_ghost)52915292if -1 not in ids_ghosts:5293print 'ERROR: no more ghosts available, ids_ghosts', ids_ghosts5294# sys.exit(1)5295print ' overwrite last ghost'5296# here we could sunstitute the ghost with the longest distance5297ind_ghost = len(ids_ghosts)-15298else:5299ind_ghost = ids_ghosts.index(-1)53005301if is_substitute:5302id_ghost_prev = ids_ghosts[ind_ghost]5303if id_ghost_prev > -1:5304self.stop_update(id_ghost_prev)5305if ind_ghost > 0:5306ind_ghost -= 153075308if ind_ghost > 0:5309print 'WARNING: unusual number of ghosts, ids_ghosts', ids_ghosts5310# sys.exit(1)53115312self.ids_ghosts[id_veh][ind_ghost] = id_ghost5313self.diststomerge0[id_veh][ind_ghost] = dist_to_merge_veh5314self.diststomerge0_ghosts[id_veh][ind_ghost] = dist_to_merge_ghost53155316# nose to nose distances5317self.dists0[id_veh][ind_ghost] = dist_to_merge_veh - dist_to_merge_ghost53185319# get absolute running distances5320self.odos0_vehicles[id_veh][ind_ghost] = get_traci_odo(self.get_id_sumo(id_veh))5321self.odos0_ghosts[id_veh][ind_ghost] = get_traci_odo(self.get_id_sumo(id_ghost))53225323# both ghosts and vehicles need update5324self.start_update(id_veh)5325self.start_update(id_ghost)53265327def del_ghosts(self, id_veh):5328if self.ids_ghosts[id_veh][0] == -1:5329# id_veh has no ghosts5330return5331else:5332for id_ghost in self.ids_ghosts[id_veh]:5333if id_ghost > -1:5334self.del_ghost(id_veh, id_ghost)53355336def del_ghost(self, id_veh, id_ghost):5337print 'del_ghost id_veh %d id_ghost %d' % (id_veh, id_ghost)5338if id_ghost in self.ids_ghosts[id_veh]:53395340ind_ghost = list(self.ids_ghosts[id_veh]).index(id_ghost)5341self.ids_ghosts[id_veh][ind_ghost] = -153425343self.diststomerge0[id_veh][ind_ghost] = np.inf5344self.diststomerge0_ghosts[id_veh][ind_ghost] = np.inf5345self.dists0[id_veh][ind_ghost] = np.inf53465347self.odos0_vehicles[id_veh][ind_ghost] = -1.05348self.odos0_ghosts[id_veh][ind_ghost] = -np.inf53495350self.stop_update(id_veh)5351self.stop_update(id_ghost)5352else:5353# veh has not such ghost5354pass53555356def del_all_ghosts(self, id_veh):5357if self.ids_ghosts[id_veh][0] == -1:5358# id_veh has no ghosts5359return53605361for id_ghost in self.ids_ghosts[id_veh]:5362if id_ghost > -1:5363self.del_ghost(id_veh, id_ghost)53645365# just to be sure ...5366self.stop_update(id_veh)53675368def switch_off_control(self, id_veh):5369"""Direct way to switch of SUMO control of vehicles"""5370print 'switch_off_control id_veh', id_veh5371traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], 6) # 6=respect max accel/decel53725373def switch_on_control(self, id_veh):5374"""Direct way to switch of SUMO control of vehicles"""5375print 'switch_on_control id_veh', id_veh5376traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], self._speedmode_leader)53775378def start_update(self, id_veh):5379"""Start updating control by ghosts"""5380self.are_update[id_veh] = True5381traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], 6) # 6=respect max accel/decel53825383def stop_update(self, id_veh):5384"""Stop updating control by ghosts"""5385if np.all(self.ids_ghosts[id_veh] == -1): # id_veh has no ghosts?53865387# attention stopping from being conrolled by merge means5388# handing control back to SUMO.5389# followers are not controlled by the merge process5390traci.vehicle.setSpeedMode(self.ids_sumo[id_veh], self._speedmode_leader)5391if id_veh not in self.ids_ghosts: # id_veh is no ghost ?5392self.are_update[id_veh] = False # stop updating53935394def process_step(self, process):5395simtime = process.simtime5396print 79*'_'5397print 'PrtVehicles.process_step at', simtime5398net = self.get_scenario().net5399vehicles = self.parent.prtvehicles5400ids = self.get_ids()5401if len(ids) == 0:5402return5403time_update = self.time_update.get_value()5404decel_emergency = self.decel_emergency.get_value()5405print ' update', len(np.flatnonzero(self.are_update[ids])), 'vehicles'5406ids_update = ids[self.are_update[ids]]5407print ' ids_update', ids_update5408#ids_debug = [324,251,417,400]5409#ids_debug = [182,133,204,170]5410#ids_debug = [271, 304]5411ids_debug = [482, 483, 484]5412if 1:5413print ' *Debug:'5414#ids_debug = [307, 236, 41, 231, 208, 44, 249, 229, 136]5415#ids_debug = [56, 271, 264, 244, 256, 253, 240, 251, 163, 150]5416#ids_debug = [26,242,139,79,138]5417#ids_debug = [2,482,44,63,67]5418for id_veh, id_veh_sumo, id_follower, id_leader in zip(ids_debug, self.ids_sumo[ids_debug], self.ids_follower[ids_debug], self.ids_leader[ids_debug]):5419print ' *id_veh prt.%d' % id_veh, 'id_follower', id_follower, 'id_leader', id_leader, 'ids_ghost', self.ids_ghosts[id_veh]5420print ' id_stop_target', self.ids_stop_target[id_veh], 'lp=%.1fm' % self.lengths_plat[id_veh]5421if self.states[id_veh] > 0:5422print ' pax', traci.vehicle.getPersonIDList(id_veh_sumo), 'isStopped', traci.vehicle.isStopped(id_veh_sumo), 'speed', traci.vehicle.getSpeed(id_veh_sumo)54235424#self.id_follower_probe = self.ids_follower[271]54255426# loop through vehicles that need speed modifications5427# these are vehicles which have ghosts or vehicles which are5428# in merge processes5429for id_veh, id_veh_sumo in zip(ids_update, self.ids_sumo[ids_update]):5430# update odometer and speed5431self.velocities[id_veh] = get_traci_velocity(id_veh_sumo)5432self.odos[id_veh] = get_traci_odo(id_veh_sumo)54335434if 0:5435ids_ghost = self.ids_ghosts[id_veh]5436print ' %7s' % id_veh_sumo, 'ghosts', ids_ghost, self.ids_leader[id_veh], "lp=%.1fm" % self.lengths_plat[id_veh]5437#odo = self.odos[id_veh]5438#delta_vehs = odo-self.odos0_vehicles[id_veh]5439#delta_ghosts = self.odos[ids_ghost] - self.odos0_ghosts[id_veh]5440# print ' delta_vehs, delta_ghosts',min(delta_vehs), min(delta_ghosts)#, self.dists0[id_veh]5441# print ' dists', min(self.dists0[id_veh] + delta_ghosts - delta_vehs)54425443#self.diststomerge0[id_veh][ind_ghost] = np.inf5444#self.diststomerge0_ghosts[id_veh][ind_ghost] = np.inf54455446# pick vehicle ids that must be controlled due to a present ghost5447ids_contr = ids_update[self.ids_ghosts[ids_update][:, 0] > -1]5448# print ' ids_contr',ids_contr5449# print ' self.ids_ghosts[ids_update][:,0]',self.ids_ghosts[ids_update][:,0]5450# print ' inds',self.ids_ghosts[ids_update][:,0]>-15451n_contr = len(ids_contr)5452n_ghosts_max = self.n_ghosts_max.get_value()54535454# no vehicles with ghost, nothing to control5455if n_contr == 0:5456return54575458# get gosts5459ids_ghosts = self.ids_ghosts[ids_contr]54605461# print ' self.odos[ids_contr]',self.odos[ids_contr].reshape(n_contr,1)5462# print ' self.odos0_vehicles[ids_contr]',self.odos0_vehicles[ids_contr]54635464# distance made since merge zone is entered5465deltas_vehs = self.odos[ids_contr].reshape(n_contr, 1)-self.odos0_vehicles[ids_contr]5466deltas_ghosts = self.odos[ids_ghosts] - self.odos0_ghosts[ids_contr]54675468#dists = self.dists0[ids_contr] + deltas_ghosts - deltas_vehs5469# print ' dists',dists5470#dists_min = np.min(self.dists0[ids_contr] + deltas_ghosts - deltas_vehs, 1) - (self.length+self.lengths_plat[ids_contr])54715472# get distance between nose of vehicle and tail of ghost which is closest5473dists_min = np.min(self.dists0[ids_contr] + deltas_ghosts - deltas_vehs -5474self.lengths_plat[ids_ghosts], 1) - self.length54755476# ??????? minimum dist to merge over all vehicles -> remove, not in use5477#diststomerge_min = np.min(self.diststomerge0[ids_contr] - deltas_vehs , 1)5478#self.diststomerge0[id_veh][ind_ghost] = dist_to_merge_veh5479# self.diststomerge0_ghosts[id_veh][ind_ghost] =54805481# print ' dists_min',dists_min5482velocities = self.velocities[ids_contr]54835484# print ' velocities_ghosts masked\n',self.velocities[ids_ghosts]54855486#mask_ghosts = INF*(ids_ghosts==-1).astype(np.float32)5487# print ' mask_ghosts\n',mask_ghosts5488velocities_ghosts = self.velocities[ids_ghosts] + INF*(ids_ghosts == -1)54895490# print ' velocities_ghosts masked\n',velocities_ghosts5491#5492# velocities of slowest ghosts5493velocities_ghost_min = np.min(self.velocities[ids_ghosts] + INF*(ids_ghosts == -1), 1)5494# print ' velocities_ghost_min\n',velocities_ghost_min5495dists_safe = self.tau*velocities + 0.5/decel_emergency*velocities*velocities5496dists_comf = self.tau*velocities + 0.5/self.decel * \5497(velocities*velocities-velocities_ghost_min*velocities_ghost_min)54985499# print ' dists_safe',dists_safe5500# print ' dists_comf',dists_comf5501#dists_crit = np.max(np.concatenate((dists_safe.reshape(n_contr,1),dists_comf.reshape(n_contr,1)),1),1)5502# print ' dists_crit',dists_crit55035504deltas_crit = dists_min-np.max(np.concatenate((dists_safe.reshape(n_contr, 1),5505dists_comf.reshape(n_contr, 1)), 1), 1)5506#deltas_crit = dists_min-dists_safe5507# print ' deltas_crit',deltas_crit5508inds_slow = deltas_crit < 05509inds_accel = (deltas_crit > 0) & (velocities < 0.8*velocities_ghost_min)5510# print ' inds_slow',inds_slow55115512if 1:5513# print ' deltas_vehs',deltas_vehs5514for id_veh, id_sumo, velocity, velocitiy_ghost_min,\5515dist_safe, dist_comf, dist_min, delta_crit,\5516is_slow, is_accel, length_plat, odo, dist0, delta_veh, delta_ghost, dist_rel\5517in zip(ids_contr, self.ids_sumo[ids_contr],5518velocities,5519velocities_ghost_min,5520dists_safe,5521dists_comf,5522dists_min,5523deltas_crit,5524inds_slow, inds_accel, self.lengths_plat[ids_contr],5525# diststomerge_min,5526self.odos[ids_contr],5527self.dists0[ids_contr][:, 0],5528deltas_vehs[:, 0], # .flatten(),5529deltas_ghosts[:, 0],5530deltas_ghosts[:, 0] - deltas_vehs[:, 0]5531):55325533if id_veh in ids_debug:5534if is_slow:5535a = '-'5536elif is_accel:5537a = '+'5538else:5539a = '='5540# print 'id_sumo, velocity, velocitiy_ghost_min,dist_safe,dist_comf,dist_min,delta_crit,is_slow,is_accel, length_plat\n',\5541# id_sumo, velocity, velocitiy_ghost_min,\5542# dist_safe,dist_comf,dist_min,delta_crit,\5543#is_slow,is_accel, length_plat55445545th = (dist_min + self.length)/velocity5546ds_check = self.tau*velocity + 0.5/decel_emergency*velocity*velocity5547dist_min_check = dist0 + delta_ghost - delta_veh - \5548self.lengths_plat[self.ids_ghosts[id_veh][0]] - self.length5549# print ' %7s: v=%3.1f vg=%3.1f dh=%4.1f th=%4.1fs ds=%4.1f dc=%4.1f lp=%3.1f %s'%(id_sumo, velocity, velocitiy_ghost_min,dist_min,th,dist_safe,dist_comf,length_plat,a)5550print ' %7s: v=%3.1f vg=%3.1f d0=%4.1f dh=%4.1f th=%3.1fs ds=%4.1f dc=%4.1f odo=%4.1f %s' % (id_sumo, velocity, velocitiy_ghost_min, dist0, dist_min, th, dist_safe, dist_comf, odo, a)5551print ' dist_min', dist_min, 'dist_min_check', dist_min_check, 'id_ghost', self.ids_ghosts[id_veh][0]5552print ' delta_veh', delta_veh, 'delta_ghost', delta_ghost, 'dist_rel', dist_rel55535554fact_urgent = np.ones(dists_safe.shape, dtype=np.float32) # np.clip(dists_safe/diststomerge_min,0.0,1.0)55555556v_delta_brake = time_update*self.decel*fact_urgent5557for id_sumo, velocity, dv in zip(self.ids_sumo[ids_contr[inds_slow]], velocities[inds_slow], v_delta_brake):5558# print ' deccel %s from %.2f to %.2fm/s dv = %.2fm/s'%(id_sumo, velocity, velocity-dv,dv)5559if velocity-dv > 0: # upset when negative velocities5560traci.vehicle.slowDown(id_sumo, velocity-dv, time_update)55615562v_delta_accel = time_update*self.accel*fact_urgent5563for id_sumo, velocity, dv in zip(self.ids_sumo[ids_contr[inds_accel]], velocities[inds_accel], v_delta_accel):5564#dv = time_update*self.accel5565# print ' accel %s from %.2f to %.2fm/s dv = %.2fm/s'%(id_sumo, velocity, velocity+dv,dv)5566traci.vehicle.slowDown(id_sumo, velocity+dv, time_update)55675568# print ' deltas_vehs',deltas_vehs5569# print ' self.ids_ghosts[ids_contr]',self.ids_ghosts[ids_contr]5570# print ' self.odos[self.ids_ghosts[ids_contr]]',self.odos[self.ids_ghosts[ids_contr]]5571# print ' self.odos0_ghosts[id_veh]',self.odos0_ghosts[ids_contr]5572# print ' deltas_ghosts',deltas_ghosts5573# print ' dists',dists5574# for id_contr, delta_vehs, delta_ghosts,dist in zip(ids_contr,deltas_vehs,deltas_ghosts,dists):5575# print ' veh',id_contr,'dist',dist55765577#self.length = vtypes.lengths[id_vtype]5578#self.speed_max = vtypes.speeds_max[id_vtype]5579#self.accel = vtypes.accels[id_vtype]5580#self.decel = vtypes.decels[id_vtype]5581#self.tau = vtypes.taus[id_vtype]5582# if self.id_follower_probe != self.ids_follower[271]:5583# print 'WARNING: prt.271 changed follower'55845585def get_targetedge_current(self, id_veh):5586return self.routes[id_veh][-1]55875588def set_route_target(self, id_veh, route, id_stop_target=None, is_disengage_from_berth=False, is_emptytrip=False):5589"""5590This is the vehicle route to the next target, not necessary the final one.5591"""5592print 'set_route_target prt.%d' % id_veh, 'id_stop_target', id_stop_target, 'is_disengage_from_berth', is_disengage_from_berth5593print ' route', route55945595# set target only if valid target, otherwise set only route5596if id_stop_target is not None:5597self.ids_stop_target[id_veh] = id_stop_target55985599# these actions are taken only once when target is set in berth5600if is_disengage_from_berth:5601# now remove the stop in order to prevent that other passengers can board5602# this is mayby not the best way to do it5603id_veh_sumo = self.get_id_sumo(id_veh)5604# print ' pax',traci.vehicle.getPersonIDList(id_veh_sumo)5605traci.vehicle.resume(id_veh_sumo)5606#if is_emptytrip: #5607# # NO!! setPersonCapacity does not exist5608# traci.vehicle.setPersonCapacity(id_veh_sumo, 0)5609# make sure that vehicle does not move5610# traci.vehicle.setStop( id_veh_sumo,5611# traci.vehicle.getRoadID(id_veh_sumo),5612# pos = traci.vehicle.getLanePosition(id_veh_sumo)+0.1,5613# flags= 32,#5614# laneIndex= 1,5615# )5616traci.vehicle.setMaxSpeed(id_veh_sumo, 0.0000001) # 0 speed not allowed5617#traci.vehicle.slowDown(id_veh_sumo, 0.0,0.1)5618traci.vehicle.changeLane(id_veh_sumo, 1, 600.0)56195620self.routes[id_veh] = list(route)56215622def set_route_completed(self, id_veh):5623self.ids_stop_target[id_veh] = -15624self.routes[id_veh] = []56255626def reset_speedmode(self, id_veh_sumo):5627print 'reset_speedmode', id_veh_sumo5628# speed mode (0xb3)5629# Per default, the vehicle is using the given speed regarding the safe gap, the maximum acceleration, and the maximum deceleration. Furthermore, vehicles follow the right-of-way rules when approaching an intersection and if necessary they brake hard to avoid driving across a red light. One can control this behavior using the speed mode (0xb3) command, the given integer is a bitset (bit0 is the least significant bit) with the following fields:5630# 1 bit0: Regard safe speed5631# 2 bit1: Regard maximum acceleration5632# 4 bit2: Regard maximum deceleration5633# 8 bit3: Regard right of way at intersections5634# 16 bit4: Brake hard to avoid passing a red light5635# 1+2+45636# traci.vehicle.setSpeedMode(id_veh_sumo,7)5637#self.speed_max = vtypes.speeds_max[id_vtype]5638#self.accel = vtypes.accels[id_vtype]5639traci.vehicle.slowDown(id_veh_sumo, self.speed_max.get_value(), self.speed_max.get_value()/self.accel)5640# pass56415642def concatenate(self, id_veh, id_veh_pre):5643print 'concatenate prt.%d' % id_veh, 'behind prt.%d' % id_veh_pre5644self.ids_leader[id_veh] = id_veh_pre5645self.ids_follower[id_veh_pre] = id_veh56465647id_veh_sumo = self.get_id_sumo(id_veh)56485649# if 0:5650# traci.vehicle.setSpeedFactor(id_veh_sumo,2.0)# +random.uniform(-0.01,0.01)5651# traci.vehicle.setImperfection(id_veh_sumo,0.0)5652# traci.vehicle.setAccel(id_veh_sumo,3.5)5653# traci.vehicle.setMinGap(id_veh_sumo,0.01)5654# traci.vehicle.setTau(id_veh_sumo,0.2)56555656# if 1:5657traci.vehicle.setSpeedMode(id_veh_sumo, self._speedmode_follower)5658traci.vehicle.setSpeedFactor(id_veh_sumo, self._factor_speed_follower)5659# traci.vehicle.setImperfection(id_veh_sumo,0.0)5660traci.vehicle.setDecel(id_veh_sumo, self._decel_emergency_follower)5661traci.vehicle.setAccel(id_veh_sumo, self._accel_follower)5662traci.vehicle.setMinGap(id_veh_sumo, self._dist_min_follower)5663traci.vehicle.setTau(id_veh_sumo, self._tau_follower)56645665if self.lengths_plat[id_veh] > 0.1:5666self._update_concatenate(id_veh, self.lengths_plat[id_veh])5667else:5668self._update_concatenate(id_veh, 0.0)56695670print ' length_plat=', self.lengths_plat[id_veh]56715672def _update_concatenate(self, id_veh, length_plat):5673"""5674Propagates length to the first vehicle of the platoon5675"""5676# TODO: this is a very inefficient method because call each time a vehicle is added.5677# Try to avoid altogether5678print '_update_concatenate prt.%s, length_plat=%.1f, length=%.1f,' % (id_veh, length_plat, self.length), 'id_leader', self.ids_leader[id_veh]5679if self.ids_leader[id_veh] == -1:5680# first vehicle5681# print ' first vehicle prt.%s'%id_veh,length_plat5682self.lengths_plat[id_veh] = length_plat5683else:5684# propagate platoon length5685self.lengths_plat[id_veh] = 0.05686self._update_concatenate(self.ids_leader[id_veh], length_plat + self.length)56875688def decatenate(self, id_veh):5689print 'decatenate prt.%d' % id_veh56905691id_leader = self.ids_leader[id_veh]5692# print ' id_leader',id_leader5693if id_leader > -1:5694id_veh_sumo = self.get_id_sumo(id_veh)56955696# if self.ids_leader[id_leader] == -1:5697# # leader of this vehicle is first in platoon5698# # this should be normally the case if a platoon is5699# # broken up from the first vehicle backwards5700#5701# # calculate new shortened platoon length5702# # TODO5703# self.lengths_plat[id_veh] = self.lengths_plat[id_leader]-self.length5704# else:5705# print 'WARNING in decatenate: platoon broken up in the middel at',id_veh_sumo,'with id_leader',id_leader5706# self.lengths_plat[id_veh] = 0.057075708# this vehicle will become first in the platoon57095710self.lengths_plat[id_veh] = 0.05711self.ids_leader[id_veh] = -15712self.ids_follower[id_leader] = -15713# if 0:5714# traci.vehicle.setSpeedFactor(id_veh_sumo, 1.5)#+random.uniform(-0.01,0.01)5715# traci.vehicle.setMinGap(id_veh_sumo,0.3)5716# traci.vehicle.setImperfection(id_veh_sumo,0.0)5717# traci.vehicle.setTau(id_veh_sumo,0.8)5718# traci.vehicle.setAccel(id_veh_sumo,2.5)57195720# if 1:5721# reset parameters5722traci.vehicle.setSpeedMode(id_veh_sumo, self._speedmode_leader)57235724# rest are leader values taken from type def5725traci.vehicle.setSpeedFactor(id_veh_sumo, self.factor_speed) # +random.uniform(-0.01,0.01)5726traci.vehicle.setMinGap(id_veh_sumo, self.dist_min)5727# traci.vehicle.setImperfection(id_veh_sumo,1.0)5728traci.vehicle.setTau(id_veh_sumo, self.tau)5729traci.vehicle.setDecel(id_veh_sumo, self.decel)5730traci.vehicle.setAccel(id_veh_sumo, self.accel)5731else:5732# it is a leader itself and does not need to decatenate5733# remove platoon length5734self.lengths_plat[id_veh] = 0.057355736print ' length_plat=', self.lengths_plat[id_veh]57375738def get_platoonleader(self, id_veh_tail):5739id_veh = 1*id_veh_tail5740while self.ids_leader[id_veh] > -1:5741id_veh = self.ids_leader[id_veh]5742return id_veh57435744def get_platoontail(self, id_veh_leader):5745id_veh = 1*id_veh_leader5746while self.ids_follower[id_veh] > -1:5747id_veh = self.ids_follower[id_veh]5748return id_veh57495750def get_platoonsize(self, id_veh_leader):5751id_veh = 1*id_veh_leader5752n = 15753while self.ids_follower[id_veh] > -1:5754id_veh = self.ids_follower[id_veh]5755n += 15756return n57575758def get_platoon(self, id_veh_leader):5759print 'get_platoon for leader prt.%d' % id_veh_leader5760ids_veh = [id_veh_leader, ]5761id_veh = self.ids_follower[id_veh_leader]5762# print ' id_veh',id_veh5763while id_veh > -1:5764ids_veh.append(id_veh)5765id_veh = self.ids_follower[id_veh]5766# print ' id_veh',id_veh57675768print ' ids_veh', ids_veh5769return ids_veh57705771def get_entered_left(self, id_edge_sumo, ids_veh_previous_sumo):5772"""5773Returns:5774array with SUMO IDs of entered vehicles during last poll5775array with SUMO IDs of left vehicles during last poll5776array with SUMO IDs current vehicles on id_edge_sumo5777Attention: in the returned entered/left lists,5778the first vehicle in the list entered/left first5779"""5780ids_veh_new_sumo = traci.edge.getLastStepVehicleIDs(id_edge_sumo)5781print 'get_entered_left ids_veh_new_sumo=', ids_veh_new_sumo5782len_prev = len(ids_veh_previous_sumo)5783len_new = len(ids_veh_new_sumo)57845785if len_prev == 0:5786return ids_veh_new_sumo, [], ids_veh_new_sumo57875788if len_new == 0:5789return [], ids_veh_previous_sumo, []57905791ind_enter = 057925793for id_veh_sumo in ids_veh_new_sumo:57945795# if ind_enter+1 == len_prev:5796# ind_enter = len_new -15797# break57985799if id_veh_sumo == ids_veh_previous_sumo[0]:5800break58015802ind_enter += 15803print ' ind_enter', ind_enter, ids_veh_new_sumo[0:ind_enter], ids_veh_new_sumo[ind_enter-1::-1]5804#ids_entered_sumo = ids_veh_new_sumo[0:ind_enter]58055806ind_leave = len_prev5807for id_veh_sumo in ids_veh_previous_sumo[::-1]:58085809if id_veh_sumo == ids_veh_new_sumo[-1]:5810break58115812ind_leave -= 15813print ' ind_leave', ind_leave, ids_veh_previous_sumo[ind_leave:], ids_veh_previous_sumo[:ind_leave:-1]5814#ids_leave_sumo = ids_veh_previous_sumo[ind_leave:]58155816# return ids_entered_sumo, ids_leave_sumo, ids_veh_new_sumo5817# return reversed lists5818return ids_veh_new_sumo[0:ind_enter][::-1], ids_veh_previous_sumo[ind_leave:][::-1], ids_veh_new_sumo58195820# TODO: optimize!!!5821# return ids_veh_new_sumo[ind_enter-1::-1], ids_veh_previous_sumo[:ind_leave:-1], ids_veh_new_sumo58225823def control_stop(self, id_veh, laneindex=0):58245825id_veh_sumo = self.get_id_sumo(id_veh)5826speed = traci.vehicle.getSpeed(id_veh_sumo)5827pos = traci.vehicle.getLanePosition(id_veh_sumo)5828stopline = pos + 3.0 + 0.5/self.decel*speed**25829#time_slowdown = np.abs((speed0-speed)/self.decel)58305831print 'control_stop', id_veh_sumo, 'v = %.2f at pos %.1fm to stop at %.1fm on %s' % (speed, pos, stopline, traci.vehicle.getRoadID(id_veh_sumo))5832traci.vehicle.setStop(id_veh_sumo,5833traci.vehicle.getRoadID(id_veh_sumo),5834pos=stopline,5835laneIndex=laneindex,5836)58375838def control_speedup(self, id_veh):58395840id_veh_sumo = self.get_id_sumo(id_veh)5841print 'control_speedup', id_veh_sumo, 'isStopped', traci.vehicle.isStopped(id_veh_sumo), self.speed_max.get_value()58425843if traci.vehicle.isStopped(id_veh_sumo):5844traci.vehicle.resume(id_veh_sumo)58455846traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())5847#self.control_slow_down(id_veh, self.speed_max.get_value())58485849def control_slow_down(self, id_veh, speed=1.0, time_slowdown=None):5850print 'control_slow_down', self.get_id_sumo(id_veh), speed, time_slowdown5851id_veh_sumo = self.get_id_sumo(id_veh)5852if time_slowdown is None:5853speed0 = traci.vehicle.getSpeed(id_veh_sumo)58545855time_slowdown = np.abs((speed0-speed)/self.decel)5856print ' speed0=%.2fm/s, time_slowdown = %.2fs, dv=%.2fm/s' % (speed0, time_slowdown, speed0-speed)58575858traci.vehicle.slowDown(id_veh_sumo, speed, time_slowdown)5859#self.speed_max = vtypes.speeds_max[id_vtype]5860#self.accel = vtypes.accels[id_vtype]5861#self.decel = vtypes.decels[id_vtype]58625863def control_forewarding_exit(self, id_veh,5864id_edge_sumo=None,5865position=None,5866laneindex=2,5867):5868"""Accelerates vehicle to line up at the exit.5869Make a stop with position at the end of the station.5870"""5871# ??? is this function called at all?5872# state forewarding_exit_kickout was unknown!!!5873id_veh_sumo = self.get_id_sumo(id_veh)5874p = traci.vehicle.getLanePosition(id_veh_sumo)5875print 'control_forewarding_exit', id_veh_sumo, p, '->', position, 'laneindex', laneindex5876if traci.vehicle.isStopped(id_veh_sumo):5877print ' resume stop'5878traci.vehicle.resume(id_veh_sumo)58795880self.states[id_veh] = VEHICLESTATES['forewarding_exit_kickout']58815882if position is None:5883# print ' do not set a stop'5884pass5885else:5886print ' set stop at pos', position5887traci.vehicle.setStop(id_veh_sumo,5888id_edge_sumo,5889pos=position,5890flags=0,5891laneIndex=laneindex,5892)5893traci.vehicle.changeLane(id_veh_sumo, laneindex, 600.0)5894# accelerate vehicle. Speed here is limited by the max speed of the lane5895traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())58965897def control_stopline_enter(self, id_veh, id_edge_sumo, stopline, laneindex=1, flags=0):5898# print 'control_stopline_enter',self.get_id_sumo(id_veh),stopline5899id_veh_sumo = self.get_id_sumo(id_veh)5900print 'control_stopline_enter', id_veh_sumo, 'lane %d, pos=%.2f->targetpos %.2f' % (laneindex, traci.vehicle.getLanePosition(id_veh_sumo), stopline)5901traci.vehicle.setStop(id_veh_sumo,5902id_edge_sumo,5903pos=stopline,5904startPos=stopline,5905laneIndex=laneindex,5906flags=flags,5907)5908self.states[id_veh] = VEHICLESTATES['forewarding']5909# traci.vehicle.changeLane(self.get_id_sumo(id_veh), laneIndex, duration(59105911def control_berth_position_enter(self, id_veh, id_berth,5912id_edge_sumo=None,5913position=None,5914laneindex=2,5915):5916"""Stop vehicle with id_veh at stopline of berth with id_berth5917Memorize berth for later use.5918"""5919id_veh_sumo = self.get_id_sumo(id_veh)5920p = traci.vehicle.getLanePosition(id_veh_sumo)5921print 'control_berth_position_enter', id_veh_sumo, p, '->', position, 'id_berth', id_berth59225923# here it can happen that vehicle has been programmed to stop in front5924# of first berth to wait for allocation5925# print ' getStopState',traci.vehicle.getStopState(id_veh_sumo)5926# print ' getNextStops',traci.vehicle.getNextStops(id_veh_sumo)5927print ' isStopped', traci.vehicle.isStopped(id_veh_sumo)5928# if len(traci.vehicle.getNextStops(id_veh_sumo))>0:59295930# already resumed5931# if traci.vehicle.isStopped(id_veh_sumo):5932# traci.vehicle.resume(id_veh_sumo)59335934self.states[id_veh] = VEHICLESTATES['forewarding_enter']5935self.ids_berth[id_veh] = id_berth5936traci.vehicle.setStop(id_veh_sumo,5937id_edge_sumo,5938pos=position,5939flags=0,5940laneIndex=laneindex,5941)5942# force vehicle to stay on lane5943traci.vehicle.changeLane(id_veh_sumo, laneindex, 60.0)59445945def control_berth_position_exit(self, id_veh,5946id_edge_sumo=None,5947position=None,5948laneindex=2,5949):5950"""Move vehicle out of berth and stop vehicle at stopline of berth to wait for exit5951"""5952id_veh_sumo = self.get_id_sumo(id_veh)5953p = traci.vehicle.getLanePosition(id_veh_sumo)5954if position is None:5955position = p+0.35956print 'control_berth_position_exit', id_veh_sumo, p, '->', position5957if traci.vehicle.isStopped(id_veh_sumo):5958traci.vehicle.resume(id_veh_sumo)59595960self.ids_berth[id_veh] = -15961self.states[id_veh] = VEHICLESTATES['kickout_berth']5962traci.vehicle.changeLane(id_veh_sumo, laneindex, 300.0)5963traci.vehicle.setStop(id_veh_sumo,5964id_edge_sumo,5965pos=position,5966flags=0,5967laneIndex=laneindex,5968)5969# accelerate vehicle. Speed here is limited by the max speed of the lane5970traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())59715972def control_berth_position_exit_slowdown(self, id_veh):5973id_veh_sumo = self.get_id_sumo(id_veh)5974print ' control_berth_position_exit_slowdown', id_veh_sumo5975# function to stop vehicle after it moved out of the berth5976if traci.vehicle.isStopped(id_veh_sumo):5977traci.vehicle.resume(id_veh_sumo)5978# set speed positive just to prevemnt that passenger jump in5979traci.vehicle.setMaxSpeed(id_veh_sumo, 0.0001)5980self.states[id_veh] = VEHICLESTATES['forewarding_exit']59815982def control_berth_stop(self, id_veh,5983id_edge_sumo=None,5984position=None,5985laneindex=1,5986):5987"""Move vehicle with id_veh into the berth and stop vehicle for lighting and boarding5988"""5989id_veh_sumo = self.get_id_sumo(id_veh)5990p = traci.vehicle.getLanePosition(id_veh_sumo)5991print 'control_berth_stop', id_veh_sumo, p, '->', position5992#d = position - p5993#v = traci.vehicle.getSpeed(id_veh_sumo)5994#d_save = 1.0/(2*2.5)*(v**2)5995# print ' v=',v5996# print ' d,d_save',d,d_save5997self.states[id_veh] = VEHICLESTATES['forewarding_enter']59985999traci.vehicle.setStop(id_veh_sumo,6000id_edge_sumo,6001startPos=position-2.0,6002pos=position,6003flags=2, # park and trigger 1+2,#6004laneIndex=laneindex,6005)60066007def control_stop_board(self, id_veh, id_stop, id_berth,6008id_edge_sumo=None,6009position=None,6010):60116012# NO LONGER USED6013id_veh_sumo = self.get_id_sumo(id_veh)6014print 'control_stop_board', id_veh_sumo, id_stop, id_berth, id_edge_sumo, 'pos=%.2f,target %.2f' % (traci.vehicle.getLanePosition(id_veh_sumo), position),6015print ' v=', traci.vehicle.getSpeed(id_veh_sumo)60166017# print 'control_stop_board',id_veh_sumo,traci.vehicle.getLanePosition(id_veh_sumo),'->',position,id_berth6018self.ids_berth[id_veh] = id_berth6019self.states[id_veh] = VEHICLESTATES['forewarding']6020# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]6021if traci.vehicle.isStopped(id_veh_sumo):6022traci.vehicle.resume(id_veh_sumo)60236024traci.vehicle.setStop(id_veh_sumo,6025id_edge_sumo,6026startPos=position-4.0,6027pos=position,6028flags=2, # park and trigger 1+2,#6029laneIndex=1,6030)60316032def launch_from_stop(self, id_veh):60336034id_veh_sumo = self.get_id_sumo(id_veh)6035print 'launch_from_stop', id_veh_sumo, 'is stopped', traci.vehicle.isStopped(id_veh_sumo)6036if traci.vehicle.isStopped(id_veh_sumo):6037print ' resume!'6038traci.vehicle.resume(id_veh_sumo)60396040route_sumo = self.get_scenario().net.edges.ids_sumo[self.routes[id_veh]]6041traci.vehicle.setRoute(id_veh_sumo, route_sumo)6042# accelerate !6043traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)6044#traci.vehicle.setMaxSpeed(id_veh_sumo, self.speed_max.get_value())6045#traci.vehicle.setMaxSpeed(id_veh_sumo, 0.66)6046print ' after launch is stopped', traci.vehicle.isStopped(id_veh_sumo), 'getMaxSpeed', traci.vehicle.getMaxSpeed(id_veh_sumo)60476048def alight(self, id_veh):6049# print 'alight',self.get_id_sumo(id_veh)6050# TODO: necessary to keep copy of state?6051self.states[id_veh] = VEHICLESTATES['alighting']60526053# traci.vehicle.getStopState(self.get_id_sumo(id_veh))6054# VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting'60556056def board(self, id_veh, id_edge_sumo=None, position=None):6057# print 'board',self.get_id_sumo(id_veh)6058# TODO: necessary to keep copy of state?6059self.states[id_veh] = VEHICLESTATES['boarding']6060#id_veh_sumo = self.get_id_sumo(id_veh)6061# print 'board',id_veh_sumo,'stopstate',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]6062# print ' ',dir(traci.vehicle)6063# traci.vehicle.getLastStepPersonIDs()6064# traci.vehicle.getStopState(self.get_id_sumo(id_veh))6065# VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting'6066#traci.vehicle.setRoute(id_veh_sumo, [id_edge_sumo])6067# traci.vehicle.resume(id_veh_sumo)60686069# traci.vehicle.setStop( self.get_id_sumo(id_veh),6070# traci.vehicle.getRoadID(id_veh_sumo),6071# pos = traci.vehicle.getLanePosition(id_veh_sumo),6072# flags= 2,#6073# laneIndex= 1,6074# )6075# print 'board ',id_veh_sumo, traci.vehicle.getStopState(id_veh_sumo )# bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]60766077def init_passthrough(self, id_veh, id_edge_sumo, stopline, laneindex=1, flags=0):6078id_veh_sumo = self.get_id_sumo(id_veh)6079print 'init_passthrough', id_veh_sumo, 'lane %d, pos=%.2f->targetpos %.2f' % (laneindex, traci.vehicle.getLanePosition(id_veh_sumo), stopline)60806081# do n6082#is_stop = True6083# if id_veh_infront > -1:6084# if self.states[id_veh_infront] == VEHICLESTATES['forewarding_passthrough']:6085# is_stop = False60866087# if is_stop:6088traci.vehicle.setStop(id_veh_sumo,6089id_edge_sumo,6090pos=stopline,6091startPos=stopline,6092laneIndex=laneindex,6093flags=flags,6094)60956096self.states[id_veh] = VEHICLESTATES['forewarding_passthrough']60976098def foreward_passthrough(self, id_veh):60996100id_veh_sumo = self.get_id_sumo(id_veh)6101print 'foreward_passthrough', id_veh_sumo6102if traci.vehicle.isStopped(id_veh_sumo):6103# print ' resume!'6104traci.vehicle.resume(id_veh_sumo)61056106traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)61076108def reached_stop_sumo(self, id_veh_sumo):6109state = traci.vehicle.getStopState(id_veh_sumo)6110print 'reached_stop', id_veh_sumo, bin(state), bin(state)[-1] == '1'6111return bin(state)[-1] == '1'61126113def is_completed_alighting(self, id_veh):6114print 'is_completed_alighting', self.get_id_sumo(id_veh), self.states[id_veh], 'alighting', self.states[id_veh] == VEHICLESTATES['alighting'], 'pers on board', traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)), type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)))6115if self.states[id_veh] == VEHICLESTATES['alighting']:6116ids_persons_sumo_on_board = traci.vehicle.getPersonIDList(self.get_id_sumo(id_veh))6117if self.ids_persons_sumo[id_veh].isdisjoint(ids_persons_sumo_on_board):6118# if traci.vehicle.getPersonIDList(self.get_id_sumo(id_veh)) == 0:6119print ' completed alighting ids_persons_sumo_on_board', ids_persons_sumo_on_board6120if len(ids_persons_sumo_on_board) > 0:6121self.states[id_veh] = VEHICLESTATES['boarding']6122else:6123self.states[id_veh] = VEHICLESTATES['waiting']6124return True6125else:6126# somebody is still in the vehicle6127return False61286129else:6130return True61316132def is_completed_boarding(self, id_veh):6133# print 'is_completed_boarding',self.get_id_sumo(id_veh),traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)),type(traci.vehicle.getPersonNumber(self.get_id_sumo(id_veh)))61346135# TODO: this is still assuming one person at max6136# for groups this must change6137if self.states[id_veh] in (VEHICLESTATES['boarding'], VEHICLESTATES['waiting']):6138ids_person_sumo = traci.vehicle.getPersonIDList(self.get_id_sumo(id_veh))6139if len(ids_person_sumo) == 1:6140print ' completed boarding'6141self.states[id_veh] = VEHICLESTATES['boarding_completed']6142self.ids_persons_sumo[id_veh].add(ids_person_sumo)6143return True6144else:6145return False61466147elif self.states[id_veh] == VEHICLESTATES['boarding_completed']:6148return True61496150else:6151return False61526153def init_trip_occupied(self, id_veh, id_edge_sumo, stopline=None):6154id_veh_sumo = self.get_id_sumo(id_veh)6155print 'init_trip_occupied', self.get_id_sumo(id_veh), id_edge_sumo, stopline6156# print ' current route:',traci.vehicle.getRoute(id_veh_sumo)6157self.states[id_veh] = VEHICLESTATES['occupiedtrip']61586159# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]6160if traci.vehicle.isStopped(id_veh_sumo):6161traci.vehicle.resume(id_veh_sumo)6162#traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest)6163#traci.vehicle.changeTarget(self.get_id_sumo(id_veh), id_edge_sumo_dest)6164if stopline is not None:6165traci.vehicle.setStop(id_veh_sumo,6166id_edge_sumo,6167pos=stopline,6168laneIndex=1,6169)6170else:6171speed_crawl = 1.06172time_accel = 4.06173#traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel)61746175def init_trip_empty(self, id_veh, id_edge_sumo, stopline=None):6176print 'Vehicles.init_trip_empty', self.get_id_sumo(id_veh), id_edge_sumo, stopline6177self.states[id_veh] = VEHICLESTATES['emptytrip']6178id_veh_sumo = self.get_id_sumo(id_veh)6179if traci.vehicle.isStopped(id_veh_sumo):6180traci.vehicle.resume(id_veh_sumo)6181#traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to)6182if stopline is not None:6183# if stopline>=0:6184# print ' Route=',traci.vehicle.getRoute(id_veh_sumo)6185# print ' Position=',traci.vehicle.getLanePosition(id_veh_sumo),stopline6186# print ' StopState=',bin(traci.vehicle.getStopState(id_veh_sumo ))[2:]61876188traci.vehicle.setStop(id_veh_sumo,6189id_edge_sumo,6190pos=stopline,6191laneIndex=1,6192)6193else:6194speed_crawl = 1.06195time_accel = 4.06196#traci.vehicle.slowDown(id_veh_sumo, speed_crawl, time_accel)61976198def reschedule_trip(self, id_veh, id_edge_sumo_to=None, route_sumo=None):6199print 'reschedule_trip', self.get_id_sumo(id_veh), id_edge_sumo_to, route_sumo6200id_veh_sumo = self.get_id_sumo(id_veh)6201if traci.vehicle.isStopped(id_veh_sumo):6202traci.vehicle.resume(id_veh_sumo)62036204if route_sumo is not None:6205# set entire route6206traci.vehicle.setRoute(id_veh_sumo, route_sumo)6207else:6208# set new target and let SUMO do the routing6209traci.vehicle.changeTarget(id_veh_sumo, id_edge_sumo_to)62106211#6212# self.reset_speedmode(id_veh_sumo)6213# limit speed to run slowly on exit line6214# the merge will take over speed control62156216#traci.vehicle.setMaxSpeed(id_veh_sumo, 6.0/3.6)6217# print ' set speed to',traci.vehicle.getMaxSpeed(id_veh_sumo)6218#traci.vehicle.slowDown(id_veh_sumo, 13.0, 5.0)62196220def add_to_net(self, n=-1, length_veh_av=4.0):6221"""6222Add n PRT vehicles to network6223If n = -1 then fill up stops with vehicles.6224"""6225# print 'PrtVehicles.make',n,length_veh_av6226# self.clear()6227net = self.get_scenario().net6228ptstops = net.ptstops6229prtstops = self.parent.prtstops6230lanes = net.lanes6231ids_prtstop = prtstops.get_ids()6232ids_ptstop = prtstops.ids_ptstop[ids_prtstop]6233ids_veh = []6234n_stop = len(prtstops)62356236for id_stop, id_edge, pos_from, pos_to in zip(6237ids_prtstop,6238lanes.ids_edge[ptstops.ids_lane[ids_ptstop]],6239ptstops.positions_from[ids_ptstop],6240ptstops.positions_to[ids_ptstop],6241):6242# TODO: here we can select depos or distribute a6243# fixed number of vehicles or put them into berth62446245# print ' ',pos_to,pos_from,int((pos_to-pos_from)/length_veh_av)6246if n > 0:6247n_veh_per_stop = int(float(n)/n_stop+0.5)6248else:6249n_veh_per_stop = int((pos_to-pos_from)/length_veh_av)62506251# print ' n,n_stop,n_veh_per_stop',n,n_stop,n_veh_per_stop6252for i in range(n_veh_per_stop):6253id_veh = self.add_row(ids_stop_target=id_stop,6254ids_currentedge=id_edge,6255)62566257self.ids_sumo[id_veh] = self.get_id_sumo(id_veh)6258ids_veh.append(id_veh)62596260return ids_veh62616262# def write_veh6263#62646265def get_scenario(self):6266return self.parent.get_scenario()62676268def get_vtypes(self):6269"""6270Returns a set with all used PRT vehicle types.6271"""6272# print 'Vehicles_individual.get_vtypes',self.cols.vtype6273return set(self.ids_vtype.get_value())62746275def get_id_sumo(self, id_veh):6276return 'prt.%s' % (id_veh)62776278def get_id_from_id_sumo(self, id_veh_sumo):6279if len(id_veh_sumo.split('.')) == 2:6280prefix, id_veh = id_veh_sumo.split('.')6281if prefix == 'prt':6282return int(id_veh)6283else:6284return -16285return -162866287def get_ids_from_ids_sumo(self, ids_veh_sumo):6288n = len(ids_veh_sumo)6289ids = np.zeros(n, np.int32)6290for i in xrange(n):6291ids[i] = self.get_id_from_id_sumo(ids_veh_sumo[i])6292return ids62936294def get_id_line_xml(self):6295return 'prt'629662976298class HcPrtStrategy(StrategyMixin):6299def __init__(self, ident, parent=None,6300name='High Capacity Personal Rapid Transit Strategy',6301info='With this strategy, the person uses High Capacity Personla Rapid Transit as main transport mode.',6302**kwargs):63036304self._init_objman(ident, parent, name=name, info=info, **kwargs)6305attrsman = self.set_attrsman(cm.Attrsman(self))6306# specific init6307self._init_attributes()6308self._init_constants()63096310def _init_attributes(self):6311# print 'StrategyMixin._init_attributes'6312pass63136314def _init_constants(self):6315#virtualpop = self.get_virtualpop()6316#stagetables = virtualpop.get_stagetables()63176318#self._walkstages = stagetables.get_stagetable('walks')6319#self._ridestages = stagetables.get_stagetable('rides')6320#self._activitystages = stagetables.get_stagetable('activities')63216322#self._plans = virtualpop.get_plans()6323#6324# print 'AutoStrategy._init_constants'6325# print dir(self)6326# self.get_attrsman().do_not_save_attrs(['_activitystages','_ridestages','_walkstages','_plans'])63276328modes = self.get_virtualpop().get_scenario().net.modes6329self._id_mode_bike = modes.get_id_mode('bicycle')6330self._id_mode_auto = modes.get_id_mode('passenger')6331self._id_mode_moto = modes.get_id_mode('motorcycle')6332self._id_mode_bus = modes.get_id_mode('bus')6333self.get_attrsman().do_not_save_attrs([6334'_id_mode_bike', '_id_mode_auto', '_id_mode_moto', '_id_mode_bus'6335])63366337def set_prtservice(self, prtservice):6338#self.add( cm.ObjConf( prtservice, is_child = False,groups = ['_private']))6339self.prtservice = prtservice6340self.get_attrsman().do_not_save_attrs(['prtservice'])63416342def preevaluate(self, ids_person):6343"""6344Preevaluation strategies for person IDs in vector ids_person.63456346Returns a preevaluation vector with a preevaluation value6347for each person ID. The values of the preevaluation vector are as follows:6348-1 : Strategy cannot be applied63490 : Stategy can be applied, but the preferred mode is not used63501 : Stategy can be applied, and preferred mode is part of the strategy63512 : Strategy uses predomunantly preferred mode63526353"""6354n_pers = len(ids_person)6355persons = self.get_virtualpop()6356preeval = np.zeros(n_pers, dtype=np.int32)63576358# TODO: here we could exclude by age or distance facilities-stops63596360# put 0 for persons whose preference is not public transport6361preeval[persons.ids_mode_preferred[ids_person] != self.prtservice.id_prtmode] = 063626363# put 2 for persons who prefer prt (probably few in pre PRT times)6364preeval[persons.ids_mode_preferred[ids_person] == self.prtservice.id_prtmode] = 263656366print ' HcPrtStrategy.preevaluate', len(np.flatnonzero(preeval))6367return preeval63686369def plan(self, ids_person, logger=None):6370"""6371Generates a plan for these person according to this strategie.6372Overriden by specific strategy.6373"""6374print 'HcPrtStrategy.plan', len(ids_person)6375#make_plans_private(self, ids_person = None, mode = 'passenger')6376# routing necessary?6377virtualpop = self.get_virtualpop()6378scenario = virtualpop.get_scenario()6379plans = virtualpop.get_plans() # self._plans6380demand = scenario.demand6381#ptlines = demand.ptlines63826383walkstages = plans.get_stagetable('walks')6384prtstages = plans.get_stagetable('hcprttransits')6385activitystages = plans.get_stagetable('activities')63866387activities = virtualpop.get_activities()6388activitytypes = demand.activitytypes6389prtstops = self.prtservice.prtstops63906391if len(prtstops) == 0:6392print 'WARNING: no prt stops, no prt plans'6393return True63946395net = scenario.net6396edges = net.edges6397lanes = net.lanes6398modes = net.modes6399landuse = scenario.landuse6400facilities = landuse.facilities64016402times_est_plan = plans.times_est6403# here we can determine edge weights for different modes64046405# this could be centralized to avoid redundance6406plans.prepare_stagetables(['walks', 'hcprttransits', 'activities'])6407# must be after preparation:6408if self.prtservice.times_stop_to_stop is None:6409self.prtservice.make_times_stop_to_stop()64106411times_stop_to_stop = self.prtservice.times_stop_to_stop6412if times_stop_to_stop is None:6413print 'WARNING: stop to stop matrix not calculated. Please configure the PRT system.'6414return True64156416ids_person_act, ids_act_from, ids_act_to\6417= virtualpop.get_activities_from_pattern(0, ids_person=ids_person)64186419if len(ids_person_act) == 0:6420print 'WARNING in TrasitStrategy.plan: no eligible persons found.'6421return False64226423# temporary maps from ids_person to other parameters6424nm = np.max(ids_person_act)+16425map_ids_plan = np.zeros(nm, dtype=np.int32)6426#ids_plan_act = virtualpop.add_plans(ids_person_act, id_strategy = self.get_id_strategy())6427map_ids_plan[ids_person_act] = virtualpop.add_plans(ids_person_act, id_strategy=self.get_id_strategy())64286429map_times = np.zeros(nm, dtype=np.int32)6430map_times[ids_person_act] = activities.get_times_end(ids_act_from, pdf='unit')64316432# set start time to plans (important!)6433plans.times_begin[map_ids_plan[ids_person_act]] = map_times[ids_person_act]64346435map_ids_fac_from = np.zeros(nm, dtype=np.int32)6436map_ids_fac_from[ids_person_act] = activities.ids_facility[ids_act_from]64376438n_plans = len(ids_person_act)6439print 'TrasitStrategy.plan n_plans=', n_plans64406441# make initial activity stage6442ids_edge_from = facilities.ids_roadedge_closest[map_ids_fac_from[ids_person_act]]6443poss_edge_from = facilities.positions_roadedge_closest[map_ids_fac_from[ids_person_act]]6444# this is the time when first activity starts6445# first activity is normally not simulated64466447names_acttype_from = activitytypes.names[activities.ids_activitytype[ids_act_from]]6448durations_act_from = activities.get_durations(ids_act_from)6449times_from = map_times[ids_person_act]-durations_act_from6450#times_from = activities.get_times_end(ids_act_from, pdf = 'unit')64516452for id_plan,\6453time,\6454id_act_from,\6455name_acttype_from,\6456duration_act_from,\6457id_edge_from,\6458pos_edge_from \6459in zip(map_ids_plan[ids_person_act],6460times_from,6461ids_act_from,6462names_acttype_from,6463durations_act_from,6464ids_edge_from,6465poss_edge_from):64666467id_stage_act, time = activitystages.append_stage(6468id_plan, time,6469ids_activity=id_act_from,6470names_activitytype=name_acttype_from,6471durations=duration_act_from,6472ids_lane=edges.ids_lanes[id_edge_from][0],6473positions=pos_edge_from,6474)64756476##64776478ind_act = 064796480# main loop while there are persons performing6481# an activity at index ind_act6482while len(ids_person_act) > 0:6483ids_plan = map_ids_plan[ids_person_act]64846485times_from = map_times[ids_person_act]64866487names_acttype_to = activitytypes.names[activities.ids_activitytype[ids_act_to]]6488durations_act_to = activities.get_durations(ids_act_to)64896490ids_fac_from = map_ids_fac_from[ids_person_act]6491ids_fac_to = activities.ids_facility[ids_act_to]64926493centroids_from = facilities.centroids[ids_fac_from]6494centroids_to = facilities.centroids[ids_fac_to]6495dists_from_to = np.sqrt(np.sum((centroids_to - centroids_from)**2, 1))6496dists_walk_max = virtualpop.dists_walk_max[ids_person_act]64976498# origin edge and position6499ids_edge_from = facilities.ids_roadedge_closest[ids_fac_from]6500poss_edge_from = facilities.positions_roadedge_closest[ids_fac_from]65016502# destination edge and position6503# attention, this methods assumes that all stops are reachable by foot6504ids_edge_to = facilities.ids_roadedge_closest[ids_fac_to]6505poss_edge_to = facilities.positions_roadedge_closest[ids_fac_to]65066507# find closest prt stop!!6508#ids_stop_from, ids_stopedge_from = prtstops.get_closest(centroids_from)6509#ids_stop_to, ids_stopedge_to = prtstops.get_closest(centroids_to)65106511ids_stop_from, ids_stopedge_from, ids_stop_to, ids_stopedge_to = prtstops.get_closest_for_trip(6512centroids_from, centroids_to, ids_person=ids_person_act)65136514poss_stop_from = prtstops.get_waitpositions(ids_stop_from, offset=-0.5)6515poss_stop_to = prtstops.get_waitpositions(ids_stop_to, offset=-0.5)65166517i = 0.06518for id_person, id_plan, time_from, id_act_from, id_act_to, name_acttype_to, duration_act_to, id_edge_from, pos_edge_from, id_edge_to, pos_edge_to, id_stop_from, id_stopedge_from, pos_stop_from, id_stop_to, id_stopedge_to, pos_stop_to, dist_from_to, dist_walk_max\6519in zip(ids_person_act, ids_plan, times_from, ids_act_from, ids_act_to, names_acttype_to, durations_act_to, ids_edge_from, poss_edge_from, ids_edge_to, poss_edge_to, ids_stop_from, ids_stopedge_from, poss_stop_from, ids_stop_to, ids_stopedge_to, poss_stop_to, dists_from_to, dists_walk_max):6520n_pers = len(ids_person_act)6521if logger:6522logger.progress(i/n_pers*100)6523i += 1.06524print 79*'_'6525print ' id_plan=%d, id_person=%d, ' % (id_plan, id_person)65266527if id_person == 17214:6528print ' id_stop_from', id_stop_from, 'id_stop_to', id_stop_to6529print ' id_stopedge_from', id_stopedge_from, 'id_stopedge_to', id_stopedge_to65306531if (dist_from_to < dist_walk_max) | (id_edge_from == -1) | (id_edge_to == -1) | (id_stop_from == id_stop_to):6532print ' go by foot because distance is too short ', dist_from_to, 'edges', id_edge_from, id_edge_to, 'stops', id_stop_from, id_stop_to65336534id_stage_walk1, time = walkstages.append_stage(6535id_plan, time_from,6536id_edge_from=id_edge_from,6537position_edge_from=pos_edge_from,6538id_edge_to=id_edge_to,6539position_edge_to=pos_edge_to,6540)6541else:6542id_stage_walk1, time = walkstages.append_stage(id_plan, time_from,6543id_edge_from=id_edge_from,6544position_edge_from=pos_edge_from,6545id_edge_to=id_stopedge_from,6546position_edge_to=pos_stop_from, # -7.0,6547)65486549# take PRT6550# self.ids_edge_to_ids_prtstop6551id_stage_transit, time = prtstages.append_stage(6552id_plan, time,6553duration=times_stop_to_stop[id_stop_from, id_stop_to],6554id_fromedge=id_stopedge_from,6555id_toedge=id_stopedge_to,6556)65576558# walk from final prtstop to activity6559# print ' Stage for linktype %2d fromedge %s toedge %s'%(linktype, edges.ids_sumo[id_stopedge_to],edges.ids_sumo[id_edge_to] )6560id_stage_walk2, time = walkstages.append_stage(id_plan, time,6561id_edge_from=id_stopedge_to,6562position_edge_from=pos_stop_to,6563id_edge_to=id_edge_to,6564position_edge_to=pos_edge_to,6565)65666567# update time for trips estimation for this plan6568plans.times_est[id_plan] += time-time_from65696570# define current end time without last activity duration6571plans.times_end[id_plan] = time65726573id_stage_act, time = activitystages.append_stage(6574id_plan, time,6575ids_to=id_act_to,6576names_totype=name_acttype_to,6577durations=duration_act_to,6578ids_lane=edges.ids_lanes[id_edge_to][0],6579positions=pos_edge_to,6580)65816582# store time for next iteration in case other activities are6583# following6584map_times[id_person] = time65856586# select persons and activities for next setp6587ind_act += 16588ids_person_act, ids_act_from, ids_act_to\6589= virtualpop.get_activities_from_pattern(ind_act, ids_person=ids_person_act)659065916592class HcPrtTransits(StageTypeMixin):6593def __init__(self, ident, stages,6594name='Ride on HCPRT',6595info='Ride on High Capacity Personal Rapid Transit network.',6596# **kwargs,6597):65986599print 'HcPrtTransits.__init__', ident, stages6600self.init_stagetable(ident,6601stages, name=name,6602info=info,6603)6604self._init_attributes()6605self._init_constants()66066607def _init_attributes(self):6608edges = self.get_virtualpop().get_net().edges66096610self.add_col(am.IdsArrayConf('ids_fromedge', edges,6611groupnames=['parameters'],6612name='Edge ID from',6613info='Edge ID of departure PRT station.',6614))66156616self.add_col(am.IdsArrayConf('ids_toedge', edges,6617groupnames=['parameters'],6618name='Edge ID to',6619info='Edge ID of destination PRT station.',6620))66216622def set_prtservice(self, prtservice):6623print 'HcPrtTransits.set_prtservice', prtservice, 'id(self)', id(self)6624self.add(cm.ObjConf(prtservice, is_child=False, groups=['_private']))66256626def get_prtservice(self):6627print 'get_prtservice', self, id(self)6628return self.hcprtservice.get_value()66296630def prepare_planning(self):66316632prtservice = self.get_prtservice()6633print 'HcPrtTransits.prepare_planning', prtservice.times_stop_to_stop6634if prtservice.times_stop_to_stop is None:6635prtservice.make_times_stop_to_stop()6636print prtservice.times_stop_to_stop66376638def append_stage(self, id_plan, time_start=-1.0,6639duration=0.0,6640id_fromedge=-1, id_toedge=-1, **kwargs):6641"""6642Appends a PRT transit stage to plan id_plan.66436644"""6645# print 'HcPrtTransits.append_stage',id_stage66466647id_stage, time_end = StageTypeMixin.append_stage(self,6648id_plan,6649time_start,6650durations=duration,6651ids_fromedge=id_fromedge,6652ids_toedge=id_toedge,6653)66546655# add this stage to the vehicle database6656# ind_ride gives the index of this ride (within the same plan??)6657#ind_ride = self.parent.get_individualvehicles().append_ride(id_veh, id_stage)6658return id_stage, time_end66596660def to_xml(self, id_stage, fd, indent=0):6661# <ride from="1/3to0/3" to="0/4to1/4" lines="train0"/>6662net = self.get_virtualpop().get_net()6663#ids_stoplane = net.ptstops.ids_lane6664#ids_laneedge = net.lanes.ids_edge6665ids_sumoedge = net.edges.ids_sumo66666667#ind = self.get_ind(id_stage)6668fd.write(xm.start('ride', indent=indent))6669fd.write(xm.num('from', ids_sumoedge[self.ids_fromedge[id_stage]]))6670fd.write(xm.num('to', ids_sumoedge[self.ids_toedge[id_stage]]))6671fd.write(xm.num('lines', 'prt'))6672# if self.cols.pos_edge_from[ind]>0:6673# fd.write(xm.num('departPos', self.cols.pos_edge_from[ind]))6674# if self.cols.pos_edge_to[ind]>0:6675# fd.write(xm.num('arrivalPos', self.cols.pos_edge_to[ind]))66766677fd.write(xm.stopit()) # ends stage667866796680class VehicleMan(am.ArrayObjman):6681def __init__(self, ident, prtservices, **kwargs):6682self._init_objman(ident=ident,6683parent=prtservices,6684name='HC PRT vehicle management',6685info='HC PRT vehicle management.',6686#xmltag = ('additional','busStop','stopnames'),6687version=0.0,6688**kwargs)66896690self._init_attributes()6691self._init_constants()66926693def _init_attributes(self):6694self.add(cm.AttrConf('time_update', 2.0,6695groupnames=['parameters'],6696name='Man. update time',6697info="Update time for vehicle management.",6698unit='s',6699))67006701# self.time_update.set(5.0)67026703self.add(cm.AttrConf('time_update_flows', 10.0,6704groupnames=['parameters'],6705name='Flow update time',6706info="Update time for flow estimations.",6707unit='s',6708))6709# self.time_update.set(10.0)6710# if hasattr(self,'time_flowaverage'):6711# self.delete('time_flowaverage')67126713self.add(cm.AttrConf('time_est_max', 1200,6714groupnames=['parameters'],6715name='prediction interval',6716info="Prediction time range of vehicle management.",6717unit='s',6718))67196720self.add(cm.AttrConf('time_search_occupied', 10.0,6721groupnames=['parameters'],6722name='Occupied search time',6723info="Time interval for search of optimum departure time in case of an occupied vehicle trip.",6724unit='s',6725))67266727self.add(cm.AttrConf('time_search_empty', 20.0,6728groupnames=['parameters'],6729name='Empty search time',6730info="Time interval for search of optimum departure time in case of an empty vehicle trip.",6731unit='s',6732))67336734self.add(cm.AttrConf('weight_demand', 0.01,6735groupnames=['parameters'],6736name='Demand weight',6737info="Weight of current demand at stations when assigning empty vehicles trips.",6738))67396740self.add(cm.AttrConf('weight_flow', 1.0,6741groupnames=['parameters'],6742name='Flow weight',6743info="Weight of flows (changes in demand over time) at stations when assigning empty vehicles trips.",6744))67456746self.add(cm.AttrConf('constant_timeweight', 0.005,6747groupnames=['parameters'],6748name='Time weight const.',6749info="Constant for the exponential decay function weighting the time instance in the optimization function.",6750unit='1/s',6751))67526753self.add(cm.AttrConf('flow_max_default', 700.0,6754groupnames=['parameters'],6755name='Default max. veh flow',6756info="Maximum vehicle flow allowed for a stop. This is a default value an may be replaced by capacity capculations that depend on the geometry of the stop.",6757unit='1/h',6758))67596760# def set_stops(self,vehicleman):6761# self.add( cm.ObjConf( stops, is_child = False,groups = ['_private']))67626763def _init_constants(self):6764self.do_not_save_attrs([6765'ids_stop', 'numbers_veh_arr', 'n_est_max',6766'inflows_sched', 'inflows_person', 'inflows_person_last',6767'ids_veh', 'ids_stop_target', 'ids_stop_current',6768'times_order', 'occupiedtrips_new', 'emptytrips_new',6769'are_emptytrips',6770'log_inflows_temp',6771])67726773def get_stops(self):6774return self.parent.prtstops67756776def get_vehicles(self):6777return self.parent.prtvehicles67786779def get_scenario(self):6780return self.parent.parent.get_scenario()67816782def prepare_sim(self, process):6783print 'VehicleMan.prepare_sim'6784net = self.get_scenario().net67856786# station management6787# self.ids_stop_to_ids_edge_sumo = np.zeros(np.max(ids)+1,dtype = np.object)67886789self.ids_stop = self.get_stops().get_ids()67906791if len(self.ids_stop) == 0:6792return []67936794n_stoparray = np.max(self.ids_stop)+167956796# number of arrived vehicles for each station and all future time intervals6797self.numbers_veh_arr = np.zeros(n_stoparray, dtype=np.int32)6798self.n_est_max = int(self.time_est_max.get_value()/self.time_update_flows.get_value())67996800# maximum station flows as maximum number of vehicles per timeslot6801# this should be delivered by each station in function of its dimension6802# self.flow_max_default.get_value() # vehicles per hour68036804self.flows_stop_max = np.zeros(n_stoparray, dtype=np.float32)68056806for id_stop in self.ids_stop:6807self.flows_stop_max[id_stop] = self.get_stops().get_capacity(6808id_stop) / (3600.0/self.time_update_flows.get_value())68096810#self.flows_stop_max = self.flow_max_default.get_value()/(3600.0/self.time_update_flows.get_value()) * np.ones(n_stoparray, dtype = np.float32)68116812# current targets by station, updated by station and processed each veh. man. step6813# this is the target stop of the vehicle(s) waiting at each stop to be launched by the vehicle man6814self.ids_stop_target_current = -1*np.ones(n_stoparray, dtype=np.int32)68156816# current etimated times to targets by station, updated by station and processed each veh. man. step6817self.duration_est_target_current = np.zeros(n_stoparray, dtype=np.float32)68186819# current number of waiting vehicles with targets by station, updated by station and processed each veh. man. step6820self.numbers_veh_target_current = np.zeros(n_stoparray, dtype=np.int32)68216822# scheduled departure time for vehicles to be launched at each station6823self.times_departure_sched = -np.ones(n_stoparray, dtype=np.int32)68246825# scheduled flows for each station and each future time intervals6826self.inflows_sched = np.zeros((n_stoparray, self.n_est_max), dtype=np.int32)68276828# inflow of persons for each stop in current time interval6829self.inflows_person = np.zeros(n_stoparray, dtype=np.int32)68306831# inflow of persons for each stop in last time interval6832self.inflows_person_last = np.zeros(n_stoparray, dtype=np.int32)68336834# numbers of vehicles which initiated a trip to each target station6835# the trip initiates when the vehicle is still in the berth6836# and ends when the vehicle is entering the target station6837self.numbers_veh_target_init = np.zeros(n_stoparray, dtype=np.int32)68386839# vehicle management6840self.ids_veh = self.get_vehicles().get_ids()68416842if len(self.ids_veh) == 0:6843print 'WARNING: no PRT vehicles, please add PRT vehicles.'6844return []68456846n_veharray = np.max(self.ids_veh)+168476848# could go in vehicle array68496850self.ids_stop_target = -1*np.ones(n_veharray, dtype=np.int32)6851self.ids_stop_current = -1*np.ones(n_veharray, dtype=np.int32)6852self.times_order = 10**6*np.ones(n_veharray, dtype=np.int32)6853# self.occupiedtrips_new = []#?? put this is also in general time scheme with more urgency??6854#self.emptytrips_new = []68556856# from veh arrays6857#self.are_emptytrips = np.zeros(n_veharray, dtype = np.bool)68586859# logging6860results = process.get_results()6861if results is not None:6862time_update_flows = self.time_update_flows.get_value()6863n_timesteps = int((process.duration-process.time_warmup)/time_update_flows+1)6864results.hcprtstopresults.init_recording(n_timesteps, time_update_flows)68656866# number of vehicles arrived in each stop during one time interval6867self.log_inflows_temp = np.zeros(n_stoparray, dtype=np.int32)68686869return [(self.time_update.get_value(), self.process_step),6870(self.time_update_flows.get_value(), self.update_flows),6871]68726873def update_flows(self, process):6874print 'HC VehicleMan update flow prediction'6875self.inflows_sched[:, 0] = 06876self.inflows_sched = np.roll(self.inflows_sched, -1)6877time_update_flows = self.time_update_flows.get_value()68786879if process.simtime > process.time_warmup:6880stops = self.get_stops()6881ids_stop = self.ids_stop6882# print ' dir(results)',dir(process.get_results())6883prtstopresults = process.get_results().hcprtstopresults6884const_time = 1.0/time_update_flows # np.array([1.0/time_update_flows],dtype=np.float32)6885timestep = (process.simtime - process.simtime_start - process.time_warmup)/time_update_flows6886prtstopresults.record(timestep, ids_stop,6887inflows_veh=np.array(const_time * self.log_inflows_temp[ids_stop], dtype=np.float32),6888inflows_veh_sched=np.array(6889const_time * self.inflows_sched[ids_stop, 0], dtype=np.float32),6890numbers_person_wait=stops.numbers_person_wait[ids_stop],6891waittimes_tot=stops.waittimes_tot[ids_stop],6892inflows_person=np.array(const_time * self.inflows_person[ids_stop], dtype=np.float32),6893#inflows_person = stops.flows_person[ids_stop],6894)6895if self.debug > 5:6896for id_stop in ids_stop:6897self.display_flows_est(id_stop)68986899self.inflows_person_last = self.inflows_person.copy()6900self.inflows_person[:] = 06901self.log_inflows_temp[:] = 069026903def process_step(self, process):6904print 79*'M'6905print 'HC VehicleMan.process_step'69066907self.debug = 969086909# push all vehicles out of output queue, if flow conditions allow6910# these are vehicles which have already a destination6911self.push_out_vehicles(process)69126913is_cont = True6914while is_cont:6915surpluses_veh, surpluses_veh_urgent, demands_veh, balances_veh, n_move_eff_total = self.equalize_empty_vehicles(6916process)6917#is_cont = (n_move_eff_total>0) & ((np.any(surpluses_veh > 0) & np.any(balances_veh < 0)) | np.any(surpluses_veh_urgent > 0))6918is_cont = (n_move_eff_total > 0) & np.any(surpluses_veh_urgent > 0)6919is_cont = False6920if self.debug > 4:6921print 79*'-'6922print ' check equalize iteration', np.any(surpluses_veh > 0), np.any(balances_veh > 0), np.any(surpluses_veh_urgent > 0), 'is_cont', is_cont6923print ' n_move_eff_total', n_move_eff_total6924print ' surpluses_veh', surpluses_veh6925print ' demands_veh', demands_veh6926print ' balances_veh', balances_veh6927print ' surpluses_veh_urgent', surpluses_veh_urgent69286929if 0:6930stops = self.get_stops()6931#vehicles = self.get_vehicles()69326933has_programmed = True6934#ids_veh_ready_for_departure = stops.ids_veh_ready_for_departure[self.ids_stop]69356936while has_programmed:6937has_programmed = False69386939if len(inds_valid) > 0:69406941has_programmed |= self.push_out_vehicles(ids_veh_ready_for_departure, process)6942ids_veh_lead = stops.ids_veh_lead[self.ids_stop]6943inds_valid = np.flatnonzero(ids_veh_lead >= 0)6944has_programmed |= self.push_empty_leadvehs(ids_veh_lead[inds_valid], process)6945ids_veh_lead = stops.ids_veh_lead[self.ids_stop]6946inds_valid = np.flatnonzero(ids_veh_lead >= 0)69476948#has_programmed |= self.pull_empty_leadvehs(ids_veh_lead[inds_valid],process)6949#ids_veh_lead = stops.ids_veh_lead[self.ids_stop]6950#inds_valid = np.flatnonzero(ids_veh_lead >= 0)6951# print ' main:ids_veh_lead',has_programmed,len(inds_valid), stops.ids_veh_lead[self.ids_stop]6952else:6953# no more leaders6954has_programmed = False6955# print '\n terminated vehicle man n_est_max',self.n_est_max6956# print ' inflows_sched=\n',self.inflows_sched69576958def note_person_entered(self, id_stop, n_pax):6959# here just estimate person flows6960self.inflows_person[id_stop] += n_pax69616962def note_vehs_ready_for_departure(self, id_stop, id_stop_target, time_est, n_veh):6963print 'note_vehs_ready_for_departure id_stop', id_stop, id_stop_target, time_est, n_veh6964self.ids_stop_target_current[id_stop] = id_stop_target6965self.duration_est_target_current[id_stop] = time_est6966self.numbers_veh_target_current[id_stop] = n_veh69676968def fit_vehicles(self, id_stop, n_veh, ind_time_arrival):6969"""6970Try to fit n_veh at stop id_stop for the arrival timeslot ind_time_arrival69716972Returns:6973flows_alloc: a vector that distributes the newly allocated vehicles6974over one or more timeslots.6975If the vector is of zero size means vehicles cannot be fit6976"""6977capa = self.flows_stop_max[id_stop]6978n_slots = int(np.ceil(float(n_veh)/capa))69796980n_slots_search_empty = int(self.time_search_empty.get_value()/self.time_update_flows.get_value()+0.5)69816982# extend search interval proportionally to the number of slots6983# idea behind is that room for more slots are more difficult to find6984n_slots_search = n_slots_search_empty + n_slots6985if self.debug > 1:6986print 'fit_vehicles n_veh', n_veh, 'n_slots', n_slots, 'capa_slots %.2f' % (capa * n_slots), 'at slot', ind_time_arrival, 'n_slots_search', n_slots_search6987ind_delay = 06988is_fit = False6989while (ind_delay < n_slots_search) & (not is_fit) & (ind_time_arrival + ind_delay + n_slots < self.n_est_max):69906991ind_time_arrival_sched = ind_time_arrival + ind_delay6992flows_sched = self.inflows_sched[id_stop, ind_time_arrival_sched:ind_time_arrival_sched+n_slots]69936994is_fit = np.sum(flows_sched) + n_veh < capa * n_slots6995print ' ind_delay', ind_delay, 'is_fit', is_fit, 'from', ind_time_arrival_sched, 'to', ind_time_arrival_sched + n_slots, 'flows_sched', flows_sched, # 'max',self.n_est_max6996ind_delay += 169976998# check if sufficient time-slots in the future are available6999# at estimated arrival time7000if self.debug > 2:7001print ' ind_time_arrival_sched', ind_time_arrival_sched, 'ind_delay', ind_delay7002print ' flows_sched ', flows_sched7003print ' n_slots ', n_slots, 'scheduled', np.sum(flows_sched), 'avail', capa * n_slots, 'is_fit', is_fit70047005if self.debug > 5:7006self.display_flows_est(id_stop, ind_time_arrival_sched, ind_time_arrival_sched+n_slots)70077008if is_fit:7009# n_veh fit in n_slots, considering also previous allocations70107011# distribute the n_veh over n_slots by filling up time slot to capacity7012capa_slot = capa7013flows_alloc = np.zeros(n_slots, dtype=np.int32)7014i_slot = 07015n_alloc_cum = 07016while (i_slot < n_slots) & (n_alloc_cum < n_veh):7017flow_sched = flows_sched[i_slot]7018capa_avail = capa_slot - flow_sched7019n_alloc = min(int(capa_avail), n_veh-n_alloc_cum)7020if self.debug > 5:7021print ' i_slot', i_slot, 'capa_slot %.2f' % capa_slot, 'capa_avail %.2f' % capa_avail, 'n_alloc', n_alloc, 'n_alloc_cum', n_alloc_cum7022if n_alloc > 0:7023flows_alloc[i_slot] += n_alloc7024n_alloc_cum += n_alloc7025if self.debug > 5:7026print ' add n_alloc', n_alloc, 'n_alloc_cum', n_alloc_cum7027# capacity of next slot is augmented by the7028# rest capacity of the present slot7029capa_slot = capa + (capa - n_alloc - flow_sched)70307031i_slot += 170327033# finally check whether all vehicle have been assigned7034if self.debug > 2:7035print ' n_alloc_cum', n_alloc_cum, 'n_veh', n_veh, 'flows_alloc', flows_alloc70367037# due to rounding errors the rest of the last slot may not be assigned7038if n_alloc_cum < n_veh:7039# assign the difference to the last slot7040flows_alloc[i_slot-1] += n_veh-n_alloc_cum70417042return flows_alloc, ind_time_arrival_sched70437044return [], -170457046def get_timeslot_occupation(self, id_stop, n_veh):7047"""7048NO LONGER USED!!7049Returns for stop id_stop:7050capacity limit at integer level7051the number of needed timeslots to process n_veh vehicles7052the required flows for each time slot7053"""7054capa = self.flows_stop_max[id_stop]70557056#capa_int = int(capa)70577058n_slots = n_slots = np.ceil(float(n_veh)/capa)70597060print 'get_timeslot_occupation n_veh', n_veh, 'capa_int', capa_int, 'n_slots', n_slots, 'rem', n_veh - n_slots*capa_int7061if n_slots == 0:7062flows = np.zeros(1, dtype=np.int32)7063else:7064flows = np.ones(n_slots, dtype=np.int32)*capa_int70657066flows[0] += n_veh - n_slots*capa_int70677068return n_slots, flows70697070def push_out_vehicles(self, process):7071"""7072Kick vehicles out of stops if vehicles are ready to depart.7073Kick out immediately if flow-conditions at target allow.7074If not, delay appropriately and kick out later.7075"""7076simtime = process.simtime7077time_update_flows = self.time_update_flows.get_value()70787079stops = self.get_stops()7080ids_stop_all = stops.get_ids()7081ids_stop = ids_stop_all[self.numbers_veh_target_current[ids_stop_all] > 0]7082print 'HC push_out_vehicles of %d stops' % (len(ids_stop))7083#vehicles = self.get_vehicles()70847085ids_stop_launched = []7086for id_stop, id_stop_target, duration_est, n_veh\7087in zip(7088ids_stop,7089self.ids_stop_target_current[ids_stop],7090self.duration_est_target_current[ids_stop],7091self.numbers_veh_target_current[ids_stop],7092):7093time_depart = self.times_departure_sched[id_stop]7094print '\n check id_stop', id_stop, 'id_stop_target', id_stop_target, 'n_veh', n_veh, 'dur %.2f' % duration_est, 't_dep', time_depart, 'simtime', simtime70957096if time_depart != -1:7097print ' delay has been programmed is_launch', simtime > time_depart7098if (simtime > time_depart):7099# simtime has reached scheduled departure time, so launch7100self.times_departure_sched[id_stop] = -17101is_launch = True7102else:7103# simtime has not yet reached scheduled departure time7104is_launch = False7105else:7106# no delay is programmed so check out availability of capacity7107time_arr_est = simtime + duration_est7108ind_time_arrival = int(duration_est/time_update_flows+0.5)71097110print ' time_arr_est', time_arr_est, 'ind_time_arrival', ind_time_arrival, 'in range', ind_time_arrival < self.n_est_max71117112if ind_time_arrival < self.n_est_max:7113# required number of free time slots for n_veh7114flows_alloc, ind_time_arrival_sched = self.fit_vehicles(id_stop_target, n_veh, ind_time_arrival)7115n_alloc = len(flows_alloc)7116if n_alloc > 0:7117# allocation successful7118self.inflows_sched[id_stop_target,7119ind_time_arrival_sched:ind_time_arrival_sched+n_alloc] += flows_alloc7120print ' schedule id_stop_target', id_stop_target, 'inflows_sched', self.inflows_sched[id_stop_target, ind_time_arrival_sched:ind_time_arrival_sched+n_alloc]7121if ind_time_arrival_sched == ind_time_arrival:7122print ' immediate launch'7123self.times_departure_sched[id_stop] = -17124is_launch = True7125else:7126# delayed launch, determine scheduled launch time7127self.times_departure_sched[id_stop] = simtime + \7128ind_time_arrival_sched * time_update_flows - duration_est7129print ' delayed launch: sched dep time', self.times_departure_sched[id_stop]7130is_launch = False71317132else:7133print 'WARNING: no capacity available at id_stop_target', id_stop_target, ' at this arrival time.'7134is_launch = False7135else:7136#7137print'WARNING: arrival time out of measurement range for id_stop_target', id_stop_target7138is_launch = True71397140if is_launch:7141# here stop is called to start vehicles7142# argument id_stop_target is passed to check if correct7143# vehicle platoon is started. Alternatively this could be done7144# by an order ID that has been placed when notifying7145# the presence of the platoons at exit7146ids_stop_launched.append(id_stop)7147stops.launch_vehs(id_stop, id_stop_target)7148self.numbers_veh_arr[id_stop_target] += n_veh71497150if len(ids_stop_launched) > 0:7151# vehicles from at least one stop have been launched7152self.ids_stop_target_current[ids_stop_launched] = -17153self.duration_est_target_current[ids_stop_launched] = 0.07154self.numbers_veh_target_current[ids_stop_launched] = -171557156return True7157else:7158return False71597160def equalize_empty_vehicles(self, process):7161"""7162from /home/joerg/projects/sumopy/sumopy-201022/plugins/hcprt/hcprt.py7163Launches empty vehicle trips from the stops with the highest7164vehicle supply to the station with the highest demand.7165"""7166n_move_eff_total = 07167simtime = process.simtime7168time_update_flows = self.time_update_flows.get_value()7169times_stop_to_stop = self.parent.times_stop_to_stop71707171stops = self.get_stops()7172ids_stop = stops.get_ids()7173n_stops = len(ids_stop)7174print 'equalize_empty_vehicles of %d stops' % n_stops71757176balances_veh = np.zeros(n_stops, dtype=np.float32)7177demands_veh = np.zeros(n_stops, dtype=np.float32)7178surpluses_veh = np.zeros(n_stops, dtype=np.int32)7179surpluses_veh_urgent = np.zeros(n_stops, dtype=np.int32)7180waittimes_max = np.zeros(n_stops, dtype=np.int32)7181vehicles = self.get_vehicles()71827183#ids_stop_launched = []7184i = 07185for id_stop, n_pax_wait, inflow_pax\7186in zip(7187ids_stop, stops.numbers_person_wait[ids_stop],7188# self.inflows_person[ids_stop]## no, not filtered7189stops.flows_person[ids_stop]):7190surplus_veh, surplus_veh_urgent = stops.get_surplus_veh(id_stop)71917192surplus_veh_future = self.numbers_veh_target_init[id_stop]7193#surplus_veh_future = np.sum(self.inflows_sched[id_stop, :])7194n_pax_future = 0.5*inflow_pax * self.n_est_max7195waittimes_max[i] = stops.get_waittime_max(id_stop, simtime)71967197surpluses_veh[i] = surplus_veh # this is current surplus, vehicles immediately available7198surpluses_veh_urgent[i] = surplus_veh_urgent # number of vehicles that need to be kicked out7199if self.debug > 2:7200print '\n sssssssssseek destinations for id_stop', id_stop72017202if self.debug > 5:7203self.display_flows_est(id_stop)72047205demands_veh[i] = -surplus_veh - surplus_veh_future + n_pax_wait + n_pax_future7206balances_veh[i] = 1000.0 * surplus_veh_urgent + 1.0 * \7207surplus_veh + surplus_veh_future - n_pax_wait - n_pax_future72087209if self.debug > 2:7210print ' surplus_veh', surplus_veh, 'surplus_future', surplus_veh_future, 'surplus_veh_urgent', surplus_veh_urgent7211print ' n_pax_wait ', n_pax_wait, 'n_pax_future', n_pax_future7212print ' balance ', balances_veh[i]7213print ' waittime_max ', waittimes_max[i]7214i += 172157216inds_sorted = np.argsort(balances_veh)72177218#surpluses_veh_emitters = surpluses_veh[inds_sorted[::-1]]7219if self.debug > 2:7220print ' Emitters sorted:'7221print ' ids_stop_sorted ', ids_stop[inds_sorted[::-1]]7222print ' surpluses_veh', surpluses_veh[inds_sorted[::-1]]7223print ' balances_sorted ', balances_veh[inds_sorted[::-1]]7224print ' max(surpluses_veh)', max(surpluses_veh)7225print ' >>>max(balances_veh)', max(balances_veh)72267227if (np.max(balances_veh) > 0) & (max(surpluses_veh) > 0):72287229i = 07230for id_stop_from, ind_from in zip(ids_stop[inds_sorted[::-1]], inds_sorted[::-1]):7231balance_from = balances_veh[ind_from]7232surplus_from = surpluses_veh[ind_from]7233surplus_veh_urgent_from = surpluses_veh_urgent[ind_from]7234demand_from = demands_veh[ind_from]72357236# distribute surplus on neares, most in need7237if (surplus_from >= 1) & (balance_from >= 1):7238if self.debug > 5:7239# ,'ind_from',ind_from,'continue?',(surplus_from >= 1) & (balance_from >= 1)7240print '\n potential emitter stop: id_stop_from', id_stop_from, 'surplus_from', surplus_from, 'balance_from', balance_from7241# there are empties to send away and positive balance7242utilities = np.zeros(n_stops, dtype=np.float32)7243numbers_move = np.zeros(n_stops, dtype=np.int32)7244j = 07245for id_stop_to, ind_to in zip(ids_stop[inds_sorted], inds_sorted):7246if id_stop_to != id_stop_from:7247demand_to = demands_veh[ind_to]7248balance_to = balances_veh[ind_to]7249waittime_max_to = waittimes_max[ind_to]7250time_to = times_stop_to_stop[id_stop_from, id_stop_to]72517252if self.debug > 5:7253print ' j', j, 'id_stop_from ', id_stop_from, 'id_stop_to', id_stop_to7254print ' balance_from', balance_from, 'balance_to', balance_to, 'min', -balance_to+0.5, surplus_from7255print ' demand_to', demand_to, 'waittime_max_to', waittime_max_to72567257if (surplus_from >= 1) & (balance_from >= 1) & (demand_to > 0):7258# the demand of the station is positive7259# here the utility looks at the maximum waiting times72607261# move the maximum possible number of available vehicles7262n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))7263if self.debug > 5:7264print ' potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to7265#utilities[j] = n_move+ self.constant_timeweight*time_to7266utilities[j] = float(n_move)/float(time_to)7267#utilities[j] = waittime_max_to/float(time_to)7268numbers_move[j] = n_move7269if self.debug > 5:7270print ' =>U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)72717272elif (surplus_veh_urgent_from > 0):7273# we have a stop where we want to send out the maximum number of vehicles7274# here the utility looks mainly at the highest demand of the destination72757276# if possible, move as much possible as there is demand7277#n_move = min(int(demand_to+0.5), surplus_veh_urgent_from)7278#n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))7279n_move = surplus_veh_urgent_from72807281# high balance means vehicle needs to be kicked out72827283if self.debug > 5:7284print ' forced potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to7285#utilities[j] = n_move+ self.constant_timeweight*time_to7286#utilities[j] = float(n_move)/float(time_to)7287utilities[j] = n_move*(demand_to)/float(time_to)7288numbers_move[j] = n_move7289if self.debug > 5:7290print ' =>U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)72917292j += 172937294ind_max = np.argmax(utilities)7295utility_max = utilities[ind_max]72967297# limit platoon length here7298# TODO: here shoulld be the max platoon length of the station??7299# or is this done in the platoon formation?7300n_move = min(numbers_move[ind_max], 8)73017302#min(numbers_move[ind_max], self.flows_stop_max[ids_stop[inds_sorted][ind_max]])7303if (n_move > 0) & (utility_max > 0):7304# there are some useful moves7305n_move_eff = stops.route_empties(7306id_stop_from, ids_stop[inds_sorted][ind_max], numbers_move[ind_max], simtime)7307if self.debug > 2:7308print ' moved', n_move_eff, 'of', numbers_move[ind_max], 'empty vehs from', id_stop_from, 'to', ids_stop[inds_sorted][ind_max], 'utility_max', utility_max73097310# continute till balance is zero?7311# indeed need to update balances7312surpluses_veh[ind_from] -= n_move_eff7313balances_veh[ind_from] -= n_move_eff7314#balances_veh[ind_max] += n_move7315balances_veh[inds_sorted[ind_max]] += n_move_eff7316demands_veh[inds_sorted[ind_max]] -= n_move_eff73177318# break7319else:7320break73217322i += 173237324return surpluses_veh, surpluses_veh_urgent, demands_veh, balances_veh, n_move_eff_total73257326def equalize_empty_vehicles_broke(self, process):7327"""7328Launches empty vehicle trips from the stops with the highest7329vehicle supply to the station with the highest demand.7330"""7331simtime = process.simtime7332time_update_flows = self.time_update_flows.get_value()7333times_stop_to_stop = self.parent.times_stop_to_stop73347335stops = self.get_stops()7336ids_stop = stops.get_ids()7337n_stops = len(ids_stop)7338print 'equalize_empty_vehicles of %d stops' % n_stops73397340balances_veh = np.zeros(n_stops, dtype=np.float32)7341demands_veh = np.zeros(n_stops, dtype=np.float32)7342surpluses_veh = np.zeros(n_stops, dtype=np.int32)7343surpluses_veh_urgent = np.zeros(n_stops, dtype=np.int32)7344waittimes_max = np.zeros(n_stops, dtype=np.int32)7345vehicles = self.get_vehicles()7346n_move_eff_total = 073477348#ids_stop_launched = []7349i = 07350for id_stop, n_pax_wait, inflow_pax\7351in zip(7352ids_stop, stops.numbers_person_wait[ids_stop],7353# self.inflows_person[ids_stop]## no, not filtered7354stops.flows_person[ids_stop]):7355surplus_veh, surplus_veh_urgent = stops.get_surplus_veh(id_stop)73567357surplus_veh_future = self.numbers_veh_target_init[id_stop]7358#surplus_veh_future = np.sum(self.inflows_sched[id_stop, :])7359n_pax_future = 0.5*inflow_pax * self.n_est_max7360waittimes_max[i] = stops.get_waittime_max(id_stop, simtime)73617362surpluses_veh[i] = surplus_veh # this is current surplus, vehicles immediately available7363surpluses_veh_urgent[i] = surplus_veh_urgent # number of vehicles that need to be kicked out7364if self.debug > 2:7365print '\n sssssssssseek destinations for id_stop', id_stop73667367if self.debug > 5:7368self.display_flows_est(id_stop)73697370demands_veh[i] = -surplus_veh - surplus_veh_future + n_pax_wait + n_pax_future7371# factor 1000 should move station with too many vehicles to the top of the queue7372# but current sort by current surplus_veh7373#balances_veh[i] = 1000.0 *surplus_veh_urgent + 1.0*surplus_veh + surplus_veh_future - n_pax_wait - n_pax_future7374balances_veh[i] = 1.0*surplus_veh + surplus_veh_future - n_pax_wait - n_pax_future7375if self.debug > 2:7376print ' surplus_veh', surplus_veh, 'surplus_future', surplus_veh_future, 'surplus_veh_urgent', surplus_veh_urgent7377print ' n_pax_wait ', n_pax_wait, 'n_pax_future', n_pax_future7378print ' balance ', balances_veh[i]7379print ' waittime_max ', waittimes_max[i]7380i += 173817382# sort per surpluses, because this is the most critical quantity7383# because if there are no vehicle, no vehicle cen be send7384#inds_sorted = np.argsort(balances_veh)7385inds_sorted = np.argsort(surpluses_veh*(surpluses_veh_urgent+1))7386#surpluses_veh_emitters = surpluses_veh[inds_sorted[::-1]]7387if self.debug > 2:7388print ' Emitters sorted:'7389print ' ids_stop_sorted ', ids_stop[inds_sorted[::-1]]7390print ' surpluses_veh', surpluses_veh[inds_sorted[::-1]]7391print ' surpluses_veh_urgent', surpluses_veh_urgent[inds_sorted[::-1]]73927393print ' balances_sorted ', balances_veh[inds_sorted[::-1]]7394print ' max(surpluses_veh)', max(surpluses_veh)7395print ' >>>max(balances_veh)', max(balances_veh)73967397if (np.max(balances_veh) > 0) & (max(surpluses_veh) > 0):7398if self.debug > 5:7399print ' start optimizing target', len(inds_sorted[::-1])7400i = 07401for id_stop_from, ind_from in zip(ids_stop[inds_sorted[::-1]], inds_sorted[::-1]):7402balance_from = balances_veh[ind_from]7403surplus_from = surpluses_veh[ind_from]7404surplus_veh_urgent_from = surpluses_veh_urgent[ind_from]7405demand_from = demands_veh[ind_from]7406print ' surplus_from', surplus_from, 'balance_from', balance_from7407# distribute surplus on neares, most in need7408if (surplus_from >= 1) & (balance_from >= 1):7409if self.debug > 5:7410# ,'ind_from',ind_from,'continue?',(surplus_from >= 1) & (balance_from >= 1)7411print '\n potential emitter stop: id_stop_from', id_stop_from, 'surplus_from', surplus_from, 'balance_from', balance_from7412# there are empties to send away and positive balance7413utilities = np.zeros(n_stops, dtype=np.float32)7414numbers_move = np.zeros(n_stops, dtype=np.int32)7415j = 07416for id_stop_to, ind_to in zip(ids_stop[inds_sorted], inds_sorted):7417demand_to = demands_veh[ind_to]7418balance_to = balances_veh[ind_to]7419waittime_max_to = waittimes_max[ind_to]7420time_to = times_stop_to_stop[id_stop_from, id_stop_to]74217422if self.debug > 5:7423print ' id_stop_from ', id_stop_from, 'id_stop_to', id_stop_to7424print ' balance_from', balance_from, 'balance_to', balance_to, 'min', -balance_to+0.5, surplus_from7425print ' demand_to', demand_to, 'waittime_max_to', waittime_max_to74267427if (surplus_from >= 1) & (balance_from >= 1) & (demand_to > 0):7428# the demand of the station is positive7429# here the utility looks at the maximum waiting times74307431# move the maximum possible number of available vehicles7432n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))7433if self.debug > 5:7434print ' potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to7435#utilities[j] = n_move+ self.constant_timeweight*time_to7436#utilities[j] = float(n_move)/float(time_to)7437utilities[j] = (waittime_max_to*demand_to)/float(time_to)7438numbers_move[j] = n_move7439if self.debug > 5:7440print ' ********'7441print ' U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)7442print ' ********'7443j += 174447445elif 0: # (surplus_veh_urgent_from> 0 ):7446# we have a stop where we want to send out the maximum number of vehicles7447# here the utility looks mainly at the highest demand of the destination74487449# if possible, move as much possible as there is demand7450#n_move = min(int(demand_to+0.5), surplus_veh_urgent_from)7451#n_move = min(int(demand_to+0.5), surplus_from, int(-demand_from+0.5))7452n_move = surplus_veh_urgent_from74537454# high balance means vehicle needs to be kicked out74557456if self.debug > 5:7457print ' forced potential n_move', n_move, 'vehs from stop', id_stop_from, 'to stop', id_stop_to7458#utilities[j] = n_move+ self.constant_timeweight*time_to7459#utilities[j] = float(n_move)/float(time_to)7460utilities[j] = n_move*(demand_to)/float(time_to)7461numbers_move[j] = n_move7462if self.debug > 5:7463print ' U=%.2f' % (utilities[j]), 'n_move', n_move, 'time_to %ds' % (time_to)7464j += 174657466ind_max = np.argmax(utilities)7467utility_max = utilities[ind_max]74687469# limit platoon length here7470# TODO: here shoulld be the max platoon length of the station??7471# or is this done in the platoon formation?7472n_move = min(numbers_move[ind_max], 8)7473if self.debug > 2:7474print ' utility_max %.0f' % utility_max, 'ind_max', ind_max, 'n_move', n_move7475#min(numbers_move[ind_max], self.flows_stop_max[ids_stop[inds_sorted][ind_max]])7476if n_move > 0:7477# there are some useful moves7478n_move_eff = stops.route_empties(7479id_stop_from, ids_stop[inds_sorted][ind_max], numbers_move[ind_max], simtime)7480if self.debug > 2:7481print ' => moved', n_move_eff, 'of', numbers_move[ind_max], 'empty vehs from', id_stop_from, 'to', ids_stop[inds_sorted][ind_max], 'utility_max', utility_max74827483# continute till balance is zero?7484# indeed need to update balances7485surpluses_veh[ind_from] -= n_move_eff7486# this is done in any case , does not matter when it becomes negative7487surpluses_veh_urgent[ind_from] -= n_move_eff7488balances_veh[ind_from] -= n_move_eff7489#balances_veh[ind_max] += n_move7490balances_veh[inds_sorted[ind_max]] += n_move_eff7491demands_veh[inds_sorted[ind_max]] -= n_move_eff7492n_move_eff_total += n_move_eff7493# break7494else:7495break74967497i += 174987499return surpluses_veh, surpluses_veh_urgent, demands_veh, balances_veh, n_move_eff_total75007501def display_flows_est(self, id_stop, timeind_begin=None, timeind_end=None):7502# print 'display_flows_est',id_stop7503n_char = 807504disp = np.zeros(n_char, dtype='S1')7505disp[:] = ' '7506flows = self.inflows_sched[id_stop, :]7507factor = 1.0/self.n_est_max*n_char7508inds = np.flatnonzero(flows)7509inds_disp = np.array(inds*factor, dtype=np.int32)7510disp[inds_disp] = self.inflows_sched[id_stop, inds]75117512print '%03d' % id_stop+(n_char-3)*'.'7513print string.join(disp, '')75147515disp = None7516if timeind_begin is not None:7517disp = np.zeros(n_char, dtype='S1')7518disp[:] = ' '7519disp[int(timeind_begin*factor+0.5)] = '>'7520if timeind_end is not None:7521disp[int(timeind_end*factor+0.5)] = '<'75227523if disp is not None:7524print string.join(disp, '')7525# print ' flows',flows7526# print ' inds',inds7527# print ' inds_disp',inds_disp75287529def pull_empty_leadvehs_old(self, ids_veh_lead, process):75307531n_timeslot_offset = 275327533#self.numbers_veh = np.zeros(np.max(ids)+1, dtype = np.int32)7534#self.numbers_person_wait = np.zeros(np.max(ids)+1, dtype = np.int32)75357536# inds_valid = np.flatnonzero( (vehicles.states[ids_veh_lead] == VEHICLESTATES['waiting'])\7537# & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0))7538vehicles = self.get_vehicles()7539stops = self.get_stops()7540print 'pull_empty_leadvehs', ids_veh_lead7541# print ' bordingstate',vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding']7542# print ' nowaits stop',stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] ==075437544times_stop_to_stop = self.parent.times_stop_to_stop75457546# get potential pull vehicles7547inds_valid = np.flatnonzero((vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding'])7548& (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0))75497550# print ' states',vehicles.states[ids_veh_lead], VEHICLESTATES['boarding']7551# print ' numbers_person_wait',stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]]7552# print ' &',(vehicles.states[ids_veh_lead] == VEHICLESTATES['boarding'])\7553# & (stops.numbers_person_wait[self.ids_stop_current[ids_veh_lead]] == 0)7554# print ' origins inds_valid',inds_valid7555if len(inds_valid) == 0:7556# print ' all stops busy'7557return False75587559#ids_veh_lead = ids_veh_lead[inds_valid]7560ids_stop_current = self.ids_stop_current[ids_veh_lead[inds_valid]]75617562# print ' available for pulling ids_veh_lead',ids_veh_lead7563# print ' ids_stop_current',ids_stop_current7564# get potential target station with demand7565demands = stops.numbers_person_wait[self.ids_stop]\7566- (0.5*stops.numbers_veh[self.ids_stop]7567+ self.numbers_veh_arr[self.ids_stop])7568inds_valid = np.flatnonzero(demands > 0)7569# print ' targets inds_valid',inds_valid7570if len(inds_valid) == 0:7571# print ' no demand'7572return False75737574ids_stop_target = self.ids_stop[inds_valid]7575demands = demands[inds_valid]75767577print ' ids_stop_current', ids_stop_current7578# print ' ids_stop_target',ids_stop_target7579# print ' demands',demands7580# calculate cost matrix with id_stop_current in rows and id_stop_target75817582#n_origin = len(ids_stop_current)7583#n_targets = len(ids_stop_target)7584times = times_stop_to_stop[ids_stop_current, :][:, ids_stop_target]7585times[times == 0] = 999997586timeweight = np.exp(-self.constant_timeweight.get_value() * times)7587#costs = times_stop_to_stop[ids_stop_current,:][:,ids_stop_target]7588#costs[costs == 0] = 999997589# print ' timeweight\n',timeweight75907591costs = timeweight * demands7592for id_stop_target, demand, number_veh, number_veh_arr\7593in zip(ids_stop_target, demands, stops.numbers_veh[ids_stop_target], self.numbers_veh_arr[ids_stop_target]):7594print ' id_stop_target', id_stop_target, 'dem', demand, 'n_veh', number_veh, 'n_veh_arr', number_veh_arr75957596#costs = np.zeros(costs.size, np.float32)-demands75977598inds_pull = np.argmax(costs, 1)7599# print ' costs\n',costs7600# print ' ->inds_pull,ids_stop_target',inds_pull,ids_stop_target[inds_pull]76017602durations_est = times_stop_to_stop[ids_stop_current, ids_stop_target[inds_pull]]7603# print ' duration_est, t_est_max',durations_est,self.n_est_max*self.time_update_flows.get_value()76047605inds_time_min = n_timeslot_offset+np.array(np.clip(np.array(1.0*durations_est/self.time_update_flows.get_value(7606), dtype=np.int32), 0, self.n_est_max-1-n_timeslot_offset), dtype=np.int32)7607inds_time_max = inds_time_min+27608# print ' inds_time_min',inds_time_min7609# print ' inds_time_max',inds_time_max76107611is_started = False7612for id_veh_lead, state, id_stop_current, id_stop_target, time_order, ind_min, ind_max, duration_est\7613in zip(7614ids_veh_lead[inds_valid],7615vehicles.states[ids_veh_lead],7616ids_stop_current,7617ids_stop_target[inds_pull],7618self.times_order[ids_veh_lead],7619inds_time_min,7620inds_time_max,7621durations_est,7622):76237624print ' check veh prt.%d' % (id_veh_lead), state, 'id_stop_current', id_stop_current, 'id_stop_target', id_stop_target76257626#VEHICLESTATES = {'init':0,'waiting':1,'boarding':2,'alighting':3,'emptytrip':4,'occupiedtrip':5,'forewarding':6}7627# if state == VEHICLESTATES['occupiedtrip']:76287629#ids_stop = list(self.ids_stop)7630# ids_stop.remove(id_stop)7631#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]7632#ids_stop [np.argmax(costs)]7633inds_time = np.arange(ind_min, ind_max)7634costs = self.inflows_sched[id_stop_current, inds_time]7635ind_time_depart = inds_time[np.argmin(costs)]76367637self.inflows_sched[id_stop_target, ind_time_depart] += 17638time_depart = process.simtime + ind_time_depart*self.time_update_flows.get_value()-duration_est76397640# this is a workarouned that vehicle does first reach the stopline7641# before it gets rescheduled...try with stoplinecheck76427643# if time_depart < process.simtime+15:7644# time_depart = process.simtime+157645# print ' ind_time_depart, time_arr, duration_est',ind_time_depart,process.simtime + ind_time_depart*self.time_update_flows.get_value(),duration_est7646# print ' time_order' ,time_order,'time_depart',time_depart,'delay',time_depart-time_order76477648stops.program_leadveh(id_stop_current, id_veh_lead, id_stop_target, time_depart)7649self.numbers_veh_arr[id_stop_target] += 17650is_started = True76517652return is_started76537654def init_trip_occupied(self, id_veh, id_stop_from, id_stop_to, time_order):7655"""7656Called from the stop when a vehicle in the berth initiate a trip with7657a the target destination of persons who entered7658"""7659print 'init_trip_occupied to', id_stop_to7660# search closest stop7661#self.are_emptytrips[id_veh] = False76627663self.numbers_veh_target_init[id_stop_to] += 176647665#self.ids_stop_current[id_veh] = id_stop_from7666#self.ids_stop_target[id_veh] = id_stop_to7667#self.times_order[id_veh] = time_order76687669def init_trip(self, id_veh, id_stop, id_stop_to, time_order):7670"""7671Called from the stop when a vehicle in the berth initiate a trip with7672a the target destination7673"""7674print 'init_trip_empty to', id_stop_to76757676self.numbers_veh_target_init[id_stop_to] += 176777678def init_trip_empty_old(self, id_veh, id_stop, id_stop_to, time_order):7679"""7680Called from the stop when a vehicle in the berth initiate a trip with7681a the target destination defined by the vehicle management7682"""7683print 'init_trip_empty to', id_stop_to76847685self.numbers_veh_target_init[id_stop_to] += 176867687#self.ids_stop_current[id_veh] = id_stop7688#self.times_order[id_veh] = time_order76897690def indicate_trip_empty_old(self, id_veh, id_stop, time_order):7691# print 'indicate_trip_empty id_veh,id_stop',id_veh,id_stop7692# search closest stop7693self.ids_stop_current[id_veh] = id_stop7694self.times_order[id_veh] = time_order76957696def get_stop_emptytrip_old(self, id_stop):7697stops = self.get_stops()7698ids_stop = list(self.ids_stop)7699ids_stop.remove(id_stop)7700costs = (stops.numbers_person_wait[ids_stop]-stops.numbers_veh[ids_stop] -7701self.numbers_veh_arr[ids_stop])/self.parent.times_stop_to_stop[id_stop, ids_stop]77027703return ids_stop[np.argmax(costs)]77047705def conclude_trip(self, id_veh, id_stop, is_final_dest=False):7706#self.ids_stop_target[id_veh] = -177077708if is_final_dest:7709# counts vehvicles to target since launche from stop7710self.numbers_veh_arr[id_stop] += 177117712# counts vehicles to target since programming in berth7713# this count is anticipating earlier the number of vehicle going to7714# each stop7715self.numbers_veh_target_init[id_stop] -= 177167717# measures actually arrived vehicles at stop7718# accumulates counts over one flow measurement interval7719self.log_inflows_temp[id_stop] += 1772077217722class HcPrtService(SimobjMixin, DemandobjMixin, cm.BaseObjman):7723def __init__(self, ident, simulation=None,7724name='HC PRT service', info='High capacity PRT service',7725**kwargs):7726# print 'PrtService.__init__',name77277728self._init_objman(ident=ident, parent=simulation,7729name=name, info=info, **kwargs)77307731attrsman = self.set_attrsman(cm.Attrsman(self))77327733# make PRTservice a demand object as link7734self.get_scenario().demand.add_demandobject(obj=self)77357736self._init_attributes()7737self._init_constants()77387739def get_scenario(self):7740return self.parent.parent77417742def _init_attributes(self):7743print 'HcPrtService._init_attributes'7744attrsman = self.get_attrsman()7745scenario = self.get_scenario()7746# here we ged classes not vehicle type7747# specific vehicle type within a class will be generated later7748modechoices = scenario.net.modes.names.get_indexmap()77497750# print ' modechoices',modechoices7751self.id_prtmode = attrsman.add(am.AttrConf('id_prtmode', modechoices['custom1'],7752groupnames=['options'],7753choices=modechoices,7754name='Mode',7755info='PRT transport mode (or vehicle class).',7756))77577758self.prtstops = attrsman.add(cm.ObjConf(PrtPlatoonStops('prtstops', self)))7759self.compressors = attrsman.add(cm.ObjConf(Compressors('compressors', self)))7760self.decompressors = attrsman.add(cm.ObjConf(Decompressors('decompressors', self)))7761self.mergenodes = attrsman.add(cm.ObjConf(Mergenodes('mergenodes', self)))7762self.prtvehicles = attrsman.add(cm.ObjConf(PrtVehicles('prtvehicles', self)))7763self.vehicleman = attrsman.add(cm.ObjConf(VehicleMan('vehicleman', self)))77647765#self.demo = attrsman.add( cm.ObjConf(TraciDemo('demo',self)))77667767# --------------------------------------------------------------------7768# prt transit table7769# attention: prttransits will be a child of virtual pop,7770# and a link from prt service77717772# if not hasattr(self,'prttransit'):7773virtualpop = self.get_scenario().demand.virtualpop7774prttransits = virtualpop.get_plans().add_stagetable('hcprttransits', HcPrtTransits)77757776print ' prttransits =', prttransits, id(prttransits)7777# add attribute as link7778# self.prttransits = attrsman.add(\7779# cm.ObjConf(prttransits,is_child = False ),7780# is_overwrite = False,)7781prttransits.set_prtservice(self)77827783prtstrategy = virtualpop.get_strategies().add_strategy(7784'hcprt', HcPrtStrategy, np.array([208, 50, 156, 230], np.float32)/255)7785# self.prttransits = attrsman.add(\7786# cm.ObjConf(prttransits,is_child = False ),7787# is_overwrite = False,)7788prtstrategy.set_prtservice(self)77897790# temporary attrfix7791#prtserviceconfig = self.parent.get_attrsman().prtservice7792#prtserviceconfig.groupnames = []7793#prtserviceconfig.add_groupnames(['demand objects'])77947795def _init_constants(self):7796# print 'PrtService._init_constants',self,self.parent7797attrsman = self.get_attrsman()7798self.times_stop_to_stop = None7799self.fstar = None7800self._results = None78017802attrsman.do_not_save_attrs(['times_stop_to_stop', 'fstar', '_results'7803'times_stop_to_stop', 'ids_edge_to_ids_prtstop',7804])78057806def get_vtypes(self):78077808ids_vtypes = set(self.prtvehicles.ids_vtype.get_value())7809return ids_vtypes78107811def get_writexmlinfo(self, is_route=False, is_plain=False, **kwargs):7812"""7813Returns three array where the first array is the7814begin time of the first vehicle and the second array is the7815write function to be called for the respectice vehicle and7816the third array contains the vehicle ids78177818Method used to sort trips when exporting to route or trip xml file7819"""7820print 'PRT.get_writexmlinfo'78217822if is_plain:7823return [], [], []78247825# time of first PRT vehicle(s) to be inserted7826virtualpop = self.get_scenario().demand.virtualpop7827t_start = virtualpop.get_time_depart_first()78287829#t_start = 0.07830# time between insertion of consecutive vehicles at same stop7831t_delta = 10 # s78327833n_veh = len(self.prtvehicles)7834times_depart = np.zeros(n_veh, dtype=np.int32)7835writefuncs = np.zeros(n_veh, dtype=np.object)7836writefuncs[:] = self.write_prtvehicle_xml7837ids_veh = self.prtvehicles.get_ids()78387839id_edge_prev = -17840i = 07841t0 = t_start7842for id_edge in self.prtvehicles.ids_currentedge[ids_veh]:7843# print ' id_edge, t_start, id_edge_prev',id_edge, t0, id_edge_prev7844times_depart[i] = t07845t0 += t_delta7846if id_edge != id_edge_prev:7847t0 = t_start7848id_edge_prev = 1*id_edge7849i += 178507851return times_depart, writefuncs, ids_veh78527853def write_prtvehicle_xml(self, fd, id_veh, time_begin, indent=2):7854# print 'write_prtvehicle_xml',id_veh, time_begin7855# TODO: actually this should go in prtvehicles7856#time_veh_wait_after_stop = 36007857scenario = self.get_scenario()7858net = scenario.net78597860#lanes = net.lanes7861edges = net.edges7862#ind_ride = rides.get_inds(id_stage)7863#id_veh = rides.ids_veh[id_stage]7864prtvehicles = self.prtvehicles7865#ptstops = net.ptstops7866#prtstops = self.parent.prtstops7867#ids_prtstop = prtstops.get_ids()7868#ids_ptstop = prtstops.ids_ptstop[id_stop]7869# lanes.ids_edge[ptstops.ids_lane[ids_ptstop]],7870#id_lane_from = parking.ids_lane[id_parking_from]7871#laneindex_from = lanes.indexes[id_lane_from]7872#pos_from = parking.positions[id_parking_from]78737874#id_parking_to = rides.ids_parking_to[id_stage]7875#id_lane_to = parking.ids_lane[id_parking_to]7876#laneindex_to = lanes.indexes[id_lane_to]7877#pos_to = parking.positions[id_parking_to]78787879# write unique veh ID to prevent confusion with other veh declarations7880fd.write(xm.start('vehicle id="%s"' % prtvehicles.get_id_sumo(id_veh), indent+2))78817882fd.write(xm.num('depart', '%d' % time_begin))7883fd.write(xm.num('type', scenario.demand.vtypes.ids_sumo[prtvehicles.ids_vtype[id_veh]]))7884fd.write(xm.num('line', prtvehicles.get_id_line_xml()))7885fd.write(xm.num('departPos', 'base'))7886fd.write(xm.num('departLane', 2))7887fd.write(xm.stop())78887889# write route7890fd.write(xm.start('route', indent+4))7891# print ' edgeindex[ids_edge]',edgeindex[ids_edge]7892fd.write(xm.arr('edges', [edges.ids_sumo[prtvehicles.ids_currentedge[id_veh]]]))78937894# does not seem to have an effect, always starts at base????7895#fd.write(xm.num('departPos', 'base'))7896#fd.write(xm.num('departLane', 2 ))7897fd.write(xm.stopit())78987899# write depart stop7900# fd.write(xm.start('stop',indent+4))7901#fd.write(xm.num('lane', edges.ids_sumo[lanes.ids_edge[id_lane_from]]+'_%d'%laneindex_from ))7902#fd.write(xm.num('duration', time_veh_wait_after_stop))7903#fd.write(xm.num('startPos', pos_from ))7904#fd.write(xm.num('endPos', pos_from + parking.lengths[id_parking_from]))7905#fd.write(xm.num('triggered', "True"))7906# fd.write(xm.stopit())79077908fd.write(xm.end('vehicle', indent+2))79097910# def make_stops_and_vehicles(self, n_veh = -1):7911# self.prtstops.make_from_net()7912# self.prtvehicles.make(n_veh)7913# self.make_times_stop_to_stop()79147915def prepare_sim(self, process):7916print 'prepare_sim', self.ident7917# print ' self.times_stop_to_stop',self.times_stop_to_stop79187919if self.fstar is None:7920self.make_fstar()79217922if self.times_stop_to_stop is None:7923print ' times_stop_to_stop'7924self.make_times_stop_to_stop()79257926updatedata = self.prtvehicles.prepare_sim(process)7927updatedata += self.prtstops.prepare_sim(process)7928#updatedata += self.compressors.prepare_sim(process)7929#updatedata += self.decompressors.prepare_sim(process)7930updatedata += self.mergenodes.prepare_sim(process)7931updatedata += self.vehicleman.prepare_sim(process)7932#7933#updatedata += self.demo.prepare_sim(process)7934# print 'PrtService.prepare_sim updatedata',updatedata7935return updatedata79367937def make_fstar(self, is_update=False):7938if (self.fstar is None) | is_update:7939self.fstar = self.get_fstar()7940self.edgetimes = self.get_times(self.fstar)79417942def get_route(self, id_fromedge, id_toedge):7943"""7944Centralized function to determin fastest route between7945PRT network edges.7946"""7947duration, route = get_mincostroute_edge2edge(id_fromedge, id_toedge,7948weights=self.edgetimes, fstar=self.fstar)79497950return route, duration79517952def make_times_stop_to_stop(self, fstar=None, times=None):7953print 'make_times_stop_to_stop'7954log = self.get_logger()7955if fstar is None:7956if self.fstar is None:7957self.make_fstar()79587959fstar = self.fstar # get_fstar()7960times = self.edgetimes # self.get_times(fstar)79617962if len(fstar) == 0:7963self.times_stop_to_stop = [[]]7964return79657966ids_prtstop = self.prtstops.get_ids()7967if len(ids_prtstop) == 0:7968self.get_logger().w('WARNING: no PRT stops, no plans. Generate them!')7969return79707971ids_edge = self.prtstops.get_edges(ids_prtstop)79727973# check if all PRT stop edges are in fstar7974ids_ptstop = self.prtstops.ids_ptstop[ids_prtstop] # for debug only7975is_incomplete_fstar = False7976for id_edge, id_stop, id_ptstop in zip(ids_edge, ids_prtstop, ids_ptstop):7977# print ' Found PRT stop %d, PT stop %d with id_edge %d '%(id_stop,id_ptstop, id_edge)7978if not fstar.has_key(id_edge):7979print 'WARNING in make_times_stop_to_stop: PRT stop %d, PT stop %d has no id_edge %d in fstar' % (id_stop, id_ptstop, id_edge)7980is_incomplete_fstar = True79817982# check if fstar is complete (all to edges are in keys)7983ids_fromedge_set = set(fstar.keys())7984ids_sumo = self.get_scenario().net.edges.ids_sumo7985for id_fromedge in ids_fromedge_set:7986if not ids_fromedge_set.issuperset(fstar[id_fromedge]):7987is_incomplete_fstar = True7988ids_miss = fstar[id_fromedge].difference(ids_fromedge_set)7989print 'WARNING in make_times_stop_to_stop: incomplete fstar of id_fromedge = %d, %s' % (id_fromedge, ids_sumo[id_fromedge])7990for id_edge in ids_miss:7991print ' missing', id_edge, ids_sumo[id_edge]79927993if is_incomplete_fstar:7994return79957996# print ' ids_prtstop,ids_edge',ids_prtstop,ids_edge7997n_elem = np.max(ids_prtstop)+17998stop_to_stop = np.zeros((n_elem, n_elem), dtype=np.int32)79998000ids_edge_to_ids_prtstop = np.zeros(np.max(ids_edge)+1, dtype=np.int32)8001ids_edge_to_ids_prtstop[ids_edge] = ids_prtstop80028003ids_edge_target = set(ids_edge)80048005for id_stop, id_edge in zip(ids_prtstop, ids_edge):8006# print ' route for id_stop, id_edge',id_stop, id_edge80078008# remove origin from target8009ids_edge_target.discard(id_edge)80108011costs, routes = edgedijkstra(id_edge,8012ids_edge_target=ids_edge_target,8013weights=times, fstar=fstar8014)80158016# print ' ids_edge_target',ids_edge_target8017# print ' costs\n', costs8018# print ' routes\n', routes8019# for route in routes:8020# if len(route)==0:8021# print 'WARNING in make_times_stop_to_stop: empty route'8022# else:8023# print ' found route to id_edge, id_stop',route[-1],ids_edge_to_ids_prtstop[route[-1]],len(route)80248025if costs is not None:8026# TODO: could be vectorialized, but not so easy8027for id_edge_target in ids_edge_target:8028#stop_to_stop[id_edge,id_edge_target] = costs[id_edge_target]8029# 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]8030# print ' stop_orig,costs ',ids_edge_to_ids_prtstop[id_edge],ids_sumo[id_edge]8031# print ' stop_target',ids_edge_to_ids_prtstop[id_edge_target],ids_sumo[id_edge_target]8032# print ' costs ',costs[id_edge_target]8033# stop_to_stop[ids_edge_to_ids_prtstop[[id_edge,id_edge_target]]]=costs[id_edge_target]8034if id_edge_target in costs:8035stop_to_stop[ids_edge_to_ids_prtstop[id_edge],8036ids_edge_to_ids_prtstop[id_edge_target]] = costs[id_edge_target]8037else:8038print 'WARNING in make_times_stop_to_stop: unreacle station id_fromedge = %d, %s' % (id_edge_target, ids_sumo[id_edge_target])8039is_incomplete_fstar = True80408041# put back origin to targets (probably not the best way)8042ids_edge_target.add(id_edge)8043# print ' ids_edge_target (all)',ids_edge_target80448045# print ' stop_to_stop',stop_to_stop8046# TODO: here we could also store the routes80478048if is_incomplete_fstar:8049return False80508051self.times_stop_to_stop = stop_to_stop8052self.ids_edge_to_ids_prtstop = ids_edge_to_ids_prtstop8053print ' times_stop_to_stop=\n', self.times_stop_to_stop8054return True80558056def get_fstar(self):8057"""8058Returns the forward star graph of the network as dictionary:8059fstar[id_fromedge] = set([id_toedge1, id_toedge2,...])8060"""8061print 'get_fstar'8062net = self.get_scenario().net8063# prt mode8064id_mode = self.id_prtmode80658066#ids_edge = self.get_ids()8067#fstar = np.array(np.zeros(np.max(ids_edge)+1, np.obj))8068fstar = {}8069connections = net.connections8070lanes = net.lanes80718072#inds_con = connections.get_inds()8073#ids_fromlane = connections.ids_fromlane.get_value()[inds_con]8074#ids_tolane = connections.ids_tolane.get_value()[inds_con]80758076ids_con = connections.get_ids()8077ids_fromlane = connections.ids_fromlane[ids_con]8078ids_tolane = connections.ids_tolane[ids_con]80798080ids_mainmode_from = lanes.ids_mode[ids_fromlane]8081ids_mainmode_to = lanes.ids_mode[ids_tolane]80828083#ids_modes_allow_from = lanes.ids_modes_allow[ids_fromlane]8084#ids_modes_allow_to = lanes.ids_modes_allow[ids_tolane]80858086ids_fromedge = lanes.ids_edge[ids_fromlane]8087ids_toedge = lanes.ids_edge[ids_tolane]8088# print ' ids_fromedge',ids_fromedge8089# print ' ids_modes_allow',ids_modes_allow80908091for id_fromedge, id_toedge, id_mode_allow_from, id_mode_allow_to, id_fromlane, id_tolane in\8092zip(ids_fromedge, ids_toedge, ids_mainmode_from, ids_mainmode_to,8093ids_fromlane, ids_tolane):80948095if id_mode_allow_from == id_mode:8096if id_mode_allow_to == id_mode:80978098if fstar.has_key(id_fromedge):8099fstar[id_fromedge].add(id_toedge)8100else:8101fstar[id_fromedge] = set([id_toedge])8102# if id_fromedge == 14048:8103# print ' id_fromedge, id_toedge',id_fromedge, id_toedge,fstar.has_key(id_fromedge)8104# print ' id_fromlane, id_tolane ',id_fromlane, id_tolane8105# print ' id_mode_allow_from, id_mode_allow_to',id_mode_allow_from, id_mode_allow_to81068107# for id_fromedge, id_toedge,ids_mode_allow_from,id_modes_allow_to in\8108# zip(ids_fromedge, ids_toedge, ids_modes_allow_from, ids_modes_allow_to):8109# if len(ids_mode_allow_from)>0:8110# if ids_mode_allow_from[-1] == id_mode:8111# if len(id_modes_allow_to)>0:8112# if id_modes_allow_to[-1] == id_mode:8113#8114# if fstar.has_key(id_fromedge):8115# fstar[id_fromedge].add(id_toedge)8116# else:8117# fstar[id_fromedge]=set([id_toedge])81188119return fstar81208121def get_times(self, fstar):8122"""8123Returns freeflow travel times for all edges.8124The returned array represents the speed and the index corresponds to8125edge IDs.81268127"""8128if len(fstar) == 0:8129return []81308131net = self.get_scenario().net8132#id_mode = net.modes.get_id_mode(mode)8133id_mode = self.id_prtmode8134# print 'get_times id_mode,is_check_lanes,speed_max',id_mode,is_check_lanes,speed_max8135ids_edge = np.array(fstar.keys(), dtype=np.int32)81368137times = np.array(np.zeros(np.max(ids_edge)+1, np.float32))8138speeds = net.edges.speeds_max[ids_edge]81398140# limit allowed speeds with max speeds of mode8141speeds = np.clip(speeds, 0.0, net.modes.speeds_max[id_mode])81428143times[ids_edge] = net.edges.lengths[ids_edge]/speeds81448145return times81468147def config_results(self, results):8148print 'HcPrtService.config_results', results, id(results)8149# keep a link to results here because needed to8150# log data during simulation8151# this link should not be followed during save process8152#self._results = results81538154tripresults = res.Tripresults('hcprttripresults', results,8155self.prtvehicles,8156self.get_scenario().net.edges,8157name='HC PRT trip results',8158info='Table with simulation results for each PRT vehicle. The results refer to the vehicle journey over the entire simulation period.',8159)8160results.add_resultobj(tripresults, groupnames=['Trip results'])81618162prtstopresults = HcPrtStopResults('hcprtstopresults', results, self.prtstops)8163results.add_resultobj(prtstopresults, groupnames=['HCPRT stop results'])81648165# def get_results(self):8166# return self._results81678168def process_results(self, results, process=None):8169pass817081718172class HcPrtStopResults(am.ArrayObjman):8173def __init__(self, ident, results, prtstops,8174name='HC PRT Stop results',8175info='Table with simulation results of PRT platoon stops generated from vehicle management.',8176**kwargs):81778178self._init_objman(ident=ident,8179parent=results, # main results object8180info=info,8181name=name,8182**kwargs)81838184self.add(cm.AttrConf('time_step', 5.0,8185groupnames=['parameters'],8186name='Step time',8187info="Time of one recording step.",8188unit='s',8189))81908191self.add(cm.ObjConf(prtstops, is_child=False, # groupnames = ['_private']8192))81938194self.add_col(am.IdsArrayConf('ids_stop', prtstops,8195groupnames=['state'],8196is_index=True,8197name='PRT stop ID',8198info='ID of PRT stop.',8199))82008201attrinfos = [8202('inflows_veh', {'name': 'Vehicle in-flows', 'unit': '1/s',8203'dtype': np.float32, 'info': 'Vehicle flow into the stop over time.'}),8204('inflows_veh_sched', {'name': 'Sched. vehicle in-flows', 'unit': '1/s',8205'dtype': np.float32, 'info': 'Scheduled vehicle flow into the stop over time.'}),8206('inflows_person', {'name': 'Person in-flows', 'unit': '1/s',8207'dtype': np.float32, 'info': 'Person flow into the stop over time.'}),8208('numbers_person_wait', {'name': 'waiting person', 'dtype': np.int32,8209'info': 'Number of waiting persons at stop over time.'}),8210('waittimes_tot', {'name': 'total wait time', 'dtype': np.float32,8211'info': 'Wait times of all waiting persons at a stop over time.'}),8212]82138214for attrname, kwargs in attrinfos:8215self.add_resultattr(attrname, **kwargs)82168217def get_dimensions(self):8218return len(self), len(self.inflows_veh.get_default())82198220def get_prtstops(self):8221return self.prtstops.get_value()8222# return self.ids_stop.get_linktab()82238224def init_recording(self, n_timesteps, time_step):8225print 'HC init_recording n_timesteps, time_step', n_timesteps, time_step, len(self.ids_stop.get_linktab().get_ids())8226print ' stops instance', self.prtstops.get_value(), self.ids_stop.get_linktab(), id(self.prtstops.get_value()), id(self.ids_stop.get_linktab())8227self.clear()82288229self.time_step.set_value(time_step)82308231for attrconfig in self.get_stopresultattrconfigs():8232# print ' reset attrconfig',attrconfig.attrname8233attrconfig.set_default(np.zeros(n_timesteps, dtype=attrconfig.get_dtype()))8234attrconfig.reset()8235# print ' default=',attrconfig.get_default(),attrconfig.get_default().dtype8236ids_stop = self.get_prtstops().get_ids()8237# print ' ids_stop',ids_stop8238self.add_rows(n=len(ids_stop), ids_stop=ids_stop)82398240def record(self, timestep, ids, **kwargs):82418242inds = self.ids_stop.get_linktab().get_inds(ids)8243timestep_int = int(timestep)8244for attrname, values in kwargs.iteritems():8245print ' record', attrname, 'dtype', values.dtype, values.shape, 'array', getattr(self, attrname).get_value().dtype, 'shape', getattr(self, attrname).get_value().shape8246# print ' inds',type(inds),inds.dtype,8247getattr(self, attrname).get_value()[inds, timestep_int] = values82488249def get_stopresultattrconfigs(self):8250return self.get_attrsman().get_group_attrs('PRT results').values()82518252def get_persons(self):8253return self.ids_person.get_linktab()82548255def add_resultattr(self, attrname, **kwargs):8256self.add_col(am.ArrayConf(attrname, 0, groupnames=['PRT results', 'results'], **kwargs))82578258def import_xml(self, sumo, datapaths):8259# no imports, data come from prtservice8260pass826182628263