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-2025 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 const std::vector<MSLane*>* const allowed = parent.allowedLanes(*edge);
137 assert(allowed != nullptr);
138 assert(allowed->size() > 0);
139 for (MSLane* const l : *allowed) {
140 std::vector<MSLane*>::const_iterator it = std::find(lanes.begin(), lanes.end(), l);
141 myFollowerMap[edge] |= (1 << distance(lanes.begin(), it));
142 }
143 }
144 }
145 myQueueCapacity = length;
146 } else {
147 myQueues.push_back(Queue(parent.getPermissions()));
148 }
149
150 initSegment(edgeType, parent, length * usableLanes);
151}
152
153void
154MESegment::initSegment(const MesoEdgeType& edgeType, const MSEdge& parent, const double capacity) {
155
156 myCapacity = capacity;
157 if (myQueues.size() == 1) {
158 const double laneScale = capacity / myLength;
159 myQueueCapacity = capacity;
161 // Eissfeldt p. 90 and 151 ff.
162 myTau_ff = (SUMOTime)((double)edgeType.tauff / laneScale);
163 myTau_fj = (SUMOTime)((double)edgeType.taufj / laneScale);
164 myTau_jf = (SUMOTime)((double)edgeType.taujf / laneScale);
165 myTau_jj = (SUMOTime)((double)edgeType.taujj / laneScale);
166 } else {
167 myTau_ff = edgeType.tauff;
168 myTau_fj = edgeType.taufj;
169 myTau_jf = edgeType.taujf;
170 myTau_jj = edgeType.taujj;
171 }
172
174 myTLSPenalty = ((edgeType.tlsPenalty > 0 || edgeType.tlsFlowPenalty > 0) &&
175 // only apply to the last segment of a tls-controlled edge
176 myNextSegment == nullptr && (
180 && !tlsPenaltyOverride());
181
182 // only apply to the last segment of an uncontrolled edge that has at least 1 minor link
183 myCheckMinorPenalty = (edgeType.minorPenalty > 0 &&
184 myNextSegment == nullptr &&
188 parent.hasMinorLink());
189 myMinorPenalty = edgeType.minorPenalty;
191
192 //std::cout << getID() << " myMinorPenalty=" << myMinorPenalty << " myTLSPenalty=" << myTLSPenalty << " myJunctionControl=" << myJunctionControl << " myOvertaking=" << myOvertaking << "\n";
193
195}
196
197MESegment::MESegment(const std::string& id):
198 Named(id),
199 myEdge(myDummyParent), // arbitrary edge needed to supply the needed reference
200 myNextSegment(nullptr), myLength(0), myIndex(0),
201 myTau_ff(0), myTau_fj(0), myTau_jf(0), myTau_jj(0),
202 myTLSPenalty(false),
203 myCheckMinorPenalty(false),
204 myMinorPenalty(0),
205 myJunctionControl(false),
206 myOvertaking(false),
207 myTau_length(1) {
208}
209
210
211void
213 if (myQueues.size() > 1) {
214 for (MSLane* lane : myEdge.getLanes()) {
215 myQueues[lane->getIndex()].setPermissions(lane->getPermissions());
216 }
217 } else {
218 myQueues.back().setPermissions(myEdge.getPermissions());
219 }
220}
221
222
223void
225 if (jamThresh == DO_NOT_PATCH_JAM_THRESHOLD) {
226 return;
227 }
228 if (jamThresh < 0) {
229 // compute based on speed
231 } else {
232 // compute based on specified percentage
233 myJamThreshold = jamThresh * myCapacity;
234 }
235}
236
237
238double
239MESegment::jamThresholdForSpeed(double speed, double jamThresh) const {
240 // vehicles driving freely at maximum speed should not jam
241 // we compute how many vehicles could possible enter the segment until the first vehicle leaves
242 // and multiply by the space these vehicles would occupy
243 // the jamThresh parameter is scale the resulting value
244 if (speed == 0) {
245 return std::numeric_limits<double>::max(); // never jam. Irrelevant at speed 0 anyway
246 }
247#ifdef DEBUG_JAMTHRESHOLD
248 if (true || DEBUG_COND) {
249 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
250 << "\n";
251 }
252#endif
254}
255
256
257void
259 if (queueIndex == -1) {
260 for (Queue& q : myQueues) {
261 q.addDetector(data);
262 }
263 } else {
264 assert(queueIndex < (int)myQueues.size());
265 myQueues[queueIndex].addDetector(data);
266 }
267}
268
269
270/*
271void
272MESegment::removeDetector(MSMoveReminder* data) {
273 std::vector<MSMoveReminder*>::iterator it = std::find(myDetectorData.begin(), myDetectorData.end(), data);
274 if (it != myDetectorData.end()) {
275 myDetectorData.erase(it);
276 }
277 for (const Queue& q : myQueues) {
278 for (MEVehicle* const v : q.getVehicles()) {
279 v->removeReminder(data);
280 }
281 }
282}
283*/
284
285
286void
288 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
289 if (queueIndex == -1) {
290 for (const Queue& q : myQueues) {
291 SUMOTime earliestExitTime = currentTime;
292 for (std::vector<MEVehicle*>::const_reverse_iterator i = q.getVehicles().rbegin(); i != q.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 } else {
299 SUMOTime earliestExitTime = currentTime;
300 for (std::vector<MEVehicle*>::const_reverse_iterator i = myQueues[queueIndex].getVehicles().rbegin(); i != myQueues[queueIndex].getVehicles().rend(); ++i) {
301 const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
302 (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
303 earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
304 }
305 }
306}
307
308
310MESegment::hasSpaceFor(const MEVehicle* const veh, const SUMOTime entryTime, int& qIdx, const bool init) const {
311 SUMOTime earliestEntry = SUMOTime_MAX;
312 qIdx = 0;
313 if (myNumVehicles == 0 && myQueues.size() == 1) {
314 // we have always space for at least one vehicle
315 if (myQueues.front().allows(veh->getVClass())) {
316 return entryTime;
317 } else {
318 return earliestEntry;
319 }
320 }
321 const SUMOVehicleClass svc = veh->getVClass();
322 int minSize = std::numeric_limits<int>::max();
323 const MSEdge* const succ = myNextSegment == nullptr ? veh->succEdge(veh->getEdge() == &myEdge ? 1 : 2) : nullptr;
324 for (int i = 0; i < (int)myQueues.size(); i++) {
325 const Queue& q = myQueues[i];
326 const double newOccupancy = q.size() == 0 ? 0. : q.getOccupancy() + veh->getVehicleType().getLengthWithGap();
327 if (newOccupancy <= myQueueCapacity) { // we must ensure that occupancy remains below capacity
328 if (succ == nullptr || myFollowerMap.count(succ) == 0 || ((myFollowerMap.find(succ)->second & (1 << i)) != 0)) {
329 if (q.allows(svc) && q.size() < minSize) {
330 if (init) {
331 // regular insertions and initial insertions must respect different constraints:
332 // - regular insertions must respect entryBlockTime
333 // - initial insertions should not cause additional jamming
334 // - inserted vehicle should be able to continue at the current speed
335 if (veh->getInsertionChecks() == (int)InsertionCheck::NONE) {
336 qIdx = i;
337 minSize = q.size();
338 } else if (q.getOccupancy() <= myJamThreshold && !hasBlockedLeader() && !myTLSPenalty) {
339 if (newOccupancy <= myJamThreshold) {
340 qIdx = i;
341 minSize = q.size();
342 }
343 } else {
344 if (newOccupancy <= jamThresholdForSpeed(getMeanSpeed(false), -1)) {
345 qIdx = i;
346 minSize = q.size();
347 }
348 }
349 } else if (entryTime >= q.getEntryBlockTime()) {
350 qIdx = i;
351 minSize = q.size();
352 } else {
353 earliestEntry = MIN2(earliestEntry, q.getEntryBlockTime());
354 }
355 }
356 }
357 }
358 }
359 if (minSize == std::numeric_limits<int>::max()) {
360 return earliestEntry;
361 }
362 return entryTime;
363}
364
365
366bool
368 int qIdx = 0;
369 if (hasSpaceFor(veh, time, qIdx, true) == time) {
370 receive(veh, qIdx, time, true);
371 // we can check only after insertion because insertion may change the route via devices
372 std::string msg;
373 if (MSGlobals::gCheckRoutes && !veh->hasValidRoute(msg)) {
374 throw ProcessError(TLF("Vehicle '%' has no valid route. %", veh->getID(), msg));
375 }
376 return true;
377 }
378 return false;
379}
380
381
382double
383MESegment::getMeanSpeed(bool useCached) const {
384 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
385 if (currentTime != myLastMeanSpeedUpdate || !useCached) {
386 myLastMeanSpeedUpdate = currentTime;
387 double v = 0;
388 int count = 0;
389 for (const Queue& q : myQueues) {
390 const SUMOTime tau = q.getOccupancy() < myJamThreshold ? myTau_ff : myTau_jf;
391 SUMOTime earliestExitTime = currentTime;
392 count += q.size();
393 for (std::vector<MEVehicle*>::const_reverse_iterator veh = q.getVehicles().rbegin(); veh != q.getVehicles().rend(); ++veh) {
394 v += (*veh)->getConservativeSpeed(earliestExitTime); // earliestExitTime is updated!
395 earliestExitTime += tauWithVehLength(tau, (*veh)->getVehicleType().getLengthWithGap(), (*veh)->getVehicleType().getCarFollowModel().getHeadwayTime());
396 }
397 }
398 if (count == 0) {
400 } else {
401 myMeanSpeed = v / (double) count;
402 }
403 }
404 return myMeanSpeed;
405}
406
407
408void
412
413void
415 for (const Queue& q : myQueues) {
416 for (const MEVehicle* const veh : q.getVehicles()) {
418 }
419 }
420}
421
422
425 Queue& q = myQueues[v->getQueIndex()];
426 // One could be tempted to do v->setSegment(next); here but position on lane will be invalid if next == 0
427 v->updateDetectors(leaveTime, v->getEventTime(), true, reason);
429 myEdge.lock();
430 MEVehicle* nextLeader = q.remove(v);
431 myEdge.unlock();
432 return nextLeader;
433}
434
435
438 // since we do not know which queue will be used we give a conservative estimate
439 SUMOTime earliestLeave = earliestEntry;
440 SUMOTime latestEntry = -1;
441 for (const Queue& q : myQueues) {
442 earliestLeave = MAX2(earliestLeave, q.getBlockTime());
443 latestEntry = MAX2(latestEntry, q.getEntryBlockTime());
444 }
445 if (myEdge.getSpeedLimit() == 0) {
446 return MAX2(earliestEntry, latestEntry); // FIXME: This line is just an adhoc-fix to avoid division by zero (Leo)
447 } else {
448 return MAX3(earliestEntry, earliestLeave - TIME2STEPS(myLength / myEdge.getSpeedLimit()), latestEntry);
449 }
450}
451
452
453MSLink*
454MESegment::getLink(const MEVehicle* veh, bool penalty) const {
455 if (myJunctionControl || penalty) {
456 const MSEdge* const nextEdge = veh->succEdge(1);
457 if (nextEdge == nullptr || veh->getQueIndex() == PARKING_QUEUE) {
458 return nullptr;
459 }
460 // try to find any link leading to our next edge, start with the lane pointed to by the que index
461 const MSLane* const bestLane = myEdge.getLanes()[veh->getQueIndex()];
462 for (MSLink* const link : bestLane->getLinkCont()) {
463 if (&link->getLane()->getEdge() == nextEdge) {
464 return link;
465 }
466 }
467 // this is for the non-multique case, maybe we should use caching here !!!
468 for (const MSLane* const lane : myEdge.getLanes()) {
469 if (lane != bestLane) {
470 for (MSLink* const link : lane->getLinkCont()) {
471 if (&link->getLane()->getEdge() == nextEdge) {
472 return link;
473 }
474 }
475 }
476 }
477 }
478 return nullptr;
479}
480
481
482bool
483MESegment::isOpen(const MEVehicle* veh) const {
484#ifdef DEBUG_OPENED
485 if (DEBUG_COND || DEBUG_COND2(veh)) {
486 gDebugFlag1 = true;
487 std::cout << SIMTIME << " opened seg=" << getID() << " veh=" << Named::getIDSecure(veh)
488 << " tlsPenalty=" << myTLSPenalty;
489 const MSLink* link = getLink(veh);
490 if (link == 0) {
491 std::cout << " link=0";
492 } else {
493 std::cout << " prio=" << link->havePriority()
494 << " override=" << limitedControlOverride(link)
495 << " isOpen=" << link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
498 0, nullptr, false, veh)
499 << " et=" << veh->getEventTime()
500 << " v=" << veh->getSpeed()
501 << " vLeave=" << veh->estimateLeaveSpeed(link)
502 << " impatience=" << veh->getImpatience()
503 << " tWait=" << veh->getWaitingTime();
504 }
505 std::cout << "\n";
506 gDebugFlag1 = false;
507 }
508#endif
509 if (myTLSPenalty) {
510 // XXX should limited control take precedence over tls penalty?
511 return true;
512 }
513 const MSLink* link = getLink(veh);
514 return (link == nullptr
515 || link->havePriority()
517 || link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
520 0, nullptr, false, veh));
521}
522
523
524bool
526 assert(link != nullptr);
528 return false;
529 }
530 // if the target segment of this link is not saturated junction control is disabled
531 const MSEdge& targetEdge = link->getLane()->getEdge();
532 const MESegment* target = MSGlobals::gMesoNet->getSegmentForEdge(targetEdge);
533 return (target->getBruttoOccupancy() * 2 < target->myJamThreshold) && !targetEdge.isRoundabout();
534}
535
536
537void
538MESegment::send(MEVehicle* veh, MESegment* const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason) {
539 Queue& q = myQueues[veh->getQueIndex()];
540 assert(isInvalid(next) || time >= q.getBlockTime());
541 MSLink* const link = getLink(veh);
542 if (link != nullptr) {
543 link->removeApproaching(veh);
544 }
545 if (veh->isStopped()) {
546 veh->processStop();
547 }
548 MEVehicle* lc = removeCar(veh, time, reason); // new leaderCar
549 q.setBlockTime(time);
550 if (!isInvalid(next)) {
551 const bool nextFree = next->myQueues[nextQIdx].getOccupancy() <= next->myJamThreshold;
552 const SUMOTime tau = (q.getOccupancy() <= myJamThreshold
553 ? (nextFree ? myTau_ff : myTau_fj)
554 : (nextFree ? myTau_jf : getTauJJ((double)next->myQueues[nextQIdx].size(), next->myQueueCapacity, next->myJamThreshold)));
555 assert(tau >= 0);
557 if (myTLSPenalty) {
558 const MSLink* const tllink = getLink(veh, true);
559 if (tllink != nullptr && tllink->isTLSControlled()) {
560 assert(tllink->getGreenFraction() > 0);
561 myLastHeadway = (SUMOTime)((double)myLastHeadway / tllink->getGreenFraction());
562 }
563 }
565 }
566 if (lc != nullptr) {
569 }
570}
571
573MESegment::getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const {
574 // compute coefficients for the jam-jam headway function
575 // this function models the effect that "empty space" needs to move
576 // backwards through the downstream segment before the upstream segment may
577 // send annother vehicle.
578 // this allows jams to clear and move upstream.
579 // the headway function f(x) depends on the number of vehicles in the
580 // downstream segment x
581 // f is a linear function that passes through the following fixed points:
582 // f(n_jam_threshold) = tau_jf_withLength (for continuity)
583 // f(headwayCapacity) = myTau_jj * headwayCapacity
584
585 const SUMOTime tau_jf_withLength = tauWithVehLength(myTau_jf, DEFAULT_VEH_LENGTH_WITH_GAP, 1.);
586 // number of vehicles that fit into the NEXT queue (could be larger than expected with DEFAULT_VEH_LENGTH_WITH_GAP!)
587 const double headwayCapacity = MAX2(nextQueueSize, nextQueueCapacity / DEFAULT_VEH_LENGTH_WITH_GAP);
588 // number of vehicles above which the NEXT queue is jammed
589 const double n_jam_threshold = headwayCapacity * nextJamThreshold / nextQueueCapacity;
590
591 // slope a and axis offset b for the jam-jam headway function
592 // solving f(x) = a * x + b
593 const double a = (STEPS2TIME(myTau_jj) * headwayCapacity - STEPS2TIME(tau_jf_withLength)) / (headwayCapacity - n_jam_threshold);
594 const double b = headwayCapacity * (STEPS2TIME(myTau_jj) - a);
595
596 // it is only well defined for nextQueueSize >= n_jam_threshold (which may not be the case for longer vehicles), so we take the MAX
597 return TIME2STEPS(a * MAX2(nextQueueSize, n_jam_threshold) + b);
598}
599
600
601bool
605
606
607void
609 if (veh->getQueIndex() != PARKING_QUEUE) {
610 myQueues[veh->getQueIndex()].addReminders(veh);
611 }
612}
613
614
615void
616MESegment::receive(MEVehicle* veh, const int qIdx, SUMOTime time, const bool isDepart, const bool isTeleport, const bool newEdge) {
617 const double speed = isDepart ? -1 : MAX2(veh->getSpeed(), MESO_MIN_SPEED); // on the previous segment
618 veh->setSegment(this); // for arrival checking
619 veh->setLastEntryTime(time);
621 if (!isDepart && (
622 // arrival on entering a new edge
623 (newEdge && veh->moveRoutePointer())
624 // arrival on entering a new segment
625 || veh->hasArrived())) {
626 // route has ended
627 veh->setEventTime(time + TIME2STEPS(myLength / speed)); // for correct arrival speed
628 addReminders(veh);
630 veh->updateDetectors(time, veh->getEventTime(), true,
633 return;
634 }
635 assert(veh->getEdge() == &getEdge());
636 // route continues
637 Queue& q = myQueues[qIdx];
638 const double maxSpeedOnEdge = veh->getEdge()->getLanes()[qIdx]->getVehicleMaxSpeed(veh);
639 const double uspeed = MAX2(maxSpeedOnEdge, MESO_MIN_SPEED);
640 std::vector<MEVehicle*>& cars = q.getModifiableVehicles();
641 MEVehicle* newLeader = nullptr; // first vehicle in the current queue
642 const SUMOTime stopTime = veh->checkStop(time);
643 SUMOTime tleave = MAX2(stopTime + TIME2STEPS(myLength / uspeed) + getLinkPenalty(veh), q.getBlockTime());
644 if (veh->isStopped()) {
645 myEdge.addWaiting(veh);
646 }
647 if (veh->isParking()) {
648 // parking stops should take at least 1ms
649 veh->setEventTime(MAX2(stopTime, veh->getEventTime() + 1));
650 veh->setSegment(this, PARKING_QUEUE);
651 myEdge.getLanes()[0]->addParking(veh); // TODO for GUI only
652 } else {
653 myEdge.lock();
654 if (cars.empty()) {
655 cars.push_back(veh);
656 newLeader = veh;
657 } else {
658 SUMOTime leaderOut = cars[0]->getEventTime();
659 if (!isDepart && leaderOut > tleave && overtake()) {
660 if (cars.size() == 1) {
662 newLeader = veh;
663 }
664 cars.insert(cars.begin() + 1, veh);
665 } else {
666 tleave = MAX2(leaderOut + tauWithVehLength(myTau_ff, cars[0]->getVehicleType().getLengthWithGap(), cars[0]->getVehicleType().getCarFollowModel().getHeadwayTime()), tleave);
667 cars.insert(cars.begin(), veh);
668 }
669 }
670 myEdge.unlock();
672 if (!isDepart && !isTeleport) {
673 // departs and teleports could take place anywhere on the edge so they should not block regular flow
674 // the -1 facilitates interleaving of multiple streams
676 }
678 veh->setEventTime(tleave);
679 veh->setSegment(this, qIdx);
680 }
681 addReminders(veh);
682 if (isDepart) {
683 veh->onDepart();
685 } else if (newEdge) {
687 } else {
689 }
690 if (veh->isParking()) {
691 MSGlobals::gMesoNet->addLeaderCar(veh, nullptr);
692 } else {
693 if (newLeader != nullptr) {
694 MSGlobals::gMesoNet->addLeaderCar(newLeader, getLink(newLeader));
695 }
696 }
697}
698
699
700bool
702 for (const Queue& q : myQueues) {
703 if (q.size() > 0) {
704 for (MEVehicle* const veh : q.getVehicles()) {
705 if (filter->vehicleApplies(*veh)) {
708 return true;
709 }
710 }
711 }
712 }
713 return false;
714}
715
716
717void
718MESegment::setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector<MEVehicle*>& vehs) {
719 MEVehicle* v = vehs.back();
720 SUMOTime oldEarliestExitTime = currentTime;
721 const SUMOTime oldExit = MAX2(oldEarliestExitTime, v->getEventTime());
722 v->updateDetectors(currentTime, oldExit, false);
724 SUMOTime newEvent = MAX2(newArrival(v, newSpeed, currentTime), blockTime);
725 if (v->getEventTime() != newEvent) {
727 v->setEventTime(newEvent);
729 }
730 for (std::vector<MEVehicle*>::const_reverse_iterator i = vehs.rbegin() + 1; i != vehs.rend(); ++i) {
731 const SUMOTime oldExitTime = MAX2(oldEarliestExitTime, (*i)->getEventTime());
732 (*i)->updateDetectors(currentTime, oldExitTime, false);
733 const SUMOTime minTau = tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
734 oldEarliestExitTime = oldExitTime + minTau;
735 newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + minTau);
736 (*i)->setEventTime(newEvent);
737 }
738}
739
740
742MESegment::newArrival(const MEVehicle* const v, double newSpeed, SUMOTime currentTime) {
743 // since speed is only an upper bound, pos may be too optimistic
744 const double pos = MIN2(myLength, STEPS2TIME(currentTime - v->getLastEntryTime()) * v->getSpeed());
745 // traveltime may not be 0
746 double tt = (myLength - pos) / MAX2(newSpeed, MESO_MIN_SPEED);
747 return currentTime + MAX2(TIME2STEPS(tt), SUMOTime(1));
748}
749
750
751void
752MESegment::setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh, int qIdx) {
753 recomputeJamThreshold(jamThresh);
754 //myTau_length = MAX2(MESO_MIN_SPEED, newSpeed) * myEdge.getLanes().size() / TIME2STEPS(1);
755 int i = 0;
756 for (const Queue& q : myQueues) {
757 if (q.size() != 0) {
758 if (qIdx == -1 || qIdx == i) {
759 setSpeedForQueue(newSpeed, currentTime, q.getBlockTime(), q.getVehicles());
760 }
761 }
762 i++;
763 }
764}
765
766
769 SUMOTime result = SUMOTime_MAX;
770 for (const Queue& q : myQueues) {
771 if (q.size() != 0 && q.getVehicles().back()->getEventTime() < result) {
772 result = q.getVehicles().back()->getEventTime();
773 }
774 }
775 if (result < SUMOTime_MAX) {
776 return result;
777 }
778 return -1;
779}
780
781
782void
784 bool write = false;
785 for (const Queue& q : myQueues) {
786 if (q.getBlockTime() != -1 || !q.getVehicles().empty()) {
787 write = true;
788 break;
789 }
790 }
791 if (write) {
793 for (const Queue& q : myQueues) {
795 out.writeAttr(SUMO_ATTR_TIME, toString<SUMOTime>(q.getBlockTime()));
796 out.writeAttr(SUMO_ATTR_BLOCKTIME, toString<SUMOTime>(q.getEntryBlockTime()));
797 out.writeAttr(SUMO_ATTR_VALUE, q.getVehicles());
798 out.closeTag();
799 }
800 out.closeTag();
801 }
802}
803
804
805void
807 for (Queue& q : myQueues) {
808 q.getModifiableVehicles().clear();
809 }
810}
811
812void
813MESegment::loadState(const std::vector<SUMOVehicle*>& vehs, const SUMOTime blockTime, const SUMOTime entryBlockTime, const int queIdx) {
814 Queue& q = myQueues[queIdx];
815 for (SUMOVehicle* veh : vehs) {
816 MEVehicle* v = static_cast<MEVehicle*>(veh);
817 assert(v->getSegment() == this);
818 q.getModifiableVehicles().push_back(v);
821 addReminders(v);
822 }
823 if (q.size() != 0) {
824 // add the last vehicle of this queue
825 // !!! one question - what about the previously added vehicle? Is it stored twice?
826 MEVehicle* veh = q.getVehicles().back();
828 }
829 q.setBlockTime(blockTime);
830 q.setEntryBlockTime(entryBlockTime);
832}
833
834
835std::vector<const MEVehicle*>
837 std::vector<const MEVehicle*> result;
838 for (const Queue& q : myQueues) {
839 result.insert(result.end(), q.getVehicles().begin(), q.getVehicles().end());
840 }
841 return result;
842}
843
844
845bool
847 for (const Queue& q : myQueues) {
848 if (q.size() > 0 && q.getVehicles().back()->getWaitingTime() > 0) {
849 return true;
850 }
851 }
852 return false;
853}
854
855
856double
858 return 3600 * getCarNumber() * getMeanSpeed() / myLength;
859}
860
861
864 const MSLink* link = getLink(veh, myTLSPenalty || myCheckMinorPenalty);
865 if (link != nullptr) {
866 SUMOTime result = 0;
867 if (link->isTLSControlled() && myTLSPenalty) {
868 result += link->getMesoTLSPenalty();
869 }
870 // minor tls links may get an additional penalty
871 if (!link->havePriority() &&
872 // do not apply penalty on top of tLSPenalty
873 !myTLSPenalty &&
874 // do not apply penalty if limited control is active
876 result += myMinorPenalty;
877 }
878 return result;
879 } else {
880 return 0;
881 }
882}
883
884
885bool
887 for (const MSLane* lane : myEdge.getLanes()) {
888 for (const MSLink* link : lane->getLinkCont()) {
889 if (link->isTLSControlled() && StringUtils::toBool(link->getTLLogic()->getParameter(OVERRIDE_TLS_PENALTIES, "0"))) {
890 return true;
891 }
892 }
893 }
894 return false;
895}
896
897
898double
900 double result = 0;
901 for (const Queue& q : myQueues) {
902 // @note: only the leader currently accumulates waitingTime but this might change in the future
903 for (const MEVehicle* veh : q.getVehicles()) {
904 result += veh->getWaitingSeconds();
905 }
906 }
907 return result;
908}
909
910
911/****************************************************************************/
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:55
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SUMOTime_MIN
Definition SUMOTime.h:35
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SUMO_TAG_VIEWSETTINGS_VEHICLES
@ SUMO_TAG_SEGMENT
segment of a lane
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_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:357
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:340
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:75
void setOccupancy(const double occ)
Definition MESegment.h:88
MEVehicle * remove(MEVehicle *v)
Definition MESegment.cpp:70
void setBlockTime(SUMOTime t)
Definition MESegment.h:108
SUMOTime getBlockTime() const
Definition MESegment.h:105
double myOccupancy
The occupied space (in m) in the queue.
Definition MESegment.h:127
bool allows(SUMOVehicleClass vclass) const
Definition MESegment.h:91
std::vector< MEVehicle * > & getModifiableVehicles()
Definition MESegment.h:82
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:101
double getOccupancy() const
Definition MESegment.h:85
std::vector< MEVehicle * > myVehicles
Definition MESegment.h:124
const std::vector< MEVehicle * > & getVehicles() const
Definition MESegment.h:78
SUMOTime getEntryBlockTime() const
return the next time at which a vehicle may enter this queue
Definition MESegment.h:96
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:560
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:511
SUMOTime myTau_ff
The time headway parameters, see the Eissfeldt thesis.
Definition MESegment.h:537
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:566
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition MESegment.h:260
SUMOTime myLastHeadway
the last headway
Definition MESegment.h:575
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 tlsPenaltyOverride() const
whether the traffic light should use normal junction control despite penalty options
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:572
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:569
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:364
static MESegment myVaporizationTarget
Definition MESegment.h:580
double myJamThreshold
The space (in m) which needs to be occupied before the segment is considered jammed.
Definition MESegment.h:563
const int myIndex
Running number of the segment in the edge.
Definition MESegment.h:531
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:544
double myMeanSpeed
the mean speed on this segment. Updated at event time or on demand
Definition MESegment.h:583
bool myCheckMinorPenalty
penalty for minor links
Definition MESegment.h:543
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:586
SUMOTime myTau_jf
Definition MESegment.h:537
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:525
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:528
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:522
static const std::string OVERRIDE_TLS_PENALTIES
Definition MESegment.h:54
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:579
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:299
int getCarNumber() const
Returns the total number of cars on the segment.
Definition MESegment.h:208
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:554
SUMOTime myTau_jj
Definition MESegment.h:537
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:547
bool myTLSPenalty
Whether tls penalty is enabled.
Definition MESegment.h:540
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:447
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:557
bool myOvertaking
Whether overtaking is permitted on this segment.
Definition MESegment.h:550
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:537
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:788
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition MSEdge.h:657
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:482
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:1168
const MSJunction * getToJunction() const
Definition MSEdge.h:426
static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored=0)
Definition MSEdge.cpp:318
bool isRoundabout() const
Definition MSEdge.h:729
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:442
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1461
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1360
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition MSEdge.h:785
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1268
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:769
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:729
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:186
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:62
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter
#define DEBUG_COND
edge type specific meso parameters
Definition MESegment.h:57