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-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  while (nFrom->getToNode()->getOutgoingEdges().size() == 1) {
241  NBEdge* t = nFrom->getToNode()->getOutgoingEdges()[0];
242  if (t->getID().substr(0, t->getID().find('/')) != nFrom->getID().substr(0, nFrom->getID().find('/'))) {
243  break;
244  }
245  nFrom = t;
246  }
247  if (nFrom == 0 || !nFrom->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, mayDefinitelyPass)) {
248  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
249  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'.");
250  }
251  // set as to be re-applied after network processing
252  myEdgeCont.addPostProcessConnection(nFrom->getID(), fromLane, to->getID(), toLane, mayDefinitelyPass);
253  } else {
254  from = nFrom;
255  }
256  }
257  } catch (NumberFormatException&) {
258  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
259  }
260  //
261  bool keepUncontrolled = attrs.getOpt<bool>(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
262  if (keepUncontrolled) {
263  from->disableConnection4TLS(fromLane, to, toLane);
264  }
265 }
266 
267 bool
269  int* fromLane, int* toLane) {
270  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
271  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
272  } else {
273  return parseLaneDefinition(attributes, fromLane, toLane);
274  }
275 }
276 
277 
278 inline bool
280  NBEdge* from, NBEdge* to,
281  int* fromLane, int* toLane) {
282  bool ok = true;
285  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
287  "' instead.");
288  }
289 
290  std::string laneConn = attributes.get<std::string>(SUMO_ATTR_LANE, 0, ok);
291  StringTokenizer st(laneConn, ':');
292  if (!ok || st.size() != 2) {
293  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
294  from->getID() + "' to '" + to->getID() + "'.");
295  return false; // There was an error.
296  }
297 
298  *fromLane = TplConvert::_2intSec(st.next().c_str(), -1);
299  *toLane = TplConvert::_2intSec(st.next().c_str(), -1);
300 
301  return true; // We succeeded.
302 }
303 
304 
305 inline bool
307  int* fromLane,
308  int* toLane) {
309  bool ok = true;
310  *fromLane = attributes.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
311  *toLane = attributes.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
312  return ok;
313 }
314 
315 
316 void
318  bool ok = true;
319  NBNode* node = 0;
320  EdgeVector edges;
321  const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok);
322  const SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBNode::DEFAULT_CROSSING_WIDTH, true);
323  std::vector<std::string> edgeIDs;
324  SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs);
325  if (!ok) {
326  return;
327  }
328  for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) {
329  NBEdge* edge = myEdgeCont.retrieve(*it);
330  if (edge == 0) {
331  WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known.");
332  return;
333  }
334  if (node == 0) {
335  if (edge->getToNode()->getID() == nodeID) {
336  node = edge->getToNode();
337  } else if (edge->getFromNode()->getID() == nodeID) {
338  node = edge->getFromNode();
339  } else {
340  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
341  return;
342  }
343  } else {
344  if (edge->getToNode() != node && edge->getFromNode() != node) {
345  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
346  return;
347  }
348  }
349  edges.push_back(edge);
350  }
351  bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true);
352  if (node->isTLControlled() && !priority) {
353  // traffic_light nodes should always have priority crossings
354  WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized");
355  priority = true;
356  }
357  node->addCrossing(edges, width, priority);
358 }
359 
360 
361 
362 /****************************************************************************/
363 
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:2013
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&#39;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&#39;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: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: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:218
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:719
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