Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/import/vissim/vissim_parseRoutes.py
169679 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2009-2025 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
import codecs
37
if 'SUMO_HOME' in os.environ:
38
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
39
import sumolib # noqa
40
41
42
def getName(vals, beg):
43
name = vals[beg]
44
while name.count('"') != 2:
45
beg = beg + 1
46
name = name + " " + vals[beg]
47
return name.replace('"', '')
48
49
50
def parseInFlow(inflow, suggested_name):
51
vals = inflow.split()
52
i = vals.index("NAME")
53
name = getName(vals, i + 1)
54
if (name == ""):
55
name = suggested_name # SUMO can't cope with empty IDs, unlike VISSIM
56
i = vals.index("STRECKE", i)
57
strecke = vals[i + 1]
58
i = vals.index("Q", i + 1)
59
if vals[i + 1] == "EXAKT":
60
q = float(vals[i + 2])
61
else:
62
q = float(vals[i + 1])
63
i = vals.index("ZUSAMMENSETZUNG", i + 1)
64
i = vals.index("ZEIT", i)
65
i = vals.index("VON", i)
66
von = float(vals[i + 1])
67
i = vals.index("BIS")
68
bis = float(vals[i + 1])
69
return (name, strecke, q, von, bis)
70
71
72
def parseRouteDecision(rd):
73
vals = rd.split()
74
i = vals.index("STRECKE")
75
strecke = vals[i + 1]
76
# probably, we would normally already here to iterate over time spans...
77
i = vals.index("ZEIT", i)
78
i = vals.index("VON", i + 1)
79
von = float(vals[i + 1])
80
i = vals.index("BIS", i + 1)
81
bis = float(vals[i + 1])
82
if "ROUTE" in vals:
83
i = vals.index("ROUTE", i + 1)
84
else:
85
i = 0
86
sumAnteil = 0
87
routes = []
88
while i > 0:
89
r_id = vals[i + 1]
90
i = vals.index("STRECKE", i + 1)
91
r_ziel = vals[i + 1]
92
i = vals.index("ANTEIL", i + 1)
93
r_anteil = float(vals[i + 1])
94
r_edges = []
95
if vals[i + 2] == "UEBER":
96
i = i + 3
97
while i < len(vals) and vals[i] != "ROUTE":
98
if vals[i] in edgemap:
99
r_edges.append(edgemap[vals[i]])
100
else:
101
r_edges.append(vals[i])
102
i = i + 1
103
else:
104
try:
105
i = vals.index("ROUTE", i)
106
except Exception:
107
i = -1
108
if r_ziel in edgemap:
109
r_edges.append(edgemap[r_ziel])
110
else:
111
r_edges.append(r_ziel)
112
routes.append((r_id, r_anteil, r_edges))
113
sumAnteil = sumAnteil + r_anteil
114
if i >= len(vals):
115
i = -1
116
return (strecke, sumAnteil, von, bis, routes)
117
118
119
def sorter(idx):
120
def t(i, j):
121
if i[idx] < j[idx]:
122
return -1
123
elif i[idx] > j[idx]:
124
return 1
125
else:
126
return 0
127
128
129
# MAIN
130
if __name__ == '__main__':
131
op = sumolib.options.ArgumentParser(description="parse routes from a VISSIM network")
132
op.add_option("vissimNet", category="input", type=op.file, help="the VISSIM network file")
133
op.add_option("-o", "--output", default="out", category="output", help="output filename prefix")
134
op.add_option("-e", "--edgemap", category="input", type=op.edge_list,
135
help="mapping of edge names for renamed edges (orig1:renamed1,orig2:renamed2,...)")
136
op.add_option("-s", "--seed", type=int, default=42, category="input", help="random seed")
137
options = op.parse_args()
138
139
random.seed(options.seed)
140
edgemap = {}
141
if options.edgemap:
142
for entry in options.edgemap.split(","):
143
orig, renamed = entry.split(":")
144
edgemap[orig] = renamed
145
print("Parsing Vissim input...")
146
fd = codecs.open(options.vissimNet, encoding='latin1')
147
routeDecisions = []
148
haveRouteDecision = False
149
currentRouteDecision = ""
150
inflows = []
151
haveInFlow = False
152
currentInFlow = ""
153
for line in fd:
154
# put all route decision ("ROUTENENTSCHEIDUNG") to a list (routeDecisions)
155
if line.find("ROUTENENTSCHEIDUNG") == 0:
156
if haveRouteDecision:
157
routeDecisions.append(" ".join(currentRouteDecision.split()))
158
haveRouteDecision = True
159
currentRouteDecision = ""
160
elif line[0] != ' ':
161
if haveRouteDecision:
162
routeDecisions.append(" ".join(currentRouteDecision.split()))
163
haveRouteDecision = False
164
if haveRouteDecision:
165
currentRouteDecision = currentRouteDecision + line
166
# put all inflows ("ZUFLUSS") to a list (inflows)
167
if line.find("ZUFLUSS") == 0:
168
if haveInFlow:
169
inflows.append(" ".join(currentInFlow.split()))
170
haveInFlow = True
171
currentInFlow = ""
172
elif line[0] != ' ':
173
if haveInFlow:
174
inflows.append(" ".join(currentInFlow.split()))
175
haveInFlow = False
176
if haveInFlow:
177
currentInFlow = currentInFlow + line
178
fd.close()
179
180
# process inflows
181
print("Writing flows...")
182
fdo = open(options.output + ".flows.xml", "w")
183
sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)
184
flow_sn = 0
185
for inflow in inflows:
186
(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))
187
fdo.write(' <flow id="' + name + '" from="' + strecke + '" begin="' +
188
str(von) + '" end="' + str(bis) + '" no="' + str(int(q)) + '"/>\n')
189
flow_sn = flow_sn + 1
190
fdo.write("</routes>\n")
191
fdo.close()
192
193
# process combinations
194
# parse route decision
195
print("Building routes...")
196
edges2check = {}
197
edgesSumFlows = {}
198
for rd in routeDecisions:
199
(strecke, sumAnteil, von, bis, routes) = parseRouteDecision(rd)
200
if strecke not in edges2check:
201
edgesSumFlows[strecke] = sumAnteil
202
edges2check[strecke] = (von, bis, routes)
203
# compute emissions with routes
204
emissions = []
205
flow_sn = 0
206
for inflow in inflows:
207
(name, strecke, q, von, bis) = parseInFlow(inflow, str(flow_sn))
208
flow_sn = flow_sn + 1
209
if strecke in edges2check:
210
routes = edges2check[strecke]
211
for vi in range(0, int(q)):
212
t = von + float(bis - von) / float(q) * float(vi)
213
fi = random.random() * edgesSumFlows[strecke]
214
edges = []
215
ri = 0
216
rid = ""
217
while len(edges) == 0 and ri < len(routes[2]) and fi >= 0:
218
fi = fi - routes[2][ri][1]
219
if fi < 0:
220
edges = routes[2][ri][2]
221
rid = routes[2][ri][0]
222
ri = ri + 1
223
id = str(name.replace(" ", "_")) + "_" + str(rid) + "_" + str(vi)
224
if strecke in edgemap:
225
if edgemap[strecke] not in edges:
226
edges.insert(0, edgemap[strecke])
227
else:
228
if strecke not in edges:
229
edges.insert(0, strecke)
230
emissions.append((int(t), id, edges))
231
# sort emissions
232
print("Sorting routes...")
233
emissions.sort(key=sorter(0))
234
235
# save emissions
236
print("Writing routes...")
237
fdo = open(options.output + ".rou.xml", "w")
238
sumolib.writeXMLHeader(fdo, "$Id$", "routes", options=options)
239
for emission in emissions:
240
if len(emission[2]) < 2:
241
continue
242
fdo.write(' <vehicle id="' + emission[1] + '" depart="' + str(
243
emission[0]) + '"><route edges="' + " ".join(emission[2]) + '"/></vehicle>\n')
244
fdo.write("</routes>\n")
245
fdo.close()
246
247