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