Path: blob/main/tools/import/vissim/vissim_parseRoutes.py
169679 views
#!/usr/bin/env python1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2# Copyright (C) 2009-2025 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 random35import codecs36if 'SUMO_HOME' in os.environ:37sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))38import sumolib # noqa394041def getName(vals, beg):42name = vals[beg]43while name.count('"') != 2:44beg = beg + 145name = name + " " + vals[beg]46return name.replace('"', '')474849def parseInFlow(inflow, suggested_name):50vals = inflow.split()51i = vals.index("NAME")52name = getName(vals, i + 1)53if (name == ""):54name = suggested_name # SUMO can't cope with empty IDs, unlike VISSIM55i = vals.index("STRECKE", i)56strecke = vals[i + 1]57i = vals.index("Q", i + 1)58if vals[i + 1] == "EXAKT":59q = float(vals[i + 2])60else:61q = float(vals[i + 1])62i = vals.index("ZUSAMMENSETZUNG", i + 1)63i = vals.index("ZEIT", i)64i = vals.index("VON", i)65von = float(vals[i + 1])66i = vals.index("BIS")67bis = float(vals[i + 1])68return (name, strecke, q, von, bis)697071def parseRouteDecision(rd):72vals = rd.split()73i = vals.index("STRECKE")74strecke = vals[i + 1]75# probably, we would normally already here to iterate over time spans...76i = vals.index("ZEIT", i)77i = vals.index("VON", i + 1)78von = float(vals[i + 1])79i = vals.index("BIS", i + 1)80bis = float(vals[i + 1])81if "ROUTE" in vals:82i = vals.index("ROUTE", i + 1)83else:84i = 085sumAnteil = 086routes = []87while i > 0:88r_id = vals[i + 1]89i = vals.index("STRECKE", i + 1)90r_ziel = vals[i + 1]91i = vals.index("ANTEIL", i + 1)92r_anteil = float(vals[i + 1])93r_edges = []94if vals[i + 2] == "UEBER":95i = i + 396while i < len(vals) and vals[i] != "ROUTE":97if vals[i] in edgemap:98r_edges.append(edgemap[vals[i]])99else:100r_edges.append(vals[i])101i = i + 1102else:103try:104i = vals.index("ROUTE", i)105except Exception:106i = -1107if r_ziel in edgemap:108r_edges.append(edgemap[r_ziel])109else:110r_edges.append(r_ziel)111routes.append((r_id, r_anteil, r_edges))112sumAnteil = sumAnteil + r_anteil113if i >= len(vals):114i = -1115return (strecke, sumAnteil, von, bis, routes)116117118def sorter(idx):119def t(i, j):120if i[idx] < j[idx]:121return -1122elif i[idx] > j[idx]:123return 1124else:125return 0126127128# MAIN129if __name__ == '__main__':130op = sumolib.options.ArgumentParser(description="parse routes from a VISSIM network")131op.add_option("vissimNet", category="input", type=op.file, help="the VISSIM network file")132op.add_option("-o", "--output", default="out", category="output", help="output filename prefix")133op.add_option("-e", "--edgemap", category="input", type=op.edge_list,134help="mapping of edge names for renamed edges (orig1:renamed1,orig2:renamed2,...)")135op.add_option("-s", "--seed", type=int, default=42, category="input", help="random seed")136options = op.parse_args()137138random.seed(options.seed)139edgemap = {}140if options.edgemap:141for entry in options.edgemap.split(","):142orig, renamed = entry.split(":")143edgemap[orig] = renamed144print("Parsing Vissim input...")145fd = codecs.open(options.vissimNet, encoding='latin1')146routeDecisions = []147haveRouteDecision = False148currentRouteDecision = ""149inflows = []150haveInFlow = False151currentInFlow = ""152for line in fd:153# put all route decision ("ROUTENENTSCHEIDUNG") to a list (routeDecisions)154if line.find("ROUTENENTSCHEIDUNG") == 0:155if haveRouteDecision:156routeDecisions.append(" ".join(currentRouteDecision.split()))157haveRouteDecision = True158currentRouteDecision = ""159elif line[0] != ' ':160if haveRouteDecision:161routeDecisions.append(" ".join(currentRouteDecision.split()))162haveRouteDecision = False163if haveRouteDecision:164currentRouteDecision = currentRouteDecision + line165# put all inflows ("ZUFLUSS") to a list (inflows)166if line.find("ZUFLUSS") == 0:167if haveInFlow:168inflows.append(" ".join(currentInFlow.split()))169haveInFlow = True170currentInFlow = ""171elif line[0] != ' ':172if haveInFlow:173inflows.append(" ".join(currentInFlow.split()))174haveInFlow = False175if haveInFlow:176currentInFlow = currentInFlow + line177fd.close()178179# process inflows180print("Writing flows...")181fdo = open(options.output + ".flows.xml", "w")182sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)183flow_sn = 0184for inflow in inflows:185(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))186fdo.write(' <flow id="' + name + '" from="' + strecke + '" begin="' +187str(von) + '" end="' + str(bis) + '" no="' + str(int(q)) + '"/>\n')188flow_sn = flow_sn + 1189fdo.write("</routes>\n")190fdo.close()191192# process combinations193# parse route decision194print("Building routes...")195edges2check = {}196edgesSumFlows = {}197for rd in routeDecisions:198(strecke, sumAnteil, von, bis, routes) = parseRouteDecision(rd)199if strecke not in edges2check:200edgesSumFlows[strecke] = sumAnteil201edges2check[strecke] = (von, bis, routes)202# compute emissions with routes203emissions = []204flow_sn = 0205for inflow in inflows:206(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))207flow_sn = flow_sn + 1208if strecke in edges2check:209routes = edges2check[strecke]210for vi in range(0, int(q)):211t = von + float(bis - von) / float(q) * float(vi)212fi = random.random() * edgesSumFlows[strecke]213edges = []214ri = 0215rid = ""216while len(edges) == 0 and ri < len(routes[2]) and fi >= 0:217fi = fi - routes[2][ri][1]218if fi < 0:219edges = routes[2][ri][2]220rid = routes[2][ri][0]221ri = ri + 1222id = str(name.replace(" ", "_")) + "_" + str(rid) + "_" + str(vi)223if strecke in edgemap:224if edgemap[strecke] not in edges:225edges.insert(0, edgemap[strecke])226else:227if strecke not in edges:228edges.insert(0, strecke)229emissions.append((int(t), id, edges))230# sort emissions231print("Sorting routes...")232emissions.sort(key=sorter(0))233234# save emissions235print("Writing routes...")236fdo = open(options.output + ".rou.xml", "w")237sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)238for emission in emissions:239if len(emission[2]) < 2:240continue241fdo.write(' <vehicle id="' + emission[1] + '" depart="' + str(242emission[0]) + '"><route edges="' + " ".join(emission[2]) + '"/></vehicle>\n')243fdo.write("</routes>\n")244fdo.close()245246247