Eclipse 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.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // A single mesoscopic segment (cell)
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <algorithm>
23 #include <limits>
24 #include <utils/common/StdDefs.h>
25 #include <microsim/MSGlobals.h>
26 #include <microsim/MSEdge.h>
27 #include <microsim/MSJunction.h>
28 #include <microsim/MSNet.h>
29 #include <microsim/MSLane.h>
30 #include <microsim/MSLink.h>
39 #include "MEVehicle.h"
40 #include "MELoop.h"
41 #include "MESegment.h"
42 
43 #define DEFAULT_VEH_LENGTH_WITH_GAP (SUMOVTypeParameter::getDefault().length + SUMOVTypeParameter::getDefault().minGap)
44 // avoid division by zero when driving very slowly
45 #define MESO_MIN_SPEED (0.05)
46 
47 //#define DEBUG_OPENED
48 //#define DEBUG_JAMTHRESHOLD
49 //#define DEBUG_COND (getID() == "blocker")
50 //#define DEBUG_COND (true)
51 #define DEBUG_COND (myEdge.isSelected())
52 #define DEBUG_COND2(obj) ((obj != 0 && (obj)->isSelected()))
53 
54 
55 // ===========================================================================
56 // static member definition
57 // ===========================================================================
58 MSEdge MESegment::myDummyParent("MESegmentDummyParent", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
59 MESegment MESegment::myVaporizationTarget("vaporizationTarget");
60 const double MESegment::DO_NOT_PATCH_JAM_THRESHOLD(std::numeric_limits<double>::max());
61 
62 
63 // ===========================================================================
64 // MESegment::Queue method definitions
65 // ===========================================================================
66 MEVehicle*
69  assert(std::find(myVehicles.begin(), myVehicles.end(), v) != myVehicles.end());
70  if (v == myVehicles.back()) {
71  myVehicles.pop_back();
72  if (myVehicles.empty()) {
73  myOccupancy = 0.;
74  } else {
75  return myVehicles.back();
76  }
77  } else {
78  myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), v));
79  }
80  return nullptr;
81 }
82 
83 void
85  myDetectorData.push_back(data);
86  for (MEVehicle* const v : myVehicles) {
87  v->addReminder(data);
88  }
89 }
90 
91 void
93  for (MSMoveReminder* rem : myDetectorData) {
94  veh->addReminder(rem);
95  }
96 }
97 
98 // ===========================================================================
99 // MESegment method definitions
100 // ===========================================================================
101 MESegment::MESegment(const std::string& id,
102  const MSEdge& parent, MESegment* next,
103  const double length, const double speed,
104  const int idx,
105  const bool multiQueue,
106  const MesoEdgeType& edgeType):
107  Named(id), myEdge(parent), myNextSegment(next),
108  myLength(length), myIndex(idx),
110  myNumVehicles(0),
112  myMeanSpeed(speed),
114 
115  const std::vector<MSLane*>& lanes = parent.getLanes();
116  int usableLanes = 0;
117  for (MSLane* const l : lanes) {
118  const SVCPermissions allow = MSEdge::getMesoPermissions(l->getPermissions());
119  if (multiQueue) {
120  myQueues.push_back(Queue(allow));
121  }
122  if (allow != 0) {
123  usableLanes++;
124  }
125  }
126  if (usableLanes == 0) {
127  // cars won't drive here. Give sensible tau values capacity for the ignored classes
128  usableLanes = 1;
129  }
130  if (multiQueue) {
131  if (next == nullptr) {
132  for (const MSEdge* const edge : parent.getSuccessors()) {
133  const std::vector<MSLane*>* const allowed = parent.allowedLanes(*edge);
134  assert(allowed != nullptr);
135  assert(allowed->size() > 0);
136  for (MSLane* const l : *allowed) {
137  std::vector<MSLane*>::const_iterator it = std::find(lanes.begin(), lanes.end(), l);
138  myFollowerMap[edge] |= (1 << distance(lanes.begin(), it));
139  }
140  }
141  }
142  myQueueCapacity = length;
143  } else {
144  myQueues.push_back(Queue(parent.getPermissions()));
145  }
146 
147  initSegment(edgeType, parent, length * usableLanes);
148 }
149 
150 void
151 MESegment::initSegment(const MesoEdgeType& edgeType, const MSEdge& parent, const double capacity) {
152 
153  myCapacity = capacity;
154  if (myQueues.size() == 1) {
155  const double laneScale = capacity / myLength;
156  myQueueCapacity = capacity;
158  // Eissfeldt p. 90 and 151 ff.
159  myTau_ff = (SUMOTime)((double)edgeType.tauff / laneScale);
160  myTau_fj = (SUMOTime)((double)edgeType.taufj / laneScale);
161  myTau_jf = (SUMOTime)((double)edgeType.taujf / laneScale);
162  myTau_jj = (SUMOTime)((double)edgeType.taujj / laneScale);
163  } else {
164  myTau_ff = edgeType.tauff;
165  myTau_fj = edgeType.taufj;
166  myTau_jf = edgeType.taujf;
167  myTau_jj = edgeType.taujj;
168  }
169 
170  myJunctionControl = myNextSegment == nullptr && (edgeType.junctionControl || MELoop::isEnteringRoundabout(parent));
171  myTLSPenalty = ((edgeType.tlsPenalty > 0 || edgeType.tlsFlowPenalty > 0) &&
172  // only apply to the last segment of a tls-controlled edge
173  myNextSegment == nullptr && (
177 
178  // only apply to the last segment of an uncontrolled edge that has at least 1 minor link
179  myCheckMinorPenalty = (edgeType.minorPenalty > 0 &&
180  myNextSegment == nullptr &&
184  parent.hasMinorLink());
185  myMinorPenalty = edgeType.minorPenalty;
186  myOvertaking = edgeType.overtaking && myCapacity > myLength;
187 
188  //std::cout << getID() << " myMinorPenalty=" << myMinorPenalty << " myTLSPenalty=" << myTLSPenalty << " myJunctionControl=" << myJunctionControl << " myOvertaking=" << myOvertaking << "\n";
189 
191 }
192 
193 MESegment::MESegment(const std::string& id):
194  Named(id),
195  myEdge(myDummyParent), // arbitrary edge needed to supply the needed reference
196  myNextSegment(nullptr), myLength(0), myIndex(0),
197  myTau_ff(0), myTau_fj(0), myTau_jf(0), myTau_jj(0),
198  myTLSPenalty(false),
199  myCheckMinorPenalty(false),
200  myMinorPenalty(0),
201  myJunctionControl(false),
202  myOvertaking(false),
203  myTau_length(1) {
204 }
205 
206 
207 void
209  if (myQueues.size() > 1) {
210  for (MSLane* lane : myEdge.getLanes()) {
211  myQueues[lane->getIndex()].setPermissions(lane->getPermissions());
212  }
213  } else {
214  myQueues.back().setPermissions(myEdge.getPermissions());
215  }
216 }
217 
218 
219 void
221  if (jamThresh == DO_NOT_PATCH_JAM_THRESHOLD) {
222  return;
223  }
224  if (jamThresh < 0) {
225  // compute based on speed
227  } else {
228  // compute based on specified percentage
229  myJamThreshold = jamThresh * myCapacity;
230  }
231 }
232 
233 
234 double
235 MESegment::jamThresholdForSpeed(double speed, double jamThresh) const {
236  // vehicles driving freely at maximum speed should not jam
237  // we compute how many vehicles could possible enter the segment until the first vehicle leaves
238  // and multiply by the space these vehicles would occupy
239  // the jamThresh parameter is scale the resulting value
240  if (speed == 0) {
241  return std::numeric_limits<double>::max(); // never jam. Irrelevant at speed 0 anyway
242  }
243 #ifdef DEBUG_JAMTHRESHOLD
244  if (true || DEBUG_COND) {
245  std::cout << "jamThresholdForSpeed seg=" << getID() << " speed=" << speed << " jamThresh=" << jamThresh << " ffVehs=" << std::ceil(myLength / (-jamThresh * speed * STEPS2TIME(tauWithVehLength(myTau_ff, DEFAULT_VEH_LENGTH_WITH_GAP)))) << " thresh=" << std::ceil(myLength / (-jamThresh * speed * STEPS2TIME(tauWithVehLength(myTau_ff, DEFAULT_VEH_LENGTH_WITH_GAP)))) * DEFAULT_VEH_LENGTH_WITH_GAP
246  << "\n";
247  }
248 #endif
249  return std::ceil(myLength / (-jamThresh * speed * STEPS2TIME(tauWithVehLength(myTau_ff, DEFAULT_VEH_LENGTH_WITH_GAP, 1.)))) * DEFAULT_VEH_LENGTH_WITH_GAP;
250 }
251 
252 
253 void
254 MESegment::addDetector(MSMoveReminder* data, int queueIndex) {
255  if (queueIndex == -1) {
256  for (Queue& q : myQueues) {
257  q.addDetector(data);
258  }
259  } else {
260  assert(queueIndex < (int)myQueues.size());
261  myQueues[queueIndex].addDetector(data);
262  }
263 }
264 
265 
266 /*
267 void
268 MESegment::removeDetector(MSMoveReminder* data) {
269  std::vector<MSMoveReminder*>::iterator it = std::find(myDetectorData.begin(), myDetectorData.end(), data);
270  if (it != myDetectorData.end()) {
271  myDetectorData.erase(it);
272  }
273  for (const Queue& q : myQueues) {
274  for (MEVehicle* const v : q.getVehicles()) {
275  v->removeReminder(data);
276  }
277  }
278 }
279 */
280 
281 
282 void
284  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
285  if (queueIndex == -1) {
286  for (const Queue& q : myQueues) {
287  SUMOTime earliestExitTime = currentTime;
288  for (std::vector<MEVehicle*>::const_reverse_iterator i = q.getVehicles().rbegin(); i != q.getVehicles().rend(); ++i) {
289  const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
290  (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
291  earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
292  }
293  }
294  } else {
295  SUMOTime earliestExitTime = currentTime;
296  for (std::vector<MEVehicle*>::const_reverse_iterator i = myQueues[queueIndex].getVehicles().rbegin(); i != myQueues[queueIndex].getVehicles().rend(); ++i) {
297  const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
298  (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
299  earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
300  }
301  }
302 }
303 
304 
305 SUMOTime
306 MESegment::hasSpaceFor(const MEVehicle* const veh, const SUMOTime entryTime, int& qIdx, const bool init) const {
307  SUMOTime earliestEntry = SUMOTime_MAX;
308  qIdx = 0;
309  if (myNumVehicles == 0 && myQueues.size() == 1) {
310  // we have always space for at least one vehicle
311  if (myQueues.front().allows(veh->getVClass())) {
312  return entryTime;
313  } else {
314  return earliestEntry;
315  }
316  }
317  const SUMOVehicleClass svc = veh->getVClass();
318  int minSize = std::numeric_limits<int>::max();
319  const MSEdge* const succ = myNextSegment == nullptr ? veh->succEdge(1) : nullptr;
320  for (int i = 0; i < (int)myQueues.size(); i++) {
321  const Queue& q = myQueues[i];
322  const double newOccupancy = q.size() == 0 ? 0. : q.getOccupancy() + veh->getVehicleType().getLengthWithGap();
323  if (newOccupancy <= myQueueCapacity) { // we must ensure that occupancy remains below capacity
324  if (succ == nullptr || myFollowerMap.count(succ) == 0 || ((myFollowerMap.find(succ)->second & (1 << i)) != 0)) {
325  if (q.allows(svc) && q.size() < minSize) {
326  if (init) {
327  // regular insertions and initial insertions must respect different constraints:
328  // - regular insertions must respect entryBlockTime
329  // - initial insertions should not cause additional jamming
330  // - inserted vehicle should be able to continue at the current speed
332  if (newOccupancy <= myJamThreshold) {
333  qIdx = i;
334  minSize = q.size();
335  }
336  } else {
337  if (newOccupancy <= jamThresholdForSpeed(getMeanSpeed(false), -1)) {
338  qIdx = i;
339  minSize = q.size();
340  }
341  }
342  } else if (entryTime >= q.getEntryBlockTime()) {
343  qIdx = i;
344  minSize = q.size();
345  } else {
346  earliestEntry = MIN2(earliestEntry, q.getEntryBlockTime());
347  }
348  }
349  }
350  }
351  }
352  if (minSize == std::numeric_limits<int>::max()) {
353  return earliestEntry;
354  }
355  return entryTime;
356 }
357 
358 
359 bool
361  int qIdx = 0;
362  if (hasSpaceFor(veh, time, qIdx, true) == time) {
363  receive(veh, qIdx, time, true);
364  // we can check only after insertion because insertion may change the route via devices
365  std::string msg;
366  if (MSGlobals::gCheckRoutes && !veh->hasValidRoute(msg)) {
367  throw ProcessError("Vehicle '" + veh->getID() + "' has no valid route. " + msg);
368  }
369  return true;
370  }
371  return false;
372 }
373 
374 
375 double
376 MESegment::getMeanSpeed(bool useCached) const {
377  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
378  if (currentTime != myLastMeanSpeedUpdate || !useCached) {
379  myLastMeanSpeedUpdate = currentTime;
380  double v = 0;
381  int count = 0;
382  for (const Queue& q : myQueues) {
383  const SUMOTime tau = q.getOccupancy() < myJamThreshold ? myTau_ff : myTau_jf;
384  SUMOTime earliestExitTime = currentTime;
385  count += q.size();
386  for (std::vector<MEVehicle*>::const_reverse_iterator veh = q.getVehicles().rbegin(); veh != q.getVehicles().rend(); ++veh) {
387  v += (*veh)->getConservativeSpeed(earliestExitTime); // earliestExitTime is updated!
388  earliestExitTime += tauWithVehLength(tau, (*veh)->getVehicleType().getLengthWithGap(), (*veh)->getVehicleType().getCarFollowModel().getHeadwayTime());
389  }
390  }
391  if (count == 0) {
393  } else {
394  myMeanSpeed = v / (double) count;
395  }
396  }
397  return myMeanSpeed;
398 }
399 
400 
401 void
403  for (const Queue& q : myQueues) {
404  for (const MEVehicle* const veh : q.getVehicles()) {
405  MSXMLRawOut::writeVehicle(of, *veh);
406  }
407  }
408 }
409 
410 
411 MEVehicle*
413  Queue& q = myQueues[v->getQueIndex()];
414  // One could be tempted to do v->setSegment(next); here but position on lane will be invalid if next == 0
415  v->updateDetectors(leaveTime, true, reason);
416  myNumVehicles--;
417  myEdge.lock();
418  MEVehicle* nextLeader = q.remove(v);
419  myEdge.unlock();
420  return nextLeader;
421 }
422 
423 
424 SUMOTime
426  // since we do not know which queue will be used we give a conservative estimate
427  SUMOTime earliestLeave = earliestEntry;
428  SUMOTime latestEntry = -1;
429  for (const Queue& q : myQueues) {
430  earliestLeave = MAX2(earliestLeave, q.getBlockTime());
431  latestEntry = MAX2(latestEntry, q.getEntryBlockTime());
432  }
433  if (myEdge.getSpeedLimit() == 0) {
434  return MAX2(earliestEntry, latestEntry); // FIXME: This line is just an adhoc-fix to avoid division by zero (Leo)
435  } else {
436  return MAX3(earliestEntry, earliestLeave - TIME2STEPS(myLength / myEdge.getSpeedLimit()), latestEntry);
437  }
438 }
439 
440 
441 MSLink*
442 MESegment::getLink(const MEVehicle* veh, bool penalty) const {
443  if (myJunctionControl || penalty) {
444  const MSEdge* const nextEdge = veh->succEdge(1);
445  if (nextEdge == nullptr || veh->getQueIndex() == PARKING_QUEUE) {
446  return nullptr;
447  }
448  // try to find any link leading to our next edge, start with the lane pointed to by the que index
449  const MSLane* const bestLane = myEdge.getLanes()[veh->getQueIndex()];
450  for (MSLink* const link : bestLane->getLinkCont()) {
451  if (&link->getLane()->getEdge() == nextEdge) {
452  return link;
453  }
454  }
455  // this is for the non-multique case, maybe we should use caching here !!!
456  for (const MSLane* const lane : myEdge.getLanes()) {
457  if (lane != bestLane) {
458  for (MSLink* const link : lane->getLinkCont()) {
459  if (&link->getLane()->getEdge() == nextEdge) {
460  return link;
461  }
462  }
463  }
464  }
465  }
466  return nullptr;
467 }
468 
469 
470 bool
471 MESegment::isOpen(const MEVehicle* veh) const {
472 #ifdef DEBUG_OPENED
473  if (DEBUG_COND || DEBUG_COND2(veh)) {
474  gDebugFlag1 = true;
475  std::cout << SIMTIME << " opened seg=" << getID() << " veh=" << Named::getIDSecure(veh)
476  << " tlsPenalty=" << myTLSPenalty;
477  const MSLink* link = getLink(veh);
478  if (link == 0) {
479  std::cout << " link=0";
480  } else {
481  std::cout << " prio=" << link->havePriority()
482  << " override=" << limitedControlOverride(link)
483  << " isOpen=" << link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
486  0, nullptr, false, veh)
487  << " et=" << veh->getEventTime()
488  << " v=" << veh->getSpeed()
489  << " vLeave=" << veh->estimateLeaveSpeed(link)
490  << " impatience=" << veh->getImpatience()
491  << " tWait=" << veh->getWaitingTime();
492  }
493  std::cout << "\n";
494  gDebugFlag1 = false;
495  }
496 #endif
497  if (myTLSPenalty) {
498  // XXX should limited control take precedence over tls penalty?
499  return true;
500  }
501  const MSLink* link = getLink(veh);
502  return (link == nullptr
503  || link->havePriority()
504  || limitedControlOverride(link)
505  || link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
508  0, nullptr, false, veh));
509 }
510 
511 
512 bool
514  assert(link != nullptr);
516  return false;
517  }
518  // if the target segment of this link is not saturated junction control is disabled
519  const MSEdge& targetEdge = link->getLane()->getEdge();
520  const MESegment* target = MSGlobals::gMesoNet->getSegmentForEdge(targetEdge);
521  return (target->getBruttoOccupancy() * 2 < target->myJamThreshold) && !targetEdge.isRoundabout();
522 }
523 
524 
525 void
526 MESegment::send(MEVehicle* veh, MESegment* const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason) {
527  Queue& q = myQueues[veh->getQueIndex()];
528  assert(isInvalid(next) || time >= q.getBlockTime());
529  MSLink* const link = getLink(veh);
530  if (link != nullptr) {
531  link->removeApproaching(veh);
532  }
533  if (veh->isStopped()) {
534  veh->processStop();
535  }
536  MEVehicle* lc = removeCar(veh, time, reason); // new leaderCar
537  q.setBlockTime(time);
538  if (!isInvalid(next)) {
539  const bool nextFree = next->myQueues[nextQIdx].getOccupancy() <= next->myJamThreshold;
540  const SUMOTime tau = (q.getOccupancy() <= myJamThreshold
541  ? (nextFree ? myTau_ff : myTau_fj)
542  : (nextFree ? myTau_jf : getTauJJ((double)next->myQueues[nextQIdx].size(), next->myQueueCapacity, next->myJamThreshold)));
543  assert(tau >= 0);
545  if (myTLSPenalty) {
546  const MSLink* const tllink = getLink(veh, true);
547  if (tllink != nullptr && tllink->isTLSControlled()) {
548  assert(tllink->getGreenFraction() > 0);
549  myLastHeadway = (SUMOTime)((double)myLastHeadway / tllink->getGreenFraction());
550  }
551  }
553  }
554  if (lc != nullptr) {
555  lc->setEventTime(MAX2(lc->getEventTime(), q.getBlockTime()));
557  }
558 }
559 
560 SUMOTime
561 MESegment::getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const {
562  // compute coefficients for the jam-jam headway function
563  // this function models the effect that "empty space" needs to move
564  // backwards through the downstream segment before the upstream segment may
565  // send annother vehicle.
566  // this allows jams to clear and move upstream.
567  // the headway function f(x) depends on the number of vehicles in the
568  // downstream segment x
569  // f is a linear function that passes through the following fixed points:
570  // f(n_jam_threshold) = tau_jf_withLength (for continuity)
571  // f(headwayCapacity) = myTau_jj * headwayCapacity
572 
573  const SUMOTime tau_jf_withLength = tauWithVehLength(myTau_jf, DEFAULT_VEH_LENGTH_WITH_GAP, 1.);
574  // number of vehicles that fit into the NEXT queue (could be larger than expected with DEFAULT_VEH_LENGTH_WITH_GAP!)
575  const double headwayCapacity = MAX2(nextQueueSize, nextQueueCapacity / DEFAULT_VEH_LENGTH_WITH_GAP);
576  // number of vehicles above which the NEXT queue is jammed
577  const double n_jam_threshold = headwayCapacity * nextJamThreshold / nextQueueCapacity;
578 
579  // slope a and axis offset b for the jam-jam headway function
580  // solving f(x) = a * x + b
581  const double a = (STEPS2TIME(myTau_jj) * headwayCapacity - STEPS2TIME(tau_jf_withLength)) / (headwayCapacity - n_jam_threshold);
582  const double b = headwayCapacity * (STEPS2TIME(myTau_jj) - a);
583 
584  // it is only well defined for nextQueueSize >= n_jam_threshold (which may not be the case for longer vehicles), so we take the MAX
585  return TIME2STEPS(a * MAX2(nextQueueSize, n_jam_threshold) + b);
586 }
587 
588 
589 bool
592 }
593 
594 
595 void
597  if (veh->getQueIndex() != PARKING_QUEUE) {
598  myQueues[veh->getQueIndex()].addReminders(veh);
599  }
600 }
601 
602 
603 void
604 MESegment::receive(MEVehicle* veh, const int qIdx, SUMOTime time, const bool isDepart, const bool isTeleport, const bool newEdge) {
605  const double speed = isDepart ? -1 : MAX2(veh->getSpeed(), MESO_MIN_SPEED); // on the previous segment
606  veh->setSegment(this); // for arrival checking
607  veh->setLastEntryTime(time);
609  if (!isDepart && (
610  // arrival on entering a new edge
611  (newEdge && veh->moveRoutePointer())
612  // arrival on entering a new segment
613  || veh->hasArrived())) {
614  // route has ended
615  veh->setEventTime(time + TIME2STEPS(myLength / speed)); // for correct arrival speed
616  addReminders(veh);
618  veh->updateDetectors(time, true,
621  return;
622  }
623  assert(veh->getEdge() == &getEdge());
624  // route continues
625  Queue& q = myQueues[qIdx];
626  const double maxSpeedOnEdge = veh->getEdge()->getLanes()[qIdx]->getVehicleMaxSpeed(veh);
627  const double uspeed = MAX2(maxSpeedOnEdge, MESO_MIN_SPEED);
628  std::vector<MEVehicle*>& cars = q.getModifiableVehicles();
629  MEVehicle* newLeader = nullptr; // first vehicle in the current queue
630  const SUMOTime stopTime = veh->checkStop(time);
631  SUMOTime tleave = MAX2(stopTime + TIME2STEPS(myLength / uspeed) + getLinkPenalty(veh), q.getBlockTime());
632  if (veh->isStopped()) {
633  myEdge.addWaiting(veh);
634  }
635  if (veh->isParking()) {
636  veh->setEventTime(stopTime);
637  veh->setSegment(this, PARKING_QUEUE);
638  myEdge.getLanes()[0]->addParking(veh); // TODO for GUI only
639  } else {
640  myEdge.lock();
641  if (cars.empty()) {
642  cars.push_back(veh);
643  newLeader = veh;
644  } else {
645  SUMOTime leaderOut = cars[0]->getEventTime();
646  if (!isDepart && leaderOut > tleave && overtake()) {
647  if (cars.size() == 1) {
649  newLeader = veh;
650  }
651  cars.insert(cars.begin() + 1, veh);
652  } else {
653  tleave = MAX2(leaderOut + tauWithVehLength(myTau_ff, cars[0]->getVehicleType().getLengthWithGap(), cars[0]->getVehicleType().getCarFollowModel().getHeadwayTime()), tleave);
654  cars.insert(cars.begin(), veh);
655  }
656  }
657  myEdge.unlock();
658  myNumVehicles++;
659  if (!isDepart && !isTeleport) {
660  // departs and teleports could take place anywhere on the edge so they should not block regular flow
661  // the -1 facilitates interleaving of multiple streams
663  }
665  veh->setEventTime(tleave);
666  veh->setSegment(this, qIdx);
667  }
668  addReminders(veh);
669  if (isDepart) {
670  veh->onDepart();
672  } else if (newEdge) {
674  } else {
676  }
677  if (veh->isParking()) {
678  MSGlobals::gMesoNet->addLeaderCar(veh, nullptr);
679  } else {
680  if (newLeader != nullptr) {
681  MSGlobals::gMesoNet->addLeaderCar(newLeader, getLink(newLeader));
682  }
683  }
684 }
685 
686 
687 bool
689  for (const Queue& q : myQueues) {
690  if (q.size() > 0) {
691  for (MEVehicle* const veh : q.getVehicles()) {
692  if (filter->vehicleApplies(*veh)) {
695  return true;
696  }
697  }
698  }
699  }
700  return false;
701 }
702 
703 
704 void
705 MESegment::setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector<MEVehicle*>& vehs) {
706  MEVehicle* v = vehs.back();
707  v->updateDetectors(currentTime, false);
708  SUMOTime newEvent = MAX2(newArrival(v, newSpeed, currentTime), blockTime);
709  if (v->getEventTime() != newEvent) {
711  v->setEventTime(newEvent);
713  }
714  for (std::vector<MEVehicle*>::const_reverse_iterator i = vehs.rbegin() + 1; i != vehs.rend(); ++i) {
715  (*i)->updateDetectors(currentTime, false);
716  newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff);
717  //newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff + (SUMOTime)((*(i - 1))->getVehicleType().getLength() / myTau_length));
718  (*i)->setEventTime(newEvent);
719  }
720 }
721 
722 
723 SUMOTime
724 MESegment::newArrival(const MEVehicle* const v, double newSpeed, SUMOTime currentTime) {
725  // since speed is only an upper bound pos may be to optimistic
726  const double pos = MIN2(myLength, STEPS2TIME(currentTime - v->getLastEntryTime()) * v->getSpeed());
727  // traveltime may not be 0
728  double tt = (myLength - pos) / MAX2(newSpeed, MESO_MIN_SPEED);
729  return currentTime + MAX2(TIME2STEPS(tt), SUMOTime(1));
730 }
731 
732 
733 void
734 MESegment::setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh, int qIdx) {
735  recomputeJamThreshold(jamThresh);
736  //myTau_length = MAX2(MESO_MIN_SPEED, newSpeed) * myEdge.getLanes().size() / TIME2STEPS(1);
737  int i = 0;
738  for (const Queue& q : myQueues) {
739  if (q.size() != 0) {
740  if (qIdx == -1 || qIdx == i) {
741  setSpeedForQueue(newSpeed, currentTime, q.getBlockTime(), q.getVehicles());
742  }
743  }
744  i++;
745  }
746 }
747 
748 
749 SUMOTime
751  SUMOTime result = SUMOTime_MAX;
752  for (const Queue& q : myQueues) {
753  if (q.size() != 0 && q.getVehicles().back()->getEventTime() < result) {
754  result = q.getVehicles().back()->getEventTime();
755  }
756  }
757  if (result < SUMOTime_MAX) {
758  return result;
759  }
760  return -1;
761 }
762 
763 
764 void
766  bool write = false;
767  for (const Queue& q : myQueues) {
768  if (q.getBlockTime() != -1 || !q.getVehicles().empty()) {
769  write = true;
770  break;
771  }
772  }
773  if (write) {
775  for (const Queue& q : myQueues) {
776  out.openTag(SUMO_TAG_VIEWSETTINGS_VEHICLES).writeAttr(SUMO_ATTR_TIME, toString<SUMOTime>(q.getBlockTime()));
777  out.writeAttr(SUMO_ATTR_VALUE, q.getVehicles());
778  out.closeTag();
779  }
780  out.closeTag();
781  }
782 }
783 
784 
785 void
787  for (Queue& q : myQueues) {
788  q.getModifiableVehicles().clear();
789  }
790 }
791 
792 void
793 MESegment::loadState(const std::vector<std::string>& vehIds, MSVehicleControl& vc, const SUMOTime block, const int queIdx) {
794  Queue& q = myQueues[queIdx];
795  for (const std::string& id : vehIds) {
796  MEVehicle* v = static_cast<MEVehicle*>(vc.getVehicle(id));
797  // vehicle could be removed due to options
798  if (v != nullptr) {
799  assert(v->getSegment() == this);
800  q.getModifiableVehicles().push_back(v);
801  myNumVehicles++;
803  }
804  }
805  if (q.size() != 0) {
806  // add the last vehicle of this queue
807  // !!! one question - what about the previously added vehicle? Is it stored twice?
808  MEVehicle* veh = q.getVehicles().back();
810  }
811  q.setBlockTime(block);
813 }
814 
815 
816 std::vector<const MEVehicle*>
818  std::vector<const MEVehicle*> result;
819  for (const Queue& q : myQueues) {
820  result.insert(result.end(), q.getVehicles().begin(), q.getVehicles().end());
821  }
822  return result;
823 }
824 
825 
826 bool
828  for (const Queue& q : myQueues) {
829  if (q.size() > 0 && q.getVehicles().back()->getWaitingTime() > 0) {
830  return true;
831  }
832  }
833  return false;
834 }
835 
836 
837 double
839  return 3600 * getCarNumber() * getMeanSpeed() / myLength;
840 }
841 
842 
843 SUMOTime
845  const MSLink* link = getLink(veh, myTLSPenalty || myCheckMinorPenalty);
846  if (link != nullptr) {
847  SUMOTime result = 0;
848  if (link->isTLSControlled()) {
849  result += link->getMesoTLSPenalty();
850  }
851  // minor tls links may get an additional penalty
852  if (!link->havePriority() &&
853  // do not apply penalty on top of tLSPenalty
854  !myTLSPenalty &&
855  // do not apply penalty if limited control is active
857  result += myMinorPenalty;
858  }
859  return result;
860  } else {
861  return 0;
862  }
863 }
864 
865 
866 double
868  double result = 0;
869  for (const Queue& q : myQueues) {
870  // @note: only the leader currently accumulates waitingTime but this might change in the future
871  for (const MEVehicle* veh : q.getVehicles()) {
872  result += veh->getWaitingSeconds();
873  }
874  }
875  return result;
876 }
877 
878 
879 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define MESO_MIN_SPEED
Definition: MESegment.cpp:45
#define DEFAULT_VEH_LENGTH_WITH_GAP
Definition: MESegment.cpp:43
#define DEBUG_COND
Definition: MESegment.cpp:51
#define DEBUG_COND2(obj)
Definition: MESegment.cpp:52
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define SUMOTime_MIN
Definition: SUMOTime.h:35
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SUMO_TAG_VIEWSETTINGS_VEHICLES
@ SUMO_TAG_SEGMENT
segment of a lane
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_ID
@ SUMO_ATTR_TIME
trigger: the time of the step
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:37
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
T MAX3(T a, T b, T c)
Definition: StdDefs.h:96
static bool isEnteringRoundabout(const MSEdge &e)
whether the given edge is entering a roundabout
Definition: MELoop.cpp:350
SUMOTime changeSegment(MEVehicle *veh, SUMOTime leaveTime, MESegment *const toSegment, MSMoveReminder::Notification reason, const bool ignoreLink=false) const
change to the next segment this handles combinations of the following cases: (ending / continuing rou...
Definition: MELoop.cpp:79
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:333
bool removeLeaderCar(MEVehicle *v)
Removes the given car from the leading vehicles.
Definition: MELoop.cpp:244
void addLeaderCar(MEVehicle *veh, MSLink *link)
Adds the given car to the leading vehicles.
Definition: MELoop.cpp:231
int size() const
Definition: MESegment.h:73
void setOccupancy(const double occ)
Definition: MESegment.h:86
MEVehicle * remove(MEVehicle *v)
Definition: MESegment.cpp:67
void setBlockTime(SUMOTime t)
Definition: MESegment.h:106
SUMOTime getBlockTime() const
Definition: MESegment.h:103
double myOccupancy
The occupied space (in m) in the queue.
Definition: MESegment.h:125
bool allows(SUMOVehicleClass vclass) const
Definition: MESegment.h:89
void addReminders(MEVehicle *veh) const
Definition: MESegment.cpp:92
void addDetector(MSMoveReminder *data)
Definition: MESegment.cpp:84
void setEntryBlockTime(SUMOTime entryBlockTime)
set the next time at which a vehicle may enter this queue
Definition: MESegment.h:99
double getOccupancy() const
Definition: MESegment.h:83
const std::vector< MEVehicle * > & getVehicles() const
Definition: MESegment.h:76
std::vector< MEVehicle * > myVehicles
Definition: MESegment.h:122
SUMOTime getEntryBlockTime() const
return the next time at which a vehicle may enter this queue
Definition: MESegment.h:94
std::vector< MEVehicle * > & getModifiableVehicles()
Definition: MESegment.h:80
A single mesoscopic segment (cell)
Definition: MESegment.h:49
void addReminders(MEVehicle *veh) const
add this lanes MoveReminders to the given vehicle
Definition: MESegment.cpp:596
double myQueueCapacity
The number of lanes represented by the queue * the length of the lane.
Definition: MESegment.h:553
bool overtake()
Definition: MESegment.cpp:590
SUMOTime tauWithVehLength(SUMOTime tau, double lengthWithGap, double vehicleTau) const
convert net time gap (leader back to follower front) to gross time gap (leader front to follower fron...
Definition: MESegment.h:507
SUMOTime myTau_ff
The time headway parameters, see the Eissfeldt thesis.
Definition: MESegment.h:530
bool initialise(MEVehicle *veh, SUMOTime time)
Inserts (emits) vehicle into the segment.
Definition: MESegment.cpp:360
std::vector< Queue > myQueues
The car queues. Vehicles are inserted in the front and removed in the back.
Definition: MESegment.h:559
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition: MESegment.h:258
SUMOTime myLastHeadway
the last headway
Definition: MESegment.h:568
static const int PARKING_QUEUE
Definition: MESegment.h:52
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:513
bool isOpen(const MEVehicle *veh) const
Returns whether the vehicle may use the next link.
Definition: MESegment.cpp:471
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:254
void clearState()
Remove all vehicles before quick-loading state.
Definition: MESegment.cpp:786
void receive(MEVehicle *veh, const int qIdx, SUMOTime time, const bool isDepart=false, const bool isTeleport=false, const bool newEdge=false)
Adds the vehicle to the segment, adapting its parameters.
Definition: MESegment.cpp:604
SUMOTime getLinkPenalty(const MEVehicle *veh) const
Returns the penalty time for passing a link (if using gMesoTLSPenalty > 0 or gMesoMinorPenalty > 0)
Definition: MESegment.cpp:844
void writeVehicles(OutputDevice &of) const
Definition: MESegment.cpp:402
std::map< const MSEdge *, int > myFollowerMap
The follower edge to allowed que index mapping for multi queue segments.
Definition: MESegment.h:565
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:442
int myNumVehicles
The cached value for the number of vehicles.
Definition: MESegment.h:562
void setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector< MEVehicle * > &vehs)
Definition: MESegment.cpp:705
SUMOTime hasSpaceFor(const MEVehicle *const veh, const SUMOTime entryTime, int &qIdx, const bool init=false) const
Returns whether the given vehicle would still fit into the segment.
Definition: MESegment.cpp:306
void updatePermissions()
called when permissions change due to Rerouter or TraCI
Definition: MESegment.cpp:208
void saveState(OutputDevice &out) const
Saves the state of this segment into the given stream.
Definition: MESegment.cpp:765
void initSegment(const MesoEdgeType &edgeType, const MSEdge &parent, const double capacity)
set model parameters (may be updated from additional file after network loading is complete)
Definition: MESegment.cpp:151
static MESegment myVaporizationTarget
Definition: MESegment.h:573
double myJamThreshold
The space (in m) which needs to be occupied before the segment is considered jammed.
Definition: MESegment.h:556
const int myIndex
Running number of the segment in the edge.
Definition: MESegment.h:524
void send(MEVehicle *veh, MESegment *const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason)
Removes the vehicle from the segment, adapting its parameters.
Definition: MESegment.cpp:526
SUMOTime myMinorPenalty
Definition: MESegment.h:537
double myMeanSpeed
the mean speed on this segment. Updated at event time or on demand
Definition: MESegment.h:576
bool myCheckMinorPenalty
penalty for minor links
Definition: MESegment.h:536
double jamThresholdForSpeed(double speed, double jamThresh) const
compute jam threshold for the given speed and jam-threshold option
Definition: MESegment.cpp:235
SUMOTime myLastMeanSpeedUpdate
the time at which myMeanSpeed was last updated
Definition: MESegment.h:579
SUMOTime myTau_jf
Definition: MESegment.h:530
void setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh=DO_NOT_PATCH_JAM_THRESHOLD, int qIdx=-1)
reset mySpeed and patch the speed of all vehicles in it. Also set/recompute myJamThreshold
Definition: MESegment.cpp:734
MESegment * myNextSegment
The next segment of this edge, 0 if this is the last segment of this edge.
Definition: MESegment.h:518
const MSEdge & getEdge() const
Returns the edge this segment belongs to.
Definition: MESegment.h:359
bool hasBlockedLeader() const
whether a leader in any queue is blocked
Definition: MESegment.cpp:827
double getWaitingSeconds() const
Get the waiting time for vehicles in all queues.
Definition: MESegment.cpp:867
const double myLength
The segment's length.
Definition: MESegment.h:521
SUMOTime getEventTime() const
Returns the (planned) time at which the next vehicle leaves this segment.
Definition: MESegment.cpp:750
const MSEdge & myEdge
The microsim edge this segment belongs to.
Definition: MESegment.h:515
MESegment(const std::string &id, const MSEdge &parent, MESegment *next, const double length, const double speed, const int idx, const bool multiQueue, const MesoEdgeType &edgeType)
constructor
Definition: MESegment.cpp:101
MEVehicle * removeCar(MEVehicle *v, SUMOTime leaveTime, const MSMoveReminder::Notification reason)
Removes the given car from the edge's que.
Definition: MESegment.cpp:412
std::vector< const MEVehicle * > getVehicles() const
returns all vehicles (for debugging)
Definition: MESegment.cpp:817
static MSEdge myDummyParent
Definition: MESegment.h:572
void recomputeJamThreshold(double jamThresh)
compute a value for myJamThreshold if jamThresh is negative, compute a value which allows free flow a...
Definition: MESegment.cpp:220
double getMeanSpeed() const
wrapper to satisfy the FunctionBinding signature
Definition: MESegment.h:294
int getCarNumber() const
Returns the total number of cars on the segment.
Definition: MESegment.h:206
void loadState(const 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:793
double myTau_length
Headway parameter for computing gross time headyway from net time headway, length and edge speed.
Definition: MESegment.h:547
SUMOTime myTau_jj
Definition: MESegment.h:530
SUMOTime newArrival(const MEVehicle *const v, double newSpeed, SUMOTime currentTime)
compute the new arrival time when switching speed
Definition: MESegment.cpp:724
bool myJunctionControl
Whether junction control is enabled.
Definition: MESegment.h:540
bool myTLSPenalty
Whether tls penalty is enabled.
Definition: MESegment.h:533
static const double DO_NOT_PATCH_JAM_THRESHOLD
Definition: MESegment.h:51
double getFlow() const
returns flow based on headway
Definition: MESegment.cpp:838
static bool isInvalid(const MESegment *segment)
whether the given segment is 0 or encodes vaporization
Definition: MESegment.h:443
SUMOTime getNextInsertionTime(SUMOTime earliestEntry) const
return a time after earliestEntry at which a vehicle may be inserted at full speed
Definition: MESegment.cpp:425
double myCapacity
The number of lanes represented by the queue * the length of the lane.
Definition: MESegment.h:550
bool myOvertaking
Whether overtaking is permitted on this segment.
Definition: MESegment.h:543
void prepareDetectorForWriting(MSMoveReminder &data, int queueIndex=-1)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:283
bool vaporizeAnyCar(SUMOTime currentTime, const MSDetectorFileOutput *filter)
tries to remove any car from this segment
Definition: MESegment.cpp:688
SUMOTime myTau_fj
Definition: MESegment.h:530
SUMOTime getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const
Definition: MESegment.cpp:561
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:42
double estimateLeaveSpeed(const MSLink *link) const
Returns the vehicle's estimated speed after driving accross the link.
Definition: MEVehicle.cpp:140
void processStop()
ends the current stop and performs loading/unloading
Definition: MEVehicle.cpp:336
SUMOTime getWaitingTime(const bool accumulated=false) const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:279
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge)
Definition: MEVehicle.cpp:174
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:156
SUMOTime checkStop(SUMOTime time)
Returns until when to stop at the current segment and sets the information that the stop has been rea...
Definition: MEVehicle.cpp:230
void updateDetectors(SUMOTime currentTime, const bool isLeave, const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_JUNCTION)
Updates all vehicle detectors.
Definition: MEVehicle.cpp:462
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition: MEVehicle.h:250
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves its current segment.
Definition: MEVehicle.h:190
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:220
void setLastEntryTime(SUMOTime t)
Sets the entry time for the current segment.
Definition: MEVehicle.h:242
int getQueIndex() const
Returns the index of the que the vehicle is in.
Definition: MEVehicle.h:228
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:211
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves its current segment.
Definition: MEVehicle.h:202
void setBlockTime(const SUMOTime t)
Sets the time at which the vehicle was blocked.
Definition: MEVehicle.h:264
double getSpeed() const
Returns the vehicle's estimated speed assuming no delays.
Definition: MEVehicle.cpp:119
double getImpatience() const
Returns this vehicles impatience.
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
bool hasValidRoute(std::string &msg, ConstMSRoutePtr route=0) const
Validates the current or given route.
bool isParking() const
Returns whether the vehicle is parking.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
virtual void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
void onDepart()
Called when the vehicle is inserted into the network.
bool isStopped() const
Returns whether the vehicle is at a stop.
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:264
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition: MSCFModel.h:311
Base of value-generating classes (detectors)
bool vehicleApplies(const SUMOTrafficObject &veh) const
Checks whether the detector measures vehicles of the given type.
A road/street connecting two junctions.
Definition: MSEdge.h:77
virtual void unlock() const
release exclusive access to the mesoscopic state
Definition: MSEdge.h:762
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition: MSEdge.h:634
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:479
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is retured; should pro...
Definition: MSEdge.cpp:1106
static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored=0)
Definition: MSEdge.cpp:315
bool isRoundabout() const
Definition: MSEdge.h:706
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:434
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition: MSEdge.cpp:1399
bool hasMinorLink() const
whether any lane has a minor link
Definition: MSEdge.cpp:1298
const MSJunction * getToJunction() const
Definition: MSEdge.h:418
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition: MSEdge.h:759
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:1206
static bool gCheckRoutes
Definition: MSGlobals.h:88
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:109
static bool gMesoLimitedJunctionControl
Definition: MSGlobals.h:106
SumoXMLNodeType getType() const
return the type of this Junction
Definition: MSJunction.h:133
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:716
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
@ NOTIFICATION_VAPORIZED_CALIBRATOR
The vehicle got removed by a calibrator.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
@ NOTIFICATION_VAPORIZED_VAPORIZER
The vehicle got vaporized with a vaporizer.
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
The class responsible for building and deletion of vehicles.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void scheduleVehicleRemoval(SUMOVehicle *veh, bool checkDuplicate=false)
Removes a vehicle after it has ended.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
static void writeVehicle(OutputDevice &of, const MSBaseVehicle &veh)
Writes the dump of the given vehicle into the given device.
Base class for objects which have an id.
Definition: Named.h:54
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:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
edge type specific meso parameters
Definition: MESegment.h:55