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