SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIXMLConnectionsHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Importer for edge connections stored in XML
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
13 // Copyright (C) 2001-2015 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
35 #include <iostream>
36 #include <xercesc/sax/HandlerBase.hpp>
37 #include <xercesc/sax/AttributeList.hpp>
38 #include <xercesc/sax/SAXParseException.hpp>
39 #include <xercesc/sax/SAXException.hpp>
41 #include <netbuild/NBEdge.h>
42 #include <netbuild/NBEdgeCont.h>
43 #include <netbuild/NBNodeCont.h>
45 #include <netbuild/NBNode.h>
49 #include <utils/common/ToString.h>
54 
55 #ifdef CHECK_MEMORY_LEAKS
56 #include <foreign/nvwa/debug_new.h>
57 #endif // CHECK_MEMORY_LEAKS
58 
59 
60 // ===========================================================================
61 // method definitions
62 // ===========================================================================
64  SUMOSAXHandler("xml-connection-description"),
65  myEdgeCont(ec),
66  myNodeCont(nc),
67  myTLLogicCont(tlc),
68  myHaveWarnedAboutDeprecatedLanes(false),
69  myErrorMsgHandler(OptionsCont::getOptions().getBool("ignore-errors.connections") ?
70  MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) {}
71 
72 
74 
75 
76 void
78  const SUMOSAXAttributes& attrs) {
79  if (element == SUMO_TAG_DELETE) {
80  bool ok = true;
81  std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
82  std::string to = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
83  if (!ok) {
84  return;
85  }
86  // these connections were removed when the edge was deleted
87  if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) {
88  return;
89  }
90  NBEdge* fromEdge = myEdgeCont.retrieve(from);
91  NBEdge* toEdge = myEdgeCont.retrieve(to);
92  if (fromEdge == 0) {
93  myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known.");
94  return;
95  }
96  if (toEdge == 0) {
97  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known.");
98  return;
99  }
100  if (!fromEdge->isConnectedTo(toEdge) && fromEdge->getStep() >= NBEdge::EDGE2EDGES) {
101  WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset.");
102  return;
103  }
104  int fromLane = -1; // Assume all lanes are to be reset.
105  int toLane = -1;
106  if (attrs.hasAttribute(SUMO_ATTR_LANE)
108  || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
109  if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) {
110  return;
111  }
112  // we could be trying to reset a connection loaded from a sumo net and which has become obsolete.
113  // In this case it's ok to encounter invalid lance indices
114  if (!fromEdge->hasConnectionTo(toEdge, toLane) && fromEdge->getStep() >= NBEdge::LANES2EDGES) {
115  WRITE_WARNING("Edge '" + fromEdge->getID() + "' has no connection to lane " + toString(toLane) + " of edge '" + toEdge->getID() + "'; the connection cannot be reset.");
116  }
117  }
118  fromEdge->removeFromConnections(toEdge, fromLane, toLane, true);
119  }
120 
121  if (element == SUMO_TAG_CONNECTION) {
122  bool ok = true;
123  std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, "connection", ok);
124  std::string to = attrs.getOpt<std::string>(SUMO_ATTR_TO, "connection", ok, "");
125  if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) {
126  return;
127  }
128  // extract edges
129  NBEdge* fromEdge = myEdgeCont.retrieve(from);
130  NBEdge* toEdge = to.length() != 0 ? myEdgeCont.retrieve(to) : 0;
131  // check whether they are valid
132  if (fromEdge == 0) {
133  myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known.");
134  return;
135  }
136  if (toEdge == 0 && to.length() != 0) {
137  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known.");
138  return;
139  }
140  // invalidate traffic light definition loaded from a SUMO network
141  // XXX it would be preferable to reconstruct the phase definitions heuristically
142  fromEdge->getToNode()->invalidateTLS(myTLLogicCont);
143  // parse optional lane information
145  parseLaneBound(attrs, fromEdge, toEdge);
146  } else {
147  fromEdge->addEdge2EdgeConnection(toEdge);
148  }
149  }
150  if (element == SUMO_TAG_PROHIBITION) {
151  bool ok = true;
152  std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, "");
153  std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, "");
154  if (!ok) {
155  return;
156  }
157  NBConnection prohibitorC = parseConnection("prohibitor", prohibitor);
158  NBConnection prohibitedC = parseConnection("prohibited", prohibited);
159  if (prohibitorC == NBConnection::InvalidConnection || prohibitedC == NBConnection::InvalidConnection) {
160  // something failed
161  return;
162  }
163  NBNode* n = prohibitorC.getFrom()->getToNode();
164  n->addSortedLinkFoes(prohibitorC, prohibitedC);
165  }
166  if (element == SUMO_TAG_CROSSING) {
167  addCrossing(attrs);
168  }
169  if (element == SUMO_TAG_CUSTOMSHAPE) {
170  addCustomShape(attrs);
171  }
172 }
173 
174 
176 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) {
177  // split from/to
178  size_t div = def.find("->");
179  if (div == std::string::npos) {
180  myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'");
182  }
183  std::string fromDef = def.substr(0, div);
184  std::string toDef = def.substr(div + 2);
185 
186  // retrieve the edges
187  // check whether the definition includes a lane information (do not process it)
188  if (fromDef.find('_') != std::string::npos) {
189  fromDef = fromDef.substr(0, fromDef.find('_'));
190  }
191  if (toDef.find('_') != std::string::npos) {
192  toDef = toDef.substr(0, toDef.find('_'));
193  }
194  // retrieve them now
195  NBEdge* fromE = myEdgeCont.retrieve(fromDef);
196  NBEdge* toE = myEdgeCont.retrieve(toDef);
197  // check
198  if (fromE == 0) {
199  myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'");
201  }
202  if (toE == 0) {
203  myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'");
205  }
206  return NBConnection(fromE, toE);
207 }
208 
209 
210 void
212  if (to == 0) {
213  // do nothing if it's a dead end
214  return;
215  }
216  bool ok = true;
217  const bool mayDefinitelyPass = attrs.getOpt<bool>(SUMO_ATTR_PASS, 0, ok, false);
218  const bool keepClear = attrs.getOpt<bool>(SUMO_ATTR_KEEP_CLEAR, 0, ok, true);
219  if (!ok) {
220  return;
221  }
222  // get the begin and the end lane
223  int fromLane;
224  int toLane;
225  try {
226  if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
227  return;
228  }
229  if (fromLane < 0) {
230  myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
231  "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
232  from->getID() + "' to '" + to->getID() + "'.");
233  return;
234  }
235  if (toLane < 0) {
236  myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
237  "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
238  from->getID() + "' to '" + to->getID() + "'.");
239  return;
240  }
241  if (from->hasConnectionTo(to, toLane)) {
242  WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
243  }
244  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass, keepClear)) {
245  NBEdge* nFrom = from;
246  while (nFrom->getToNode()->getOutgoingEdges().size() == 1) {
247  NBEdge* t = nFrom->getToNode()->getOutgoingEdges()[0];
248  if (t->getID().substr(0, t->getID().find('/')) != nFrom->getID().substr(0, nFrom->getID().find('/'))) {
249  break;
250  }
251  nFrom = t;
252  }
253  if (nFrom == 0 || !nFrom->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, mayDefinitelyPass, keepClear)) {
254  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
255  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'.");
256  }
257  // set as to be re-applied after network processing
258  myEdgeCont.addPostProcessConnection(nFrom->getID(), fromLane, to->getID(), toLane, mayDefinitelyPass, keepClear);
259  } else {
260  from = nFrom;
261  }
262  }
263  } catch (NumberFormatException&) {
264  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
265  }
266  //
267  bool keepUncontrolled = attrs.getOpt<bool>(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
268  if (keepUncontrolled) {
269  from->disableConnection4TLS(fromLane, to, toLane);
270  }
271 }
272 
273 bool
275  int* fromLane, int* toLane) {
276  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
277  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
278  } else {
279  return parseLaneDefinition(attributes, fromLane, toLane);
280  }
281 }
282 
283 
284 inline bool
286  NBEdge* from, NBEdge* to,
287  int* fromLane, int* toLane) {
288  bool ok = true;
291  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
293  "' instead.");
294  }
295 
296  std::string laneConn = attributes.get<std::string>(SUMO_ATTR_LANE, 0, ok);
297  StringTokenizer st(laneConn, ':');
298  if (!ok || st.size() != 2) {
299  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
300  from->getID() + "' to '" + to->getID() + "'.");
301  return false; // There was an error.
302  }
303 
304  *fromLane = TplConvert::_2intSec(st.next().c_str(), -1);
305  *toLane = TplConvert::_2intSec(st.next().c_str(), -1);
306 
307  return true; // We succeeded.
308 }
309 
310 
311 inline bool
313  int* fromLane,
314  int* toLane) {
315  bool ok = true;
316  *fromLane = attributes.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
317  *toLane = attributes.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
318  return ok;
319 }
320 
321 
322 void
324  bool ok = true;
325  NBNode* node = 0;
326  EdgeVector edges;
327  const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok);
328  const SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBNode::DEFAULT_CROSSING_WIDTH, true);
329  const bool discard = attrs.getOpt<bool>(SUMO_ATTR_DISCARD, nodeID.c_str(), ok, false, true);
330  std::vector<std::string> edgeIDs;
331  if (!attrs.hasAttribute(SUMO_ATTR_EDGES)) {
332  if (discard) {
333  node = myNodeCont.retrieve(nodeID);
334  if (node == 0) {
335  WRITE_ERROR("Node '" + nodeID + "' in crossing is not known.");
336  return;
337  }
338  node->discardAllCrossings();
339  return;
340  } else {
341  WRITE_ERROR("No edges specified for crossing at node '" + nodeID + "'.");
342  return;
343  }
344  }
345  SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs);
346  if (!ok) {
347  return;
348  }
349  for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) {
350  NBEdge* edge = myEdgeCont.retrieve(*it);
351  if (edge == 0) {
352  WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known.");
353  return;
354  }
355  if (node == 0) {
356  if (edge->getToNode()->getID() == nodeID) {
357  node = edge->getToNode();
358  } else if (edge->getFromNode()->getID() == nodeID) {
359  node = edge->getFromNode();
360  } else {
361  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
362  return;
363  }
364  } else {
365  if (edge->getToNode() != node && edge->getFromNode() != node) {
366  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
367  return;
368  }
369  }
370  edges.push_back(edge);
371  }
372  bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true);
373  if (node->isTLControlled() && !priority) {
374  // traffic_light nodes should always have priority crossings
375  WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized");
376  priority = true;
377  }
378  if (discard) {
379  node->removeCrossing(edges);
380  } else {
381  node->addCrossing(edges, width, priority);
382  }
383 }
384 
385 
386 void
388  bool ok = true;
389  const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
390  const PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
391  if (!ok) {
392  return;
393  }
394  const std::string nodeID = NBNode::getNodeIDFromInternalLane(id);
395  NBNode* node = myNodeCont.retrieve(nodeID);
396  if (node == 0) {
397  WRITE_ERROR("Node '" + nodeID + "' in customShape is not known.");
398  return;
399  }
400  node->setCustomLaneShape(id, shape);
401 }
402 
403 
404 
405 /****************************************************************************/
406 
bool hasConnectionTo(NBEdge *destEdge, unsigned int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:783
Whether vehicles must keep the junction clear.
The relationships between edges are computed/loaded.
Definition: NBEdge.h:95
void addCrossing(const SUMOSAXAttributes &attrs)
Parses a crossing and updates the referenced node.
static const NBConnection InvalidConnection
Definition: NBConnection.h:125
A container for traffic light definitions and built programs.
bool myHaveWarnedAboutDeprecatedLanes
Information whether we have a deprecated attribute.
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:311
bool parseLaneInfo(const SUMOSAXAttributes &attributes, NBEdge *fromEdge, NBEdge *toEdge, int *fromLane, int *toLane)
Parses information about lane-2-lane connection when it describes a lane-2-lane relationship.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:71
void parseLaneBound(const SUMOSAXAttributes &attrs, NBEdge *from, NBEdge *to)
Parses a connection when it describes a lane-2-lane relationship.
void addPostProcessConnection(const std::string &from, int fromLane, const std::string &to, int toLane, bool mayDefinitelyPass, bool keepClear)
Adds a connection which could not be set during loading.
Definition: NBEdgeCont.cpp:777
SAX-handler base for SUMO-files.
bool parseLaneDefinition(const SUMOSAXAttributes &attributes, int *fromLane, int *toLane)
Parses information about lane-2-lane connection.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges.
Definition: NBNode.h:255
NBEdgeCont & myEdgeCont
The edge container to fill.
const std::string & getID() const
Returns the id.
Definition: Named.h:60
bool parseDeprecatedLaneDefinition(const SUMOSAXAttributes &attributes, NBEdge *fromEdge, NBEdge *toEdge, int *fromLane, int *toLane)
Parses information about lane-2-lane connection in deprecated format.
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:646
NBConnection parseConnection(const std::string &defRole, const std::string &def)
Returns the connection described by def.
static void parseStringVector(const std::string &def, std::vector< std::string > &into)
Splits the given string.
bool isConnectedTo(NBEdge *e)
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:789
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
Definition: NBNode.cpp:2314
the edges of a route
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:2159
Encapsulated SAX-Attributes.
void addCustomShape(const SUMOSAXAttributes &attrs)
Parses a customShape and updates the referenced node.
A list of positions.
EdgeBuildingStep getStep() const
The building step of this edge.
Definition: NBEdge.h:437
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
NBNodeCont & myNodeCont
The edge container to fill.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
void setCustomLaneShape(const std::string &laneID, const PositionVector &shape)
sets a custom shape for an internal lane
Definition: NBNode.cpp:1539
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:53
The connection was given by the user.
Definition: NBEdge.h:114
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:893
MsgHandler *const myErrorMsgHandler
the handler for loading errors
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:205
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:670
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:367
void addCrossing(EdgeVector edges, SUMOReal width, bool priority, bool fromSumoNet=false)
add a pedestrian crossing to this node
Definition: NBNode.cpp:2305
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:274
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
Definition: NBEdge.cpp:1997
bool wasRemoved(std::string id) const
Returns whether the edge with the id was deleted explicitly.
Definition: NBEdgeCont.h:470
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:89
A storage for options typed value containers)
Definition: OptionsCont.h:108
static const SUMOReal DEFAULT_CROSSING_WIDTH
default width of pedetrian crossings
Definition: NBNode.h:187
NIXMLConnectionsHandler(NBEdgeCont &ec, NBNodeCont &nc, NBTrafficLightLogicCont &tlc)
Constructor.
Represents a single node (junction) during network building.
Definition: NBNode.h:75
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
Definition: NBNode.cpp:1068
#define SUMOReal
Definition: config.h:215
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.
bool wasIgnored(std::string id) const
Returns whether the edge with the id was ignored during parsing.
Definition: NBEdgeCont.h:463
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:108
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
static int _2intSec(const E *const data, int def)
Definition: TplConvert.h:341
void invalidateTLS(NBTrafficLightLogicCont &tlCont)
causes the traffic light to be computed anew
Definition: NBNode.cpp:346
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:97
NBTrafficLightLogicCont & myTLLogicCont
The traffic lights container to add built tls to (when invalidating tls)
void discardAllCrossings()
Definition: NBNode.h:637
static std::string getNodeIDFromInternalLane(const std::string id)
returns the node id for internal lanes, crossings and walkingareas
Definition: NBNode.cpp:2393
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:359