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-2016 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 checkEdgesOnce,
58  int maxVehicleNumber) :
59  myVehicleControl(vc),
60  myMaxDepartDelay(maxDepartDelay),
61  myCheckEdgesOnce(checkEdgesOnce),
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;
90  flow.index = 0;
91  if (!flow.isVolatile) {
93  if (dist != 0) {
94  const std::vector<const MSRoute*>& routes = dist->getVals();
95  const MSEdge* e = 0;
96  for (std::vector<const MSRoute*>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
97  if (e == 0) {
98  e = (*i)->getEdges()[0];
99  } else {
100  if (e != (*i)->getEdges()[0]) {
101  flow.isVolatile = true;
102  break;
103  }
104  }
105  }
106  }
107  }
108  flow.vehicle = 0;
109  myFlows.push_back(flow);
110  myFlowIDs.insert(pars->id);
111  return true;
112 }
113 
114 
115 int
117  // check whether any vehicles shall be emitted within this time step
118  const bool havePreChecked = MSDevice_Routing::isEnabled();
119  if (myPendingEmits.empty() || (havePreChecked && myEmitCandidates.empty())) {
120  return 0;
121  }
122  int numEmitted = 0;
123  // we use buffering for the refused emits to save time
124  // for this, we have two lists; one contains previously refused emits, the second
125  // will be used to append those vehicles that will not be able to depart in this
126  // time step
128 
129  // go through the list of previously refused vehicles, first
130  MSVehicleContainer::VehicleVector::const_iterator veh;
131  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
132  if (havePreChecked && (myEmitCandidates.count(*veh) == 0)) {
133  refusedEmits.push_back(*veh);
134  } else {
135  numEmitted += tryInsert(time, *veh, refusedEmits);
136  }
137  }
138  myEmitCandidates.clear();
139  myPendingEmits = refusedEmits;
140  return numEmitted;
141 }
142 
143 
144 int
146  MSVehicleContainer::VehicleVector& refusedEmits) {
147  assert(veh->getParameter().depart < time + DELTA_T);
148  const MSEdge& edge = *veh->getEdge();
149  if (veh->isOnRoad()) {
150  return 1;
151  }
152  if ((myMaxVehicleNumber < 0 || (int)MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() < myMaxVehicleNumber)
153  && (!myCheckEdgesOnce || edge.getLastFailedInsertionTime() != time)
154  && edge.insertVehicle(*veh, time)) {
155  // Successful insertion
156  checkFlowWait(veh);
157  return 1;
158  }
159  if (myMaxDepartDelay >= 0 && time - veh->getParameter().depart > myMaxDepartDelay) {
160  // remove vehicles waiting too long for departure
161  checkFlowWait(veh);
162  myVehicleControl.deleteVehicle(veh, true);
163  } else if (edge.isVaporizing()) {
164  // remove vehicles if the edge shall be empty
165  checkFlowWait(veh);
166  myVehicleControl.deleteVehicle(veh, true);
167  } else if (myAbortedEmits.count(veh) > 0) {
168  // remove vehicles which shall not be inserted for some reason
169  myAbortedEmits.erase(veh);
170  checkFlowWait(veh);
171  myVehicleControl.deleteVehicle(veh, true);
172  } else {
173  // let the vehicle wait one step, we'll retry then
174  refusedEmits.push_back(veh);
175  }
176  edge.setLastFailedInsertionTime(time);
177  return 0;
178 }
179 
180 
181 void
183  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
184  if (i->vehicle == veh) {
185  i->vehicle = 0;
186  break;
187  }
188  }
189 }
190 
191 
192 void
193 MSInsertionControl::checkCandidates(SUMOTime time, const bool preCheck) {
194  while (myAllVeh.anyWaitingBefore(time + DELTA_T)) {
196  copy(top.begin(), top.end(), back_inserter(myPendingEmits));
197  myAllVeh.pop();
198  }
199  if (preCheck) {
200  MSVehicleContainer::VehicleVector::const_iterator veh;
201  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
202  SUMOVehicle* const v = *veh;
203  const MSEdge* const edge = v->getEdge();
204  if ((!myCheckEdgesOnce || edge->getLastFailedInsertionTime() != time) && edge->insertVehicle(*v, time, true)) {
205  myEmitCandidates.insert(v);
206  } else {
207  MSDevice_Routing* dev = static_cast<MSDevice_Routing*>(v->getDevice(typeid(MSDevice_Routing)));
208  if (dev != 0) {
209  dev->skipRouting(time);
210  }
211  }
212  }
213  }
214 }
215 
216 
217 void
220  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end();) {
221  SUMOVehicleParameter* pars = i->pars;
222  if (!i->isVolatile && i->vehicle != 0 && pars->repetitionProbability < 0) {
223  ++i;
224  //std::cout << SIMTIME << " volatile=" << i->isVolatile << " veh=" << i->vehicle << "\n";
225  continue;
226  }
227  bool tryEmitByProb = pars->repetitionProbability > 0;
228  while ((pars->repetitionProbability < 0
229  && pars->repetitionsDone < pars->repetitionNumber
230  && pars->depart + pars->repetitionsDone * pars->repetitionOffset < time + DELTA_T)
231  || (tryEmitByProb
232  && pars->depart < time + DELTA_T
233  && pars->repetitionEnd > time
234  // only call rand if all other conditions are met
235  && RandHelper::rand() < (pars->repetitionProbability * TS))
236  ) {
237  tryEmitByProb = false; // only emit one per step
238  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
239  newPars->id = pars->id + "." + toString(i->index);
240  newPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
241  pars->repetitionsDone++;
242  // try to build the vehicle
243  if (vehControl.getVehicle(newPars->id) == 0) {
244  const MSRoute* route = MSRoute::dictionary(pars->routeid);
245  const MSVehicleType* vtype = vehControl.getVType(pars->vtypeid, MSRouteHandler::getParsingRNG());
246  i->vehicle = vehControl.buildVehicle(newPars, route, vtype, false);
247  int quota = vehControl.getQuota();
248  if (quota > 0) {
249  vehControl.addVehicle(newPars->id, i->vehicle);
250  add(i->vehicle);
251  i->index++;
252  while (--quota > 0) {
253  SUMOVehicleParameter* quotaPars = new SUMOVehicleParameter(*pars);
254  quotaPars->id = pars->id + "." + toString(i->index);
255  quotaPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
256  i->vehicle = vehControl.buildVehicle(quotaPars, route, vtype, false);
257  vehControl.addVehicle(quotaPars->id, i->vehicle);
258  add(i->vehicle);
259  i->index++;
260  }
261  } else {
262  vehControl.deleteVehicle(i->vehicle, true);
263  i->vehicle = 0;
264  }
265  } else {
266  // strange: another vehicle with the same id already exists
268  vehControl.discountStateLoaded();
269  break;
270  }
271  throw ProcessError("Another vehicle with the id '" + newPars->id + "' exists.");
272  }
273  }
274  if (pars->repetitionsDone == pars->repetitionNumber || (pars->repetitionProbability > 0 && pars->repetitionEnd <= time)) {
275  i = myFlows.erase(i);
277  delete pars;
278  } else {
279  ++i;
280  }
281  }
283 }
284 
285 
286 int
288  return (int)myPendingEmits.size();
289 }
290 
291 
292 int
294  return (int)myFlows.size();
295 }
296 
297 
298 void
300  myAbortedEmits.insert(veh);
301 }
302 
303 
304 void
306  myPendingEmits.erase(std::remove(myPendingEmits.begin(), myPendingEmits.end(), veh), myPendingEmits.end());
307  myAllVeh.remove(veh);
308 }
309 
310 
311 void
313  //clear out the refused vehicle list, deleting the vehicles entirely
314  MSVehicleContainer::VehicleVector::iterator veh;
315  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end();) {
316  if ((*veh)->getRoute().getID() == route || route == "") {
317  myVehicleControl.deleteVehicle(*veh, true);
318  veh = myPendingEmits.erase(veh);
319  } else {
320  ++veh;
321  }
322  }
323 }
324 
325 
326 int
328  if (MSNet::getInstance()->getCurrentTimeStep() > myPendingEmitsUpdateTime) {
329  // updated pending emits (only once per time step)
330  myPendingEmitsForLane.clear();
331  for (MSVehicleContainer::VehicleVector::const_iterator veh = myPendingEmits.begin(); veh != myPendingEmits.end(); ++veh) {
332  const MSLane* lane = (*veh)->getLane();
333  if (lane != 0) {
334  myPendingEmitsForLane[lane]++;
335  } else {
336  // no (tentative) departLane was set, increase count for all
337  // lanes of the depart edge
338  const MSEdge* edge = (*veh)->getEdge();
339  const std::vector<MSLane*>& lanes = edge->getLanes();
340  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
341  myPendingEmitsForLane[*i]++;
342  }
343  }
344  }
346  }
347  return myPendingEmitsForLane[lane];
348 }
349 
350 /****************************************************************************/
351 
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.
int getPendingFlowCount() const
Returns the number of flows that are still active.
void checkFlowWait(SUMOVehicle *veh)
Checks whether any flow is blocked due to this vehicle and clears the block.
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.
bool insertVehicle(SUMOVehicle &v, SUMOTime time, const bool checkOnly=false) const
Tries to insert the given vehicle into the network.
Definition: MSEdge.cpp:473
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.
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
virtual const MSEdge * getEdge() const =0
Returns the edge the vehicle is currently at.
static MTRand * getParsingRNG()
static bool gStateLoaded
Information whether a state has been loaded.
Definition: MSGlobals.h:87
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.
SUMOVehicle * vehicle
The last created vehicle.
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:39
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
The lane is chosen randomly.
static RandomDistributor< const MSRoute * > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition: MSRoute.cpp:165
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:254
The position is chosen randomly.
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
const std::vector< T > & getVals() const
Returns the members of the distribution.
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 routeid
The vehicle&#39;s route id.
Representation of a vehicle.
Definition: SUMOVehicle.h:66
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
int emitVehicles(SUMOTime time)
Emits vehicles that want to depart at the given time.
bool myCheckEdgesOnce
Whether an edge on which a vehicle could not depart should be ignored in the same step...
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:307
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)
virtual bool isOnRoad() const =0
Returns the information whether the vehicle is on a road (is simulated)
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.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
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.
bool isVolatile
whether it has route or vehicle type distribution
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.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle&#39;s parameter (including departure definition)
MSVehicleControl & myVehicleControl
The assigned vehicle control (needed for vehicle re-insertion and deletion)
SUMOTime getLastFailedInsertionTime() const
Returns the last time a vehicle could not be inserted.
Definition: MSEdge.h:524
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
bool anyWaitingBefore(SUMOTime time) const
Returns the information whether any vehicles want to depart before the given time.
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
virtual MSDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
The class responsible for building and deletion of vehicles.
int index
the running index
SUMOVehicleParameter * pars
The paramters.
void discountStateLoaded()
avoid counting a vehicle twice if it was loaded from state and route input
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