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  // invalidate traffic light definition loaded from a SUMO network
137  // XXX it would be preferable to reconstruct the phase definitions heuristically
138  fromEdge->getToNode()->invalidateTLS(myTLLogicCont);
139  // parse optional lane information
141  parseLaneBound(attrs, fromEdge, toEdge);
142  } else {
143  fromEdge->addEdge2EdgeConnection(toEdge);
144  }
145  }
146  if (element == SUMO_TAG_PROHIBITION) {
147  bool ok = true;
148  std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, "");
149  std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, "");
150  if (!ok) {
151  return;
152  }
153  NBConnection prohibitorC = parseConnection("prohibitor", prohibitor);
154  NBConnection prohibitedC = parseConnection("prohibited", prohibited);
155  if (prohibitorC == NBConnection::InvalidConnection || prohibitedC == NBConnection::InvalidConnection) {
156  // something failed
157  return;
158  }
159  NBNode* n = prohibitorC.getFrom()->getToNode();
160  n->addSortedLinkFoes(prohibitorC, prohibitedC);
161  }
162  if (element == SUMO_TAG_CROSSING) {
163  addCrossing(attrs);
164  }
165  if (element == SUMO_TAG_CUSTOMSHAPE) {
166  addCustomShape(attrs);
167  }
168 }
169 
170 
172 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) {
173  // split from/to
174  const std::string::size_type div = def.find("->");
175  if (div == std::string::npos) {
176  myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'");
178  }
179  std::string fromDef = def.substr(0, div);
180  std::string toDef = def.substr(div + 2);
181 
182  // retrieve the edges
183  // check whether the definition includes a lane information (do not process it)
184  if (fromDef.find('_') != std::string::npos) {
185  fromDef = fromDef.substr(0, fromDef.find('_'));
186  }
187  if (toDef.find('_') != std::string::npos) {
188  toDef = toDef.substr(0, toDef.find('_'));
189  }
190  // retrieve them now
191  NBEdge* fromE = myEdgeCont.retrieve(fromDef);
192  NBEdge* toE = myEdgeCont.retrieve(toDef);
193  // check
194  if (fromE == 0) {
195  myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'");
197  }
198  if (toE == 0) {
199  myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'");
201  }
202  return NBConnection(fromE, toE);
203 }
204 
205 
206 void
208  if (to == 0) {
209  // do nothing if it's a dead end
210  return;
211  }
212  bool ok = true;
213  const bool mayDefinitelyPass = attrs.getOpt<bool>(SUMO_ATTR_PASS, 0, ok, false);
214  const bool keepClear = attrs.getOpt<bool>(SUMO_ATTR_KEEP_CLEAR, 0, ok, true);
215  const double contPos = attrs.getOpt<double>(SUMO_ATTR_CONTPOS, 0, ok, NBEdge::UNSPECIFIED_CONTPOS);
216  const double visibility = attrs.getOpt<double>(SUMO_ATTR_VISIBILITY_DISTANCE, 0, ok, NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE);
217  if (!ok) {
218  return;
219  }
220  // get the begin and the end lane
221  int fromLane;
222  int toLane;
223  try {
224  if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
225  return;
226  }
227  if (fromLane < 0) {
228  myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
229  "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
230  from->getID() + "' to '" + to->getID() + "'.");
231  return;
232  }
233  if (toLane < 0) {
234  myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
235  "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
236  from->getID() + "' to '" + to->getID() + "'.");
237  return;
238  }
239  if (from->hasConnectionTo(to, toLane) && from->getToNode()->getType() != NODETYPE_ZIPPER) {
240  WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
241  }
242  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass, keepClear, contPos, visibility)) {
243  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
244  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'.");
245  }
246  // set as to be re-applied after network processing
247  myEdgeCont.addPostProcessConnection(from->getID(), fromLane, to->getID(), toLane, mayDefinitelyPass, keepClear, contPos, visibility);
248  }
249  } catch (NumberFormatException&) {
250  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
251  }
252  //
253  bool keepUncontrolled = attrs.getOpt<bool>(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
254  if (keepUncontrolled) {
255  from->disableConnection4TLS(fromLane, to, toLane);
256  }
257 }
258 
259 bool
261  int* fromLane, int* toLane) {
262  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
263  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
264  } else {
265  return parseLaneDefinition(attributes, fromLane, toLane);
266  }
267 }
268 
269 
270 inline bool
272  NBEdge* from, NBEdge* to,
273  int* fromLane, int* toLane) {
274  bool ok = true;
277  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
279  "' instead.");
280  }
281 
282  std::string laneConn = attributes.get<std::string>(SUMO_ATTR_LANE, 0, ok);
283  StringTokenizer st(laneConn, ':');
284  if (!ok || st.size() != 2) {
285  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
286  from->getID() + "' to '" + to->getID() + "'.");
287  return false; // There was an error.
288  }
289 
290  *fromLane = TplConvert::_2intSec(st.next().c_str(), -1);
291  *toLane = TplConvert::_2intSec(st.next().c_str(), -1);
292 
293  return true; // We succeeded.
294 }
295 
296 
297 inline bool
299  int* fromLane,
300  int* toLane) {
301  bool ok = true;
302  *fromLane = attributes.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
303  *toLane = attributes.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
304  return ok;
305 }
306 
307 
308 void
310  bool ok = true;
311  NBNode* node = 0;
312  EdgeVector edges;
313  const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok);
314  const double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBNode::DEFAULT_CROSSING_WIDTH, true);
315  const bool discard = attrs.getOpt<bool>(SUMO_ATTR_DISCARD, nodeID.c_str(), ok, false, true);
316  std::vector<std::string> edgeIDs;
317  if (!attrs.hasAttribute(SUMO_ATTR_EDGES)) {
318  if (discard) {
319  node = myNodeCont.retrieve(nodeID);
320  if (node == 0) {
321  WRITE_ERROR("Node '" + nodeID + "' in crossing is not known.");
322  return;
323  }
324  node->discardAllCrossings();
325  return;
326  } else {
327  WRITE_ERROR("No edges specified for crossing at node '" + nodeID + "'.");
328  return;
329  }
330  }
331  SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs);
332  if (!ok) {
333  return;
334  }
335  for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) {
336  NBEdge* edge = myEdgeCont.retrieve(*it);
337  if (edge == 0) {
338  WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known.");
339  return;
340  }
341  if (node == 0) {
342  if (edge->getToNode()->getID() == nodeID) {
343  node = edge->getToNode();
344  } else if (edge->getFromNode()->getID() == nodeID) {
345  node = edge->getFromNode();
346  } else {
347  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
348  return;
349  }
350  } else {
351  if (edge->getToNode() != node && edge->getFromNode() != node) {
352  WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
353  return;
354  }
355  }
356  edges.push_back(edge);
357  }
358  bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true);
359  if (node->isTLControlled() && !priority) {
360  // traffic_light nodes should always have priority crossings
361  WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized");
362  priority = true;
363  }
364  if (discard) {
365  node->removeCrossing(edges);
366  } else {
367  node->addCrossing(edges, width, priority);
368  }
369 }
370 
371 
372 void
374  bool ok = true;
375  const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
376  const PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
377  if (!ok) {
378  return;
379  }
380  const std::string nodeID = NBNode::getNodeIDFromInternalLane(id);
381  NBNode* node = myNodeCont.retrieve(nodeID);
382  if (node == 0) {
383  WRITE_ERROR("Node '" + nodeID + "' in customShape is not known.");
384  return;
385  }
386  node->setCustomLaneShape(id, shape);
387 }
388 
389 
390 
391 /****************************************************************************/
392 
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:837
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:106
Whether vehicles must keep the junction clear.
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:267
The relationships between edges are computed/loaded.
Definition: NBEdge.h:96
bool isConnectedTo(const NBEdge *e) const
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:1057
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.
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.
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:197
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:1174
NBEdge * getFrom() const
returns the from-edge (start of the connection)
void parseLaneBound(const SUMOSAXAttributes &attrs, NBEdge *from, NBEdge *to)
Parses a 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)
const std::string & getID() const
Returns the id.
Definition: Named.h:66
SAX-handler base for SUMO-files.
bool parseLaneDefinition(const SUMOSAXAttributes &attributes, int *fromLane, int *toLane)
Parses information about lane-2-lane connection.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
prohibition of circulation between two edges
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:65
NBEdgeCont & myEdgeCont
The edge container to fill.
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:876
NBConnection parseConnection(const std::string &defRole, const std::string &def)
Returns the connection described by def.
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:288
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:2553
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.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
std::string getLaneID(int lane) const
get Lane ID (Secure)
Definition: NBEdge.cpp:2679
A list of positions.
bool wasRemoved(std::string id) const
Returns whether the edge with the id was deleted explicitly.
Definition: NBEdgeCont.h:485
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:264
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:1051
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:1729
EdgeBuildingStep getStep() const
The building step of this edge.
Definition: NBEdge.h:516
edge: the shape in xml-definition
The connection was given by the user.
Definition: NBEdge.h:115
MsgHandler *const myErrorMsgHandler
the handler for loading errors
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
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.
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
disable connections for TLS
Definition: NBEdge.cpp:2504
Custom shape for an element.
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:251
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
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:257
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:900
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:2544
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
add shorted link FOES
Definition: NBNode.cpp:1248
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:427
bool wasIgnored(std::string id) const
Returns whether the edge with the id was ignored during parsing.
Definition: NBEdgeCont.h:474
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
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:186
void invalidateTLS(NBTrafficLightLogicCont &tlCont)
causes the traffic light to be computed anew
Definition: NBNode.cpp:350
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:98
NBTrafficLightLogicCont & myTLLogicCont
The traffic lights container to add built tls to (when invalidating tls)
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:434
void discardAllCrossings()
discard all crossings
Definition: NBNode.h:610
static std::string getNodeIDFromInternalLane(const std::string id)
returns the node id for internal lanes, crossings and walkingareas
Definition: NBNode.cpp:2663