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