|
SUMO - Simulation of Urban MObility
|
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