Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MESegment.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18// A single mesoscopic segment (cell)
19/****************************************************************************/
20#include <config.h>
21
22#include <algorithm>
23#include <limits>
25#include <microsim/MSGlobals.h>
26#include <microsim/MSEdge.h>
27#include <microsim/MSJunction.h>
28#include <microsim/MSNet.h>
29#include <microsim/MSLane.h>
30#include <microsim/MSLink.h>
43#include "MEVehicle.h"
44#include "MELoop.h"
45#include "MESegment.h"
46
47#define DEFAULT_VEH_LENGTH_WITH_GAP (SUMOVTypeParameter::getDefault().length + SUMOVTypeParameter::getDefault().minGap)
48// avoid division by zero when driving very slowly
49#define MESO_MIN_SPEED (0.05)
50
51//#define DEBUG_OPENED
52//#define DEBUG_JAMTHRESHOLD
53//#define DEBUG_COND (getID() == "blocker")
54//#define DEBUG_COND (true)
55#define DEBUG_COND (myEdge.isSelected())
56#define DEBUG_COND2(obj) ((obj != 0 && (obj)->isSelected()))
57
58
59// ===========================================================================
60// static member definition
61// ===========================================================================
62MSEdge MESegment::myDummyParent("MESegmentDummyParent", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", "", -1, 0);
63MESegment MESegment::myVaporizationTarget("vaporizationTarget");
65const double MESegment::DO_NOT_PATCH_JAM_THRESHOLD(std::numeric_limits<double>::max());
66const std::string MESegment::OVERRIDE_TLS_PENALTIES("meso.tls.control");
67
68
69// ===========================================================================
70// MESegment::Queue method definitions
71// ===========================================================================
75 assert(std::find(myVehicles.begin(), myVehicles.end(), v) != myVehicles.end());
76 if (v == myVehicles.back()) {
77 myVehicles.pop_back();
78 if (myVehicles.empty()) {
79 myOccupancy = 0.;
80 } else {
81 return myVehicles.back();
82 }
83 } else {
84 myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), v));
85 }
86 return nullptr;
87}
88
89void
91 myDetectorData.push_back(data);
92 for (MEVehicle* const v : myVehicles) {
93 v->addReminder(data);
94 }
95}
96
97void
99 for (MSMoveReminder* rem : myDetectorData) {
100 veh->addReminder(rem);
101 }
102}
103
104// ===========================================================================
105// MESegment method definitions
106// ===========================================================================
107MESegment::MESegment(const std::string& id,
108 const MSEdge& parent, MESegment* next,
109 const double length, const double speed,
110 const int idx,
111 const bool multiQueue,
112 const MesoEdgeType& edgeType):
113 Named(id), myEdge(parent), myNextSegment(next),
114 myLength(length), myIndex(idx),
115 myTau_length((double)TIME2STEPS(1) / MAX2(MESO_MIN_SPEED, speed)),
116 myNumVehicles(0),
118 myMeanSpeed(speed),
120
121 const std::vector<MSLane*>& lanes = parent.getLanes();
122 int usableLanes = 0;
123 SVCPermissions maxAllow = 0;
124 SVCPermissions minAllow = SVCAll;
125 for (MSLane* const l : lanes) {
126 const SVCPermissions allow = MSEdge::getMesoPermissions(l->getPermissions());
127 if (multiQueue) {
128 myQueues.push_back(Queue(allow));
129 }
130 if (allow != 0) {
131 usableLanes++;
132 maxAllow |= allow;
133 minAllow &= allow;
134 }
135 }
136 if (usableLanes == 0) {
137 // cars won't drive here. Give sensible tau values capacity for the ignored classes
138 usableLanes = 1;
139 }
140 if (multiQueue) {
141 // vehicles choose their queue by their next edge on the last segment and on all segments ending within the lookahead distance
142 const double distToEnd = parent.getLength() - (idx + 1) * length;
143 if (next == nullptr || distToEnd < edgeType.lookahead) {
144 SearchedMap searched;
145 for (const MSEdge* const edge : parent.getSuccessors()) {
146 if (edge->isTazConnector()) {
147 continue;
148 }
149 const std::vector<MSLane*>* const allowed = parent.allowedLanes(*edge);
150 assert(allowed != nullptr);
151 assert(allowed->size() > 0);
152 for (MSLane* const l : *allowed) {
153 std::vector<MSLane*>::const_iterator it = std::find(lanes.begin(), lanes.end(), l);
154 myFollowerMap[edge] |= (1 << distance(lanes.begin(), it));
155 }
156 if (edgeType.lookahead > 0) {
157 // follow the lanes of this edge into later edges whose turns are within the lookahead distance
158 std::vector<int> reach(lanes.size(), 0);
159 for (int i = 0; i < (int)lanes.size(); i++) {
160 for (const MSLink* const link : lanes[i]->getLinkCont()) {
161 if (&link->getLane()->getEdge() == edge) {
162 reach[i] |= 1 << link->getLane()->getIndex();
163 }
164 }
165 }
166 addDownstreamFollowers(*edge, reach, 0., edgeType.lookahead - MAX2(0., distToEnd), 1, searched);
167 }
168 }
169 }
170 myQueueCapacity = length;
171 } else {
172 myQueues.push_back(Queue(parent.getPermissions()));
173 maxAllow &= ~minAllow;
174 if ((maxAllow & ~myMultiModalWarnings) != 0) {
175 WRITE_WARNINGF("Mismodelled capacity on edge '%'. Not all lanes are usable by vClass '%'. Use option --meso-lane-queue or add unused class to option --meso-ignore-lanes-by-vclass.",
177 myMultiModalWarnings |= maxAllow;
178 }
179 }
180
181 initSegment(edgeType, parent, length * usableLanes);
182}
183
184void
185MESegment::addDownstreamFollowers(const MSEdge& edge, const std::vector<int>& reach, const double dist, const double lookahead, const int depth, SearchedMap& searched) {
186 if (dist + edge.getLength() >= lookahead) {
187 return;
188 }
189 // a search with the same reach that started no further away and at least as deep has added everything this one would
190 std::vector<std::pair<double, int> >& previous = searched[std::make_pair(&edge, reach)];
191 for (const std::pair<double, int>& p : previous) {
192 if (p.first <= dist && p.second >= depth) {
193 return;
194 }
195 }
196 previous.push_back(std::make_pair(dist, depth));
197 const std::vector<MSLane*>& lanes = edge.getLanes();
198 int usable = 0;
199 for (int i = 0; i < (int)reach.size(); i++) {
200 if (reach[i] != 0) {
201 usable |= 1 << i;
202 }
203 }
204 for (const MSEdge* const succ : edge.getSuccessors()) {
205 if (succ->isTazConnector()) {
206 continue;
207 }
208 // the queues of this segment from which succ can be reached without changing lanes
209 int queues = 0;
210 std::vector<int> succReach(reach.size(), 0);
211 for (int i = 0; i < (int)reach.size(); i++) {
212 for (int j = 0; j < (int)lanes.size(); j++) {
213 if ((reach[i] & (1 << j)) != 0) {
214 for (const MSLink* const link : lanes[j]->getLinkCont()) {
215 if (&link->getLane()->getEdge() == succ) {
216 queues |= 1 << i;
217 succReach[i] |= 1 << link->getLane()->getIndex();
218 }
219 }
220 }
221 }
222 }
223 if (queues != 0) {
224 if (queues != usable) {
225 myFollowerMap[succ] |= queues;
226 myLookahead = MAX2(myLookahead, depth + 1);
227 }
228 addDownstreamFollowers(*succ, succReach, dist + edge.getLength(), lookahead, depth + 1, searched);
229 }
230 }
231}
232
233
234void
235MESegment::initSegment(const MesoEdgeType& edgeType, const MSEdge& parent, const double capacity) {
236
237 myCapacity = capacity;
238 if (myQueues.size() == 1) {
239 const double laneScale = capacity / myLength;
240 myQueueCapacity = capacity;
241 myTau_length = (double)TIME2STEPS(1) / MAX2(MESO_MIN_SPEED, myMeanSpeed) / laneScale;
242 // Eissfeldt p. 90 and 151 ff.
243 myTau_ff = (SUMOTime)((double)edgeType.tauff / laneScale);
244 myTau_fj = (SUMOTime)((double)edgeType.taufj / laneScale);
245 myTau_jf = (SUMOTime)((double)edgeType.taujf / laneScale);
246 myTau_jj = (SUMOTime)((double)edgeType.taujj / laneScale);
247 } else {
248 myTau_ff = edgeType.tauff;
249 myTau_fj = edgeType.taufj;
250 myTau_jf = edgeType.taujf;
251 myTau_jj = edgeType.taujj;
252 }
253
255 myTLSPenalty = ((edgeType.tlsPenalty > 0 || edgeType.tlsFlowPenalty > 0) &&
256 // only apply to the last segment of a tls-controlled edge
257 myNextSegment == nullptr && (
261
262 // only apply to the last segment of an uncontrolled edge that has at least 1 minor link
263 myCheckMinorPenalty = (edgeType.minorPenalty > 0 &&
264 myNextSegment == nullptr &&
268 parent.hasMinorLink());
269 myMinorPenalty = edgeType.minorPenalty;
271
272 //std::cout << getID() << " myMinorPenalty=" << myMinorPenalty << " myTLSPenalty=" << myTLSPenalty << " myJunctionControl=" << myJunctionControl << " myOvertaking=" << myOvertaking << "\n";
273
275}
276
277MESegment::MESegment(const std::string& id):
278 Named(id),
279 myEdge(myDummyParent), // arbitrary edge needed to supply the needed reference
280 myNextSegment(nullptr), myLength(0), myIndex(0),
281 myTau_ff(0), myTau_fj(0), myTau_jf(0), myTau_jj(0),
282 myTLSPenalty(false),
283 myCheckMinorPenalty(false),
284 myMinorPenalty(0),
285 myJunctionControl(false),
286 myOvertaking(false),
287 myTau_length(1) {
288}
289
290
291void
293 if (myQueues.size() > 1) {
294 for (MSLane* lane : myEdge.getLanes()) {
295 myQueues[lane->getIndex()].setPermissions(lane->getPermissions());
296 }
297 } else {
298 myQueues.back().setPermissions(myEdge.getPermissions());
299 }
300}
301
302
303void
305 if (jamThresh == DO_NOT_PATCH_JAM_THRESHOLD) {
306 return;
307 }
308 if (jamThresh < 0) {
309 // compute based on speed
311 } else {
312 // compute based on specified percentage
313 myJamThreshold = jamThresh * myCapacity;
314 }
315}
316
317
318double
319MESegment::jamThresholdForSpeed(double speed, double jamThresh) const {
320 // vehicles driving freely at maximum speed should not jam
321 // we compute how many vehicles could possible enter the segment until the first vehicle leaves
322 // and multiply by the space these vehicles would occupy
323 // the jamThresh parameter is scale the resulting value
324 if (speed == 0) {
325 return std::numeric_limits<double>::max(); // never jam. Irrelevant at speed 0 anyway
326 }
327#ifdef DEBUG_JAMTHRESHOLD
328 if (true || DEBUG_COND) {
329 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
330 << "\n";
331 }
332#endif
334}
335
336
337void
339 if (queueIndex == -1) {
340 for (Queue& q : myQueues) {
341 q.addDetector(data);
342 }
343 } else {
344 assert(queueIndex < (int)myQueues.size());
345 myQueues[queueIndex].addDetector(data);
346 }
347}
348
349
350/*
351void
352MESegment::removeDetector(MSMoveReminder* data) {
353 std::vector<MSMoveReminder*>::iterator it = std::find(myDetectorData.begin(), myDetectorData.end(), data);
354 if (it != myDetectorData.end()) {
355 myDetectorData.erase(it);
356 }
357 for (const Queue& q : myQueues) {
358 for (MEVehicle* const v : q.getVehicles()) {
359 v->removeReminder(data);
360 }
361 }
362}
363*/
364
365
366void
368 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
369 if (queueIndex == -1) {
370 for (const Queue& q : myQueues) {
371 SUMOTime earliestExitTime = currentTime;
372 for (std::vector<MEVehicle*>::const_reverse_iterator i = q.getVehicles().rbegin(); i != q.getVehicles().rend(); ++i) {
373 const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
374 (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
375 earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
376 }
377 }
378 } else {
379 SUMOTime earliestExitTime = currentTime;
380 for (std::vector<MEVehicle*>::const_reverse_iterator i = myQueues[queueIndex].getVehicles().rbegin(); i != myQueues[queueIndex].getVehicles().rend(); ++i) {
381 const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
382 (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
383 earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
384 }
385 }
386}
387
388
390MESegment::hasSpaceFor(const MEVehicle* const veh, const SUMOTime entryTime, int& qIdx, const bool init) const {
391 SUMOTime earliestEntry = SUMOTime_MAX;
392 qIdx = 0;
393 if (myNumVehicles == 0 && myQueues.size() == 1) {
394 // we have always space for at least one vehicle
395 if (myQueues.front().allows(veh->getVClass())) {
396 return entryTime;
397 } else {
398 return earliestEntry;
399 }
400 }
401 const SUMOVehicleClass svc = veh->getVClass();
402 int minSize = std::numeric_limits<int>::max();
403 // the queues leading to the next edges of the vehicle's route
404 int usable = -1;
405 if (!myFollowerMap.empty()) {
406 // the lane chain to a later route edge may run through lanes the vehicle may not use
407 int permitted = -1;
408 if (myLookahead > 1) {
409 permitted = 0;
410 for (int i = 0; i < (int)myQueues.size(); i++) {
411 if (myQueues[i].allows(svc)) {
412 permitted |= 1 << i;
413 }
414 }
415 }
416 const int offset = veh->getEdge() == &myEdge ? 1 : 2;
417 for (int k = 0; k < myLookahead; k++) {
418 const MSEdge* const succ = veh->succEdge(offset + k);
419 if (succ == nullptr) {
420 break;
421 }
422 const auto it = myFollowerMap.find(succ);
423 if (it != myFollowerMap.end() && (k == 0 || (usable & it->second & permitted) != 0)) {
424 usable &= it->second;
425 }
426 }
427 }
428 for (int i = 0; i < (int)myQueues.size(); i++) {
429 const Queue& q = myQueues[i];
430 const double newOccupancy = q.size() == 0 ? 0. : q.getOccupancy() + veh->getVehicleType().getLengthWithGap();
431 if (newOccupancy <= myQueueCapacity) { // we must ensure that occupancy remains below capacity
432 if ((usable & (1 << i)) != 0) {
433 if (q.allows(svc) && q.size() < minSize) {
434 if (init) {
435 // regular insertions and initial insertions must respect different constraints:
436 if (veh->getInsertionChecks() == (int)InsertionCheck::NONE || hasSpaceForInsertion(q, i, newOccupancy, entryTime)) {
437 qIdx = i;
438 minSize = q.size();
439 }
440 } else if (entryTime >= q.getEntryBlockTime()) {
441 qIdx = i;
442 minSize = q.size();
443 } else {
444 earliestEntry = MIN2(earliestEntry, q.getEntryBlockTime());
445 }
446 }
447 }
448 }
449 }
450 if (minSize == std::numeric_limits<int>::max()) {
451 return earliestEntry;
452 }
453 return entryTime;
454}
455
456
457bool
458MESegment::hasSpaceForInsertion(const Queue& q, int /*qIdx*/, double newOccupancy, SUMOTime /*entryTime*/) const {
459 // - regular insertions must respect entryBlockTime
460 // - initial insertions should not cause additional jamming
461 // - inserted vehicle should be able to continue at the current speed
463 return newOccupancy <= myJamThreshold;
464 } else {
465 return newOccupancy <= jamThresholdForSpeed(getMeanSpeed(false), -1);
466 }
467}
468
469
470bool
472 int qIdx = 0;
473 if (hasSpaceFor(veh, time, qIdx, true) == time) {
474 const bool isRail = veh->isRail();
475 // see MSLane::isInsertionSuccess
476 if (isRail && veh->getInsertionChecks() != (int)InsertionCheck::NONE
481 MSEdgeVector occupied;
482 if (dw->foeDriveWayOccupied(false, veh, occupied) || dw->sidingDeadlock(veh)) {
483 myEdge.getLanes()[0]->setParameter("insertionBlocked:" + veh->getID(), dw->getID());
484 return false;
485 }
486 }
487 receive(veh, qIdx, time, true);
488 if (isRail) {
489 myEdge.getLanes()[0]->unsetParameter("insertionConstraint:" + veh->getID());
490 //unsetParameter("insertionOrder:" + veh->getID());
491 //unsetParameter("insertionBlocked:" + veh->getID());
494 //if (firstRailSignal != nullptr && firstRailSignal->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
495 // veh->registerInsertionApproach(firstRailSignal, firstRailSignalDist);
496 //}
497 }
498 return true;
499 }
500 return false;
501}
502
503
504double
505MESegment::getMeanSpeed(bool useCached) const {
506 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
507 if (currentTime != myLastMeanSpeedUpdate || !useCached) {
508 myLastMeanSpeedUpdate = currentTime;
509 double v = 0;
510 int count = 0;
511 for (const Queue& q : myQueues) {
512 const SUMOTime tau = q.getOccupancy() < myJamThreshold ? myTau_ff : myTau_jf;
513 SUMOTime earliestExitTime = currentTime;
514 count += q.size();
515 for (std::vector<MEVehicle*>::const_reverse_iterator veh = q.getVehicles().rbegin(); veh != q.getVehicles().rend(); ++veh) {
516 v += (*veh)->getConservativeSpeed(earliestExitTime); // earliestExitTime is updated!
517 earliestExitTime += tauWithVehLength(tau, (*veh)->getVehicleType().getLengthWithGap(), (*veh)->getVehicleType().getCarFollowModel().getHeadwayTime());
518 }
519 }
520 if (count == 0) {
522 } else {
523 myMeanSpeed = v / (double) count;
524 }
525 }
526 return myMeanSpeed;
527}
528
529
530void
534
535void
537 for (const Queue& q : myQueues) {
538 for (const MEVehicle* const veh : q.getVehicles()) {
540 }
541 }
542}
543
544
547 Queue& q = myQueues[v->getQueIndex()];
548 // One could be tempted to do v->setSegment(next); here but position on lane will be invalid if next == 0
549 v->updateDetectors(leaveTime, v->getEventTime(), true, reason);
551 myEdge.lock();
552 MEVehicle* nextLeader = q.remove(v);
554 myEdge.unlock();
555 return nextLeader;
556}
557
558
561 // since we do not know which queue will be used we give a conservative estimate
562 SUMOTime earliestLeave = earliestEntry;
563 SUMOTime latestEntry = -1;
564 for (const Queue& q : myQueues) {
565 earliestLeave = MAX2(earliestLeave, q.getBlockTime());
566 latestEntry = MAX2(latestEntry, q.getEntryBlockTime());
567 }
568 if (myEdge.getSpeedLimit() == 0) {
569 return MAX2(earliestEntry, latestEntry); // FIXME: This line is just an adhoc-fix to avoid division by zero (Leo)
570 } else {
571 return MAX3(earliestEntry, earliestLeave - TIME2STEPS(myLength / myEdge.getSpeedLimit()), latestEntry);
572 }
573}
574
575
576MSLink*
577MESegment::getLink(const MEVehicle* veh, bool penalty) const {
578 if (myJunctionControl || penalty) {
579 const MSEdge* const nextEdge = veh->succEdge(1);
580 if (nextEdge == nullptr || veh->getQueIndex() == PARKING_QUEUE) {
581 return nullptr;
582 }
583 // try to find any link leading to our next edge, start with the lane pointed to by the que index
584 const MSLane* const bestLane = myEdge.getLanes()[veh->getQueIndex()];
585 for (MSLink* const link : bestLane->getLinkCont()) {
586 if (&link->getLane()->getEdge() == nextEdge) {
587 return link;
588 }
589 }
590 // this is for the non-multique case, maybe we should use caching here !!!
591 for (const MSLane* const lane : myEdge.getLanes()) {
592 if (lane != bestLane) {
593 for (MSLink* const link : lane->getLinkCont()) {
594 if (&link->getLane()->getEdge() == nextEdge) {
595 return link;
596 }
597 }
598 }
599 }
600 }
601 return nullptr;
602}
603
604
605bool
606MESegment::isOpen(const MEVehicle* veh) const {
607#ifdef DEBUG_OPENED
608 if (DEBUG_COND || DEBUG_COND2(veh)) {
609 gDebugFlag1 = true;
610 std::cout << SIMTIME << " opened seg=" << getID() << " veh=" << Named::getIDSecure(veh)
611 << " tlsPenalty=" << myTLSPenalty;
612 const MSLink* link = getLink(veh);
613 if (link == 0) {
614 std::cout << " link=0";
615 } else {
616 std::cout << " prio=" << link->havePriority()
617 << " override=" << limitedControlOverride(link)
618 << " isOpen=" << link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
621 0, nullptr, false, veh)
622 << " et=" << veh->getEventTime()
623 << " v=" << veh->getSpeed()
624 << " vLeave=" << veh->estimateLeaveSpeed(link)
625 << " impatience=" << veh->getImpatience()
626 << " tWait=" << veh->getWaitingTime();
627 }
628 std::cout << "\n";
629 gDebugFlag1 = false;
630 }
631#endif
632 if (myTLSPenalty) {
633 // XXX should limited control take precedence over tls penalty?
634 return true;
635 }
636 const MSLink* link = getLink(veh);
637 return (link == nullptr
638 || link->havePriority()
640 || link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
643 0, nullptr, false, veh));
644}
645
646
647bool
649 assert(link != nullptr);
651 return false;
652 }
653 // if the target segment of this link is not saturated junction control is disabled
654 const MSEdge& targetEdge = link->getLane()->getEdge();
655 const MESegment* target = MSGlobals::gMesoNet->getSegmentForEdge(targetEdge);
656 return (target->getBruttoOccupancy() * 2 < target->myJamThreshold) && !targetEdge.isRoundabout();
657}
658
659
661MESegment::computeHeadway(Queue& /*q*/, const Queue& qNext, const MESegment* const next, const MEVehicle* veh) const {
662 const bool nextFree = qNext.getOccupancy() <= next->myJamThreshold;
663 const SUMOTime tau = (!veh->wasJammed()
664 ? (nextFree ? myTau_ff : myTau_fj)
665 : (nextFree ? myTau_jf : getTauJJ((double)qNext.size(), next->myQueueCapacity, next->myJamThreshold)));
666 assert(tau >= 0);
668 if (myTLSPenalty) {
669 const MSLink* const tllink = getLink(veh, true);
670 if (tllink != nullptr && tllink->isTLSControlled()) {
671 assert(tllink->getGreenFraction() > 0);
672 headway = (SUMOTime)((double)headway / tllink->getGreenFraction());
673 }
674 }
675 return headway;
676}
677
678
679void
680MESegment::send(MEVehicle* veh, MESegment* const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason) {
681 Queue& q = myQueues[veh->getQueIndex()];
682 assert(isInvalid(next) || time >= q.getBlockTime());
683 MSLink* const link = getLink(veh);
684 if (link != nullptr) {
685 link->removeApproaching(veh);
686 }
687 if (veh->isStopped()) {
688 veh->processStop();
689 }
690 MEVehicle* lc = removeCar(veh, time, reason); // new leaderCar
691 q.setBlockTime(time);
692 if (myEdge.isNormal() && myCapacity >= 22.5) {
694 }
695 if (!isInvalid(next)) {
696 myLastHeadway = computeHeadway(q, next->myQueues[nextQIdx], next, veh);
697 q.setBlockTime(time + myLastHeadway);
698 }
699 if (lc != nullptr) {
702 }
703}
704
705
707MESegment::getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const {
708 // compute coefficients for the jam-jam headway function
709 // this function models the effect that "empty space" needs to move
710 // backwards through the downstream segment before the upstream segment may
711 // send annother vehicle.
712 // this allows jams to clear and move upstream.
713 // the headway function f(x) depends on the number of vehicles in the
714 // downstream segment x
715 // f is a linear function that passes through the following fixed points:
716 // f(n_jam_threshold) = tau_jf_withLength (for continuity)
717 // f(headwayCapacity) = myTau_jj * headwayCapacity
718
719 const SUMOTime tau_jf_withLength = tauWithVehLength(myTau_jf, DEFAULT_VEH_LENGTH_WITH_GAP, 1.);
720 // number of vehicles that fit into the NEXT queue (could be larger than expected with DEFAULT_VEH_LENGTH_WITH_GAP!)
721 const double headwayCapacity = MAX2(nextQueueSize, nextQueueCapacity / DEFAULT_VEH_LENGTH_WITH_GAP);
722 // number of vehicles above which the NEXT queue is jammed
723 const double n_jam_threshold = headwayCapacity * nextJamThreshold / nextQueueCapacity;
724
725 // slope a and axis offset b for the jam-jam headway function
726 // solving f(x) = a * x + b
727 const double a = (STEPS2TIME(myTau_jj) * headwayCapacity - STEPS2TIME(tau_jf_withLength)) / (headwayCapacity - n_jam_threshold);
728 const double b = headwayCapacity * (STEPS2TIME(myTau_jj) - a);
729
730 // it is only well defined for nextQueueSize >= n_jam_threshold (which may not be the case for longer vehicles), so we take the MAX
731 return TIME2STEPS(a * MAX2(nextQueueSize, n_jam_threshold) + b);
732}
733
734
735bool
739
740
741void
743 if (veh->getQueIndex() != PARKING_QUEUE) {
744 myQueues[veh->getQueIndex()].addReminders(veh);
745 }
746}
747
748
749void
750MESegment::receive(MEVehicle* veh, const int qIdx, SUMOTime time, const bool isDepart, const bool isTeleport, const bool newEdge) {
751 const double speed = isDepart ? -1 : MAX2(veh->getSpeed(), MESO_MIN_SPEED); // on the previous segment
752 veh->setSegment(this); // for arrival checking
753 veh->setLastEntryTime(time);
755 if (!isDepart && (
756 // arrival on entering a new edge
757 (newEdge && myEdge.isNormal() && veh->moveRoutePointer())
758 // arrival on entering a new segment
759 || veh->hasArrived())) {
760 // route has ended
761 veh->setEventTime(time + TIME2STEPS(myLength / speed)); // for correct arrival speed
762 addReminders(veh);
764 veh->updateDetectors(time, veh->getEventTime(), true,
767 return;
768 }
769 assert(veh->getEdge() == &getEdge() || getEdge().isInternal());
770 // route continues
771 Queue& q = myQueues[qIdx];
772 const double maxSpeedOnEdge = veh->getEdge()->getLanes()[qIdx]->getVehicleMaxSpeed(veh);
773 const double uspeed = MAX2(maxSpeedOnEdge, MESO_MIN_SPEED);
774 std::vector<MEVehicle*>& cars = q.getModifiableVehicles();
775 MEVehicle* newLeader = nullptr; // first vehicle in the current queue
776 const SUMOTime stopTime = veh->checkStop(time);
777 SUMOTime tleave = MAX2(stopTime + TIME2STEPS(myLength / uspeed) + getLinkPenalty(veh), q.getBlockTime());
778 if (veh->isStopped()) {
779 myEdge.addWaiting(veh);
780 }
781 if (veh->isParking()) {
782 // parking stops should take at least 1ms
783 veh->setEventTime(MAX2(stopTime, veh->getEventTime() + 1));
784 veh->setSegment(this, PARKING_QUEUE);
785 myEdge.getLanes()[0]->addParking(veh); // TODO for GUI only
786 } else {
787 myEdge.lock();
788 if (cars.empty()) {
789 cars.push_back(veh);
790 newLeader = veh;
791 } else {
792 SUMOTime leaderOut = cars[0]->getEventTime();
793 if (!isDepart && leaderOut > tleave && overtake()) {
794 if (cars.size() == 1) {
795 // the overtaken car is no longer the leader and must not block foes
796 MSLink* const link = getLink(cars[0]);
797 if (link != nullptr) {
798 link->removeApproaching(cars[0]);
799 }
801 newLeader = veh;
802 }
803 cars.insert(cars.begin() + 1, veh);
804 } else {
805 tleave = MAX2(leaderOut + tauWithVehLength(myTau_ff, cars[0]->getVehicleType().getLengthWithGap(), cars[0]->getVehicleType().getCarFollowModel().getHeadwayTime()), tleave);
806 cars.insert(cars.begin(), veh);
807 }
808 }
810 myEdge.unlock();
812 if (!isDepart && !isTeleport) {
813 // departs and teleports could take place anywhere on the edge so they should not block regular flow
814 // the -1 facilitates interleaving of multiple streams
816 }
818 veh->setEventTime(tleave);
819 veh->setUnqueuedEventTime(tleave);
820 veh->setSegment(this, qIdx);
821 }
822 addReminders(veh);
823 if (isDepart) {
824 veh->onDepart();
826 } else if (newEdge) {
828 } else {
830 }
831 if (veh->isParking()) {
832 MSGlobals::gMesoNet->addLeaderCar(veh, nullptr);
833 } else {
834 if (newLeader != nullptr) {
835 MSGlobals::gMesoNet->addLeaderCar(newLeader, getLink(newLeader));
836 }
837 }
838}
839
840
841bool
843 for (const Queue& q : myQueues) {
844 if (q.size() > 0) {
845 for (MEVehicle* const veh : q.getVehicles()) {
846 if (filter->vehicleApplies(*veh)) {
849 return true;
850 }
851 }
852 }
853 }
854 return false;
855}
856
857
858void
859MESegment::setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector<MEVehicle*>& vehs) {
860 MEVehicle* v = vehs.back();
861 SUMOTime oldEarliestExitTime = currentTime;
862 const SUMOTime oldExit = MAX2(oldEarliestExitTime, v->getEventTime());
863 v->updateDetectors(currentTime, oldExit, false);
865 SUMOTime newEvent = MAX2(newArrival(v, newSpeed, currentTime), blockTime);
866 if (v->getEventTime() != newEvent) {
868 v->setEventTime(newEvent);
870 }
871 for (std::vector<MEVehicle*>::const_reverse_iterator i = vehs.rbegin() + 1; i != vehs.rend(); ++i) {
872 const SUMOTime oldExitTime = MAX2(oldEarliestExitTime, (*i)->getEventTime());
873 (*i)->updateDetectors(currentTime, oldExitTime, false);
874 const SUMOTime minTau = tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap(), (*i)->getVehicleType().getCarFollowModel().getHeadwayTime());
875 oldEarliestExitTime = oldExitTime + minTau;
876 newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + minTau);
877 (*i)->setEventTime(newEvent);
878 }
879}
880
881
883MESegment::newArrival(const MEVehicle* const v, double newSpeed, SUMOTime currentTime) {
884 // since speed is only an upper bound, pos may be too optimistic
885 const double pos = MIN2(myLength, STEPS2TIME(currentTime - v->getLastEntryTime()) * v->getSpeed());
886 // traveltime may not be 0
887 double tt = (myLength - pos) / MAX2(newSpeed, MESO_MIN_SPEED);
888 return currentTime + MAX2(TIME2STEPS(tt), SUMOTime(1));
889}
890
891
892void
893MESegment::setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh, int qIdx) {
894 recomputeJamThreshold(jamThresh);
895 //myTau_length = MAX2(MESO_MIN_SPEED, newSpeed) * myEdge.getLanes().size() / TIME2STEPS(1);
896 int i = 0;
897 for (const Queue& q : myQueues) {
898 if (q.size() != 0) {
899 if (qIdx == -1 || qIdx == i) {
900 setSpeedForQueue(newSpeed, currentTime, q.getBlockTime(), q.getVehicles());
901 }
902 }
903 i++;
904 }
905}
906
907
910 SUMOTime result = SUMOTime_MAX;
911 for (const Queue& q : myQueues) {
912 if (q.size() != 0 && q.getVehicles().back()->getEventTime() < result) {
913 result = q.getVehicles().back()->getEventTime();
914 }
915 }
916 if (result < SUMOTime_MAX) {
917 return result;
918 }
919 return -1;
920}
921
922
923void
925 bool write = false;
926 for (int i = 0; i < (int)myQueues.size(); i++) {
927 if (myQueues[i].getBlockTime() != -1 || !myQueues[i].getVehicles().empty() || getQueueExtraState(i) != "") {
928 write = true;
929 break;
930 }
931 }
932 if (write) {
934 for (int i = 0; i < (int)myQueues.size(); i++) {
935 const Queue& q = myQueues[i];
937 out.writeAttr(SUMO_ATTR_TIME, toString<SUMOTime>(q.getBlockTime()));
938 out.writeAttr(SUMO_ATTR_BLOCKTIME, toString<SUMOTime>(q.getEntryBlockTime()));
940 const std::string extra = getQueueExtraState(i);
941 if (extra != "") {
942 out.writeAttr(SUMO_ATTR_STATE, extra);
943 }
944 out.closeTag();
945 }
946 out.closeTag();
947 }
948}
949
950
951void
953 for (Queue& q : myQueues) {
954 q.getModifiableVehicles().clear();
955 }
956}
957
958void
959MESegment::loadState(const std::vector<SUMOVehicle*>& vehs, const SUMOTime blockTime, const SUMOTime entryBlockTime, const int queIdx) {
960 Queue& q = myQueues[queIdx];
961 for (SUMOVehicle* veh : vehs) {
962 MEVehicle* v = static_cast<MEVehicle*>(veh);
963 assert(v->getSegment() == this || myEdge.isInternal());
964 if (myEdge.isInternal()) {
965 v->setSegment(this, v->getQueIndex());
966 }
967 q.getModifiableVehicles().push_back(v);
970 addReminders(v);
971 }
972 if (q.size() != 0) {
973 // add the last vehicle of this queue
974 // !!! one question - what about the previously added vehicle? Is it stored twice?
975 MEVehicle* veh = q.getVehicles().back();
976 MSGlobals::gMesoNet->addLeaderCar(veh, getLink(veh), true);
977 }
978 q.setBlockTime(blockTime);
979 q.setEntryBlockTime(entryBlockTime);
981}
982
983
984std::vector<const MEVehicle*>
986 std::vector<const MEVehicle*> result;
987 for (const Queue& q : myQueues) {
988 result.insert(result.end(), q.getVehicles().begin(), q.getVehicles().end());
989 }
990 return result;
991}
992
993
994bool
996 for (const Queue& q : myQueues) {
997 if (q.size() > 0 && q.getVehicles().back()->getWaitingTime() > 0) {
998 return true;
999 }
1000 }
1001 return false;
1002}
1003
1004
1005double
1007 return 3600 * getCarNumber() * getMeanSpeed() / myLength;
1008}
1009
1010
1013 const MSLink* link = getLink(veh, myTLSPenalty || myCheckMinorPenalty);
1014 if (link != nullptr) {
1015 SUMOTime result = 0;
1016 if (link->isTLSControlled() && myTLSPenalty) {
1017 result += link->getMesoTLSPenalty();
1018 }
1019 // minor tls links may get an additional penalty
1020 if (!link->havePriority() &&
1021 // do not apply penalty on top of tLSPenalty
1022 !myTLSPenalty &&
1023 // do not apply penalty if limited control is active
1025 result += myMinorPenalty;
1026 }
1027 return result;
1028 } else {
1029 return 0;
1030 }
1031}
1032
1033
1034double
1036 double result = 0;
1037 for (const Queue& q : myQueues) {
1038 // @note: only the leader currently accumulates waitingTime but this might change in the future
1039 for (const MEVehicle* veh : q.getVehicles()) {
1040 result += veh->getWaitingSeconds();
1041 }
1042 }
1043 return result;
1044}
1045
1046
1047/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define DEFAULT_VEH_LENGTH_WITH_GAP
#define DEBUG_COND2(obj)
#define MESO_MIN_SPEED
Definition MESegment.cpp:49
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define STEPS2TIME(x)
Definition SUMOTime.h:58
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SUMOTime_MIN
Definition SUMOTime.h:35
#define SIMTIME
Definition SUMOTime.h:70
const SVCPermissions SVCAll
all VClasses are allowed
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
bool isRailwayOrShared(SVCPermissions permissions)
Returns whether an edge with the given permissions is a railway edge or a shared road/rail edge.
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.
@ SPLIT
The departure is triggered by a train split.
@ SUMO_TAG_VIEWSETTINGS_VEHICLES
@ SUMO_TAG_SEGMENT
segment of a lane
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_BLOCKTIME
@ SUMO_ATTR_ID
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_TIME
trigger: the time of the step
bool gDebugFlag1
global utility flags for debugging
Definition StdDefs.cpp:44
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:414
void addLeaderCar(MEVehicle *veh, MSLink *link, const bool fromState=false)
Adds the given car to the leading vehicles.
Definition MELoop.cpp:301
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:114
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:397
void removeLeaderCar(MEVehicle *v)
Removes the given car from the leading vehicles.
Definition MELoop.cpp:318
int size() const
Definition MESegment.h:78
void setOccupancy(const double occ)
Definition MESegment.h:91
MEVehicle * remove(MEVehicle *v)
Definition MESegment.cpp:73
void setBlockTime(SUMOTime t)
Definition MESegment.h:111
SUMOTime getBlockTime() const
Definition MESegment.h:108
double myOccupancy
The occupied space (in m) in the queue.
Definition MESegment.h:130
bool allows(SUMOVehicleClass vclass) const
Definition MESegment.h:94
std::vector< MEVehicle * > & getModifiableVehicles()
Definition MESegment.h:85
void addReminders(MEVehicle *veh) const
Definition MESegment.cpp:98
void addDetector(MSMoveReminder *data)
Definition MESegment.cpp:90
void setEntryBlockTime(SUMOTime entryBlockTime)
set the next time at which a vehicle may enter this queue
Definition MESegment.h:104
double getOccupancy() const
Definition MESegment.h:88
std::vector< MEVehicle * > myVehicles
Definition MESegment.h:127
const std::vector< MEVehicle * > & getVehicles() const
Definition MESegment.h:81
SUMOTime getEntryBlockTime() const
return the next time at which a vehicle may enter this queue
Definition MESegment.h:99
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:620
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:555
SUMOTime myTau_ff
The time headway parameters, see the Eissfeldt thesis.
Definition MESegment.h:597
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:626
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition MESegment.h:277
SUMOTime myLastHeadway
the last headway
Definition MESegment.h:638
static const int PARKING_QUEUE
Definition MESegment.h:53
bool limitedControlOverride(const MSLink *link) const
whether the given link may be passed because the option meso-junction-control.limited is set
bool isOpen(const MEVehicle *veh) const
Returns whether the vehicle may use the next link.
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
void clearState()
Remove all vehicles before quick-loading state.
void receive(MEVehicle *veh, const int qIdx, SUMOTime time, const bool isDepart=false, const bool isTeleport=false, const bool newEdge=false)
Adds the vehicle to the segment, adapting its parameters.
static SVCPermissions myMultiModalWarnings
Definition MESegment.h:645
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:632
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:629
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:381
static MESegment myVaporizationTarget
Definition MESegment.h:643
int myLookahead
The number of route edges after myEdge to look up in myFollowerMap.
Definition MESegment.h:635
void addDownstreamFollowers(const MSEdge &edge, const std::vector< int > &reach, const double dist, const double lookahead, const int depth, SearchedMap &searched)
add the queues leading to the successors of the given downstream edge to myFollowerMap
virtual std::string getQueueExtraState(int) const
model specific queue state (e.g. the gap times of meso-ltm) for saving / loading
Definition MESegment.h:203
double myJamThreshold
The space (in m) which needs to be occupied before the segment is considered jammed.
Definition MESegment.h:623
const int myIndex
Running number of the segment in the edge.
Definition MESegment.h:591
virtual 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:604
double myMeanSpeed
the mean speed on this segment. Updated at event time or on demand
Definition MESegment.h:648
bool myCheckMinorPenalty
penalty for minor links
Definition MESegment.h:603
virtual SUMOTime computeHeadway(Queue &q, const Queue &qNext, const MESegment *const next, const MEVehicle *veh) const
compute current headway depending on traffic state
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:651
SUMOTime myTau_jf
Definition MESegment.h:597
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:585
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:588
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:582
static const std::string OVERRIDE_TLS_PENALTIES
special param value
Definition MESegment.h:55
MESegment(const std::string &id, const MSEdge &parent, MESegment *next, const double length, const double speed, const int idx, const bool multiQueue, const MesoEdgeType &edgeType)
constructor
MEVehicle * removeCar(MEVehicle *v, SUMOTime leaveTime, const MSMoveReminder::Notification reason)
Removes the given car from the edge's que.
std::vector< const MEVehicle * > getVehicles() const
returns all vehicles (for debugging)
static MSEdge myDummyParent
Definition MESegment.h:642
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:316
int getCarNumber() const
Returns the total number of cars on the segment.
Definition MESegment.h:220
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:614
SUMOTime myTau_jj
Definition MESegment.h:597
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:607
virtual bool hasSpaceForInsertion(const Queue &q, int qIdx, double newOccupancy, SUMOTime entryTime) const
check jam-avoidance constraints during insertion
bool myTLSPenalty
Whether tls penalty is enabled.
Definition MESegment.h:600
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:474
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:617
bool myOvertaking
Whether overtaking is permitted on this segment.
Definition MESegment.h:610
void prepareDetectorForWriting(MSMoveReminder &data, int queueIndex=-1)
Removes a data collector for a detector from this segment.
std::map< std::pair< const MSEdge *, std::vector< int > >, std::vector< std::pair< double, int > > > SearchedMap
the (distance, depth) pairs at which a downstream edge was searched with a given lane reach
Definition MESegment.h:568
bool vaporizeAnyCar(SUMOTime currentTime, const MSDetectorFileOutput *filter)
tries to remove any car from this segment
SUMOTime myTau_fj
Definition MESegment.h:597
SUMOTime getTauJJ(double nextQueueSize, double nextQueueCapacity, double nextJamThreshold) const
A vehicle from the mesoscopic point of view.
Definition MEVehicle.h:42
void markJammed(bool jammed)
Definition MEVehicle.h:385
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:319
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...
void setUnqueuedEventTime(SUMOTime t)
Sets the minimum time at which the vehicle leaves its current segment (this includes planned stops)
Definition MEVehicle.h:235
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition MEVehicle.h:290
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves its current segment.
Definition MEVehicle.h:206
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition MEVehicle.h:259
bool wasJammed() const
Definition MEVehicle.h:389
void setLastEntryTime(SUMOTime t)
Sets the entry time for the current segment.
Definition MEVehicle.h:282
int getQueIndex() const
Returns the index of the que the vehicle is in.
Definition MEVehicle.h:268
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition MEVehicle.h:250
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves its current segment.
Definition MEVehicle.h:218
void setBlockTime(const SUMOTime t)
Sets the time at which the vehicle was blocked.
Definition MEVehicle.h:304
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
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
bool isRail() const
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:285
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition MSCFModel.h:355
Base of value-generating classes (detectors)
bool vehicleApplies(const SUMOTrafficObject &veh) const
Checks whether the detector measures vehicles of the given type.
bool sidingDeadlock(const SUMOVehicle *veh) const
whether insertion on this driveway would cause deadlock in an approached siding
static const MSDriveWay * getDepartureDriveway(const SUMOVehicle *veh, bool init=false)
bool foeDriveWayOccupied(bool store, const SUMOVehicle *ego, MSEdgeVector &occupied) const
whether any of myFoes is occupied (vehicles that are the target of a join must be ignored)
A road/street connecting two junctions.
Definition MSEdge.h:78
virtual void unlock() const
release exclusive access to the mesoscopic state
Definition MSEdge.h:802
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition MSEdge.h:659
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:169
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:516
void invalidateMesoCache() const
Definition MSEdge.h:898
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:265
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is returned; should pr...
Definition MSEdge.cpp:1235
const MSJunction * getToJunction() const
Definition MSEdge.h:428
double getLength() const
return the length of the edge
Definition MSEdge.h:695
static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored=0)
Definition MSEdge.cpp:317
bool isRoundabout() const
Definition MSEdge.h:743
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:270
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:444
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1534
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1433
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition MSEdge.h:799
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1342
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
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:790
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:750
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:201
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
static bool isSignalized(SUMOVehicleClass svc)
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:53
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:66
const std::string & getID() const
Returns the id.
Definition Named.h:73
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Representation of a vehicle.
Definition SUMOVehicle.h:63
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
#define DEBUG_COND
edge type specific meso parameters
Definition MESegment.h:58