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-2017 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 
56 // ===========================================================================
57 // method definitions
58 // ===========================================================================
60  SUMOSAXHandler("xml-connection-description"),
61  myEdgeCont(ec),
62  myNodeCont(nc),
63  myTLLogicCont(tlc),
64  myHaveWarnedAboutDeprecatedLanes(false),
65  myErrorMsgHandler(OptionsCont::getOptions().getBool("ignore-errors.connections") ?
66  MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) {}
67 
68 
70 
71 
72 void
74  const SUMOSAXAttributes& attrs) {
75  if (element == SUMO_TAG_DELETE) {
76  bool ok = true;
77  std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
78  std::string to = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
79  if (!ok) {
80  return;
81  }
82  // these connections were removed when the edge was deleted
83  if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) {
84  return;
85  }
86  NBEdge* fromEdge = myEdgeCont.retrieve(from);
87  NBEdge* toEdge = myEdgeCont.retrieve(to);
88  if (fromEdge == 0) {
89  myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known.");
90  return;
91  }
92  if (toEdge == 0) {
93  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known.");
94  return;
95  }
96  if (!fromEdge->isConnectedTo(toEdge) && fromEdge->getStep() >= NBEdge::EDGE2EDGES) {
97  WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset.");
98  return;
99  }
100  int fromLane = -1; // Assume all lanes are to be reset.
101  int toLane = -1;
102  if (attrs.hasAttribute(SUMO_ATTR_LANE)
104  || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
105  if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) {
106  return;
107  }
108  // we could be trying to reset a connection loaded from a sumo net and which has become obsolete.
109  // In this case it's ok to encounter invalid lance indices
110  if (!fromEdge->hasConnectionTo(toEdge, toLane) && fromEdge->getStep() >= NBEdge::LANES2EDGES) {
111  WRITE_WARNING("Edge '" + fromEdge->getID() + "' has no connection to lane " + toString(toLane) + " of edge '" + toEdge->getID() + "'; the connection cannot be reset.");
112  }
113  }
114  fromEdge->removeFromConnections(toEdge, fromLane, toLane, true);
115  }
116 
117  if (element == SUMO_TAG_CONNECTION) {
118  bool ok = true;
119  std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, "connection", ok);
120  std::string to = attrs.getOpt<std::string>(SUMO_ATTR_TO, "connection", ok, "");
121  if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) {
122  return;
123  }
124  // extract edges
125  NBEdge* fromEdge = myEdgeCont.retrieve(from);
126  NBEdge* toEdge = to.length() != 0 ? myEdgeCont.retrieve(to) : 0;
127  // check whether they are valid
128  if (fromEdge == 0) {
129  myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known.");
130  return;
131  }
132  if (toEdge == 0 && to.length() != 0) {
133  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known.");
134  return;
135  }
136  fromEdge->getToNode()->invalidateTLS(myTLLogicCont, true, false);
137  // parse optional lane information
139  parseLaneBound(attrs, fromEdge, toEdge);
140  } else {
141  fromEdge->addEdge2EdgeConnection(toEdge);
142  }
143  }
144  if (element == SUMO_TAG_PROHIBITION) {
145  bool ok = true;
146  std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, "");
147  std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, "");
148  if (!ok) {
149  return;
150  }
151  NBConnection prohibitorC = parseConnection("prohibitor", prohibitor);
152  NBConnection prohibitedC = parseConnection("prohibited", prohibited);
153  if (prohibitorC == NBConnection::InvalidConnection || prohibitedC == NBConnection::InvalidConnection) {
154  // something failed
155  return;
156  }
157  NBNode* n = prohibitorC.getFrom()->getToNode();
158  n->addSortedLinkFoes(prohibitorC, prohibitedC);
159  }
160  if (element == SUMO_TAG_CROSSING) {
161  addCrossing(attrs);
162  }
163  if (element == SUMO_TAG_CUSTOMSHAPE) {
164  addCustomShape(attrs);
165  }
166 }
167 
168 
170 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) {
171  // split from/to
172  const std::string::size_type div = def.find("->");
173  if (div == std::string::npos) {
174  myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'");
176  }
177  std::string fromDef = def.substr(0, div);
178  std::string toDef = def.substr(div + 2);
179 
180  // retrieve the edges
181  // check whether the definition includes a lane information (do not process it)
182  if (fromDef.find('_') != std::string::npos) {
183  fromDef = fromDef.substr(0, fromDef.find('_'));
184  }
185  if (toDef.find('_') != std::string::npos) {
186  toDef = toDef.substr(0, toDef.find('_'));
187  }
188  // retrieve them now
189  NBEdge* fromE = myEdgeCont.retrieve(fromDef);
190  NBEdge* toE = myEdgeCont.retrieve(toDef);
191  // check
192  if (fromE == 0) {
193  myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'");
195  }
196  if (toE == 0) {
197  myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'");
199  }
200  return NBConnection(fromE, toE);
201 }
202 
203 
204 void
206  if (to == 0) {
207  // do nothing if it's a dead end
208  return;
209  }
210  bool ok = true;
211  const bool mayDefinitelyPass = attrs.getOpt<bool>(SUMO_ATTR_PASS, 0, ok, false);
212  const bool keepClear = attrs.getOpt<bool>(SUMO_ATTR_KEEP_CLEAR, 0, ok, true);
213  const double contPos = attrs.getOpt<double>(SUMO_ATTR_CONTPOS, 0, ok, NBEdge::UNSPECIFIED_CONTPOS);
214  const double visibility = attrs.getOpt<double>(SUMO_ATTR_VISIBILITY_DISTANCE, 0, ok, NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE);
215  if (!ok) {
216  return;
217  }
218  // get the begin and the end lane
219  int fromLane;
220  int toLane;
221  try {
222  if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
223  return;
224  }
225  if (fromLane < 0) {
226  myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
227  "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
228  from->getID() + "' to '" + to->getID() + "'.");
229  return;
230  }
231  if (toLane < 0) {
232  myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
233  "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
234  from->getID() + "' to '" + to->getID() + "'.");
235  return;
236  }
237  if (from->hasConnectionTo(to, toLane) && from->getToNode()->getType() != NODETYPE_ZIPPER) {
238  WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
239  }
240  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass, keepClear, contPos, visibility)) {
241  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
242  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'.");
243  }
244  // set as to be re-applied after network processing
245  myEdgeCont.addPostProcessConnection(from->getID(), fromLane, to->getID(), toLane, mayDefinitelyPass, keepClear, contPos, visibility);
246  }
247  } catch (NumberFormatException&) {
248  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
249  }
250  //
251  bool keepUncontrolled = attrs.getOpt<bool>(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
252  if (keepUncontrolled) {
253  from->disableConnection4TLS(fromLane, to, toLane);
254  }
255 }
256 
257 bool
259  int* fromLane, int* toLane) {
260  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
261  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
262  } else {
263  return parseLaneDefinition(attributes, fromLane, toLane);
264  }
265 }
266 
267 
268 inline bool
270  NBEdge* from, NBEdge* to,
271  int* fromLane, int* toLane) {
272  bool ok = true;
275  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
277  "' instead.");
278  }
279 
280  std::string laneConn = attributes.get<std::string>(SUMO_ATTR_LANE, 0, ok);
281  StringTokenizer st(laneConn, ':');
282  if (!ok || st.size() != 2) {
283  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
284  from->getID() + "' to '" + to->getID() + "'.");
285  return false; // There was an error.
286  }
287 
288  *fromLane = TplConvert::_2intSec(st.next().c_str(), -1);
289  *toLane = TplConvert::_2intSec(st.next().c_str(), -1);
290 
291  return true; // We succeeded.
292 }
293 
294 
295 inline bool
297  int* fromLane,
298  int* toLane) {
299  bool ok = true;
300  *fromLane = attributes.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
301  *toLane = attributes.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
302  return ok;
303 }
304 
305 
306 void
308  bool ok = true;
309  NBNode* node = 0;
310  EdgeVector edges;
311  const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok);
312  const double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBNode::DEFAULT_CROSSING_WIDTH, true);
313  const bool discard = attrs.getOpt<bool>(SUMO_ATTR_DISCARD, nodeID.c_str(), ok, false, true);
314  std::vector<std::string> edgeIDs;
315  if (!attrs.hasAttribute(SUMO_ATTR_EDGES)) {
316  if (discard) {
317  node = myNodeCont.retrieve(nodeID);
318  if (node == 0) {
319  WRITE_ERROR("Node '" + nodeID + "' in crossing is not known.");
320  return;
321  }
322  node->discardAllCrossings(true);
323  return;
324  } else {
325  WRITE_ERROR("No edges specified for crossing at node '" + nodeID + "'.");
326  return;
327  }
328  }
329  SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs);
330  if (!ok) {
331  return;
332  }
333  for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) {
334  NBEdge* edge = myEdgeCont.retrieve(*it);
335  if (edge == 0) {
336  WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known.");
337  return;
338  }
339  if (node == 0) {
340  if (edge->getToNode()->getID() == nodeID) {
341  node = edge->getToNode();
342  } else if (edge->getFromNode()->getID() == nodeID) {
343  node = edge->getFromNode();
344  } else {
345  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
346  return;
347  }
348  } else {
349  if (edge->getToNode() != node && edge->getFromNode() != node) {
350  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
351  return;
352  }
353  }
354  edges.push_back(edge);
355  }
356  bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true);
357  if (node->isTLControlled() && !priority) {
358  // traffic_light nodes should always have priority crossings
359  WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized");
360  priority = true;
361  }
362  if (discard) {
363  node->removeCrossing(edges);
364  } else {
365  node->addCrossing(edges, width, priority);
366  }
367 }
368 
369 
370 void
372  bool ok = true;
373  const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
374  const PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
375  if (!ok) {
376  return;
377  }
378  const std::string nodeID = NBNode::getNodeIDFromInternalLane(id);
379  NBNode* node = myNodeCont.retrieve(nodeID);
380  if (node == 0) {
381  WRITE_ERROR("Node '" + nodeID + "' in customShape is not known.");
382  return;
383  }
384  node->setCustomLaneShape(id, shape);
385 }
386 
387 
388 
389 /****************************************************************************/
390 
void addPostProcessConnection(const std::string &from, int fromLane, const std::string &to, int toLane, bool mayDefinitelyPass, bool keepClear, double contPos, double visibility, bool warnOnly=false)
Adds a connection which could not be set during loading.
Definition: NBEdgeCont.cpp:849
Whether vehicles must keep the junction clear.
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:268
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:127
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:291
connectio between two lanes
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
foe visibility distance of a link
static const double DEFAULT_CROSSING_WIDTH
default width of pedetrian crossings
Definition: NBNode.h:200
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:1187
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)
prohibition of circulation between two edges
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
bool isConnectedTo(const NBEdge *e) const
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:1070
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:65
NBEdgeCont & myEdgeCont
The edge container to fill.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool removedConnections, bool addedConnections)
causes the traffic light to be computed anew
Definition: NBNode.cpp:338
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:889
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.
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
Definition: NBNode.cpp:2606
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:1064
the edges of a route
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
Encapsulated SAX-Attributes.
void addCustomShape(const SUMOSAXAttributes &attrs)
Parses a customShape and updates the referenced node.
A list of positions.
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:265
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:260
EdgeBuildingStep getStep() const
The building step of this edge.
Definition: NBEdge.h:517
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:1744
edge: the shape in xml-definition
void discardAllCrossings(bool rejectAll)
discard all current (and optionally future) crossings
Definition: NBNode.cpp:2065
The connection was given by the user.
Definition: NBEdge.h:113
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
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:435
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)
disable connections for TLS
Definition: NBEdge.cpp:2559
bool wasRemoved(std::string id) const
Returns whether the edge with the id was deleted explicitly.
Definition: NBEdgeCont.h:485
Custom shape for an element.
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:85
A storage for options typed value containers)
Definition: OptionsCont.h:99
NIXMLConnectionsHandler(NBEdgeCont &ec, NBNodeCont &nc, NBTrafficLightLogicCont &tlc)
Constructor.
crossing between edges for pedestrians
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:913
Represents a single node (junction) during network building.
Definition: NBNode.h:75
void addCrossing(EdgeVector edges, double width, bool priority, bool fromSumoNet=false)
add a pedestrian crossing to this node
Definition: NBNode.cpp:2597
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
add shorted link FOES
Definition: NBNode.cpp:1238
std::string getLaneID(int lane) const
get Lane ID (Secure)
Definition: NBEdge.cpp:2746
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:474
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:106
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.
delete certain element
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:196
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)
static std::string getNodeIDFromInternalLane(const std::string id)
returns the node id for internal lanes, crossings and walkingareas
Definition: NBNode.cpp:2707
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:428