1#!/usr/local/bin/python3.8 2# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo 3# Copyright (C) 2009-2019 German Aerospace Center (DLR) and others. 4# This program and the accompanying materials 5# are made available under the terms of the Eclipse Public License v2.0 6# which accompanies this distribution, and is available at 7# http://www.eclipse.org/legal/epl-v20.html 8# SPDX-License-Identifier: EPL-2.0 9 10# @file generateTLSE3Detectors.py 11# @author Daniel Krajzewicz 12# @author Karol Stosiek 13# @author Michael Behrisch 14# @date 2007-10-25 15# @version $Id$ 16 17from __future__ import absolute_import 18from __future__ import print_function 19 20import logging 21import optparse 22import os 23import sys 24 25sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 26import sumolib # noqa 27 28 29def getOptions(): 30 option_parser = optparse.OptionParser() 31 option_parser.add_option("-n", "--net-file", 32 dest="net_file", 33 help="Network file to work with. Mandatory.", 34 type="string") 35 option_parser.add_option("-j", "--junction-ids", 36 dest="junctionIDs", 37 help="List of junctions that shall receive detectors (comma separated)", 38 type="string") 39 option_parser.add_option("-l", "--detector-length", 40 dest="requested_detector_length", 41 help="Length of the detector in meters " 42 "(-1 for maximal length).", 43 type="int", 44 default=250) 45 option_parser.add_option("-d", "--distance-to-TLS", 46 dest="requested_distance_to_tls", 47 help="Distance of the detector to the traffic " 48 "light in meters. Defaults to 0.1m.", 49 type="float", 50 default=.1) 51 option_parser.add_option("-f", "--frequency", 52 dest="frequency", 53 help="Detector's frequency. Defaults to 60.", 54 type="int", 55 default=60) 56 option_parser.add_option("-o", "--output", 57 dest="output", 58 help="The name of the file to write the detector " 59 "definitions into. Defaults to e3.add.xml.", 60 type="string", 61 default="e3.add.xml") 62 option_parser.add_option("--prefix", 63 dest="prefix", 64 help="Prefix for generated detectors", 65 type="string", 66 default="e3_") 67 option_parser.add_option("-r", "--results-file", 68 dest="results", 69 help="The name of the file the detectors write " 70 "their output into. Defaults to e3output.xml.", 71 type="string", 72 default="e3output.xml") 73 option_parser.add_option("--min-pos", 74 dest="minPos", 75 help="minimum position of entry detectors light in meters. Defaults to 0.1m.", 76 type="float", 77 default=.1) 78 79 option_parser.add_option( 80 "--interior", action="store_true", 81 default=False, help="Extend measurement area to the junction interior") 82 option_parser.add_option( 83 "--joined", action="store_true", 84 default=False, help="Create one e3Detector per junction") 85 option_parser.add_option( 86 "--follow-turnaround", dest="followTurnaround", action="store_true", 87 default=False, help="Extend entry detectors past turn-around connections") 88 option_parser.set_usage("generateTLSE3Detectors.py -n example.net.xml " 89 "-l 250 -d .1 -f 60") 90 91 (options, args) = option_parser.parse_args() 92 if not options.net_file: 93 print("Missing arguments") 94 option_parser.print_help() 95 exit() 96 return options 97 98 99def writeEntryExit(options, edge, detector_xml, writeExit=True): 100 stopOnTLS = True 101 stopOnTurnaround = not options.followTurnaround 102 input_edges = network.getDownstreamEdges( 103 edge, options.requested_detector_length, stopOnTLS, stopOnTurnaround) 104 input_edges.sort(key=lambda vals: vals[0].getID()) 105 for firstEdge, position, intermediate, aborted in input_edges: 106 if aborted: 107 position = .1 108 position = max(position, min(options.minPos, firstEdge.getLength())) 109 for lane in firstEdge.getLanes(): 110 detector_entry_xml = detector_xml.addChild("detEntry") 111 detector_entry_xml.setAttribute("lane", lane.getID()) 112 detector_entry_xml.setAttribute("pos", "%.2f" % position) 113 114 if writeExit: 115 if options.interior: 116 # exit just after leaving the intersection 117 for e2 in sorted(edge.getOutgoing(), key=lambda e: e.getID()): 118 for lane in e2.getLanes(): 119 detector_exit_xml = detector_xml.addChild("detExit") 120 detector_exit_xml.setAttribute("lane", lane.getID()) 121 detector_exit_xml.setAttribute("pos", "0") 122 else: 123 # exit just before entering the intersection 124 for lane in edge.getLanes(): 125 detector_exit_xml = detector_xml.addChild("detExit") 126 detector_exit_xml.setAttribute("lane", lane.getID()) 127 detector_exit_xml.setAttribute("pos", "-.1") 128 129 130if __name__ == "__main__": 131 # pylint: disable-msg=C0103 132 options = getOptions() 133 134 logging.basicConfig(level="INFO") 135 136 logging.info("Reading net...") 137 network = sumolib.net.readNet(options.net_file) 138 139 logging.info("Generating detectors...") 140 detectors_xml = sumolib.xml.create_document("additional") 141 generated_detectors = 0 142 143 tlsList, getEdges = network._tlss, sumolib.net.TLS.getEdges 144 if options.junctionIDs: 145 tlsList = [network.getNode(n) for n in options.junctionIDs.split(',')] 146 getEdges = sumolib.net.node.Node.getIncoming 147 148 for tls in tlsList: 149 if options.joined: 150 detector_xml = detectors_xml.addChild("e3Detector") 151 detector_xml.setAttribute("id", options.prefix + str(tls.getID())) 152 detector_xml.setAttribute("freq", str(options.frequency)) 153 detector_xml.setAttribute("file", options.results) 154 generated_detectors += 1 155 writeExit = True 156 for edge in sorted(getEdges(tls), key=sumolib.net.edge.Edge.getID): 157 writeEntryExit(options, edge, detector_xml, writeExit) 158 writeExit = not options.interior 159 160 else: 161 for edge in sorted(getEdges(tls), key=sumolib.net.edge.Edge.getID): 162 detector_xml = detectors_xml.addChild("e3Detector") 163 detector_xml.setAttribute( 164 "id", options.prefix + str(tls.getID()) + "_" + str(edge.getID())) 165 detector_xml.setAttribute("freq", str(options.frequency)) 166 detector_xml.setAttribute("file", options.results) 167 if options.interior: 168 detector_xml.setAttribute("openEntry", "true") 169 writeEntryExit(options, edge, detector_xml) 170 generated_detectors += 1 171 172 detector_file = open(options.output, 'w') 173 detector_file.write(detectors_xml.toXML()) 174 detector_file.close() 175 176 logging.info("%d e3 detectors generated!" % (generated_detectors)) 177