00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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 <utils/options/OptionsCont.h>
00033 #include <utils/common/WrappingCommand.h>
00034 #include <utils/common/StaticCommand.h>
00035 #include <utils/common/DijkstraRouterTT.h>
00036
00037 #ifdef CHECK_MEMORY_LEAKS
00038 #include <foreign/nvwa/debug_new.h>
00039 #endif // CHECK_MEMORY_LEAKS
00040
00041
00042
00043
00044
00045 int MSDevice_Routing::myVehicleIndex = 0;
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
00052
00053
00054
00055
00056
00057
00058
00059 void
00060 MSDevice_Routing::insertOptions() throw() {
00061 OptionsCont &oc = OptionsCont::getOptions();
00062 oc.addOptionSubTopic("Routing");
00063
00064 oc.doRegister("device.routing.probability", new Option_Float(0.));
00065 oc.addDescription("device.routing.probability", "Routing", "The probability for a vehicle to have a routing device");
00066
00067 oc.doRegister("device.routing.knownveh", new Option_String());
00068 oc.addDescription("device.routing.knownveh", "Routing", "Assign a device to named vehicles");
00069
00070 oc.doRegister("device.routing.deterministic", new Option_Bool(false));
00071 oc.addDescription("device.routing.deterministic", "Routing", "The devices are set deterministic using a fraction of 1000");
00072
00073 oc.doRegister("device.routing.period", new Option_String("0"));
00074 oc.addDescription("device.routing.period", "Routing", "The period with which the vehicle shall be rerouted");
00075
00076 oc.doRegister("device.routing.pre-period", new Option_String("0"));
00077 oc.addDescription("device.routing.pre-period", "Routing", "The rerouting period before emit");
00078
00079 oc.doRegister("device.routing.adaptation-weight", new Option_Float(.5));
00080 oc.addDescription("device.routing.adaptation-weight", "Routing", "The weight of prior edge weights.");
00081
00082 oc.doRegister("device.routing.adaptation-interval", new Option_String("1"));
00083 oc.addDescription("device.routing.adaptation-interval", "Routing", "The interval for updating the edge weights.");
00084
00085 oc.doRegister("device.routing.with-taz", new Option_Bool(false));
00086 oc.addDescription("device.routing.with-taz", "Routing", "Use zones (districts) as routing end points");
00087
00088 myVehicleIndex = 0;
00089 myEdgeWeightSettingCommand = 0;
00090 myEdgeEfforts.clear();
00091 }
00092
00093
00094 void
00095 MSDevice_Routing::buildVehicleDevices(MSVehicle &v, std::vector<MSDevice*> &into) throw() {
00096 OptionsCont &oc = OptionsCont::getOptions();
00097 if (oc.getFloat("device.routing.probability")==0&&!oc.isSet("device.routing.knownveh")) {
00098
00099 return;
00100 }
00101
00102 bool haveByNumber = false;
00103 if (oc.getBool("device.routing.deterministic")) {
00104 haveByNumber = ((myVehicleIndex%1000) < (int)(oc.getFloat("device.routing.probability")*1000.));
00105 } else {
00106 haveByNumber = RandHelper::rand()<=oc.getFloat("device.routing.probability");
00107 }
00108 bool haveByName = oc.isSet("device.routing.knownveh") && OptionsCont::getOptions().isInStringVector("device.routing.knownveh", v.getID());
00109 if (haveByNumber||haveByName) {
00110
00111 MSDevice_Routing* device = new MSDevice_Routing(v, "routing_" + v.getID(),
00112 string2time(oc.getString("device.routing.period")),
00113 string2time(oc.getString("device.routing.pre-period")));
00114 into.push_back(device);
00115
00116 if (myEdgeEfforts.size()==0) {
00117 const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges();
00118 for (std::vector<MSEdge*>::const_iterator i=edges.begin(); i!=edges.end(); ++i) {
00119 myEdgeEfforts[*i] = (*i)->getCurrentTravelTime();
00120 }
00121 }
00122
00123 if (myEdgeWeightSettingCommand==0) {
00124 myEdgeWeightSettingCommand = new StaticCommand< MSDevice_Routing >(&MSDevice_Routing::adaptEdgeEfforts);
00125 MSNet::getInstance()->getEndOfTimestepEvents().addEvent(
00126 myEdgeWeightSettingCommand, 0, MSEventControl::ADAPT_AFTER_EXECUTION);
00127 myAdaptationWeight = oc.getFloat("device.routing.adaptation-weight");
00128 myAdaptationInterval = string2time(oc.getString("device.routing.adaptation-interval"));
00129 }
00130 myWithTaz = oc.getBool("device.routing.with-taz");
00131 if (myWithTaz) {
00132 if (MSEdge::dictionary(v.getParameter().fromTaz+"-source") == 0) {
00133 WRITE_ERROR("Source district '" + v.getParameter().fromTaz + "' not known when rerouting '" + v.getID() + "'!");
00134 return;
00135 }
00136 if (MSEdge::dictionary(v.getParameter().toTaz) == 0) {
00137 WRITE_ERROR("Destination district '" + v.getParameter().toTaz + "' not known when rerouting '" + v.getID() + "'!");
00138 return;
00139 }
00140 }
00141 }
00142 myVehicleIndex++;
00143 }
00144
00145
00146
00147
00148
00149 MSDevice_Routing::MSDevice_Routing(MSVehicle &holder, const std::string &id,
00150 SUMOTime period, SUMOTime preEmitPeriod) throw()
00151 : MSDevice(holder, id), myPeriod(period), myPreEmitPeriod(period),
00152 myLastPreEmitReroute(-1), myRerouteCommand(0) {
00153 }
00154
00155
00156 MSDevice_Routing::~MSDevice_Routing() throw() {
00157
00158 if (myRerouteCommand!=0) {
00159 myRerouteCommand->deschedule();
00160 }
00161 }
00162
00163
00164 void
00165 MSDevice_Routing::onTryEmit() {
00166 if (myWithTaz) {
00167 const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
00168 if (myLastPreEmitReroute == -1 ||
00169 (myPreEmitPeriod > 0 && myLastPreEmitReroute + myPreEmitPeriod <= now)) {
00170 DijkstraRouterTT_ByProxi<MSEdge, SUMOVehicle, prohibited_withRestrictions<MSEdge, SUMOVehicle>, MSDevice_Routing>
00171 router(MSEdge::dictSize(), true, this, &MSDevice_Routing::getEffort);
00172 myHolder.reroute(MSNet::getInstance()->getCurrentTimeStep(), router, true);
00173 myLastPreEmitReroute = now;
00174 }
00175 }
00176 }
00177
00178
00179 void
00180 MSDevice_Routing::enterLaneAtEmit(MSLane*, const MSVehicle::State &) {
00181 if (myLastPreEmitReroute == -1) {
00182 DijkstraRouterTT_ByProxi<MSEdge, SUMOVehicle, prohibited_withRestrictions<MSEdge, SUMOVehicle>, MSDevice_Routing>
00183 router(MSEdge::dictSize(), true, this, &MSDevice_Routing::getEffort);
00184 myHolder.reroute(MSNet::getInstance()->getCurrentTimeStep(), router);
00185 }
00186
00187 if (myPeriod>0&&myRerouteCommand==0) {
00188 myRerouteCommand = new WrappingCommand< MSDevice_Routing >(this, &MSDevice_Routing::wrappedRerouteCommandExecute);
00189 MSNet::getInstance()->getBeginOfTimestepEvents().addEvent(
00190 myRerouteCommand, myPeriod+MSNet::getInstance()->getCurrentTimeStep(),
00191 MSEventControl::ADAPT_AFTER_EXECUTION);
00192 }
00193 }
00194
00195
00196 SUMOTime
00197 MSDevice_Routing::wrappedRerouteCommandExecute(SUMOTime currentTime) throw(ProcessError) {
00198 DijkstraRouterTT_ByProxi<MSEdge, SUMOVehicle, prohibited_withRestrictions<MSEdge, SUMOVehicle>, MSDevice_Routing>
00199 router(MSEdge::dictSize(), true, this, &MSDevice_Routing::getEffort);
00200 myHolder.reroute(currentTime, router);
00201 return myPeriod;
00202 }
00203
00204
00205 SUMOReal
00206 MSDevice_Routing::getEffort(const MSEdge * const e, const SUMOVehicle * const v, SUMOReal) const {
00207 if (myEdgeEfforts.find(e) != myEdgeEfforts.end()) {
00208 return MAX2(myEdgeEfforts.find(e)->second, e->getLanes()[0]->getLength()/v->getMaxSpeed());
00209 }
00210 return 0;
00211 }
00212
00213
00214 SUMOTime
00215 MSDevice_Routing::adaptEdgeEfforts(SUMOTime currentTime) throw(ProcessError) {
00216 SUMOReal newWeight = (SUMOReal)(1. - myAdaptationWeight);
00217 const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges();
00218 for (std::vector<MSEdge*>::const_iterator i=edges.begin(); i!=edges.end(); ++i) {
00219 myEdgeEfforts[*i] = myEdgeEfforts[*i] * myAdaptationWeight + (*i)->getCurrentTravelTime() * newWeight;
00220 }
00221 return myAdaptationInterval;
00222 }
00223
00224
00225
00226
00227