SUMO - Simulation of Urban MObility
RONet.cpp
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines