SUMO - Simulation of Urban MObility
MESegment.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // A single mesoscopic segment (cell)
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2001-2017 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 <algorithm>
32 #include <limits>
33 #include <utils/common/StdDefs.h>
34 #include <microsim/MSGlobals.h>
35 #include <microsim/MSEdge.h>
36 #include <microsim/MSJunction.h>
37 #include <microsim/MSNet.h>
38 #include <microsim/MSLane.h>
39 #include <microsim/MSLinkCont.h>
40 #include <microsim/MSVehicle.h>
49 #include "MEVehicle.h"
50 #include "MELoop.h"
51 #include "MESegment.h"
52 
53 #ifdef CHECK_MEMORY_LEAKS
54 #include <foreign/nvwa/debug_new.h>
55 #endif // CHECK_MEMORY_LEAKS
56 
57 #define DEFAULT_VEH_LENGHT_WITH_GAP (SUMOVTypeParameter::getDefault().length + SUMOVTypeParameter::getDefault().minGap)
58 // avoid division by zero when driving very slowly
59 #define MESO_MIN_SPEED ((SUMOReal)0.05)
60 
61 // ===========================================================================
62 // static member defintion
63 // ===========================================================================
64 MSEdge MESegment::myDummyParent("MESegmentDummyParent", -1, MSEdge::EDGEFUNCTION_UNKNOWN, "", "", -1);
65 MESegment MESegment::myVaporizationTarget("vaporizationTarget");
67 
68 // ===========================================================================
69 // method definitions
70 // ===========================================================================
71 MESegment::MESegment(const std::string& id,
72  const MSEdge& parent, MESegment* next,
73  SUMOReal length, SUMOReal speed,
74  int idx,
75  SUMOTime tauff, SUMOTime taufj,
76  SUMOTime taujf, SUMOTime taujj,
77  SUMOReal jamThresh, bool multiQueue, bool junctionControl) :
78  Named(id), myEdge(parent), myNextSegment(next),
79  myLength(length), myIndex(idx),
80  myTau_ff((SUMOTime)(tauff / parent.getLanes().size())),
81  myTau_fj((SUMOTime)(taufj / parent.getLanes().size())), // Eissfeldt p. 90 and 151 ff.
82  myTau_jf((SUMOTime)(taujf / parent.getLanes().size())),
83  myTau_jj((SUMOTime)(taujj / parent.getLanes().size())),
84  myTau_length(MAX2(MESO_MIN_SPEED, speed) * parent.getLanes().size() / TIME2STEPS(1)),
85  myHeadwayCapacity(length / DEFAULT_VEH_LENGHT_WITH_GAP * parent.getLanes().size())/* Eissfeldt p. 69 */,
86  myCapacity(length * parent.getLanes().size()),
87  myOccupancy(0.f),
88  myJunctionControl(junctionControl),
89  myTLSPenalty(MSGlobals::gMesoTLSPenalty > 0 &&
90  // only apply to the last segment of a tls-controlled edge
91  myNextSegment == 0 && (
92  parent.getToJunction()->getType() == NODETYPE_TRAFFIC_LIGHT ||
93  parent.getToJunction()->getType() == NODETYPE_TRAFFIC_LIGHT_NOJUNCTION ||
94  parent.getToJunction()->getType() == NODETYPE_TRAFFIC_LIGHT_RIGHT_ON_RED)),
95  myMinorPenalty(MSGlobals::gMesoMinorPenalty > 0 &&
96  // only apply to the last segment of an uncontrolled edge that has at least 1 minor link
97  myNextSegment == 0 &&
98  parent.getToJunction()->getType() != NODETYPE_TRAFFIC_LIGHT &&
99  parent.getToJunction()->getType() != NODETYPE_TRAFFIC_LIGHT_NOJUNCTION &&
100  parent.getToJunction()->getType() != NODETYPE_TRAFFIC_LIGHT_RIGHT_ON_RED &&
101  parent.hasMinorLink()),
102  myEntryBlockTime(SUMOTime_MIN),
103  myLastHeadway(TIME2STEPS(-1)),
104  myMeanSpeed(speed),
105  myLastMeanSpeedUpdate(SUMOTime_MIN) {
106  myCarQues.push_back(std::vector<MEVehicle*>());
107  myBlockTimes.push_back(-1);
108  if (useMultiQueue(multiQueue, parent)) {
109  const std::vector<MSLane*>& lanes = parent.getLanes();
110  while (myCarQues.size() < lanes.size()) {
111  myCarQues.push_back(std::vector<MEVehicle*>());
112  myBlockTimes.push_back(-1);
113  }
114  for (int i = 0; i < (int)parent.getNumSuccessors(); ++i) {
115  const MSEdge* const edge = parent.getSuccessors()[i];
116  const std::vector<MSLane*>* const allowed = parent.allowedLanes(*edge);
117  assert(allowed != 0);
118  assert(allowed->size() > 0);
119  for (std::vector<MSLane*>::const_iterator j = allowed->begin(); j != allowed->end(); ++j) {
120  std::vector<MSLane*>::const_iterator it = find(lanes.begin(), lanes.end(), *j);
121  myFollowerMap[edge].push_back((int)distance(lanes.begin(), it));
122  }
123  }
124  }
125  recomputeJamThreshold(jamThresh);
126 }
127 
128 
129 MESegment::MESegment(const std::string& id):
130  Named(id),
131  myEdge(myDummyParent), // arbitrary edge needed to supply the needed reference
132  myNextSegment(0), myLength(0), myIndex(0),
133  myTau_ff(0), myTau_fj(0), myTau_jf(0), myTau_jj(0), myTau_length(1),
135  myTLSPenalty(false),
136  myMinorPenalty(false) {
137 }
138 
139 
140 bool
141 MESegment::useMultiQueue(bool multiQueue, const MSEdge& parent) {
142  return multiQueue && parent.getLanes().size() > 1 && parent.getNumSuccessors() > 1;
143 }
144 
145 void
147  if (jamThresh == DO_NOT_PATCH_JAM_THRESHOLD) {
148  return;
149  }
150  if (jamThresh < 0) {
151  // compute based on speed
152  SUMOReal speed = myEdge.getSpeedLimit();
153  if (myTLSPenalty || myMinorPenalty) {
154  SUMOReal travelTime = myLength / MAX2(speed, NUMERICAL_EPS) + getMaxPenaltySeconds();
155  speed = myLength / travelTime;
156  }
157  myJamThreshold = jamThresholdForSpeed(speed, jamThresh);
158  } else {
159  // compute based on specified percentage
160  myJamThreshold = jamThresh * myCapacity;
161  }
162 
163  // update coefficients for the jam-jam headway function
164  // this function models the effect that "empty space" needs to move
165  // backwards through the downstream segment before the upstream segment may
166  // send annother vehicle.
167  // this allows jams to clear and move upstream.
168  // the headway function f(x) depends on the number of vehicles in the
169  // downstream segment x
170  // f is a linear function that passes through the following fixed points:
171  // f(n_jam_threshold) = tau_jf_withLength (for continuity)
172  // f(myHeadwayCapacity) = myTau_jj * myHeadwayCapacity
173 
175  if (myJamThreshold < myCapacity) {
176  // jamming is possible
177  const SUMOReal n_jam_threshold = myHeadwayCapacity * myJamThreshold / myCapacity; // number of vehicles above which the segment is jammed
178  // solving f(x) = a * x + b
179  myA = (STEPS2TIME(myTau_jj) * myHeadwayCapacity - STEPS2TIME(tau_jf_withLength)) / (myHeadwayCapacity - n_jam_threshold);
181 
182  // note that the original Eissfeldt model (p. 69) used different fixed points
183  // f(n_jam_threshold) = n_jam_threshold * myTau_jj
184  // f(myHeadwayCapacity) = myTau_jf * myHeadwayCapacity
185  //
186  // However, this systematically underestimates the backpropagation speed of the jam front (see #2244)
187  } else {
188  // dummy values. Should not be used
189  myA = 0;
190  myB = STEPS2TIME(tau_jf_withLength);
191  }
192 }
193 
194 
195 SUMOReal
197  // vehicles driving freely at maximum speed should not jam
198  // we compute how many vehicles could possible enter the segment until the first vehicle leaves
199  // and multiply by the space these vehicles would occupy
200  // the jamThresh parameter is scale the resulting value
201  if (speed == 0) {
202  return std::numeric_limits<double>::max(); // never jam. Irrelevant at speed 0 anyway
203  }
205 }
206 
207 
208 void
210  myDetectorData.push_back(data);
211  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
212  for (std::vector<MEVehicle*>::const_reverse_iterator i = k->rbegin(); i != k->rend(); ++i) {
213  (*i)->addReminder(data);
214  }
215  }
216 }
217 
218 
219 void
221  std::vector<MSMoveReminder*>::iterator it = find(
222  myDetectorData.begin(), myDetectorData.end(), data);
223  if (it != myDetectorData.end()) {
224  myDetectorData.erase(it);
225  }
226  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
227  for (std::vector<MEVehicle*>::const_reverse_iterator i = k->rbegin(); i != k->rend(); ++i) {
228  (*i)->removeReminder(data);
229  }
230  }
231 }
232 
233 
234 void
237  if (next == 0) {
239  } else if (next == &myVaporizationTarget) {
241  } else if (myNextSegment == 0) {
243  } else {
245  }
246  v->updateDetectors(currentTime, true, reason);
247 }
248 
249 
250 void
252  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
253  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
254  SUMOTime earliestExitTime = currentTime;
255  for (std::vector<MEVehicle*>::const_reverse_iterator i = k->rbegin(); i != k->rend(); ++i) {
256  const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
257  (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
258  earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap());
259  }
260  }
261 }
262 
263 
264 bool
265 MESegment::hasSpaceFor(const MEVehicle* veh, SUMOTime entryTime, bool init) const {
266  if (myOccupancy == 0.) {
267  // we have always space for at least one vehicle
268  return true;
269  }
270  const SUMOReal newOccupancy = myOccupancy + veh->getVehicleType().getLengthWithGap();
271  if (newOccupancy > myCapacity) {
272  // we must ensure that occupancy remains below capacity
273  return false;
274  }
275  // regular insertions and initial insertions must respect different constraints:
276  // - regular insertions must respect entryBlockTime
277  // - initial insertions should not cause additional jamming
278  // - inserted vehicle should be able to continue at the current speed
279  if (init) {
280  if (free() && !hasBlockedLeader()) {
281  return newOccupancy <= myJamThreshold;
282  } else {
283  return newOccupancy <= jamThresholdForSpeed(getMeanSpeed(false), -1);
284  }
285  }
286  // maintain propper spacing between inflow from different lanes
287  return entryTime >= myEntryBlockTime;
288 }
289 
290 
291 bool
293  if (hasSpaceFor(veh, time, true)) {
294  receive(veh, time, true);
295  // we can check only after insertion because insertion may change the route via devices
296  std::string msg;
297  if (MSGlobals::gCheckRoutes && !veh->hasValidRoute(msg)) {
298  throw ProcessError("Vehicle '" + veh->getID() + "' has no valid route. " + msg);
299  }
300  return true;
301  }
302  return false;
303 }
304 
305 
306 int
308  int total = 0;
309  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
310  total += (int)k->size();
311  }
312  return total;
313 }
314 
315 
316 SUMOReal
317 MESegment::getMeanSpeed(bool useCached) const {
318  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
319  if (currentTime != myLastMeanSpeedUpdate || !useCached) {
320  myLastMeanSpeedUpdate = currentTime;
321  const SUMOTime tau = free() ? myTau_ff : myTau_jf;
322  SUMOReal v = 0;
323  int count = 0;
324  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
325  SUMOTime earliestExitTime = currentTime;
326  count += (int)k->size();
327  for (std::vector<MEVehicle*>::const_reverse_iterator veh = k->rbegin(); veh != k->rend(); ++veh) {
328  v += (*veh)->getConservativeSpeed(earliestExitTime); // earliestExitTime is updated!
329  earliestExitTime += tauWithVehLength(tau, (*veh)->getVehicleType().getLengthWithGap());
330  }
331  }
332  if (count == 0) {
334  } else {
335  myMeanSpeed = v / (SUMOReal) count;
336  }
337  }
338  return myMeanSpeed;
339 }
340 
341 
342 void
344  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
345  for (std::vector<MEVehicle*>::const_iterator veh = k->begin(); veh != k->end(); ++veh) {
346  MSXMLRawOut::writeVehicle(of, *(*veh));
347  }
348  }
349 }
350 
351 
352 MEVehicle*
355  std::vector<MEVehicle*>& cars = myCarQues[v->getQueIndex()];
356  assert(std::find(cars.begin(), cars.end(), v) != cars.end());
357  // One could be tempted to do v->setSegment(next); here but position on lane will be invalid if next == 0
358  updateDetectorsOnLeave(v, leaveTime, next);
359  myEdge.lock();
360  if (v == cars.back()) {
361  cars.pop_back();
362  if (!cars.empty()) {
363  myEdge.unlock();
364  return cars.back();
365  }
366  } else {
367  cars.erase(std::find(cars.begin(), cars.end(), v));
368  }
369  myEdge.unlock();
370  return 0;
371 }
372 
373 
374 SUMOTime
376  const SUMOTime tau = (pred->free()
377  ? (free() ? myTau_ff : myTau_fj)
378  : (free() ? myTau_jf : TIME2STEPS(myA * getCarNumber() + myB)));
379  return (SUMOTime)(tauWithVehLength(tau, veh->getVehicleType().getLengthWithGap()) / pred->getTLSCapacity(veh));
380 }
381 
382 
383 SUMOTime
385  // since we do not know which queue will be used we give a conservative estimate
386  SUMOTime earliestLeave = earliestEntry;
387  for (int i = 0; i < (int)myCarQues.size(); ++i) {
388  earliestLeave = MAX2(earliestLeave, myBlockTimes[i]);
389  }
390  if (myEdge.getSpeedLimit() == 0) {
391  return MAX2(earliestEntry, myEntryBlockTime); // FIXME: This line is just an adhoc-fix to avoid division by zero (Leo)
392  } else {
393  return MAX3(earliestEntry, earliestLeave - TIME2STEPS(myLength / myEdge.getSpeedLimit()), myEntryBlockTime);
394  }
395 }
396 
397 
398 MSLink*
399 MESegment::getLink(const MEVehicle* veh, bool penalty) const {
400  if (myJunctionControl || penalty) {
401  const MSEdge* const nextEdge = veh->succEdge(1);
402  if (nextEdge == 0) {
403  return 0;
404  }
405  // try to find any link leading to our next edge, start with the lane pointed to by the que index
406  const MSLane* const bestLane = myEdge.getLanes()[veh->getQueIndex()];
407  const MSLinkCont& links = bestLane->getLinkCont();
408  for (std::vector<MSLink*>::const_iterator j = links.begin(); j != links.end(); ++j) {
409  if (&(*j)->getLane()->getEdge() == nextEdge) {
410  return *j;
411  }
412  }
413  // this is for the non-multique case, maybe we should use caching here !!!
414  for (std::vector<MSLane*>::const_iterator l = myEdge.getLanes().begin(); l != myEdge.getLanes().end(); ++l) {
415  if ((*l) != bestLane) {
416  const MSLinkCont& links = (*l)->getLinkCont();
417  for (std::vector<MSLink*>::const_iterator j = links.begin(); j != links.end(); ++j) {
418  if (&(*j)->getLane()->getEdge() == nextEdge) {
419  return *j;
420  }
421  }
422  }
423  }
424  }
425  return 0;
426 }
427 
428 
429 bool
430 MESegment::isOpen(const MEVehicle* veh) const {
431  if (myTLSPenalty) {
432  // XXX should limited control take precedence over tls penalty?
433  return true;
434  }
435  const MSLink* link = getLink(veh);
436  return (link == 0
437  || link->havePriority()
438  || limitedControlOverride(link)
439  || link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
442 }
443 
444 
445 bool
447  assert(link != 0);
449  return false;
450  }
451  // if the target segment of this link is not saturated junction control is disabled
452  const MSEdge& targetEdge = link->getLane()->getEdge();
453  const MESegment* target = MSGlobals::gMesoNet->getSegmentForEdge(targetEdge);
454  return target->myOccupancy * 2 < target->myJamThreshold;
455 }
456 
457 
458 void
460  assert(isInvalid(next) || time >= myBlockTimes[veh->getQueIndex()]);
461  MSLink* link = getLink(veh);
462  if (link != 0) {
463  link->removeApproaching(veh);
464  }
465  MEVehicle* lc = removeCar(veh, time, next); // new leaderCar
466  myBlockTimes[veh->getQueIndex()] = time;
467  if (!isInvalid(next)) {
468  myLastHeadway = next->getTimeHeadway(this, veh);
470  }
471  if (lc != 0) {
474  }
475 }
476 
477 bool
480 }
481 
482 
483 void
485  for (std::vector<MSMoveReminder*>::const_iterator i = myDetectorData.begin(); i != myDetectorData.end(); ++i) {
486  veh->addReminder(*i);
487  }
488 }
489 
490 void
491 MESegment::receive(MEVehicle* veh, SUMOTime time, bool isDepart, bool afterTeleport) {
492  const SUMOReal speed = isDepart ? -1 : MAX2(veh->getSpeed(), MESO_MIN_SPEED); // on the previous segment
493  veh->setSegment(this); // for arrival checking
494  veh->setLastEntryTime(time);
496  if (!isDepart && (
497  // arrival on entering a new edge
498  ((myIndex == 0 || afterTeleport) && veh->moveRoutePointer())
499  // arrival on entering a new segment
500  || veh->hasArrived())) {
501  // route has ended
502  veh->setEventTime(time + TIME2STEPS(myLength / speed)); // for correct arrival speed
503  addReminders(veh);
505  updateDetectorsOnLeave(veh, time, 0);
507  return;
508  }
509  // route continues
510  const SUMOReal maxSpeedOnEdge = veh->getEdge()->getVehicleMaxSpeed(veh);
511  const SUMOReal uspeed = MAX2(maxSpeedOnEdge, MESO_MIN_SPEED);
512  int nextQueIndex = 0;
513  if (myCarQues.size() > 1) {
514  const MSEdge* succ = veh->succEdge(1);
515  // succ may be invalid if called from initialise() with an invalid route
516  if (succ != 0 && myFollowerMap.count(succ) > 0) {
517  const std::vector<int>& indices = myFollowerMap[succ];
518  nextQueIndex = indices[0];
519  for (std::vector<int>::const_iterator i = indices.begin() + 1; i != indices.end(); ++i) {
520  if (myCarQues[*i].size() < myCarQues[nextQueIndex].size()) {
521  nextQueIndex = *i;
522  }
523  }
524  }
525  }
526  std::vector<MEVehicle*>& cars = myCarQues[nextQueIndex];
527  MEVehicle* newLeader = 0; // first vehicle in the current queue
528  SUMOTime tleave = MAX2(time + TIME2STEPS(myLength / uspeed) + veh->getStoptime(this) + getLinkPenalty(veh), myBlockTimes[nextQueIndex]);
529  myEdge.lock();
530  if (cars.empty()) {
531  cars.push_back(veh);
532  newLeader = veh;
533  } else {
534  SUMOTime leaderOut = cars[0]->getEventTime();
535  if (!isDepart && leaderOut > tleave && overtake()) {
536  if (cars.size() == 1) {
538  newLeader = veh;
539  }
540  cars.insert(cars.begin() + 1, veh);
541  } else {
542  tleave = MAX2(leaderOut + tauWithVehLength(myTau_ff, cars[0]->getVehicleType().getLengthWithGap()), tleave);
543  cars.insert(cars.begin(), veh);
544  }
545  }
546  myEdge.unlock();
547  if (!isDepart) {
548  // regular departs could take place anywhere on the edge so they should not block regular flow
549  // the -1 facilitates interleaving of multiple streams
551  }
552  veh->setEventTime(tleave);
553  veh->setSegment(this, nextQueIndex);
555  addReminders(veh);
556  if (isDepart) {
557  veh->onDepart();
559  } else if (myIndex == 0 || afterTeleport) {
561  } else {
563  }
564  if (newLeader != 0) {
565  MSGlobals::gMesoNet->addLeaderCar(newLeader, getLink(newLeader));
566  }
567 }
568 
569 
570 bool
572  MEVehicle* remove = 0;
573  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
574  if (!k->empty()) {
575  // remove last in queue
576  remove = k->front();
577  if (k->size() == 1) {
579  }
581  return true;
582  }
583  }
584  return false;
585 }
586 
587 
588 void
589 MESegment::setSpeedForQueue(SUMOReal newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector<MEVehicle*>& vehs) {
590  MEVehicle* v = vehs.back();
591  v->updateDetectors(currentTime, false);
592  SUMOTime newEvent = MAX2(newArrival(v, newSpeed, currentTime), blockTime);
593  if (v->getEventTime() != newEvent) {
595  v->setEventTime(newEvent);
597  }
598  for (std::vector<MEVehicle*>::const_reverse_iterator i = vehs.rbegin() + 1; i != vehs.rend(); ++i) {
599  (*i)->updateDetectors(currentTime, false);
600  newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff);
601  //newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff + (SUMOTime)((*(i - 1))->getVehicleType().getLength() / myTau_length));
602  (*i)->setEventTime(newEvent);
603  }
604 }
605 
606 
607 SUMOTime
608 MESegment::newArrival(const MEVehicle* const v, SUMOReal newSpeed, SUMOTime currentTime) {
609  // since speed is only an upper bound pos may be to optimistic
610  const SUMOReal pos = MIN2(myLength, STEPS2TIME(currentTime - v->getLastEntryTime()) * v->getSpeed());
611  // traveltime may not be 0
612  return currentTime + MAX2(TIME2STEPS((myLength - pos) / newSpeed), SUMOTime(1));
613 }
614 
615 
616 void
617 MESegment::setSpeed(SUMOReal newSpeed, SUMOTime currentTime, SUMOReal jamThresh) {
618  recomputeJamThreshold(jamThresh);
619  //myTau_length = MAX2(MESO_MIN_SPEED, newSpeed) * myEdge.getLanes().size() / TIME2STEPS(1);
620  for (int i = 0; i < (int)myCarQues.size(); ++i) {
621  if (myCarQues[i].size() != 0) {
622  setSpeedForQueue(newSpeed, currentTime, myBlockTimes[i], myCarQues[i]);
623  }
624  }
625 }
626 
627 
628 SUMOTime
630  SUMOTime result = SUMOTime_MAX;
631  for (int i = 0; i < (int)myCarQues.size(); ++i) {
632  if (myCarQues[i].size() != 0 && myCarQues[i].back()->getEventTime() < result) {
633  result = myCarQues[i].back()->getEventTime();
634  }
635  }
636  if (result < SUMOTime_MAX) {
637  return result;
638  }
639  return -1;
640 }
641 
642 
643 void
646  for (int i = 0; i < (int)myCarQues.size(); ++i) {
649  out.closeTag();
650  }
651  out.closeTag();
652 }
653 
654 
655 void
656 MESegment::loadState(std::vector<std::string>& vehIds, MSVehicleControl& vc, const SUMOTime block, const int queIdx) {
657  for (std::vector<std::string>::const_iterator it = vehIds.begin(); it != vehIds.end(); ++it) {
658  MEVehicle* v = static_cast<MEVehicle*>(vc.getVehicle(*it));
659  assert(v != 0);
660  assert(v->getSegment() == this);
661  myCarQues[queIdx].push_back(v);
663  }
664  if (myCarQues[queIdx].size() != 0) {
665  // add the last vehicle of this queue
666  // !!! one question - what about the previously added vehicle? Is it stored twice?
667  MEVehicle* veh = myCarQues[queIdx].back();
669  }
670  myBlockTimes[queIdx] = block;
672 }
673 
674 
675 std::vector<const MEVehicle*>
677  std::vector<const MEVehicle*> result;
678  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
679  result.insert(result.end(), k->begin(), k->end());
680  }
681  return result;
682 }
683 
684 
685 bool
687  for (Queues::const_iterator k = myCarQues.begin(); k != myCarQues.end(); ++k) {
688  if (k->size() > 0 && (*k).back()->getWaitingTime() > 0) {
689  return true;
690  }
691  }
692  return false;
693 }
694 
695 
696 SUMOReal
698  return 3600 * getCarNumber() * getMeanSpeed() / myLength;
699 }
700 
701 
702 SUMOTime
704  const MSLink* link = getLink(veh, myTLSPenalty || myMinorPenalty);
705  if (link != 0) {
706  SUMOTime result = 0;
707  if (link->isTLSControlled()) {
708  result += link->getMesoTLSPenalty();
709  }
710  // minor tls links may get an additional penalty
711  if (!link->havePriority() &&
712  // do not apply penalty if limited control is active
715  }
716  return result;
717  } else {
718  return 0;
719  }
720 }
721 
722 
723 SUMOReal
725  if (myTLSPenalty) {
726  const MSLink* link = getLink(veh, true);
727  if (link != 0) {
728  assert(link->isTLSControlled());
729  assert(link->getGreenFraction() > 0);
730  return link->getGreenFraction();
731  }
732  }
733  return 1;
734 }
735 
736 
737 SUMOReal
739  SUMOReal maxPenalty = 0;
740  for (std::vector<MSLane*>::const_iterator i = myEdge.getLanes().begin(); i != myEdge.getLanes().end(); ++i) {
741  MSLane* l = *i;
742  const MSLinkCont& lc = l->getLinkCont();
743  for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) {
744  MSLink* link = *j;
745  maxPenalty = MAX2(maxPenalty, STEPS2TIME(
746  link->getMesoTLSPenalty() + (link->havePriority() ? 0 : MSGlobals::gMesoMinorPenalty)));
747  }
748  }
749  return maxPenalty;
750 }
751 
752 /****************************************************************************/
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
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
static MESegment myVaporizationTarget
Definition: MESegment.h:508
SUMOReal getTLSCapacity(const MEVehicle *veh) const
Returns the average green time as fraction of cycle time.
Definition: MESegment.cpp:724
segment of a lane
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:571
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:216
long long int SUMOTime
Definition: SUMOTime.h:43
SUMOReal getFlow() const
returns flow based on headway
Definition: MESegment.cpp:697
const SUMOReal myCapacity
The number of lanes * the length.
Definition: MESegment.h:468
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge) ...
Definition: MEVehicle.cpp:159
std::vector< const MEVehicle * > getVehicles() const
returns all vehicles (for debugging)
Definition: MESegment.cpp:676
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:52
const bool myMinorPenalty
Whether minor penalty is enabled.
Definition: MESegment.h:480
MEVehicle * removeCar(MEVehicle *v, SUMOTime leaveTime, MESegment *next)
Removes the given car from the edge&#39;s que.
Definition: MESegment.cpp:353
SUMOReal jamThresholdForSpeed(SUMOReal speed, SUMOReal jamThresh) const
compute jam threshold for the given speed and jam-threshold option
Definition: MESegment.cpp:196
bool overtake()
Definition: MESegment.cpp:478
bool initialise(MEVehicle *veh, SUMOTime time)
Inserts (emits) vehicle into the segment.
Definition: MESegment.cpp:292
bool limitedControlOverride(const MSLink *link) const
whether the given link may be passed because the option meso-junction-control.limited is set ...
Definition: MESegment.cpp:446
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:192
SUMOReal getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
SUMOReal getImpatience() const
Returns this vehicles impatience.
The vehicle arrived at a junction.
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition: MSEdge.h:653
SUMOTime getStoptime(const MESegment *const seg) const
Returns how long to stop at the given segment.
Definition: MEVehicle.cpp:244
SUMOTime myEntryBlockTime
Definition: MESegment.h:500
static const SUMOReal DO_NOT_PATCH_JAM_THRESHOLD
Definition: MESegment.h:379
SUMOTime getWaitingTime() const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:272
SUMOReal getSpeed() const
Returns the vehicle&#39;s estimated speed assuming no delays.
Definition: MEVehicle.cpp:113
Notification
Definition of a vehicle state.
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
std::vector< MSMoveReminder * > myDetectorData
The data collection for all kinds of detectors.
Definition: MESegment.h:486
SUMOReal myOccupancy
The occupied space (in m) on the segment.
Definition: MESegment.h:471
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
static bool useMultiQueue(bool multiQueue, const MSEdge &parent)
whether the segment requires use of multiple queues
Definition: MESegment.cpp:141
T MAX2(T a, T b)
Definition: StdDefs.h:70
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:207
SUMOReal getMeanSpeed() const
wrapper to satisfy the FunctionBinding signature
Definition: MESegment.h:206
SUMOTime newArrival(const MEVehicle *const v, SUMOReal newSpeed, SUMOTime currentTime)
compute the new arrival time when switching speed
Definition: MESegment.cpp:608
The vehicle got vaporized.
The vehicle changes the segment (meso only)
void setSpeedForQueue(SUMOReal newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector< MEVehicle * > &vehs)
Definition: MESegment.cpp:589
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
bool hasBlockedLeader() const
whether a leader in any queue is blocked
Definition: MESegment.cpp:686
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:255
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition: MEVehicle.h:249
static bool gMesoOvertaking
Definition: MSGlobals.h:101
bool hasValidRoute(std::string &msg, const MSRoute *route=0) const
Validates the current or given route.
T MAX3(T a, T b, T c)
Definition: StdDefs.h:84
void setBlockTime(const SUMOTime t)
Sets the time at which the vehicle was blocked.
Definition: MEVehicle.h:257
The purpose of the edge is not known.
Definition: MSEdge.h:91
Queues myCarQues
The car queues. Vehicles are inserted in the front and removed in the back.
Definition: MESegment.h:489
const MSCFModel & getCarFollowModel() const
Returns the vehicle type&#39;s car following model definition (const version)
void loadState(std::vector< std::string > &vehIDs, MSVehicleControl &vc, const SUMOTime blockTime, const int queIdx)
Loads the state of this segment with the given parameters.
Definition: MESegment.cpp:656
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:399
#define SUMOTime_MIN
Definition: SUMOTime.h:45
A road/street connecting two junctions.
Definition: MSEdge.h:80
const SUMOReal myHeadwayCapacity
The capacity of the segment in number of cars, used only in time headway calculation This parameter h...
Definition: MESegment.h:465
#define max(a, b)
Definition: polyfonts.c:65
void receive(MEVehicle *veh, SUMOTime time, bool isDepart=false, bool afterTeleport=false)
Adds the vehicle to the segment, adapting its parameters.
Definition: MESegment.cpp:491
void writeVehicles(OutputDevice &of) const
Definition: MESegment.cpp:343
static bool gCheckRoutes
Definition: MSGlobals.h:83
SUMOTime myLastMeanSpeedUpdate
the time at which myMeanSpeed was last updated
Definition: MESegment.h:514
SUMOTime getLinkPenalty(const MEVehicle *veh) const
Returns the penalty time for passing a link (if using gMesoTLSPenalty > 0 or gMesoMinorPenalty > 0) ...
Definition: MESegment.cpp:703
std::map< const MSEdge *, std::vector< int > > myFollowerMap
The follower edge to que index mapping for multi queue segments.
Definition: MESegment.h:492
bool free() const
return whether this segment is considered free as opposed to jammed
Definition: MESegment.h:351
const SUMOTime myTau_jf
Definition: MESegment.h:456
static bool isInvalid(const MESegment *segment)
whether the given segment is 0 or encodes vaporization
Definition: MESegment.h:342
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:308
static MSEdge myDummyParent
Definition: MESegment.h:507
void setLastEntryTime(SUMOTime t)
Sets the entry time for the current segment.
Definition: MEVehicle.h:241
void updateDetectorsOnLeave(MEVehicle *v, SUMOTime currentTime, MESegment *next)
Updates data of all detectors for a leaving vehicle.
Definition: MESegment.cpp:235
The vehicle arrived at its destination (is deleted)
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
SUMOReal myTau_length
Headway parameter for computing gross time headyway from net time headway, length and edge speed...
Definition: MESegment.h:458
int getNumSuccessors() const
Returns the number of edges that may be reached from this edge.
Definition: MSEdge.h:332
static SUMOTime gMesoMinorPenalty
Definition: MSGlobals.h:107
T MIN2(T a, T b)
Definition: StdDefs.h:64
const SUMOReal myLength
The segment&#39;s length.
Definition: MESegment.h:450
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:209
Something on a lane to be noticed about vehicle movement.
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
bool vaporizeAnyCar(SUMOTime currentTime)
tries to remove any car from this segment
Definition: MESegment.cpp:571
SUMOReal myJamThreshold
The space (in m) which needs to be occupied before the segment is considered jammed.
Definition: MESegment.h:483
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:789
void removeDetector(MSMoveReminder *data)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:220
Base class for objects which have an id.
Definition: Named.h:46
bool isOpen(const MEVehicle *veh) const
Returns whether the vehicle may use the next link.
Definition: MESegment.cpp:430
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:145
const MSEdge & myEdge
The microsim edge this segment belongs to.
Definition: MESegment.h:444
SUMOReal myA
slope and axis offset for the jam-jam headway function
Definition: MESegment.h:461
const SUMOTime myTau_jj
Definition: MESegment.h:456
void setSpeed(SUMOReal newSpeed, SUMOTime currentTime, SUMOReal jamThresh=DO_NOT_PATCH_JAM_THRESHOLD)
reset mySpeed and patch the speed of all vehicles in it. Also set/recompute myJamThreshold ...
Definition: MESegment.cpp:617
trigger: the time of the step
The vehicle has departed (was inserted into the network)
void scheduleVehicleRemoval(SUMOVehicle *veh)
Removes a vehicle after it has ended.
const bool myTLSPenalty
Whether tls penalty is enabled.
Definition: MESegment.h:477
MESegment * myNextSegment
The next segment of this edge, 0 if this is the last segment of this edge.
Definition: MESegment.h:447
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs&#39;th successor of edge the vehicle is currently at.
#define SUMOTime_MAX
Definition: SUMOTime.h:44
virtual void unlock() const
release exclusive access to the mesoscopic state
Definition: MSEdge.h:656
SUMOReal myB
Definition: MESegment.h:461
SUMOTime getEventTime() const
Returns the (planned) time at which the next vehicle leaves this segment.
Definition: MESegment.cpp:629
SUMOTime myLastHeadway
the last headway
Definition: MESegment.h:503
virtual void activateReminders(const MSMoveReminder::Notification reason)
"Activates" all current move reminder
A single mesoscopic segment (cell)
Definition: MESegment.h:57
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:299
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:265
void onDepart()
Called when the vehicle is inserted into the network.
void updateDetectors(SUMOTime currentTime, const bool isLeave, const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_JUNCTION)
Updates all vehicle detectors.
Definition: MEVehicle.cpp:297
int getQueIndex() const
Returns the index of the que the vehicle is in.
Definition: MEVehicle.h:233
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
MESegment * getSegmentForEdge(const MSEdge &e, SUMOReal pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:293
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:110
const bool myJunctionControl
Whether junction control is enabled.
Definition: MESegment.h:474
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:195
int getCarNumber() const
Returns the total number of cars on the segment.
Definition: MESegment.cpp:307
const SUMOTime myTau_fj
Definition: MESegment.h:456
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:208
void saveState(OutputDevice &out)
Saves the state of this segment into the given stream.
Definition: MESegment.cpp:644
const MSEdgeVector & getSuccessors() const
Returns the following edges.
Definition: MSEdge.h:339
#define NUMERICAL_EPS
Definition: config.h:158
SUMOTime getNextInsertionTime(SUMOTime earliestEntry) const
return a time after earliestEntry at which a vehicle may be inserted at full speed ...
Definition: MESegment.cpp:384
MESegment(const std::string &id, const MSEdge &parent, MESegment *next, SUMOReal length, SUMOReal speed, int idx, SUMOTime tauff, SUMOTime taufj, SUMOTime taujf, SUMOTime taujj, SUMOReal jamThresh, bool multiQueue, bool junctionControl)
constructor
Definition: MESegment.cpp:71
SUMOReal getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition: MSEdge.cpp:796
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
std::vector< SUMOTime > myBlockTimes
The block times.
Definition: MESegment.h:495
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1545
The class responsible for building and deletion of vehicles.
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:251
static void writeVehicle(OutputDevice &of, const MSBaseVehicle &veh)
Writes the dump of the given vehicle into the given device.
SUMOTime getTimeHeadway(const MESegment *pred, const MEVehicle *veh)
Definition: MESegment.cpp:375
void send(MEVehicle *veh, MESegment *next, SUMOTime time)
Removes the vehicle from the segment, adapting its parameters.
Definition: MESegment.cpp:459
#define DEFAULT_VEH_LENGHT_WITH_GAP
Definition: MESegment.cpp:57
SUMOReal myMeanSpeed
the mean speed on this segment. Updated at event time or on demand
Definition: MESegment.h:511
#define MESO_MIN_SPEED
Definition: MESegment.cpp:59
const int myIndex
Running number of the segment in the edge.
Definition: MESegment.h:453
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
const SUMOTime myTau_ff
The time headway parameters, see the Eissfeldt thesis.
Definition: MESegment.h:456
static bool gMesoLimitedJunctionControl
Definition: MSGlobals.h:98
void addLeaderCar(MEVehicle *veh, MSLink *link)
Adds the given car to the leading vehicles.
Definition: MELoop.cpp:208
void addReminders(MEVehicle *veh) const
add this lanes MoveReminders to the given vehicle
Definition: MESegment.cpp:484
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:225
SUMOReal estimateLeaveSpeed(const MSLink *link) const
Returns the vehicle&#39;s estimated speed after driving accross the link.
Definition: MEVehicle.cpp:129
SUMOReal getMaxPenaltySeconds() const
return the maximum tls penalty for all links from this edge
Definition: MESegment.cpp:738
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
SUMOTime tauWithVehLength(SUMOTime tau, SUMOReal lengthWithGap) const
convert net time gap (leader back to follower front) to gross time gap (leader front to follower fron...
Definition: MESegment.h:438
void recomputeJamThreshold(SUMOReal jamThresh)
compute a value for myJamThreshold if jamThresh is negative, compute a value which allows free flow a...
Definition: MESegment.cpp:146
const std::string & getID() const
Returns the name of the vehicle.