Path: blob/main/tools/contributed/sumopy/coremodules/simulation/sumo.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 sumo.py15# @author Joerg Schweizer16# @date 20121718from agilepy.lib_base.processes import Process, CmlMixin, ff, call, P, filepathlist_to_filepathstring, Options19from coremodules.scenario.scenario import load_scenario20from results import Simresults21from coremodules.network.network import SumoIdsConf22import agilepy.lib_base.xmlman as xm23import agilepy.lib_base.arrayman as am24import agilepy.lib_base.classman as cm25import numpy as np26from coremodules.modules_common import *27import os28import sys29import string30import time31import shutil # for deleting directory trees32from collections import OrderedDict33from xml.sax import saxutils, parse, handler34if __name__ == '__main__':35try:36APPDIR = os.path.dirname(os.path.abspath(__file__))37except:38APPDIR = os.path.dirname(os.path.abspath(sys.argv[0]))39SUMOPYDIR = os.path.join(APPDIR, '..', '..')40sys.path.append(SUMOPYDIR)41try:42if 'SUMO_HOME' in os.environ:43tools = os.path.join(os.environ['SUMO_HOME'], 'tools')44sys.path.append(tools)45else:46print("please declare environment variable 'SUMO_HOME'")4748import traci49import traci.constants as tc505152except:53print 'WARNING: No module traci in syspath. Please provide SUMO_HOME.'5455traci = None5657#from agilepy.lib_base.misc import get_inversemap58#from agilepy.lib_base.geometry import find_area596061def write_netconfig(filename_netconfig, filename_net,62filename_routes='',63filename_poly=None,64dirname_output='',65starttime=None, stoptime=None,66time_step=1.0,67time_to_teleport=-1,68pedestrian_model='None',69width_sublanes=-1.0,70filename_ptstops=None,71filepath_output_vehroute=None,72filepath_output_tripinfo=None,73is_tripdata_unfinished=False,74filepath_output_edgedata=None,75filepath_output_lanedata=None,76filepath_output_edgeemissions=None,77filepath_output_laneemissions=None,78filepath_output_edgenoise=None,79filepath_output_lanenoise=None,80filepath_output_electricenergy=None,81filepath_output_fcd=None,82filepath_output_summary=None,83freq=60,84is_exclude_emptyedges=False,85is_exclude_emptylanes=False,86is_ignore_route_errors=True,87filepath_gui=None,88seed=1025,89is_openscenegraph=False,90width_pedestrian_striping=0.49,91slowdownfactor_pedestrian_striping=0.2,92jamtime_pedestrian_striping=20,93jamtime_pedestrian_crossing_striping=10,94is_collission_check_junctions=True,95is_ignore_accidents=False,96collission_action='teleport',97is_ballistic_integrator=False,98is_rerouting=False,99probability_rerouting=0.0,100is_deterministic_rerouting=False,101period_rerouting=0,102preperiod_rerouting=60,103adaptationinterval_rerouting=1,104adaptationweight_rerouting=0.0,105adaptationsteps_rerouting=180,106taxiservice=None,107):108"""109filename_netconfig = output filename of network config file without path110filename_net = input filename of network file without path111filename_rou = input filename of routes file without path112filename_poly = input filename of polygons file without path113dirname_output = directory where config, network, route and poly file reside114"""115# print 'write_netconfig >>%s<<'%filename_netconfig116# print ' filename_poly=>>%s<<'%filename_poly117if dirname_output:118filepath_netconfig = os.path.join(dirname_output, filename_netconfig)119else:120filepath_netconfig = filename_netconfig121122if (filepath_output_edgedata is not None)\123| (filepath_output_lanedata is not None)\124| (filepath_output_edgeemissions is not None)\125| (filepath_output_laneemissions is not None)\126| (filepath_output_edgenoise is not None)\127| (filepath_output_lanenoise is not None)\128| (filepath_output_electricenergy is not None):129# filename of additional files:130filename_add = string.join(filename_netconfig.split('.')[:-2]+['outc.xml'], '.')131filepath_add = os.path.join(dirname_output, filename_add)132# print ' filepath_add',filepath_add133else:134filename_add = None135136simfile = open(filepath_netconfig, 'w')137138simfile.write(139"""<?xml version="1.0"?>140<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.sf.net/xsd/sumoConfiguration.xsd">141<input>\n""")142143simfile.write(' <net-file value="%s"/>\n' % filename_net)144145if filename_routes != "":146simfile.write(' <route-files value="%s"/>\n' % filename_routes)147148# print ' filename_add',filename_add149# print ' filepath_add',filepath_add150simfile.write(' <additional-files value="')151152filenames_add = set([filename_poly, filename_add, filename_ptstops])153filenames_add.discard(None)154filenames_add = list(filenames_add)155156if len(filenames_add) > 0:157for filename in filenames_add[:-1]:158simfile.write('%s,' % filename)159simfile.write('%s' % filenames_add[-1])160161simfile.write('" />\n')162simfile.write('</input>\n')163164if (starttime is not None) & (stoptime is not None):165simfile.write(166"""167<time>168<begin value="%s"/>169<end value="%s"/>170</time>171""" % (starttime, stoptime))172173simfile.write('<time-to-teleport value="%s"/>\n' % time_to_teleport)174simfile.write('<seed value="%s"/>\n' % seed)175simfile.write('<step-length value="%s"/>\n' % time_step)176177simfile.write('<ignore-route-errors value="%s"/>\n' % is_ignore_route_errors)178179if is_ballistic_integrator:180simfile.write('<step-method.ballistic value="True"/>\n')181182if width_sublanes > 0:183simfile.write('<lateral-resolution value="%s"/>\n' % width_sublanes)184# not (yet) recogniced...move to cml185if pedestrian_model != 'None':186simfile.write('<pedestrian.model value="%s"/>\n' % pedestrian_model)187if pedestrian_model == 'striping':188simfile.write('<pedestrian.striping.stripe-width value="%s"/>\n' % width_pedestrian_striping)189simfile.write('<pedestrian.striping.dawdling value="%s"/>\n' % slowdownfactor_pedestrian_striping)190simfile.write('<pedestrian.striping.jamtime value="%s"/>\n' % jamtime_pedestrian_striping)191192# from 1.3.0193#simfile.write('<pedestrian.striping.jamtime.crossing value="%s"/>\n'%jamtime_pedestrian_crossing_striping)194195simfile.write('<collision.check-junctions value="%s"/>\n' % is_collission_check_junctions)196simfile.write('<collision.action value="%s"/>\n' % collission_action)197#simfile.write('<ignore-accidents value="%s"/>\n'%is_ignore_accidents)198199if taxiservice is not None:200taxiservice.write_config(simfile, ident=0)201202simfile.write('<output>\n')203# <output-file value="quickstart.net.xml"/>204205if filepath_output_vehroute is not None:206simfile.write('<vehroute-output value="%s"/>\n' % filepath_output_vehroute)207if filepath_output_tripinfo is not None:208simfile.write('<tripinfo-output value="%s"/>\n' % filepath_output_tripinfo)209210if filepath_output_fcd is not None:211simfile.write("""<fcd-output value="%s"/>212<device.fcd.probability value="1"/>\n213""" % (filepath_output_fcd,))214# <device.fcd.period value="1"/>215216if filepath_output_electricenergy is not None:217simfile.write("""<battery-output value="%s"/>218<battery-output.precision value="4"/>219<device.battery.probability value="1"/>220\n221""" % (filepath_output_electricenergy,))222223if filepath_output_summary is not None:224simfile.write("""<summary-output value="%s"/>""" % filepath_output_summary)225226simfile.write('</output>\n')227228if filepath_gui is not None:229simfile.write('<gui-settings-file value="%s"/>\n' % filepath_gui)230231if is_openscenegraph:232simfile.write('<osg-view value="true"/>\n')233234if is_tripdata_unfinished:235simfile.write('<tripinfo-output.write-unfinished value="true"/>\n')236237if is_rerouting:238simfile.write("""<routing>239<device.rerouting.probability value="%.2f"/>240<device.rerouting.deterministic value="%s"/>241<device.rerouting.period value="%d"/>242<device.rerouting.pre-period value="%d"/>243<device.rerouting.adaptation-interval value = "%d"/>\n244""" % (probability_rerouting,245is_deterministic_rerouting,246period_rerouting,247preperiod_rerouting,248float(adaptationinterval_rerouting)/time_step,249))250251if adaptationweight_rerouting > 0:252simfile.write("""<device.rerouting.adaptation-weight value="%.4f"/>\n""" % adaptationweight_rerouting)253else:254simfile.write("""<device.rerouting.adaptation-steps value="%d"/>\n""" % adaptationsteps_rerouting)255256simfile.write('</routing>\n')257258# <report>259# <no-duration-log value="true"/>260# <no-step-log value="true"/>261# </report>262263simfile.write('</configuration>\n')264simfile.close()265266# add path to additional files if necessary267if filename_add is not None:268addfile = open(filepath_add, 'w')269addfile.write('<add>\n')270if filepath_output_edgedata is not None:271addfile.write(' <edgeData id="output_edgedata_%d" freq="%d" file="%s" excludeEmpty="%s"/>\n' %272(freq, freq, filepath_output_edgedata, str(is_exclude_emptyedges).lower()))273274if filepath_output_lanedata is not None:275addfile.write(' <laneData id="output_lanedata_%d" freq="%d" file="%s" excludeEmpty="%s"/>\n' %276(freq, freq, filepath_output_lanedata, str(is_exclude_emptylanes).lower()))277278if filepath_output_edgeemissions is not None:279addfile.write(' <edgeData id="output_edgeemissions_%d" type="emissions" freq="%d" file="%s" excludeEmpty="%s"/>\n' %280(freq, freq, filepath_output_edgeemissions, str(is_exclude_emptyedges).lower()))281282if filepath_output_laneemissions is not None:283addfile.write(' <laneData id="output_laneemissions_%d" type="emissions" freq="%d" file="%s" excludeEmpty="%s"/>\n' %284(freq, freq, filepath_output_laneemissions, str(is_exclude_emptylanes).lower()))285286if filepath_output_edgenoise is not None:287addfile.write(' <edgeData id="edgenoise_%d" type="harmonoise" freq="%d" file="%s" excludeEmpty="%s"/>\n' %288(freq, freq, filepath_output_edgenoise, str(is_exclude_emptyedges).lower()))289290if filepath_output_lanenoise is not None:291addfile.write(' <laneData id="lanenoise_%d" type="harmonoise" freq="%d" file="%s" excludeEmpty="%s"/>\n' %292(freq, freq, filepath_output_lanenoise, str(is_exclude_emptylanes).lower()))293294# if filepath_output_electricenergy is not None:295# addfile.write(' <laneData id="lanenoise_%d" type="harmonoise" freq="%d" file="%s" excludeEmpty="%s"/>\n'%(freq,freq,filepath_output_lanenoise,str(is_exclude_emptylanes).lower()))296297addfile.write('</add>\n')298addfile.close()299300301class Sumo(CmlMixin, Process):302def __init__(self, scenario,303results=None,304logger=None,305guimode='sumopy', # sumo,306is_runnow=False,307is_run_background=False, is_nohup=False,308workdirpath=None,309is_export_net=True,310is_export_poly=True,311is_export_rou=True,312is_prompt_filepaths=False,313routefilepaths=None,314netfilepath=None,315ptstopsfilepath=None,316polyfilepath=None,317logfilepath='',318cmlfilepath=None, # write command line into this file instead of executing sumo319**kwargs):320321#self.scenario = scenario322self._cmlfilepath = cmlfilepath323self._init_common('sumo', parent=scenario, name='SUMO',324logger=logger,325info='SUMO micro simulation of scenario.',326)327328# if results is None:329# self._results = Simresults(scenario=scenario)330# else:331self._results = results332333rootname = scenario.get_rootfilename()334rootdirpath = scenario.get_workdirpath()335self.configfilepath = os.path.join(rootdirpath, rootname+'.netc.xml')336337self.init_cml('xxx', is_run_background=is_run_background, is_nohup=is_nohup) # pass main shell command338attrsman = self.get_attrsman()339340self.guimode = attrsman.add(cm.AttrConf('guimode', guimode,341groupnames=['options', 'misc'],342choices=['sumopy', 'sumopy+map', 'native', 'nogui'], # 'openscene'???343name='GUI mode',344perm='rw',345info='Gui mode: sumopy = sumopy style, sumopy+map = sumopy theme with backround map, native = Native SUMO gui, openscene = Open street graph, nogui = run without gui window'346))347348simtime_start_default = scenario.demand.get_time_depart_first()349# estimate end of simtime350simtime_end_default = scenario.demand.get_time_depart_last()351352self.simtime_start = attrsman.add(cm.AttrConf('simtime_start', kwargs.get('simtime_start', simtime_start_default),353groupnames=['options', 'timing'],354name='Start time',355perm='rw',356info='Start time of simulation in seconds after midnight.',357unit='s',358cml='--begin', # no prefix359))360361self.simtime_end = attrsman.add(cm.AttrConf('simtime_end', kwargs.get('simtime_end', simtime_end_default),362groupnames=['options', 'timing'],363name='End time',364perm='rw',365info='End time of simulation in seconds after midnight.',366unit='s',367cml='--end', # no prefix368))369370self.is_dynaroute = attrsman.add(cm.AttrConf('is_dynaroute', kwargs.get('is_dynaroute', False),371groupnames=['options', 'timing'],372name='Dynamic routing',373perm='rw',374info='Routing is always performed during the simulation on vehicle dearture time, based on current edge travel times. This option corrisponds to the so called one shot assignment.',375))376377self.time_to_teleport = attrsman.add(cm.AttrConf('time_to_teleport', kwargs.get('time_to_teleport', -1),378groupnames=['options', 'timing'],379name='teleport',380perm='rw',381info='Time to teleport in seconds, which is the time after'382+ 'dedlocks get resolved by teleporting\n'383+ '-1 means no teleporting takes place',384metatype='time',385unit='s',386cml='--time-to-teleport',387))388389self._init_attributes_basic(scenario, **kwargs)390391# print '\nSumo.__init__',kwargs392393#self.scenario = scenario394#self.settings = scenario.settings395396self.time_sample = attrsman.add(cm.AttrConf('time_sample', kwargs.get('time_sample', 60),397groupnames=['options', 'timing'],398name='Output sample time',399perm='rw',400info='Common sampling time of output data.',401metatype='time',402unit='s',403))404405self.time_warmup = attrsman.add(cm.AttrConf('time_warmup', kwargs.get('time_warmup', 0.0),406groupnames=['options', 'timing'],407name='Warmup time',408perm='rw',409info='Start recording results after this time. It currently work with edgeresults, connectionresults and virtualpersonresults',410metatype='time',411unit='s',412))413414self.is_edgedata = attrsman.add(cm.AttrConf('is_edgedata', kwargs.get('is_edgedata', False),415groupnames=['options', 'output'],416name='Output edge data',417perm='rw',418info='If set, generate detailed data for all edges.'419))420421self.is_routedata = attrsman.add(cm.AttrConf('is_routedata', kwargs.get('is_routedata', False),422groupnames=['options', 'output'],423name='Output route data',424perm='rw',425info='If set, generate detailed data for all routes.'426))427428self.is_tripdata = attrsman.add(cm.AttrConf('is_tripdata', kwargs.get('is_tripdata', False),429groupnames=['options', 'output'],430name='Output trip data',431perm='rw',432info='If set, generate detailed data for all completed trips.'433))434435self.is_tripdata_unfinished = attrsman.add(cm.AttrConf('is_tripdata_unfinished', kwargs.get('is_tripdata_unfinished', False),436groupnames=['options', 'output'],437name='Include unfinished trip data',438perm='rw',439info='If set, also unfinished trip data is collected.'440))441442self.is_edgenoise = attrsman.add(cm.AttrConf('is_edgenoise', kwargs.get('is_edgenoise', False),443groupnames=['options', 'output'],444name='Output edge noise',445perm='rw',446info='If set, generate noise information for all edges.'447))448449self.is_edgesemissions = attrsman.add(cm.AttrConf('is_edgesemissions', kwargs.get('is_edgesemissions', False),450groupnames=['options', 'output'],451name='Output edge emissions',452perm='rw',453info='If set, generate emission information for all edges.'454))455456self.is_electricenergy = attrsman.add(cm.AttrConf('is_electricenergy', kwargs.get('is_electricenergy', False),457groupnames=['options', 'output'],458name='Output electric energy',459perm='rw',460info='If set, record energy data for vehicles with electric drive.'461))462463self.is_fcd = attrsman.add(cm.AttrConf('is_fcd', kwargs.get('is_fcd', False),464groupnames=['options', 'output'],465name='Output vehicle trajectories',466perm='rw',467info='If set, record vehicle trajectories and speed for each timestep. This means SUMO FCD output is generated. Attention, this option will eat up a tremendous amount of disk space.'468))469470self.is_summary = attrsman.add(cm.AttrConf('is_summary', kwargs.get('is_summary', False),471groupnames=['options', 'output'],472name='Output summary',473perm='rw',474info='If set, generate summary data of simulation steps.'475))476477outfile_prefix = kwargs.get('outfile_prefix', 'out')478self.routesdatapath = attrsman.add(cm.AttrConf('routesdatapath', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.roudata.xml'),479groupnames=['outputfiles', '_private'],480perm='r',481name='Route data file',482wildcards='Route data XML files (*.roudata.xml)|*.roudata.xml',483metatype='filepath',484info="""SUMO xml file with route output info.""",485#attrnames_data = ['depart','arrival'],486#element = 'vehicle',487#id_type = 'trip',488#reader = 'plain',489))490491self.tripdatapath = attrsman.add(cm.AttrConf('tripdatapath', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.tripdata.xml'),492groupnames=['outputfiles', '_private'],493perm='r',494name='Edge data file',495wildcards='Trip data XML files (*.tripdata.xml)|*.tripdata.xml',496metatype='filepath',497info="""SUMO xml file with trip output data.""",498attrnames_data=['depart', 'arrival', 'duration'],499#element = 'tripinfo',500#id_type = 'trip',501#reader = 'plain',502))503504self.edgedatapath = attrsman.add(cm.AttrConf('edgedatapath', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.edgedata.xml'),505groupnames=['outputfiles', '_private'],506perm='r',507name='Edge data file',508wildcards='Edge data XML files (*.edgedata.xml)|*.edgedata.xml',509metatype='filepath',510info="""SUMO xml file with edge output data.""",511))512513self.edgenoisepath = attrsman.add(cm.AttrConf('edgenoisepath', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.edgenoise.xml'),514groupnames=['outputfiles', '_private'],515perm='r',516name='Edge noise file',517wildcards='Edge noise XML files (*.edgenoise.xml)|*.edgenoise.xml',518metatype='filepath',519info="""SUMO xml file with edge noise data.""",520#attrnames_averaged = ['noise'],521#element = 'edge',522#id_type = 'edge',523#reader = 'interval',524))525526self.edgeemissionspath = attrsman.add(cm.AttrConf('edgeemissionspath', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.edgeemissions.xml'),527groupnames=['outputfiles', '_private'],528perm='r',529name='Edge noise file',530wildcards='Edge noise XML files (*.edgeemissions.xml)|*.edgeemissions.xml',531metatype='filepath',532info="""SUMO xml file with edge emission data.""",533attrnames_data=['fuel_abs', 'CO_abs',534'CO2_abs', 'NOx_abs', 'PMx_abs'],535attrnames_averaged=['fuel_normed',536'CO_normed', 'CO2_normed', ],537element='edge',538id_type='edge',539reader='interval',540))541542self.electricenergypath = attrsman.add(cm.AttrConf('electricenergypath', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.electricenergy.xml'),543groupnames=['outputfiles', '_private'],544perm='r',545name='Electrical energy file',546wildcards='Electrical energy XML files (*.electricenergy.xml)|*.electricenergy.xml',547metatype='filepath',548info="""SUMO xml file with edge emission data.""",549attrnames_data=['Consum', 'energyCharged',550'energyChargedInTransit', 'energyChargedStopped'],551attrnames_averaged=['speed', ],552element='vehicle',553id_type='vehicle',554reader='interval',555))556557self.filepath_output_fcd = attrsman.add(cm.AttrConf('filepath_output_fcd', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.fcd.xml'),558groupnames=['outputfiles', '_private'],559perm='r',560name='Trajectory file',561wildcards='Trajectory XML files (*.fcd.xml)|*.fcd.xml',562metatype='filepath',563info="""SUMO xml file with edge emission data.""",564attrnames_data=['x', 'y', 'angle', ],565attrnames_averaged=['speed', ],566element='vehicle',567id_type='vehicle',568reader='interval',569))570571self.summarypath = attrsman.add(cm.AttrConf('summarypath', os.path.join(rootdirpath, rootname+'.'+outfile_prefix+'.electricenergysum.xml'),572groupnames=['_private'],573perm='r',574name='Simulation summary file',575wildcards='Simulation summary XML files (*.xml)|*.xml',576metatype='filepath',577info="""SUMO xml file with summary data on simulatin steps.""",578))579580self.is_rerouting = attrsman.add(cm.AttrConf('is_rerouting', kwargs.get('is_rerouting', False),581groupnames=['options', 'rerouting'],582name='Rerouting enabled',583perm='rw',584info='Enable rerouting of vehicles during the simulation.'585))586587self.probability_rerouting = attrsman.add(cm.AttrConf('probability_rerouting', kwargs.get('probability_rerouting', 0.25),588groupnames=['options', 'rerouting'],589name='Rerouting probability',590perm='rw',591info='The probability for a vehicle to have a routing device.'592))593594self.is_deterministic_rerouting = attrsman.add(cm.AttrConf('is_deterministic_rerouting', kwargs.get('is_deterministic_rerouting', False),595groupnames=['options', 'rerouting'],596name='Deterministic rerouting',597perm='rw',598info='The devices are set deterministic using a fraction of 1000 (with the defined probability).'599))600601self.period_rerouting = attrsman.add(cm.AttrConf('period_rerouting', kwargs.get('period_rerouting', 180),602groupnames=['options', 'rerouting'],603name='Rerouting period',604perm='rw',605info='The period with which the vehicle shall be rerouted.',606unit='s',607))608609self.preperiod_rerouting = attrsman.add(cm.AttrConf('preperiod_rerouting', kwargs.get('preperiod_rerouting', 180),610groupnames=['options', 'rerouting'],611name='Rerouting pre-period',612perm='rw',613info='The rerouting period before insertion/depart.',614unit='s',615))616self.adaptationinterval_rerouting = attrsman.add(cm.AttrConf('adaptationinterval_rerouting', kwargs.get('adaptationinterval_rerouting', 180),617groupnames=['options', 'rerouting'],618name='adaptation interval edge weight',619perm='rw',620info='The interval for updating the edge weights. Short update times means a large computational burden.',621unit='s',622))623self.adaptationweight_rerouting = attrsman.add(cm.AttrConf('adaptationweight_rerouting', kwargs.get('adaptationweight_rerouting', 0.0),624groupnames=['options', 'rerouting'],625name='Adaptation weight for rerouting',626perm='rw',627info='The weight of prior edge weights for exponential averaging from [0, 1]. Disabeled for 0.0.'628))629630self.adaptationsteps_rerouting = attrsman.add(cm.AttrConf('adaptationsteps_rerouting', kwargs.get('adaptationsteps_rerouting', 10),631groupnames=['options', 'rerouting'],632name='Adaptation steps for rerouting',633perm='rw',634info='The number of adaptation steps for edge weights averaging (enable for values > 0).'635))636637self._init_special(**kwargs)638639self.is_include_poly = attrsman.add(cm.AttrConf('is_include_poly', kwargs.get('is_include_poly', True),640name='Include buildings?',641perm='rw',642groupnames=['options', 'misc'],643info='Include building polynomials. Only for visualization purposes.',644))645646self.is_start = attrsman.add(cm.AttrConf('is_start', kwargs.get('is_start', False),647groupnames=['options', 'misc'],648perm='rw',649name='Start immediately',650info='Immediate start of simulation, without waiting to press the start button in GUI mode.',651is_enabled=lambda self: self.guimode is not 'nogui',652))653654self.is_quit_on_end = attrsman.add(cm.AttrConf('is_quit_on_end', kwargs.get('is_quit_on_end', False),655groupnames=['options', 'misc'],656perm='rw',657name='Quit on end',658info='Quits the GUI when the simulation stops.',659is_enabled=lambda self: self.guimode is not 'nogui',660))661662self.logfilepath = attrsman.add(cm.AttrConf('logfilepath', logfilepath,663groupnames=['options', 'misc'],664perm='rw',665name='Log file',666wildcards='Log file (*.txt)|*.txt',667metatype='filepath',668info="Writes all messages to Log filepath, implies verbous. If blank, no logfile is created",669))670671if ptstopsfilepath is None:672ptstopsfilepath = scenario.net.ptstops.get_stopfilepath()673674self.is_export_ptstops = attrsman.add(cm.AttrConf('is_export_ptstops', True,675groupnames=['input', 'options'],676perm='rw',677name='Export PT stops?',678info='Export PT stops before simulation?',679))680681if routefilepaths is None:682routefilepaths = scenario.demand.get_routefilepath()683684self.is_export_rou = attrsman.add(cm.AttrConf('is_export_rou', is_export_rou,685groupnames=['input', 'options'],686perm='rw',687name='Export routes?',688info='Export current routes before simulation? Needs to be done only once after demand has changed.',689))690else:691self.is_export_rou = False692693if netfilepath is None:694netfilepath = scenario.net.get_filepath()695696self.is_export_net = attrsman.add(cm.AttrConf('is_export_net', is_export_net,697groupnames=['input', 'options'],698perm='rw',699name='Export net?',700info='Export current network before simulation? Needs to be done only once after network has changed.',701))702else:703self.is_export_net = False704705if polyfilepath is None:706polyfilepath = scenario.landuse.get_filepath()707self.is_export_poly = attrsman.add(cm.AttrConf('is_export_poly', is_export_poly,708groupnames=['input', 'options'],709perm='rw',710name='Export buildings?',711info='Export current buildings before simulation? Needs to be done only once after buildings have changed.',712))713else:714self.is_export_poly = False715716if is_prompt_filepaths:717filepathgroupnames = ['input', 'options']718else:719filepathgroupnames = ['input', '_private']720721self.dirpath_results = attrsman.add(cm.AttrConf('dirpath_results', rootdirpath,722groupnames=filepathgroupnames,723perm='rw',724name='Result directory',725metatype='dirpath',726info="""Directory where general SUMO simulation result files are placed.""",727))728729self.netfilepath = attrsman.add(cm.AttrConf('netfilepath', netfilepath,730groupnames=filepathgroupnames,731perm='rw',732name='Netfile',733wildcards='SUMO net XML files (*.net.xml)|*.net.xml',734metatype='filepath',735info="""SUMO network xml file.""",736))737738self.ptstopsfilepath = attrsman.add(cm.AttrConf('ptstopsfilepath', ptstopsfilepath,739groupnames=filepathgroupnames,740perm='rw',741name='Stop file',742wildcards='SUMO XML files (*.add.xml)|*.add.xml',743metatype='filepath',744info="""SUMO additional xml file with info on public transport stops.""",745))746747self.routefilepaths = attrsman.add(cm.AttrConf('routefilepaths', routefilepaths,748groupnames=filepathgroupnames,749perm='rw',750name='Route file(s)',751wildcards='Typemap XML files (*.rou.xml)|*.rou.xml',752metatype='filepaths',753info='SUMO route xml file.\n'754+ 'If multiple, comma separated files are given'755+ ' then make sure the start time of trips'756+ ' are in increasing chronological order.',757))758759self.polyfilepath = attrsman.add(cm.AttrConf('polyfilepath', polyfilepath,760groupnames=filepathgroupnames,761perm='rw',762name='Poly file',763wildcards='Poly XML files (*.poly.xml)|*.poly.xml',764metatype='filepath',765info='SUMO polynomial xml file',766))767768# print ' is_export_poly,is_include_poly, filepath_poly',is_export_poly, self.is_include_poly, self.polyfilepath769770if is_runnow:771self.run()772773def _init_attributes_basic(self, scenario, optionprefix='', **kwargs):774attrsman = self.get_attrsman()775776if optionprefix == '':777optionprefix_nice = ''778prefixgroups = []779else:780optionprefix_nice = optionprefix.title()+': '781prefixgroups = [optionprefix]782783self.time_step = attrsman.add(cm.AttrConf('time_step', kwargs.get('time_step', 0.2),784groupnames=['options', 'timing']+prefixgroups,785name=optionprefix_nice+'Time step',786perm='rw',787info='Basic simulation time step (1s by default).',788metatype='time',789unit='s',790cml=optionprefix+'--step-length',791))792793self.is_ballistic_integrator = attrsman.add(cm.AttrConf('is_ballistic_integrator', kwargs.get('is_ballistic_integrator', False),794groupnames=['options', 'timing']+prefixgroups,795name=optionprefix_nice+'Ballistic integrator',796perm='rw',797info='Whether to use ballistic method for the positional update of vehicles (default is a semi-implicit Euler method).',798cml=optionprefix+'--step-method.ballistic',799))800801# print ' ',scenario.demand.vtypes.lanechangemodel.get_value()802if scenario.demand.vtypes.lanechangemodel.get_value() in ['SL2015', ]:803width_sublanes_default = 1.0804else:805width_sublanes_default = -1.0806807self.width_sublanes = attrsman.add(cm.AttrConf('width_sublanes', kwargs.get('width_sublanes', width_sublanes_default),808groupnames=['options', 'edges']+prefixgroups,809cml=optionprefix+'--lateral-resolution',810perm='rw',811name=optionprefix_nice+'Sublane width',812unit='m',813info='Width of sublanes. Should be less than lane width. If negative the sublanes are disabeled.',814is_enabled=lambda self: self.width_sublanes > 0,815))816817#818# --max-depart-delay <TIME> <TIME> may be used to discard vehicles which could not be inserted within <TIME> seconds.819820# self.is_ignore_accidents = attrsman.add(cm.AttrConf( 'is_ignore_accidents', kwargs.get('is_ignore_accidents',False),821# name = 'ignore accidents',822# perm = 'rw',823# groupnames = ['options','misc'],824# info = 'Ignore accidents.',825# ))826827self.is_collission_check_junctions = attrsman.add(cm.AttrConf('is_collission_check_junctions', kwargs.get('is_collission_check_junctions', True),828name=optionprefix_nice+'Collission check junctions',829perm='rw',830groupnames=['options', 'misc']+prefixgroups,831info='Perform collission check at junctions.',832cml=optionprefix+'--collision.check-junctions',833))834835self.collission_action = attrsman.add(cm.AttrConf('collission_action', kwargs.get('collission_action', 'warn'),836name=optionprefix_nice+'Collission action',837choices=['none', 'warn', 'teleport', 'remove'],838perm='rw',839groupnames=['options', 'misc']+prefixgroups,840info='Specifioes what to do when a collission occurs.',841cml=optionprefix+'--collision.action',842))843844# self.factor_collission_mingap = attrsman.add(cm.AttrConf( 'factor_collission_mingap', kwargs.get('factor_collission_mingap',-1),845# name = 'factor_collission_mingap',846# perm = 'rw',847# groupnames = ['options','misc'],848# info = 'Sets the fraction of minGap that must be maintained to avoid collision detection. If a negative value is given, the carFollowModel parameter is used.',849# cml = optionprefix+'--collision.mingap-factor',850# ))851852# self.is_exclude_emptyedges = attrsman.add(cm.AttrConf( 'is_exclude_emptyedges', kwargs.get('is_exclude_emptyedges',True),853# name = 'No empty edges',854# perm = 'rw',855# groupnames = ['options','misc'],856# info = 'Excludes empty edges from being sampled.',857# #cml = optionprefix+'--end',858# ))859860# self.is_exclude_emptylanes = attrsman.add(cm.AttrConf( 'is_exclude_emptylanes',kwargs.get('is_exclude_emptylanes',True),861# name = 'No empty lanes',862# perm = 'rw',863# groupnames = ['options','misc'],864# info = 'Excludes empty edges from being sampled.',865# cml = optionprefix+'--end',866# ))867868self.seed = attrsman.add(cm.AttrConf('seed', kwargs.get('seed', 0),869name=optionprefix_nice+'Seed',870perm='rw',871groupnames=['options', 'misc']+prefixgroups,872info='Random seed.',873cml=optionprefix+'--seed',874))875876def _init_special(self, **kwargs):877"""878Special initializations. To be overridden.879"""880pass881882def get_results(self):883return self._results884885def is_ready(self):886"""887Returns True if process is ready to run.888889"""890# here we can check existance of files891return True892893def do(self):894"""895Called by run after is_ready verification896"""897898print 'do... '899900scenario = self.parent901902# exports, if required903delta = np.zeros(3, dtype=np.float32)904if self.is_export_net:905ptstopsfilepath = scenario.net.ptstops.export_sumoxml(self.ptstopsfilepath)906netfilepath, delta = scenario.net.export_netxml(self.netfilepath, is_return_delta=True)907else:908ptstopsfilepath = self.ptstopsfilepath909910if self.is_export_rou & (self.routefilepaths.count(',') == 0):911scenario.demand.export_routes_xml(self.routefilepaths,912is_route=not self.is_dynaroute)913914if self.is_export_poly & (self.guimode not in ['sumopy+map']):915polyfilepath = scenario.landuse.export_polyxml(self.polyfilepath, delta=delta)916else:917polyfilepath = self.polyfilepath918919# Output data920if self.is_routedata:921routesdatapath = self.routesdatapath922else:923routesdatapath = None924925if self.is_tripdata:926tripdatapath = self.tripdatapath927else:928tripdatapath = None929930if self.is_edgedata:931edgedatapath = self.edgedatapath932else:933edgedatapath = None934935if self.is_edgenoise:936edgenoisepath = self.edgenoisepath937else:938edgenoisepath = None939940if self.is_edgesemissions:941edgeemissionspath = self.edgeemissionspath942else:943edgeemissionspath = None944945if self.is_electricenergy:946electricenergypath = self.electricenergypath947else:948electricenergypath = None949950if self.is_fcd:951filepath_output_fcd = self.filepath_output_fcd952else:953filepath_output_fcd = None954955if self.is_summary:956summarypath = self.summarypath957else:958summarypath = None959960# print ' is_include_poly, filepath_poly', self.is_include_poly, self.polyfilepath961if self.is_include_poly & (self.guimode not in ['sumopy+map']):962if polyfilepath is None:963filename_poly = None964elif os.path.isfile(self.polyfilepath):965filename_poly = os.path.basename(self.polyfilepath)966else:967filename_poly = None968else:969filename_poly = None970# print ' guimode',self.guimode,self.guimode == 'sumopy+map',is_maps971# ['sumopy','sumopy+map','native','osg','nogui']972if self.guimode in ['sumopy', 'sumopy+map']:973filepath_gui = os.path.basename(self.parent.net.write_guiconfig(974is_maps=self.guimode in ['sumopy+map'], delta=delta))975else:976filepath_gui = None977978if ptstopsfilepath is None:979filename_ptstops = None980elif os.path.isfile(ptstopsfilepath) & self.is_export_ptstops:981filename_ptstops = os.path.basename(self.ptstopsfilepath)982else:983filename_ptstops = None984# if self.files_input.filepath.get('ptstops')=='':985# filepath_ptstops = None986# filename_ptstops = None987# else:988# filepath_ptstops = self.files_input.filepath.get('ptstops')989# filename_ptstops = os.path.basename(filepath_ptstops)990991# print ' >>%s<<'%self.configfilepath992#filename_netconfig = os.path.basename(self.filepath_netconfig)993994# print ' filepath_poly =',filepath_poly995# print ' filename_poly =',filename_poly996# write configuration file997998write_netconfig(999self.configfilepath,1000self.netfilepath,1001self.routefilepaths,1002starttime=self.simtime_start,1003stoptime=self.simtime_end,1004time_step=self.time_step,1005filename_ptstops=filename_ptstops,1006pedestrian_model=scenario.demand.vtypes.pedestrian_model.get_value(),1007width_sublanes=self.width_sublanes,1008filename_poly=filename_poly,1009dirname_output=self.dirpath_results,1010time_to_teleport=self.time_to_teleport,1011filepath_output_vehroute=routesdatapath,1012filepath_output_tripinfo=tripdatapath,1013is_tripdata_unfinished=self.is_tripdata_unfinished,1014filepath_output_edgedata=edgedatapath,1015#filepath_output_lanedata = self._get_filepath_output('lanedata'),1016filepath_output_edgeemissions=edgeemissionspath,1017filepath_output_electricenergy=electricenergypath,1018filepath_output_fcd=filepath_output_fcd,1019filepath_output_summary=summarypath,1020#filepath_output_laneemissions = self._get_filepath_output('laneemissions'),1021filepath_output_edgenoise=edgenoisepath,1022#filepath_output_lanenoise = self._get_filepath_output('lanenoise'),1023freq=self.time_sample,1024#is_exclude_emptyedges = self.is_exclude_emptyedges,1025#is_exclude_emptylanes =self.is_exclude_emptylanes,1026seed=self.seed,1027filepath_gui=filepath_gui,1028is_openscenegraph=self.guimode is 'openscene',1029width_pedestrian_striping=scenario.demand.vtypes.width_pedestrian_striping.get_value(),1030slowdownfactor_pedestrian_striping=scenario.demand.vtypes.slowdownfactor_pedestrian_striping.get_value(),1031jamtime_pedestrian_striping=scenario.demand.vtypes.jamtime_pedestrian_striping.get_value(),1032jamtime_pedestrian_crossing_striping=scenario.demand.vtypes.jamtime_pedestrian_crossing_striping.get_value(),1033is_collission_check_junctions=self.is_collission_check_junctions,1034#is_ignore_accidents = self.is_ignore_accidents,1035collission_action=self.collission_action,1036is_ballistic_integrator=self.is_ballistic_integrator,1037is_rerouting=self.is_rerouting,1038probability_rerouting=self.probability_rerouting,1039is_deterministic_rerouting=self.is_deterministic_rerouting,1040period_rerouting=self.period_rerouting,1041preperiod_rerouting=self.preperiod_rerouting,1042adaptationinterval_rerouting=self.adaptationinterval_rerouting,1043adaptationweight_rerouting=self.adaptationweight_rerouting,1044adaptationsteps_rerouting=self.adaptationsteps_rerouting,1045taxiservice=self.parent.simulation.taxiservice,1046)10471048if self._cmlfilepath is None:1049print ' call run_cml'1050return self.run_cml(cml=self.get_cml())1051else:1052print ' do not simulate but write cml to', self._cmlfilepath1053f = open(self._cmlfilepath, "w+")1054f.write(self.get_cml()+'\n')10551056f.close()1057return True1058# self.import_results()10591060def get_scenario(self):1061return self.parent10621063def import_results(self, results=None):1064"""1065Imports simulation resuts into results object.1066"""1067print 'import_results'10681069# first a dict is created with available dataname as key1070# and filepath as value10711072# with this dict, the import_xml method of results1073# is called, where the files are parsed for specific data10741075if results is None:1076results = self._results1077if results is None:1078results = self.parent.simulation.results10791080if results is not None:10811082resultfilepaths = {}1083if self.is_edgedata:1084if os.path.isfile(self.edgedatapath):1085resultfilepaths['edgedatapath'] = self.edgedatapath10861087if self.is_edgenoise:1088if os.path.isfile(self.edgenoisepath):1089resultfilepaths['edgenoisepath'] = self.edgenoisepath10901091if self.is_edgesemissions:1092if os.path.isfile(self.edgeemissionspath):1093resultfilepaths['edgeemissionspath'] = self.edgeemissionspath10941095if self.is_routedata:1096if os.path.isfile(self.routesdatapath):1097resultfilepaths['routesdatapath'] = self.routesdatapath10981099if self.is_tripdata:1100if os.path.isfile(self.tripdatapath):1101resultfilepaths['tripdatapath'] = self.tripdatapath11021103if self.is_electricenergy:1104if os.path.isfile(self.electricenergypath):1105resultfilepaths['electricenergypath'] = self.electricenergypath11061107if self.is_fcd:1108if os.path.isfile(self.filepath_output_fcd):1109resultfilepaths['trajectorypath'] = self.filepath_output_fcd11101111if len(resultfilepaths) > 0:1112results.import_xml(self, **resultfilepaths)11131114# no. do some preprocessing during import_results then take1115# specific actions on demand objects1116# def process_results(self):1117# self._results.process(self)11181119def get_cml(self, is_primed=True):1120"""1121Overwritten, providing configuration file instead of cml options.1122"""1123if is_primed:1124p = P1125else:1126p = ''1127print 'get_cml p=%s=' % p1128# print ' self.configfilepath=%s='%self.configfilepath1129# print ' self.logfilepath=%s='%self.logfilepath1130if self.guimode is 'nogui':1131command = 'sumo'1132else:1133command = 'sumo-gui'1134if self.is_quit_on_end:1135command += ' --quit-on-end'1136if self.is_start:1137command += ' --start'1138if self.logfilepath != '':1139command += ' --log '+p+self.logfilepath+p11401141# went into config...1142# if self.pedestrian_model=='None':1143# pedmodeloptions = ''1144# else:1145# pedmodeloptions = '--pedestrian.model %s'%self.pedestrian_model1146# return command + ' ' +pedmodeloptions+' -c '+P+self.configfilepath+P1147return command + ' -c '+p+self.configfilepath+p114811491150class Meso(Sumo):1151"""1152Mesoscopic simulation process.1153The mesoscopic simulation model which uses the same input data as the main SUMO model.1154It computes vehicle movements with queues and runs up to 100 times faster than the microscopic model of SUMO. Additionally, due to using a coarser model for intersections and lane-changing it is more tolerant of network modelling errors than SUMO.11551156The simulation model is based on the work of Eissfeldt, Vehicle-based modelling of traffic.1157"""11581159def _init_special(self, **kwargs):1160"""1161Special initializations. To be overridden.1162"""1163attrsman = self.get_attrsman()11641165self.add_option('edgelength_meso', kwargs.get('edgelength_meso', 100.0),1166groupnames=['options', 'meso'],1167cml='--meso-edgelength',1168name='MESO: Maximum queue length',1169unit='m',1170info='Maximum queue length.',1171)11721173self.add_option('is_allow_overtaking', kwargs.get('is_allow_overtaking', True),1174groupnames=['options', 'meso'],1175cml='--meso-overtaking',1176name='MESO: Allow overtaking',1177info='If True, vehicles may overtake each other (swap their position). This is a randomized process depending on vehicle speeds and density.',1178)11791180self.add_option('enable_junction_control', kwargs.get('enable_junction_control', 'true'),1181groupnames=['options', 'meso'],1182choices=['true', 'false'],1183cml='--meso-junction-control',1184name='MESO: enable junction control',1185info='If True, junctions are modeled as in the simplified microsim mode (without internal links).',1186)11871188self.add_option('time_panelty_minor', kwargs.get('time_panelty_minor', 0.0),1189groupnames=['options', 'meso'],1190cml='--meso-minor-penalty',1191name='MESO: junction timepenalty',1192unit='s',1193info='fixed time penalty when passing an unprioritzed link.',1194)11951196self.add_option('penalty_tls', kwargs.get('penalty_tls', 0.0),1197groupnames=['options', 'meso'],1198cml='--meso-tls-penalty',1199name='MESO: TLS penalty',1200info='For values >0, a time penalty is applied according to the average delay time (based on red phase duration) and the minimum headway time is increased to model the maximum capacity (according the proportion of green time to cycle time). The panelty is used as a scaling factor that roughly corresponds to coordination (1.0 corresponds to uncoordinated traffic lights, whereas values approaching 0 model near-perfect coordination).',1201)12021203self.add_option('time_to_impatience', kwargs.get('time_to_impatience', 1000.0),1204groupnames=['options', 'meso'],1205cml='--time-to-impatience',1206name='MESO: time to impacience',1207unit='s',1208info='Time to reach an impatience value of 1. Vehicles that reach an impatience value of 1 (maximum) can pass an intersection regardless of foe traffic with higher priority.',1209)12101211def get_cml(self, is_primed=True):1212"""1213Overwritten, providing configuration file instead of cml options.1214"""12151216# currently meso options are provided through the command line options1217# while SUMO options are written to the configuration file1218options = self.get_options()1219optionstr = options.get_optionstring()12201221return Sumo.get_cml(self, is_primed) + ' --mesosim true ' + optionstr122212231224class SumoTraci(Sumo):1225"""1226SUMO simulation process with interactive control via TRACI.1227"""12281229def _init_special(self, **kwargs):1230"""1231Special initializations. To be overridden.1232"""1233pass1234# self.is_simpla = self.get_attrsman().add(cm.AttrConf( 'is_simpla', kwargs.get('is_simpla',False),1235# groupnames = ['options','misc'],1236# name = 'Use simple platooning',1237# perm = 'rw',1238# info = 'Performs simple platooning operations, as configured in Simpla.',1239# ))12401241def do(self):1242"""1243Called by run after is_ready verification1244"""12451246Sumo.do(self)12471248def run_cml(self, cml):1249scenario = self.parent1250cmllist = cml.split(' ')1251print 'SumoTraci.run_cml', cmllist1252traci.start(cmllist)12531254simplaconfig = self.parent.simulation.simplaconfig1255if simplaconfig.is_enabled:1256simplaconfig.prepare_sim()12571258self.simtime = self.simtime_start1259self.duration = 1.0+self.simtime_end-self.simtime_start1260self.get_attrsman().status.set('running')1261print ' traci started', self.get_attrsman().status.get()1262simobjects = []12631264for simobj in self.parent.simulation.get_simobjects():1265# attention, simpla is not a simulation object, only a demand object1266# print ' prepare_sim',simobj.ident1267simobjects += simobj.prepare_sim(self)12681269#simobjects = self._prtservice.prepare_sim(self)1270self.simobjects = []1271for time_sample, simfunc in simobjects:1272self.simobjects.append([self.simtime_start, time_sample, simfunc])1273# print ' simobjects=',self.simobjects1274return True12751276def get_cml(self):1277"""1278Returns commandline with all options.1279The only difference from this method of the SUMO class is1280that filenames must not be quoted when passed to traci.1281"""1282return Sumo.get_cml(self, is_primed=False)12831284def aboard(self):1285return self.finish_sim()12861287def step(self):1288# called interactively1289# when gui it is called through the timer function1290print 79*'='1291print "simstep", self.simtime, self.simtime_end, self.simtime >= self.simtime_end1292traci.simulationStep()1293for i in xrange(len(self.simobjects)):1294# for time_last, time_sample, simfunc in self.simobjects:1295time_last, time_sample, simfunc = self.simobjects[i]1296# print ' simfunc',simfunc,'time_last',time_last,'dt',self.simtime-time_last,'sim?',self.simtime-time_last > time_sample1297if self.simtime-time_last > time_sample:1298self.simobjects[i][0] = self.simtime1299simfunc(self)13001301#self.get_logger().w(100.0*self.simtime/self.duration, key ='progress')13021303if self.simtime >= self.simtime_end: # | (not (traci.simulation.getMinExpectedNumber() > 0)):1304# if self.simtime >= self.simtime_end:1305print ' end of simulation reached at', self.simtime1306return self.finish_sim()13071308self.simtime += self.time_step13091310def finish_sim(self):1311print 'finish_sim'1312# for demandobj in self.parent.demand.get_demandobjects():1313# print ' finish_sim',demandobj.ident1314# #demandobj.finish_sim(self) # why not for sim objects?1315traci.close()1316print ' traci closed.'1317self.get_attrsman().status.set('success')13181319simplaconfig = self.parent.simulation.simplaconfig1320if simplaconfig.is_enabled:1321scenario = self.get_scenario()1322simplaconfig.finish_sim()13231324return True13251326# def process_step(self):1327# #print traci.vehicle.getSubscriptionResults(vehID)1328# print 'process_step time=',self.simtime132913301331class Duaiterate(CmlMixin, Sumo): # attention, CmlMixin overrides Sumo1332def __init__(self, scenario,1333routefilepath=None,1334netfilepath=None,1335ptstopsfilepath=None,1336logger=None,1337results=None,1338**kwargs):13391340self._init_common('duaiterate', name='Dynamic User Equilibrium traffic assignment',1341parent=scenario,1342logger=logger,1343info='The Dynamic User equilibrium traffic Assignment is an iterative micro-simulation process.',1344)13451346# point to script1347self.init_cml(os.path.join(os.environ['SUMO_HOME'], 'tools', 'assign', 'duaIterate.py'),1348workdirpath=scenario.get_workdirpath())13491350self._results = results1351self.time_warmup = 0.0 # needed for compatibility with sumo process1352attrsman = self.get_attrsman()13531354simtime_start_default = int(scenario.demand.get_time_depart_first())1355# estimate end of simtime1356simtime_end_default = int(scenario.demand.get_time_depart_last())13571358self.add_option('simtime_start', kwargs.get('simtime_start', simtime_start_default),1359groupnames=['options', 'timing'],1360name='Start time',1361perm='rw',1362info='Start time of simulation in seconds after midnight.',1363unit='s',1364cml='--begin', # no prefix1365)13661367self.add_option('simtime_end', kwargs.get('simtime_end', simtime_end_default),1368groupnames=['options', 'timing'],1369name='End time',1370perm='rw',1371info='End time of simulation in seconds after midnight.',1372unit='s',1373cml='--end', # no prefix1374)13751376self.add_option('step_first', kwargs.get('step_first', 0),1377groupnames=['options', 'timing'],1378name='First step',1379perm='rw',1380info='First DUA step. Default is zero. By settting the first step, one can continue iterate from a previous process.',1381cml='--first-step',1382)13831384self.add_option('step_last', kwargs.get('step_last', 50),1385groupnames=['options', 'timing'],1386name='Last step',1387perm='rw',1388info='Last DUA step.',1389cml='--last-step',1390)13911392self.add_option('n_convergence_iterations', kwargs.get('n_convergence_iterations', 10),1393groupnames=['options', 'processing'],1394cml='--convergence-iterations',1395name="convergence iterations",1396info="Number of iterations to use for convergence calculation.",1397)13981399self.add_option('routesteps', kwargs.get('routesteps', 200),1400groupnames=['options', 'processing'],1401cml='--route-steps',1402name="Route steps",1403info="Last DUA iteration step.\n"1404+ "This is the maximim number of iterations performed.",1405)14061407self.add_option('time_aggregation', kwargs.get('time_aggregation', 900),1408groupnames=['options', 'processing'],1409name='Aggregation time',1410cml='--aggregation',1411info='Set main weights aggregation period.',1412unit='s',1413)14141415self.add_option('is_mesosim', kwargs.get('is_mesosim', False),1416groupnames=['options', 'processing'],1417cml='--mesosim',1418name='mesosim',1419perm='rw',1420info='Whether mesosim shall be used.',1421)14221423self.add_option('is_no_internal_link', kwargs.get('is_no_internal_link', False),1424groupnames=['options', 'processing'],1425cml='--nointernal-link',1426name='Simulate no internal links',1427perm='rw',1428info='No internal links simulated.',1429)14301431# self.add_option( 'path', kwargs.get('path',''),1432# name = 'bin dir',1433# perm = 'rw',1434# info = 'Directory with SUMO binaries.',1435# metatype = 'dirpath',1436# )14371438self.add_option('time_to_teleport', kwargs.get('time_to_teleport', -1),1439groupnames=['options', 'timing'],1440name='teleport',1441perm='rw',1442info='Time to teleport in seconds, which is the time after'1443+ 'dedlocks get resolved by teleporting\n'1444+ '-1 means no teleporting takes place',1445metatype='time',1446unit='s',1447cml='--time-to-teleport',1448is_enabled=lambda self: self.time_to_teleport >= 0,1449)14501451self.add_option('is_absrand', kwargs.get('is_absrand', False),1452groupnames=['options', 'processing'],1453cml='--absrand',1454name='time rand',1455perm='rw',1456info='Use current time to generate random number.',1457)14581459# these are duarouter options, but not duaiterate options1460# self.add_option( 'is_remove_loops', kwargs.get('is_remove_loops',False),1461# groupnames = ['options','processing'],#1462# cml = '--remove-loops',1463# name = 'Remove loops',1464# perm = 'rw',1465# info = 'Remove loops within the route; Remove turnarounds at start and end of the route.',1466# )14671468# self.add_option( 'is_repair_routes', kwargs.get('is_repair_routes',False),1469# groupnames = ['options','processing'],#1470# cml = '--repair',1471# name = 'Repair routes',1472# perm = 'rw',1473# info = 'Tries to correct a false route.',1474# )1475# self.add_option('is_ignore_errors',kwargs.get('is_ignore_errors',True),1476# name = 'Ignore disconnected',1477# info = 'Continue if a route could not be build.',1478# cml = '--ignore-errors',1479# groupnames = ['options','processing'],#1480# perm='rw',1481# )1482# self.add_option( 'use_no_internallink', kwargs.get('use_no_internallink',False),1483# groupnames = ['options','processing'],#1484# cml = '--internallink',1485# name = 'No internal links',1486# perm = 'rw',1487# info = 'Not to simulate internal link: true or false.',1488# )14891490self.add_option('is_mesojunctioncontrol', kwargs.get('is_mesojunctioncontrol', False),1491groupnames=['options', 'processing'],1492cml='--mesojunctioncontrol',1493name='meso junction control?',1494perm='rw',1495info='Enable mesoscopic traffic light and priority junciton handling.',1496)14971498self.add_option('is_mesomultiqueue', kwargs.get('is_mesomultiqueue', False),1499groupnames=['options', 'processing'],1500cml='--mesomultiqueue',1501name='meso mesomulti queue?',1502perm='rw',1503info='Enable multiple queues at edge ends with mesoscopic simulation.',1504)15051506self.add_option('n_meso_recheck', kwargs.get('n_meso_recheck', 0),1507groupnames=['options', 'processing'],1508cml='--meso-recheck',1509name='meso recheck count',1510perm='rw',1511info='Delay before checking whether a jam is gone. (higher values can lead to a big speed increase)',1512)15131514self.add_option('is_zip_old_iterations', kwargs.get('is_zip_old_iterations', False),1515groupnames=['options', 'processing'],1516cml='--7',1517name='zip old iterations',1518perm='rw',1519info='zip old iterations using 7zip.',1520)15211522self.add_option('is_no_warnings', kwargs.get('is_no_warnings', False),1523groupnames=['options', 'processing'],1524cml='--noWarnings',1525name='no warnings',1526perm='rw',1527info='Disables warnings.',1528)15291530self.add_option('is_weight_memory', kwargs.get('is_weight_memory', False),1531groupnames=['options', 'processing'],1532cml='--weight-memory',1533name='Weight memory',1534info='Smooth edge weights across iterations.',1535)15361537self.add_option('is_expand_weights', kwargs.get('is_expand_weights', False),1538groupnames=['options', 'processing'],1539cml='--weights.expand',1540name='Expand edge weights',1541info='Expand edge weights at time interval boundaries.',1542)15431544self.add_option('g_alpha', kwargs.get('g_alpha', 0.5),1545groupnames=['options', 'processing'],1546cml='--gA',1547name="g_alpha",1548perm='rw',1549info="Sets Gawron's Alpha",1550)15511552self.add_option('g_beta', kwargs.get('g_beta', 0.9),1553groupnames=['options', 'processing'],1554cml='--gBeta',1555name="g_beta",1556perm='rw',1557info="Sets Gawron's Beta",1558)15591560self.add_option('routingalgorithm', kwargs.get('routingalgorithm', 'dijkstra'),1561groupnames=['options', 'processing'],1562choices=['dijkstra', 'astar', 'CH', 'CHWrapper'],1563cml='--routing-algorithm',1564name='Routing algorithm',1565info='Routing algorithm.',1566)15671568self.add_option('is_no_summary', kwargs.get('is_no_summary', False),1569groupnames=['options', 'processing'],1570cml='--disable-summary',1571name="No summary",1572perm='rw',1573info="No summaries are written by the simulation after each step, which saves time and disk space.",1574)15751576self.add_option('is_no_tripinfo', kwargs.get('is_no_tripinfo', True),1577groupnames=['options', 'processing'],1578cml='--disable-tripinfos',1579name="No Tripinfo",1580perm='rw',1581info="No tripinfos are written by the simulation after each step, which saves time and disk space.",1582)15831584self.add_option('inc_base', kwargs.get('inc_base', -1),1585groupnames=['options', 'processing'],1586cml='--inc-base',1587name="inc base",1588perm='rw',1589info="Give the incrementation base. Negative values disable incremental scaling.",1590is_enabled=lambda self: self.inc_base >= 0, # default is disabeled1591)15921593self.add_option('inc_value', kwargs.get('inc_value', 1),1594groupnames=['options', 'processing'],1595cml='--incrementation',1596name="inc value",1597perm='rw',1598info="Give the incrementation",1599)16001601self.add_option('time_inc', kwargs.get('time_inc', 0),1602groupnames=['options', 'processing'],1603cml='--time-inc',1604name="inc time",1605perm='rw',1606info="Give the time incrementation.",1607unit='s',1608)16091610self.add_option('format_routefile', kwargs.get('format_routefile', 'None'),1611groupnames=['options', 'processing'],1612cml='--vehroute-file',1613name="Route file format",1614choices=('None', 'routesonly', 'detailed'),1615perm='rw',1616info="Choose the format of the route file.",1617)16181619self.add_option('is_output_lastroute', kwargs.get('is_output_lastroute', False),1620groupnames=['options', 'processing'],1621cml='--output-lastRoute',1622name="Output last route",1623perm='rw',1624info="Output the last routes.",1625)16261627self.add_option('is_keep_all_routes', kwargs.get('is_keep_all_routes', False),1628groupnames=['options', 'processing'],1629cml='--keep-allroutes',1630name="Keep all routes",1631perm='rw',1632info="Save routes even with near zero probability.",1633)16341635self.add_option('is_clean_alt', kwargs.get('is_clean_alt', True),1636groupnames=['options', 'processing'],1637cml='--clean-alt',1638name="Clean alternative routes",1639perm='rw',1640info=" Whether old rou.alt.xml files shall be removed. This saves lots of disk space.",1641)16421643self.add_option('is_binary_routes', kwargs.get('is_binary_routes', False),1644groupnames=['options', 'processing'],1645cml='--binary',1646name="Save routes in binary format",1647perm='rw',1648info="Use binary format for intermediate and resulting route files. This saves disk space",1649)16501651self.add_option('is_skip_first_routing', kwargs.get('is_skip_first_routing', False),1652groupnames=['options', 'processing'],1653cml='--skip-first-routing',1654name="Skip first routing",1655perm='r',1656info="run simulation with demands before first routing. This means, use present routes for the first simulation step.",1657)16581659self.add_option('is_verbose_router', kwargs.get('is_verbose_router', False),1660groupnames=['options', 'processing'],1661cml='--router-verbose',1662name="Verbose router",1663perm='rw',1664info="Verbose log of routing in dua.log file.",1665)16661667self.is_clean_files = attrsman.add(cm.AttrConf('is_clean_files', True,1668groupnames=['input', 'options'],1669perm='rw',1670name='Clean up files',1671info='Cleans up all temporary files and leaves only the route file of the last iteration (i.g. the final result).',1672))16731674# self.add_option( 'districts', kwargs.get('use_districts',''),1675# groupnames = ['options','processing'],#1676# name = "Use districts",1677# perm = 'rw',1678# info = "Use districts as sources and targets.",1679# )16801681# self.add_option( 'additional', kwargs.get('filepath_add',''),1682# name = "additional files",1683# perm = 'rw',1684# info = "Path of additional files.",1685# )16861687# standart sumo options1688# add basic sumo options1689self._init_attributes_basic(scenario, optionprefix='sumo', **kwargs)16901691# filepath stuff1692if ptstopsfilepath is None:1693self.ptstopsfilepath = scenario.net.ptstops.get_stopfilepath()16941695self.is_export_ptstops = attrsman.add(cm.AttrConf('is_export_ptstops', kwargs.get('is_export_ptstops', True),1696groupnames=['input', 'options'],1697perm='rw',1698name='Export PT stops?',1699info='Export PT stops before simulation?',1700))1701else:1702self.ptstopsfilepath = ptstopsfilepath1703self.is_export_ptstops = False17041705if routefilepath is None:1706self.routefilepath = scenario.demand.get_routefilepath()1707self.is_export_routes = attrsman.add(cm.AttrConf('is_export_routes', kwargs.get('is_export_routes', True),1708groupnames=['input', 'options'],1709perm='rw',1710name='Export routes?',1711info='Export routes before simulation? ',1712))17131714else:1715self.is_export_routes = False1716self.routefilepath = routefilepath17171718if netfilepath is None:1719self.netfilepath = scenario.net.get_filepath()17201721self.is_export_net = attrsman.add(cm.AttrConf('is_export_net', kwargs.get('is_export_net', True),1722groupnames=['input', 'options'],1723perm='rw',1724name='Export net?',1725info='Export current network before simulation? Needs to be done only once after network has changed.',1726))1727else:1728self.is_export_net = False1729self.netfilepath = netfilepath17301731# logfilepath not available in duaiterate but as SUMO arg1732# self.logfilepath = attrsman.add(cm.AttrConf('logfilepath',kwargs.get('logfilepath',''),1733# groupnames = ['options','misc'],1734# perm='rw',1735# name = 'Log file',1736# wildcards = 'Log file (*.txt)|*.txt',1737# metatype = 'filepath',1738# info = "Writes all messages to Log filepath, implies verbous. If blank, no logfile is created",1739# ))17401741def get_last_step(self):1742# very fragile method1743#filenames = os.listdir(self.workdir)1744# filenames.sort()1745#step = int(filenames[-1].split('_')[1])1746if 1:1747step_max = 01748for filename in os.listdir(self.workdirpath):1749try:1750step = int(filename)1751except:1752step = -11753if step > step_max:1754step_max = step17551756if 0: # older sumo version1757step_max = 01758for filename in os.listdir(self.workdirpath):1759if filename.startswith('dump'):1760# print ' ',filename,1761step = int(filename.split('_')[1])1762if step > step_max:1763step_max = step17641765return min(step_max, self.step_last)17661767def do(self):17681769# /usr/local/share/sumo/tools/assign/duaIterate_analysis.py17701771scenario = self.parent17721773# exports, if required1774if self.is_export_net:1775ptstopsfilepath = scenario.net.ptstops.export_sumoxml(self.ptstopsfilepath)1776netfilepath = scenario.net.export_netxml(self.netfilepath, is_return_delta=False)1777else:1778ptstopsfilepath = self.ptstopsfilepath17791780if self.is_export_routes:1781# scenario.demand.export_routes_xml( filepath=self.routefilepath,1782# demandobjects = [scenario.demand.trips], is_route = True,1783# vtypeattrs_excluded = ['times_boarding','times_loading'],# bug of duaiterate!!1784# )17851786# eport routes of all demand objects17871788scenario.demand.export_routes_xml(filepath=None, encoding='UTF-8',1789is_route=False, # allow True if route export is implemened in virtual population self.is_skip_first_routing,# produce routes only if first dua routing is skipped1790vtypeattrs_excluded=['times_boarding',1791'times_loading'], # bug of duaiterate!!1792is_plain=True, # this will prevent exporting stops and plans1793is_exclude_pedestrians=True, # no pedestriann trips, but plans are OK1794)17951796# get command with duaiterate options1797cml = self.get_cml()17981799# do filepath options here1800cml += ' --net-file %s' % (ff(self.netfilepath)) +\1801' --routes %s' % (ff(self.routefilepath))18021803additionalpaths = []1804if os.path.isfile(self.ptstopsfilepath):1805additionalpaths.append(self.ptstopsfilepath)18061807if len(additionalpaths) > 0:1808cml += ' --additional %s' % (filepathlist_to_filepathstring(additionalpaths))18091810# finally add all sumo command line options1811sumooptions = Options()1812for attrconfig in self.get_attrsman().get_configs(is_all=True):1813if ('sumo' in attrconfig.groupnames) & hasattr(attrconfig, 'cml'):1814# print ' sumooption',attrconfig.attrname,attrconfig.groupnames,'is path',attrconfig.get_metatype() in self.pathmetatypes,'has cmlmap',hasattr(attrconfig,'cmlvaluemap')1815is_enabled = True1816if hasattr(attrconfig, 'is_enabled'):1817# print ' is_enabled=',attrconfig.is_enabled(self), attrconfig.get_value()1818is_enabled = attrconfig.is_enabled(self)1819if is_enabled: # disabeled options are simply not added1820if hasattr(attrconfig, 'cmlvaluemap'):1821cmlvaluemap = attrconfig.cmlvaluemap1822else:1823cmlvaluemap = None1824is_filepath = attrconfig.get_metatype() in self.pathmetatypes1825sumooptions.add_option(attrconfig.attrname, attrconfig.get_value(),1826attrconfig.cml, is_filepath=is_filepath, cmlvaluemap=cmlvaluemap)18271828cml += ' '+sumooptions.get_optionstring()18291830# if self.logfilepath != '':1831# cml += ' --log %s'%(ff(self.logfilepath))18321833# print '\n Starting command:',cml1834if self.run_cml(cml): # call(cml):1835step_last = self.get_last_step()1836if 0: # old SUMO version1837routefilepath_final = '.'.join(self.routefilepath.split(1838'.')[:-2]) + "_%03d.rou.xml" % (self.get_last_step(),)1839else:1840# print ' new since 1.8.0 ?'1841# print ' workdirpath',self.workdirpath,'step_last',step_last1842resultdir = os.path.join(self.workdirpath, str(step_last))1843print ' resultdir', resultdir1844filename = self.parent.get_rootfilename() + "_%03d.rou.xml" % (self.get_last_step(),)1845print ' filename', filename1846#routefilepath_final = os.path.join(self.workdirpath, str(step_last),'.'.join(self.routefilepath.split('.')[:-2]) + "_%03d.rou.xml"%(step_last,))1847routefilepath_final = os.path.join(resultdir, filename)18481849print ' load routes from file ', routefilepath_final1850if os.path.isfile(routefilepath_final):1851scenario.demand.import_routes_xml(routefilepath_final)18521853if self.is_clean_files:1854if 0: # old version1855for filename in os.listdir(self.workdirpath):1856if filename.startswith('dump'):1857os.remove(os.path.join(self.workdirpath, filename))18581859elif filename.startswith('dua_dump_'):1860os.remove(os.path.join(self.workdirpath, filename))18611862elif filename.startswith('iteration_'):1863os.remove(os.path.join(self.workdirpath, filename))18641865elif filename.startswith('summary_'):1866os.remove(os.path.join(self.workdirpath, filename))18671868else: # new since 1.8.0 ?'1869for step in xrange(self.step_first, step_last):1870filepath = os.path.join(self.workdirpath, str(step))1871print ' delete dir', filepath1872if os.path.isdir(filepath):1873# print ' delete now'1874try:1875shutil.rmtree(filepath)1876except OSError as e:1877print("Error: %s - %s." % (e.filename, e.strerror))18781879return True18801881else:1882return False18831884def import_results(self, results=None):1885"""1886Imports simulation resuts into results object.1887"""1888print 'import_results'18891890# currently nothing is imported in results only routs are1891# reimported in trip database18921893if results is None:1894results = self._results1895if results is None:1896results = self.parent.simulation.results189718981899