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 #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