Eclipse SUMO - Simulation of Urban MObility
NIXMLNodesHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-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 /****************************************************************************/
21 // Importer for network nodes stored in XML
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <string>
26 #include <iostream>
27 #include <xercesc/sax/HandlerBase.hpp>
28 #include <xercesc/sax/AttributeList.hpp>
29 #include <xercesc/sax/SAXParseException.hpp>
30 #include <xercesc/sax/SAXException.hpp>
35 #include <utils/common/ToString.h>
39 #include <netbuild/NBNodeCont.h>
41 #include <netbuild/NBOwnTLDef.h>
42 #include <netbuild/NBNetBuilder.h>
43 #include "NIXMLNodesHandler.h"
44 #include "NIImporter_SUMO.h"
45 
46 
47 // ===========================================================================
48 // method definitions
49 // ===========================================================================
52  OptionsCont& options) :
53  SUMOSAXHandler("xml-nodes - file"),
54  myOptions(options),
55  myNodeCont(nc),
56  myEdgeCont(ec),
57  myTLLogicCont(tlc),
58  myLocation(nullptr),
59  myLastParameterised(nullptr) {
60 }
61 
62 
64  delete myLocation;
65 }
66 
67 
68 void
70  const SUMOSAXAttributes& attrs) {
71  switch (element) {
72  case SUMO_TAG_LOCATION:
74  break;
75  case SUMO_TAG_NODE:
76  addNode(attrs);
77  break;
78  case SUMO_TAG_JOIN:
79  addJoinCluster(attrs);
80  break;
82  addJoinExclusion(attrs);
83  break;
84  case SUMO_TAG_DEL:
85  deleteNode(attrs);
86  break;
87  case SUMO_TAG_PARAM:
88  if (myLastParameterised != nullptr) {
89  bool ok = true;
90  const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
91  // circumventing empty string test
92  const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
94  }
95  default:
96  break;
97  }
98 }
99 
100 
101 void
103  switch (element) {
104  case SUMO_TAG_NODE:
105  myLastParameterised = nullptr;
106  break;
107  default:
108  break;
109  }
110 }
111 
112 
113 void
115  bool ok = true;
116  // get the id, report a warning if not given or empty...
117  myID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
118  if (!ok) {
119  return;
120  }
121  NBNode* node = myNodeCont.retrieve(myID);
122  // retrieve the position of the node
123  bool xOk = false;
124  bool yOk = false;
125  bool needConversion = true;
126  if (node != nullptr) {
127  myPosition = node->getPosition();
128  xOk = yOk = true;
129  needConversion = false;
130  } else {
131  myPosition.set(0, 0, 0); // better to reset than to reuse the previous (z)-value
132  }
133  if (attrs.hasAttribute(SUMO_ATTR_X)) {
134  myPosition.set(attrs.get<double>(SUMO_ATTR_X, myID.c_str(), ok), myPosition.y());
135  xOk = true;
136  needConversion = true;
137  }
138  if (attrs.hasAttribute(SUMO_ATTR_Y)) {
139  myPosition.set(myPosition.x(), attrs.get<double>(SUMO_ATTR_Y, myID.c_str(), ok));
140  yOk = true;
141  needConversion = true;
142  }
143  if (attrs.hasAttribute(SUMO_ATTR_Z)) {
144  myPosition.set(myPosition.x(), myPosition.y(), attrs.get<double>(SUMO_ATTR_Z, myID.c_str(), ok));
145  }
146  if (xOk && yOk) {
147  if (needConversion && !NBNetBuilder::transformCoordinate(myPosition, true, myLocation)) {
148  WRITE_ERROR("Unable to project coordinates for node '" + myID + "'.");
149  }
150  } else {
151  WRITE_ERROR("Missing position (at node ID='" + myID + "').");
152  }
153  bool updateEdgeGeometries = node != nullptr && myPosition != node->getPosition();
154  node = processNodeType(attrs, node, myID, myPosition, updateEdgeGeometries, myNodeCont, myEdgeCont, myTLLogicCont);
155  myLastParameterised = node;
156 }
157 
158 
159 NBNode*
160 NIXMLNodesHandler::processNodeType(const SUMOSAXAttributes& attrs, NBNode* node, const std::string& nodeID, const Position& position,
161  bool updateEdgeGeometries,
163  bool ok = true;
164  // get the type
166  if (node != nullptr) {
167  type = node->getType();
168  }
169  std::string typeS = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, nodeID.c_str(), ok, "");
170  if (SUMOXMLDefinitions::NodeTypes.hasString(typeS)) {
171  type = SUMOXMLDefinitions::NodeTypes.get(typeS);
173  // dead end is a computed status. Reset this to unknown so it will
174  // be corrected if additional connections are loaded
176  }
177  }
178  std::set<NBTrafficLightDefinition*> oldTLS;
179  // check whether a prior node shall be modified
180  if (node == nullptr) {
181  node = new NBNode(nodeID, position, type);
182  if (!nc.insert(node)) {
183  throw ProcessError("Could not insert node though checked this before (id='" + nodeID + "').");
184  }
185  } else {
186  // patch information
187  oldTLS = node->getControllingTLS();
189  ec.removeRoundabout(node);
190  }
191  node->reinit(position, type, updateEdgeGeometries);
192  }
193  // process traffic light definition
194  if (NBNode::isTrafficLight(type)) {
195  processTrafficLightDefinitions(attrs, node, tlc);
196  }
197  // remove previously set tls if this node is not controlled by them
198  for (std::set<NBTrafficLightDefinition*>::iterator i = oldTLS.begin(); i != oldTLS.end(); ++i) {
199  if ((*i)->getNodes().size() == 0) {
200  tlc.removeFully((*i)->getID());
201  }
202  }
203 
204  // set optional shape
205  PositionVector shape;
206  if (attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
207  shape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, nodeID.c_str(), ok, PositionVector());
209  WRITE_ERROR("Unable to project node shape at node '" + node->getID() + "'.");
210  }
211  if (shape.size() > 2) {
212  shape.closePolygon();
213  }
214  node->setCustomShape(shape);
215  }
216  // set optional radius
217  if (attrs.hasAttribute(SUMO_ATTR_RADIUS)) {
218  node->setRadius(attrs.get<double>(SUMO_ATTR_RADIUS, nodeID.c_str(), ok));
219  }
220  // set optional keepClear flag
221  if (attrs.hasAttribute(SUMO_ATTR_KEEP_CLEAR)) {
222  node->setKeepClear(attrs.get<bool>(SUMO_ATTR_KEEP_CLEAR, nodeID.c_str(), ok));
223  }
224 
225  // set optional right-of-way hint
227  node->setRightOfWay(attrs.getRightOfWay(ok));
228  }
229 
230  // set optional fringe type
231  if (attrs.hasAttribute(SUMO_ATTR_FRINGE)) {
232  node->setFringeType(attrs.getFringeType(ok));
233  }
234  // set optional name
235  if (attrs.hasAttribute(SUMO_ATTR_NAME)) {
236  node->setName(attrs.get<std::string>(SUMO_ATTR_NAME, nodeID.c_str(), ok));
237  }
238  return node;
239 }
240 
241 
242 void
244  bool ok = true;
245  // get the id, report a warning if not given or empty...
246  myID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
247  if (!ok) {
248  return;
249  }
250  NBNode* node = myNodeCont.retrieve(myID);
251  if (node == nullptr) {
252  WRITE_WARNING("Ignoring tag '" + toString(SUMO_TAG_DEL) + "' for unknown node '" +
253  myID + "'");
254  return;
255  } else {
256  myNodeCont.extract(node, true);
257  }
258 }
259 
260 
261 void
263  bool ok = true;
264  const std::string clusterString = attrs.get<std::string>(SUMO_ATTR_NODES, nullptr, ok);
265  std::vector<std::string> ids = StringTokenizer(clusterString).getVector();
266  std::sort(ids.begin(), ids.end());
267 
268  myID = attrs.getOpt<std::string>(SUMO_ATTR_ID, nullptr, ok, "cluster_" + joinToString(ids, "_"));
269 
271  if (attrs.hasAttribute(SUMO_ATTR_X)) {
272  myPosition.setx(attrs.get<double>(SUMO_ATTR_X, myID.c_str(), ok));
273  }
274  if (attrs.hasAttribute(SUMO_ATTR_Y)) {
275  myPosition.sety(attrs.get<double>(SUMO_ATTR_Y, myID.c_str(), ok));
276  }
277  if (attrs.hasAttribute(SUMO_ATTR_Z)) {
278  myPosition.setz(attrs.get<double>(SUMO_ATTR_Z, myID.c_str(), ok));
279  }
280 
281  NBNode* node = processNodeType(attrs, nullptr, myID, myPosition, false, myNodeCont, myEdgeCont, myTLLogicCont);
282  if (ok) {
283  myNodeCont.addCluster2Join(std::set<std::string>(ids.begin(), ids.end()), node);
284  }
285 }
286 
287 
288 void
290  bool ok = true;
291  const std::vector<std::string> ids = StringTokenizer(
292  attrs.get<std::string>(SUMO_ATTR_NODES, nullptr, ok)).getVector();
293  if (ok) {
295  }
296 }
297 
298 
299 void
301  NBNode* currentNode, NBTrafficLightLogicCont& tlc) {
302  // try to get the tl-id
303  // if a tl-id is given, we will look whether this tl already exists
304  // if so, we will add the node to it (and to all programs with this id), otherwise allocate a new one with this id
305  // if no tl-id exists, we will build a tl with the node's id
306  std::set<NBTrafficLightDefinition*> tlDefs;
307  bool ok = true;
308 
309  std::string oldTlID = "";
310  std::string oldTypeS = OptionsCont::getOptions().getString("tls.default-type");
311 
312  if (currentNode->isTLControlled()) {
313  NBTrafficLightDefinition* oldDef = *(currentNode->getControllingTLS().begin());
314  oldTlID = oldDef->getID();
315  oldTypeS = toString(oldDef->getType());
316  }
317  std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, nullptr, ok, oldTlID);
318  std::string typeS = attrs.getOpt<std::string>(SUMO_ATTR_TLTYPE, nullptr, ok, oldTypeS);
319  if (tlID != oldTlID || typeS != oldTypeS) {
320  currentNode->removeTrafficLights();
321  }
322  TrafficLightType type;
323  if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
325  } else {
326  WRITE_ERROR("Unknown traffic light type '" + typeS + "' for node '" + currentNode->getID() + "'.");
327  return;
328  }
330  if (attrs.hasAttribute(SUMO_ATTR_TLLAYOUT)) {
331  std::string layoutS = attrs.get<std::string>(SUMO_ATTR_TLLAYOUT, nullptr, ok);
332  if (SUMOXMLDefinitions::TrafficLightLayouts.hasString(layoutS)) {
334  } else {
335  WRITE_ERROR("Unknown traffic light layout '" + typeS + "' for node '" + currentNode->getID() + "'.");
336  return;
337  }
338  }
339  if (tlID != "" && tlc.getPrograms(tlID).size() > 0) {
340  // we already have definitions for this tlID
341  for (auto item : tlc.getPrograms(tlID)) {
342  NBTrafficLightDefinition* def = item.second;
343  tlDefs.insert(def);
344  def->addNode(currentNode);
345  if (def->getType() != type && attrs.hasAttribute(SUMO_ATTR_TLTYPE)) {
346  WRITE_WARNINGF("Changing traffic light type '%' to '%' for tl '%'.", toString(def->getType()), typeS, tlID);
347  def->setType(type);
348  if (type != TrafficLightType::STATIC && dynamic_cast<NBLoadedSUMOTLDef*>(def) != nullptr) {
349  dynamic_cast<NBLoadedSUMOTLDef*>(def)->guessMinMaxDuration();
350  }
351  }
352  if (layout != TrafficLightLayout::DEFAULT && dynamic_cast<NBOwnTLDef*>(def) != nullptr) {
353  dynamic_cast<NBOwnTLDef*>(def)->setLayout(layout);
354  }
355  }
356  } else {
357  // we need to add a new defition
358  tlID = (tlID == "" ? currentNode->getID() : tlID);
359  NBOwnTLDef* tlDef = new NBOwnTLDef(tlID, currentNode, 0, type);
360  if (!tlc.insert(tlDef)) {
361  // actually, nothing should fail here
362  delete tlDef;
363  throw ProcessError("Could not allocate tls '" + currentNode->getID() + "'.");
364  }
365  tlDef->setLayout(layout);
366  tlDefs.insert(tlDef);
367  }
368  // process inner edges which shall be controlled
369  const std::vector<std::string>& controlledInner = attrs.getOptStringVector(SUMO_ATTR_CONTROLLED_INNER, nullptr, ok);
370  if (controlledInner.size() != 0) {
371  for (std::set<NBTrafficLightDefinition*>::iterator it = tlDefs.begin(); it != tlDefs.end(); it++) {
372  (*it)->addControlledInnerEdges(controlledInner);
373  }
374  }
375 }
376 
377 
378 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:277
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
TrafficLightType
@ SUMO_TAG_JOINEXCLUDE
join exlude operation
@ SUMO_TAG_LOCATION
@ SUMO_TAG_JOIN
Join operation.
@ SUMO_TAG_NODE
alternative definition for junction
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_TAG_DEL
delete certain element (note: DELETE is a macro)
TrafficLightLayout
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
@ SUMO_ATTR_NODES
a list of node ids, used for controlling joining
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_RADIUS
The turning radius at an intersection in m.
@ SUMO_ATTR_Y
@ SUMO_ATTR_Z
@ SUMO_ATTR_X
@ SUMO_ATTR_TLLAYOUT
node: the layout of the traffic light program
@ SUMO_ATTR_FRINGE
Fringe type of node.
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_TLTYPE
node: the type of traffic light
@ SUMO_ATTR_NAME
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_RIGHT_OF_WAY
How to compute right of way.
@ SUMO_ATTR_CONTROLLED_INNER
@ SUMO_ATTR_KEY
@ SUMO_ATTR_KEEP_CLEAR
Whether vehicles must keep the junction clear.
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:250
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
void removeRoundabout(const NBNode *node)
remove roundabout that contains the given node
A loaded (complete) traffic light logic.
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:58
void addCluster2Join(std::set< std::string > cluster, NBNode *node)
add ids of nodes which shall be joined into a single node
Definition: NBNodeCont.cpp:592
void addJoinExclusion(const std::vector< std::string > &ids, bool check=false)
Definition: NBNodeCont.cpp:576
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:90
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:119
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
Definition: NBNodeCont.cpp:160
Represents a single node (junction) during network building.
Definition: NBNode.h:66
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:306
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:271
void setRightOfWay(RightOfWay rightOfWay)
set method for computing right-of-way
Definition: NBNode.h:538
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition: NBNode.cpp:2291
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
Definition: NBNode.cpp:3424
void setKeepClear(bool keepClear)
set the keepClear flag
Definition: NBNode.h:533
void removeTrafficLights(bool setAsPriority=false)
Removes all references to traffic lights that control this tls.
Definition: NBNode.cpp:381
void setRadius(double radius)
set the turning radius
Definition: NBNode.h:528
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
void setName(const std::string &name)
set intersection name
Definition: NBNode.h:548
const Position & getPosition() const
Definition: NBNode.h:246
void setFringeType(FringeType fringeType)
set method for computing right-of-way
Definition: NBNode.h:543
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:317
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:44
void setLayout(TrafficLightLayout layout)
sets the layout for the generated signal plan
Definition: NBOwnTLDef.h:137
The base class for traffic light logic definitions.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
virtual void setType(TrafficLightType type)
set the algorithm type (static etc..)
A container for traffic light definitions and built programs.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
static GeoConvHelper * loadLocation(const SUMOSAXAttributes &attrs)
Parses network location description and registers it with GeoConveHelper::setLoaded.
~NIXMLNodesHandler()
Destructor.
std::string myID
The id of the currently parsed node.
void addJoinCluster(const SUMOSAXAttributes &attrs)
GeoConvHelper * myLocation
The coordinate transformation which was used compute the node coordinates.
Position myPosition
The position of the currently parsed node.
NBNodeCont & myNodeCont
The node container to add built nodes to.
void deleteNode(const SUMOSAXAttributes &attrs)
NBTrafficLightLogicCont & myTLLogicCont
The traffic lights container to add built tls to.
static void processTrafficLightDefinitions(const SUMOSAXAttributes &attrs, NBNode *currentNode, NBTrafficLightLogicCont &tlc)
Builds the defined traffic light or adds a node to it.
NBEdgeCont & myEdgeCont
The node container to add built nodes to.
Parameterised * myLastParameterised
last item the could receive parameters
void myEndElement(int element)
Called when a closing tag occurs.
void addNode(const SUMOSAXAttributes &attrs)
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
NIXMLNodesHandler(NBNodeCont &nc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, OptionsCont &options)
Constructor.
static NBNode * processNodeType(const SUMOSAXAttributes &attrs, NBNode *node, const std::string &nodeID, const Position &position, bool updateEdgeGeometries, NBNodeCont &nc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
parses node attributes (not related to positioning)
void addJoinExclusion(const SUMOSAXAttributes &attrs)
const std::string & getID() const
Returns the id.
Definition: Named.h:73
A storage for options typed value containers)
Definition: OptionsCont.h:89
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.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
void setx(double x)
set position x
Definition: Position.h:69
void set(double x, double y)
set positions x and y
Definition: Position.h:84
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:282
double x() const
Returns the x-position.
Definition: Position.h:54
void setz(double z)
set position z
Definition: Position.h:79
void sety(double y)
set position y
Definition: Position.h:74
double y() const
Returns the y-position.
Definition: Position.h:59
A list of positions.
void closePolygon()
ensures that the last position equals the first
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.
const std::vector< std::string > getOptStringVector(int attr, const char *objectid, bool &ok, bool report=true) const
convenience function to avoid the default argument and the template stuff at getOpt<>
virtual FringeType getFringeType(bool &ok) const =0
returns fringe type
virtual RightOfWay getRightOfWay(bool &ok) const =0
Returns the right-of-way method.
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< SumoXMLNodeType > NodeTypes
node types
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
static StringBijection< TrafficLightLayout > TrafficLightLayouts
traffic light layouts
T get(const std::string &str) const
std::vector< std::string > getVector()
return vector of strings