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