SUMO - Simulation of Urban MObility

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