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