SUMO - Simulation of Urban MObility
MSInsertionControl.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
21 // Inserts vehicles into the network when their departure time is reached
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <iostream>
35 #include <algorithm>
36 #include <cassert>
37 #include <iterator>
39 #include "MSGlobals.h"
40 #include "MSVehicle.h"
41 #include "MSVehicleControl.h"
42 #include "MSLane.h"
43 #include "MSEdge.h"
44 #include "MSNet.h"
45 #include "MSRouteHandler.h"
46 #include "MSInsertionControl.h"
47 
48 
49 // ===========================================================================
50 // member method definitions
51 // ===========================================================================
53  SUMOTime maxDepartDelay,
54  bool eagerInsertionCheck,
55  int maxVehicleNumber) :
56  myVehicleControl(vc),
57  myMaxDepartDelay(maxDepartDelay),
58  myEagerInsertionCheck(eagerInsertionCheck),
59  myMaxVehicleNumber(maxVehicleNumber),
60  myPendingEmitsUpdateTime(SUMOTime_MIN) {
61 }
62 
63 
65  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
66  delete(i->pars);
67  }
68 }
69 
70 
71 void
73  myAllVeh.add(veh);
74 }
75 
76 
77 bool
79  if (myFlowIDs.count(pars->id) > 0) {
80  return false;
81  }
82  Flow flow;
83  flow.pars = pars;
84  flow.index = 0;
85  myFlows.push_back(flow);
86  myFlowIDs.insert(pars->id);
87  return true;
88 }
89 
90 
91 int
93  // check whether any vehicles shall be emitted within this time step
94  const bool havePreChecked = MSDevice_Routing::isEnabled();
95  if (myPendingEmits.empty() || (havePreChecked && myEmitCandidates.empty())) {
96  return 0;
97  }
98  int numEmitted = 0;
99  // we use buffering for the refused emits to save time
100  // for this, we have two lists; one contains previously refused emits, the second
101  // will be used to append those vehicles that will not be able to depart in this
102  // time step
104 
105  // go through the list of previously refused vehicles, first
106  MSVehicleContainer::VehicleVector::const_iterator veh;
107  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
108  if (havePreChecked && (myEmitCandidates.count(*veh) == 0)) {
109  refusedEmits.push_back(*veh);
110  } else {
111  numEmitted += tryInsert(time, *veh, refusedEmits);
112  }
113  }
114  myEmitCandidates.clear();
115  myPendingEmits = refusedEmits;
116  return numEmitted;
117 }
118 
119 
120 int
122  MSVehicleContainer::VehicleVector& refusedEmits) {
123  assert(veh->getParameter().depart < time + DELTA_T);
124  const MSEdge& edge = *veh->getEdge();
125  if (veh->isOnRoad()) {
126  return 1;
127  }
128  if ((myMaxVehicleNumber < 0 || (int)MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() < myMaxVehicleNumber)
129  && edge.insertVehicle(*veh, time, false, myEagerInsertionCheck)) {
130  // Successful insertion
131  return 1;
132  }
133  if (myMaxDepartDelay >= 0 && time - veh->getParameter().depart > myMaxDepartDelay) {
134  // remove vehicles waiting too long for departure
135  myVehicleControl.deleteVehicle(veh, true);
136  } else if (edge.isVaporizing()) {
137  // remove vehicles if the edge shall be empty
138  myVehicleControl.deleteVehicle(veh, true);
139  } else if (myAbortedEmits.count(veh) > 0) {
140  // remove vehicles which shall not be inserted for some reason
141  myAbortedEmits.erase(veh);
142  myVehicleControl.deleteVehicle(veh, true);
143  } else {
144  // let the vehicle wait one step, we'll retry then
145  refusedEmits.push_back(veh);
146  }
147  edge.setLastFailedInsertionTime(time);
148  return 0;
149 }
150 
151 
152 void
153 MSInsertionControl::checkCandidates(SUMOTime time, const bool preCheck) {
154  while (myAllVeh.anyWaitingBefore(time + DELTA_T)) {
156  copy(top.begin(), top.end(), back_inserter(myPendingEmits));
157  myAllVeh.pop();
158  }
159  if (preCheck) {
160  MSVehicleContainer::VehicleVector::const_iterator veh;
161  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
162  SUMOVehicle* const v = *veh;
163  const MSEdge* const edge = v->getEdge();
164  if (edge->insertVehicle(*v, time, true, myEagerInsertionCheck)) {
165  myEmitCandidates.insert(v);
166  } else {
167  MSDevice_Routing* dev = static_cast<MSDevice_Routing*>(v->getDevice(typeid(MSDevice_Routing)));
168  if (dev != 0) {
169  dev->skipRouting(time);
170  }
171  }
172  }
173  }
174 }
175 
176 
177 void
180  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end();) {
181  SUMOVehicleParameter* pars = i->pars;
182  bool tryEmitByProb = pars->repetitionProbability > 0;
183  while ((pars->repetitionProbability < 0
184  && pars->repetitionsDone < pars->repetitionNumber
185  && pars->depart + pars->repetitionsDone * pars->repetitionOffset < time + DELTA_T)
186  || (tryEmitByProb
187  && pars->depart < time + DELTA_T
188  && pars->repetitionEnd > time
189  // only call rand if all other conditions are met
190  && RandHelper::rand() < (pars->repetitionProbability * TS))
191  ) {
192  tryEmitByProb = false; // only emit one per step
193  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
194  newPars->id = pars->id + "." + toString(i->index);
195  newPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
196  pars->repetitionsDone++;
197  // try to build the vehicle
198  if (vehControl.getVehicle(newPars->id) == 0) {
199  const MSRoute* route = MSRoute::dictionary(pars->routeid);
200  MSVehicleType* vtype = vehControl.getVType(pars->vtypeid, MSRouteHandler::getParsingRNG());
201  SUMOVehicle* vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes);
202  int quota = vehControl.getQuota();
203  if (quota > 0) {
204  vehControl.addVehicle(newPars->id, vehicle);
205  add(vehicle);
206  i->index++;
207  while (--quota > 0) {
208  SUMOVehicleParameter* quotaPars = new SUMOVehicleParameter(*pars);
209  quotaPars->id = pars->id + "." + toString(i->index);
210  quotaPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
211  SUMOVehicle* vehicle = vehControl.buildVehicle(quotaPars, route, vtype, !MSGlobals::gCheckRoutes);
212  vehControl.addVehicle(quotaPars->id, vehicle);
213  add(vehicle);
214  i->index++;
215  }
216  } else {
217  vehControl.deleteVehicle(vehicle, true);
218  }
219  } else {
220  // strange: another vehicle with the same id already exists
222  vehControl.discountStateLoaded();
223  break;
224  }
225  throw ProcessError("Another vehicle with the id '" + newPars->id + "' exists.");
226  }
227  }
228  if (pars->repetitionsDone == pars->repetitionNumber || (pars->repetitionProbability > 0 && pars->repetitionEnd <= time)) {
229  i = myFlows.erase(i);
231  delete pars;
232  } else {
233  ++i;
234  }
235  }
237 }
238 
239 
240 int
242  return (int)myPendingEmits.size();
243 }
244 
245 
246 int
248  return (int)myFlows.size();
249 }
250 
251 
252 void
254  myAbortedEmits.insert(veh);
255 }
256 
257 
258 void
260  myPendingEmits.erase(std::remove(myPendingEmits.begin(), myPendingEmits.end(), veh), myPendingEmits.end());
261  myAllVeh.remove(veh);
262 }
263 
264 
265 void
267  //clear out the refused vehicle list, deleting the vehicles entirely
268  MSVehicleContainer::VehicleVector::iterator veh;
269  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end();) {
270  if ((*veh)->getRoute().getID() == route || route == "") {
271  myVehicleControl.deleteVehicle(*veh, true);
272  veh = myPendingEmits.erase(veh);
273  } else {
274  ++veh;
275  }
276  }
277 }
278 
279 
280 int
282  if (MSNet::getInstance()->getCurrentTimeStep() > myPendingEmitsUpdateTime) {
283  // updated pending emits (only once per time step)
284  myPendingEmitsForLane.clear();
285  for (MSVehicleContainer::VehicleVector::const_iterator veh = myPendingEmits.begin(); veh != myPendingEmits.end(); ++veh) {
286  const MSLane* lane = (*veh)->getLane();
287  if (lane != 0) {
288  myPendingEmitsForLane[lane]++;
289  } else {
290  // no (tentative) departLane was set, increase count for all
291  // lanes of the depart edge
292  const MSEdge* edge = (*veh)->getEdge();
293  const std::vector<MSLane*>& lanes = edge->getLanes();
294  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
295  myPendingEmitsForLane[*i]++;
296  }
297  }
298  }
300  }
301  return myPendingEmitsForLane[lane];
302 }
303 
304 
305 void
307  // fill the public transport router with pre-parsed public transport lines
308  for (const Flow& f : myFlows) {
309  if (f.pars->line != "") {
310  const MSRoute* route = MSRoute::dictionary(f.pars->routeid);
311  const std::vector<SUMOVehicleParameter::Stop>* addStops = 0;
312  if (route != 0) {
313  addStops = &route->getStops();
314  }
315  router.addSchedule(*f.pars, addStops);
316  }
317  }
318 }
319 
320 
321 /****************************************************************************/
std::map< const MSLane *, int > myPendingEmitsForLane
the number of pending emits for each edge in the current time step
void adaptIntermodalRouter(MSNet::MSIntermodalRouter &router) const
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:530
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
void remove(SUMOVehicle *veh)
Removes a single vehicle.
int repetitionNumber
The number of times the vehicle shall be repeatedly inserted.
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.
Definition of vehicle flow with the current index for vehicle numbering.
double repetitionProbability
The probability for emitting a vehicle per second.
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:64
virtual const MSEdge * getEdge() const =0
Returns the edge the vehicle is currently at.
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:94
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:167
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:167
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.
void skipRouting(const SUMOTime currentTime)
Labels the current time step as "unroutable".
#define TS
Definition: SUMOTime.h:51
~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:72
static std::mt19937 * getParsingRNG()
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:44
A road/street connecting two junctions.
Definition: MSEdge.h:80
void pop()
Removes the uppermost vehicle vector.
void addSchedule(const SUMOVehicleParameter &pars, const std::vector< SUMOVehicleParameter::Stop > *addStops=0)
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:66
static bool gCheckRoutes
Definition: MSGlobals.h:85
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:306
bool myEagerInsertionCheck
Whether an edge on which a vehicle could not depart should be ignored in the same step...
SUMOTime depart
The vehicle&#39;s departure time.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:253
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)
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, std::mt19937 *rng=0)
Returns the named vehicle type or a sample from the named distribution.
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:51
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 parameters.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true)
Builds a vehicle, increases the number of built vehicles.
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
std::set< const SUMOVehicle * > myAbortedEmits
Set of vehicles which shall not be inserted anymore.
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:189
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:366
void descheduleDeparture(const SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
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:117