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