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