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