SUMO - Simulation of Urban MObility
MSInsertionControl.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // Inserts vehicles into the network when their departure time is reached
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
14 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include <iostream>
36 #include <algorithm>
37 #include <cassert>
38 #include <iterator>
40 #include "MSGlobals.h"
41 #include "MSInsertionControl.h"
42 #include "MSVehicle.h"
43 #include "MSLane.h"
44 #include "MSEdge.h"
45 #include "MSRouteHandler.h"
46 
47 #ifdef CHECK_MEMORY_LEAKS
48 #include <foreign/nvwa/debug_new.h>
49 #endif // CHECK_MEMORY_LEAKS
50 
51 
52 // ===========================================================================
53 // member method definitions
54 // ===========================================================================
56  SUMOTime maxDepartDelay,
57  bool eagerInsertionCheck,
58  int maxVehicleNumber) :
59  myVehicleControl(vc),
60  myMaxDepartDelay(maxDepartDelay),
61  myEagerInsertionCheck(eagerInsertionCheck),
62  myMaxVehicleNumber(maxVehicleNumber),
63  myPendingEmitsUpdateTime(SUMOTime_MIN) {
64 }
65 
66 
68  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
69  delete(i->pars);
70  }
71 }
72 
73 
74 void
76  myAllVeh.add(veh);
77 }
78 
79 
80 bool
82  if (myFlowIDs.count(pars->id) > 0) {
83  return false;
84  }
85  Flow flow;
86  flow.pars = pars;
87  flow.index = 0;
88  myFlows.push_back(flow);
89  myFlowIDs.insert(pars->id);
90  return true;
91 }
92 
93 
94 int
96  // check whether any vehicles shall be emitted within this time step
97  const bool havePreChecked = MSDevice_Routing::isEnabled();
98  if (myPendingEmits.empty() || (havePreChecked && myEmitCandidates.empty())) {
99  return 0;
100  }
101  int numEmitted = 0;
102  // we use buffering for the refused emits to save time
103  // for this, we have two lists; one contains previously refused emits, the second
104  // will be used to append those vehicles that will not be able to depart in this
105  // time step
107 
108  // go through the list of previously refused vehicles, first
109  MSVehicleContainer::VehicleVector::const_iterator veh;
110  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
111  if (havePreChecked && (myEmitCandidates.count(*veh) == 0)) {
112  refusedEmits.push_back(*veh);
113  } else {
114  numEmitted += tryInsert(time, *veh, refusedEmits);
115  }
116  }
117  myEmitCandidates.clear();
118  myPendingEmits = refusedEmits;
119  return numEmitted;
120 }
121 
122 
123 int
125  MSVehicleContainer::VehicleVector& refusedEmits) {
126  assert(veh->getParameter().depart < time + DELTA_T);
127  const MSEdge& edge = *veh->getEdge();
128  if (veh->isOnRoad()) {
129  return 1;
130  }
131  if ((myMaxVehicleNumber < 0 || (int)MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() < myMaxVehicleNumber)
132  && edge.insertVehicle(*veh, time, false, myEagerInsertionCheck)) {
133  // Successful insertion
134  return 1;
135  }
136  if (myMaxDepartDelay >= 0 && time - veh->getParameter().depart > myMaxDepartDelay) {
137  // remove vehicles waiting too long for departure
138  myVehicleControl.deleteVehicle(veh, true);
139  } else if (edge.isVaporizing()) {
140  // remove vehicles if the edge shall be empty
141  myVehicleControl.deleteVehicle(veh, true);
142  } else if (myAbortedEmits.count(veh) > 0) {
143  // remove vehicles which shall not be inserted for some reason
144  myAbortedEmits.erase(veh);
145  myVehicleControl.deleteVehicle(veh, true);
146  } else {
147  // let the vehicle wait one step, we'll retry then
148  refusedEmits.push_back(veh);
149  }
150  edge.setLastFailedInsertionTime(time);
151  return 0;
152 }
153 
154 
155 void
156 MSInsertionControl::checkCandidates(SUMOTime time, const bool preCheck) {
157  while (myAllVeh.anyWaitingBefore(time + DELTA_T)) {
159  copy(top.begin(), top.end(), back_inserter(myPendingEmits));
160  myAllVeh.pop();
161  }
162  if (preCheck) {
163  MSVehicleContainer::VehicleVector::const_iterator veh;
164  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
165  SUMOVehicle* const v = *veh;
166  const MSEdge* const edge = v->getEdge();
167  if (edge->insertVehicle(*v, time, true, myEagerInsertionCheck)) {
168  myEmitCandidates.insert(v);
169  } else {
170  MSDevice_Routing* dev = static_cast<MSDevice_Routing*>(v->getDevice(typeid(MSDevice_Routing)));
171  if (dev != 0) {
172  dev->skipRouting(time);
173  }
174  }
175  }
176  }
177 }
178 
179 
180 void
183  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end();) {
184  SUMOVehicleParameter* pars = i->pars;
185  bool tryEmitByProb = pars->repetitionProbability > 0;
186  while ((pars->repetitionProbability < 0
187  && pars->repetitionsDone < pars->repetitionNumber
188  && pars->depart + pars->repetitionsDone * pars->repetitionOffset < time + DELTA_T)
189  || (tryEmitByProb
190  && pars->depart < time + DELTA_T
191  && pars->repetitionEnd > time
192  // only call rand if all other conditions are met
193  && RandHelper::rand() < (pars->repetitionProbability * TS))
194  ) {
195  tryEmitByProb = false; // only emit one per step
196  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
197  newPars->id = pars->id + "." + toString(i->index);
198  newPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
199  pars->repetitionsDone++;
200  // try to build the vehicle
201  if (vehControl.getVehicle(newPars->id) == 0) {
202  const MSRoute* route = MSRoute::dictionary(pars->routeid);
203  const MSVehicleType* vtype = vehControl.getVType(pars->vtypeid, MSRouteHandler::getParsingRNG());
204  SUMOVehicle* vehicle = vehControl.buildVehicle(newPars, route, vtype, false);
205  int quota = vehControl.getQuota();
206  if (quota > 0) {
207  vehControl.addVehicle(newPars->id, vehicle);
208  add(vehicle);
209  i->index++;
210  while (--quota > 0) {
211  SUMOVehicleParameter* quotaPars = new SUMOVehicleParameter(*pars);
212  quotaPars->id = pars->id + "." + toString(i->index);
213  quotaPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
214  SUMOVehicle* vehicle = vehControl.buildVehicle(quotaPars, route, vtype, false);
215  vehControl.addVehicle(quotaPars->id, vehicle);
216  add(vehicle);
217  i->index++;
218  }
219  } else {
220  vehControl.deleteVehicle(vehicle, true);
221  }
222  } else {
223  // strange: another vehicle with the same id already exists
225  vehControl.discountStateLoaded();
226  break;
227  }
228  throw ProcessError("Another vehicle with the id '" + newPars->id + "' exists.");
229  }
230  }
231  if (pars->repetitionsDone == pars->repetitionNumber || (pars->repetitionProbability > 0 && pars->repetitionEnd <= time)) {
232  i = myFlows.erase(i);
234  delete pars;
235  } else {
236  ++i;
237  }
238  }
240 }
241 
242 
243 int
245  return (int)myPendingEmits.size();
246 }
247 
248 
249 int
251  return (int)myFlows.size();
252 }
253 
254 
255 void
257  myAbortedEmits.insert(veh);
258 }
259 
260 
261 void
263  myPendingEmits.erase(std::remove(myPendingEmits.begin(), myPendingEmits.end(), veh), myPendingEmits.end());
264  myAllVeh.remove(veh);
265 }
266 
267 
268 void
270  //clear out the refused vehicle list, deleting the vehicles entirely
271  MSVehicleContainer::VehicleVector::iterator veh;
272  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end();) {
273  if ((*veh)->getRoute().getID() == route || route == "") {
274  myVehicleControl.deleteVehicle(*veh, true);
275  veh = myPendingEmits.erase(veh);
276  } else {
277  ++veh;
278  }
279  }
280 }
281 
282 
283 int
285  if (MSNet::getInstance()->getCurrentTimeStep() > myPendingEmitsUpdateTime) {
286  // updated pending emits (only once per time step)
287  myPendingEmitsForLane.clear();
288  for (MSVehicleContainer::VehicleVector::const_iterator veh = myPendingEmits.begin(); veh != myPendingEmits.end(); ++veh) {
289  const MSLane* lane = (*veh)->getLane();
290  if (lane != 0) {
291  myPendingEmitsForLane[lane]++;
292  } else {
293  // no (tentative) departLane was set, increase count for all
294  // lanes of the depart edge
295  const MSEdge* edge = (*veh)->getEdge();
296  const std::vector<MSLane*>& lanes = edge->getLanes();
297  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
298  myPendingEmitsForLane[*i]++;
299  }
300  }
301  }
303  }
304  return myPendingEmitsForLane[lane];
305 }
306 
307 /****************************************************************************/
308 
std::map< const MSLane *, int > myPendingEmitsForLane
the number of pending emits for each edge in the current time step
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
SUMOReal repetitionProbability
The probability for emitting a vehicle per second.
void discountStateLoaded(bool removed=false)
avoid counting a vehicle twice if it was loaded from state and route input
int getPendingFlowCount() const
Returns the number of flows that are still active.
virtual bool isOnRoad() const =0
Returns the information whether the vehicle is on a road (is simulated)
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
long long int SUMOTime
Definition: SUMOTime.h:43
void descheduleDeparture(SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
void remove(SUMOVehicle *veh)
Removes a single vehicle.
int repetitionNumber
The number of times the vehicle shall be repeatedly inserted.
std::set< SUMOVehicle * > myAbortedEmits
Set of vehicles which shall not be inserted anymore.
std::string vtypeid
The vehicle&#39;s type id.
int getQuota(SUMOReal frac=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:192
void checkCandidates(SUMOTime time, const bool preCheck)
Adds all vehicles that should have been emitted earlier to the refuse container.
static MTRand * getParsingRNG()
static bool gStateLoaded
Information whether a state has been loaded.
Definition: MSGlobals.h:92
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
A device that performs vehicle rerouting based on current edge speeds.
int repetitionsDone
The number of times the vehicle was already inserted.
virtual const MSEdge * getEdge() const =0
Returns the edge the vehicle is currently at.
MSVehicleContainer myAllVeh
All loaded vehicles sorted by their departure time.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
void skipRouting(const SUMOTime currentTime)
Labels the current time step as "unroutable".
#define TS
Definition: SUMOTime.h:52
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:255
int getWaitingVehicleNo() const
Returns the number of waiting vehicles.
~MSInsertionControl()
Destructor.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
The car-following model and parameter.
Definition: MSVehicleType.h:74
std::vector< SUMOVehicle * > VehicleVector
definition of a list of vehicles which have the same departure time
MSInsertionControl(MSVehicleControl &vc, SUMOTime maxDepartDelay, bool checkEdgesOnce, int maxVehicleNumber)
Constructor.
#define SUMOTime_MIN
Definition: SUMOTime.h:45
A road/street connecting two junctions.
Definition: MSEdge.h:80
void pop()
Removes the uppermost vehicle vector.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
std::string routeid
The vehicle&#39;s route id.
Representation of a vehicle.
Definition: SUMOVehicle.h:67
int emitVehicles(SUMOTime time)
Emits vehicles that want to depart at the given time.
MSVehicleContainer::VehicleVector myPendingEmits
Buffers for vehicles that could not be inserted.
int tryInsert(SUMOTime time, SUMOVehicle *veh, MSVehicleContainer::VehicleVector &refusedEmits)
Tries to emit the vehicle.
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:308
bool myEagerInsertionCheck
Whether an edge on which a vehicle could not depart should be ignored in the same step...
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, const MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true)
Builds a vehicle, increases the number of built vehicles.
SUMOTime depart
The vehicle&#39;s departure time.
SUMOTime myMaxDepartDelay
The maximum waiting time; vehicles waiting longer are deleted (-1: no deletion)
bool insertVehicle(SUMOVehicle &v, SUMOTime time, const bool checkOnly=false, const bool forceCheck=false) const
Tries to insert the given vehicle into the network.
Definition: MSEdge.cpp:471
void clearPendingVehicles(std::string &route)
clears out all pending vehicles from a route, "" for all routes
std::set< SUMOVehicle * > myEmitCandidates
Buffer for vehicles that may be inserted in the current step.
void add(SUMOVehicle *veh)
Adds a single vehicle.
static bool isEnabled()
returns whether any routing actions take place
SUMOTime myPendingEmitsUpdateTime
Last time at which pending emits for each edge where counted.
const VehicleVector & top()
Returns the uppermost vehicle vector.
std::vector< Flow > myFlows
Container for periodical vehicle parameters.
void alreadyDeparted(SUMOVehicle *veh)
stops trying to emit the given vehicle (because it already departed)
int myMaxVehicleNumber
Storage for maximum vehicle number.
Structure representing possible vehicle parameter.
MSVehicleControl & myVehicleControl
The assigned vehicle control (needed for vehicle re-insertion and deletion)
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle&#39;s parameter (including departure definition)
bool anyWaitingBefore(SUMOTime time) const
Returns the information whether any vehicles want to depart before the given time.
The class responsible for building and deletion of vehicles.
int index
the running index
SUMOVehicleParameter * pars
The paramters.
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, MTRand *rng=0)
Returns the named vehicle type or a sample from the named distribution.
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
std::set< std::string > myFlowIDs
Cache for periodical vehicle ids for quicker checking.
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition: MSRoute.cpp:194
int getPendingEmits(const MSLane *lane)
return the number of pending emits for the given lane
void determineCandidates(SUMOTime time)
Checks for all vehicles whether they can be emitted.
std::string id
The vehicle&#39;s id.
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:122
virtual MSDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.