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