SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
MELoop.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // The main mesocopic simulation loop
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #ifdef _MSC_VER
26 #include <windows_config.h>
27 #else
28 #include <config.h>
29 #endif
30 
31 #include <queue>
32 #include <vector>
33 #include <map>
34 #include <cmath>
35 
36 #include <microsim/MSNet.h>
37 #include <microsim/MSEdge.h>
38 #include <microsim/MSGlobals.h>
39 #include <microsim/MSLane.h>
40 #include <microsim/MSVehicle.h>
42 #include <utils/common/ToString.h>
44 #include <utils/common/SUMOTime.h>
46 #include "MELoop.h"
47 #include "MESegment.h"
48 #include "MEVehicle.h"
49 
50 #ifdef CHECK_MEMORY_LEAKS
51 #include <foreign/nvwa/debug_new.h>
52 #endif // CHECK_MEMORY_LEAKS
53 
54 
55 // ===========================================================================
56 // method definitions
57 // ===========================================================================
58 MELoop::MELoop(const SUMOTime recheckInterval) : myFullRecheckInterval(recheckInterval), myLinkRecheckInterval(TIME2STEPS(1)) {
59 }
60 
62  for (std::vector<MESegment*>::const_iterator j = myEdges2FirstSegments.begin(); j != myEdges2FirstSegments.end(); ++j) {
63  for (MESegment* s = *j; s != 0;) {
64  MESegment* n = s->getNextSegment();
65  delete s;
66  s = n;
67  }
68  }
69 }
70 
71 
72 void
74  while (!myLeaderCars.empty()) {
75  const SUMOTime time = myLeaderCars.begin()->first;
76  assert(time > tMax - DELTA_T);
77  if (time > tMax) {
78  return;
79  }
80  std::vector<MEVehicle*> vehs = myLeaderCars[time];
81  myLeaderCars.erase(time);
82  for (std::vector<MEVehicle*>::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
83  checkCar(*i);
84  assert(myLeaderCars.empty() || myLeaderCars.begin()->first >= time);
85  }
86  }
87 }
88 
89 
90 bool
91 MELoop::changeSegment(MEVehicle* veh, SUMOTime leaveTime, MESegment* const toSegment, const bool ignoreLink) {
92  MESegment* const onSegment = veh->getSegment();
93  if (MESegment::isInvalid(toSegment)) {
94  if (onSegment != 0) {
95  onSegment->send(veh, toSegment, leaveTime);
96  } else {
97  WRITE_WARNING("Vehicle '" + veh->getID() + "' teleports beyond arrival edge '" + veh->getEdge()->getID() + "', time " + time2string(leaveTime) + ".");
98  }
99  veh->setSegment(toSegment); // signal arrival
101  return true;
102  }
103  if (toSegment->hasSpaceFor(veh, leaveTime) && (ignoreLink || veh->mayProceed())) {
104  if (onSegment != 0) {
105  onSegment->send(veh, toSegment, leaveTime);
106  toSegment->receive(veh, leaveTime, false, ignoreLink);
107  } else {
108  WRITE_WARNING("Vehicle '" + veh->getID() + "' ends teleporting on edge '" + toSegment->getEdge().getID()
109  + "':" + toString(toSegment->getIndex()) + ", time " + time2string(leaveTime) + ".");
110  // this is not quite correct but suffices for interrogation by
111  // subsequent methods (veh->getSpeed() needs segment != 0)
113  toSegment->receive(veh, leaveTime, false, true);
114  }
115  return true;
116  }
117  return false;
118 }
119 
120 
121 void
123  const SUMOTime leaveTime = veh->getEventTime();
124  MESegment* const onSegment = veh->getSegment();
125  MESegment* const toSegment = nextSegment(onSegment, veh);
126  const bool teleporting = (onSegment == 0); // is the vehicle currently teleporting?
127  if (changeSegment(veh, leaveTime, toSegment, teleporting)) {
128  return;
129  }
131  teleportVehicle(veh, toSegment);
132  return;
133  }
134  if (veh->getBlockTime() == SUMOTime_MAX) {
135  veh->setBlockTime(leaveTime);
136  }
137  if (leaveTime < toSegment->getEntryBlockTime()) {
138  // receiving segment has recently received another vehicle
139  veh->setEventTime(toSegment->getEntryBlockTime());
140  } else if (toSegment->hasSpaceFor(veh, leaveTime) && !veh->mayProceed()) {
141  // either the junction is blocked or the traffic light is red
142  veh->setEventTime(leaveTime + MAX2(SUMOTime(1), myLinkRecheckInterval));
143  } else {
144  SUMOTime newEventTime = MAX3(toSegment->getEventTime() + 1, leaveTime + 1, leaveTime + myFullRecheckInterval);
145  if (MSGlobals::gTimeToGridlock > 0) {
146  // if teleporting is enabled, make sure we look at the vehicle when the the gridlock-time is up
147  newEventTime = MIN2(newEventTime, veh->getBlockTime() + MSGlobals::gTimeToGridlock + 1);
148  }
149  veh->setEventTime(newEventTime);
150  }
151  addLeaderCar(veh, onSegment->getLink(veh));
152 }
153 
154 
155 void
156 MELoop::teleportVehicle(MEVehicle* veh, MESegment* const toSegment) {
157  const SUMOTime leaveTime = veh->getEventTime();
158  MESegment* const onSegment = veh->getSegment();
159  const bool teleporting = (onSegment == 0); // is the vehicle already teleporting?
160  // try to find a place on the current edge
161  MESegment* teleSegment = toSegment->getNextSegment();
162  while (teleSegment != 0 && !teleSegment->hasSpaceFor(veh, leaveTime)) {
163  // @caution the time to get to the next segment here is ignored XXX
164  teleSegment = teleSegment->getNextSegment();
165  }
166  if (teleSegment != 0) {
167  if (!teleporting) {
168  // we managed to teleport in a single jump
169  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long, from edge '" + onSegment->getEdge().getID()
170  + "':" + toString(onSegment->getIndex())
171  + " to edge '" + teleSegment->getEdge().getID()
172  + "':" + toString(teleSegment->getIndex())
173  + ", time " + time2string(leaveTime) + ".");
175  }
176  changeSegment(veh, leaveTime, teleSegment, true);
177  teleSegment->setEntryBlockTime(leaveTime); // teleports should not block normal flow
178  } else {
179  // teleport across the current edge and try insertion later
180  if (!teleporting) {
181  // announce start of multi-step teleport, arrival will be announced in changeSegment()
182  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long, from edge '" + onSegment->getEdge().getID()
183  + "':" + toString(onSegment->getIndex()) + ", time " + time2string(leaveTime) + ".");
185  // remove from current segment
186  onSegment->send(veh, 0, leaveTime);
187  // mark veh as teleporting
188  veh->setSegment(0, 0);
189  }
190  // @caution microsim uses current travel time teleport duration
191  const SUMOTime teleArrival = leaveTime + TIME2STEPS(veh->getEdge()->getLength() / veh->getEdge()->getSpeedLimit());
192  const bool atDest = veh->moveRoutePointer();
193  if (atDest) {
194  // teleporting to end of route
195  changeSegment(veh, teleArrival, 0, true);
196  } else {
197  veh->setEventTime(teleArrival);
198  addLeaderCar(veh, 0);
199  // teleporting vehicles must react to rerouters
200  getSegmentForEdge(*veh->getEdge())->addReminders(veh);
202  }
203  }
204 }
205 
206 
207 void
209  myLeaderCars[veh->getEventTime()].push_back(veh);
210  setApproaching(veh, link);
211 }
212 
213 
214 void
216  if (link != 0) {
217  link->setApproaching(veh, veh->getEventTime() + (link->getState() == LINKSTATE_ALLWAY_STOP ?
218  (SUMOTime)RandHelper::rand((int)2) : 0), // tie braker
219  veh->getSpeed(), veh->getSpeed(), true,
220  veh->getEventTime(), veh->getSpeed(), veh->getWaitingTime(),
221  // @note: dist is not used by meso (getZipperSpeed is never called)
222  veh->getSegment()->getLength());
223  }
224 }
225 
226 
227 void
229  std::vector<MEVehicle*>& cands = myLeaderCars[v->getEventTime()];
230  cands.erase(find(cands.begin(), cands.end(), v));
231 }
232 
233 
234 MESegment*
236  if (s != 0) { // vehicle is not teleporting
237  MESegment* next = s->getNextSegment();
238  if (next != 0) {
239  // ok, the street continues
240  return next;
241  }
242  }
243  // we have to check the next edge in the vehicle's route
244  const MSEdge* nextEdge = v->succEdge(1);
245  if (nextEdge == 0) {
246  // end of route
247  return 0;
248  }
249  return myEdges2FirstSegments[nextEdge->getNumericalID()];
250 }
251 
252 
253 int
254 MELoop::numSegmentsFor(const SUMOReal length, const SUMOReal sLength) {
255  int no = (int)floor(length / sLength + 0.5);
256  if (no == 0) { // assure there is at least one segment
257  return 1;
258  } else {
259  return no;
260  }
261 }
262 
263 
264 void
266  const SUMOReal length = e.getLength();
267  int no = numSegmentsFor(length, oc.getFloat("meso-edgelength"));
268  const SUMOReal slength = length / (SUMOReal)no;
269  const SUMOReal lengthGeometryFactor = e.getLanes()[0]->getLengthGeometryFactor();
270  MESegment* newSegment = 0;
271  MESegment* nextSegment = 0;
272  bool multiQueue = oc.getBool("meso-multi-queue");
273  bool junctionControl = oc.getBool("meso-junction-control");
274  for (int s = no - 1; s >= 0; s--) {
275  std::string id = e.getID() + ":" + toString(s);
276  newSegment =
277  new MESegment(id, e, nextSegment, slength,
278  e.getLanes()[0]->getSpeedLimit(), s,
279  string2time(oc.getString("meso-tauff")), string2time(oc.getString("meso-taufj")),
280  string2time(oc.getString("meso-taujf")), string2time(oc.getString("meso-taujj")),
281  oc.getFloat("meso-jam-threshold"), multiQueue, junctionControl,
282  lengthGeometryFactor);
283  multiQueue = false;
284  junctionControl = false;
285  nextSegment = newSegment;
286  }
287  while (e.getNumericalID() >= static_cast<int>(myEdges2FirstSegments.size())) {
288  myEdges2FirstSegments.push_back(0);
289  }
290  myEdges2FirstSegments[e.getNumericalID()] = newSegment;
291 }
292 
293 
294 MESegment*
297  if (pos > 0) {
298  SUMOReal cpos = 0;
299  while (s->getNextSegment() != 0 && cpos + s->getLength() < pos) {
300  cpos += s->getLength();
301  s = s->getNextSegment();
302  }
303  }
304  return s;
305 }
306 
307 
308 /****************************************************************************/
bool changeSegment(MEVehicle *veh, SUMOTime leaveTime, MESegment *const toSegment, const bool ignoreLink=false)
change to the next segment this handles combinations of the following cases: (ending / continuing rou...
Definition: MELoop.cpp:91
MELoop(const SUMOTime recheckInterval)
SUMO constructor.
Definition: MELoop.cpp:58
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:204
long long int SUMOTime
Definition: SUMOTime.h:43
MESegment * nextSegment(MESegment *s, MEVehicle *v)
Retrieve next segment.
Definition: MELoop.cpp:235
SUMOTime getBlockTime() const
Returns the time at which the vehicle was blocked.
Definition: MEVehicle.h:254
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:52
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:192
The vehicle arrived at a junction.
~MELoop()
Definition: MELoop.cpp:61
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
SUMOTime getWaitingTime() const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:260
const SUMOTime myFullRecheckInterval
the interval at which to recheck at full segments (<=0 means asap)
Definition: MELoop.h:153
std::vector< MESegment * > myEdges2FirstSegments
mapping from internal edge ids to their initial segments
Definition: MELoop.h:150
SUMOReal getSpeed() const
Returns the vehicle's estimated speed assuming no delays.
Definition: MEVehicle.cpp:113
void buildSegmentsFor(const MSEdge &e, const OptionsCont &oc)
Build the segments for a given edge.
Definition: MELoop.cpp:265
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
void teleportVehicle(MEVehicle *veh, MESegment *const toSegment)
teleports a vehicle or continues a teleport
Definition: MELoop.cpp:156
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
T MAX2(T a, T b)
Definition: StdDefs.h:75
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:195
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
SUMOTime getEntryBlockTime() const
return the next time at which a vehicle my enter this segment
Definition: MESegment.h:361
SUMOReal getFloat(const std::string &name) const
Returns the SUMOReal-value of the named option (only for Option_Float)
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
This is an uncontrolled, all-way stop link.
const MSEdge & getEdge() const
Returns the edge this segment belongs to.
Definition: MESegment.h:272
T MAX3(T a, T b, T c)
Definition: StdDefs.h:89
void setBlockTime(const SUMOTime t)
Sets the time at which the vehicle was blocked.
Definition: MEVehicle.h:245
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
void setEntryBlockTime(SUMOTime entryBlockTime)
set the next time at which a vehicle my enter this segment
Definition: MESegment.h:366
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void removeLeaderCar(MEVehicle *v)
Removes the given car from the leading vehicles.
Definition: MELoop.cpp:228
MSLink * getLink(const MEVehicle *veh, bool tlsPenalty=false) const
Returns the link the given car will use when passing the next junction.
Definition: MESegment.cpp:386
const std::string & getID() const
Returns the id.
Definition: Named.h:66
A road/street connecting two junctions.
Definition: MSEdge.h:80
SUMOReal getLength() const
return the length of the edge
Definition: MSEdge.h:591
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MEVehicle.cpp:231
void receive(MEVehicle *veh, SUMOTime time, bool isDepart=false, bool afterTeleport=false)
Adds the vehicle to the segment, adapting its parameters.
Definition: MESegment.cpp:477
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:158
static int numSegmentsFor(const SUMOReal length, const SUMOReal slength)
Compute number of segments per edge (best value stay close to the configured segment length) ...
Definition: MELoop.cpp:254
static bool isInvalid(const MESegment *segment)
whether the given segment is 0 or encodes vaporization
Definition: MESegment.h:338
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:307
SUMOReal getLength() const
Returns the length of the segment in meters.
Definition: MESegment.h:166
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:46
std::map< SUMOTime, std::vector< MEVehicle * > > myLeaderCars
leader cars in the segments sorted by exit time
Definition: MELoop.h:147
T MIN2(T a, T b)
Definition: StdDefs.h:69
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
SUMOReal getSpeedLimit() const
Returns the speed limit of the edge The speed limit of the first lane is retured; should probably be...
Definition: MSEdge.cpp:769
void registerTeleportJam()
register one non-collision-related teleport
static void setApproaching(MEVehicle *veh, MSLink *link)
registers vehicle with the given link
Definition: MELoop.cpp:215
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:145
void scheduleVehicleRemoval(SUMOVehicle *veh)
Removes a vehicle after it has ended.
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
#define SUMOTime_MAX
Definition: SUMOTime.h:44
int getNumericalID() const
Returns the numerical id of the edge.
Definition: MSEdge.h:275
SUMOTime getEventTime() const
Returns the (planned) time at which the next vehicle leaves this segment.
Definition: MESegment.cpp:615
virtual void activateReminders(const MSMoveReminder::Notification reason)
"Activates" all current move reminder
A single mesoscopic segment (cell)
Definition: MESegment.h:57
bool hasSpaceFor(const MEVehicle *veh, SUMOTime entryTime, bool init=false) const
Returns whether the given vehicle would still fit into the segment.
Definition: MESegment.cpp:249
A storage for options typed value containers)
Definition: OptionsCont.h:99
MESegment * getSegmentForEdge(const MSEdge &e, SUMOReal pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:295
const SUMOTime myLinkRecheckInterval
the interval at which to recheck at blocked junctions (<=0 means asap)
Definition: MELoop.h:156
void checkCar(MEVehicle *veh)
Check whether the vehicle may move.
Definition: MELoop.cpp:122
static SUMOTime gTimeToGridlock
Definition: MSGlobals.h:67
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:183
int getIndex() const
Returns the running index of the segment in the edge (0 is the most upstream).
Definition: MESegment.h:150
#define SUMOReal
Definition: config.h:214
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
bool mayProceed() const
Returns whether the vehicle is allowed to pass the next junction.
Definition: MEVehicle.cpp:262
void send(MEVehicle *veh, MESegment *next, SUMOTime time)
Removes the vehicle from the segment, adapting its parameters.
Definition: MESegment.cpp:446
void simulate(SUMOTime tMax)
Perform simulation up to the given time.
Definition: MELoop.cpp:73
void addLeaderCar(MEVehicle *veh, MSLink *link)
Adds the given car to the leading vehicles.
Definition: MELoop.cpp:208
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:213
const std::string & getID() const
Returns the name of the vehicle.