Path: blob/main/tools/import/vissim/vissim_parseRoutes.py
194342 views
#!/usr/bin/env python1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2# Copyright (C) 2009-2026 German Aerospace Center (DLR) and others.3# This program and the accompanying materials are made available under the4# terms of the Eclipse Public License 2.0 which is available at5# https://www.eclipse.org/legal/epl-2.0/6# This Source Code may also be made available under the following Secondary7# Licenses when the conditions for such availability set forth in the Eclipse8# Public License 2.0 are satisfied: GNU General Public License, version 29# or later which is available at10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1213# @file vissim_parseRoutes.py14# @author Daniel Krajzewicz15# @author Michael Behrisch16# @date 2009-05-271718"""1920Parses routes given in the Vissim file (first parameter) as (in-)flows and21route decisions.2223The read flows are saved as <OUTPUT_PREFIX>.flows.xml24The read routes are saved as <OUTPUT_PREFIX>.rou.xml2526(Starting?) edges of the route may be renamed by setting them with "edgemap"27option (see below).28"""29from __future__ import absolute_import30from __future__ import print_function3132import os33import sys34import random35if 'SUMO_HOME' in os.environ:36sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))37import sumolib # noqa383940def getName(vals, beg):41name = vals[beg]42while name.count('"') != 2:43beg = beg + 144name = name + " " + vals[beg]45return name.replace('"', '')464748def parseInFlow(inflow, suggested_name):49vals = inflow.split()50i = vals.index("NAME")51name = getName(vals, i + 1)52if (name == ""):53name = suggested_name # SUMO can't cope with empty IDs, unlike VISSIM54i = vals.index("STRECKE", i)55strecke = vals[i + 1]56i = vals.index("Q", i + 1)57if vals[i + 1] == "EXAKT":58q = float(vals[i + 2])59else:60q = float(vals[i + 1])61i = vals.index("ZUSAMMENSETZUNG", i + 1)62i = vals.index("ZEIT", i)63i = vals.index("VON", i)64von = float(vals[i + 1])65i = vals.index("BIS")66bis = float(vals[i + 1])67return (name, strecke, q, von, bis)686970def parseRouteDecision(rd):71vals = rd.split()72i = vals.index("STRECKE")73strecke = vals[i + 1]74# probably, we would normally already here to iterate over time spans...75i = vals.index("ZEIT", i)76i = vals.index("VON", i + 1)77von = float(vals[i + 1])78i = vals.index("BIS", i + 1)79bis = float(vals[i + 1])80if "ROUTE" in vals:81i = vals.index("ROUTE", i + 1)82else:83i = 084sumAnteil = 085routes = []86while i > 0:87r_id = vals[i + 1]88i = vals.index("STRECKE", i + 1)89r_ziel = vals[i + 1]90i = vals.index("ANTEIL", i + 1)91r_anteil = float(vals[i + 1])92r_edges = []93if vals[i + 2] == "UEBER":94i = i + 395while i < len(vals) and vals[i] != "ROUTE":96if vals[i] in edgemap:97r_edges.append(edgemap[vals[i]])98else:99r_edges.append(vals[i])100i = i + 1101else:102try:103i = vals.index("ROUTE", i)104except Exception:105i = -1106if r_ziel in edgemap:107r_edges.append(edgemap[r_ziel])108else:109r_edges.append(r_ziel)110routes.append((r_id, r_anteil, r_edges))111sumAnteil = sumAnteil + r_anteil112if i >= len(vals):113i = -1114return (strecke, sumAnteil, von, bis, routes)115116117def sorter(idx):118def t(i, j):119if i[idx] < j[idx]:120return -1121elif i[idx] > j[idx]:122return 1123else:124return 0125126127# MAIN128if __name__ == '__main__':129op = sumolib.options.ArgumentParser(description="parse routes from a VISSIM network")130op.add_option("vissimNet", category="input", type=op.file, help="the VISSIM network file")131op.add_option("-o", "--output", default="out", category="output", help="output filename prefix")132op.add_option("-e", "--edgemap", category="input", type=op.edge_list,133help="mapping of edge names for renamed edges (orig1:renamed1,orig2:renamed2,...)")134op.add_option("-s", "--seed", type=int, default=42, category="input", help="random seed")135options = op.parse_args()136137random.seed(options.seed)138edgemap = {}139if options.edgemap:140for entry in options.edgemap.split(","):141orig, renamed = entry.split(":")142edgemap[orig] = renamed143print("Parsing Vissim input...")144fd = sumolib.openz(options.vissimNet, encoding='latin1')145routeDecisions = []146haveRouteDecision = False147currentRouteDecision = ""148inflows = []149haveInFlow = False150currentInFlow = ""151for line in fd:152# put all route decision ("ROUTENENTSCHEIDUNG") to a list (routeDecisions)153if line.find("ROUTENENTSCHEIDUNG") == 0:154if haveRouteDecision:155routeDecisions.append(" ".join(currentRouteDecision.split()))156haveRouteDecision = True157currentRouteDecision = ""158elif line[0] != ' ':159if haveRouteDecision:160routeDecisions.append(" ".join(currentRouteDecision.split()))161haveRouteDecision = False162if haveRouteDecision:163currentRouteDecision = currentRouteDecision + line164# put all inflows ("ZUFLUSS") to a list (inflows)165if line.find("ZUFLUSS") == 0:166if haveInFlow:167inflows.append(" ".join(currentInFlow.split()))168haveInFlow = True169currentInFlow = ""170elif line[0] != ' ':171if haveInFlow:172inflows.append(" ".join(currentInFlow.split()))173haveInFlow = False174if haveInFlow:175currentInFlow = currentInFlow + line176fd.close()177178# process inflows179print("Writing flows...")180fdo = open(options.output + ".flows.xml", "w")181sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)182flow_sn = 0183for inflow in inflows:184(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))185fdo.write(' <flow id="' + name + '" from="' + strecke + '" begin="' +186str(von) + '" end="' + str(bis) + '" no="' + str(int(q)) + '"/>\n')187flow_sn = flow_sn + 1188fdo.write("</routes>\n")189fdo.close()190191# process combinations192# parse route decision193print("Building routes...")194edges2check = {}195edgesSumFlows = {}196for rd in routeDecisions:197(strecke, sumAnteil, von, bis, routes) = parseRouteDecision(rd)198if strecke not in edges2check:199edgesSumFlows[strecke] = sumAnteil200edges2check[strecke] = (von, bis, routes)201# compute emissions with routes202emissions = []203flow_sn = 0204for inflow in inflows:205(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))206flow_sn = flow_sn + 1207if strecke in edges2check:208routes = edges2check[strecke]209for vi in range(0, int(q)):210t = von + float(bis - von) / float(q) * float(vi)211fi = random.random() * edgesSumFlows[strecke]212edges = []213ri = 0214rid = ""215while len(edges) == 0 and ri < len(routes[2]) and fi >= 0:216fi = fi - routes[2][ri][1]217if fi < 0:218edges = routes[2][ri][2]219rid = routes[2][ri][0]220ri = ri + 1221id = str(name.replace(" ", "_")) + "_" + str(rid) + "_" + str(vi)222if strecke in edgemap:223if edgemap[strecke] not in edges:224edges.insert(0, edgemap[strecke])225else:226if strecke not in edges:227edges.insert(0, strecke)228emissions.append((int(t), id, edges))229# sort emissions230print("Sorting routes...")231emissions.sort(key=sorter(0))232233# save emissions234print("Writing routes...")235fdo = open(options.output + ".rou.xml", "w")236sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)237for emission in emissions:238if len(emission[2]) < 2:239continue240fdo.write(' <vehicle id="' + emission[1] + '" depart="' + str(241emission[0]) + '"><route edges="' + " ".join(emission[2]) + '"/></vehicle>\n')242fdo.write("</routes>\n")243fdo.close()244245246