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