Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
NIXMLTrafficLightsHandler.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2011-2024 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/****************************************************************************/
20// Importer for traffic lights stored in XML
21/****************************************************************************/
22#include <config.h>
23
24#include <string>
25#include <iostream>
34#include <netbuild/NBEdge.h>
35#include <netbuild/NBEdgeCont.h>
36#include <netbuild/NBNode.h>
37#include <netbuild/NBOwnTLDef.h>
40#include "NIImporter_SUMO.h"
42
43
44// ===========================================================================
45// method definitions
46// ===========================================================================
48 NBTrafficLightLogicCont& tlCont, NBEdgeCont& ec, bool ignoreUnknown) :
49 SUMOSAXHandler("xml-tllogics"),
50 myTLLCont(tlCont),
51 myEdgeCont(ec),
52 myCurrentTL(nullptr),
53 myResetPhases(false),
54 myIgnoreUnknown(ignoreUnknown)
55{ }
56
57
59
60
61void
63 int element, const SUMOSAXAttributes& attrs) {
64 switch (element) {
67 break;
68 case SUMO_TAG_PHASE:
69 if (myCurrentTL != nullptr) {
70 if (myResetPhases) {
72 myResetPhases = false;
73 }
76 }
77 break;
79 addTlConnection(attrs);
80 break;
81 case SUMO_TAG_DEL:
82 removeTlConnection(attrs);
83 break;
84 case SUMO_TAG_PARAM:
85 if (myCurrentTL != nullptr) {
86 bool ok = true;
87 const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
88 // circumventing empty string test
89 const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
90 myCurrentTL->setParameter(key, val);
91 }
92 break;
93 default:
94 break;
95 }
96}
97
98
99void
101 switch (element) {
102 case SUMO_TAG_TLLOGIC:
103 myCurrentTL = nullptr;
104 break;
105 default:
106 break;
107 }
108}
109
110
113 if (currentTL) {
114 WRITE_ERRORF(TL("Definition of tlLogic '%' was not finished."), currentTL->getID());
115 return nullptr;
116 }
117 bool ok = true;
118 std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
119 std::string programID = attrs.getOpt<std::string>(SUMO_ATTR_PROGRAMID, id.c_str(), ok, "UNKNOWN_PROGRAM");
120 SUMOTime offset = attrs.hasAttribute(SUMO_ATTR_OFFSET) ? TIME2STEPS(attrs.get<double>(SUMO_ATTR_OFFSET, id.c_str(), ok)) : 0;
121 std::string typeS = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, nullptr, ok,
122 OptionsCont::getOptions().getString("tls.default-type"));
123 TrafficLightType type;
124 if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
126 } else {
127 WRITE_ERRORF(TL("Unknown traffic light type '%' for tlLogic '%'."), typeS, id);
128 return nullptr;
129 }
130 // there are three scenarios to consider
131 // 1) the tll.xml is loaded to update traffic lights defined in a net.xml:
132 // simply retrieve the loaded definitions and update them
133 // 2) the tll.xml is loaded to define new traffic lights
134 // nod.xml will have triggered building of NBOwnTLDef. Replace it with NBLoadedSUMOTLDef
135 // 3) the tll.xml is loaded to define new programs for a defined traffic light
136 // there should be a definition with the same id but different programID
137 const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(id);
138 if (programs.size() == 0) {
139 if (!myIgnoreUnknown) {
140 WRITE_ERRORF(TL("Cannot load traffic light program for unknown id '%', programID '%'."), id, programID);
141 }
142 return nullptr;
143 }
144 const std::string existingProgram = programs.begin()->first; // arbitrary for our purpose
145 NBLoadedSUMOTLDef* loadedDef = dynamic_cast<NBLoadedSUMOTLDef*>(myTLLCont.getDefinition(id, programID));
146 if (loadedDef == nullptr) {
147 NBLoadedSUMOTLDef* oldDef = dynamic_cast<NBLoadedSUMOTLDef*>(myTLLCont.getDefinition(id, existingProgram));
148 if (oldDef == nullptr) {
149 // case 2
152 bool deleteDefault = false;
153 if (newDef == nullptr) {
154 // the default program may have already been replaced with a loaded program
155 newDef = dynamic_cast<NBLoadedSUMOTLDef*>(myTLLCont.getDefinition(
157 if (newDef == nullptr) {
158 WRITE_ERRORF(TL("Cannot load traffic light program for unknown id '%', programID '%'."), id, programID);
159 return nullptr;
160 }
161 } else {
162 deleteDefault = true;
163 }
164 assert(newDef != nullptr);
165 loadedDef = new NBLoadedSUMOTLDef(id, programID, offset, type);
166 // copy nodes and controlled inner edges
167 for (NBNode* const n : newDef->getNodes()) {
168 loadedDef->addNode(n);
169 }
171 if (deleteDefault) {
172 // make a copy because the vector is modified in the loop
173 const std::vector<NBNode*> nodes = newDef->getNodes();
174 // replace default Program
175 for (NBNode* const n : nodes) {
176 n->removeTrafficLight(newDef);
177 }
179 }
180 myTLLCont.insert(loadedDef);
181 } else {
182 // case 3
183 NBTrafficLightLogic* oldLogic = oldDef->getLogic();
184 NBTrafficLightLogic newLogic(id, programID, oldLogic->getNumLinks(), offset, type);
185 loadedDef = new NBLoadedSUMOTLDef(*oldDef, newLogic);
186 // copy nodes
187 std::vector<NBNode*> nodes = oldDef->getNodes();
188 for (std::vector<NBNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
189 loadedDef->addNode(*it);
190 }
191 //std::cout << " case3 oldDef=" << oldDef->getDescription() << " loadedDef=" << loadedDef->getDescription() << "\n";
192 myTLLCont.insert(loadedDef);
193 }
194 } else {
195 // case 1
196 if (attrs.hasAttribute(SUMO_ATTR_OFFSET)) {
197 loadedDef->setOffset(offset);
198 }
199 if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
200 loadedDef->setType(type);
201 }
202 }
203 if (ok) {
204 myResetPhases = true;
205 mySeenIDs.insert(id);
206 return loadedDef;
207 } else {
208 return nullptr;
209 }
210}
211
212
213void
215 bool ok = true;
216 // parse identifying attributes
217 NBEdge* from = retrieveEdge(attrs, SUMO_ATTR_FROM, ok);
218 NBEdge* to = retrieveEdge(attrs, SUMO_ATTR_TO, ok);
219 if (!ok) {
220 return;
221 }
222 int fromLane = retrieveLaneIndex(attrs, SUMO_ATTR_FROM_LANE, from, ok);
223 int toLane = retrieveLaneIndex(attrs, SUMO_ATTR_TO_LANE, to, ok);
224 if (!ok) {
225 return;
226 }
227 // retrieve connection
228 const std::vector<NBEdge::Connection>& connections = from->getConnections();
229 std::vector<NBEdge::Connection>::const_iterator con_it;
230 con_it = find_if(connections.begin(), connections.end(),
231 NBEdge::connections_finder(fromLane, to, toLane));
232 if (con_it == connections.end()) {
233 WRITE_ERROR("Connection from=" + from->getID() + " to=" + to->getID() +
234 " fromLane=" + toString(fromLane) + " toLane=" + toString(toLane) + " not found");
235 return;
236 }
237 NBEdge::Connection c = *con_it;
238 // read other attributes
239 std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, nullptr, ok, "");
240 if (tlID == "") {
241 // we are updating an existing tl-controlled connection
242 tlID = (*(from->getToNode()->getControllingTLS().begin()))->getID();
243 assert(tlID != "");
244 }
245 int tlIndex = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX, nullptr, ok, -1);
246 if (tlIndex == -1) {
247 // we are updating an existing tl-controlled connection
248 tlIndex = c.tlLinkIndex;
249 }
250 int tlIndex2 = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX2, nullptr, ok, -1);
251 if (tlIndex2 == -1) {
252 // we are updating an existing tl-controlled connection or index2 is not used
253 tlIndex2 = c.tlLinkIndex2;
254 }
255
256 // register the connection with all definitions
257 const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(tlID);
258 if (programs.size() > 0) {
259 std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
260 for (it = programs.begin(); it != programs.end(); it++) {
261 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
262 if (tlDef) {
263 tlDef->addConnection(from, c.toEdge, c.fromLane, c.toLane, tlIndex, tlIndex2, false);
264 } else {
265 throw ProcessError("Corrupt traffic light definition '"
266 + tlID + "' (program '" + it->first + "')");
267 }
268 }
269 } else {
270 SumoXMLNodeType type = from->getToNode()->getType();
272 WRITE_ERRORF(TL("The traffic light '%' is not known."), tlID);
273 }
274 }
275}
276
277
278void
280 bool ok = true;
281 std::string tlID = attrs.get<std::string>(SUMO_ATTR_TLID, nullptr, ok);
282 // does the traffic light still exist?
283 const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(tlID);
284 if (programs.size() > 0) {
285 // parse identifying attributes
286 NBEdge* from = retrieveEdge(attrs, SUMO_ATTR_FROM, ok);
287 NBEdge* to = retrieveEdge(attrs, SUMO_ATTR_TO, ok);
288 int fromLane = -1;
289 int toLane = -1;
290 if (ok) {
291 fromLane = retrieveLaneIndex(attrs, SUMO_ATTR_FROM_LANE, from, ok, true);
292 toLane = retrieveLaneIndex(attrs, SUMO_ATTR_TO_LANE, to, ok, true);
293 }
294 int tlIndex = attrs.get<int>(SUMO_ATTR_TLLINKINDEX, nullptr, ok);
295
296 NBConnection conn(from, fromLane, to, toLane, tlIndex);
297 // remove the connection from all definitions
298 std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
299 for (it = programs.begin(); it != programs.end(); it++) {
300 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
301 if (tlDef) {
302 tlDef->removeConnection(conn, false);
303 } else {
304 throw ProcessError("Corrupt traffic light definition '"
305 + tlID + "' (program '" + it->first + "')");
306 }
307 }
308 }
309}
310
311
312NBEdge*
314 const SUMOSAXAttributes& attrs, SumoXMLAttr attr, bool& ok) {
315 std::string edgeID = attrs.get<std::string>(attr, nullptr, ok);
316 NBEdge* edge = myEdgeCont.retrieve(edgeID, true);
317 if (edge == nullptr) {
318 WRITE_ERRORF(TL("Unknown edge '%' given in connection."), edgeID);
319 ok = false;
320 }
321 return edge;
322}
323
324
325int
327 const SUMOSAXAttributes& attrs, SumoXMLAttr attr, NBEdge* edge, bool& ok, bool isDelete) {
328 int laneIndex = attrs.get<int>(attr, nullptr, ok);
329 if (edge->getNumLanes() <= laneIndex) {
330 if (!isDelete) {
331 WRITE_ERRORF(TL("Invalid lane index '%' for edge '%'."), toString(laneIndex), edge->getID());
332 }
333 ok = false;
334 }
335 return laneIndex;
336}
337
338
339/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_ERRORF(...)
Definition MsgHandler.h:305
#define WRITE_ERROR(msg)
Definition MsgHandler.h:304
#define TL(string)
Definition MsgHandler.h:315
#define TIME2STEPS(x)
Definition SUMOTime.h:57
@ SUMO_TAG_PHASE
a single phase description
@ SUMO_TAG_CONNECTION
connectioon between two lanes
@ SUMO_TAG_TLLOGIC
a traffic light logic
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_TAG_DEL
delete certain element (note: DELETE is a macro)
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_TLLINKINDEX2
link: the index of the opposite direction link of a pedestrian crossing
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_FROM_LANE
@ SUMO_ATTR_OFFSET
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_TO_LANE
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
@ SUMO_ATTR_KEY
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
Storage for edges, including some functionality operating on multiple edges.
Definition NBEdgeCont.h:59
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
The representation of a single edge during network building.
Definition NBEdge.h:92
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1041
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:546
const std::string & getID() const
Definition NBEdge.h:1528
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:520
A loaded (complete) traffic light logic.
void phasesLoaded()
mark phases as load
NBTrafficLightLogic * getLogic()
Returns the internal logic.
void removeConnection(const NBConnection &conn, bool reconstruct=true)
removes the given connection from the traffic light if recontruct=true, reconstructs the logic and in...
void setType(TrafficLightType type)
Sets the algorithm type of this tls.
void addConnection(NBEdge *from, NBEdge *to, int fromLane, int toLane, int linkIndex, int linkIndex2, bool reconstruct=true)
Adds a connection and immediately informs the edges.
void setOffset(SUMOTime offset)
Sets the offset of this tls.
Represents a single node (junction) during network building.
Definition NBNode.h:66
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition NBNode.h:336
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
A traffic light logics which must be computed (only nodes/edges are given)
Definition NBOwnTLDef.h:44
The base class for traffic light logic definitions.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
void addControlledInnerEdges(const std::vector< std::string > &edges)
Adds the given ids into the list of inner edges controlled by the tls.
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
std::vector< std::string > getControlledInnerEdges() const
Retrieve the ids of edges explicitly controlled by the tls.
static const std::string DefaultProgramID
A container for traffic light definitions and built programs.
bool removeProgram(const std::string id, const std::string programID, bool del=true)
Removes a program of a logic definition from the dictionary.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
NBTrafficLightDefinition * getDefinition(const std::string &id, const std::string &programID) const
Returns the named definition.
A SUMO-compliant built logic for a traffic light.
void resetPhases()
deletes all phases and reset the expect number of links
int getNumLinks()
Returns the number of participating links.
static void addPhase(const SUMOSAXAttributes &attrs, NBLoadedSUMOTLDef *currentTL)
adds a phase to the traffic lights logic currently build
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
NBEdgeCont & myEdgeCont
The edge container for retrieving edges.
bool myResetPhases
whether phases of a previously loaded traffic light must be reset
NBLoadedSUMOTLDef * myCurrentTL
The currently parsed traffic light.
int retrieveLaneIndex(const SUMOSAXAttributes &attrs, SumoXMLAttr attr, NBEdge *edge, bool &ok, bool isDelete=false)
parses a lane index and verifies its correctness
NBTrafficLightLogicCont & myTLLCont
The traffic light container to fill.
bool myIgnoreUnknown
whether definitions for unknown traffic lights shall be silently ignored
void myEndElement(int element)
Called when a closing tag occurs.
NBEdge * retrieveEdge(const SUMOSAXAttributes &attrs, SumoXMLAttr attr, bool &ok)
parses and edge id an returns an existing edge
std::set< std::string > mySeenIDs
list of traffic light logics that were found
void addTlConnection(const SUMOSAXAttributes &attrs)
reads and adds tl-controlled connection
void removeTlConnection(const SUMOSAXAttributes &attrs)
reads and removes tl-controlled connection
NBLoadedSUMOTLDef * initTrafficLightLogic(const SUMOSAXAttributes &attrs, NBLoadedSUMOTLDef *currentTL)
NIXMLTrafficLightsHandler(NBTrafficLightLogicCont &tlCont, NBEdgeCont &ec, bool ignoreUnknown=false)
Constructor.
const std::string & getID() const
Returns the id.
Definition Named.h:74
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
static OptionsCont & getOptions()
Retrieves the options.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
SAX-handler base for SUMO-files.
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
T get(const std::string &str) const
A structure which describes a connection between edges or lanes.
Definition NBEdge.h:201
int fromLane
The lane the connections starts at.
Definition NBEdge.h:210
int toLane
The lane the connections yields in.
Definition NBEdge.h:216
NBEdge * toEdge
The edge the connections yields in.
Definition NBEdge.h:213
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
Definition NBEdge.h:225
int tlLinkIndex
The index of this connection within the controlling traffic light.
Definition NBEdge.h:222