Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/output/generateDetectors.py
194025 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2009-2026 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 generateDetectors.py
15
# @author Jakob Erdmann
16
# @date 2025-04-13
17
18
from __future__ import absolute_import
19
from __future__ import print_function
20
21
import os
22
import sys
23
import random
24
25
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
26
import sumolib # noqa
27
from sumolib.options import ArgumentParser # noqa
28
from sumolib.miscutils import openz # noqa
29
30
SHORT_NAMES = {
31
'E1': 'inductionLoop',
32
'E1I': 'instantInductionLoop',
33
'E2': 'laneAreaDetector',
34
# 'E3': 'multiEntryExitDetector'
35
}
36
37
NEED_EXTENT = ['laneAreaDetector',
38
# 'multiEntryExitDetector'
39
]
40
41
42
def get_options(args=None):
43
ap = ArgumentParser(description="Generate detectors on selected network edges")
44
ap.add_option("-n", "--net-file", dest="net_file", type=ap.net_file, required=True,
45
help="Network file to work with. Mandatory.")
46
ap.add_option("-o", "--output", required=True, type=ap.additional_file,
47
help="The name of the file to write the detectors to")
48
ap.add_option("--period", type=int, default=60,
49
help="Aggregation period in s")
50
ap.add_option("--prefix", default="",
51
help="prefix for the detectors ids")
52
ap.add_option("-r", "--results-file", dest="results", type=ap.file, default="det.out.xml",
53
help="The name of the file the detectors write their output into. Defaults to det.out.xml.")
54
ap.add_option("--relpos", default=0.5,
55
help="relative detector position along the edge [0,1] or 'random'")
56
ap.add_option("--probability", type=float, default=1,
57
help="build detector with the given probability ]0, 1] (lanewise)")
58
ap.add_option("--edge-probability", type=float, default=1, dest="edgeProbability",
59
help="build detector with the given probability ]0, 1] (edgewise)")
60
ap.add_option("-t", "--detector-type", dest="dType", default="inductionLoop",
61
help="one of %s or the corresponding shortcut %s" % (
62
list(SHORT_NAMES.values()),
63
list(SHORT_NAMES.keys())))
64
ap.add_option("--vclass", default="passenger",
65
help="only place detectors on lanes that permit the given vehicle class")
66
ap.add_option("--length", type=float,
67
help="Set length for detector types that support it")
68
ap.add_option("--next", action="store_true", default=False,
69
help="generate nextEdges attribute and additional detectors for lanes with multiple targets")
70
ap.add_option("-s", "--seed", type=int, default=42, help="random seed")
71
ap.add_option("-v", "--verbose", action="store_true", default=False,
72
help="tell me what you are doing")
73
options = ap.parse_args(args=args)
74
75
options.dType = SHORT_NAMES.get(options.dType, options.dType)
76
77
if options.dType not in SHORT_NAMES.values():
78
sys.exit("Unsupported value '%s' for option --detector-type ")
79
80
if options.relpos is not None:
81
try:
82
options.relpos = max(0, min(1, float(options.relpos)))
83
options.getRelpos = lambda lane: lane.getLength() * options.relpos
84
except ValueError:
85
if options.relpos == 'random':
86
options.getRelpos = lambda lane: lane.getLength() * random.random()
87
else:
88
sys.exit("option --relpos must be set to 'random' or to a float value from [0,1]")
89
90
if options.length and options.dType == "instantInductionLoop":
91
sys.exit("Unsupported option --length for detector-type %s" % options.dType)
92
93
return options
94
95
96
def main(options):
97
random.seed(options.seed)
98
99
if options.verbose:
100
print("Reading net '%s'..." % options.net_file)
101
net = sumolib.net.readNet(options.net_file)
102
103
if options.verbose:
104
print("Generating detectors...")
105
106
numWritten = 0
107
with openz(options.output, 'w') as fout:
108
sumolib.writeXMLHeader(fout, "$Id$", "additional", options=options)
109
period = '' if options.dType == "instantInductionLoop" else 'period="%s" ' % options.period
110
length = '' if options.length is None else 'length="%s" ' % options.length
111
endPos = ''
112
friendlyPos = ''
113
if length != '':
114
friendlyPos = 'friendlyPos="true" '
115
elif options.dType in NEED_EXTENT:
116
endPos = 'endPos="-1" '
117
118
def writeDet(options, lane, numWritten, nextEdge=None):
119
fout.write(' <%s id="%s%s%s" lane="%s" pos="%s" %s%s%s%s%sfile="%s"/>\n' % (
120
options.dType,
121
options.prefix, lane.getID(),
122
'_%s' % nextEdge.getID() if nextEdge else '',
123
lane.getID(),
124
"%.2f" % options.getRelpos(lane),
125
period, length, endPos, friendlyPos,
126
'nextEdges="%s" ' % nextEdge.getID() if nextEdge else "",
127
options.results))
128
numWritten += 1
129
130
for edge in net.getEdges():
131
if options.edgeProbability < 1 and random.random() > options.edgeProbability:
132
continue
133
for lane in edge.getLanes():
134
if not lane.allows(options.vclass):
135
continue
136
if options.probability < 1 and random.random() > options.probability:
137
continue
138
if options.next and len(lane.getOutgoing()) > 1:
139
for edge in lane.getOutgoingEdges():
140
writeDet(options, lane, numWritten, edge)
141
else:
142
writeDet(options, lane, numWritten)
143
144
fout.write('</additional>\n')
145
146
if options.verbose:
147
print("Wrote %s detectors." % numWritten)
148
149
150
if __name__ == "__main__":
151
main(get_options())
152
153