SUMO - Simulation of Urban MObility

MSDevice_Routing.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00010 // A device that performs vehicle rerouting based on current edge speeds
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 // included modules
00026 // ===========================================================================
00027 #ifdef _MSC_VER
00028 #include <windows_config.h>
00029 #else
00030 #include <config.h>
00031 #endif
00032 
00033 #include "MSDevice_Routing.h"
00034 #include <microsim/MSNet.h>
00035 #include <microsim/MSLane.h>
00036 #include <microsim/MSEdgeControl.h>
00037 #include <utils/options/OptionsCont.h>
00038 #include <utils/common/WrappingCommand.h>
00039 #include <utils/common/StaticCommand.h>
00040 #include <utils/common/DijkstraRouterTT.h>
00041 
00042 #ifdef CHECK_MEMORY_LEAKS
00043 #include <foreign/nvwa/debug_new.h>
00044 #endif // CHECK_MEMORY_LEAKS
00045 
00046 
00047 // ===========================================================================
00048 // static member variables
00049 // ===========================================================================
00050 std::map<const MSEdge*, SUMOReal> MSDevice_Routing::myEdgeEfforts;
00051 Command* MSDevice_Routing::myEdgeWeightSettingCommand = 0;
00052 SUMOReal MSDevice_Routing::myAdaptationWeight;
00053 SUMOTime MSDevice_Routing::myAdaptationInterval;
00054 bool MSDevice_Routing::myWithTaz;
00055 std::map<std::pair<const MSEdge*, const MSEdge*>, const MSRoute*> MSDevice_Routing::myCachedRoutes;
00056 
00057 
00058 // ===========================================================================
00059 // method definitions
00060 // ===========================================================================
00061 // ---------------------------------------------------------------------------
00062 // static initialisation methods
00063 // ---------------------------------------------------------------------------
00064 void
00065 MSDevice_Routing::insertOptions() {
00066     OptionsCont& oc = OptionsCont::getOptions();
00067     oc.addOptionSubTopic("Routing");
00068 
00069     oc.doRegister("device.rerouting.probability", new Option_Float(0.));
00070     oc.addSynonyme("device.rerouting.probability", "device.routing.probability", true);
00071     oc.addDescription("device.rerouting.probability", "Routing", "The probability for a vehicle to have a routing device");
00072 
00073     oc.doRegister("device.rerouting.explicit", new Option_String());
00074     oc.addSynonyme("device.rerouting.explicit", "device.routing.knownveh", true);
00075     oc.addDescription("device.rerouting.explicit", "Routing", "Assign a device to named vehicles");
00076 
00077     oc.doRegister("device.rerouting.deterministic", new Option_Bool(false));
00078     oc.addSynonyme("device.rerouting.deterministic", "device.routing.deterministic", true);
00079     oc.addDescription("device.rerouting.deterministic", "Routing", "The devices are set deterministic using a fraction of 1000");
00080 
00081     oc.doRegister("device.rerouting.period", new Option_String("0", "TIME"));
00082     oc.addSynonyme("device.rerouting.period", "device.routing.period", true);
00083     oc.addDescription("device.rerouting.period", "Routing", "The period with which the vehicle shall be rerouted");
00084 
00085     oc.doRegister("device.rerouting.pre-period", new Option_String("0", "TIME"));
00086     oc.addSynonyme("device.rerouting.pre-period", "device.routing.pre-period", true);
00087     oc.addDescription("device.rerouting.pre-period", "Routing", "The rerouting period before depart");
00088 
00089     oc.doRegister("device.rerouting.adaptation-weight", new Option_Float(.5));
00090     oc.addSynonyme("device.rerouting.adaptation-weight", "device.routing.adaptation-weight", true);
00091     oc.addDescription("device.rerouting.adaptation-weight", "Routing", "The weight of prior edge weights.");
00092 
00093     oc.doRegister("device.rerouting.adaptation-interval", new Option_String("1", "TIME"));
00094     oc.addSynonyme("device.rerouting.adaptation-interval", "device.routing.adaptation-interval", true);
00095     oc.addDescription("device.rerouting.adaptation-interval", "Routing", "The interval for updating the edge weights.");
00096 
00097     oc.doRegister("device.rerouting.with-taz", new Option_Bool(false));
00098     oc.addSynonyme("device.rerouting.with-taz", "device.routing.with-taz", true);
00099     oc.addDescription("device.rerouting.with-taz", "Routing", "Use zones (districts) as routing end points");
00100 
00101     myEdgeWeightSettingCommand = 0;
00102     myEdgeEfforts.clear();
00103 }
00104 
00105 
00106 void
00107 MSDevice_Routing::buildVehicleDevices(SUMOVehicle& v, std::vector<MSDevice*> &into) {
00108     OptionsCont& oc = OptionsCont::getOptions();
00109     bool needRerouting = v.getParameter().wasSet(VEHPARS_FORCE_REROUTE);
00110     if (!needRerouting && oc.getFloat("device.rerouting.probability") == 0 && !oc.isSet("device.rerouting.explicit")) {
00111         // no route computation is modelled
00112         return;
00113     }
00114     // route computation is enabled
00115     bool haveByNumber = false;
00116     if (oc.getBool("device.rerouting.deterministic")) {
00117         haveByNumber = MSNet::getInstance()->getVehicleControl().isInQuota(oc.getFloat("device.rerouting.probability"));
00118     } else {
00119         haveByNumber = RandHelper::rand() <= oc.getFloat("device.rerouting.probability");
00120     }
00121     bool haveByName = oc.isSet("device.rerouting.explicit") && OptionsCont::getOptions().isInStringVector("device.rerouting.explicit", v.getID());
00122     myWithTaz = oc.getBool("device.rerouting.with-taz");
00123     if (needRerouting || haveByNumber || haveByName) {
00124         // build the device
00125         MSDevice_Routing* device = new MSDevice_Routing(v, "routing_" + v.getID(),
00126                 string2time(oc.getString("device.rerouting.period")),
00127                 string2time(oc.getString("device.rerouting.pre-period")));
00128         into.push_back(device);
00129         // initialise edge efforts if not done before
00130         if (myEdgeEfforts.size() == 0) {
00131             const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges();
00132             for (std::vector<MSEdge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
00133                 myEdgeEfforts[*i] = (*i)->getCurrentTravelTime();
00134             }
00135         }
00136         // make the weights be updated
00137         if (myEdgeWeightSettingCommand == 0) {
00138             myEdgeWeightSettingCommand = new StaticCommand< MSDevice_Routing >(&MSDevice_Routing::adaptEdgeEfforts);
00139             MSNet::getInstance()->getEndOfTimestepEvents().addEvent(
00140                 myEdgeWeightSettingCommand, 0, MSEventControl::ADAPT_AFTER_EXECUTION);
00141             myAdaptationWeight = oc.getFloat("device.rerouting.adaptation-weight");
00142             myAdaptationInterval = string2time(oc.getString("device.rerouting.adaptation-interval"));
00143         }
00144         if (myWithTaz) {
00145             if (MSEdge::dictionary(v.getParameter().fromTaz + "-source") == 0) {
00146                 WRITE_ERROR("Source district '" + v.getParameter().fromTaz + "' not known when rerouting '" + v.getID() + "'!");
00147                 return;
00148             }
00149             if (MSEdge::dictionary(v.getParameter().toTaz + "-sink") == 0) {
00150                 WRITE_ERROR("Destination district '" + v.getParameter().toTaz + "' not known when rerouting '" + v.getID() + "'!");
00151                 return;
00152             }
00153         }
00154     }
00155 }
00156 
00157 
00158 // ---------------------------------------------------------------------------
00159 // MSDevice_Routing-methods
00160 // ---------------------------------------------------------------------------
00161 MSDevice_Routing::MSDevice_Routing(SUMOVehicle& holder, const std::string& id,
00162                                    SUMOTime period, SUMOTime preInsertionPeriod)
00163     : MSDevice(holder, id), myPeriod(period), myPreInsertionPeriod(preInsertionPeriod), myRerouteCommand(0) {
00164     if (myWithTaz) {
00165         myRerouteCommand = new WrappingCommand< MSDevice_Routing >(this, &MSDevice_Routing::preInsertionReroute);
00166         MSNet::getInstance()->getInsertionEvents().addEvent(
00167             myRerouteCommand, holder.getParameter().depart,
00168             MSEventControl::ADAPT_AFTER_EXECUTION);
00169     }
00170 }
00171 
00172 
00173 MSDevice_Routing::~MSDevice_Routing() {
00174     // make the rerouting command invalid if there is one
00175     if (myRerouteCommand != 0) {
00176         myRerouteCommand->deschedule();
00177     }
00178 }
00179 
00180 
00181 bool
00182 MSDevice_Routing::notifyEnter(SUMOVehicle& /*veh*/, MSMoveReminder::Notification reason) {
00183     if (reason == MSMoveReminder::NOTIFICATION_DEPARTED) {
00184         if (myRerouteCommand != 0) { // clean up pre depart rerouting
00185             if (myPreInsertionPeriod > 0) {
00186                 myRerouteCommand->deschedule();
00187             }
00188             myRerouteCommand = 0;
00189         }
00190         if (!myWithTaz) {
00191             wrappedRerouteCommandExecute(MSNet::getInstance()->getCurrentTimeStep());
00192         }
00193         // build repetition trigger if routing shall be done more often
00194         if (myPeriod > 0) {
00195             myRerouteCommand = new WrappingCommand< MSDevice_Routing >(this, &MSDevice_Routing::wrappedRerouteCommandExecute);
00196             MSNet::getInstance()->getBeginOfTimestepEvents().addEvent(
00197                 myRerouteCommand, myPeriod + MSNet::getInstance()->getCurrentTimeStep(),
00198                 MSEventControl::ADAPT_AFTER_EXECUTION);
00199         }
00200     }
00201     return false;
00202 }
00203 
00204 
00205 SUMOTime
00206 MSDevice_Routing::preInsertionReroute(SUMOTime currentTime) {
00207     const MSEdge* source = MSEdge::dictionary(myHolder.getParameter().fromTaz + "-source");
00208     const MSEdge* dest = MSEdge::dictionary(myHolder.getParameter().toTaz + "-sink");
00209     if (source && dest) {
00210         const std::pair<const MSEdge*, const MSEdge*> key = std::make_pair(source, dest);
00211         if (myCachedRoutes.find(key) == myCachedRoutes.end()) {
00212             DijkstraRouterTT_ByProxi<MSEdge, SUMOVehicle, prohibited_withRestrictions<MSEdge, SUMOVehicle>, MSDevice_Routing>
00213             router(MSEdge::dictSize(), true, this, &MSDevice_Routing::getEffort);
00214             myHolder.reroute(currentTime, router, true);
00215             myCachedRoutes[key] = &myHolder.getRoute();
00216             myHolder.getRoute().addReference();
00217         } else {
00218             myHolder.replaceRoute(myCachedRoutes[key], true);
00219         }
00220     }
00221     return myPreInsertionPeriod;
00222 }
00223 
00224 
00225 SUMOTime
00226 MSDevice_Routing::wrappedRerouteCommandExecute(SUMOTime currentTime) {
00227     DijkstraRouterTT_ByProxi<MSEdge, SUMOVehicle, prohibited_withRestrictions<MSEdge, SUMOVehicle>, MSDevice_Routing>
00228     router(MSEdge::dictSize(), true, this, &MSDevice_Routing::getEffort);
00229     myHolder.reroute(currentTime, router);
00230     return myPeriod;
00231 }
00232 
00233 
00234 SUMOReal
00235 MSDevice_Routing::getEffort(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal) const {
00236     if (myEdgeEfforts.find(e) != myEdgeEfforts.end()) {
00237         return MAX2(myEdgeEfforts.find(e)->second, e->getLanes()[0]->getLength() / v->getMaxSpeed());
00238     }
00239     return 0;
00240 }
00241 
00242 
00243 SUMOTime
00244 MSDevice_Routing::adaptEdgeEfforts(SUMOTime /*currentTime*/) {
00245     std::map<std::pair<const MSEdge*, const MSEdge*>, const MSRoute*>::iterator it = myCachedRoutes.begin();
00246     for (; it != myCachedRoutes.end(); ++it) {
00247         it->second->release();
00248     }
00249     myCachedRoutes.clear();
00250     SUMOReal newWeight = (SUMOReal)(1. - myAdaptationWeight);
00251     const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges();
00252     for (std::vector<MSEdge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
00253         myEdgeEfforts[*i] = myEdgeEfforts[*i] * myAdaptationWeight + (*i)->getCurrentTravelTime() * newWeight;
00254     }
00255     return myAdaptationInterval;
00256 }
00257 
00258 
00259 
00260 /****************************************************************************/
00261 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines