MSEmitControl.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // Inserts vehicles into the network when their departure time is reached
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 <iostream>
00031 #include <algorithm>
00032 #include <cassert>
00033 #include "MSEmitControl.h"
00034 #include "MSVehicle.h"
00035 #include "MSLane.h"
00036 
00037 #ifdef CHECK_MEMORY_LEAKS
00038 #include <foreign/nvwa/debug_new.h>
00039 #endif // CHECK_MEMORY_LEAKS
00040 
00041 
00042 // ===========================================================================
00043 // member method definitions
00044 // ===========================================================================
00045 MSEmitControl::MSEmitControl(MSVehicleControl &vc,
00046                              SUMOTime maxDepartDelay,
00047                              bool checkEdgesOnce) throw()
00048         : myVehicleControl(vc), myMaxDepartDelay(maxDepartDelay),
00049         myCheckEdgesOnce(checkEdgesOnce) {}
00050 
00051 
00052 MSEmitControl::~MSEmitControl() throw() {
00053     for (std::vector<Flow>::iterator i=myFlows.begin(); i!=myFlows.end(); ++i) {
00054         delete(i->pars);
00055     }
00056 }
00057 
00058 
00059 void
00060 MSEmitControl::add(MSVehicle *veh) throw() {
00061     myAllVeh.add(veh);
00062 }
00063 
00064 
00065 void
00066 MSEmitControl::add(SUMOVehicleParameter *pars) throw() {
00067     Flow flow;
00068     flow.pars = pars;
00069     flow.isVolatile = pars->departLaneProcedure==DEPART_LANE_RANDOM ||
00070                       pars->departPosProcedure==DEPART_POS_RANDOM ||
00071                       MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(pars->vtypeid);
00072     if (!flow.isVolatile) {
00073         RandomDistributor<const MSRoute*> *dist = MSRoute::distDictionary(pars->routeid);
00074         if (dist != 0) {
00075             const std::vector<const MSRoute*>& routes = dist->getVals();
00076             const MSEdge* e = 0;
00077             for (std::vector<const MSRoute*>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
00078                 if (e == 0) {
00079                     e = (*i)->getEdges()[0];
00080                 } else {
00081                     if (e != (*i)->getEdges()[0]) {
00082                         flow.isVolatile = true;
00083                         break;
00084                     }
00085                 }
00086             }
00087         }
00088     }
00089     flow.vehicle = 0;
00090     myFlows.push_back(flow);
00091 }
00092 
00093 
00094 unsigned int
00095 MSEmitControl::emitVehicles(SUMOTime time) throw(ProcessError) {
00096     checkPrevious(time);
00097     // check whether any vehicles shall be emitted within this time step
00098     if (!myAllVeh.anyWaitingFor(time)&&myRefusedEmits1.empty()&&myRefusedEmits2.empty()&&myFlows.empty()) {
00099         return 0;
00100     }
00101     unsigned int noEmitted = 0;
00102     // we use buffering for the refused emits to save time
00103     //  for this, we have two lists; one contains previously refused emits, the second
00104     //  will be used to append those vehicles that will not be able to depart in this
00105     //  time step
00106     assert(myRefusedEmits1.size()==0||myRefusedEmits2.size()==0);
00107     MSVehicleContainer::VehicleVector &refusedEmits =
00108         myRefusedEmits1.size()==0 ? myRefusedEmits1 : myRefusedEmits2;
00109     MSVehicleContainer::VehicleVector &previousRefused =
00110         myRefusedEmits2.size()==0 ? myRefusedEmits1 : myRefusedEmits2;
00111 
00112     // go through the list of previously refused vehicles, first
00113     MSVehicleContainer::VehicleVector::const_iterator veh;
00114     for (veh=previousRefused.begin(); veh!=previousRefused.end(); veh++) {
00115         noEmitted += tryEmit(time, *veh, refusedEmits);
00116     }
00117     // clear previously refused vehicle container
00118     previousRefused.clear();
00119 
00120     // Insert vehicles from myTrips into the net until the next vehicle's
00121     //  departure time is greater than the current time.
00122     // Retrieve the list of vehicles to emit within this time step
00123 
00124     noEmitted += checkFlows(time, refusedEmits);
00125     while (myAllVeh.anyWaitingFor(time)) {
00126         const MSVehicleContainer::VehicleVector &next = myAllVeh.top();
00127         // go through the list and try to emit
00128         for (veh=next.begin(); veh!=next.end(); veh++) {
00129             noEmitted += tryEmit(time, *veh, refusedEmits);
00130         }
00131         // let the MSVehicleContainer clear the vehicles
00132         myAllVeh.pop();
00133     }
00134     // Return the number of emitted vehicles
00135     return noEmitted;
00136 }
00137 
00138 
00139 unsigned int
00140 MSEmitControl::tryEmit(SUMOTime time, MSVehicle *veh,
00141                        MSVehicleContainer::VehicleVector &refusedEmits) throw(ProcessError) {
00142     assert(veh->getDesiredDepart() <= time);
00143     veh->onTryEmit();
00144     const MSEdge &edge = veh->getDepartEdge();
00145     if ((!myCheckEdgesOnce || edge.getLastFailedEmissionTime()!=time) && edge.emit(*veh, time)) {
00146         // Successful emission.
00147         checkFlowWait(veh);
00148         veh->onDepart();
00149         return 1;
00150     }
00151     if (myMaxDepartDelay != -1 && time - veh->getDesiredDepart() > myMaxDepartDelay) {
00152         // remove vehicles waiting too long for departure
00153         checkFlowWait(veh);
00154         myVehicleControl.deleteVehicle(veh);
00155     } else if (edge.isVaporizing()) {
00156         // remove vehicles if the edge shall be empty
00157         checkFlowWait(veh);
00158         veh->setWasVaporized(true);
00159         myVehicleControl.deleteVehicle(veh);
00160     } else {
00161         // let the vehicle wait one step, we'll retry then
00162         refusedEmits.push_back(veh);
00163     }
00164     edge.setLastFailedEmissionTime(time);
00165     return 0;
00166 }
00167 
00168 
00169 void
00170 MSEmitControl::checkFlowWait(MSVehicle *veh) throw() {
00171     for (std::vector<Flow>::iterator i=myFlows.begin(); i!=myFlows.end(); ++i) {
00172         if (i->vehicle == veh) {
00173             i->vehicle = 0;
00174             break;
00175         }
00176     }
00177 }
00178 
00179 
00180 void
00181 MSEmitControl::checkPrevious(SUMOTime time) throw() {
00182     // check to which list append to
00183     MSVehicleContainer::VehicleVector &previousRefused =
00184         myRefusedEmits2.size()==0 ? myRefusedEmits1 : myRefusedEmits2;
00185     while (!myAllVeh.isEmpty()&&myAllVeh.topTime()<time) {
00186         const MSVehicleContainer::VehicleVector &top = myAllVeh.top();
00187         copy(top.begin(), top.end(), back_inserter(previousRefused));
00188         myAllVeh.pop();
00189     }
00190 }
00191 
00192 
00193 unsigned int
00194 MSEmitControl::checkFlows(SUMOTime time,
00195                           MSVehicleContainer::VehicleVector &refusedEmits) throw(ProcessError) {
00196     unsigned int noEmitted = 0;
00197     for (std::vector<Flow>::iterator i=myFlows.begin(); i!=myFlows.end();) {
00198         SUMOVehicleParameter* pars = i->pars;
00199         if (!i->isVolatile && i->vehicle!=0) {
00200             ++i;
00201             continue;
00202         }
00203         while (pars->repetitionsDone < pars->repetitionNumber &&
00204                 pars->depart + pars->repetitionsDone * pars->repetitionOffset < time + DELTA_T) {
00205             SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
00206             newPars->id = pars->id + "." + toString(pars->repetitionsDone);
00207             newPars->depart = (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
00208             pars->repetitionsDone++;
00209             // try to build the vehicle
00210             if (MSNet::getInstance()->getVehicleControl().getVehicle(newPars->id)==0) {
00211                 const MSRoute *route = MSRoute::dictionary(pars->routeid);
00212                 const MSVehicleType *vtype = MSNet::getInstance()->getVehicleControl().getVType(pars->vtypeid);
00213                 i->vehicle = MSNet::getInstance()->getVehicleControl().buildVehicle(newPars, route, vtype);
00214                 MSNet::getInstance()->getVehicleControl().addVehicle(newPars->id, i->vehicle);
00215                 noEmitted += tryEmit(time, i->vehicle, refusedEmits);
00216                 if (!i->isVolatile && i->vehicle!=0) {
00217                     break;
00218                 }
00219             } else {
00220                 // strange: another vehicle with the same id already exists
00221 #ifdef HAVE_MESOSIM
00222                 if (MSGlobals::gStateLoaded) {
00223                     break;
00224                 }
00225 #endif
00226                 throw ProcessError("Another vehicle with the id '" + newPars->id + "' exists.");
00227             }
00228         }
00229         if (pars->repetitionsDone == pars->repetitionNumber) {
00230             i = myFlows.erase(i);
00231             delete(pars);
00232         } else {
00233             ++i;
00234         }
00235     }
00236     return noEmitted;
00237 }
00238 
00239 
00240 unsigned int
00241 MSEmitControl::getWaitingVehicleNo() const throw() {
00242     return (unsigned int)(myRefusedEmits1.size() + myRefusedEmits2.size());
00243 }
00244 
00245 
00246 bool
00247 MSEmitControl::hasPendingFlows() const throw() {
00248     return !myFlows.empty();
00249 }
00250 
00251 
00252 /****************************************************************************/
00253 

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