Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/net/reduceLanes.py
169673 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2016-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 reduceLanes.py
15
# @author Jakob Erdmann
16
# @author Michael Behrisch
17
# @date 2016-12-08
18
19
"""
20
build a patch file for the given network that reduces the lanes
21
for edges with more than 2 lanes within a specified range of its nodes
22
"""
23
24
from __future__ import absolute_import
25
from __future__ import print_function
26
27
import os
28
import sys
29
30
if 'SUMO_HOME' in os.environ:
31
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
32
import sumolib # noqa
33
from sumolib.geomhelper import polyLength # noqa
34
35
36
def parse_args():
37
ap = sumolib.options.ArgumentParser()
38
ap.add_argument("-n", "--network", category="input", type=ap.net_file, required=True, help="sumo network to use")
39
ap.add_argument("-o", "--output-file", category="output", type=ap.edgedata_file,
40
default="reduced.edg.xml", help="The output edge patch file name")
41
ap.add_argument("--too-short-output", category="output", type=ap.edgedata_file,
42
help="The output for edges which were ignored because of length")
43
ap.add_argument("--roundabout-output", category="output", type=ap.edgedata_file,
44
help="The output for edges which were ignored because of roundabouts")
45
ap.add_argument("--min-length", type=float, default=60.,
46
help="the minimum edge length to process")
47
ap.add_argument("--min-lane-number", type=int, default=1,
48
help="the minimum number of lanes to process")
49
ap.add_argument("--junction-distance", type=float, default=20.,
50
help="where to perform the edge split near the junction")
51
ap.add_argument("--max-priority", type=int, default=13,
52
help="the maximum priority")
53
return ap.parse_args()
54
55
56
if __name__ == "__main__":
57
options = parse_args()
58
sys.stdout.write("Loading net %s ..." % options.network)
59
sys.stdout.flush()
60
net = sumolib.net.readNet(options.network)
61
sys.stdout.write(" done.\n")
62
63
allRoundabouts = set()
64
for r in net.getRoundabouts():
65
allRoundabouts.update(r.getEdges())
66
67
modifiedEdges = 0
68
tooShort = set()
69
roundabouts = set()
70
with open(options.output_file, 'w') as f:
71
f.write('<edges>\n')
72
totalLength = 0.
73
totalMultiLaneLength = 0.
74
totalReduced = 0.
75
for edge in net.getEdges():
76
edgeID = edge.getID()
77
length = min(polyLength(edge.getShape()), edge.getLength())
78
totalLength += length
79
if edge.getLaneNumber() > options.min_lane_number:
80
totalMultiLaneLength += length
81
if edge.getPriority() <= options.max_priority and edge.getLaneNumber() > options.min_lane_number:
82
if any([lane.getPermissions() in (set(["bus"]), set(["tram"])) for lane in edge.getLanes()]):
83
continue
84
if length >= options.min_length:
85
if edgeID not in allRoundabouts:
86
modifiedEdges += 1
87
lanes = edge.getLaneNumber()
88
f.write(' <edge id="%s">\n' % edgeID)
89
f.write(' <split lanes="%s" pos="%s" idBefore="%s"/>\n' %
90
(" ".join(map(str, range(lanes)[1:])), options.junction_distance, edgeID + ".before"))
91
f.write(' <split pos="%s" idBefore="%s" idAfter="%s"/>\n' %
92
(-options.junction_distance, edgeID, edgeID + ".after"))
93
f.write(' </edge>\n')
94
totalReduced += length - 2 * options.junction_distance
95
else:
96
roundabouts.add(edgeID)
97
else:
98
tooShort.add(edgeID)
99
f.write('</edges>\n')
100
print("added splits for %s edges (%s were to short to qualify and %s were roundabouts)" %
101
(modifiedEdges, len(tooShort), len(roundabouts)))
102
print("total road length: %.2fm, %.2fm total lane reduced length: %.2fm." %
103
(totalLength, totalMultiLaneLength, totalReduced))
104
105
if tooShort and options.too_short_output:
106
with open(options.too_short_output, 'w') as f:
107
for edgeID in tooShort:
108
f.write("edge:%s\n" % edgeID)
109
110
if roundabouts and options.roundabout_output:
111
with open(options.roundabout_output, 'w') as f:
112
for edgeID in roundabouts:
113
f.write("edge:%s\n" % edgeID)
114
115