MSEmitter.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // A vehicle emitting device
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright 2001-2010 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 <utils/common/MsgHandler.h>
00032 #include <utils/common/Command.h>
00033 #include <utils/common/WrappingCommand.h>
00034 #include <microsim/MSLane.h>
00035 #include <utils/xml/SUMOXMLDefinitions.h>
00036 #include <utils/common/UtilExceptions.h>
00037 #include <utils/common/ToString.h>
00038 #include <microsim/MSEventControl.h>
00039 #include "MSEmitter.h"
00040 #include <microsim/MSGlobals.h>
00041 
00042 #ifdef CHECK_MEMORY_LEAKS
00043 #include <foreign/nvwa/debug_new.h>
00044 #endif // CHECK_MEMORY_LEAKS
00045 
00046 
00047 
00048 /* -------------------------------------------------------------------------
00049  * MSTriggeredReader::UserCommand-methods
00050  * ----------------------------------------------------------------------- */
00051 MSEmitter::MSEmitter_FileTriggeredChild::MSEmitter_FileTriggeredChild(
00052     MSNet &net, const std::string &aXMLFilename,
00053     MSEmitter &parent, MSVehicleControl &vc) throw()
00054         : MSTriggeredXMLReader(net, aXMLFilename), MSEmitterChild(parent, vc),
00055         myHaveNext(false), myFlow(-1), myHaveInitialisedFlow(false), myRunningID(0) {
00056     myBeginTime = net.getCurrentTimeStep();
00057 }
00058 
00059 
00060 MSEmitter::MSEmitter_FileTriggeredChild::~MSEmitter_FileTriggeredChild() throw() {}
00061 
00062 
00063 SUMOTime
00064 MSEmitter::MSEmitter_FileTriggeredChild::execute(SUMOTime) throw(ProcessError) {
00065     if (myParent.childCheckEmit(this)) {
00066         buildAndScheduleFlowVehicle();
00067         return (SUMOTime) computeOffset(myFlow);
00068     }
00069     return 1;
00070 }
00071 
00072 
00073 bool
00074 MSEmitter::MSEmitter_FileTriggeredChild::processNextEntryReaderTriggered() {
00075     if (myFlow>=0) {
00076         return true;
00077     }
00078     if (!myHaveNext) {
00079         return true;
00080     }
00081     if (myParent.childCheckEmit(this)) {
00082         myHaveNext = false;
00083         return true;
00084     }
00085     return false;
00086 }
00087 
00088 
00089 void
00090 MSEmitter::MSEmitter_FileTriggeredChild::buildAndScheduleFlowVehicle() {
00091     SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00092     pars->id = myParent.getID() + "_" + toString(myRunningID++);
00093     pars->depart = myOffset+1;
00094     pars->repetitionNumber = -1;
00095     pars->repetitionOffset = -1;
00096     MSVehicleType* aVehType = myVTypeDist.getOverallProb()>0
00097                               ? myVTypeDist.get()
00098                               : MSNet::getInstance()->getVehicleControl().getVType();
00099     if (aVehType==0) {
00100         WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.");
00101         WRITE_WARNING("Continuing with next element.");
00102         return;// false;
00103     }
00104     // check and assign vehicle type
00105     const MSRoute *aEmitRoute = myRouteDist.get();
00106     if (aEmitRoute==0) {
00107         WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00108         WRITE_WARNING("Continuing with next element.");
00109         return;// false;
00110     }
00111 
00112     MSVehicle *veh =
00113         MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00114     myParent.schedule(this, veh, -1);
00115     myHaveNext = true;
00116 }
00117 
00118 
00119 void
00120 MSEmitter::MSEmitter_FileTriggeredChild::myStartElement(SumoXMLTag element,
00121         const SUMOSAXAttributes &attrs) throw(ProcessError) {
00122     if (element==SUMO_TAG_ROUTEDISTELEM) {
00123         // check probability
00124         bool ok = true;
00125         SUMOReal prob = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "emitter/routedistelem", myParent.getID().c_str(), ok);
00126         std::string routeStr = attrs.getStringReporting(SUMO_ATTR_ID, "emitter/routedistelem", myParent.getID().c_str(), ok);
00127         if (ok) {
00128             const MSRoute* route = MSRoute::dictionary(routeStr);
00129             if (route == 0) {
00130                 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Route '" + routeStr + "' does not exist.");
00131             }
00132             if (prob<0) {
00133                 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
00134             }
00135             // atributes ok, add to routeDist
00136             myRouteDist.add(prob, route);
00137             return;
00138         }
00139         throw ProcessError();
00140     }
00141 
00142     if (element==SUMO_TAG_VTYPEDISTELEM) {
00143         bool ok = true;
00144         SUMOReal prob = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "emitter/vtypedistelem", myParent.getID().c_str(), ok);
00145         std::string vtypeStr = attrs.getStringReporting(SUMO_ATTR_ID, "emitter/vtypedistelem", myParent.getID().c_str(), ok);
00146         if (ok) {
00147             MSVehicleType *vtype = MSNet::getInstance()->getVehicleControl().getVType(vtypeStr);
00148             if (vtype==0) {
00149                 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Vehicle type '" + vtypeStr + "' does not exist.");
00150             }
00151             if (prob<0) {
00152                 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Attribute 'probability' for vtype '" + vtypeStr + "' is negative (must not).");
00153             }
00154             myVTypeDist.add(prob, vtype);
00155             return;
00156         }
00157         throw ProcessError();
00158     }
00159 
00160     if (element==SUMO_TAG_FLOW) {
00161         bool ok = true;
00162         SUMOReal no = attrs.getSUMORealReporting(SUMO_ATTR_NO, "emitter/flow", myParent.getID().c_str(), ok);
00163         if (no<0) {
00164             throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Negative flow in emitter '" + myParent.getID() + "'.");
00165         }
00166         SUMOTime end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, "emitter/flow", myParent.getID().c_str(), ok, -1);
00167         if (!ok) {
00168             return;
00169         }
00170         myFlow = (SUMOReal) no;
00171         if (end==-1||end>=MSNet::getInstance()->getCurrentTimeStep()) {
00172             if (myFlow>0) {
00173                 buildAndScheduleFlowVehicle();
00174                 MSNet::getInstance()->getEmissionEvents().addEvent(
00175                     new WrappingCommand<MSEmitter::MSEmitter_FileTriggeredChild>(this, &MSEmitter::MSEmitter_FileTriggeredChild::execute),
00176                     (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00177                     MSEventControl::ADAPT_AFTER_EXECUTION);
00178                 myHaveInitialisedFlow = true;
00179             }
00180         }
00181     }
00182 
00183     // check whethe the correct tag is read
00184     if (element==SUMO_TAG_EMIT) {
00185         bool ok = true;
00186         SUMOTime depart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_TIME, "emit", myParent.getID().c_str(), ok, -1);
00187         SUMOReal departSpeed = attrs.getOptSUMORealReporting(SUMO_ATTR_SPEED, "emit", myParent.getID().c_str(), ok, -1);
00188         std::string id = attrs.getOptStringReporting(SUMO_ATTR_ID, "emit", myParent.getID().c_str(), ok, "");
00189         std::string type = attrs.getOptStringReporting(SUMO_ATTR_TYPE, "emit", myParent.getID().c_str(), ok, "");
00190         std::string route = attrs.getOptStringReporting(SUMO_ATTR_ROUTE, "emit", myParent.getID().c_str(), ok, "");
00191         if (!ok) {
00192             return;
00193         }
00194         if (depart<myBeginTime) {
00195             // do not process the vehicle if the emission time is before the simulation begin
00196             return;
00197         }
00198         SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00199         pars->repetitionNumber = -1;
00200         pars->repetitionOffset = -1;
00201         pars->depart = depart;
00202         pars->departSpeed = departSpeed;
00203         // check and assign id
00204         pars->id = id;
00205         if (myVehicleControl.getVehicle(pars->id)!=0) {
00206             WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Generating a default id.");
00207             pars->id = "";
00208         }
00209         if (pars->id=="") {
00210             pars->id = myParent.getID() +  "_" + time2string(pars->depart) +  "_" + toString(myRunningID++);
00211             if (myVehicleControl.getVehicle(pars->id)!=0) {
00212                 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Continuing with next element.");
00213                 delete pars;
00214                 return;
00215             }
00216         }
00217         // check and assign vehicle type
00218         pars->vtypeid = type;
00219         MSVehicleType* aVehType = MSNet::getInstance()->getVehicleControl().getVType(pars->vtypeid);
00220         if (aVehType == 0) {
00221             if (myVTypeDist.getOverallProb()!=0) {
00222                 aVehType = myVTypeDist.get();
00223             }
00224             if (aVehType==0) {
00225                 aVehType = MSNet::getInstance()->getVehicleControl().getVType();
00226                 if (aVehType==0) {
00227                     WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.\n Continuing with next element.");
00228                     delete pars;
00229                     return;
00230                 }
00231             }
00232         }
00233         // check and assign vehicle type
00234         pars->routeid = route;
00235         const MSRoute *aEmitRoute = MSRoute::dictionary(pars->routeid);
00236         if (aEmitRoute==0) {
00237             if (myRouteDist.getOverallProb()!=0) {
00238                 aEmitRoute = myRouteDist.get();
00239             }
00240             if (aEmitRoute==0) {
00241                 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00242                 WRITE_WARNING("Continuing with next element.");
00243                 delete pars;
00244                 return;
00245             }
00246         }
00247         // build vehicle
00248         MSVehicle *veh = MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00249         myParent.schedule(this, veh, pars->departSpeed);
00250         myHaveNext = true;
00251         myOffset = SUMOTime(pars->depart);
00252     }
00253     // check whethe the correct tag is read
00254     if (element==SUMO_TAG_RESET) {
00255         myVTypeDist.clear();
00256         myRouteDist.clear();
00257     }
00258 }
00259 
00260 
00261 bool
00262 MSEmitter::MSEmitter_FileTriggeredChild::nextRead() {
00263     return myHaveNext;
00264 }
00265 
00266 
00267 SUMOReal
00268 MSEmitter::MSEmitter_FileTriggeredChild::getLoadedFlow() const {
00269     return myFlow;
00270 }
00271 
00272 
00273 void
00274 MSEmitter::MSEmitter_FileTriggeredChild::inputEndReached() {
00275     if (myFlow>0&&!myHaveInitialisedFlow) {
00276         buildAndScheduleFlowVehicle();
00277         MSNet::getInstance()->getEmissionEvents().addEvent(
00278             new WrappingCommand<MSEmitter::MSEmitter_FileTriggeredChild>(this, &MSEmitter::MSEmitter_FileTriggeredChild::execute),
00279             (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00280             MSEventControl::ADAPT_AFTER_EXECUTION);
00281         myHaveInitialisedFlow = true;
00282     }
00283 }
00284 
00285 
00286 // ===========================================================================
00287 // method definitions
00288 // ===========================================================================
00289 MSEmitter::MSEmitter(const std::string &id,
00290                      MSNet &net,
00291                      MSLane* destLane, SUMOReal pos,
00292                      const std::string &aXMLFilename) throw()
00293         : MSTrigger(id), myNet(net),
00294         myDestLane(destLane), myPos((SUMOReal) pos) {
00295     assert(myPos>=0);
00296     myActiveChild =
00297         new MSEmitter_FileTriggeredChild(net, aXMLFilename, *this, net.getVehicleControl());
00298     myFileBasedEmitter = myActiveChild;
00299 }
00300 
00301 
00302 MSEmitter::~MSEmitter() throw() {
00303     delete myFileBasedEmitter;
00304     std::map<MSEmitterChild*, std::pair<MSVehicle*, SUMOReal> >::iterator i;
00305     for (i=myToEmit.begin(); i!=myToEmit.end(); ++i) {
00306         delete(*i).second.first;
00307     }
00308 }
00309 
00310 
00311 bool
00312 MSEmitter::childCheckEmit(MSEmitterChild *child) {
00313     if (myToEmit.find(child)==myToEmit.end()) {
00314         // should not happen - a child is calling and should have a vehicle added
00315         throw 1;
00316     }
00317     if (child!=myActiveChild||myDestLane->getEdge().isVaporizing()) {
00318         // check whether this is due to vaporization
00319         if (myDestLane->getEdge().isVaporizing()) {
00320             myToEmit[child].first->setWasVaporized(true);
00321         }
00322         // remove the vehicle previously inserted by the child
00323         delete myToEmit[child].first;
00324         // erase the child information
00325         myToEmit.erase(myToEmit.find(child));
00326         // inform child to process the next one (the current was not used)
00327         return true;
00328     }
00329     // get the vehicle and the speed the child has read/generated
00330     MSVehicle *veh = myToEmit[child].first;
00331     if (veh->getDesiredDepart()>MSNet::getInstance()->getCurrentTimeStep()) {
00332         return false;
00333     }
00334     SUMOReal speed = myToEmit[child].second;
00335     // !!! add warning if speed to high or negative
00336     // check whether the speed shall be patched
00337     SUMOReal pos = myPos;
00338     if (speed<0) {
00339         speed = MIN2(myDestLane->getMaxSpeed(), veh->getMaxSpeed());
00340     } else {
00341         speed = MIN3(myDestLane->getMaxSpeed(), veh->getMaxSpeed(), speed);
00342     }
00343     // try to emit
00344 #ifdef HAVE_MESOSIM
00345     if (MSGlobals::gUseMesoSim) {
00346         if (myDestLane->getEdge().emit(*veh,  myNet.getCurrentTimeStep())) {
00347             veh->onDepart();
00348             // insert vehicle into the dictionary
00349             if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00350                 // !!!
00351                 throw 1;
00352             }
00353             // erase the child information
00354             myToEmit.erase(myToEmit.find(child));
00355             return true;
00356         }
00357     } else {
00358 #endif
00359         if (myDestLane->isEmissionSuccess(veh, speed, pos, true)) {
00360             veh->onDepart();
00361             // insert vehicle into the dictionary
00362             if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00363                 // !!!
00364                 throw 1;
00365             }
00366             // erase the child information
00367             myToEmit.erase(myToEmit.find(child));
00368             return true;
00369         }
00370 #ifdef HAVE_MESOSIM
00371     }
00372 #endif
00373     return false;
00374 }
00375 
00376 
00377 void
00378 MSEmitter::schedule(MSEmitterChild *child,
00379                     MSVehicle *v, SUMOReal speed) {
00380     v->onTryEmit();
00381     myToEmit[child] = std::make_pair(v, speed);
00382 }
00383 
00384 
00385 size_t
00386 MSEmitter::getActiveChildIndex() const {
00387     return
00388         myFileBasedEmitter==myActiveChild ? 0 : 1;
00389 }
00390 
00391 
00392 void
00393 MSEmitter::setActiveChild(MSEmitterChild *c) {
00394     myActiveChild = c;
00395 }
00396 
00397 
00398 /****************************************************************************/
00399 

Generated on Wed May 5 00:06:31 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6