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/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