|
SUMO - Simulation of Urban MObility
|
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