SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 // The handler for SUMO-Networks 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 <utils/options/OptionsCont.h> 00036 #include <utils/common/MsgHandler.h> 00037 #include <utils/common/StringTokenizer.h> 00038 #include <utils/common/UtilExceptions.h> 00039 #include <utils/common/ToString.h> 00040 #include <utils/xml/SUMOSAXHandler.h> 00041 #include <utils/xml/SUMOXMLDefinitions.h> 00042 #include "ROEdge.h" 00043 #include "ROLane.h" 00044 #include "RONode.h" 00045 #include "RONet.h" 00046 #include "RONetHandler.h" 00047 #include "ROAbstractEdgeBuilder.h" 00048 00049 #ifdef CHECK_MEMORY_LEAKS 00050 #include <foreign/nvwa/debug_new.h> 00051 #endif // CHECK_MEMORY_LEAKS 00052 00053 00054 // =========================================================================== 00055 // method definitions 00056 // =========================================================================== 00057 RONetHandler::RONetHandler(RONet& net, 00058 ROAbstractEdgeBuilder& eb) 00059 : SUMOSAXHandler("sumo-network"), 00060 myNet(net), myCurrentName(), 00061 myCurrentEdge(0), myEdgeBuilder(eb), 00062 myHaveWarnedAboutDeprecatedDistrict(false), myHaveWarnedAboutDeprecatedDSource(false), myHaveWarnedAboutDeprecatedDSink(false) {} 00063 00064 00065 RONetHandler::~RONetHandler() {} 00066 00067 00068 void 00069 RONetHandler::myStartElement(int element, 00070 const SUMOSAXAttributes& attrs) { 00071 switch (element) { 00072 case SUMO_TAG_EDGE: 00073 // in the first step, we do need the name to allocate the edge 00074 // in the second, we need it to know to which edge we have to add 00075 // the following edges to 00076 parseEdge(attrs); 00077 break; 00078 case SUMO_TAG_LANE: 00079 if (myProcess) { 00080 parseLane(attrs); 00081 } 00082 break; 00083 case SUMO_TAG_JUNCTION: 00084 parseJunction(attrs); 00085 break; 00086 case SUMO_TAG_SUCC: 00087 parseConnectingEdge(attrs); 00088 break; 00089 case SUMO_TAG_SUCCLANE: 00090 parseConnectedEdge(attrs); 00091 break; 00092 case SUMO_TAG_CONNECTION: 00093 parseConnection(attrs); 00094 break; 00095 case SUMO_TAG_DISTRICT__DEPRECATED: 00096 if (!myHaveWarnedAboutDeprecatedDistrict) { 00097 myHaveWarnedAboutDeprecatedDistrict = true; 00098 WRITE_WARNING("'" + toString(SUMO_TAG_DISTRICT__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_TAG_TAZ) + "'."); 00099 } 00100 case SUMO_TAG_TAZ: 00101 parseDistrict(attrs); 00102 break; 00103 case SUMO_TAG_DSOURCE__DEPRECATED: 00104 if (!myHaveWarnedAboutDeprecatedDSource) { 00105 myHaveWarnedAboutDeprecatedDSource = true; 00106 WRITE_WARNING("'" + toString(SUMO_TAG_DSOURCE__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_TAG_TAZSOURCE) + "'."); 00107 } 00108 case SUMO_TAG_TAZSOURCE: 00109 parseDistrictEdge(attrs, true); 00110 break; 00111 case SUMO_TAG_DSINK__DEPRECATED: 00112 if (!myHaveWarnedAboutDeprecatedDSink) { 00113 myHaveWarnedAboutDeprecatedDSink = true; 00114 WRITE_WARNING("'" + toString(SUMO_TAG_DSINK__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_TAG_TAZSINK) + "'."); 00115 } 00116 case SUMO_TAG_TAZSINK: 00117 parseDistrictEdge(attrs, false); 00118 break; 00119 default: 00120 break; 00121 } 00122 } 00123 00124 00125 void 00126 RONetHandler::parseEdge(const SUMOSAXAttributes& attrs) { 00127 // get the id, report an error if not given or empty... 00128 bool ok = true; 00129 myCurrentName = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00130 if (!ok) { 00131 throw ProcessError(); 00132 } 00133 // get the edge 00134 myCurrentEdge = 0; 00135 if (myCurrentName[0] == ':') { 00136 // this is an internal edge - we will not use it 00137 // !!! recheck this; internal edges may be of importance during the dua 00138 return; 00139 } 00140 std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, myCurrentName.c_str(), ok); 00141 std::string to = attrs.getStringReporting(SUMO_ATTR_TO, myCurrentName.c_str(), ok); 00142 std::string type = attrs.hasAttribute(SUMO_ATTR_FUNCTION) ? attrs.getStringReporting(SUMO_ATTR_FUNCTION, myCurrentName.c_str(), ok) : ""; 00143 if (!ok) { 00144 return; 00145 } 00146 RONode* fromNode = myNet.getNode(from); 00147 if (fromNode == 0) { 00148 fromNode = new RONode(from); 00149 myNet.addNode(fromNode); 00150 } 00151 RONode* toNode = myNet.getNode(to); 00152 if (toNode == 0) { 00153 toNode = new RONode(to); 00154 myNet.addNode(toNode); 00155 } 00156 // build the edge 00157 myCurrentEdge = myEdgeBuilder.buildEdge(myCurrentName, fromNode, toNode); 00158 if (myNet.addEdge(myCurrentEdge)) { 00159 // get the type of the edge 00160 myProcess = true; 00161 if (type == "" || type == "normal" || type == "connector") { 00162 myCurrentEdge->setType(ROEdge::ET_NORMAL); 00163 } else if (type == "source") { 00164 myCurrentEdge->setType(ROEdge::ET_SOURCE); 00165 } else if (type == "sink") { 00166 myCurrentEdge->setType(ROEdge::ET_SINK); 00167 } else if (type == "internal") { 00168 myProcess = false; 00169 } else { 00170 WRITE_ERROR("Edge '" + myCurrentName + "' has an unknown type."); 00171 return; 00172 } 00173 } else { 00174 myCurrentEdge = 0; 00175 } 00176 } 00177 00178 00179 void 00180 RONetHandler::parseLane(const SUMOSAXAttributes& attrs) { 00181 if (myCurrentEdge == 0) { 00182 // was an internal edge to skip or an error occured 00183 return; 00184 } 00185 bool ok = true; 00186 // get the id, report an error if not given or empty... 00187 std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00188 if (!ok) { 00189 return; 00190 } 00191 // get the speed 00192 SUMOReal maxSpeed = attrs.hasAttribute(SUMO_ATTR_SPEED) 00193 ? attrs.getSUMORealReporting(SUMO_ATTR_SPEED, id.c_str(), ok) 00194 : attrs.getSUMORealReporting(SUMO_ATTR_MAXSPEED__DEPRECATED, id.c_str(), ok); 00195 SUMOReal length = attrs.getSUMORealReporting(SUMO_ATTR_LENGTH, id.c_str(), ok); 00196 std::string allow = attrs.getOptStringReporting(SUMO_ATTR_ALLOW, id.c_str(), ok, ""); 00197 std::string disallow = attrs.getOptStringReporting(SUMO_ATTR_DISALLOW, id.c_str(), ok, ""); 00198 if (!ok) { 00199 return; 00200 } 00201 // get the length 00202 // get the vehicle classes 00203 SVCPermissions permissions = parseVehicleClasses(allow, disallow); 00204 if (permissions != SVCFreeForAll) { 00205 myNet.setRestrictionFound(); 00206 } 00207 // add when both values are valid 00208 if (maxSpeed > 0 && length > 0 && id.length() > 0) { 00209 myCurrentEdge->addLane(new ROLane(id, length, maxSpeed, permissions)); 00210 } 00211 } 00212 00213 00214 void 00215 RONetHandler::parseJunction(const SUMOSAXAttributes& attrs) { 00216 bool ok = true; 00217 // get the id, report an error if not given or empty... 00218 std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00219 if (!ok) { 00220 return; 00221 } 00222 // get the position of the node 00223 SUMOReal x = attrs.getSUMORealReporting(SUMO_ATTR_X, id.c_str(), ok); 00224 SUMOReal y = attrs.getSUMORealReporting(SUMO_ATTR_Y, id.c_str(), ok); 00225 if (ok) { 00226 RONode* n = myNet.getNode(id); 00227 if (n == 0) { 00228 n = new RONode(id); 00229 myNet.addNode(n); 00230 } 00231 n->setPosition(Position(x, y)); 00232 } else { 00233 throw ProcessError(); 00234 } 00235 } 00236 00237 00238 void 00239 RONetHandler::parseConnectingEdge(const SUMOSAXAttributes& attrs) { 00240 bool ok = true; 00241 std::string id = attrs.getStringReporting(SUMO_ATTR_EDGE, 0, ok); 00242 if (id[0] == ':') { 00243 myCurrentEdge = 0; 00244 return; 00245 } 00246 myCurrentEdge = myNet.getEdge(id); 00247 if (myCurrentEdge == 0) { 00248 throw ProcessError("An unknown edge occured (id='" + id + "')."); 00249 } 00250 } 00251 00252 00253 void 00254 RONetHandler::parseConnectedEdge(const SUMOSAXAttributes& attrs) { 00255 if (myCurrentEdge == 0) { 00256 // earlier error or internal link 00257 return; 00258 } 00259 bool ok = true; 00260 std::string id = attrs.getStringReporting(SUMO_ATTR_LANE, myCurrentName.c_str(), ok); 00261 if (id == "SUMO_NO_DESTINATION") { 00262 return; 00263 } 00264 ROEdge* succ = myNet.getEdge(id.substr(0, id.rfind('_'))); 00265 if (succ != 0) { 00266 // connect edge 00267 myCurrentEdge->addFollower(succ); 00268 } else { 00269 WRITE_ERROR("At edge '" + myCurrentName + "': succeeding edge '" + id + "' does not exist."); 00270 } 00271 } 00272 00273 00274 void 00275 RONetHandler::parseConnection(const SUMOSAXAttributes& attrs) { 00276 bool ok = true; 00277 std::string fromID = attrs.getStringReporting(SUMO_ATTR_FROM, 0, ok); 00278 std::string toID = attrs.getStringReporting(SUMO_ATTR_TO, 0, ok); 00279 std::string dir = attrs.getStringReporting(SUMO_ATTR_DIR, 0, ok); 00280 if (fromID[0] == ':') { // skip inner lane connections 00281 return; 00282 } 00283 ROEdge* from = myNet.getEdge(fromID); 00284 ROEdge* to = myNet.getEdge(toID); 00285 if (from == 0) { 00286 throw ProcessError("unknown from-edge '" + fromID + "' in connection"); 00287 } 00288 if (to == 0) { 00289 throw ProcessError("unknown to-edge '" + toID + "' in connection"); 00290 } 00291 from->addFollower(to, dir); 00292 } 00293 00294 00295 void 00296 RONetHandler::parseDistrict(const SUMOSAXAttributes& attrs) { 00297 myCurrentEdge = 0; 00298 bool ok = true; 00299 myCurrentName = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00300 if (!ok) { 00301 return; 00302 } 00303 ROEdge* sink = myEdgeBuilder.buildEdge(myCurrentName + "-sink", 0, 0); 00304 sink->setType(ROEdge::ET_DISTRICT); 00305 myNet.addEdge(sink); 00306 ROEdge* source = myEdgeBuilder.buildEdge(myCurrentName + "-source", 0, 0); 00307 source->setType(ROEdge::ET_DISTRICT); 00308 myNet.addEdge(source); 00309 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) { 00310 std::vector<std::string> desc = StringTokenizer(attrs.getString(SUMO_ATTR_EDGES)).getVector(); 00311 for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) { 00312 ROEdge* edge = myNet.getEdge(*i); 00313 // check whether the edge exists 00314 if (edge == 0) { 00315 throw ProcessError("The edge '" + *i + "' within district '" + myCurrentName + "' is not known."); 00316 } 00317 source->addFollower(edge); 00318 edge->addFollower(sink); 00319 } 00320 } 00321 } 00322 00323 00324 void 00325 RONetHandler::parseDistrictEdge(const SUMOSAXAttributes& attrs, bool isSource) { 00326 bool ok = true; 00327 std::string id = attrs.getStringReporting(SUMO_ATTR_ID, myCurrentName.c_str(), ok); 00328 ROEdge* succ = myNet.getEdge(id); 00329 if (succ != 0) { 00330 // connect edge 00331 if (isSource) { 00332 myNet.getEdge(myCurrentName + "-source")->addFollower(succ); 00333 } else { 00334 succ->addFollower(myNet.getEdge(myCurrentName + "-sink")); 00335 } 00336 } else { 00337 WRITE_ERROR("At district '" + myCurrentName + "': succeeding edge '" + id + "' does not exist."); 00338 } 00339 } 00340 00341 00342 00343 /****************************************************************************/ 00344