Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/generateRerouters.py
169659 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2010-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 generateRerouters.py
15
# @author Jakob Erdmann
16
# @date 2023-02-07
17
18
"""
19
This script generates rerouters for a given list of closed edges and
20
automatically finds upstream rerouter edges that permit rerouting.
21
"""
22
from __future__ import print_function
23
from __future__ import absolute_import
24
import os
25
import sys
26
27
if 'SUMO_HOME' in os.environ:
28
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
29
import sumolib # noqa
30
31
32
def get_options(args=None):
33
op = sumolib.options.ArgumentParser(description="Generate rerouter definition for closed edges",)
34
op.add_option("-n", "--net-file", category="input", dest="netfile", type=op.net_file,
35
help="define the net file (mandatory)", required=True)
36
op.add_option("-o", "--output-file", category="output", dest="outfile", type=op.additional_file,
37
help="define the output rerouter filename", default="rerouters.xml")
38
op.add_option("-x", "--closed-edges", category="input", dest="closedEdges", type=op.edge_list,
39
help="provide a comma-separated list of edges to close")
40
op.add_option("-i", "--id-prefix", category="processing", dest="idPrefix", default="rr",
41
help="id prefix for generated rerouters")
42
op.add_option("--vclass", category="processing", default="passenger",
43
help="only consider necessary detours for the given vehicle class (default passenger)")
44
op.add_option("--allow", category="processing", default="authority",
45
help="vClasses that shall be permitted on the closed edge")
46
op.add_option("--disallow", category="processing",
47
help="vClasses that shall be prohibited on the closed edge")
48
op.add_option("-b", "--begin", category="time", default=0, type=float,
49
help="begin time for the closing")
50
op.add_option("-e", "--end", category="time", default=86400, type=float,
51
help="end time for the closing (default 86400)")
52
options = op.parse_args(args=args)
53
if not options.netfile or not options.closedEdges:
54
op.print_help()
55
sys.exit(1)
56
57
options.closedEdges = options.closedEdges.split(',')
58
return options
59
60
61
def findNotifcationEdges(options, net, closedEdges):
62
result = set()
63
64
# close edges in the network
65
for e in closedEdges:
66
for lane in e.getLanes():
67
p = set(lane.getPermissions())
68
p.remove(options.vclass)
69
lane.setPermissions(p)
70
71
for e in closedEdges:
72
reachable = set()
73
for succ in e.getOutgoing().keys():
74
if succ.allows(options.vclass):
75
reachable.update(net.getReachable(succ, options.vclass))
76
77
upstream = []
78
seen = set()
79
for pred in e.getIncoming().keys():
80
if pred.allows(options.vclass):
81
upstream.append(pred)
82
83
while upstream and reachable:
84
cand = upstream.pop(0)
85
seen.add(cand)
86
reachable2 = net.getReachable(cand, options.vclass)
87
found = reachable2.intersection(reachable)
88
if found:
89
result.add(cand)
90
reachable.difference_update(found)
91
for pred in cand.getIncoming().keys():
92
if pred.allows(options.vclass):
93
if pred not in seen:
94
upstream.append(pred)
95
return result
96
97
98
def main(options):
99
net = sumolib.net.readNet(options.netfile)
100
101
closedEdges = []
102
for closedID in options.closedEdges:
103
if not net.hasEdge(closedID):
104
sys.exit("Unknown closed edge '%s'" % closedID)
105
closedEdges.append(net.getEdge(closedID))
106
107
allowDisallow = ""
108
if options.disallow is not None:
109
allowDisallow = ' disallow="%s"' % options.disallow
110
elif options.allow != "":
111
allowDisallow = ' allow="%s"' % options.allow
112
113
with open(options.outfile, 'w') as outf:
114
sumolib.writeXMLHeader(outf, "$Id$", "additional", options=options)
115
116
rerouterEdges = findNotifcationEdges(options, net, closedEdges)
117
rerouterEdgeIDs = sorted([e.getID() for e in rerouterEdges])
118
119
outf.write(' <rerouter id="%s" edges="%s">\n' % (
120
options.idPrefix,
121
' '.join(rerouterEdgeIDs)))
122
outf.write(' <interval begin="%s" end="%s">\n' % (options.begin, options.end))
123
for e in closedEdges:
124
outf.write(' <closingReroute id="%s"%s/>\n' % (e.getID(), allowDisallow))
125
126
outf.write(' </interval>\n')
127
outf.write(' </rerouter>\n')
128
outf.write('</additional>\n')
129
130
131
if __name__ == "__main__":
132
main(get_options())
133
134