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>
40#include "MEVehicle.h"
41#include "MELoop.h"
42#include "MESegment.h"
43
44#define DEFAULT_VEH_LENGTH_WITH_GAP (SUMOVTypeParameter::getDefault().length + SUMOVTypeParameter::getDefault().minGap)
45// avoid division by zero when driving very slowly
46#define MESO_MIN_SPEED (0.05)
47
48//#define DEBUG_OPENED
49//#define DEBUG_JAMTHRESHOLD
50//#define DEBUG_COND (getID() == "blocker")
51//#define DEBUG_COND (true)
52#define DEBUG_COND (myEdge.isSelected())
53#define DEBUG_COND2(obj) ((obj != 0 && (obj)->isSelected()))
54
55
56// ===========================================================================
57// static member definition
58// ===========================================================================
59MSEdge MESegment::myDummyParent("MESegmentDummyParent", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
60MESegment MESegment::myVaporizationTarget("vaporizationTarget");
61const double MESegment::DO_NOT_PATCH_JAM_THRESHOLD(std::numeric_limits<double>::max());
62const std::string MESegment::OVERRIDE_TLS_PENALTIES("meso.tls.control");
63
64
65// ===========================================================================
66// MESegment::Queue method definitions
67// ===========================================================================
71 assert(std::find(myVehicles.begin(), myVehicles.end(), v) != myVehicles.end());
72 if (v == myVehicles.back()) {
73 myVehicles.pop_back();
74 if (myVehicles.empty()) {
75 myOccupancy = 0.;
76 } else {
77 return myVehicles.back();
78 }
79 } else {
80 myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), v));
81 }
82 return nullptr;
83}
84
85void
87 myDetectorData.push_back(data);
88 for (MEVehicle* const v : myVehicles) {
89 v->addReminder(data);
90 }
91}
92
93void
95 for (MSMoveReminder* rem : myDetectorData) {
96 veh->addReminder(rem);
97 }
98}
99
100// ===========================================================================
101// MESegment method definitions
102// ===========================================================================
103MESegment::MESegment(const std::string& id,
104 const MSEdge& parent, MESegment* next,
105 const double length, const double speed,
106 const int idx,
107 const bool multiQueue,
108 const MesoEdgeType& edgeType):
109 Named(id), myEdge(parent), myNextSegment(next),
110 myLength(length), myIndex(idx),
112 myNumVehicles(0),
114 myMeanSpeed(speed),
116
117 const std::vector<MSLane*>& lanes = parent.getLanes();
118 int usableLanes = 0;
119 for (MSLane* const l : lanes) {
120 const SVCPermissions allow = MSEdge::getMesoPermissions(l->getPermissions());
121 if (multiQueue) {
122 myQueues.push_back(Queue(allow));
123 }
124 if (allow != 0) {
125 usableLanes++;
126 }
127 }
128 if (usableLanes == 0) {
129 // cars won't drive here. Give sensible tau values capacity for the ignored classes
130 usableLanes = 1;
131 }
132 if (multiQueue) {
133 if (next == nullptr) {
134 for (const MSEdge* const edge : parent.getSuccessors()) {
135 const std::vector<MSLane*>* const allowed = parent.allowedLanes(*edge);
136 assert(allowed != nullptr);
137 assert(allowed->size() > 0);
138 for (MSLane* const l : *allowed) {
139 std::vector<MSLane*>::const_iterator it = std::find(lanes.begin(), lanes.end(), l);
140 myFollowerMap[edge] |= (1 << distance(lanes.begin(), it));
141 }
142 }
143 }
144 myQueueCapacity = length;
145 } else {
146 myQueues.push_back(Queue(parent.getPermissions()));
147 }
148
149 initSegment(edgeType, parent, length * usableLanes);
150}
151
152void
153MESegment::initSegment(const MesoEdgeType& edgeType, const MSEdge& parent, const double capacity) {
154
155 myCapacity = capacity;
156 if (myQueues.size() == 1) {
157 const double laneScale = capacity / myLength;
158 myQueueCapacity = capacity;
160 // Eissfeldt p. 90 and 151 ff.
161 myTau_ff = (SUMOTime)((double)edgeType.tauff / laneScale);
162 myTau_fj = (SUMOTime)((double)edgeType.taufj / laneScale);
163 myTau_jf = (SUMOTime)((double)edgeType.taujf / laneScale);
164 myTau_jj = (SUMOTime)((double)edgeType.taujj / laneScale);
165 } else {
166 myTau_ff = edgeType.tauff;
167 myTau_fj = edgeType.taufj;
168 myTau_jf = edgeType.taujf;
169 myTau_jj = edgeType.taujj;
170 }
171
173 myTLSPenalty = ((edgeType.tlsPenalty > 0 || edgeType.tlsFlowPenalty > 0) &&
174 // only apply to the last segment of a tls-controlled edge
175 myNextSegment == nullptr && (
179 && !tlsPenaltyOverride());
180
181 // only apply to the last segment of an uncontrolled edge that has at least 1 minor link
182 myCheckMinorPenalty = (edgeType.minorPenalty > 0 &&
183 myNextSegment == nullptr &&
187 parent.hasMinorLink());
188 myMinorPenalty = edgeType.minorPenalty;
190
191 //std::cout << getID() << " myMinorPenalty=" << myMinorPenalty << " myTLSPenalty=" << myTLSPenalty << " myJunctionControl=" << myJunctionControl << " myOvertaking=" << myOvertaking << "\n";
192
194}
195
196MESegment::MESegment(const std::string& id):
197 Named(id),
198 myEdge(myDummyParent), // arbitrary edge needed to supply the needed reference
199 myNextSegment(nullptr), myLength(0), myIndex(0),
200 myTau_ff(0), myTau_fj(0), myTau_jf(0), myTau_jj(0),
201 myTLSPenalty(false),
202 myCheckMinorPenalty(false),
203 myMinorPenalty(0),
204 myJunctionControl(false),
205 myOvertaking(false),
206 myTau_length(1) {
207}
208
209
210void
212 if (myQueues.size() > 1) {
213 for (MSLane* lane : myEdge.getLanes()) {
214 myQueues[lane->getIndex()].setPermissions(lane->getPermissions());
215 }
216 } else {
217 myQueues.back().setPermissions(myEdge.getPermissions());
218 }
219}
220
221
222void
224 if (jamThresh == DO_NOT_PATCH_JAM_THRESHOLD) {
225 return;
226 }
227 if (jamThresh < 0) {
228 // compute based on speed
230 } else {
231 // compute based on specified percentage
232 myJamThreshold = jamThresh * myCapacity;
233 }
234}
235
236
237double
238MESegment::jamThresholdForSpeed(double speed, double jamThresh) const {
239 // vehicles driving freely at maximum speed should not jam
240 // we compute how many vehicles could possible enter the segment until the first vehicle leaves
241 // and multiply by the space these vehicles would occupy
242 // the jamThresh parameter is scale the resulting value
243 if (speed == 0) {
244 return std::numeric_limits<double>::max(); // never jam. Irrelevant at speed 0 anyway
245 }
246#ifdef DEBUG_JAMTHRESHOLD
247 if (true || DEBUG_COND) {
248 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
249 << "\n";
250 }
251#endif
253}
254
255
256void
258 if (queueIndex == -1) {
259 for (Queue& q : myQueues) {
260 q.addDetector(data);
261 }
262 } else {
263 assert(queueIndex < (int)myQueues.size());
264 myQueues[queueIndex].addDetector(data);
265 }
266}
267
268
269/*
270void
271MESegment::removeDetector(MSMoveReminder* data) {
272 std::vector<MSMoveReminder*>::iterator it = std::find(myDetectorData.begin(), myDetectorData.end(), data);
273 if (it != myDetectorData.end()) {
274 myDetectorData.erase(it);
275 }
276 for (const Queue& q : myQueues) {
277 for (MEVehicle* const v : q.getVehicles()) {
278 v->removeReminder(data);
279 }
280 }
281}
282*/
283
284
285void
287 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
288 if (queueIndex == -1) {
289 for (const Queue& q : myQueues) {
290 SUMOTime earliestExitTime = currentTime;
291 for (std::vector<MEVehicle*>::const_reverse_iterator i = q.getVehicles().rbegin(); i != q.getVehicles().rend(); ++i) {
292 const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
293 (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
294 earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
295 }
296 }
297 } else {
298 SUMOTime earliestExitTime = currentTime;
299 for (std::vector<MEVehicle*>::const_reverse_iterator i = myQueues[queueIndex].getVehicles().rbegin(); i != myQueues[queueIndex].getVehicles().rend(); ++i) {
300 const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
301 (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
302 earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
303 }
304 }
305}
306
307
309MESegment::hasSpaceFor(const MEVehicle* const veh, const SUMOTime entryTime, int& qIdx, const bool init) const {
310 SUMOTime earliestEntry = SUMOTime_MAX;
311 qIdx = 0;
312 if (myNumVehicles == 0 && myQueues.size() == 1) {
313 // we have always space for at least one vehicle
314 if (myQueues.front().allows(veh->getVClass())) {
315 return entryTime;
316 } else {
317 return earliestEntry;
318 }
319 }
320 const SUMOVehicleClass svc = veh->getVClass();
321 int minSize = std::numeric_limits<int>::max();
322 const MSEdge* const succ = myNextSegment == nullptr ? veh->succEdge(veh->getEdge() == &myEdge ? 1 : 2) : nullptr;
323 for (int i = 0; i < (int)myQueues.size(); i++) {
324 const Queue& q = myQueues[i];
325 const double newOccupancy = q.size() == 0 ? 0. : q.getOccupancy() + veh->getVehicleType().getLengthWithGap();
326 if (newOccupancy <= myQueueCapacity) { // we must ensure that occupancy remains below capacity
327 if (succ == nullptr || myFollowerMap.count(succ) == 0 || ((myFollowerMap.find(succ)->second & (1 << i)) != 0)) {
328 if (q.allows(svc) && q.size() < minSize) {
329 if (init) {
330 // regular insertions and initial insertions must respect different constraints:
331 // - regular insertions must respect entryBlockTime
332 // - initial insertions should not cause additional jamming
333 // - inserted vehicle should be able to continue at the current speed
334 if (veh->getInsertionChecks() == (int)InsertionCheck::NONE) {
335 qIdx = i;
336 minSize = q.size();
337 } else if (q.getOccupancy() <= myJamThreshold && !hasBlockedLeader() && !myTLSPenalty) {
338 if (newOccupancy <= myJamThreshold) {
339 qIdx = i;
340 minSize = q.size();
341 }
342 } else {
343 if (newOccupancy <= jamThresholdForSpeed(getMeanSpeed(false), -1)) {
344 qIdx = i;
345 minSize = q.size();
346 }
347 }
348 } else if (entryTime >= q.getEntryBlockTime()) {
349 qIdx = i;
350 minSize = q.size();
351 } else {
352 earliestEntry = MIN2(earliestEntry, q.getEntryBlockTime());
353 }
354 }
355 }
356 }
357 }
358 if (minSize == std::numeric_limits<int>::max()) {
359 return earliestEntry;
360 }
361 return entryTime;
362}
363
364
365bool
367 int qIdx = 0;
368 if (hasSpaceFor(veh, time, qIdx, true) == time) {
369 receive(veh, qIdx, time, true);
370 // we can check only after insertion because insertion may change the route via devices
371 std::string msg;
372 if (MSGlobals::gCheckRoutes && !veh->hasValidRoute(msg)) {
373 throw ProcessError("Vehicle '" + veh->getID() + "' has no valid route. " + msg);
374 }
375 return true;
376 }
377 return false;
378}
379
380
381double
382MESegment::getMeanSpeed(bool useCached) const {
383 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
384 if (currentTime != myLastMeanSpeedUpdate || !useCached) {
385 myLastMeanSpeedUpdate = currentTime;
386 double v = 0;
387 int count = 0;
388 for (const Queue& q : myQueues) {
389 const SUMOTime tau = q.getOccupancy() < myJamThreshold ? myTau_ff : myTau_jf;
390 SUMOTime earliestExitTime = currentTime;
391 count += q.size();
392 for (std::vector<MEVehicle*>::const_reverse_iterator veh = q.getVehicles().rbegin(); veh != q.getVehicles().rend(); ++veh) {
393 v += (*veh)->getConservativeSpeed(earliestExitTime); // earliestExitTime is updated!
394 earliestExitTime += tauWithVehLength(tau, (*veh)->getVehicleType().getLengthWithGap(), (*veh)->getVehicleType().getCarFollowModel().getHeadwayTime());
395 }
396 }
397 if (count == 0) {
399 } else {
400 myMeanSpeed = v / (double) count;
401 }
402 }
403 return myMeanSpeed;
404}
405
406
407void
411
412void
414 for (const Queue& q : myQueues) {
415 for (const MEVehicle* const veh : q.getVehicles()) {
417 }
418 }
419}
420
421
424 Queue& q = myQueues[v->getQueIndex()];
425 // One could be tempted to do v->setSegment(next); here but position on lane will be invalid if next == 0
426 v->updateDetectors(leaveTime, true, reason);
428 myEdge.lock();
429 MEVehicle* nextLeader = q.remove(v);
430 myEdge.unlock();
431 return nextLeader;
432}
433
434
437 // since we do not know which queue will be used we give a conservative estimate
438 SUMOTime earliestLeave = earliestEntry;
439 SUMOTime latestEntry = -1;
440 for (const Queue& q : myQueues) {
441 earliestLeave = MAX2(earliestLeave, q.getBlockTime());
442 latestEntry = MAX2(latestEntry, q.getEntryBlockTime());
443 }
444 if (myEdge.getSpeedLimit() == 0) {
445 return MAX2(earliestEntry, latestEntry); // FIXME: This line is just an adhoc-fix to avoid division by zero (Leo)
446 } else {
447 return MAX3(earliestEntry, earliestLeave - TIME2STEPS(myLength / myEdge.getSpeedLimit()), latestEntry);
448 }
449}
450
451
452MSLink*
453MESegment::getLink(const MEVehicle* veh, bool penalty) const {
454 if (myJunctionControl || penalty) {
455 const MSEdge* const nextEdge = veh->succEdge(1);
456 if (nextEdge == nullptr || veh->getQueIndex() == PARKING_QUEUE) {
457 return nullptr;
458 }
459 // try to find any link leading to our next edge, start with the lane pointed to by the que index
460 const MSLane* const bestLane = myEdge.getLanes()[veh->getQueIndex()];
461 for (MSLink* const link : bestLane->getLinkCont()) {
462 if (&link->getLane()->getEdge() == nextEdge) {
463 return link;
464 }
465 }
466 // this is for the non-multique case, maybe we should use caching here !!!
467 for (const MSLane* const lane : myEdge.getLanes()) {
468 if (lane != bestLane) {
469 for (MSLink* const link : lane->getLinkCont()) {
470 if (&link->getLane()->getEdge() == nextEdge) {
471 return link;
472 }
473 }
474 }
475 }
476 }
477 return nullptr;
478}
479
480
481bool
482MESegment::isOpen(const MEVehicle* veh) const {
483#ifdef DEBUG_OPENED
484 if (DEBUG_COND || DEBUG_COND2(veh)) {
485 gDebugFlag1 = true;
486 std::cout << SIMTIME << " opened seg=" << getID() << " veh=" << Named::getIDSecure(veh)
487 << " tlsPenalty=" << myTLSPenalty;
488 const MSLink* link = getLink(veh);
489 if (link == 0) {
490 std::cout << " link=0";
491 } else {
492 std::cout << " prio=" << link->havePriority()
493 << " override=" << limitedControlOverride(link)
494 << " isOpen=" << link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
497 0, nullptr, false, veh)
498 << " et=" << veh->getEventTime()
499 << " v=" << veh->getSpeed()
500 << " vLeave=" << veh->estimateLeaveSpeed(link)
501 << " impatience=" << veh->getImpatience()
502 << " tWait=" << veh->getWaitingTime();
503 }
504 std::cout << "\n";
505 gDebugFlag1 = false;
506 }
507#endif
508 if (myTLSPenalty) {
509 // XXX should limited control take precedence over tls penalty?
510 return true;
511 }
512 const MSLink* link = getLink(veh);
513 return (link == nullptr
514 || link->havePriority()
516 || link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
519 0, nullptr, false, veh));
520}
521
522
523bool
525 assert(link != nullptr);
527 return false;
528 }
529 // if the target segment of this link is not saturated junction control is disabled
530 const MSEdge& targetEdge = link->getLane()->getEdge();
531 const MESegment* target = MSGlobals::gMesoNet->getSegmentForEdge(targetEdge);
532 return (target->getBruttoOccupancy() * 2 < target->myJamThreshold) && !targetEdge.isRoundabout();
533}
534
535
536void
537MESegment::send(MEVehicle* veh, MESegment* const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason) {
538 Queue& q = myQueues[veh->getQueIndex()];
539 assert(isInvalid(next) || time >= q.getBlockTime());
540 MSLink* const link = getLink(veh);
541 if (link != nullptr) {
542 link->removeApproaching(veh);
543 }
544 if (veh->isStopped()) {
545 veh->processStop();
546 }
547 MEVehicle* lc = removeCar(veh, time, reason); // new leaderCar
548 q.setBlockTime(time);
549 if (!isInvalid(next)) {
550 const bool nextFree = next->myQueues[nextQIdx].getOccupancy() <= next->myJamThreshold;
551 const SUMOTime tau = (q.getOccupancy() <= myJamThreshold
552 ? (nextFree ? myTau_ff : myTau_fj)
553 : (nextFree ? myTau_jf : getTauJJ((double)next->myQueues[nextQIdx].size(), next->myQueueCapacity, next->myJamThreshold)));
554 assert(tau >= 0);
556 if (myTLSPenalty) {
557 const MSLink* const tllink = getLink(veh, true);
558 if (tllink != nullptr && tllink->isTLSControlled()) {
559 assert(tllink->getGreenFraction() > 0);
560 myLastHeadway = (SUMOTime)((double)myLastHeadway / tllink->getGreenFraction());
561 }
562 }
564 }
565 if (lc != nullptr) {
568 }
569}
570
572MESegment::getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const {
573 // compute coefficients for the jam-jam headway function
574 // this function models the effect that "empty space" needs to move
575 // backwards through the downstream segment before the upstream segment may
576 // send annother vehicle.
577 // this allows jams to clear and move upstream.
578 // the headway function f(x) depends on the number of vehicles in the
579 // downstream segment x
580 // f is a linear function that passes through the following fixed points:
581 // f(n_jam_threshold) = tau_jf_withLength (for continuity)
582 // f(headwayCapacity) = myTau_jj * headwayCapacity
583
584 const SUMOTime tau_jf_withLength = tauWithVehLength(myTau_jf, DEFAULT_VEH_LENGTH_WITH_GAP, 1.);
585 // number of vehicles that fit into the NEXT queue (could be larger than expected with DEFAULT_VEH_LENGTH_WITH_GAP!)
586 const double headwayCapacity = MAX2(nextQueueSize, nextQueueCapacity / DEFAULT_VEH_LENGTH_WITH_GAP);
587 // number of vehicles above which the NEXT queue is jammed
588 const double n_jam_threshold = headwayCapacity * nextJamThreshold / nextQueueCapacity;
589
590 // slope a and axis offset b for the jam-jam headway function
591 // solving f(x) = a * x + b
592 const double a = (STEPS2TIME(myTau_jj) * headwayCapacity - STEPS2TIME(tau_jf_withLength)) / (headwayCapacity - n_jam_threshold);
593 const double b = headwayCapacity * (STEPS2TIME(myTau_jj) - a);
594
595 // it is only well defined for nextQueueSize >= n_jam_threshold (which may not be the case for longer vehicles), so we take the MAX
596 return TIME2STEPS(a * MAX2(nextQueueSize, n_jam_threshold) + b);
597}
598
599
600bool
604
605
606void
608 if (veh->getQueIndex() != PARKING_QUEUE) {
609 myQueues[veh->getQueIndex()].addReminders(veh);
610 }
611}
612
613
614void
615MESegment::receive(MEVehicle* veh, const int qIdx, SUMOTime time, const bool isDepart, const bool isTeleport, const bool newEdge) {
616 const double speed = isDepart ? -1 : MAX2(veh->getSpeed(), MESO_MIN_SPEED); // on the previous segment
617 veh->setSegment(this); // for arrival checking
618 veh->setLastEntryTime(time);
620 if (!isDepart && (
621 // arrival on entering a new edge
622 (newEdge && veh->moveRoutePointer())
623 // arrival on entering a new segment
624 || veh->hasArrived())) {
625 // route has ended
626 veh->setEventTime(time + TIME2STEPS(myLength / speed)); // for correct arrival speed
627 addReminders(veh);
629 veh->updateDetectors(time, true,
632 return;
633 }
634 assert(veh->getEdge() == &getEdge());
635 // route continues
636 Queue& q = myQueues[qIdx];
637 const double maxSpeedOnEdge = veh->getEdge()->getLanes()[qIdx]->getVehicleMaxSpeed(veh);
638 const double uspeed = MAX2(maxSpeedOnEdge, MESO_MIN_SPEED);
639 std::vector<MEVehicle*>& cars = q.getModifiableVehicles();
640 MEVehicle* newLeader = nullptr; // first vehicle in the current queue
641 const SUMOTime stopTime = veh->checkStop(time);
642 SUMOTime tleave = MAX2(stopTime + TIME2STEPS(myLength / uspeed) + getLinkPenalty(veh), q.getBlockTime());
643 if (veh->isStopped()) {
644 myEdge.addWaiting(veh);
645 }
646 if (veh->isParking()) {
647 // parking stops should take at least 1ms
648 veh->setEventTime(MAX2(stopTime, veh->getEventTime() + 1));
649 veh->setSegment(this, PARKING_QUEUE);
650 myEdge.getLanes()[0]->addParking(veh); // TODO for GUI only
651 } else {
652 myEdge.lock();
653 if (cars.empty()) {
654 cars.push_back(veh);
655 newLeader = veh;
656 } else {
657 SUMOTime leaderOut = cars[0]->getEventTime();
658 if (!isDepart && leaderOut > tleave && overtake()) {
659 if (cars.size() == 1) {
661 newLeader = veh;
662 }
663 cars.insert(cars.begin() + 1, veh);
664 } else {
665 tleave = MAX2(leaderOut + tauWithVehLength(myTau_ff, cars[0]->getVehicleType().getLengthWithGap(), cars[0]->getVehicleType().getCarFollowModel().getHeadwayTime()), tleave);
666 cars.insert(cars.begin(), veh);
667 }
668 }
669 myEdge.unlock();
671 if (!isDepart && !isTeleport) {
672 // departs and teleports could take place anywhere on the edge so they should not block regular flow
673 // the -1 facilitates interleaving of multiple streams
675 }
677 veh->setEventTime(tleave);
678 veh->setSegment(this, qIdx);
679 }
680 addReminders(veh);
681 if (isDepart) {
682 veh->onDepart();
684 } else if (newEdge) {
686 } else {
688 }
689 if (veh->isParking()) {
690 MSGlobals::gMesoNet->addLeaderCar(veh, nullptr);
691 } else {
692 if (newLeader != nullptr) {
693 MSGlobals::gMesoNet->addLeaderCar(newLeader, getLink(newLeader));
694 }
695 }
696}
697
698
699bool
701 for (const Queue& q : myQueues) {
702 if (q.size() > 0) {
703 for (MEVehicle* const veh : q.getVehicles()) {
704 if (filter->vehicleApplies(*veh)) {
707 return true;
708 }
709 }
710 }
711 }
712 return false;
713}
714
715
716void
717MESegment::setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector<MEVehicle*>& vehs) {
718 MEVehicle* v = vehs.back();
719 v->updateDetectors(currentTime, false);
720 SUMOTime newEvent = MAX2(newArrival(v, newSpeed, currentTime), blockTime);
721 if (v->getEventTime() != newEvent) {
723 v->setEventTime(newEvent);
725 }
726 for (std::vector<MEVehicle*>::const_reverse_iterator i = vehs.rbegin() + 1; i != vehs.rend(); ++i) {
727 (*i)->updateDetectors(currentTime, false);
728 newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff);
729 //newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff + (SUMOTime)((*(i - 1))->getVehicleType().getLength() / myTau_length));
730 (*i)->setEventTime(newEvent);
731 }
732}
733
734
736MESegment::newArrival(const MEVehicle* const v, double newSpeed, SUMOTime currentTime) {
737 // since speed is only an upper bound pos may be to optimistic
738 const double pos = MIN2(myLength, STEPS2TIME(currentTime - v->getLastEntryTime()) * v->getSpeed());
739 // traveltime may not be 0
740 double tt = (myLength - pos) / MAX2(newSpeed, MESO_MIN_SPEED);
741 return currentTime + MAX2(TIME2STEPS(tt), SUMOTime(1));
742}
743
744
745void
746MESegment::setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh, int qIdx) {
747 recomputeJamThreshold(jamThresh);
748 //myTau_length = MAX2(MESO_MIN_SPEED, newSpeed) * myEdge.getLanes().size() / TIME2STEPS(1);
749 int i = 0;
750 for (const Queue& q : myQueues) {
751 if (q.size() != 0) {
752 if (qIdx == -1 || qIdx == i) {
753 setSpeedForQueue(newSpeed, currentTime, q.getBlockTime(), q.getVehicles());
754 }
755 }
756 i++;
757 }
758}
759
760
763 SUMOTime result = SUMOTime_MAX;
764 for (const Queue& q : myQueues) {
765 if (q.size() != 0 && q.getVehicles().back()->getEventTime() < result) {
766 result = q.getVehicles().back()->getEventTime();
767 }
768 }
769 if (result < SUMOTime_MAX) {
770 return result;
771 }
772 return -1;
773}
774
775
776void
778 bool write = false;
779 for (const Queue& q : myQueues) {
780 if (q.getBlockTime() != -1 || !q.getVehicles().empty()) {
781 write = true;
782 break;
783 }
784 }
785 if (write) {
787 for (const Queue& q : myQueues) {
789 out.writeAttr(SUMO_ATTR_TIME, toString<SUMOTime>(q.getBlockTime()));
790 out.writeAttr(SUMO_ATTR_BLOCKTIME, toString<SUMOTime>(q.getEntryBlockTime()));
791 out.writeAttr(SUMO_ATTR_VALUE, q.getVehicles());
792 out.closeTag();
793 }
794 out.closeTag();
795 }
796}
797
798
799void
801 for (Queue& q : myQueues) {
802 q.getModifiableVehicles().clear();
803 }
804}
805
806void
807MESegment::loadState(const std::vector<SUMOVehicle*>& vehs, const SUMOTime blockTime, const SUMOTime entryBlockTime, const int queIdx) {
808 Queue& q = myQueues[queIdx];
809 for (SUMOVehicle* veh : vehs) {
810 MEVehicle* v = static_cast<MEVehicle*>(veh);
811 assert(v->getSegment() == this);
812 q.getModifiableVehicles().push_back(v);
815 addReminders(v);
816 }
817 if (q.size() != 0) {
818 // add the last vehicle of this queue
819 // !!! one question - what about the previously added vehicle? Is it stored twice?
820 MEVehicle* veh = q.getVehicles().back();
822 }
823 q.setBlockTime(blockTime);
824 q.setEntryBlockTime(entryBlockTime);
826}
827
828
829std::vector<const MEVehicle*>
831 std::vector<const MEVehicle*> result;
832 for (const Queue& q : myQueues) {
833 result.insert(result.end(), q.getVehicles().begin(), q.getVehicles().end());
834 }
835 return result;
836}
837
838
839bool
841 for (const Queue& q : myQueues) {
842 if (q.size() > 0 && q.getVehicles().back()->getWaitingTime() > 0) {
843 return true;
844 }
845 }
846 return false;
847}
848
849
850double
852 return 3600 * getCarNumber() * getMeanSpeed() / myLength;
853}
854
855
858 const MSLink* link = getLink(veh, myTLSPenalty || myCheckMinorPenalty);
859 if (link != nullptr) {
860 SUMOTime result = 0;
861 if (link->isTLSControlled() && myTLSPenalty) {
862 result += link->getMesoTLSPenalty();
863 }
864 // minor tls links may get an additional penalty
865 if (!link->havePriority() &&
866 // do not apply penalty on top of tLSPenalty
867 !myTLSPenalty &&
868 // do not apply penalty if limited control is active
870 result += myMinorPenalty;
871 }
872 return result;
873 } else {
874 return 0;
875 }
876}
877
878
879bool
881 for (const MSLane* lane : myEdge.getLanes()) {
882 for (const MSLink* link : lane->getLinkCont()) {
883 if (link->isTLSControlled() && StringUtils::toBool(link->getTLLogic()->getParameter(OVERRIDE_TLS_PENALTIES, "0"))) {
884 return true;
885 }
886 }
887 }
888 return false;
889}
890
891
892double
894 double result = 0;
895 for (const Queue& q : myQueues) {
896 // @note: only the leader currently accumulates waitingTime but this might change in the future
897 for (const MEVehicle* veh : q.getVehicles()) {
898 result += veh->getWaitingSeconds();
899 }
900 }
901 return result;
902}
903
904
905/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define MESO_MIN_SPEED
Definition MESegment.cpp:46
#define DEFAULT_VEH_LENGTH_WITH_GAP
Definition MESegment.cpp:44
#define DEBUG_COND2(obj)
Definition MESegment.cpp:53
#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:38
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
T MAX3(T a, T b, T c)
Definition StdDefs.h:96
static bool isEnteringRoundabout(const MSEdge &e)
whether the given edge is entering a roundabout
Definition MELoop.cpp: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:69
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:94
void addDetector(MSMoveReminder *data)
Definition MESegment.cpp:86
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.
SUMOTime checkStop(SUMOTime time)
Returns until when to stop at the current segment and sets the information that the stop has been rea...
void updateDetectors(SUMOTime currentTime, const bool isLeave, const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_JUNCTION)
Updates all vehicle detectors.
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:780
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition MSEdge.h:649
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:1164
const MSJunction * getToJunction() const
Definition MSEdge.h:418
static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored=0)
Definition MSEdge.cpp:316
bool isRoundabout() const
Definition MSEdge.h:721
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:434
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1457
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1356
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition MSEdge.h:777
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1264
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:326
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:384
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