Eclipse 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-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
22 // Inserts vehicles into the network when their departure time is reached
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include <iostream>
27 #include <algorithm>
28 #include <cassert>
29 #include <iterator>
33 #include "MSGlobals.h"
34 #include "MSVehicle.h"
35 #include "MSVehicleControl.h"
36 #include "MSLane.h"
37 #include "MSEdge.h"
38 #include "MSNet.h"
39 #include "MSRouteHandler.h"
40 #include "MSInsertionControl.h"
41 
42 
43 // ===========================================================================
44 // member method definitions
45 // ===========================================================================
47  SUMOTime maxDepartDelay,
48  bool eagerInsertionCheck,
49  int maxVehicleNumber,
50  SUMOTime randomDepartOffset) :
51  myVehicleControl(vc),
52  myMaxDepartDelay(maxDepartDelay),
53  myEagerInsertionCheck(eagerInsertionCheck),
54  myMaxVehicleNumber(maxVehicleNumber),
55  myPendingEmitsUpdateTime(SUMOTime_MIN) {
56  myMaxRandomDepartOffset = randomDepartOffset;
58 }
59 
60 
62  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
63  delete (i->pars);
64  }
65 }
66 
67 
68 void
70  myAllVeh.add(veh);
71 }
72 
73 
74 bool
76  const bool loadingFromState = index >= 0;
77  if (myFlowIDs.count(pars->id) > 0) {
78  if (loadingFromState) {
79  // flows loaded from simulation state must be unique
80  return false;
81  }
82  // set actual parameters for a state-loaded flow (for which only index is known)
83  for (Flow& flow : myFlows) {
84  // if the flow was loaded from state this is recognizable by having
85  // neither repetitionNumber nor repetitionProbability
86  if (flow.pars->id == pars->id && flow.pars->repetitionNumber == -1 && flow.pars->repetitionProbability == -1) {
87  if (flow.pars->wasSet(VEHPARS_FORCE_REROUTE)) {
89  }
90  delete flow.pars;
91  flow.pars = pars;
92  return true;
93  }
94  }
95  return false;
96  } else {
97  Flow flow;
98  flow.pars = pars;
99  flow.index = loadingFromState ? index : 0;
100  myFlows.push_back(flow);
101  myFlowIDs.insert(pars->id);
102  return true;
103  }
104 }
105 
106 
107 int
109  // check whether any vehicles shall be emitted within this time step
110  const bool havePreChecked = MSRoutingEngine::isEnabled();
111  if (myPendingEmits.empty() || (havePreChecked && myEmitCandidates.empty())) {
112  return 0;
113  }
114  int numEmitted = 0;
115  // we use buffering for the refused emits to save time
116  // for this, we have two lists; one contains previously refused emits, the second
117  // will be used to append those vehicles that will not be able to depart in this
118  // time step
120 
121  // go through the list of previously refused vehicles, first
122  MSVehicleContainer::VehicleVector::const_iterator veh;
123  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
124  if (havePreChecked && (myEmitCandidates.count(*veh) == 0)) {
125  refusedEmits.push_back(*veh);
126  } else {
127  numEmitted += tryInsert(time, *veh, refusedEmits);
128  }
129  }
130  myEmitCandidates.clear();
131  myPendingEmits = refusedEmits;
132  return numEmitted;
133 }
134 
135 
136 int
138  MSVehicleContainer::VehicleVector& refusedEmits) {
139  assert(veh->getParameter().depart <= time);
140  const MSEdge& edge = *veh->getEdge();
141  if (veh->isOnRoad()) {
142  return 1;
143  }
144  if ((myMaxVehicleNumber < 0 || (int)MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() < myMaxVehicleNumber)
145  && edge.insertVehicle(*veh, time, false, myEagerInsertionCheck)) {
146  // Successful insertion
147  return 1;
148  }
149  if (myMaxDepartDelay >= 0 && time - veh->getParameter().depart > myMaxDepartDelay) {
150  // remove vehicles waiting too long for departure
151  myVehicleControl.deleteVehicle(veh, true);
152  } else if (edge.isVaporizing()) {
153  // remove vehicles if the edge shall be empty
154  myVehicleControl.deleteVehicle(veh, true);
155  } else if (myAbortedEmits.count(veh) > 0) {
156  // remove vehicles which shall not be inserted for some reason
157  myAbortedEmits.erase(veh);
158  myVehicleControl.deleteVehicle(veh, true);
159  } else if ((veh->getRouteValidity(false) & (
162  myVehicleControl.deleteVehicle(veh, true);
163  } else {
164  // let the vehicle wait one step, we'll retry then
165  refusedEmits.push_back(veh);
166  }
167  edge.setLastFailedInsertionTime(time);
168  return 0;
169 }
170 
171 
172 void
173 MSInsertionControl::checkCandidates(SUMOTime time, const bool preCheck) {
174  while (myAllVeh.anyWaitingBefore(time)) {
176  copy(top.begin(), top.end(), back_inserter(myPendingEmits));
177  myAllVeh.pop();
178  }
179  if (preCheck) {
180  MSVehicleContainer::VehicleVector::const_iterator veh;
181  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end(); veh++) {
182  SUMOVehicle* const v = *veh;
183  const MSEdge* const edge = v->getEdge();
184  if (edge->insertVehicle(*v, time, true, myEagerInsertionCheck)) {
185  myEmitCandidates.insert(v);
186  } else {
187  MSDevice_Routing* dev = static_cast<MSDevice_Routing*>(v->getDevice(typeid(MSDevice_Routing)));
188  if (dev != nullptr) {
189  dev->skipRouting(time);
190  }
191  }
192  }
193  }
194 }
195 
196 
197 void
200  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end();) {
201  SUMOVehicleParameter* pars = i->pars;
202  bool tryEmitByProb = pars->repetitionProbability > 0;
203  while ((pars->repetitionProbability < 0
204  && pars->repetitionsDone < pars->repetitionNumber
205  && pars->depart + pars->repetitionsDone * pars->repetitionOffset <= time)
206  || (tryEmitByProb
207  && pars->depart <= time
208  && pars->repetitionEnd > time
209  // only call rand if all other conditions are met
211  ) {
212  tryEmitByProb = false; // only emit one per step
213  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
214  newPars->id = pars->id + "." + toString(i->index);
215  newPars->depart = pars->repetitionProbability > 0 ? time : (SUMOTime)(pars->depart + pars->repetitionsDone * pars->repetitionOffset) + computeRandomDepartOffset();
216  pars->repetitionsDone++;
217  // try to build the vehicle
218  if (vehControl.getVehicle(newPars->id) == nullptr) {
219  const MSRoute* const route = MSRoute::dictionary(pars->routeid);
220  MSVehicleType* const vtype = vehControl.getVType(pars->vtypeid, MSRouteHandler::getParsingRNG());
221  SUMOVehicle* const vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes);
222  int quota = vehControl.getQuota();
223  if (quota > 0) {
224  vehControl.addVehicle(newPars->id, vehicle);
225  add(vehicle);
226  i->index++;
227  while (--quota > 0) {
228  SUMOVehicleParameter* const quotaPars = new SUMOVehicleParameter(*pars);
229  quotaPars->id = pars->id + "." + toString(i->index);
230  quotaPars->depart = pars->repetitionProbability > 0 ? time :
232  SUMOVehicle* const quotaVehicle = vehControl.buildVehicle(quotaPars, route, vtype, !MSGlobals::gCheckRoutes);
233  vehControl.addVehicle(quotaPars->id, quotaVehicle);
234  add(quotaVehicle);
235  i->index++;
236  }
237  } else {
238  vehControl.deleteVehicle(vehicle, true);
239  }
240  } else {
243  break;
244  }
245  throw ProcessError("Another vehicle with the id '" + newPars->id + "' exists.");
246  }
247  }
248  if (pars->repetitionsDone == pars->repetitionNumber || (pars->repetitionProbability > 0 && pars->repetitionEnd <= time)) {
249  i = myFlows.erase(i);
251  delete pars;
252  } else {
253  ++i;
254  }
255  }
257 }
258 
259 
260 int
262  return (int)myPendingEmits.size();
263 }
264 
265 
266 int
268  return (int)myFlows.size();
269 }
270 
271 
272 void
274  myAbortedEmits.insert(veh);
275 }
276 
277 
278 void
280  myPendingEmits.erase(std::remove(myPendingEmits.begin(), myPendingEmits.end(), veh), myPendingEmits.end());
281  myAllVeh.remove(veh);
282 }
283 
284 
285 void
286 MSInsertionControl::clearPendingVehicles(const std::string& route) {
287  //clear out the refused vehicle list, deleting the vehicles entirely
288  MSVehicleContainer::VehicleVector::iterator veh;
289  for (veh = myPendingEmits.begin(); veh != myPendingEmits.end();) {
290  if ((*veh)->getRoute().getID() == route || route == "") {
291  myVehicleControl.deleteVehicle(*veh, true);
292  veh = myPendingEmits.erase(veh);
293  } else {
294  ++veh;
295  }
296  }
297 }
298 
299 
300 int
302  if (MSNet::getInstance()->getCurrentTimeStep() != myPendingEmitsUpdateTime) {
303  // updated pending emits (only once per time step)
304  myPendingEmitsForLane.clear();
305  for (const SUMOVehicle* const veh : myPendingEmits) {
306  const MSLane* const vlane = veh->getLane();
307  if (vlane != nullptr) {
308  myPendingEmitsForLane[vlane]++;
309  } else {
310  // no (tentative) departLane was set, increase count for all
311  // lanes of the depart edge
312  for (const MSLane* const l : veh->getEdge()->getLanes()) {
314  }
315  }
316  }
318  }
319  return myPendingEmitsForLane[lane];
320 }
321 
322 
323 void
325  // fill the public transport router with pre-parsed public transport lines
326  for (const Flow& f : myFlows) {
327  if (f.pars->line != "") {
328  const MSRoute* const route = MSRoute::dictionary(f.pars->routeid);
329  router.getNetwork()->addSchedule(*f.pars, route == nullptr ? nullptr : &route->getStops());
330  }
331  }
332 }
333 
334 
335 void
337  // save flow states
338  for (const Flow& flow : myFlows) {
340  out.writeAttr(SUMO_ATTR_ID, flow.pars->id);
341  out.writeAttr(SUMO_ATTR_INDEX, flow.index);
342  if (flow.pars->wasSet(VEHPARS_FORCE_REROUTE)) {
343  out.writeAttr(SUMO_ATTR_REROUTE, true);
344  }
345  out.closeTag();
346  }
347 }
348 
349 void
351  for (std::vector<Flow>::iterator i = myFlows.begin(); i != myFlows.end(); ++i) {
352  delete (i->pars);
353  }
354  myFlows.clear();
355  myFlowIDs.clear();
357  myPendingEmits.clear();
358  myEmitCandidates.clear();
359  myAbortedEmits.clear();
360  // myPendingEmitsForLane must not be cleared since it updates itself on the next call
361 }
362 
363 SUMOTime
365  if (myMaxRandomDepartOffset > 0) {
366  // round to the closest usable simulation step
368  } else {
369  return 0;
370  }
371 }
372 
373 
374 /****************************************************************************/
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
#define SUMOTime_MIN
Definition: SUMOTime.h:34
#define TS
Definition: SUMOTime.h:40
long long int SUMOTime
Definition: SUMOTime.h:32
const int VEHPARS_FORCE_REROUTE
@ SUMO_TAG_FLOWSTATE
a flow state definition (used when saving and loading simulatino state)
@ SUMO_ATTR_REROUTE
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_ID
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void addSchedule(const SUMOVehicleParameter &pars, const std::vector< SUMOVehicleParameter::Stop > *addStops=nullptr)
Network * getNetwork() const
@ ROUTE_START_INVALID_LANE
Definition: MSBaseVehicle.h:74
@ ROUTE_START_INVALID_PERMISSIONS
Definition: MSBaseVehicle.h:72
A device that performs vehicle rerouting based on current edge speeds.
void skipRouting(const SUMOTime currentTime)
Labels the current time step as "unroutable".
A road/street connecting two junctions.
Definition: MSEdge.h:77
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:417
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:641
void setLastFailedInsertionTime(SUMOTime time) const
Sets the last time a vehicle could not be inserted.
Definition: MSEdge.h:563
static bool gCheckRoutes
Definition: MSGlobals.h:82
static bool gStateLoaded
Information whether a state has been loaded.
Definition: MSGlobals.h:91
std::vector< Flow > myFlows
Container for periodical vehicle parameters.
int getWaitingVehicleNo() const
Returns the number of waiting vehicles.
void clearPendingVehicles(const std::string &route)
clears out all pending vehicles from a route, "" for all routes
std::map< const MSLane *, int > myPendingEmitsForLane
the number of pending emits for each edge in the current time step
int tryInsert(SUMOTime time, SUMOVehicle *veh, MSVehicleContainer::VehicleVector &refusedEmits)
Tries to emit the vehicle.
bool myEagerInsertionCheck
Whether an edge on which a vehicle could not depart should be ignored in the same step.
int emitVehicles(SUMOTime time)
Emits vehicles that want to depart at the given time.
int getPendingEmits(const MSLane *lane)
return the number of pending emits for the given lane
bool addFlow(SUMOVehicleParameter *const pars, int index=-1)
Adds parameter for a vehicle flow for departure.
SUMOTime myPendingEmitsUpdateTime
Last time at which pending emits for each edge where counted.
std::set< SUMOVehicle * > myEmitCandidates
Buffer for vehicles that may be inserted in the current step.
void alreadyDeparted(SUMOVehicle *veh)
stops trying to emit the given vehicle (because it already departed)
SUMOTime myMaxRandomDepartOffset
The maximum random offset to be added to vehicles departure times (non-negative)
MSVehicleContainer::VehicleVector myPendingEmits
Buffers for vehicles that could not be inserted.
MSInsertionControl(MSVehicleControl &vc, SUMOTime maxDepartDelay, bool checkEdgesOnce, int maxVehicleNumber, SUMOTime randomDepartOffset)
Constructor.
MSVehicleControl & myVehicleControl
The assigned vehicle control (needed for vehicle re-insertion and deletion)
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
void determineCandidates(SUMOTime time)
Checks for all vehicles whether they can be emitted.
void checkCandidates(SUMOTime time, const bool preCheck)
Adds all vehicles that should have been emitted earlier to the refuse container.
int getPendingFlowCount() const
Returns the number of flows that are still active.
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.
void adaptIntermodalRouter(MSNet::MSIntermodalRouter &router) const
void clearState()
Remove all vehicles before quick-loading state.
int myMaxVehicleNumber
Storage for maximum vehicle number.
void saveState(OutputDevice &out)
Saves the current state into the given stream.
SUMOTime myMaxDepartDelay
The maximum waiting time; vehicles waiting longer are deleted (-1: no deletion)
void descheduleDeparture(const SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
MSVehicleContainer myAllVeh
All loaded vehicles sorted by their departure time.
~MSInsertionControl()
Destructor.
SUMOTime computeRandomDepartOffset() const
compute (optional) random offset to the departure time
SumoRNG myFlowRNG
A random number generator for probabilistic flows.
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:674
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:376
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
static SumoRNG * getParsingRNG()
get parsing RNG
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:389
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:113
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition: MSRoute.cpp:194
static bool isEnabled()
returns whether any routing actions take place
bool anyWaitingBefore(SUMOTime time) const
Returns the information whether any vehicles want to depart before the given time.
void remove(SUMOVehicle *veh)
Removes a single vehicle.
void add(SUMOVehicle *veh)
Adds a single vehicle.
void pop()
Removes the uppermost vehicle vector.
std::vector< SUMOVehicle * > VehicleVector
definition of a list of vehicles which have the same departure time
void clearState()
Remove all vehicles before quick-loading state.
const VehicleVector & top()
Returns the uppermost vehicle vector.
The class responsible for building and deletion of vehicles.
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
int getQuota(double frac=-1, int loaded=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
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.
The car-following model and parameter.
Definition: MSVehicleType.h:62
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:248
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:119
static void initRandGlobal(SumoRNG *which=nullptr)
Reads the given random number options and initialises the random number generator in accordance.
Definition: RandHelper.cpp:75
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual int getRouteValidity(bool update=true, bool silent=false, std::string *msgReturn=nullptr)=0
computes validity attributes for the current route
virtual MSVehicleDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
virtual bool isOnRoad() const =0
Returns the information whether the vehicle is on a road (is simulated)
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
int repetitionsDone
The number of times the vehicle was already inserted.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
Definition of vehicle flow with the current index for vehicle numbering.
int index
the running index
SUMOVehicleParameter * pars
The parameters.