Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/import/vissim/vissim_parseRoutes.py
194342 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2009-2026 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file vissim_parseRoutes.py
15
# @author Daniel Krajzewicz
16
# @author Michael Behrisch
17
# @date 2009-05-27
18
19
"""
20
21
Parses routes given in the Vissim file (first parameter) as (in-)flows and
22
route decisions.
23
24
The read flows are saved as <OUTPUT_PREFIX>.flows.xml
25
The read routes are saved as <OUTPUT_PREFIX>.rou.xml
26
27
(Starting?) edges of the route may be renamed by setting them with "edgemap"
28
option (see below).
29
"""
30
from __future__ import absolute_import
31
from __future__ import print_function
32
33
import os
34
import sys
35
import random
36
if 'SUMO_HOME' in os.environ:
37
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
38
import sumolib # noqa
39
40
41
def getName(vals, beg):
42
name = vals[beg]
43
while name.count('"') != 2:
44
beg = beg + 1
45
name = name + " " + vals[beg]
46
return name.replace('"', '')
47
48
49
def parseInFlow(inflow, suggested_name):
50
vals = inflow.split()
51
i = vals.index("NAME")
52
name = getName(vals, i + 1)
53
if (name == ""):
54
name = suggested_name # SUMO can't cope with empty IDs, unlike VISSIM
55
i = vals.index("STRECKE", i)
56
strecke = vals[i + 1]
57
i = vals.index("Q", i + 1)
58
if vals[i + 1] == "EXAKT":
59
q = float(vals[i + 2])
60
else:
61
q = float(vals[i + 1])
62
i = vals.index("ZUSAMMENSETZUNG", i + 1)
63
i = vals.index("ZEIT", i)
64
i = vals.index("VON", i)
65
von = float(vals[i + 1])
66
i = vals.index("BIS")
67
bis = float(vals[i + 1])
68
return (name, strecke, q, von, bis)
69
70
71
def parseRouteDecision(rd):
72
vals = rd.split()
73
i = vals.index("STRECKE")
74
strecke = vals[i + 1]
75
# probably, we would normally already here to iterate over time spans...
76
i = vals.index("ZEIT", i)
77
i = vals.index("VON", i + 1)
78
von = float(vals[i + 1])
79
i = vals.index("BIS", i + 1)
80
bis = float(vals[i + 1])
81
if "ROUTE" in vals:
82
i = vals.index("ROUTE", i + 1)
83
else:
84
i = 0
85
sumAnteil = 0
86
routes = []
87
while i > 0:
88
r_id = vals[i + 1]
89
i = vals.index("STRECKE", i + 1)
90
r_ziel = vals[i + 1]
91
i = vals.index("ANTEIL", i + 1)
92
r_anteil = float(vals[i + 1])
93
r_edges = []
94
if vals[i + 2] == "UEBER":
95
i = i + 3
96
while i < len(vals) and vals[i] != "ROUTE":
97
if vals[i] in edgemap:
98
r_edges.append(edgemap[vals[i]])
99
else:
100
r_edges.append(vals[i])
101
i = i + 1
102
else:
103
try:
104
i = vals.index("ROUTE", i)
105
except Exception:
106
i = -1
107
if r_ziel in edgemap:
108
r_edges.append(edgemap[r_ziel])
109
else:
110
r_edges.append(r_ziel)
111
routes.append((r_id, r_anteil, r_edges))
112
sumAnteil = sumAnteil + r_anteil
113
if i >= len(vals):
114
i = -1
115
return (strecke, sumAnteil, von, bis, routes)
116
117
118
def sorter(idx):
119
def t(i, j):
120
if i[idx] < j[idx]:
121
return -1
122
elif i[idx] > j[idx]:
123
return 1
124
else:
125
return 0
126
127
128
# MAIN
129
if __name__ == '__main__':
130
op = sumolib.options.ArgumentParser(description="parse routes from a VISSIM network")
131
op.add_option("vissimNet", category="input", type=op.file, help="the VISSIM network file")
132
op.add_option("-o", "--output", default="out", category="output", help="output filename prefix")
133
op.add_option("-e", "--edgemap", category="input", type=op.edge_list,
134
help="mapping of edge names for renamed edges (orig1:renamed1,orig2:renamed2,...)")
135
op.add_option("-s", "--seed", type=int, default=42, category="input", help="random seed")
136
options = op.parse_args()
137
138
random.seed(options.seed)
139
edgemap = {}
140
if options.edgemap:
141
for entry in options.edgemap.split(","):
142
orig, renamed = entry.split(":")
143
edgemap[orig] = renamed
144
print("Parsing Vissim input...")
145
fd = sumolib.openz(options.vissimNet, encoding='latin1')
146
routeDecisions = []
147
haveRouteDecision = False
148
currentRouteDecision = ""
149
inflows = []
150
haveInFlow = False
151
currentInFlow = ""
152
for line in fd:
153
# put all route decision ("ROUTENENTSCHEIDUNG") to a list (routeDecisions)
154
if line.find("ROUTENENTSCHEIDUNG") == 0:
155
if haveRouteDecision:
156
routeDecisions.append(" ".join(currentRouteDecision.split()))
157
haveRouteDecision = True
158
currentRouteDecision = ""
159
elif line[0] != ' ':
160
if haveRouteDecision:
161
routeDecisions.append(" ".join(currentRouteDecision.split()))
162
haveRouteDecision = False
163
if haveRouteDecision:
164
currentRouteDecision = currentRouteDecision + line
165
# put all inflows ("ZUFLUSS") to a list (inflows)
166
if line.find("ZUFLUSS") == 0:
167
if haveInFlow:
168
inflows.append(" ".join(currentInFlow.split()))
169
haveInFlow = True
170
currentInFlow = ""
171
elif line[0] != ' ':
172
if haveInFlow:
173
inflows.append(" ".join(currentInFlow.split()))
174
haveInFlow = False
175
if haveInFlow:
176
currentInFlow = currentInFlow + line
177
fd.close()
178
179
# process inflows
180
print("Writing flows...")
181
fdo = open(options.output + ".flows.xml", "w")
182
sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)
183
flow_sn = 0
184
for inflow in inflows:
185
(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))
186
fdo.write(' <flow id="' + name + '" from="' + strecke + '" begin="' +
187
str(von) + '" end="' + str(bis) + '" no="' + str(int(q)) + '"/>\n')
188
flow_sn = flow_sn + 1
189
fdo.write("</routes>\n")
190
fdo.close()
191
192
# process combinations
193
# parse route decision
194
print("Building routes...")
195
edges2check = {}
196
edgesSumFlows = {}
197
for rd in routeDecisions:
198
(strecke, sumAnteil, von, bis, routes) = parseRouteDecision(rd)
199
if strecke not in edges2check:
200
edgesSumFlows[strecke] = sumAnteil
201
edges2check[strecke] = (von, bis, routes)
202
# compute emissions with routes
203
emissions = []
204
flow_sn = 0
205
for inflow in inflows:
206
(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))
207
flow_sn = flow_sn + 1
208
if strecke in edges2check:
209
routes = edges2check[strecke]
210
for vi in range(0, int(q)):
211
t = von + float(bis - von) / float(q) * float(vi)
212
fi = random.random() * edgesSumFlows[strecke]
213
edges = []
214
ri = 0
215
rid = ""
216
while len(edges) == 0 and ri < len(routes[2]) and fi >= 0:
217
fi = fi - routes[2][ri][1]
218
if fi < 0:
219
edges = routes[2][ri][2]
220
rid = routes[2][ri][0]
221
ri = ri + 1
222
id = str(name.replace(" ", "_")) + "_" + str(rid) + "_" + str(vi)
223
if strecke in edgemap:
224
if edgemap[strecke] not in edges:
225
edges.insert(0, edgemap[strecke])
226
else:
227
if strecke not in edges:
228
edges.insert(0, strecke)
229
emissions.append((int(t), id, edges))
230
# sort emissions
231
print("Sorting routes...")
232
emissions.sort(key=sorter(0))
233
234
# save emissions
235
print("Writing routes...")
236
fdo = open(options.output + ".rou.xml", "w")
237
sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)
238
for emission in emissions:
239
if len(emission[2]) < 2:
240
continue
241
fdo.write(' <vehicle id="' + emission[1] + '" depart="' + str(
242
emission[0]) + '"><route edges="' + " ".join(emission[2]) + '"/></vehicle>\n')
243
fdo.write("</routes>\n")
244
fdo.close()
245
246