SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 // Importer for edge connections stored in XML 00011 /****************************************************************************/ 00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00014 /****************************************************************************/ 00015 // 00016 // This file is part of SUMO. 00017 // SUMO is free software: you can redistribute it and/or modify 00018 // it under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation, either version 3 of the License, or 00020 // (at your option) any later version. 00021 // 00022 /****************************************************************************/ 00023 00024 00025 // =========================================================================== 00026 // included modules 00027 // =========================================================================== 00028 #ifdef _MSC_VER 00029 #include <windows_config.h> 00030 #else 00031 #include <config.h> 00032 #endif 00033 00034 #include <string> 00035 #include <iostream> 00036 #include <xercesc/sax/HandlerBase.hpp> 00037 #include <xercesc/sax/AttributeList.hpp> 00038 #include <xercesc/sax/SAXParseException.hpp> 00039 #include <xercesc/sax/SAXException.hpp> 00040 #include "NIXMLConnectionsHandler.h" 00041 #include <netbuild/NBEdge.h> 00042 #include <netbuild/NBEdgeCont.h> 00043 #include <netbuild/NBNode.h> 00044 #include <utils/common/StringTokenizer.h> 00045 #include <utils/xml/SUMOSAXHandler.h> 00046 #include <utils/xml/SUMOXMLDefinitions.h> 00047 #include <utils/common/ToString.h> 00048 #include <utils/common/TplConvert.h> 00049 #include <utils/common/TplConvertSec.h> 00050 #include <utils/common/UtilExceptions.h> 00051 #include <utils/common/MsgHandler.h> 00052 #include <utils/options/OptionsCont.h> 00053 00054 #ifdef CHECK_MEMORY_LEAKS 00055 #include <foreign/nvwa/debug_new.h> 00056 #endif // CHECK_MEMORY_LEAKS 00057 00058 00059 // =========================================================================== 00060 // method definitions 00061 // =========================================================================== 00062 NIXMLConnectionsHandler::NIXMLConnectionsHandler(NBEdgeCont& ec) : 00063 SUMOSAXHandler("xml-connection-description"), 00064 myEdgeCont(ec), 00065 myHaveWarnedAboutDeprecatedLanes(false), 00066 myErrorMsgHandler(OptionsCont::getOptions().getBool("ignore-errors.connections") ? 00067 MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) {} 00068 00069 00070 NIXMLConnectionsHandler::~NIXMLConnectionsHandler() {} 00071 00072 00073 void 00074 NIXMLConnectionsHandler::myStartElement(int element, 00075 const SUMOSAXAttributes& attrs) { 00076 if (element == SUMO_TAG_DELETE) { 00077 bool ok = true; 00078 std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, 0, ok); 00079 std::string to = attrs.getStringReporting(SUMO_ATTR_TO, 0, ok); 00080 if (!ok) { 00081 return; 00082 } 00083 // these connections were removed when the edge was deleted 00084 if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) { 00085 return; 00086 } 00087 NBEdge* fromEdge = myEdgeCont.retrieve(from); 00088 NBEdge* toEdge = myEdgeCont.retrieve(to); 00089 if (fromEdge == 0) { 00090 myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known."); 00091 return; 00092 } 00093 if (toEdge == 0) { 00094 myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known."); 00095 return; 00096 } 00097 if (!fromEdge->isConnectedTo(toEdge)) { 00098 WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset."); 00099 return; 00100 } 00101 int fromLane = -1; // Assume all lanes are to be reset. 00102 int toLane = -1; 00103 if (attrs.hasAttribute(SUMO_ATTR_LANE) 00104 || attrs.hasAttribute(SUMO_ATTR_FROM_LANE) 00105 || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) { 00106 if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) { 00107 return; 00108 } 00109 // we could be trying to reset a connection loaded from a sumo net and which has become obsolete. 00110 // In this case it's ok to encounter invalid lance indices 00111 if (!fromEdge->hasConnectionTo(toEdge, toLane)) { 00112 WRITE_WARNING("Edge '" + fromEdge->getID() + "' has no connection to lane " + toString(toLane) + " of edge '" + toEdge->getID() + "'; the connection cannot be reset."); 00113 } 00114 } 00115 fromEdge->removeFromConnections(toEdge, fromLane, toLane); 00116 } 00117 00118 if (element == SUMO_TAG_CONNECTION) { 00119 bool ok = true; 00120 std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, "connection", ok); 00121 std::string to = attrs.getOptStringReporting(SUMO_ATTR_TO, "connection", ok, ""); 00122 if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) { 00123 return; 00124 } 00125 // extract edges 00126 NBEdge* fromEdge = myEdgeCont.retrieve(from); 00127 NBEdge* toEdge = to.length() != 0 ? myEdgeCont.retrieve(to) : 0; 00128 // check whether they are valid 00129 if (fromEdge == 0) { 00130 myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known."); 00131 return; 00132 } 00133 if (toEdge == 0 && to.length() != 0) { 00134 myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known."); 00135 return; 00136 } 00137 // parse optional lane information 00138 if (attrs.hasAttribute(SUMO_ATTR_LANE) || attrs.hasAttribute(SUMO_ATTR_FROM_LANE) || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) { 00139 parseLaneBound(attrs, fromEdge, toEdge); 00140 } else { 00141 fromEdge->addEdge2EdgeConnection(toEdge); 00142 } 00143 } 00144 if (element == SUMO_TAG_PROHIBITION) { 00145 bool ok = true; 00146 std::string prohibitor = attrs.getOptStringReporting(SUMO_ATTR_PROHIBITOR, 0, ok, ""); 00147 std::string prohibited = attrs.getOptStringReporting(SUMO_ATTR_PROHIBITED, 0, ok, ""); 00148 if (!ok) { 00149 return; 00150 } 00151 NBConnection prohibitorC = parseConnection("prohibitor", prohibitor); 00152 NBConnection prohibitedC = parseConnection("prohibited", prohibited); 00153 if (prohibitorC.getFrom() == 0 || prohibitedC.getFrom() == 0) { 00154 // something failed 00155 return; 00156 } 00157 NBNode* n = prohibitorC.getFrom()->getToNode(); 00158 n->addSortedLinkFoes(prohibitorC, prohibitedC); 00159 } 00160 } 00161 00162 00163 NBConnection 00164 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) { 00165 // split from/to 00166 size_t div = def.find("->"); 00167 if (div == std::string::npos) { 00168 myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'"); 00169 return NBConnection(0, 0); 00170 } 00171 std::string fromDef = def.substr(0, div); 00172 std::string toDef = def.substr(div + 2); 00173 00174 // retrieve the edges 00175 // check whether the definition includes a lane information (do not process it) 00176 if (fromDef.find('_') != std::string::npos) { 00177 fromDef = fromDef.substr(0, fromDef.find('_')); 00178 } 00179 if (toDef.find('_') != std::string::npos) { 00180 toDef = toDef.substr(0, toDef.find('_')); 00181 } 00182 // retrieve them now 00183 NBEdge* fromE = myEdgeCont.retrieve(fromDef); 00184 NBEdge* toE = myEdgeCont.retrieve(toDef); 00185 // check 00186 if (fromE == 0) { 00187 myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'"); 00188 return NBConnection(0, 0); 00189 } 00190 if (toE == 0) { 00191 myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'"); 00192 return NBConnection(0, 0); 00193 } 00194 return NBConnection(fromE, toE); 00195 } 00196 00197 00198 void 00199 NIXMLConnectionsHandler::parseLaneBound(const SUMOSAXAttributes& attrs, NBEdge* from, NBEdge* to) { 00200 if (to == 0) { 00201 // do nothing if it's a dead end 00202 return; 00203 } 00204 bool ok = true; 00205 const bool mayDefinitelyPass = attrs.getOptBoolReporting(SUMO_ATTR_PASS, 0, ok, false); 00206 if (!ok) { 00207 return; 00208 } 00209 // get the begin and the end lane 00210 int fromLane; 00211 int toLane; 00212 try { 00213 if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) { 00214 return; 00215 } 00216 if (!validateLaneInfo(false /* canLanesBeNegative */, from, to, fromLane, toLane)) { 00217 return; 00218 } 00219 if (from->hasConnectionTo(to, toLane)) { 00220 WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'."); 00221 } 00222 if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass)) { 00223 NBEdge* nFrom = from; 00224 bool toNext = true; 00225 do { 00226 if (nFrom->getToNode()->getOutgoingEdges().size() != 1) { 00227 toNext = false; 00228 break; 00229 } 00230 NBEdge* t = nFrom->getToNode()->getOutgoingEdges()[0]; 00231 if (t->getID().substr(0, t->getID().find('/')) != nFrom->getID().substr(0, nFrom->getID().find('/'))) { 00232 toNext = false; 00233 break; 00234 } 00235 if (toNext) { 00236 nFrom = t; 00237 } 00238 } while (toNext); 00239 if (nFrom == 0 || !nFrom->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, mayDefinitelyPass)) { 00240 WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + 00241 "' to '" + to->getLaneID(toLane) + "'."); 00242 } else { 00243 from = nFrom; 00244 } 00245 } 00246 } catch (NumberFormatException&) { 00247 myErrorMsgHandler->inform("At least one of the defined lanes was not numeric"); 00248 } 00249 // 00250 bool keepUncontrolled = attrs.getOptBoolReporting(SUMO_ATTR_UNCONTROLLED, 0, ok, false); 00251 if (keepUncontrolled) { 00252 from->disableConnection4TLS(fromLane, to, toLane); 00253 } 00254 } 00255 00256 bool 00257 NIXMLConnectionsHandler::parseLaneInfo(const SUMOSAXAttributes& attributes, NBEdge* fromEdge, NBEdge* toEdge, 00258 int* fromLane, int* toLane) { 00259 if (attributes.hasAttribute(SUMO_ATTR_LANE)) { 00260 return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane); 00261 } else { 00262 return parseLaneDefinition(attributes, fromLane, toLane); 00263 } 00264 } 00265 00266 00267 inline bool 00268 NIXMLConnectionsHandler::parseDeprecatedLaneDefinition(const SUMOSAXAttributes& attributes, 00269 NBEdge* from, NBEdge* to, 00270 int* fromLane, int* toLane) { 00271 bool ok = true; 00272 if (!myHaveWarnedAboutDeprecatedLanes) { 00273 myHaveWarnedAboutDeprecatedLanes = true; 00274 WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" + 00275 toString(SUMO_ATTR_FROM_LANE) + "' and '" + toString(SUMO_ATTR_TO_LANE) + 00276 "' instead."); 00277 } 00278 00279 std::string laneConn = attributes.getStringReporting(SUMO_ATTR_LANE, 0, ok); 00280 StringTokenizer st(laneConn, ':'); 00281 if (!ok || st.size() != 2) { 00282 myErrorMsgHandler->inform("Invalid lane to lane connection from '" + 00283 from->getID() + "' to '" + to->getID() + "'."); 00284 return false; // There was an error. 00285 } 00286 00287 *fromLane = TplConvertSec<char>::_2intSec(st.next().c_str(), -1); 00288 *toLane = TplConvertSec<char>::_2intSec(st.next().c_str(), -1); 00289 00290 return true; // We succeeded. 00291 } 00292 00293 00294 inline bool 00295 NIXMLConnectionsHandler::parseLaneDefinition(const SUMOSAXAttributes& attributes, 00296 int* fromLane, 00297 int* toLane) { 00298 bool ok = true; 00299 *fromLane = attributes.getIntReporting(SUMO_ATTR_FROM_LANE, 0, ok); 00300 *toLane = attributes.getIntReporting(SUMO_ATTR_TO_LANE, 0, ok); 00301 return ok; 00302 } 00303 00304 00305 bool 00306 NIXMLConnectionsHandler::validateLaneInfo(bool canLanesBeNegative, NBEdge* fromEdge, NBEdge* toEdge, int fromLane, int toLane) { 00307 if ((!canLanesBeNegative && fromLane < 0) || 00308 static_cast<unsigned int>(fromLane) >= fromEdge->getNumLanes()) { 00309 myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) + 00310 "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" + 00311 fromEdge->getID() + "' to '" + toEdge->getID() + "'."); 00312 return false; 00313 } 00314 if ((!canLanesBeNegative && toLane < 0) || 00315 static_cast<unsigned int>(toLane) >= toEdge->getNumLanes()) { 00316 myErrorMsgHandler->inform("Invalid value '" + toString(toLane) + 00317 "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" + 00318 fromEdge->getID() + "' to '" + toEdge->getID() + "'."); 00319 return false; 00320 } 00321 return true; 00322 } 00323 00324 /****************************************************************************/ 00325