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-sim.org/
13 // Copyright (C) 2001-2013 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.getFrom() == 0 || prohibitedC.getFrom() == 0) {
158  // something failed
159  return;
160  }
161  NBNode* n = prohibitorC.getFrom()->getToNode();
162  n->addSortedLinkFoes(prohibitorC, prohibitedC);
163  }
164 }
165 
166 
168 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) {
169  // split from/to
170  size_t div = def.find("->");
171  if (div == std::string::npos) {
172  myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'");
173  return NBConnection(0, 0);
174  }
175  std::string fromDef = def.substr(0, div);
176  std::string toDef = def.substr(div + 2);
177 
178  // retrieve the edges
179  // check whether the definition includes a lane information (do not process it)
180  if (fromDef.find('_') != std::string::npos) {
181  fromDef = fromDef.substr(0, fromDef.find('_'));
182  }
183  if (toDef.find('_') != std::string::npos) {
184  toDef = toDef.substr(0, toDef.find('_'));
185  }
186  // retrieve them now
187  NBEdge* fromE = myEdgeCont.retrieve(fromDef);
188  NBEdge* toE = myEdgeCont.retrieve(toDef);
189  // check
190  if (fromE == 0) {
191  myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'");
192  return NBConnection(0, 0);
193  }
194  if (toE == 0) {
195  myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'");
196  return NBConnection(0, 0);
197  }
198  return NBConnection(fromE, toE);
199 }
200 
201 
202 void
204  if (to == 0) {
205  // do nothing if it's a dead end
206  return;
207  }
208  bool ok = true;
209  const bool mayDefinitelyPass = attrs.getOpt<bool>(SUMO_ATTR_PASS, 0, ok, false);
210  if (!ok) {
211  return;
212  }
213  // get the begin and the end lane
214  int fromLane;
215  int toLane;
216  try {
217  if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
218  return;
219  }
220  if (fromLane < 0) {
221  myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
222  "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
223  from->getID() + "' to '" + to->getID() + "'.");
224  return;
225  }
226  if (toLane < 0) {
227  myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
228  "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
229  from->getID() + "' to '" + to->getID() + "'.");
230  return;
231  }
232  if (from->hasConnectionTo(to, toLane)) {
233  WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
234  }
235  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass)) {
236  NBEdge* nFrom = from;
237  bool toNext = true;
238  do {
239  if (nFrom->getToNode()->getOutgoingEdges().size() != 1) {
240  toNext = false;
241  break;
242  }
243  NBEdge* t = nFrom->getToNode()->getOutgoingEdges()[0];
244  if (t->getID().substr(0, t->getID().find('/')) != nFrom->getID().substr(0, nFrom->getID().find('/'))) {
245  toNext = false;
246  break;
247  }
248  if (toNext) {
249  nFrom = t;
250  }
251  } while (toNext);
252  if (nFrom == 0 || !nFrom->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, mayDefinitelyPass)) {
253  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
254  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'.");
255  }
256  // set as to be re-applied after network processing
257  myEdgeCont.addPostProcessConnection(nFrom->getID(), fromLane, to->getID(), toLane, mayDefinitelyPass);
258  } else {
259  from = nFrom;
260  }
261  }
262  } catch (NumberFormatException&) {
263  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
264  }
265  //
266  bool keepUncontrolled = attrs.getOpt<bool>(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
267  if (keepUncontrolled) {
268  from->disableConnection4TLS(fromLane, to, toLane);
269  }
270 }
271 
272 bool
274  int* fromLane, int* toLane) {
275  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
276  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
277  } else {
278  return parseLaneDefinition(attributes, fromLane, toLane);
279  }
280 }
281 
282 
283 inline bool
285  NBEdge* from, NBEdge* to,
286  int* fromLane, int* toLane) {
287  bool ok = true;
290  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
292  "' instead.");
293  }
294 
295  std::string laneConn = attributes.get<std::string>(SUMO_ATTR_LANE, 0, ok);
296  StringTokenizer st(laneConn, ':');
297  if (!ok || st.size() != 2) {
298  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
299  from->getID() + "' to '" + to->getID() + "'.");
300  return false; // There was an error.
301  }
302 
303  *fromLane = TplConvert::_2intSec(st.next().c_str(), -1);
304  *toLane = TplConvert::_2intSec(st.next().c_str(), -1);
305 
306  return true; // We succeeded.
307 }
308 
309 
310 inline bool
312  int* fromLane,
313  int* toLane) {
314  bool ok = true;
315  *fromLane = attributes.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
316  *toLane = attributes.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
317  return ok;
318 }
319 
320 /****************************************************************************/
321 
The relationships between edges are computed/loaded.
Definition: NBEdge.h:95
A container for traffic light definitions and built programs.
bool myHaveWarnedAboutDeprecatedLanes
Information whether we have a deprecated attribute.
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
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:613
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:196
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges.
Definition: NBNode.h:185
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:589
NBConnection parseConnection(const std::string &defRole, const std::string &def)
Returns the connection described by def.
bool isConnectedTo(NBEdge *e)
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:729
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:1869
Encapsulated SAX-Attributes.
EdgeBuildingStep getStep() const
The building step of this edge.
Definition: NBEdge.h:432
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:51
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:824
MsgHandler *const myErrorMsgHandler
the handler for loading errors
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:362
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:251
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
Definition: NBEdge.cpp:1723
bool wasRemoved(std::string id) const
Returns whether the edge with the id was deleted explicitly.
Definition: NBEdgeCont.h:470
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
NIXMLConnectionsHandler(NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Constructor.
Represents a single node (junction) during network building.
Definition: NBNode.h:74
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
Definition: NBNode.cpp:934
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
bool hasConnectionTo(NBEdge *destEdge, unsigned int destLane) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:723
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:296
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:729
NBTrafficLightLogicCont & myTLLogicCont
The traffic lights container to add built tls to (when invalidating tls)