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-2023 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>
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// ===========================================================================
58MSEdge MESegment::myDummyParent("MESegmentDummyParent", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
59MESegment MESegment::myVaporizationTarget("vaporizationTarget");
60const double MESegment::DO_NOT_PATCH_JAM_THRESHOLD(std::numeric_limits<double>::max());
61
62
63// ===========================================================================
64// MESegment::Queue method definitions
65// ===========================================================================
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
83void
85 myDetectorData.push_back(data);
86 for (MEVehicle* const v : myVehicles) {
87 v->addReminder(data);
88 }
89}
90
91void
93 for (MSMoveReminder* rem : myDetectorData) {
94 veh->addReminder(rem);
95 }
96}
97
98// ===========================================================================
99// MESegment method definitions
100// ===========================================================================
101MESegment::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 (multiQueue) {
127 if (next == nullptr) {
128 for (const MSEdge* const edge : parent.getSuccessors()) {
129 const std::vector<MSLane*>* const allowed = parent.allowedLanes(*edge);
130 assert(allowed != nullptr);
131 assert(allowed->size() > 0);
132 for (MSLane* const l : *allowed) {
133 std::vector<MSLane*>::const_iterator it = std::find(lanes.begin(), lanes.end(), l);
134 myFollowerMap[edge] |= (1 << distance(lanes.begin(), it));
135 }
136 }
137 }
138 myQueueCapacity = length;
139 } else {
140 myQueues.push_back(Queue(parent.getPermissions()));
141 }
142
143 initSegment(edgeType, parent, length * usableLanes);
144}
145
146void
147MESegment::initSegment(const MesoEdgeType& edgeType, const MSEdge& parent, const double capacity) {
148
149 myCapacity = capacity;
150 if (myQueues.size() == 1) {
151 const double laneScale = capacity / myLength;
152 myQueueCapacity = capacity;
154 // Eissfeldt p. 90 and 151 ff.
155 myTau_ff = (SUMOTime)((double)edgeType.tauff / laneScale);
156 myTau_fj = (SUMOTime)((double)edgeType.taufj / laneScale);
157 myTau_jf = (SUMOTime)((double)edgeType.taujf / laneScale);
158 myTau_jj = (SUMOTime)((double)edgeType.taujj / laneScale);
159 } else {
160 myTau_ff = edgeType.tauff;
161 myTau_fj = edgeType.taufj;
162 myTau_jf = edgeType.taujf;
163 myTau_jj = edgeType.taujj;
164 }
165
167 myTLSPenalty = ((edgeType.tlsPenalty > 0 || edgeType.tlsFlowPenalty > 0) &&
168 // only apply to the last segment of a tls-controlled edge
169 myNextSegment == nullptr && (
173
174 // only apply to the last segment of an uncontrolled edge that has at least 1 minor link
175 myCheckMinorPenalty = (edgeType.minorPenalty > 0 &&
176 myNextSegment == nullptr &&
180 parent.hasMinorLink());
181 myMinorPenalty = edgeType.minorPenalty;
183
184 //std::cout << getID() << " myMinorPenalty=" << myMinorPenalty << " myTLSPenalty=" << myTLSPenalty << " myJunctionControl=" << myJunctionControl << " myOvertaking=" << myOvertaking << "\n";
185
187}
188
189MESegment::MESegment(const std::string& id):
190 Named(id),
191 myEdge(myDummyParent), // arbitrary edge needed to supply the needed reference
192 myNextSegment(nullptr), myLength(0), myIndex(0),
193 myTau_ff(0), myTau_fj(0), myTau_jf(0), myTau_jj(0),
194 myTLSPenalty(false),
195 myCheckMinorPenalty(false),
196 myMinorPenalty(0),
197 myJunctionControl(false),
198 myOvertaking(false),
199 myTau_length(1) {
200}
201
202
203void
205 if (myQueues.size() > 1) {
206 for (MSLane* lane : myEdge.getLanes()) {
207 myQueues[lane->getIndex()].setPermissions(lane->getPermissions());
208 }
209 } else {
210 myQueues.back().setPermissions(myEdge.getPermissions());
211 }
212}
213
214
215void
217 if (jamThresh == DO_NOT_PATCH_JAM_THRESHOLD) {
218 return;
219 }
220 if (jamThresh < 0) {
221 // compute based on speed
223 } else {
224 // compute based on specified percentage
225 myJamThreshold = jamThresh * myCapacity;
226 }
227}
228
229
230double
231MESegment::jamThresholdForSpeed(double speed, double jamThresh) const {
232 // vehicles driving freely at maximum speed should not jam
233 // we compute how many vehicles could possible enter the segment until the first vehicle leaves
234 // and multiply by the space these vehicles would occupy
235 // the jamThresh parameter is scale the resulting value
236 if (speed == 0) {
237 return std::numeric_limits<double>::max(); // never jam. Irrelevant at speed 0 anyway
238 }
239#ifdef DEBUG_JAMTHRESHOLD
240 if (true || DEBUG_COND) {
241 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
242 << "\n";
243 }
244#endif
246}
247
248
249void
251 if (queueIndex == -1) {
252 for (Queue& q : myQueues) {
253 q.addDetector(data);
254 }
255 } else {
256 assert(queueIndex < (int)myQueues.size());
257 myQueues[queueIndex].addDetector(data);
258 }
259}
260
261
262/*
263void
264MESegment::removeDetector(MSMoveReminder* data) {
265 std::vector<MSMoveReminder*>::iterator it = std::find(myDetectorData.begin(), myDetectorData.end(), data);
266 if (it != myDetectorData.end()) {
267 myDetectorData.erase(it);
268 }
269 for (const Queue& q : myQueues) {
270 for (MEVehicle* const v : q.getVehicles()) {
271 v->removeReminder(data);
272 }
273 }
274}
275*/
276
277
278void
280 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
281 if (queueIndex == -1) {
282 for (const Queue& q : myQueues) {
283 SUMOTime earliestExitTime = currentTime;
284 for (std::vector<MEVehicle*>::const_reverse_iterator i = q.getVehicles().rbegin(); i != q.getVehicles().rend(); ++i) {
285 const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
286 (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
287 earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
288 }
289 }
290 } else {
291 SUMOTime earliestExitTime = currentTime;
292 for (std::vector<MEVehicle*>::const_reverse_iterator i = myQueues[queueIndex].getVehicles().rbegin(); i != myQueues[queueIndex].getVehicles().rend(); ++i) {
293 const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
294 (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
295 earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
296 }
297 }
298}
299
300
302MESegment::hasSpaceFor(const MEVehicle* const veh, const SUMOTime entryTime, int& qIdx, const bool init) const {
303 SUMOTime earliestEntry = SUMOTime_MAX;
304 qIdx = 0;
305 if (myNumVehicles == 0 && myQueues.size() == 1) {
306 // we have always space for at least one vehicle
307 if (myQueues.front().allows(veh->getVClass())) {
308 return entryTime;
309 } else {
310 return earliestEntry;
311 }
312 }
313 const SUMOVehicleClass svc = veh->getVClass();
314 int minSize = std::numeric_limits<int>::max();
315 const MSEdge* const succ = myNextSegment == nullptr ? veh->succEdge(1) : nullptr;
316 for (int i = 0; i < (int)myQueues.size(); i++) {
317 const Queue& q = myQueues[i];
318 const double newOccupancy = q.size() == 0 ? 0. : q.getOccupancy() + veh->getVehicleType().getLengthWithGap();
319 if (newOccupancy <= myQueueCapacity) { // we must ensure that occupancy remains below capacity
320 if (succ == nullptr || myFollowerMap.count(succ) == 0 || ((myFollowerMap.find(succ)->second & (1 << i)) != 0)) {
321 if (q.allows(svc) && q.size() < minSize) {
322 if (init) {
323 // regular insertions and initial insertions must respect different constraints:
324 // - regular insertions must respect entryBlockTime
325 // - initial insertions should not cause additional jamming
326 // - inserted vehicle should be able to continue at the current speed
328 if (newOccupancy <= myJamThreshold) {
329 qIdx = i;
330 minSize = q.size();
331 }
332 } else {
333 if (newOccupancy <= jamThresholdForSpeed(getMeanSpeed(false), -1)) {
334 qIdx = i;
335 minSize = q.size();
336 }
337 }
338 } else if (entryTime >= q.getEntryBlockTime()) {
339 qIdx = i;
340 minSize = q.size();
341 } else {
342 earliestEntry = MIN2(earliestEntry, q.getEntryBlockTime());
343 }
344 }
345 }
346 }
347 }
348 if (minSize == std::numeric_limits<int>::max()) {
349 return earliestEntry;
350 }
351 return entryTime;
352}
353
354
355bool
357 int qIdx = 0;
358 if (hasSpaceFor(veh, time, qIdx, true) == time) {
359 receive(veh, qIdx, time, true);
360 // we can check only after insertion because insertion may change the route via devices
361 std::string msg;
362 if (MSGlobals::gCheckRoutes && !veh->hasValidRoute(msg)) {
363 throw ProcessError("Vehicle '" + veh->getID() + "' has no valid route. " + msg);
364 }
365 return true;
366 }
367 return false;
368}
369
370
371double
372MESegment::getMeanSpeed(bool useCached) const {
373 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
374 if (currentTime != myLastMeanSpeedUpdate || !useCached) {
375 myLastMeanSpeedUpdate = currentTime;
376 double v = 0;
377 int count = 0;
378 for (const Queue& q : myQueues) {
379 const SUMOTime tau = q.getOccupancy() < myJamThreshold ? myTau_ff : myTau_jf;
380 SUMOTime earliestExitTime = currentTime;
381 count += q.size();
382 for (std::vector<MEVehicle*>::const_reverse_iterator veh = q.getVehicles().rbegin(); veh != q.getVehicles().rend(); ++veh) {
383 v += (*veh)->getConservativeSpeed(earliestExitTime); // earliestExitTime is updated!
384 earliestExitTime += tauWithVehLength(tau, (*veh)->getVehicleType().getLengthWithGap(), (*veh)->getVehicleType().getCarFollowModel().getHeadwayTime());
385 }
386 }
387 if (count == 0) {
389 } else {
390 myMeanSpeed = v / (double) count;
391 }
392 }
393 return myMeanSpeed;
394}
395
396
397void
399 for (const Queue& q : myQueues) {
400 for (const MEVehicle* const veh : q.getVehicles()) {
402 }
403 }
404}
405
406
409 Queue& q = myQueues[v->getQueIndex()];
410 // One could be tempted to do v->setSegment(next); here but position on lane will be invalid if next == 0
411 v->updateDetectors(leaveTime, true, reason);
413 myEdge.lock();
414 MEVehicle* nextLeader = q.remove(v);
415 myEdge.unlock();
416 return nextLeader;
417}
418
419
422 // since we do not know which queue will be used we give a conservative estimate
423 SUMOTime earliestLeave = earliestEntry;
424 SUMOTime latestEntry = -1;
425 for (const Queue& q : myQueues) {
426 earliestLeave = MAX2(earliestLeave, q.getBlockTime());
427 latestEntry = MAX2(latestEntry, q.getEntryBlockTime());
428 }
429 if (myEdge.getSpeedLimit() == 0) {
430 return MAX2(earliestEntry, latestEntry); // FIXME: This line is just an adhoc-fix to avoid division by zero (Leo)
431 } else {
432 return MAX3(earliestEntry, earliestLeave - TIME2STEPS(myLength / myEdge.getSpeedLimit()), latestEntry);
433 }
434}
435
436
437MSLink*
438MESegment::getLink(const MEVehicle* veh, bool penalty) const {
439 if (myJunctionControl || penalty) {
440 const MSEdge* const nextEdge = veh->succEdge(1);
441 if (nextEdge == nullptr || veh->getQueIndex() == PARKING_QUEUE) {
442 return nullptr;
443 }
444 // try to find any link leading to our next edge, start with the lane pointed to by the que index
445 const MSLane* const bestLane = myEdge.getLanes()[veh->getQueIndex()];
446 for (MSLink* const link : bestLane->getLinkCont()) {
447 if (&link->getLane()->getEdge() == nextEdge) {
448 return link;
449 }
450 }
451 // this is for the non-multique case, maybe we should use caching here !!!
452 for (const MSLane* const lane : myEdge.getLanes()) {
453 if (lane != bestLane) {
454 for (MSLink* const link : lane->getLinkCont()) {
455 if (&link->getLane()->getEdge() == nextEdge) {
456 return link;
457 }
458 }
459 }
460 }
461 }
462 return nullptr;
463}
464
465
466bool
467MESegment::isOpen(const MEVehicle* veh) const {
468#ifdef DEBUG_OPENED
469 if (DEBUG_COND || DEBUG_COND2(veh)) {
470 gDebugFlag1 = true;
471 std::cout << SIMTIME << " opened seg=" << getID() << " veh=" << Named::getIDSecure(veh)
472 << " tlsPenalty=" << myTLSPenalty;
473 const MSLink* link = getLink(veh);
474 if (link == 0) {
475 std::cout << " link=0";
476 } else {
477 std::cout << " prio=" << link->havePriority()
478 << " override=" << limitedControlOverride(link)
479 << " isOpen=" << link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
482 << " et=" << veh->getEventTime()
483 << " v=" << veh->getSpeed()
484 << " vLeave=" << veh->estimateLeaveSpeed(link)
485 << " impatience=" << veh->getImpatience()
486 << " tWait=" << veh->getWaitingTime();
487 }
488 std::cout << "\n";
489 gDebugFlag1 = false;
490 }
491#endif
492 if (myTLSPenalty) {
493 // XXX should limited control take precedence over tls penalty?
494 return true;
495 }
496 const MSLink* link = getLink(veh);
497 return (link == nullptr
498 || link->havePriority()
500 || link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
503}
504
505
506bool
508 assert(link != nullptr);
510 return false;
511 }
512 // if the target segment of this link is not saturated junction control is disabled
513 const MSEdge& targetEdge = link->getLane()->getEdge();
514 const MESegment* target = MSGlobals::gMesoNet->getSegmentForEdge(targetEdge);
515 return (target->getBruttoOccupancy() * 2 < target->myJamThreshold) && !targetEdge.isRoundabout();
516}
517
518
519void
520MESegment::send(MEVehicle* veh, MESegment* const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason) {
521 Queue& q = myQueues[veh->getQueIndex()];
522 assert(isInvalid(next) || time >= q.getBlockTime());
523 MSLink* const link = getLink(veh);
524 if (link != nullptr) {
525 link->removeApproaching(veh);
526 }
527 if (veh->isStopped()) {
528 veh->processStop();
529 }
530 MEVehicle* lc = removeCar(veh, time, reason); // new leaderCar
531 q.setBlockTime(time);
532 if (!isInvalid(next)) {
533 const bool nextFree = next->myQueues[nextQIdx].getOccupancy() <= next->myJamThreshold;
534 const SUMOTime tau = (q.getOccupancy() <= myJamThreshold
535 ? (nextFree ? myTau_ff : myTau_fj)
536 : (nextFree ? myTau_jf : getTauJJ((double)next->myQueues[nextQIdx].size(), next->myQueueCapacity, next->myJamThreshold)));
537 assert(tau >= 0);
539 if (myTLSPenalty) {
540 const MSLink* const tllink = getLink(veh, true);
541 if (tllink != nullptr && tllink->isTLSControlled()) {
542 assert(tllink->getGreenFraction() > 0);
543 myLastHeadway = (SUMOTime)((double)myLastHeadway / tllink->getGreenFraction());
544 }
545 }
547 }
548 if (lc != nullptr) {
551 }
552}
553
555MESegment::getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const {
556 // compute coefficients for the jam-jam headway function
557 // this function models the effect that "empty space" needs to move
558 // backwards through the downstream segment before the upstream segment may
559 // send annother vehicle.
560 // this allows jams to clear and move upstream.
561 // the headway function f(x) depends on the number of vehicles in the
562 // downstream segment x
563 // f is a linear function that passes through the following fixed points:
564 // f(n_jam_threshold) = tau_jf_withLength (for continuity)
565 // f(headwayCapacity) = myTau_jj * headwayCapacity
566
567 const SUMOTime tau_jf_withLength = tauWithVehLength(myTau_jf, DEFAULT_VEH_LENGTH_WITH_GAP, 1.);
568 // number of vehicles that fit into the NEXT queue (could be larger than expected with DEFAULT_VEH_LENGTH_WITH_GAP!)
569 const double headwayCapacity = MAX2(nextQueueSize, nextQueueCapacity / DEFAULT_VEH_LENGTH_WITH_GAP);
570 // number of vehicles above which the NEXT queue is jammed
571 const double n_jam_threshold = headwayCapacity * nextJamThreshold / nextQueueCapacity;
572
573 // slope a and axis offset b for the jam-jam headway function
574 // solving f(x) = a * x + b
575 const double a = (STEPS2TIME(myTau_jj) * headwayCapacity - STEPS2TIME(tau_jf_withLength)) / (headwayCapacity - n_jam_threshold);
576 const double b = headwayCapacity * (STEPS2TIME(myTau_jj) - a);
577
578 // it is only well defined for nextQueueSize >= n_jam_threshold (which may not be the case for longer vehicles), so we take the MAX
579 return TIME2STEPS(a * MAX2(nextQueueSize, n_jam_threshold) + b);
580}
581
582
583bool
586}
587
588
589void
591 if (veh->getQueIndex() != PARKING_QUEUE) {
592 myQueues[veh->getQueIndex()].addReminders(veh);
593 }
594}
595
596
597void
598MESegment::receive(MEVehicle* veh, const int qIdx, SUMOTime time, const bool isDepart, const bool isTeleport, const bool newEdge) {
599 const double speed = isDepart ? -1 : MAX2(veh->getSpeed(), MESO_MIN_SPEED); // on the previous segment
600 veh->setSegment(this); // for arrival checking
601 veh->setLastEntryTime(time);
603 if (!isDepart && (
604 // arrival on entering a new edge
605 (newEdge && veh->moveRoutePointer())
606 // arrival on entering a new segment
607 || veh->hasArrived())) {
608 // route has ended
609 veh->setEventTime(time + TIME2STEPS(myLength / speed)); // for correct arrival speed
610 addReminders(veh);
612 veh->updateDetectors(time, true,
615 return;
616 }
617 assert(veh->getEdge() == &getEdge());
618 // route continues
619 const double maxSpeedOnEdge = veh->getEdge()->getVehicleMaxSpeed(veh);
620 const double uspeed = MAX2(maxSpeedOnEdge, MESO_MIN_SPEED);
621 Queue& q = myQueues[qIdx];
622 std::vector<MEVehicle*>& cars = q.getModifiableVehicles();
623 MEVehicle* newLeader = nullptr; // first vehicle in the current queue
624 const SUMOTime stopTime = veh->checkStop(time);
625 SUMOTime tleave = MAX2(stopTime + TIME2STEPS(myLength / uspeed) + getLinkPenalty(veh), q.getBlockTime());
626 if (veh->isStopped()) {
627 myEdge.addWaiting(veh);
628 }
629 if (veh->isParking()) {
630 veh->setEventTime(stopTime);
631 veh->setSegment(this, PARKING_QUEUE);
632 myEdge.getLanes()[0]->addParking(veh); // TODO for GUI only
633 } else {
634 myEdge.lock();
635 if (cars.empty()) {
636 cars.push_back(veh);
637 newLeader = veh;
638 } else {
639 SUMOTime leaderOut = cars[0]->getEventTime();
640 if (!isDepart && leaderOut > tleave && overtake()) {
641 if (cars.size() == 1) {
643 newLeader = veh;
644 }
645 cars.insert(cars.begin() + 1, veh);
646 } else {
647 tleave = MAX2(leaderOut + tauWithVehLength(myTau_ff, cars[0]->getVehicleType().getLengthWithGap(), cars[0]->getVehicleType().getCarFollowModel().getHeadwayTime()), tleave);
648 cars.insert(cars.begin(), veh);
649 }
650 }
651 myEdge.unlock();
653 if (!isDepart && !isTeleport) {
654 // departs and teleports could take place anywhere on the edge so they should not block regular flow
655 // the -1 facilitates interleaving of multiple streams
657 }
659 veh->setEventTime(tleave);
660 veh->setSegment(this, qIdx);
661 }
662 addReminders(veh);
663 if (isDepart) {
664 veh->onDepart();
666 } else if (newEdge) {
668 } else {
670 }
671 if (veh->isParking()) {
672 MSGlobals::gMesoNet->addLeaderCar(veh, nullptr);
673 } else {
674 if (newLeader != nullptr) {
675 MSGlobals::gMesoNet->addLeaderCar(newLeader, getLink(newLeader));
676 }
677 }
678}
679
680
681bool
683 for (const Queue& q : myQueues) {
684 if (q.size() > 0) {
685 for (MEVehicle* const veh : q.getVehicles()) {
686 if (filter->vehicleApplies(*veh)) {
689 return true;
690 }
691 }
692 }
693 }
694 return false;
695}
696
697
698void
699MESegment::setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector<MEVehicle*>& vehs) {
700 MEVehicle* v = vehs.back();
701 v->updateDetectors(currentTime, false);
702 SUMOTime newEvent = MAX2(newArrival(v, newSpeed, currentTime), blockTime);
703 if (v->getEventTime() != newEvent) {
705 v->setEventTime(newEvent);
707 }
708 for (std::vector<MEVehicle*>::const_reverse_iterator i = vehs.rbegin() + 1; i != vehs.rend(); ++i) {
709 (*i)->updateDetectors(currentTime, false);
710 newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff);
711 //newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff + (SUMOTime)((*(i - 1))->getVehicleType().getLength() / myTau_length));
712 (*i)->setEventTime(newEvent);
713 }
714}
715
716
718MESegment::newArrival(const MEVehicle* const v, double newSpeed, SUMOTime currentTime) {
719 // since speed is only an upper bound pos may be to optimistic
720 const double pos = MIN2(myLength, STEPS2TIME(currentTime - v->getLastEntryTime()) * v->getSpeed());
721 // traveltime may not be 0
722 return currentTime + MAX2(TIME2STEPS((myLength - pos) / newSpeed), SUMOTime(1));
723}
724
725
726void
727MESegment::setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh) {
728 recomputeJamThreshold(jamThresh);
729 //myTau_length = MAX2(MESO_MIN_SPEED, newSpeed) * myEdge.getLanes().size() / TIME2STEPS(1);
730 for (const Queue& q : myQueues) {
731 if (q.size() != 0) {
732 setSpeedForQueue(newSpeed, currentTime, q.getBlockTime(), q.getVehicles());
733 }
734 }
735}
736
737
740 SUMOTime result = SUMOTime_MAX;
741 for (const Queue& q : myQueues) {
742 if (q.size() != 0 && q.getVehicles().back()->getEventTime() < result) {
743 result = q.getVehicles().back()->getEventTime();
744 }
745 }
746 if (result < SUMOTime_MAX) {
747 return result;
748 }
749 return -1;
750}
751
752
753void
755 bool write = false;
756 for (const Queue& q : myQueues) {
757 if (q.getBlockTime() != -1 || !q.getVehicles().empty()) {
758 write = true;
759 break;
760 }
761 }
762 if (write) {
764 for (const Queue& q : myQueues) {
765 out.openTag(SUMO_TAG_VIEWSETTINGS_VEHICLES).writeAttr(SUMO_ATTR_TIME, toString<SUMOTime>(q.getBlockTime()));
766 out.writeAttr(SUMO_ATTR_VALUE, q.getVehicles());
767 out.closeTag();
768 }
769 out.closeTag();
770 }
771}
772
773
774void
776 for (Queue& q : myQueues) {
777 q.getModifiableVehicles().clear();
778 }
779}
780
781void
782MESegment::loadState(const std::vector<std::string>& vehIds, MSVehicleControl& vc, const SUMOTime block, const int queIdx) {
783 Queue& q = myQueues[queIdx];
784 for (const std::string& id : vehIds) {
785 MEVehicle* v = static_cast<MEVehicle*>(vc.getVehicle(id));
786 // vehicle could be removed due to options
787 if (v != nullptr) {
788 assert(v->getSegment() == this);
789 q.getModifiableVehicles().push_back(v);
792 }
793 }
794 if (q.size() != 0) {
795 // add the last vehicle of this queue
796 // !!! one question - what about the previously added vehicle? Is it stored twice?
797 MEVehicle* veh = q.getVehicles().back();
799 }
800 q.setBlockTime(block);
802}
803
804
805std::vector<const MEVehicle*>
807 std::vector<const MEVehicle*> result;
808 for (const Queue& q : myQueues) {
809 result.insert(result.end(), q.getVehicles().begin(), q.getVehicles().end());
810 }
811 return result;
812}
813
814
815bool
817 for (const Queue& q : myQueues) {
818 if (q.size() > 0 && q.getVehicles().back()->getWaitingTime() > 0) {
819 return true;
820 }
821 }
822 return false;
823}
824
825
826double
828 return 3600 * getCarNumber() * getMeanSpeed() / myLength;
829}
830
831
834 const MSLink* link = getLink(veh, myTLSPenalty || myCheckMinorPenalty);
835 if (link != nullptr) {
836 SUMOTime result = 0;
837 if (link->isTLSControlled()) {
838 result += link->getMesoTLSPenalty();
839 }
840 // minor tls links may get an additional penalty
841 if (!link->havePriority() &&
842 // do not apply penalty on top of tLSPenalty
843 !myTLSPenalty &&
844 // do not apply penalty if limited control is active
846 result += myMinorPenalty;
847 }
848 return result;
849 } else {
850 return 0;
851 }
852}
853
854
855double
857 double result = 0;
858 for (const Queue& q : myQueues) {
859 // @note: only the leader currently accumulates waitingTime but this might change in the future
860 for (const MEVehicle* veh : q.getVehicles()) {
861 result += veh->getWaitingSeconds();
862 }
863 }
864 return result;
865}
866
867
868/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#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:54
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define SUMOTime_MIN
Definition: SUMOTime.h:34
#define SIMTIME
Definition: SUMOTime.h:61
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
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:35
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:342
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:325
bool removeLeaderCar(MEVehicle *v)
Removes the given car from the leading vehicles.
Definition: MELoop.cpp:236
void addLeaderCar(MEVehicle *veh, MSLink *link)
Adds the given car to the leading vehicles.
Definition: MELoop.cpp:223
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
std::vector< MEVehicle * > & getModifiableVehicles()
Definition: MESegment.h:80
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
std::vector< MEVehicle * > myVehicles
Definition: MESegment.h:122
const std::vector< MEVehicle * > & getVehicles() const
Definition: MESegment.h:76
SUMOTime getEntryBlockTime() const
return the next time at which a vehicle may enter this queue
Definition: MESegment.h:94
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:590
double myQueueCapacity
The number of lanes represented by the queue * the length of the lane.
Definition: MESegment.h:553
bool overtake()
Definition: MESegment.cpp:584
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:356
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:507
bool isOpen(const MEVehicle *veh) const
Returns whether the vehicle may use the next link.
Definition: MESegment.cpp:467
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:250
void clearState()
Remove all vehicles before quick-loading state.
Definition: MESegment.cpp:775
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:598
SUMOTime getLinkPenalty(const MEVehicle *veh) const
Returns the penalty time for passing a link (if using gMesoTLSPenalty > 0 or gMesoMinorPenalty > 0)
Definition: MESegment.cpp:833
void writeVehicles(OutputDevice &of) const
Definition: MESegment.cpp:398
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:438
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:699
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:302
void updatePermissions()
called when permissions change due to Rerouter or TraCI
Definition: MESegment.cpp:204
void saveState(OutputDevice &out) const
Saves the state of this segment into the given stream.
Definition: MESegment.cpp:754
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:147
const MSEdge & getEdge() const
Returns the edge this segment belongs to.
Definition: MESegment.h:359
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:520
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:231
SUMOTime myLastMeanSpeedUpdate
the time at which myMeanSpeed was last updated
Definition: MESegment.h:579
SUMOTime myTau_jf
Definition: MESegment.h:530
MESegment * myNextSegment
The next segment of this edge, 0 if this is the last segment of this edge.
Definition: MESegment.h:518
bool hasBlockedLeader() const
whether a leader in any queue is blocked
Definition: MESegment.cpp:816
double getWaitingSeconds() const
Get the waiting time for vehicles in all queues.
Definition: MESegment.cpp:856
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:739
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:408
std::vector< const MEVehicle * > getVehicles() const
returns all vehicles (for debugging)
Definition: MESegment.cpp:806
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:216
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 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:727
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:782
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:718
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:827
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:421
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:279
bool vaporizeAnyCar(SUMOTime currentTime, const MSDetectorFileOutput *filter)
tries to remove any car from this segment
Definition: MESegment.cpp:682
SUMOTime myTau_fj
Definition: MESegment.h:530
SUMOTime getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const
Definition: MESegment.cpp:555
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:125
void processStop()
ends the current stop and performs loading/unloading
Definition: MEVehicle.cpp:320
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge)
Definition: MEVehicle.cpp:159
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:141
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:215
void updateDetectors(SUMOTime currentTime, const bool isLeave, const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_JUNCTION)
Updates all vehicle detectors.
Definition: MEVehicle.cpp:439
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition: MEVehicle.h:260
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves its current segment.
Definition: MEVehicle.h:200
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:230
void setLastEntryTime(SUMOTime t)
Sets the entry time for the current segment.
Definition: MEVehicle.h:252
int getQueIndex() const
Returns the index of the que the vehicle is in.
Definition: MEVehicle.h:238
SUMOTime getWaitingTime() const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:283
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:221
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves its current segment.
Definition: MEVehicle.h:212
void setBlockTime(const SUMOTime t)
Sets the time at which the vehicle was blocked.
Definition: MEVehicle.h:268
double getSpeed() const
Returns the vehicle's estimated speed assuming no delays.
Definition: MEVehicle.cpp:109
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.
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.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
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:747
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition: MSEdge.h:622
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
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:439
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:1056
const MSJunction * getToJunction() const
Definition: MSEdge.h:415
static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored=0)
Definition: MSEdge.cpp:293
bool isRoundabout() const
Definition: MSEdge.h:694
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:431
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition: MSEdge.cpp:1334
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition: MSEdge.cpp:1068
bool hasMinorLink() const
whether any lane has a minor link
Definition: MSEdge.cpp:1247
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition: MSEdge.h:744
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:1156
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:135
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:745
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:707
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:183
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
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 & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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