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.dlr.de/
13 // Copyright (C) 2001-2016 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  const std::string::size_type 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  const SUMOReal contPos = attrs.getOpt<SUMOReal>(SUMO_ATTR_CONTPOS, 0, ok, NBEdge::UNSPECIFIED_CONTPOS);
220  if (!ok) {
221  return;
222  }
223  // get the begin and the end lane
224  int fromLane;
225  int toLane;
226  try {
227  if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
228  return;
229  }
230  if (fromLane < 0) {
231  myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
232  "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
233  from->getID() + "' to '" + to->getID() + "'.");
234  return;
235  }
236  if (toLane < 0) {
237  myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
238  "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
239  from->getID() + "' to '" + to->getID() + "'.");
240  return;
241  }
242  if (from->hasConnectionTo(to, toLane) && from->getToNode()->getType() != NODETYPE_ZIPPER) {
243  WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
244  }
245  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass, keepClear, contPos)) {
246  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
247  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'.");
248  }
249  // set as to be re-applied after network processing
250  myEdgeCont.addPostProcessConnection(from->getID(), fromLane, to->getID(), toLane, mayDefinitelyPass, keepClear, contPos);
251  }
252  } catch (NumberFormatException&) {
253  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
254  }
255  //
256  bool keepUncontrolled = attrs.getOpt<bool>(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
257  if (keepUncontrolled) {
258  from->disableConnection4TLS(fromLane, to, toLane);
259  }
260 }
261 
262 bool
264  int* fromLane, int* toLane) {
265  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
266  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
267  } else {
268  return parseLaneDefinition(attributes, fromLane, toLane);
269  }
270 }
271 
272 
273 inline bool
275  NBEdge* from, NBEdge* to,
276  int* fromLane, int* toLane) {
277  bool ok = true;
280  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
282  "' instead.");
283  }
284 
285  std::string laneConn = attributes.get<std::string>(SUMO_ATTR_LANE, 0, ok);
286  StringTokenizer st(laneConn, ':');
287  if (!ok || st.size() != 2) {
288  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
289  from->getID() + "' to '" + to->getID() + "'.");
290  return false; // There was an error.
291  }
292 
293  *fromLane = TplConvert::_2intSec(st.next().c_str(), -1);
294  *toLane = TplConvert::_2intSec(st.next().c_str(), -1);
295 
296  return true; // We succeeded.
297 }
298 
299 
300 inline bool
302  int* fromLane,
303  int* toLane) {
304  bool ok = true;
305  *fromLane = attributes.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
306  *toLane = attributes.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
307  return ok;
308 }
309 
310 
311 void
313  bool ok = true;
314  NBNode* node = 0;
315  EdgeVector edges;
316  const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok);
317  const SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBNode::DEFAULT_CROSSING_WIDTH, true);
318  const bool discard = attrs.getOpt<bool>(SUMO_ATTR_DISCARD, nodeID.c_str(), ok, false, true);
319  std::vector<std::string> edgeIDs;
320  if (!attrs.hasAttribute(SUMO_ATTR_EDGES)) {
321  if (discard) {
322  node = myNodeCont.retrieve(nodeID);
323  if (node == 0) {
324  WRITE_ERROR("Node '" + nodeID + "' in crossing is not known.");
325  return;
326  }
327  node->discardAllCrossings();
328  return;
329  } else {
330  WRITE_ERROR("No edges specified for crossing at node '" + nodeID + "'.");
331  return;
332  }
333  }
334  SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs);
335  if (!ok) {
336  return;
337  }
338  for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) {
339  NBEdge* edge = myEdgeCont.retrieve(*it);
340  if (edge == 0) {
341  WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known.");
342  return;
343  }
344  if (node == 0) {
345  if (edge->getToNode()->getID() == nodeID) {
346  node = edge->getToNode();
347  } else if (edge->getFromNode()->getID() == nodeID) {
348  node = edge->getFromNode();
349  } else {
350  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
351  return;
352  }
353  } else {
354  if (edge->getToNode() != node && edge->getFromNode() != node) {
355  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
356  return;
357  }
358  }
359  edges.push_back(edge);
360  }
361  bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true);
362  if (node->isTLControlled() && !priority) {
363  // traffic_light nodes should always have priority crossings
364  WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized");
365  priority = true;
366  }
367  if (discard) {
368  node->removeCrossing(edges);
369  } else {
370  node->addCrossing(edges, width, priority);
371  }
372 }
373 
374 
375 void
377  bool ok = true;
378  const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
379  const PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
380  if (!ok) {
381  return;
382  }
383  const std::string nodeID = NBNode::getNodeIDFromInternalLane(id);
384  NBNode* node = myNodeCont.retrieve(nodeID);
385  if (node == 0) {
386  WRITE_ERROR("Node '" + nodeID + "' in customShape is not known.");
387  return;
388  }
389  node->setCustomLaneShape(id, shape);
390 }
391 
392 
393 
394 /****************************************************************************/
395 
Whether vehicles must keep the junction clear.
The relationships between edges are computed/loaded.
Definition: NBEdge.h:94
void addCrossing(const SUMOSAXAttributes &attrs)
Parses a crossing and updates the referenced node.
static const NBConnection InvalidConnection
Definition: NBConnection.h:128
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:304
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:70
void parseLaneBound(const SUMOSAXAttributes &attrs, NBEdge *from, NBEdge *to)
Parses a connection when it describes a lane-2-lane relationship.
static const SUMOReal UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:209
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...
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:697
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
NBEdgeCont & myEdgeCont
The edge container to fill.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
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:673
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:831
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
Definition: NBNode.cpp:2515
bool hasConnectionTo(NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:825
the edges of a route
Encapsulated SAX-Attributes.
void addCustomShape(const SUMOSAXAttributes &attrs)
Parses a customShape and updates the referenced node.
A list of positions.
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:265
EdgeBuildingStep getStep() const
The building step of this edge.
Definition: NBEdge.h:461
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:1712
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
The connection was given by the user.
Definition: NBEdge.h:113
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:935
MsgHandler *const myErrorMsgHandler
the handler for loading errors
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:371
void addCrossing(EdgeVector edges, SUMOReal width, bool priority, bool fromSumoNet=false)
add a pedestrian crossing to this node
Definition: NBNode.cpp:2506
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:247
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
Definition: NBEdge.cpp:2175
bool wasRemoved(std::string id) const
Returns whether the edge with the id was deleted explicitly.
Definition: NBEdgeCont.h:480
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:99
static const SUMOReal DEFAULT_CROSSING_WIDTH
default width of pedetrian crossings
Definition: NBNode.h:186
NIXMLConnectionsHandler(NBEdgeCont &ec, NBNodeCont &nc, 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:1231
#define SUMOReal
Definition: config.h:213
std::string getLaneID(int lane) const
Definition: NBEdge.cpp:2348
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:469
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:110
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
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)
converts a 0-terminated char-type array into the integer value described by it
Definition: TplConvert.h:186
void invalidateTLS(NBTrafficLightLogicCont &tlCont)
causes the traffic light to be computed anew
Definition: NBNode.cpp:352
void addPostProcessConnection(const std::string &from, int fromLane, const std::string &to, int toLane, bool mayDefinitelyPass, bool keepClear, SUMOReal contPos)
Adds a connection which could not be set during loading.
Definition: NBEdgeCont.cpp:804
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:96
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:2594
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:363