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 
48 // ===========================================================================
49 // member method definitions
50 // ===========================================================================
52  SUMOTime maxDepartDelay,
53  bool eagerInsertionCheck,
54  int maxVehicleNumber) :
55  myVehicleControl(vc),
56  myMaxDepartDelay(maxDepartDelay),
57  myEagerInsertionCheck(eagerInsertionCheck),
58  myMaxVehicleNumber(maxVehicleNumber),
59  myPendingEmitsUpdateTime(SUMOTime_MIN) {
60 }
61 
62 
64  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
65  delete(i->pars);
66  }
67 }
68 
69 
70 void
72  myAllVeh.add(veh);
73 }
74 
75 
76 bool
78  if (myFlowIDs.count(pars->id) > 0) {
79  return false;
80  }
81  Flow flow;
82  flow.pars = pars;
83  flow.index = 0;
84  myFlows.push_back(flow);
85  myFlowIDs.insert(pars->id);
86  return true;
87 }
88 
89 
90 int
92  // check whether any vehicles shall be emitted within this time step
93  const bool havePreChecked = MSDevice_Routing::isEnabled();
94  if (myPendingEmits.empty() || (havePreChecked && myEmitCandidates.empty())) {
95  return 0;
96  }
97  int numEmitted = 0;
98  // we use buffering for the refused emits to save time
99  // for this, we have two lists; one contains previously refused emits, the second
100  // will be used to append those vehicles that will not be able to depart in this
101  // time step
103 
104  // go through the list of previously refused vehicles, first
105  MSVehicleContainer::VehicleVector::const_iterator veh;
106  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
107  if (havePreChecked && (myEmitCandidates.count(*veh) == 0)) {
108  refusedEmits.push_back(*veh);
109  } else {
110  numEmitted += tryInsert(time, *veh, refusedEmits);
111  }
112  }
113  myEmitCandidates.clear();
114  myPendingEmits = refusedEmits;
115  return numEmitted;
116 }
117 
118 
119 int
121  MSVehicleContainer::VehicleVector& refusedEmits) {
122  assert(veh->getParameter().depart < time + DELTA_T);
123  const MSEdge& edge = *veh->getEdge();
124  if (veh->isOnRoad()) {
125  return 1;
126  }
127  if ((myMaxVehicleNumber < 0 || (int)MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() < myMaxVehicleNumber)
128  && edge.insertVehicle(*veh, time, false, myEagerInsertionCheck)) {
129  // Successful insertion
130  return 1;
131  }
132  if (myMaxDepartDelay >= 0 && time - veh->getParameter().depart > myMaxDepartDelay) {
133  // remove vehicles waiting too long for departure
134  myVehicleControl.deleteVehicle(veh, true);
135  } else if (edge.isVaporizing()) {
136  // remove vehicles if the edge shall be empty
137  myVehicleControl.deleteVehicle(veh, true);
138  } else if (myAbortedEmits.count(veh) > 0) {
139  // remove vehicles which shall not be inserted for some reason
140  myAbortedEmits.erase(veh);
141  myVehicleControl.deleteVehicle(veh, true);
142  } else {
143  // let the vehicle wait one step, we'll retry then
144  refusedEmits.push_back(veh);
145  }
146  edge.setLastFailedInsertionTime(time);
147  return 0;
148 }
149 
150 
151 void
152 MSInsertionControl::checkCandidates(SUMOTime time, const bool preCheck) {
153  while (myAllVeh.anyWaitingBefore(time + DELTA_T)) {
155  copy(top.begin(), top.end(), back_inserter(myPendingEmits));
156  myAllVeh.pop();
157  }
158  if (preCheck) {
159  MSVehicleContainer::VehicleVector::const_iterator veh;
160  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
161  SUMOVehicle* const v = *veh;
162  const MSEdge* const edge = v->getEdge();
163  if (edge->insertVehicle(*v, time, true, myEagerInsertionCheck)) {
164  myEmitCandidates.insert(v);
165  } else {
166  MSDevice_Routing* dev = static_cast<MSDevice_Routing*>(v->getDevice(typeid(MSDevice_Routing)));
167  if (dev != 0) {
168  dev->skipRouting(time);
169  }
170  }
171  }
172  }
173 }
174 
175 
176 void
179  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end();) {
180  SUMOVehicleParameter* pars = i->pars;
181  bool tryEmitByProb = pars->repetitionProbability > 0;
182  while ((pars->repetitionProbability < 0
183  && pars->repetitionsDone < pars->repetitionNumber
184  && pars->depart + pars->repetitionsDone * pars->repetitionOffset < time + DELTA_T)
185  || (tryEmitByProb
186  && pars->depart < time + DELTA_T
187  && pars->repetitionEnd > time
188  // only call rand if all other conditions are met
189  && RandHelper::rand() < (pars->repetitionProbability * TS))
190  ) {
191  tryEmitByProb = false; // only emit one per step
192  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
193  newPars->id = pars->id + "." + toString(i->index);
194  newPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
195  pars->repetitionsDone++;
196  // try to build the vehicle
197  if (vehControl.getVehicle(newPars->id) == 0) {
198  const MSRoute* route = MSRoute::dictionary(pars->routeid);
199  const MSVehicleType* vtype = vehControl.getVType(pars->vtypeid, MSRouteHandler::getParsingRNG());
200  SUMOVehicle* vehicle = vehControl.buildVehicle(newPars, route, vtype, false);
201  int quota = vehControl.getQuota();
202  if (quota > 0) {
203  vehControl.addVehicle(newPars->id, vehicle);
204  add(vehicle);
205  i->index++;
206  while (--quota > 0) {
207  SUMOVehicleParameter* quotaPars = new SUMOVehicleParameter(*pars);
208  quotaPars->id = pars->id + "." + toString(i->index);
209  quotaPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
210  SUMOVehicle* vehicle = vehControl.buildVehicle(quotaPars, route, vtype, false);
211  vehControl.addVehicle(quotaPars->id, vehicle);
212  add(vehicle);
213  i->index++;
214  }
215  } else {
216  vehControl.deleteVehicle(vehicle, true);
217  }
218  } else {
219  // strange: another vehicle with the same id already exists
221  vehControl.discountStateLoaded();
222  break;
223  }
224  throw ProcessError("Another vehicle with the id '" + newPars->id + "' exists.");
225  }
226  }
227  if (pars->repetitionsDone == pars->repetitionNumber || (pars->repetitionProbability > 0 && pars->repetitionEnd <= time)) {
228  i = myFlows.erase(i);
230  delete pars;
231  } else {
232  ++i;
233  }
234  }
236 }
237 
238 
239 int
241  return (int)myPendingEmits.size();
242 }
243 
244 
245 int
247  return (int)myFlows.size();
248 }
249 
250 
251 void
253  myAbortedEmits.insert(veh);
254 }
255 
256 
257 void
259  myPendingEmits.erase(std::remove(myPendingEmits.begin(), myPendingEmits.end(), veh), myPendingEmits.end());
260  myAllVeh.remove(veh);
261 }
262 
263 
264 void
266  //clear out the refused vehicle list, deleting the vehicles entirely
267  MSVehicleContainer::VehicleVector::iterator veh;
268  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end();) {
269  if ((*veh)->getRoute().getID() == route || route == "") {
270  myVehicleControl.deleteVehicle(*veh, true);
271  veh = myPendingEmits.erase(veh);
272  } else {
273  ++veh;
274  }
275  }
276 }
277 
278 
279 int
281  if (MSNet::getInstance()->getCurrentTimeStep() > myPendingEmitsUpdateTime) {
282  // updated pending emits (only once per time step)
283  myPendingEmitsForLane.clear();
284  for (MSVehicleContainer::VehicleVector::const_iterator veh = myPendingEmits.begin(); veh != myPendingEmits.end(); ++veh) {
285  const MSLane* lane = (*veh)->getLane();
286  if (lane != 0) {
287  myPendingEmitsForLane[lane]++;
288  } else {
289  // no (tentative) departLane was set, increase count for all
290  // lanes of the depart edge
291  const MSEdge* edge = (*veh)->getEdge();
292  const std::vector<MSLane*>& lanes = edge->getLanes();
293  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
294  myPendingEmitsForLane[*i]++;
295  }
296  }
297  }
299  }
300  return myPendingEmitsForLane[lane];
301 }
302 
303 /****************************************************************************/
304 
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)
void discountStateLoaded(bool removed=false)
avoid counting a vehicle twice if it was loaded from state and route input
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:527
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
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.
void checkCandidates(SUMOTime time, const bool preCheck)
Adds all vehicles that should have been emitted earlier to the refuse container.
double repetitionProbability
The probability for emitting a vehicle per second.
virtual const MSEdge * getEdge() const =0
Returns the edge the vehicle is currently at.
static MTRand * getParsingRNG()
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
static bool gStateLoaded
Information whether a state has been loaded.
Definition: MSGlobals.h:95
A device that performs vehicle rerouting based on current edge speeds.
int repetitionsDone
The number of times the vehicle was already inserted.
int getQuota(double frac=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
MSVehicleContainer myAllVeh
All loaded vehicles sorted by their departure time.
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:192
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:158
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
~MSInsertionControl()
Destructor.
bool anyWaitingBefore(SUMOTime time) const
Returns the information whether any vehicles want to depart before the given time.
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:56
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:310
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 getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:257
static double rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
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.
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.
int getWaitingVehicleNo() const
Returns the number of waiting vehicles.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle&#39;s parameter (including departure definition)
int getPendingFlowCount() const
Returns the number of flows that are still active.
MSVehicleControl & myVehicleControl
The assigned vehicle control (needed for vehicle re-insertion and deletion)
long long int SUMOTime
Definition: TraCIDefs.h:52
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.
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:190
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:118