00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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 #endif
00050
00051 #ifdef CHECK_MEMORY_LEAKS
00052 #include <foreign/nvwa/debug_new.h>
00053 #endif // CHECK_MEMORY_LEAKS
00054
00055
00056
00057
00058
00059
00060
00061
00062 MSTriggeredRerouter::Setter::Setter(MSTriggeredRerouter * const parent,
00063 MSLane * const lane) throw()
00064 : MSMoveReminder(lane), myParent(parent) {}
00065
00066
00067 MSTriggeredRerouter::Setter::~Setter() throw() {}
00068
00069
00070 bool
00071 MSTriggeredRerouter::Setter::isStillActive(MSVehicle& veh, SUMOReal ,
00072 SUMOReal , SUMOReal ) throw() {
00073 myParent->reroute(veh, myLane->getEdge());
00074 return false;
00075 }
00076
00077
00078 bool
00079 MSTriggeredRerouter::Setter::notifyEnter(MSVehicle& veh, bool, bool) throw() {
00080 myParent->reroute(veh, myLane->getEdge());
00081 return false;
00082 }
00083
00084
00085
00086
00087
00088 MSTriggeredRerouter::MSTriggeredRerouter(const std::string &id,
00089 const std::vector<MSEdge*> &edges,
00090 SUMOReal prob, const std::string &file, bool off)
00091 : MSTrigger(id), SUMOSAXHandler(file),
00092 myProbability(prob), myUserProbability(prob), myAmInUserMode(false) {
00093
00094 if (!XMLSubSys::runParser(*this, file)) {
00095 throw ProcessError();
00096 }
00097
00098 #ifdef HAVE_MESOSIM
00099 if (MSGlobals::gUseMesoSim) {
00100 for (std::vector<MSEdge*>::const_iterator j=edges.begin(); j!=edges.end(); ++j) {
00101 MESegment *s = MSGlobals::gMesoNet->getSegmentForEdge(**j);
00102 s->addRerouter(this);
00103 }
00104 } else {
00105 #endif
00106 for (std::vector<MSEdge*>::const_iterator j=edges.begin(); j!=edges.end(); ++j) {
00107 const std::vector<MSLane*> &destLanes = (*j)->getLanes();
00108 for (std::vector<MSLane*>::const_iterator i=destLanes.begin(); i!=destLanes.end(); ++i) {
00109 mySetter.push_back(new Setter(this, (*i)));
00110 }
00111 }
00112 #ifdef HAVE_MESOSIM
00113 }
00114 #endif
00115 if (off) {
00116 setUserMode(true);
00117 setUserUsageProbability(0);
00118 }
00119 }
00120
00121
00122 MSTriggeredRerouter::~MSTriggeredRerouter() throw() {
00123 {
00124 std::vector<Setter*>::iterator i;
00125 for (i=mySetter.begin(); i!=mySetter.end(); ++i) {
00126 delete *i;
00127 }
00128 }
00129 }
00130
00131
00132 void
00133 MSTriggeredRerouter::myStartElement(SumoXMLTag element,
00134 const SUMOSAXAttributes &attrs) throw(ProcessError) {
00135 if (element==SUMO_TAG_INTERVAL) {
00136 bool ok = true;
00137 myCurrentIntervalBegin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, "interval", 0, ok, -1);
00138 myCurrentIntervalEnd = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, "interval", 0, ok, -1);
00139 }
00140
00141 if (element==SUMO_TAG_DEST_PROB_REROUTE) {
00142
00143
00144 std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
00145 if (dest=="") {
00146 throw ProcessError("MSTriggeredRerouter " + getID() + ": No destination edge id given.");
00147 }
00148 MSEdge *to = MSEdge::dictionary(dest);
00149 if (to==0) {
00150 throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
00151 }
00152
00153 bool ok = true;
00154 SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, "rerouter/dest_prob_reroute", getID().c_str(), ok, 1.);
00155 if (!ok) {
00156 throw ProcessError();
00157 }
00158 if (prob<0) {
00159 throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
00160 }
00161
00162 myCurrentEdgeProb.add(prob, to);
00163 }
00164
00165 if (element==SUMO_TAG_CLOSING_REROUTE) {
00166
00167 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
00168 if (closed_id=="") {
00169 throw ProcessError("MSTriggeredRerouter " + getID() + ": closed edge id given.");
00170 }
00171 MSEdge *closed = MSEdge::dictionary(closed_id);
00172 if (closed==0) {
00173 throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
00174 }
00175 myCurrentClosed.push_back(closed);
00176 }
00177
00178 if (element==SUMO_TAG_ROUTE_PROB_REROUTE) {
00179
00180
00181 std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
00182 if (routeStr=="") {
00183 throw ProcessError("MSTriggeredRerouter " + getID() + ": No route id given.");
00184 }
00185 const MSRoute* route = MSRoute::dictionary(routeStr);
00186 if (route == 0) {
00187 throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
00188 }
00189
00190
00191 bool ok = true;
00192 SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, "rerouter/dest_prob_reroute", getID().c_str(), ok, 1.);
00193 if (!ok) {
00194 throw ProcessError();
00195 }
00196 if (prob<0) {
00197 throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
00198 }
00199
00200 myCurrentRouteProb.add(prob, route);
00201 }
00202 }
00203
00204
00205 void
00206 MSTriggeredRerouter::myEndElement(SumoXMLTag element) throw(ProcessError) {
00207 if (element==SUMO_TAG_INTERVAL) {
00208 RerouteInterval ri;
00209 ri.begin = myCurrentIntervalBegin;
00210 ri.end = myCurrentIntervalEnd;
00211 ri.closed = myCurrentClosed;
00212 ri.edgeProbs = myCurrentEdgeProb;
00213 ri.routeProbs = myCurrentRouteProb;
00214 myCurrentClosed.clear();
00215 myCurrentEdgeProb.clear();
00216 myCurrentRouteProb.clear();
00217 myIntervals.push_back(ri);
00218 }
00219 }
00220
00221
00222
00223
00224
00225 bool
00226 MSTriggeredRerouter::hasCurrentReroute(SUMOTime time, SUMOVehicle &veh) const {
00227 std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00228 const MSRoute &route = veh.getRoute();
00229 while (i!=myIntervals.end()) {
00230 if ((*i).begin<=time && (*i).end>=time) {
00231 if ((*i).edgeProbs.getOverallProb()!=0||(*i).routeProbs.getOverallProb()!=0||route.containsAnyOf((*i).closed)) {
00232 return true;
00233 }
00234 }
00235 i++;
00236 }
00237 return false;
00238 }
00239
00240
00241 bool
00242 MSTriggeredRerouter::hasCurrentReroute(SUMOTime time) const {
00243 std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00244 while (i!=myIntervals.end()) {
00245 if ((*i).begin<=time && (*i).end>=time) {
00246 if ((*i).edgeProbs.getOverallProb()!=0||(*i).routeProbs.getOverallProb()!=0||(*i).closed.size()!=0) {
00247 return true;
00248 }
00249 }
00250 i++;
00251 }
00252 return false;
00253 }
00254
00255
00256 const MSTriggeredRerouter::RerouteInterval &
00257 MSTriggeredRerouter::getCurrentReroute(SUMOTime time, SUMOVehicle &veh) const {
00258 std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00259 const MSRoute &route = veh.getRoute();
00260 while (i!=myIntervals.end()) {
00261 if ((*i).begin<=time && (*i).end>=time) {
00262 if ((*i).edgeProbs.getOverallProb()!=0||(*i).routeProbs.getOverallProb()!=0||route.containsAnyOf((*i).closed)) {
00263 return *i;
00264 }
00265 }
00266 i++;
00267 }
00268 throw 1;
00269 }
00270
00271
00272 const MSTriggeredRerouter::RerouteInterval &
00273 MSTriggeredRerouter::getCurrentReroute(SUMOTime) const {
00274 std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
00275 while (i!=myIntervals.end()) {
00276 if ((*i).edgeProbs.getOverallProb()!=0||(*i).routeProbs.getOverallProb()!=0||(*i).closed.size()!=0) {
00277 return *i;
00278 }
00279 i++;
00280 }
00281 throw 1;
00282 }
00283
00284
00285
00286 void
00287 MSTriggeredRerouter::reroute(SUMOVehicle &veh, const MSEdge &src) {
00288
00289 SUMOTime time = MSNet::getInstance()->getCurrentTimeStep();
00290 if (!hasCurrentReroute(time, veh)) {
00291 return;
00292 }
00293
00294 SUMOReal prob = myAmInUserMode ? myUserProbability : myProbability;
00295 if (RandHelper::rand() > prob) {
00296 return;
00297 }
00298
00299
00300 const MSRoute &route = veh.getRoute();
00301 const MSEdge *lastEdge = route.getLastEdge();
00302
00303 const MSTriggeredRerouter::RerouteInterval &rerouteDef = getCurrentReroute(time, veh);
00304 const MSRoute *newRoute = rerouteDef.routeProbs.getOverallProb()>0 ? rerouteDef.routeProbs.get() : 0;
00305
00306 if (newRoute!=0) {
00307 veh.replaceRoute(newRoute->getEdges(), time);
00308 return;
00309 }
00310
00311 const MSEdge *newEdge = rerouteDef.edgeProbs.getOverallProb()>0 ? rerouteDef.edgeProbs.get() : route.getLastEdge();
00312 if (newEdge==0) {
00313 newEdge = lastEdge;
00314 }
00315
00316
00317 MSEdgeWeightsStorage empty;
00318 MSNet::EdgeWeightsProxi proxi(empty, MSNet::getInstance()->getWeightsStorage());
00319 DijkstraRouterTT_ByProxi<MSEdge, SUMOVehicle, prohibited_withRestrictions<MSEdge, SUMOVehicle>, MSNet::EdgeWeightsProxi> router(MSEdge::dictSize(), true, &proxi, &MSNet::EdgeWeightsProxi::getTravelTime);
00320 router.prohibit(rerouteDef.closed);
00321 std::vector<const MSEdge*> edges;
00322 router.compute(&src, newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
00323 veh.replaceRoute(edges, MSNet::getInstance()->getCurrentTimeStep());
00324 }
00325
00326
00327 void
00328 MSTriggeredRerouter::setUserMode(bool val) {
00329 myAmInUserMode = val;
00330 }
00331
00332
00333 void
00334 MSTriggeredRerouter::setUserUsageProbability(SUMOReal prob) {
00335 myUserProbability = prob;
00336 }
00337
00338
00339 bool
00340 MSTriggeredRerouter::inUserMode() const {
00341 return myAmInUserMode;
00342 }
00343
00344
00345 SUMOReal
00346 MSTriggeredRerouter::getProbability() const {
00347 return myAmInUserMode ? myUserProbability : myProbability;
00348 }
00349
00350
00351 SUMOReal
00352 MSTriggeredRerouter::getUserProbability() const {
00353 return myUserProbability;
00354 }
00355
00356
00357
00358
00359