MSCalibrator.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 
00031 #include <string>
00032 #include <utils/common/MsgHandler.h>
00033 #include <utils/common/Command.h>
00034 #include <utils/common/WrappingCommand.h>
00035 #include <microsim/MSLane.h>
00036 #include <utils/xml/SUMOXMLDefinitions.h>
00037 #include <utils/common/UtilExceptions.h>
00038 #include <utils/common/ToString.h>
00039 #include <microsim/MSEventControl.h>
00040 #include "MSCalibrator.h"
00041 #include <microsim/MSGlobals.h>
00042 
00043 //TM
00044 #include <netload/NLDetectorBuilder.h>
00045 #include <microsim/output/MSInductLoop.h>
00046 #include <utils/iodevices/OutputDevice.h>
00047 
00048 #ifdef CHECK_MEMORY_LEAKS
00049 #include <foreign/nvwa/debug_new.h>
00050 #endif // CHECK_MEMORY_LEAKS
00051 
00052 
00053 
00054 /* -------------------------------------------------------------------------
00055  * MSTriggeredReader::UserCommand-methods
00056  * ----------------------------------------------------------------------- */
00057 MSCalibrator::MSCalibrator_FileTriggeredChild::MSCalibrator_FileTriggeredChild(
00058     MSNet &net, const std::string &aXMLFilename,
00059     MSCalibrator &parent, MSVehicleControl &vc) throw()
00060         : MSTriggeredXMLReader(net, aXMLFilename), MSCalibratorChild(parent, vc),
00061         myHaveNext(false), myFlow(-1), myHaveInitialisedFlow(false), myRunningID(0) {
00062     myBeginTime = net.getCurrentTimeStep();
00063 }
00064 
00065 
00066 MSCalibrator::MSCalibrator_FileTriggeredChild::~MSCalibrator_FileTriggeredChild() throw() {}
00067 
00068 
00069 SUMOTime
00070 MSCalibrator::MSCalibrator_FileTriggeredChild::execute(SUMOTime) throw(ProcessError) {
00071     if (myParent.childCheckEmit(this)) {
00072         buildAndScheduleFlowVehicle();
00073         return (SUMOTime) computeOffset(myFlow);
00074     }
00075     return 1;
00076 }
00077 
00078 
00079 
00080 SUMOTime
00081 MSCalibrator::execute(SUMOTime timestep) throw(ProcessError) {
00082 
00083     if (timestep == 0) {
00084         return 1;
00085     }
00086 
00087     if (myNumVehicles == -1) {
00088         return 1;
00089     }
00090 
00091 
00092 
00093     SUMOReal vehPerInterval = myNumVehicles / (myInterval);
00094     int num_replacements = 0;
00095     /*
00096         OutputDevice *dev = OutputDevice::getOutputDevice(myDebugFilesBaseName + "diff.csv");
00097         OutputDevice *dev2 = OutputDevice::getOutputDevice(myDebugFilesBaseName + "replace.csv");
00098         OutputDevice *dev3 = OutputDevice::getOutputDevice(myDebugFilesBaseName + "vehicle.xml");
00099     */
00100 
00101     //positive diff=too many vehicles, negative diff=not enough vehicles
00102     unsigned veh_cnt = myIL->getNVehContributed();
00103     SUMOReal diff =  veh_cnt - vehPerInterval + myToCalibrate;
00104     SUMOReal meanSpeed = myIL->getCurrentSpeed();
00105 
00106     if (diff > 0) {
00107 
00108         unsigned int vehNum = myDestLane->getVehicleNumber();
00109 
00110         //not enough vehicles to delete on the lane?
00111         if (vehNum < diff) {
00112 
00113             myToCalibrate = diff - vehNum;
00114 
00115             diff = (SUMOReal)vehNum;
00116         } else {
00117             myToCalibrate = diff - floor(diff);
00118         }
00119 
00120         for (int i=1; i <= diff; i++) {
00121 
00122             for (MSLane::VehCont::const_iterator it = myDestLane->getVehiclesSecure().begin();
00123                     it < myDestLane->getVehiclesSecure().end();
00124                     it++) {
00125 
00126                 MSVehicle * veh = (*it);
00127 
00128                 if (veh->getVehicleType().getID() == "BUS") {
00129                     continue;
00130                 } else {
00131                     veh->onRemovalFromNet(false);
00132                     myDestLane->removeVehicle(veh);
00133                     MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
00134                     num_replacements++;
00135                     break;
00136                 }
00137             }
00138 //          WRITE_WARNING("Removing Vehicle " + veh->getID() + " at Timestep: " + toString(timestep) + "\n");
00139         }
00140 
00141         //make sure enough cars were deleted, only happens if BUSSES were in the set
00142         myToCalibrate+diff-num_replacements;
00143     } else if (diff < 0) {
00144 
00145         myToCalibrate = diff - ceil(diff);
00146         for (int i=-1; i >= diff; i--) {
00147 //          WRITE_WARNING("Inserting Vehicle at Timestep: " + toString(timestep) + "\n");
00148 
00149             ((MSCalibrator_FileTriggeredChild*) myFileBasedCalibrator)->buildAndScheduleFlowVehicle(meanSpeed);
00150             childCheckEmit(myFileBasedCalibrator);
00151             num_replacements--;
00152         }
00153     } else if (diff == 0) {
00154         myToCalibrate = 0;
00155     }
00156     /*
00157         if (myDebugLevel > 0) {
00158             dev->getOStream() << timestep << "\t" << num_replacements << "\t" << diff << "\t" << myToCalibrate << "\t" << veh_cnt << "\t" << meanSpeed << endl;
00159 
00160             dev2->getOStream() << num_replacements << endl;
00161 
00162             myIL->writeXMLOutput(*dev3, timestep-1, timestep);
00163         }
00164 
00165     //  WRITE_WARNING("execute2(" + toString(timestep) + "): Count: " + toString(myIL->getNVehContributed(myInterval)));
00166      */
00167 
00168     return 1;
00169 }
00171 
00172 bool
00173 MSCalibrator::MSCalibrator_FileTriggeredChild::processNextEntryReaderTriggered() {
00174     if (myFlow>=0) {
00175         return true;
00176     }
00177     if (!myHaveNext) {
00178         return true;
00179     }
00180     if (myParent.childCheckEmit(this)) {
00181         myHaveNext = false;
00182         return true;
00183     }
00184     return false;
00185 }
00186 
00187 
00188 void
00189 MSCalibrator::MSCalibrator_FileTriggeredChild::buildAndScheduleFlowVehicle(SUMOReal speed) {
00190     SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00191     pars->id = myParent.getID() + "_" + toString(myRunningID++);
00192     pars->depart = myOffset+1;
00193     pars->repetitionNumber = -1;
00194     pars->repetitionOffset = -1;
00195     MSVehicleType* aVehType = myVTypeDist.getOverallProb()>0
00196                               ? myVTypeDist.get()
00197                               : MSNet::getInstance()->getVehicleControl().getVType();
00198     if (aVehType==0) {
00199         WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.");
00200         WRITE_WARNING("Continuing with next element.");
00201         return;// false;
00202     }
00203     // check and assign vehicle type
00204     const MSRoute *aEmitRoute = myRouteDist.get();
00205     if (aEmitRoute==0) {
00206         WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00207         WRITE_WARNING("Continuing with next element.");
00208         return;// false;
00209     }
00210 
00211     MSVehicle *veh =
00212         MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00213     myParent.schedule(this, veh, speed);
00214     myHaveNext = true;
00215 }
00216 
00217 
00218 void
00219 MSCalibrator::MSCalibrator_FileTriggeredChild::myStartElement(SumoXMLTag element,
00220         const SUMOSAXAttributes &attrs) throw(ProcessError) {
00221     if (element==SUMO_TAG_ROUTEDISTELEM) {
00222         bool ok = true;
00223         SUMOReal freq = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "calibrator/routedistelem", myParent.getID().c_str(), ok);
00224         std::string routeStr = attrs.getStringReporting(SUMO_ATTR_ID, "calibrator/routedistelem", myParent.getID().c_str(), ok);
00225         if (ok) {
00226             const MSRoute* route = MSRoute::dictionary(routeStr);
00227             if (route == 0) {
00228                 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Route '" + routeStr + "' does not exist.");
00229             }
00230             if (freq<0) {
00231                 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Attribute \"probability\" is negative (must not).");
00232             }
00233             // Attributes ok, add to routeDist
00234             myRouteDist.add(freq, route);
00235         }
00236         return;
00237     }
00238     // vehicle-type distributions
00239     if (element==SUMO_TAG_VTYPEDISTELEM) {
00240         // get the id, report an error if not given or empty...
00241         std::string id;
00242         if (!attrs.setIDFromAttributes("vtypedistelem", id)) {
00243             return;
00244         }
00245         bool ok = true;
00246         SUMOReal prob = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "vtypedistelem", id.c_str(), ok);
00247         if (ok) {
00248             if (prob<=0) {
00249                 MsgHandler::getErrorInstance()->inform("False probability while parsing calibrator '" + myParent.getID() + "' (" + toString(prob) + ").");
00250                 return;
00251             }
00252             MSVehicleType *vtype = MSNet::getInstance()->getVehicleControl().getVType(id);
00253             if (vtype==0) {
00254                 MsgHandler::getErrorInstance()->inform("Unknown vtype-object '" + id + "'.");
00255                 return;
00256             }
00257             myVTypeDist.add(prob, vtype);
00258         }
00259     }
00260 
00261     if (element==SUMO_TAG_FLOW) {
00262         bool ok = true;
00263         SUMOReal no = attrs.getSUMORealReporting(SUMO_ATTR_NO, "flow", myParent.getID().c_str(), ok);
00264         if (no<0) {
00265             MsgHandler::getErrorInstance()->inform("Negative flow in calibrator '" + myParent.getID() + "'.");
00266             return;
00267         }
00268         SUMOTime end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, "flow", myParent.getID().c_str(), ok, -1);
00269         if (!ok) {
00270             return;
00271         }
00272         myFlow = (SUMOReal) no;
00273         if (end==-1||end>=MSNet::getInstance()->getCurrentTimeStep()) {
00274             if (myFlow>0) {
00275                 buildAndScheduleFlowVehicle();
00276                 MSNet::getInstance()->getEmissionEvents().addEvent(
00277                     new WrappingCommand<MSCalibrator::MSCalibrator_FileTriggeredChild>(this, &MSCalibrator::MSCalibrator_FileTriggeredChild::execute),
00278                     (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00279                     MSEventControl::ADAPT_AFTER_EXECUTION);
00280                 myHaveInitialisedFlow = true;
00281             }
00282         }
00283     }
00284 
00285     // check whethe the correct tag is read
00286     if (element==SUMO_TAG_EMIT) {
00287         bool ok = true;
00288         SUMOTime depart = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME, "emit", 0, ok);
00289         SUMOReal departSpeed = attrs.getOptSUMORealReporting(SUMO_ATTR_SPEED, "emit", myParent.getID().c_str(), ok, -1);
00290         if (!ok) {
00291             return;
00292         }
00293         if (depart<myBeginTime) {
00294             // do not process the vehicle if the emission time is before the simulation begin
00295             return;
00296         }
00297 
00298         SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00299         pars->repetitionNumber = -1;
00300         pars->repetitionOffset = -1;
00301         pars->depart = depart;
00302         pars->departSpeed = departSpeed;
00303         // check and assign id
00304         pars->id = attrs.getStringSecure(SUMO_ATTR_ID, "");
00305         if (myVehicleControl.getVehicle(pars->id)!=0) {
00306             WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Generating a default id.");
00307             pars->id = "";
00308         }
00309         if (pars->id=="") {
00310             pars->id = myParent.getID() +  "_" + toString(pars->depart) +  "_" + toString(myRunningID++);
00311             if (myVehicleControl.getVehicle(pars->id)!=0) {
00312                 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Continuing with next element.");
00313                 return;
00314             }
00315         }
00316         // check and assign vehicle type
00317         pars->vtypeid = attrs.getStringReporting(SUMO_ATTR_TYPE, "calibrator/routedistelem", myParent.getID().c_str(), ok, "");
00318         MSVehicleType* aVehType = MSNet::getInstance()->getVehicleControl().getVType(pars->vtypeid);
00319         if (aVehType == 0) {
00320             if (myVTypeDist.getOverallProb()!=0) {
00321                 aVehType = myVTypeDist.get();
00322             }
00323             if (aVehType==0) {
00324                 aVehType = MSNet::getInstance()->getVehicleControl().getVType();
00325                 if (aVehType==0) {
00326                     WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.\n Continuing with next element.");
00327                     return;
00328                 }
00329             }
00330         }
00331         // check and assign vehicle type
00332         pars->routeid = attrs.getStringReporting(SUMO_ATTR_ROUTE, "calibrator/routedistelem", myParent.getID().c_str(), ok, "");
00333         const MSRoute *aEmitRoute = MSRoute::dictionary(pars->routeid);
00334         if (aEmitRoute==0) {
00335             if (myRouteDist.getOverallProb()!=0) {
00336                 aEmitRoute = myRouteDist.get();
00337             }
00338             if (aEmitRoute==0) {
00339                 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00340                 WRITE_WARNING("Continuing with next element.");
00341                 return;
00342             }
00343         }
00344         // build vehicle
00345         MSVehicle *veh = MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00346         myParent.schedule(this, veh, pars->departSpeed);
00347         myHaveNext = true;
00348         myOffset = SUMOTime(pars->depart);
00349     }
00350     // check whethe the correct tag is read
00351     if (element==SUMO_TAG_RESET) {
00352         myVTypeDist.clear();
00353         myRouteDist.clear();
00354     }
00355 #if 0
00356 #ifdef TM_CALIB
00357     if (element==SUMO_TAG_CALIB) {
00358 
00359         WRITE_WARNING("FOUND calib Tag!!!");
00360         /*
00361                   MSNet::getInstance()->getEmissionEvents().addEvent(
00362                             new WrappingCommand<MSCalibrator::MSCalibrator_FileTriggeredChild>(this, &MSCalibrator::MSCalibrator_FileTriggeredChild::execute2),
00363                             //MSNet::getInstance()->getCurrentTimeStep() + 5,
00364                             10,
00365                             MSEventControl::ADAPT_AFTER_EXECUTION);
00366         */
00367 
00368     }
00369 #endif //TM_CALIB
00370 #endif //0
00371 }
00372 
00373 
00374 bool
00375 MSCalibrator::MSCalibrator_FileTriggeredChild::nextRead() {
00376     return myHaveNext;
00377 }
00378 
00379 
00380 SUMOReal
00381 MSCalibrator::MSCalibrator_FileTriggeredChild::getLoadedFlow() const {
00382     return myFlow;
00383 }
00384 
00385 
00386 void
00387 MSCalibrator::MSCalibrator_FileTriggeredChild::inputEndReached() {
00388     if (myFlow>0&&!myHaveInitialisedFlow) {
00389         buildAndScheduleFlowVehicle();
00390         MSNet::getInstance()->getEmissionEvents().addEvent(
00391             new WrappingCommand<MSCalibrator::MSCalibrator_FileTriggeredChild>(this, &MSCalibrator::MSCalibrator_FileTriggeredChild::execute),
00392             (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00393             MSEventControl::ADAPT_AFTER_EXECUTION);
00394         myHaveInitialisedFlow = true;
00395     }
00396 }
00397 
00398 
00399 // ===========================================================================
00400 // method definitions
00401 // ===========================================================================
00402 MSCalibrator::MSCalibrator(const std::string &id,
00403                            MSNet &net,
00404                            MSLane* destLane, SUMOReal pos,
00405                            const std::string &aXMLFilename) throw()
00406         : MSTrigger(id), myNet(net),
00407         myDestLane(destLane), myPos((SUMOReal) pos), myDb(net),
00408         myDebugLevel(0), myDebugFilesBaseName("x:\\temp\\dbg_") {
00409     assert(myPos>=0);
00410 
00411     myToCalibrate = 0;
00412 
00413     //myInterval=atof(getenv("TM_INTERV")?getenv("TM_INTERV"):"1"); //1
00414     //myNumVehicles=atof(getenv("TM_NUMVEH")?getenv("TM_NUMVEH"):"0"); //14.0
00415     myInterval = 60;
00416     myNumVehicles= -1;
00417 
00418 
00419 
00420     std::string ilId = "Calib_InductLoopOn_" + myDestLane->getID();
00421     myIL = myDb.createInductLoop(ilId, myDestLane, myPos);
00422 
00423     MSNet::getInstance()->getEmissionEvents().addEvent(
00424         new WrappingCommand<MSCalibrator>(this, &MSCalibrator::execute),
00425         //MSNet::getInstance()->getCurrentTimeStep() + 5,
00426         0,
00427         MSEventControl::ADAPT_AFTER_EXECUTION);
00428 
00429 
00430     //TODO clean up in destructor!!!
00431     MSCalibrator::calibratorMap[id]=this;
00432 
00433     myActiveChild =
00434         new MSCalibrator_FileTriggeredChild(net, aXMLFilename, *this, net.getVehicleControl());
00435     myFileBasedCalibrator = myActiveChild;
00436 }
00437 
00438 
00439 MSCalibrator::~MSCalibrator() throw() {
00440     {
00441         delete myFileBasedCalibrator;
00442     }
00443     {
00444         std::map<MSCalibratorChild*, std::pair<MSVehicle*, SUMOReal> >::iterator i;
00445         for (i=myToEmit.begin(); i!=myToEmit.end(); ++i) {
00446             delete(*i).second.first;
00447         }
00448     }
00449 }
00450 
00451 
00452 bool
00453 MSCalibrator::childCheckEmit(MSCalibratorChild *child) {
00454     if (myToEmit.find(child)==myToEmit.end()) {
00455         // should not happen - a child is calling and should have a vehicle added
00456         throw 1;
00457     }
00458     if (child!=myActiveChild||myDestLane->getEdge().isVaporizing()) {
00459         // check whether this is due to vaporization
00460         if (myDestLane->getEdge().isVaporizing()) {
00461             myToEmit[child].first->setWasVaporized(true);
00462         }
00463         // remove the vehicle previously inserted by the child
00464         delete myToEmit[child].first;
00465         // erase the child information
00466         myToEmit.erase(myToEmit.find(child));
00467         // inform child to process the next one (the current was not used)
00468         return true;
00469     }
00470     // get the vehicle and the speed the child has read/generated
00471     MSVehicle *veh = myToEmit[child].first;
00472     SUMOReal speed = myToEmit[child].second;
00473     // check whether the speed shall be patched
00474     //TM
00475     SUMOReal pos = myPos+1;
00476     if (speed<0) {
00477         speed = MIN2(myDestLane->getMaxSpeed(), veh->getMaxSpeed());
00478     }
00479     // try to emit
00480 #ifdef HAVE_MESOSIM
00481     if (MSGlobals::gUseMesoSim) {
00482         if (myDestLane->getEdge().emit(*veh,  myNet.getCurrentTimeStep())) {
00483             veh->onDepart();
00484             // insert vehicle into the dictionary
00485             if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00486                 // !!!
00487                 throw 1;
00488             }
00489             // erase the child information
00490             myToEmit.erase(myToEmit.find(child));
00491             return true;
00492         }
00493     } else {
00494 #endif
00495         if (myDestLane->isEmissionSuccess(veh, speed, pos, false)) {
00496             veh->onDepart();
00497             // insert vehicle into the dictionary
00498             if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00499                 // !!!
00500                 throw 1;
00501             }
00502             // erase the child information
00503             myToEmit.erase(myToEmit.find(child));
00504             return true;
00505         }
00506 #ifdef HAVE_MESOSIM
00507     }
00508 #endif
00509     return false;
00510 }
00511 
00512 
00513 void
00514 MSCalibrator::schedule(MSCalibratorChild *child,
00515                        MSVehicle *v, SUMOReal speed) {
00516     myToEmit[child] = std::make_pair(v, speed);
00517 }
00518 
00519 
00520 size_t
00521 MSCalibrator::getActiveChildIndex() const {
00522     return
00523         myFileBasedCalibrator==myActiveChild ? 0 : 1;
00524 }
00525 
00526 
00527 void
00528 MSCalibrator::setActiveChild(MSCalibratorChild *c) {
00529     myActiveChild = c;
00530 }
00531 
00532 std::map<std::string, MSCalibrator*> MSCalibrator::calibratorMap;
00533 
00534 void
00535 MSCalibrator::updateCalibrator(std::string name, int time, SUMOReal count) {
00536 
00537     std::map<std::string, MSCalibrator*>::iterator it = MSCalibrator::calibratorMap.find(name);
00538 
00539     if (it==MSCalibrator::calibratorMap.end()) {
00540         WRITE_ERROR("WRONG UPDATE COMMAND, CALIBRATOR NOT FOUND: " + name);
00541         return;
00542     }
00543 
00544     MSCalibrator * calibrator = (*it).second;
00545 
00546     calibrator->myInterval = time;
00547     calibrator->myNumVehicles = count;
00548 
00549     //DOME
00550     int i=0;
00551 
00552 
00553 }
00554 
00555 
00556 /****************************************************************************/
00557 

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