|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // The router's network representation 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 <fstream> 00033 #include <deque> 00034 #include <queue> 00035 #include "ROEdge.h" 00036 #include "RONode.h" 00037 #include "RONet.h" 00038 #include "RORoute.h" 00039 #include "RORouteDef.h" 00040 #include "ROVehicle.h" 00041 #include <utils/common/SUMOVTypeParameter.h> 00042 #include <utils/common/SUMOAbstractRouter.h> 00043 #include <utils/options/OptionsCont.h> 00044 #include <utils/common/UtilExceptions.h> 00045 #include <utils/common/MsgHandler.h> 00046 #include <utils/common/ToString.h> 00047 #include <utils/common/RandHelper.h> 00048 #include <utils/common/SUMOVehicleClass.h> 00049 #include <utils/iodevices/OutputDevice.h> 00050 00051 #ifdef CHECK_MEMORY_LEAKS 00052 #include <foreign/nvwa/debug_new.h> 00053 #endif // CHECK_MEMORY_LEAKS 00054 00055 00056 // =========================================================================== 00057 // method definitions 00058 // =========================================================================== 00059 RONet::RONet() throw() 00060 : myVehicleTypes(), 00061 myRoutesOutput(0), myRouteAlternativesOutput(0), 00062 myReadRouteNo(0), myDiscardedRouteNo(0), myWrittenRouteNo(0), 00063 myHaveRestrictions(false) {} 00064 00065 00066 RONet::~RONet() throw() { 00067 myNodes.clear(); 00068 myEdges.clear(); 00069 myVehicleTypes.clear(); 00070 myRoutes.clear(); 00071 myVehicles.clear(); 00072 } 00073 00074 00075 bool 00076 RONet::addEdge(ROEdge* edge) throw() { 00077 if (!myEdges.add(edge->getID(), edge)) { 00078 WRITE_ERROR("The edge '" + edge->getID() + "' occurs at least twice."); 00079 delete edge; 00080 return false; 00081 } 00082 return true; 00083 } 00084 00085 00086 void 00087 RONet::addNode(RONode* node) throw() { 00088 if (!myNodes.add(node->getID(), node)) { 00089 WRITE_ERROR("The node '" + node->getID() + "' occurs at least twice."); 00090 delete node; 00091 } 00092 } 00093 00094 00095 bool 00096 RONet::addRouteDef(RORouteDef* def) throw() { 00097 return myRoutes.add(def->getID(), def); 00098 } 00099 00100 00101 void 00102 RONet::openOutput(const std::string& filename, bool useAlternatives) throw(IOError) { 00103 myRoutesOutput = &OutputDevice::getDevice(filename); 00104 myRoutesOutput->writeXMLHeader("routes", "", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/routes_file.xsd\""); 00105 if (useAlternatives) { 00106 size_t len = filename.length(); 00107 if (len > 4 && filename.substr(len - 4) == ".xml") { 00108 myRouteAlternativesOutput = &OutputDevice::getDevice(filename.substr(0, len-4)+".alt.xml"); 00109 } else { 00110 myRouteAlternativesOutput = &OutputDevice::getDevice(filename+".alt"); 00111 } 00112 myRouteAlternativesOutput->writeXMLHeader("route-alternatives", "", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/routes_file.xsd\""); 00113 } 00114 } 00115 00116 00117 void 00118 RONet::closeOutput() throw() { 00119 // end writing 00120 if (myRoutesOutput!= 0) { 00121 myRoutesOutput->close(); 00122 } 00123 // only if opened 00124 if (myRouteAlternativesOutput!=0) { 00125 myRouteAlternativesOutput->close(); 00126 } 00127 } 00128 00129 00130 00131 SUMOVTypeParameter* 00132 RONet::getVehicleTypeSecure(const std::string& id) throw() { 00133 // check whether the type was already known 00134 SUMOVTypeParameter* type = myVehicleTypes.get(id); 00135 if (type!=0) { 00136 return type; 00137 } 00138 if (id=="") { 00139 // ok, no vehicle type was given within the user input 00140 // return the default type 00141 return 0; 00142 } 00143 // Assume, the user will define the type somewhere else 00144 // return a type which contains the id only 00145 type = new SUMOVTypeParameter(); 00146 type->id = id; 00147 type->onlyReferenced = true; 00148 addVehicleType(type); 00149 return type; 00150 } 00151 00152 00153 bool 00154 RONet::addVehicleType(SUMOVTypeParameter* type) throw() { 00155 if (!myVehicleTypes.add(type->id, type)) { 00156 WRITE_ERROR("The vehicle type '" + type->id + "' occurs at least twice."); 00157 delete type; 00158 return false; 00159 } 00160 return true; 00161 } 00162 00163 00164 bool 00165 RONet::addVehicle(const std::string& id, ROVehicle* veh) throw() { 00166 if (myVehIDs.find(id)==myVehIDs.end()&&myVehicles.add(id, veh)) { 00167 myVehIDs.insert(id); 00168 myReadRouteNo++; 00169 return true; 00170 } 00171 WRITE_ERROR("The vehicle '" + id + "' occurs at least twice."); 00172 return false; 00173 } 00174 00175 00176 bool 00177 RONet::computeRoute(OptionsCont& options, SUMOAbstractRouter<ROEdge,ROVehicle> &router, 00178 const ROVehicle* const veh) { 00179 MsgHandler* mh = MsgHandler::getErrorInstance(); 00180 std::string noRouteMsg = "The vehicle '" + veh->getID() + "' has no valid route."; 00181 if (options.getBool("ignore-errors")) { 00182 mh = MsgHandler::getWarningInstance(); 00183 } 00184 RORouteDef* const routeDef = veh->getRouteDefinition(); 00185 // check if the route definition is valid 00186 if (routeDef==0) { 00187 mh->inform(noRouteMsg); 00188 return false; 00189 } 00190 // check whether the route was already saved 00191 if (routeDef->isSaved()) { 00192 return true; 00193 } 00194 // 00195 RORoute* current = routeDef->buildCurrentRoute(router, veh->getDepartureTime(), *veh); 00196 if (current==0||current->size()==0) { 00197 delete current; 00198 mh->inform(noRouteMsg); 00199 return false; 00200 } 00201 // check whether we have to evaluate the route for not containing loops 00202 if (options.getBool("remove-loops")) { 00203 current->recheckForLoops(); 00204 } 00205 // check whether the route is still valid 00206 if (current->size()==0) { 00207 delete current; 00208 mh->inform(noRouteMsg + " (after removing loops)"); 00209 return false; 00210 } 00211 // add built route 00212 routeDef->addAlternative(router, veh, current, veh->getDepartureTime()); 00213 return true; 00214 } 00215 00216 00217 SUMOTime 00218 RONet::saveAndRemoveRoutesUntil(OptionsCont& options, SUMOAbstractRouter<ROEdge,ROVehicle> &router, 00219 SUMOTime time) { 00220 SUMOTime lastTime = -1; 00221 // write all vehicles (and additional structures) 00222 while (myVehicles.size()!=0) { 00223 // get the next vehicle 00224 const ROVehicle* const veh = myVehicles.getTopVehicle(); 00225 SUMOTime currentTime = veh->getDepartureTime(); 00226 // check whether it shall not yet be computed 00227 if (currentTime>time) { 00228 lastTime = currentTime; 00229 break; 00230 } 00231 // check whether to print the output 00232 if (lastTime!=currentTime&&lastTime!=-1) { 00233 // report writing progress 00234 if (options.getInt("stats-period")>=0 && ((int) currentTime%options.getInt("stats-period"))==0) { 00235 WRITE_MESSAGE("Read: " + toString(myReadRouteNo) + ", Discarded: " + toString(myDiscardedRouteNo) + ", Written: " + toString(myWrittenRouteNo)); 00236 } 00237 } 00238 lastTime = currentTime; 00239 00240 // ok, compute the route (try it) 00241 if (computeRoute(options, router, veh)) { 00242 // write the route 00243 veh->saveAllAsXML(router, *myRoutesOutput, myRouteAlternativesOutput, options.getBool("exit-times")); 00244 myWrittenRouteNo++; 00245 // remove the route if it is not longer used 00246 /* 00247 if (!myRoutes.erase(route->getID())) { 00248 WRITE_WARNING("Could not remove " + route->getID()); 00249 } 00250 */ 00251 } else { 00252 myDiscardedRouteNo++; 00253 } 00254 // and the vehicle 00255 myVehicles.erase(veh->getID()); 00256 } 00257 return lastTime; 00258 } 00259 00260 00261 bool 00262 RONet::furtherStored() { 00263 return myVehicles.size()>0; 00264 } 00265 00266 00267 ROEdge* 00268 RONet::getRandomSource() throw() { 00269 // check whether an edge may be returned 00270 checkSourceAndDestinations(); 00271 if (mySourceEdges.size()==0) { 00272 return 0; 00273 } 00274 // choose a random edge 00275 return RandHelper::getRandomFrom(mySourceEdges); 00276 } 00277 00278 00279 const ROEdge* 00280 RONet::getRandomSource() const throw() { 00281 // check whether an edge may be returned 00282 checkSourceAndDestinations(); 00283 if (mySourceEdges.size()==0) { 00284 return 0; 00285 } 00286 // choose a random edge 00287 return RandHelper::getRandomFrom(mySourceEdges); 00288 } 00289 00290 00291 00292 ROEdge* 00293 RONet::getRandomDestination() throw() { 00294 // check whether an edge may be returned 00295 checkSourceAndDestinations(); 00296 if (myDestinationEdges.size()==0) { 00297 return 0; 00298 } 00299 // choose a random edge 00300 return RandHelper::getRandomFrom(myDestinationEdges); 00301 } 00302 00303 00304 const ROEdge* 00305 RONet::getRandomDestination() const throw() { 00306 // check whether an edge may be returned 00307 checkSourceAndDestinations(); 00308 if (myDestinationEdges.size()==0) { 00309 return 0; 00310 } 00311 // choose a random edge 00312 return RandHelper::getRandomFrom(myDestinationEdges); 00313 } 00314 00315 00316 void 00317 RONet::checkSourceAndDestinations() const { 00318 if (myDestinationEdges.size()!=0||mySourceEdges.size()!=0) { 00319 return; 00320 } 00321 const std::map<std::string, ROEdge*> &edges = myEdges.getMyMap(); 00322 for (std::map<std::string, ROEdge*>::const_iterator i=edges.begin(); i!=edges.end(); ++i) { 00323 ROEdge* e = (*i).second; 00324 ROEdge::EdgeType type = e->getType(); 00325 // !!! add something like "classified edges only" for using only sources or sinks 00326 if (type!=ROEdge::ET_SOURCE) { 00327 myDestinationEdges.push_back(e); 00328 } 00329 if (type!=ROEdge::ET_SINK) { 00330 mySourceEdges.push_back(e); 00331 } 00332 } 00333 } 00334 00335 00336 unsigned int 00337 RONet::getEdgeNo() const { 00338 return (unsigned int) myEdges.size(); 00339 } 00340 00341 00342 const std::map<std::string, ROEdge*> & 00343 RONet::getEdgeMap() const { 00344 return myEdges.getMyMap(); 00345 } 00346 00347 00348 bool 00349 RONet::hasRestrictions() const { 00350 return myHaveRestrictions; 00351 } 00352 00353 00354 void 00355 RONet::setRestrictionFound() { 00356 myHaveRestrictions = true; 00357 } 00358 00359 00360 00361 /****************************************************************************/ 00362