SUMO - Simulation of Urban MObility
MSTriggeredRerouter.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00009 // Reroutes vehicles passing an edge
00010 /****************************************************************************/
00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00013 /****************************************************************************/
00014 //
00015 //   This file is part of SUMO.
00016 //   SUMO is free software: you can redistribute it and/or modify
00017 //   it under the terms of the GNU General Public License as published by
00018 //   the Free Software Foundation, either version 3 of the License, or
00019 //   (at your option) any later version.
00020 //
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 <string>
00034 #include <algorithm>
00035 #include <utils/common/MsgHandler.h>
00036 #include <utils/common/Command.h>
00037 #include <utils/xml/SUMOXMLDefinitions.h>
00038 #include <utils/common/UtilExceptions.h>
00039 #include <utils/common/ToString.h>
00040 #include <utils/xml/XMLSubSys.h>
00041 #include <utils/common/TplConvert.h>
00042 #include <utils/xml/SUMOSAXHandler.h>
00043 #include <utils/common/DijkstraRouterTT.h>
00044 #include <utils/common/RandHelper.h>
00045 #include <microsim/MSEdgeWeightsStorage.h>
00046 #include <microsim/MSLane.h>
00047 #include <microsim/MSVehicle.h>
00048 #include <microsim/MSRoute.h>
00049 #include <microsim/MSEdge.h>
00050 #include <microsim/MSNet.h>
00051 #include <microsim/MSGlobals.h>
00052 #include "MSTriggeredRerouter.h"
00053 
00054 #ifdef HAVE_MESOSIM
00055 #include <mesosim/MELoop.h>
00056 #include <mesosim/MESegment.h>
00057 #endif
00058 
00059 #ifdef CHECK_MEMORY_LEAKS
00060 #include <foreign/nvwa/debug_new.h>
00061 #endif // CHECK_MEMORY_LEAKS
00062 
00063 
00064 // ===========================================================================
00065 // method definitions
00066 // ===========================================================================
00067 bool MSTriggeredRerouter::myHaveWarnedAboutDeprecatedDestProbReroute = false;
00068 bool MSTriggeredRerouter::myHaveWarnedAboutDeprecatedClosingReroute = false;
00069 bool MSTriggeredRerouter::myHaveWarnedAboutDeprecatedRouteReroute = false;
00070 
00071 
00072 // ===========================================================================
00073 // method definitions
00074 // ===========================================================================
00075 MSTriggeredRerouter::MSTriggeredRerouter(const std::string& id,
00076         const std::vector<MSEdge*> &edges,
00077         SUMOReal prob, const std::string& file, bool off)
00078     : MSTrigger(id), MSMoveReminder(), SUMOSAXHandler(file),
00079       myProbability(prob), myUserProbability(prob), myAmInUserMode(false) {
00080     // read in the trigger description
00081     if (file != "" && !XMLSubSys::runParser(*this, file)) {
00082         throw ProcessError();
00083     }
00084     // build actors
00085     for (std::vector<MSEdge*>::const_iterator j = edges.begin(); j != edges.end(); ++j) {
00086 #ifdef HAVE_MESOSIM
00087         if (MSGlobals::gUseMesoSim) {
00088             MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**j);
00089             s->addDetector(this);
00090             continue;
00091         }
00092 #endif
00093         const std::vector<MSLane*> &destLanes = (*j)->getLanes();
00094         for (std::vector<MSLane*>::const_iterator i = destLanes.begin(); i != destLanes.end(); ++i) {
00095             (*i)->addMoveReminder(this);
00096         }
00097     }
00098     if (off) {
00099         setUserMode(true);
00100         setUserUsageProbability(0);
00101     }
00102 }
00103 
00104 
00105 MSTriggeredRerouter::~MSTriggeredRerouter() {
00106 }
00107 
00108 // ------------ loading begin
00109 void
00110 MSTriggeredRerouter::myStartElement(int element,
00111                                     const SUMOSAXAttributes& attrs) {
00112     if (element == SUMO_TAG_INTERVAL) {
00113         bool ok = true;
00114         myCurrentIntervalBegin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, 0, ok, -1);
00115         myCurrentIntervalEnd = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, 0, ok, -1);
00116     }
00117 
00118     if (element == SUMO_TAG_DEST_PROB_REROUTE__DEPRECATED && !myHaveWarnedAboutDeprecatedDestProbReroute) {
00119         myHaveWarnedAboutDeprecatedDestProbReroute = true;
00120         WRITE_WARNING("'" + toString(SUMO_TAG_DEST_PROB_REROUTE__DEPRECATED) + "' is deprecated; please use '" + toString(SUMO_TAG_DEST_PROB_REROUTE) + "'.");
00121     }
00122     if (element == SUMO_TAG_DEST_PROB_REROUTE || element == SUMO_TAG_DEST_PROB_REROUTE__DEPRECATED) {
00123         // by giving probabilities of new destinations
00124         // get the destination edge
00125         std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
00126         if (dest == "") {
00127             throw ProcessError("MSTriggeredRerouter " + getID() + ": No destination edge id given.");
00128         }
00129         MSEdge* to = MSEdge::dictionary(dest);
00130         if (to == 0) {
00131             throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
00132         }
00133         // get the probability to reroute
00134         bool ok = true;
00135         SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
00136         if (!ok) {
00137             throw ProcessError();
00138         }
00139         if (prob < 0) {
00140             throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
00141         }
00142         // add
00143         myCurrentEdgeProb.add(prob, to);
00144     }
00145 
00146     if (element == SUMO_TAG_CLOSING_REROUTE__DEPRECATED && !myHaveWarnedAboutDeprecatedClosingReroute) {
00147         myHaveWarnedAboutDeprecatedClosingReroute = true;
00148         WRITE_WARNING("'" + toString(SUMO_TAG_CLOSING_REROUTE__DEPRECATED) + "' is deprecated; please use '" + toString(SUMO_TAG_CLOSING_REROUTE) + "'.");
00149     }
00150     if (element == SUMO_TAG_CLOSING_REROUTE || element == SUMO_TAG_CLOSING_REROUTE) {
00151         // by closing
00152         std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
00153         if (closed_id == "") {
00154             throw ProcessError("MSTriggeredRerouter " + getID() + ": closed edge id given.");
00155         }
00156         MSEdge* closed = MSEdge::dictionary(closed_id);
00157         if (closed == 0) {
00158             throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
00159         }
00160         myCurrentClosed.push_back(closed);
00161     }
00162 
00163     if (element == SUMO_TAG_ROUTE_PROB_REROUTE__DEPRECATED && !myHaveWarnedAboutDeprecatedRouteReroute) {
00164         myHaveWarnedAboutDeprecatedRouteReroute = true;
00165         WRITE_WARNING("'" + toString(SUMO_TAG_ROUTE_PROB_REROUTE__DEPRECATED) + "' is deprecated; please use '" + toString(SUMO_TAG_ROUTE_PROB_REROUTE) + "'.");
00166     }
00167     if (element == SUMO_TAG_ROUTE_PROB_REROUTE || element == SUMO_TAG_ROUTE_PROB_REROUTE__DEPRECATED) {
00168         // by explicit rerouting using routes
00169         // check if route exists
00170         std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
00171         if (routeStr == "") {
00172             throw ProcessError("MSTriggeredRerouter " + getID() + ": No route id given.");
00173         }
00174         const MSRoute* route = MSRoute::dictionary(routeStr);
00175         if (route == 0) {
00176             throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
00177         }
00178 
00179         // get the probability to reroute
00180         bool ok = true;
00181         SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
00182         if (!ok) {
00183             throw ProcessError();
00184         }
00185         if (prob < 0) {
00186             throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
00187         }
00188         // add
00189         myCurrentRouteProb.add(prob, route);
00190     }
00191 }
00192 
00193 
00194 void
00195 MSTriggeredRerouter::myEndElement(int element) {
00196     if (element == SUMO_TAG_INTERVAL) {
00197         RerouteInterval ri;
00198         ri.begin = myCurrentIntervalBegin;
00199         ri.end = myCurrentIntervalEnd;
00200         ri.closed = myCurrentClosed;
00201         ri.edgeProbs = myCurrentEdgeProb;
00202         ri.routeProbs = myCurrentRouteProb;
00203         myCurrentClosed.clear();
00204         myCurrentEdgeProb.clear();
00205         myCurrentRouteProb.clear();
00206         myIntervals.push_back(ri);
00207     }
00208 }
00209 
00210 
00211 // ------------ loading end
00212 
00213 
00214 bool
00215 MSTriggeredRerouter::hasCurrentReroute(SUMOTime time, SUMOVehicle& veh) const {
00216     std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00217     const MSRoute& route = veh.getRoute();
00218     while (i != myIntervals.end()) {
00219         if ((*i).begin <= time && (*i).end >= time) {
00220             if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || route.containsAnyOf((*i).closed)) {
00221                 return true;
00222             }
00223         }
00224         i++;
00225     }
00226     return false;
00227 }
00228 
00229 
00230 bool
00231 MSTriggeredRerouter::hasCurrentReroute(SUMOTime time) const {
00232     std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00233     while (i != myIntervals.end()) {
00234         if ((*i).begin <= time && (*i).end >= time) {
00235             if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || (*i).closed.size() != 0) {
00236                 return true;
00237             }
00238         }
00239         i++;
00240     }
00241     return false;
00242 }
00243 
00244 
00245 const MSTriggeredRerouter::RerouteInterval&
00246 MSTriggeredRerouter::getCurrentReroute(SUMOTime time, SUMOVehicle& veh) const {
00247     std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00248     const MSRoute& route = veh.getRoute();
00249     while (i != myIntervals.end()) {
00250         if ((*i).begin <= time && (*i).end >= time) {
00251             if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || route.containsAnyOf((*i).closed)) {
00252                 return *i;
00253             }
00254         }
00255         i++;
00256     }
00257     throw 1;
00258 }
00259 
00260 
00261 const MSTriggeredRerouter::RerouteInterval&
00262 MSTriggeredRerouter::getCurrentReroute(SUMOTime) const {
00263     std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00264     while (i != myIntervals.end()) {
00265         if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || (*i).closed.size() != 0) {
00266             return *i;
00267         }
00268         i++;
00269     }
00270     throw 1;
00271 }
00272 
00273 
00274 
00275 bool
00276 MSTriggeredRerouter::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification reason) {
00277     if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
00278         return false;
00279     }
00280     // check whether the vehicle shall be rerouted
00281     SUMOTime time = MSNet::getInstance()->getCurrentTimeStep();
00282     if (!hasCurrentReroute(time, veh)) {
00283         return false;
00284     }
00285 
00286     SUMOReal prob = myAmInUserMode ? myUserProbability : myProbability;
00287     if (RandHelper::rand() > prob) {
00288         return false;
00289     }
00290 
00291     // get vehicle params
00292     const MSRoute& route = veh.getRoute();
00293     const MSEdge* lastEdge = route.getLastEdge();
00294     // get rerouting params
00295     const MSTriggeredRerouter::RerouteInterval& rerouteDef = getCurrentReroute(time, veh);
00296     const MSRoute* newRoute = rerouteDef.routeProbs.getOverallProb() > 0 ? rerouteDef.routeProbs.get() : 0;
00297     // we will use the route if given rather than calling our own dijsktra...
00298     if (newRoute != 0) {
00299         veh.replaceRoute(newRoute);
00300         return false;
00301     }
00302     // ok, try using a new destination
00303     const MSEdge* newEdge = rerouteDef.edgeProbs.getOverallProb() > 0 ? rerouteDef.edgeProbs.get() : route.getLastEdge();
00304     if (newEdge == 0) {
00305         newEdge = lastEdge;
00306     }
00307 
00308     // we have a new destination, let's replace the vehicle route
00309     MSEdgeWeightsStorage empty;
00310     MSNet::EdgeWeightsProxi proxi(empty, MSNet::getInstance()->getWeightsStorage());
00311     DijkstraRouterTT_ByProxi<MSEdge, SUMOVehicle, prohibited_withRestrictions<MSEdge, SUMOVehicle>, MSNet::EdgeWeightsProxi> router(MSEdge::dictSize(), true, &proxi, &MSNet::EdgeWeightsProxi::getTravelTime);
00312     router.prohibit(rerouteDef.closed);
00313     std::vector<const MSEdge*> edges;
00314     router.compute(veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
00315     veh.replaceRouteEdges(edges);
00316     return false;
00317 }
00318 
00319 
00320 void
00321 MSTriggeredRerouter::setUserMode(bool val) {
00322     myAmInUserMode = val;
00323 }
00324 
00325 
00326 void
00327 MSTriggeredRerouter::setUserUsageProbability(SUMOReal prob) {
00328     myUserProbability = prob;
00329 }
00330 
00331 
00332 bool
00333 MSTriggeredRerouter::inUserMode() const {
00334     return myAmInUserMode;
00335 }
00336 
00337 
00338 SUMOReal
00339 MSTriggeredRerouter::getProbability() const {
00340     return myAmInUserMode ? myUserProbability : myProbability;
00341 }
00342 
00343 
00344 SUMOReal
00345 MSTriggeredRerouter::getUserProbability() const {
00346     return myUserProbability;
00347 }
00348 
00349 
00350 
00351 /****************************************************************************/
00352 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines