Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/generateParkingAreas.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 generateParkingAreas.py
15
# @author Jakob Erdmann
16
# @author Mirko Barthauer
17
# @date 2021-11-25
18
19
20
from __future__ import print_function
21
from __future__ import absolute_import
22
import os
23
import sys
24
import random
25
26
if 'SUMO_HOME' in os.environ:
27
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
28
import sumolib # noqa
29
30
31
def get_options(args=None):
32
optParser = sumolib.options.ArgumentParser(description="Generate parking areas along the edges")
33
optParser.add_argument("-n", "--net-file", category="input", dest="netfile",
34
help="define the net file (mandatory)")
35
optParser.add_argument("--selection-file", category="input", dest="selectionfile",
36
help="optionally restrict the parking area to the selected net part")
37
optParser.add_argument("-o", "--output-file", category="output", dest="outfile",
38
default="parkingareas.add.xml", help="define the output filename")
39
optParser.add_argument("-p", "--probability", category="processing", type=float, default=1,
40
help="Probability for an edge to receive a parkingArea")
41
optParser.add_argument("-L", "--length", category="processing", type=float, default=6,
42
help="Length required per parking space")
43
optParser.add_argument("-l", "--space-length", category="processing", type=float, default=5, dest="spaceLength",
44
help="visual length of each parking space")
45
optParser.add_argument("-w", "--width", category="processing", type=float,
46
help="visual width of each parking space")
47
optParser.add_argument("-r", "--random-capacity", category="processing", action="store_true", dest="randCapacity",
48
default=False, help="Randomize roadsideCapacity")
49
optParser.add_argument("--min", category="processing", type=int, default=0,
50
help="Minimum capacity for parkingAreas")
51
optParser.add_argument("--max", category="processing", type=int, default=int(1e9),
52
help="Maximum capacity for parkingAreas")
53
optParser.add_argument("--edge-type.keep", category="processing", dest="edgeTypeKeep",
54
help="Optional list of edge types to keep exclusively")
55
optParser.add_argument("--edge-type.remove", category="processing", dest="edgeTypeRemove",
56
help="Optional list of edge types to exclude")
57
optParser.add_argument("--keep-all", category="processing", action="store_true", default=False, dest="keepAll",
58
help="whether to keep parkingAreas with 0 capacity")
59
optParser.add_argument("--lefthand", category="processing", action="store_true", default=False, dest="lefthand",
60
help="whether to place parkingareas on the left of the road")
61
optParser.add_argument("-a", "--angle", category="processing", type=float,
62
help="parking area angle")
63
optParser.add_argument("--on-road", category="processing", action="store_true", default=False, dest="onRoad",
64
help="whether to place parkingareas directly on the road")
65
optParser.add_argument("--on-road.lane-offset", category="processing", type=int, default=0, dest="onRoadLaneOffset",
66
help="lane index to place on-road parking spaces on (use negative value to use all lanes)")
67
optParser.add_argument("--prefix", category="processing", default="pa", help="prefix for the parkingArea ids")
68
optParser.add_argument("-s", "--seed", category="processing", type=int, default=42, help="random seed")
69
optParser.add_argument("--random", category="processing", action="store_true", default=False,
70
help="use a random seed to initialize the random number generator")
71
optParser.add_argument("--vclass", category="processing", default="passenger",
72
help="only use edges which permit the given vehicle class")
73
optParser.add_argument("-v", "--verbose", category="processing", action="store_true",
74
default=False, help="tell me what you are doing")
75
76
options = optParser.parse_args(args=args)
77
if not options.netfile:
78
optParser.print_help()
79
sys.exit(1)
80
81
if options.edgeTypeKeep:
82
options.edgeTypeKeep = options.edgeTypeKeep.split(',')
83
if options.edgeTypeRemove:
84
options.edgeTypeRemove = options.edgeTypeRemove.split(',')
85
86
return options
87
88
89
def hasOppositeEdge(edge):
90
toNode = edge.getToNode()
91
fromNode = edge.getFromNode()
92
return fromNode in [e.getToNode() for e in toNode.getOutgoing()]
93
94
95
def main(options):
96
if not options.random:
97
random.seed(options.seed)
98
99
net = sumolib.net.readNet(options.netfile)
100
checkSelection = False
101
if options.selectionfile is not None:
102
net.loadSelection(options.selectionfile)
103
checkSelection = True
104
105
with open(options.outfile, 'w') as outf:
106
sumolib.writeXMLHeader(outf, "$Id$", "additional", options=options) # noqa
107
for edge in net.getEdges():
108
if options.edgeTypeKeep and not edge.getType() in options.edgeTypeKeep:
109
continue
110
if options.edgeTypeRemove and edge.getType() in options.edgeTypeRemove:
111
continue
112
if checkSelection and not edge.isSelected():
113
continue
114
lanes = edge.getLanes()
115
if options.lefthand:
116
lanes = reversed(lanes)
117
for lane in lanes:
118
if options.lefthand and lane.getNeigh() is not None:
119
break
120
laneIndex = lane.getIndex()
121
if options.onRoad and options.onRoadLaneOffset > -1:
122
if options.onRoadLaneOffset > laneIndex:
123
continue
124
elif options.onRoadLaneOffset < laneIndex:
125
break
126
if lane.allows(options.vclass):
127
if random.random() < options.probability:
128
capacity = lane.getLength() / options.length
129
if options.randCapacity:
130
capacity *= random.random()
131
if options.verbose and options.min > capacity:
132
print("ParkingArea on edge '%s' exceeds the available space by %.2f spaces "
133
"due to minimum capacity %d." % (edge.getID(), options.min - capacity, options.min))
134
capacity = min(options.max, max(options.min, int(capacity)))
135
if capacity > 0 or capacity == options.max or options.keepAll:
136
angle = '' if options.angle is None else ' angle="%s"' % options.angle
137
length = '' if options.spaceLength <= 0 else ' length="%s"' % options.spaceLength
138
width = '' if options.width is None else ' width="%s"' % options.width
139
onRoad = '' if not options.onRoad else ' onRoad="true"'
140
lefthand = '' if not options.lefthand else ' lefthand="true"'
141
idSuffix = '' if not options.onRoad else '_%s' % laneIndex
142
outf.write(' <parkingArea id="%s%s%s" lane="%s" roadsideCapacity="%s"%s%s%s%s%s/>\n' % (
143
options.prefix, edge.getID(), idSuffix, lane.getID(),
144
capacity, length, width, angle, lefthand, onRoad))
145
if not options.onRoad:
146
break
147
outf.write("</additional>\n")
148
149
150
if __name__ == "__main__":
151
if not main(get_options()):
152
sys.exit(1)
153
154