SUMO - Simulation of Urban MObility
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-sim.org/
13 // Copyright (C) 2001-2014 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>
44 #include <netbuild/NBNode.h>
48 #include <utils/common/ToString.h>
53 
54 #ifdef CHECK_MEMORY_LEAKS
55 #include <foreign/nvwa/debug_new.h>
56 #endif // CHECK_MEMORY_LEAKS
57 
58 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
63  SUMOSAXHandler("xml-connection-description"),
64  myEdgeCont(ec),
65  myTLLogicCont(tlc),
66  myHaveWarnedAboutDeprecatedLanes(false),
67  myErrorMsgHandler(OptionsCont::getOptions().getBool("ignore-errors.connections") ?
68  MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) {}
69 
70 
72 
73 
74 void
76  const SUMOSAXAttributes& attrs) {
77  if (element == SUMO_TAG_DELETE) {
78  bool ok = true;
79  std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
80  std::string to = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
81  if (!ok) {
82  return;
83  }
84  // these connections were removed when the edge was deleted
85  if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) {
86  return;
87  }
88  NBEdge* fromEdge = myEdgeCont.retrieve(from);
89  NBEdge* toEdge = myEdgeCont.retrieve(to);
90  if (fromEdge == 0) {
91  myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known.");
92  return;
93  }
94  if (toEdge == 0) {
95  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known.");
96  return;
97  }
98  if (!fromEdge->isConnectedTo(toEdge) && fromEdge->getStep() >= NBEdge::EDGE2EDGES) {
99  WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset.");
100  return;
101  }
102  int fromLane = -1; // Assume all lanes are to be reset.
103  int toLane = -1;
104  if (attrs.hasAttribute(SUMO_ATTR_LANE)
106  || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
107  if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) {
108  return;
109  }
110  // we could be trying to reset a connection loaded from a sumo net and which has become obsolete.
111  // In this case it's ok to encounter invalid lance indices
112  if (!fromEdge->hasConnectionTo(toEdge, toLane) && fromEdge->getStep() >= NBEdge::LANES2EDGES) {
113  WRITE_WARNING("Edge '" + fromEdge->getID() + "' has no connection to lane " + toString(toLane) + " of edge '" + toEdge->getID() + "'; the connection cannot be reset.");
114  }
115  }
116  fromEdge->removeFromConnections(toEdge, fromLane, toLane, true);
117  }
118 
119  if (element == SUMO_TAG_CONNECTION) {
120  bool ok = true;
121  std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, "connection", ok);
122  std::string to = attrs.getOpt<std::string>(SUMO_ATTR_TO, "connection", ok, "");
123  if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) {
124  return;
125  }
126  // extract edges
127  NBEdge* fromEdge = myEdgeCont.retrieve(from);
128  NBEdge* toEdge = to.length() != 0 ? myEdgeCont.retrieve(to) : 0;
129  // check whether they are valid
130  if (fromEdge == 0) {
131  myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known.");
132  return;
133  }
134  if (toEdge == 0 && to.length() != 0) {
135  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known.");
136  return;
137  }
138  // invalidate traffic light definition loaded from a SUMO network
139  // XXX it would be preferable to reconstruct the phase definitions heuristically
140  fromEdge->getToNode()->invalidateTLS(myTLLogicCont);
141  // parse optional lane information
143  parseLaneBound(attrs, fromEdge, toEdge);
144  } else {
145  fromEdge->addEdge2EdgeConnection(toEdge);
146  }
147  }
148  if (element == SUMO_TAG_PROHIBITION) {
149  bool ok = true;
150  std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, "");
151  std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, "");
152  if (!ok) {
153  return;
154  }
155  NBConnection prohibitorC = parseConnection("prohibitor", prohibitor);
156  NBConnection prohibitedC = parseConnection("prohibited", prohibited);
157  if (prohibitorC == NBConnection::InvalidConnection || prohibitedC == NBConnection::InvalidConnection) {
158  // something failed
159  return;
160  }
161  NBNode* n = prohibitorC.getFrom()->getToNode();
162  n->addSortedLinkFoes(prohibitorC, prohibitedC);
163  }
164  if (element == SUMO_TAG_CROSSING) {
165  addCrossing(attrs);
166  }
167 }
168 
169 
171 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) {
172  // split from/to
173  size_t div = def.find("->");
174  if (div == std::string::npos) {
175  myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'");
177  }
178  std::string fromDef = def.substr(0, div);
179  std::string toDef = def.substr(div + 2);
180 
181  // retrieve the edges
182  // check whether the definition includes a lane information (do not process it)
183  if (fromDef.find('_') != std::string::npos) {
184  fromDef = fromDef.substr(0, fromDef.find('_'));
185  }
186  if (toDef.find('_') != std::string::npos) {
187  toDef = toDef.substr(0, toDef.find('_'));
188  }
189  // retrieve them now
190  NBEdge* fromE = myEdgeCont.retrieve(fromDef);
191  NBEdge* toE = myEdgeCont.retrieve(toDef);
192  // check
193  if (fromE == 0) {
194  myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'");
196  }
197  if (toE == 0) {
198  myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'");
200  }
201  return NBConnection(fromE, toE);
202 }
203 
204 
205 void
207  if (to == 0) {
208  // do nothing if it's a dead end
209  return;
210  }
211  bool ok = true;
212  const bool mayDefinitelyPass = attrs.getOpt<bool>(SUMO_ATTR_PASS, 0, ok, false);
213  if (!ok) {
214  return;
215  }
216  // get the begin and the end lane
217  int fromLane;
218  int toLane;
219  try {
220  if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
221  return;
222  }
223  if (fromLane < 0) {
224  myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
225  "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
226  from->getID() + "' to '" + to->getID() + "'.");
227  return;
228  }
229  if (toLane < 0) {
230  myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
231  "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
232  from->getID() + "' to '" + to->getID() + "'.");
233  return;
234  }
235  if (from->hasConnectionTo(to, toLane)) {
236  WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
237  }
238  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass)) {
239  NBEdge* nFrom = from;
240  do {
241  if (nFrom->getToNode()->getOutgoingEdges().size() != 1) {
242  break;
243  }
244  NBEdge* t = nFrom->getToNode()->getOutgoingEdges()[0];
245  if (t->getID().substr(0, t->getID().find('/')) != nFrom->getID().substr(0, nFrom->getID().find('/'))) {
246  break;
247  }
248  nFrom = t;
249  } while (true);
250  if (nFrom == 0 || !nFrom->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, mayDefinitelyPass)) {
251  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
252  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'.");
253  }
254  // set as to be re-applied after network processing
255  myEdgeCont.addPostProcessConnection(nFrom->getID(), fromLane, to->getID(), toLane, mayDefinitelyPass);
256  } else {
257  from = nFrom;
258  }
259  }
260  } catch (NumberFormatException&) {
261  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
262  }
263  //
264  bool keepUncontrolled = attrs.getOpt<bool>(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
265  if (keepUncontrolled) {
266  from->disableConnection4TLS(fromLane, to, toLane);
267  }
268 }
269 
270 bool
272  int* fromLane, int* toLane) {
273  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
274  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
275  } else {
276  return parseLaneDefinition(attributes, fromLane, toLane);
277  }
278 }
279 
280 
281 inline bool
283  NBEdge* from, NBEdge* to,
284  int* fromLane, int* toLane) {
285  bool ok = true;
288  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
290  "' instead.");
291  }
292 
293  std::string laneConn = attributes.get<std::string>(SUMO_ATTR_LANE, 0, ok);
294  StringTokenizer st(laneConn, ':');
295  if (!ok || st.size() != 2) {
296  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
297  from->getID() + "' to '" + to->getID() + "'.");
298  return false; // There was an error.
299  }
300 
301  *fromLane = TplConvert::_2intSec(st.next().c_str(), -1);
302  *toLane = TplConvert::_2intSec(st.next().c_str(), -1);
303 
304  return true; // We succeeded.
305 }
306 
307 
308 inline bool
310  int* fromLane,
311  int* toLane) {
312  bool ok = true;
313  *fromLane = attributes.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
314  *toLane = attributes.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
315  return ok;
316 }
317 
318 
319 void
321  bool ok = true;
322  NBNode* node = 0;
323  EdgeVector edges;
324  const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok);
325  const SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBNode::DEFAULT_CROSSING_WIDTH, true);
326  std::vector<std::string> edgeIDs;
327  SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs);
328  if (!ok) {
329  return;
330  }
331  for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) {
332  NBEdge* edge = myEdgeCont.retrieve(*it);
333  if (edge == 0) {
334  WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known.");
335  return;
336  }
337  if (node == 0) {
338  if (edge->getToNode()->getID() == nodeID) {
339  node = edge->getToNode();
340  } else if (edge->getFromNode()->getID() == nodeID) {
341  node = edge->getFromNode();
342  } else {
343  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
344  return;
345  }
346  } else {
347  if (edge->getToNode() != node && edge->getFromNode() != node) {
348  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
349  return;
350  }
351  }
352  edges.push_back(edge);
353  }
354  bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true);
355  if (node->isTLControlled() && !priority) {
356  // traffic_light nodes should always have priority crossings
357  WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized");
358  priority = true;
359  }
360  node->addCrossing(edges, width, priority);
361 }
362 
363 
364 
365 /****************************************************************************/
366 
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:738
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:295
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 addCrossing(EdgeVector edges, SUMOReal width, bool priority)
add a pedestrian crossing to this node
Definition: NBNode.cpp:2000
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:628
void parseLaneBound(const SUMOSAXAttributes &attrs, NBEdge *from, NBEdge *to)
Parses a connection when it describes a lane-2-lane relationship.
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:67
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
Definition: NBNode.h:252
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:604
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:744
the edges of a route
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:1958
Encapsulated SAX-Attributes.
EdgeBuildingStep getStep() const
The building step of this edge.
Definition: NBEdge.h:438
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
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:839
MsgHandler *const myErrorMsgHandler
the handler for loading errors
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:205
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:368
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:245
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
Definition: NBEdge.cpp:1809
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:38
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:189
NIXMLConnectionsHandler(NBEdgeCont &ec, 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:988
#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
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:312
void invalidateTLS(NBTrafficLightLogicCont &tlCont)
causes the traffic light to be computed anew
Definition: NBNode.cpp:328
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:97
void addPostProcessConnection(const std::string &from, int fromLane, const std::string &to, int toLane, bool mayDefinitelyPass)
Adds a connection which could not be set during loading.
Definition: NBEdgeCont.cpp:714
NBTrafficLightLogicCont & myTLLogicCont
The traffic lights container to add built tls to (when invalidating tls)
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:360