SUMO - Simulation of Urban MObility

MSDevice_Routing.cpp

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