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-2015 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 {}
64 
65 
67  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
68  delete(i->pars);
69  }
70 }
71 
72 
73 void
75  myAllVeh.add(veh);
76 }
77 
78 
79 bool
81  if (myFlowIDs.count(pars->id) > 0) {
82  return false;
83  }
84  Flow flow;
85  flow.pars = pars;
89  flow.index = 0;
90  if (!flow.isVolatile) {
92  if (dist != 0) {
93  const std::vector<const MSRoute*>& routes = dist->getVals();
94  const MSEdge* e = 0;
95  for (std::vector<const MSRoute*>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
96  if (e == 0) {
97  e = (*i)->getEdges()[0];
98  } else {
99  if (e != (*i)->getEdges()[0]) {
100  flow.isVolatile = true;
101  break;
102  }
103  }
104  }
105  }
106  }
107  flow.vehicle = 0;
108  myFlows.push_back(flow);
109  myFlowIDs.insert(pars->id);
110  return true;
111 }
112 
113 
114 unsigned int
116  // check whether any vehicles shall be emitted within this time step
117  const bool havePreChecked = MSDevice_Routing::isEnabled();
118  if (myPendingEmits.empty() || (havePreChecked && myEmitCandidates.empty())) {
119  return 0;
120  }
121  unsigned int numEmitted = 0;
122  // we use buffering for the refused emits to save time
123  // for this, we have two lists; one contains previously refused emits, the second
124  // will be used to append those vehicles that will not be able to depart in this
125  // time step
127 
128  // go through the list of previously refused vehicles, first
129  MSVehicleContainer::VehicleVector::const_iterator veh;
130  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
131  if (havePreChecked && (myEmitCandidates.count(*veh) == 0)) {
132  refusedEmits.push_back(*veh);
133  } else {
134  numEmitted += tryInsert(time, *veh, refusedEmits);
135  }
136  }
137  myEmitCandidates.clear();
138  myPendingEmits = refusedEmits;
139  return numEmitted;
140 }
141 
142 
143 unsigned int
145  MSVehicleContainer::VehicleVector& refusedEmits) {
146  assert(veh->getParameter().depart < time + DELTA_T);
147  const MSEdge& edge = *veh->getEdge();
148  if (veh->isOnRoad()) {
149  // may have been inserted forcefully already
150  veh->onDepart();
151  return 1;
152  }
153  if ((myMaxVehicleNumber < 0 || (int)MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() < myMaxVehicleNumber)
154  && (!myCheckEdgesOnce || edge.getLastFailedInsertionTime() != time)
155  && edge.insertVehicle(*veh, time)) {
156  // Successful insertion
157  checkFlowWait(veh);
158  veh->onDepart();
159  return 1;
160  }
161  if (myMaxDepartDelay >= 0 && time - veh->getParameter().depart > myMaxDepartDelay) {
162  // remove vehicles waiting too long for departure
163  checkFlowWait(veh);
164  myVehicleControl.deleteVehicle(veh, true);
165  } else if (edge.isVaporizing()) {
166  // remove vehicles if the edge shall be empty
167  checkFlowWait(veh);
168  myVehicleControl.deleteVehicle(veh, true);
169  } else if (myAbortedEmits.count(veh) > 0) {
170  // remove vehicles which shall not be inserted for some reason
171  myAbortedEmits.erase(veh);
172  checkFlowWait(veh);
173  myVehicleControl.deleteVehicle(veh, true);
174  } else {
175  // let the vehicle wait one step, we'll retry then
176  refusedEmits.push_back(veh);
177  }
178  edge.setLastFailedInsertionTime(time);
179  return 0;
180 }
181 
182 
183 void
185  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
186  if (i->vehicle == veh) {
187  i->vehicle = 0;
188  break;
189  }
190  }
191 }
192 
193 
194 void
195 MSInsertionControl::checkCandidates(SUMOTime time, const bool preCheck) {
196  while (myAllVeh.anyWaitingBefore(time + DELTA_T)) {
198  copy(top.begin(), top.end(), back_inserter(myPendingEmits));
199  myAllVeh.pop();
200  }
201  if (preCheck) {
202  MSVehicleContainer::VehicleVector::const_iterator veh;
203  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
204  SUMOVehicle* const v = *veh;
205  const MSEdge* const edge = v->getEdge();
206  if ((!myCheckEdgesOnce || edge->getLastFailedInsertionTime() != time) && edge->insertVehicle(*v, time, true)) {
207  myEmitCandidates.insert(v);
208  } else {
209  MSDevice_Routing* dev = static_cast<MSDevice_Routing*>(v->getDevice(typeid(MSDevice_Routing)));
210  if (dev != 0) {
211  dev->skipRouting(time);
212  }
213  }
214  }
215  }
216 }
217 
218 
219 void
222  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end();) {
223  SUMOVehicleParameter* pars = i->pars;
224  if (!i->isVolatile && i->vehicle != 0 && pars->repetitionProbability < 0) {
225  ++i;
226  //std::cout << SIMTIME << " volatile=" << i->isVolatile << " veh=" << i->vehicle << "\n";
227  continue;
228  }
229  bool tryEmitByProb = pars->repetitionProbability > 0;
230  while ((pars->repetitionProbability < 0
231  && pars->repetitionsDone < pars->repetitionNumber
232  && pars->depart + pars->repetitionsDone * pars->repetitionOffset < time + DELTA_T)
233  || (tryEmitByProb
234  && pars->depart < time + DELTA_T
235  && pars->repetitionEnd > time
236  // only call rand if all other conditions are met
237  && RandHelper::rand() < (pars->repetitionProbability * TS))
238  ) {
239  tryEmitByProb = false; // only emit one per step
240  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
241  newPars->id = pars->id + "." + toString(i->index);
242  newPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
243  pars->repetitionsDone++;
244  // try to build the vehicle
245  if (vehControl.getVehicle(newPars->id) == 0) {
246  const MSRoute* route = MSRoute::dictionary(pars->routeid);
247  const MSVehicleType* vtype = vehControl.getVType(pars->vtypeid, MSRouteHandler::getParsingRNG());
248  i->vehicle = vehControl.buildVehicle(newPars, route, vtype, false);
249  unsigned int quota = vehControl.getQuota();
250  if (quota > 0) {
251  vehControl.addVehicle(newPars->id, i->vehicle);
252  add(i->vehicle);
253  i->index++;
254  while (--quota > 0) {
255  SUMOVehicleParameter* quotaPars = new SUMOVehicleParameter(*pars);
256  quotaPars->id = pars->id + "." + toString(i->index);
257  quotaPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
258  i->vehicle = vehControl.buildVehicle(quotaPars, route, vtype, false);
259  vehControl.addVehicle(quotaPars->id, i->vehicle);
260  add(i->vehicle);
261  i->index++;
262  }
263  } else {
264  vehControl.deleteVehicle(i->vehicle, true);
265  i->vehicle = 0;
266  }
267  } else {
268  // strange: another vehicle with the same id already exists
270  break;
271  }
272  throw ProcessError("Another vehicle with the id '" + newPars->id + "' exists.");
273  }
274  }
275  if (pars->repetitionsDone == pars->repetitionNumber || (pars->repetitionProbability > 0 && pars->repetitionEnd <= time)) {
276  i = myFlows.erase(i);
278  delete pars;
279  } else {
280  ++i;
281  }
282  }
284 }
285 
286 
287 unsigned int
289  return (unsigned int)myPendingEmits.size();
290 }
291 
292 
293 int
295  return (int)myFlows.size();
296 }
297 
298 
299 void
301  myAbortedEmits.insert(veh);
302 }
303 
304 void
306  //clear out the refused vehicle list, deleting the vehicles entirely
307  MSVehicleContainer::VehicleVector::iterator veh;
308  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end();) {
309  if ((*veh)->getRoute().getID() == route || route == "") {
310  myVehicleControl.deleteVehicle(*veh, true);
311  veh = myPendingEmits.erase(veh);
312  } else {
313  ++veh;
314  }
315  }
316 }
317 
318 
319 /****************************************************************************/
320 
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
bool insertVehicle(SUMOVehicle &v, SUMOTime time, const bool checkOnly=false) const
Tries to insert the given vehicle into the network.
Definition: MSEdge.cpp:396
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.
virtual void onDepart()=0
Called when the vehicle is inserted into the network.
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:86
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.
unsigned int index
the running index
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:162
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:150
void skipRouting(const SUMOTime currentTime)
Labels the current time step as "unroutable".
#define TS
Definition: SUMOTime.h:52
SUMOReal repetitionOffset
The time offset between vehicle reinsertions.
The position is chosen randomly.
~MSInsertionControl()
Destructor.
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.
A road/street connecting two junctions.
Definition: MSEdge.h:81
void pop()
Removes the uppermost vehicle vector.
unsigned int getWaitingVehicleNo() const
Returns the number of waiting vehicles.
std::string routeid
The vehicle&#39;s route id.
Representation of a vehicle.
Definition: SUMOVehicle.h:65
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
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.
unsigned int tryInsert(SUMOTime time, SUMOVehicle *veh, MSVehicleContainer::VehicleVector &refusedEmits)
Tries to emit the vehicle.
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:308
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:53
static bool isEnabled()
returns whether any routing actions take place
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.
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)
unsigned int emitVehicles(SUMOTime time)
Emits vehicles that want to depart at the given time.
SUMOTime getLastFailedInsertionTime() const
Returns the last time a vehicle could not be inserted.
Definition: MSEdge.h:486
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.
#define DELTA_T
Definition: SUMOTime.h:50
The class responsible for building and deletion of vehicles.
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.
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:173
unsigned int getQuota(SUMOReal frac=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
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:116