Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/route/route_departOffset.py
169674 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2008-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 route_departOffset.py
15
# @author Daniel Krajzewicz
16
# @author Michael Behrisch
17
# @date 11.09.2009
18
19
from __future__ import absolute_import
20
from __future__ import print_function
21
import os
22
import sys
23
import codecs
24
25
if 'SUMO_HOME' in os.environ:
26
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
27
sys.path.append(os.path.join(tools))
28
from sumolib.output import parse
29
from sumolib.options import ArgumentParser
30
from sumolib.miscutils import intIfPossible
31
else:
32
sys.exit("please declare environment variable 'SUMO_HOME'")
33
34
35
def get_options(args=None):
36
optParser = ArgumentParser()
37
optParser.add_option("-r", "--input-file", dest="infile",
38
help="the input route file (mandatory)")
39
optParser.add_option("-o", "--output-file", dest="outfile",
40
help="the output route file (mandatory)")
41
optParser.add_option("-d", "--depart-offset", dest="offset",
42
type=float, help="the depart offset to apply")
43
optParser.add_option("-i", "--depart-interval", dest="interval",
44
help="time intervals a,b,c,d where all vehicles departing in the interval" +
45
"[a,b[ are mapped to the interval [c,d[")
46
optParser.add_option("--modify-ids", dest="modify_ids", action="store_true",
47
default=False, help="whether ids should be modified as well")
48
optParser.add_option("--heterogeneous", dest="heterogeneous",
49
action="store_true", default=False, help="whether heterogeneous objects shall be parsed " +
50
"(i.e. vehicles with embedded and referenced routes)")
51
optParser.add_option("--depart-edges", dest="depart_edges",
52
help="only modify departure times of vehicles departing on the given edges")
53
optParser.add_option("--depart-edges.file", dest="depart_edges_file",
54
help="only modify departure times of vehicles departing on edges or lanes in the " +
55
"given selection file")
56
optParser.add_option("--arrival-edges", dest="arrival_edges",
57
help="only modify departure times of vehicles arriving on the given edges")
58
optParser.add_option("--arrival-edges.file", dest="arrival_edges_file",
59
help="only modify departure times of vehicles arriving on edges or lanes in the " +
60
"given selection file")
61
62
options = optParser.parse_args(args=args)
63
if options.infile is None or options.outfile is None:
64
optParser.print_help()
65
sys.exit()
66
67
if ((options.offset is None and options.interval is None) or
68
(options.offset is not None and options.interval is not None)):
69
print("Either one of the options --depart-offset or --depart-interval must be given")
70
sys.exit()
71
72
if options.offset is not None:
73
options.name_suffix = "_%s" % intIfPossible(options.offset)
74
else:
75
options.interval = tuple(map(float, options.interval.split(',')))
76
options.name_suffix = "_%s_%s_%s_%s" % options.interval
77
78
if options.depart_edges is not None:
79
options.depart_edges = options.depart_edges.split(',')
80
81
if options.depart_edges_file is not None:
82
if options.depart_edges is None:
83
options.depart_edges = []
84
with open(options.depart_edges_file) as depart_edges:
85
for line in depart_edges:
86
line = line.strip()
87
if line.startswith("edge:"):
88
options.depart_edges.append(line[5:])
89
elif line.startswith("lane:"):
90
options.depart_edges.append(line[5:-2])
91
else:
92
options.depart_edges.append(line)
93
94
if options.arrival_edges is not None:
95
options.arrival_edges = options.arrival_edges.split(',')
96
97
if options.arrival_edges_file is not None:
98
if options.arrival_edges is None:
99
options.arrival_edges = []
100
for line in open(options.arrival_edges_file):
101
line = line.strip()
102
if line.startswith("edge:"):
103
options.arrival_edges.append(line[5:])
104
elif line.startswith("lane:"):
105
options.arrival_edges.append(line[5:-2])
106
else:
107
options.arrival_edges.append(line)
108
109
return options
110
111
112
def shiftInterval(val, interval):
113
val = float(val)
114
if interval[0] <= val < interval[1]:
115
val = (val - interval[0]) / (interval[1] - interval[0]
116
) * (interval[3] - interval[2]) + interval[2]
117
return str(intIfPossible(val))
118
119
120
def main(options):
121
# cache stand-alone routes
122
routesDepart = {} # first edge for each route
123
routesArrival = {} # last edge for each route
124
125
with codecs.open(options.outfile, 'w', encoding='utf8') as out:
126
out.write("<routes>\n")
127
for route in parse(options.infile, "route"):
128
if route.hasAttribute('id') and route.id is not None:
129
routesDepart[route.id] = route.edges.split()[0]
130
routesArrival[route.id] = route.edges.split()[-1]
131
out.write(route.toXML(' '))
132
133
for obj in parse(options.infile, ['vehicle', 'trip', 'flow', 'vType'],
134
heterogeneous=options.heterogeneous, warn=False):
135
if obj.name == 'vType':
136
# copy
137
pass
138
else:
139
if options.modify_ids:
140
obj.id += options.name_suffix
141
142
# compute depart-edge filter
143
departEdge = None
144
if options.depart_edges is not None:
145
# determine the departEdge of the current vehicle
146
if obj.name == 'trip':
147
departEdge = obj.attr_from
148
elif obj.name == 'vehicle':
149
if obj.hasAttribute('route') and obj.route is not None:
150
departEdge = routesDepart[obj.route]
151
else:
152
# route child element
153
departEdge = obj.route[0].edges.split()[0]
154
elif obj.name == 'flow':
155
if obj.hasAttribute('attr_from') and obj.attr_from is not None:
156
departEdge = obj.attr_from
157
elif obj.hasAttribute('route') and obj.route is not None:
158
departEdge = routesDepart[obj.route]
159
else:
160
# route child element
161
departEdge = obj.route[0].edges.split()[0]
162
163
# compute arrival-edge filter
164
arrivalEdge = None
165
if options.arrival_edges is not None:
166
# determine the arrivalEdge of the current vehicle
167
if obj.name == 'trip':
168
arrivalEdge = obj.to
169
elif obj.name == 'vehicle':
170
if obj.hasAttribute('route') and obj.route is not None:
171
arrivalEdge = routesArrival[obj.route]
172
else:
173
# route child element
174
arrivalEdge = obj.route[0].edges.split()[-1]
175
elif obj.name == 'flow':
176
if obj.hasAttribute('to') and obj.attr_from is not None:
177
arrivalEdge = obj.to
178
elif obj.hasAttribute('route') and obj.route is not None:
179
arrivalEdge = routesArrival[obj.route]
180
else:
181
# route child element
182
arrivalEdge = obj.route[0].edges.split()[-1]
183
184
# modify departure time
185
if ((departEdge is None or departEdge in options.depart_edges) and
186
(arrivalEdge is None or arrivalEdge in options.arrival_edges)):
187
if options.offset is not None:
188
# shift by offset
189
if obj.name in ['trip', 'vehicle']:
190
obj.depart = str(intIfPossible(
191
float(obj.depart) + options.offset))
192
else:
193
obj.begin = str(intIfPossible(
194
float(obj.begin) + options.offset))
195
obj.end = str(intIfPossible(
196
float(obj.end) + options.offset))
197
else:
198
# shift by interval
199
if obj.name in ['trip', 'vehicle']:
200
obj.depart = shiftInterval(
201
obj.depart, options.interval)
202
else:
203
obj.begin = shiftInterval(
204
obj.begin, options.interval)
205
obj.end = shiftInterval(obj.end, options.interval)
206
207
out.write(obj.toXML(' '))
208
out.write("</routes>\n")
209
210
211
if __name__ == "__main__":
212
main(get_options())
213
214