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