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