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