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