Eclipse SUMO - Simulation of Urban MObility
NIXMLTrafficLightsHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2011-2020 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>
26 #include <xercesc/sax/HandlerBase.hpp>
27 #include <xercesc/sax/AttributeList.hpp>
28 #include <xercesc/sax/SAXParseException.hpp>
29 #include <xercesc/sax/SAXException.hpp>
33 #include <utils/common/ToString.h>
38 #include <netbuild/NBEdge.h>
39 #include <netbuild/NBEdgeCont.h>
40 #include <netbuild/NBNode.h>
41 #include <netbuild/NBOwnTLDef.h>
44 #include "NIImporter_SUMO.h"
46 
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
52  NBTrafficLightLogicCont& tlCont, NBEdgeCont& ec, bool ignoreUnknown) :
53  SUMOSAXHandler("xml-tllogics"),
54  myTLLCont(tlCont),
55  myEdgeCont(ec),
56  myCurrentTL(nullptr),
57  myResetPhases(false),
58  myIgnoreUnknown(ignoreUnknown)
59 { }
60 
61 
63 
64 
65 void
67  int element, const SUMOSAXAttributes& attrs) {
68  switch (element) {
69  case SUMO_TAG_TLLOGIC:
71  break;
72  case SUMO_TAG_PHASE:
73  if (myCurrentTL != nullptr) {
74  if (myResetPhases) {
76  myResetPhases = false;
77  }
80  }
81  break;
83  addTlConnection(attrs);
84  break;
85  case SUMO_TAG_DEL:
86  removeTlConnection(attrs);
87  break;
88  case SUMO_TAG_PARAM:
89  if (myCurrentTL != nullptr) {
90  bool ok = true;
91  const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
92  // circumventing empty string test
93  const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
94  myCurrentTL->setParameter(key, val);
95  }
96  default:
97  break;
98  }
99 }
100 
101 
102 void
104  switch (element) {
105  case SUMO_TAG_TLLOGIC:
106  myCurrentTL = nullptr;
107  break;
108  default:
109  break;
110  }
111 }
112 
113 
116  if (currentTL) {
117  WRITE_ERROR("Definition of tlLogic '" + currentTL->getID() + "' was not finished.");
118  return nullptr;
119  }
120  bool ok = true;
121  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
122  std::string programID = attrs.getOpt<std::string>(SUMO_ATTR_PROGRAMID, id.c_str(), ok, "UNKNOWN_PROGRAM");
123  SUMOTime offset = attrs.hasAttribute(SUMO_ATTR_OFFSET) ? TIME2STEPS(attrs.get<double>(SUMO_ATTR_OFFSET, id.c_str(), ok)) : 0;
124  std::string typeS = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, nullptr, ok,
125  OptionsCont::getOptions().getString("tls.default-type"));
126  TrafficLightType type;
127  if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
129  } else {
130  WRITE_ERROR("Unknown traffic light type '" + typeS + "' for tlLogic '" + id + "'.");
131  return nullptr;
132  }
133  // there are three scenarios to consider
134  // 1) the tll.xml is loaded to update traffic lights defined in a net.xml:
135  // simply retrieve the loaded definitions and update them
136  // 2) the tll.xml is loaded to define new traffic lights
137  // nod.xml will have triggered building of NBOwnTLDef. Replace it with NBLoadedSUMOTLDef
138  // 3) the tll.xml is loaded to define new programs for a defined traffic light
139  // there should be a definition with the same id but different programID
140  const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(id);
141  if (programs.size() == 0) {
142  if (!myIgnoreUnknown) {
143  WRITE_ERROR("Cannot load traffic light program for unknown id '" + id + "', programID '" + programID + "'.");
144  }
145  return nullptr;
146  }
147  const std::string existingProgram = programs.begin()->first; // arbitrary for our purpose
148  NBLoadedSUMOTLDef* loadedDef = dynamic_cast<NBLoadedSUMOTLDef*>(myTLLCont.getDefinition(id, programID));
149  if (loadedDef == nullptr) {
150  NBLoadedSUMOTLDef* oldDef = dynamic_cast<NBLoadedSUMOTLDef*>(myTLLCont.getDefinition(id, existingProgram));
151  if (oldDef == nullptr) {
152  // case 2
155  bool deleteDefault = false;
156  if (newDef == nullptr) {
157  // the default program may have already been replaced with a loaded program
158  newDef = dynamic_cast<NBLoadedSUMOTLDef*>(myTLLCont.getDefinition(
160  if (newDef == nullptr) {
161  WRITE_ERROR("Cannot load traffic light program for unknown id '" + id + "', programID '" + programID + "'.");
162  return nullptr;
163  }
164  } else {
165  deleteDefault = true;
166  }
167  assert(newDef != 0);
168  loadedDef = new NBLoadedSUMOTLDef(id, programID, offset, type);
169  // copy nodes and controlled inner edges
170  std::vector<NBNode*> nodes = newDef->getNodes();
171  for (std::vector<NBNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
172  loadedDef->addNode(*it);
173  }
174  loadedDef->addControlledInnerEdges(newDef->getControlledInnerEdges());
175  if (deleteDefault) {
176  // make a copy because the vector is modified in the loop
177  const std::vector<NBNode*> nodes = newDef->getNodes();
178  // replace default Program
179  for (NBNode* const n : nodes) {
180  n->removeTrafficLight(newDef);
181  }
183  }
184  myTLLCont.insert(loadedDef);
185  } else {
186  // case 3
187  NBTrafficLightLogic* oldLogic = oldDef->getLogic();
188  NBTrafficLightLogic newLogic(id, programID, oldLogic->getNumLinks(), offset, type);
189  loadedDef = new NBLoadedSUMOTLDef(*oldDef, newLogic);
190  // copy nodes
191  std::vector<NBNode*> nodes = oldDef->getNodes();
192  for (std::vector<NBNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
193  loadedDef->addNode(*it);
194  }
195  //std::cout << " case3 oldDef=" << oldDef->getDescription() << " loadedDef=" << loadedDef->getDescription() << "\n";
196  myTLLCont.insert(loadedDef);
197  }
198  } else {
199  // case 1
200  if (attrs.hasAttribute(SUMO_ATTR_OFFSET)) {
201  loadedDef->setOffset(offset);
202  }
203  if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
204  loadedDef->setType(type);
205  }
206  }
207  if (ok) {
208  myResetPhases = true;
209  return loadedDef;
210  } else {
211  return nullptr;
212  }
213 }
214 
215 
216 void
218  bool ok = true;
219  // parse identifying attributes
220  NBEdge* from = retrieveEdge(attrs, SUMO_ATTR_FROM, ok);
221  NBEdge* to = retrieveEdge(attrs, SUMO_ATTR_TO, ok);
222  if (!ok) {
223  return;
224  }
225  int fromLane = retrieveLaneIndex(attrs, SUMO_ATTR_FROM_LANE, from, ok);
226  int toLane = retrieveLaneIndex(attrs, SUMO_ATTR_TO_LANE, to, ok);
227  if (!ok) {
228  return;
229  }
230  // retrieve connection
231  const std::vector<NBEdge::Connection>& connections = from->getConnections();
232  std::vector<NBEdge::Connection>::const_iterator con_it;
233  con_it = find_if(connections.begin(), connections.end(),
234  NBEdge::connections_finder(fromLane, to, toLane));
235  if (con_it == connections.end()) {
236  WRITE_ERROR("Connection from=" + from->getID() + " to=" + to->getID() +
237  " fromLane=" + toString(fromLane) + " toLane=" + toString(toLane) + " not found");
238  return;
239  }
240  NBEdge::Connection c = *con_it;
241  // read other attributes
242  std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, nullptr, ok, "");
243  if (tlID == "") {
244  // we are updating an existing tl-controlled connection
245  tlID = (*(from->getToNode()->getControllingTLS().begin()))->getID();
246  assert(tlID != "");
247  }
248  int tlIndex = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX, nullptr, ok, -1);
249  if (tlIndex == -1) {
250  // we are updating an existing tl-controlled connection
251  tlIndex = c.tlLinkIndex;
252  }
253  int tlIndex2 = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX2, nullptr, ok, -1);
254  if (tlIndex2 == -1) {
255  // we are updating an existing tl-controlled connection or index2 is not used
256  tlIndex2 = c.tlLinkIndex2;
257  }
258 
259  // register the connection with all definitions
260  const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(tlID);
261  if (programs.size() > 0) {
262  std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
263  for (it = programs.begin(); it != programs.end(); it++) {
264  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
265  if (tlDef) {
266  tlDef->addConnection(from, c.toEdge, c.fromLane, c.toLane, tlIndex, tlIndex2, false);
267  } else {
268  throw ProcessError("Corrupt traffic light definition '"
269  + tlID + "' (program '" + it->first + "')");
270  }
271  }
272  } else {
273  SumoXMLNodeType type = from->getToNode()->getType();
275  WRITE_ERROR("The traffic light '" + tlID + "' is not known.");
276  }
277  }
278 }
279 
280 
281 void
283  bool ok = true;
284  std::string tlID = attrs.get<std::string>(SUMO_ATTR_TLID, nullptr, ok);
285  // does the traffic light still exist?
286  const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(tlID);
287  if (programs.size() > 0) {
288  // parse identifying attributes
289  NBEdge* from = retrieveEdge(attrs, SUMO_ATTR_FROM, ok);
290  NBEdge* to = retrieveEdge(attrs, SUMO_ATTR_TO, ok);
291  int fromLane = -1;
292  int toLane = -1;
293  if (ok) {
294  fromLane = retrieveLaneIndex(attrs, SUMO_ATTR_FROM_LANE, from, ok, true);
295  toLane = retrieveLaneIndex(attrs, SUMO_ATTR_TO_LANE, to, ok, true);
296  }
297  int tlIndex = attrs.get<int>(SUMO_ATTR_TLLINKINDEX, nullptr, ok);
298 
299  NBConnection conn(from, fromLane, to, toLane, tlIndex);
300  // remove the connection from all definitions
301  std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
302  for (it = programs.begin(); it != programs.end(); it++) {
303  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
304  if (tlDef) {
305  tlDef->removeConnection(conn, false);
306  } else {
307  throw ProcessError("Corrupt traffic light definition '"
308  + tlID + "' (program '" + it->first + "')");
309  }
310  }
311  }
312 }
313 
314 
315 NBEdge*
317  const SUMOSAXAttributes& attrs, SumoXMLAttr attr, bool& ok) {
318  std::string edgeID = attrs.get<std::string>(attr, nullptr, ok);
319  NBEdge* edge = myEdgeCont.retrieve(edgeID, true);
320  if (edge == nullptr) {
321  WRITE_ERROR("Unknown edge '" + edgeID + "' given in connection.");
322  ok = false;
323  }
324  return edge;
325 }
326 
327 
328 int
330  const SUMOSAXAttributes& attrs, SumoXMLAttr attr, NBEdge* edge, bool& ok, bool isDelete) {
331  int laneIndex = attrs.get<int>(attr, nullptr, ok);
332  if (edge->getNumLanes() <= laneIndex) {
333  if (!isDelete) {
334  WRITE_ERROR("Invalid lane index '" + toString(laneIndex) + "' for edge '" + edge->getID() + "'.");
335  }
336  ok = false;
337  }
338  return laneIndex;
339 }
340 
341 
342 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
TrafficLightType
@ SUMO_TAG_PHASE
a single phase description
@ SUMO_TAG_CONNECTION
connectio 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:44
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.
Definition: NBEdgeCont.cpp:275
The representation of a single edge during network building.
Definition: NBEdge.h:91
const std::string & getID() const
Definition: NBEdge.h:1423
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:516
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:490
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:964
A loaded (complete) traffic light logic.
void phasesLoaded()
mark phases as load
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.
NBTrafficLightLogic * getLogic()
Returns the internal logic.
void setOffset(SUMOTime offset)
Sets the offset of this tls.
Represents a single node (junction) during network building.
Definition: NBNode.h:66
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:271
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:322
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.
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.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
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.
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
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:73
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.
Definition: OptionsCont.cpp:58
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, 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.
virtual std::string getString(int id) const =0
Returns the string-value of the named (by its enum-value) attribute.
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:188
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:209
int toLane
The lane the connections yields in.
Definition: NBEdge.h:215
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:212
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
Definition: NBEdge.h:224
int tlLinkIndex
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:221