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