Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSEdge.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/****************************************************************************/
24// A road/street connecting two junctions
25/****************************************************************************/
26#include <config.h>
27
28#include <algorithm>
29#include <iostream>
30#include <cassert>
31#ifdef HAVE_FOX
33#endif
37#include <mesosim/MELoop.h>
38#include <mesosim/MESegment.h>
39#include <mesosim/MEVehicle.h>
40#include "MSInsertionControl.h"
41#include "MSJunction.h"
42#include "MSLane.h"
43#include "MSLaneChanger.h"
45#include "MSLink.h"
46#include "MSGlobals.h"
47#include "MSNet.h"
48#include "MSVehicle.h"
49#include "MSLeaderInfo.h"
52#include "MSEdge.h"
53
54#define BEST_LANE_LOOKAHEAD 3000.0
55
56// ===========================================================================
57// static member definitions
58// ===========================================================================
60std::unordered_map<std::string_view, MSEdge*> MSEdge::myHashDict;
65
66// ===========================================================================
67// member method definitions
68// ===========================================================================
69MSEdge::MSEdge(const std::string& id, int numericalID,
70 const SumoXMLEdgeFunc function,
71 const std::string& streetName,
72 const std::string& edgeType,
73 const std::string& routingType,
74 int priority,
75 double distance) :
76 Named(id), myNumericalID(numericalID), myLanes(nullptr),
77 myLaneChanger(nullptr), myFunction(function), myVaporizationRequests(0),
78 myLastFailedInsertionTime(-1),
79 myFromJunction(nullptr), myToJunction(nullptr),
80 myHaveTransientPermissions(false),
81 myOtherTazConnector(nullptr),
82 myStreetName(streetName),
83 myEdgeType(edgeType),
84 myRoutingType(routingType),
85 myPriority(priority),
86 myDistance(distance),
87 myWidth(0.),
88 myLength(0.),
89 myEmptyTraveltime(0.),
90 myTimePenalty(0.),
91 myAmDelayed(false),
92 myAmRoundabout(false),
93 myAmFringe(true),
94 myBidiEdge(nullptr)
95{ }
96
97
99 delete myLaneChanger;
102}
103
104
105void
106MSEdge::initialize(const std::vector<MSLane*>* lanes) {
107 assert(lanes != 0);
108 myLanes = std::shared_ptr<const std::vector<MSLane*> >(lanes);
111 }
112 for (MSLane* const lane : *lanes) {
113 lane->setRightSideOnEdge(myWidth, (int)mySublaneSides.size());
114 MSLeaderInfo ahead(lane->getWidth());
115 for (int j = 0; j < ahead.numSublanes(); ++j) {
117 }
118 myWidth += lane->getWidth();
119 }
120}
121
122
124 if (myLanes->empty()) {
125 return;
126 }
127 myLength = myLanes->front()->getLength();
128 myEmptyTraveltime = myLength / MAX2(getSpeedLimit(), NUMERICAL_EPS);
130 SUMOTime minorPenalty = 0;
131 bool haveTLSPenalty = MSGlobals::gTLSPenalty > 0;
134 minorPenalty = edgeType.minorPenalty;
135 haveTLSPenalty = edgeType.tlsPenalty > 0;
136 }
137 if (haveTLSPenalty || minorPenalty > 0) {
138 // add tls penalties to the minimum travel time
139 SUMOTime minPenalty = -1;
140 for (const MSLane* const l : *myLanes) {
141 for (const MSLink* const link : l->getLinkCont()) {
142 if (link->getLane()->isWalkingArea() && link->getLaneBefore()->isNormal()) {
143 continue;
144 }
145 SUMOTime linkPenalty = link->isTLSControlled() ? link->getMesoTLSPenalty() : (link->havePriority() ? 0 : minorPenalty);
146 if (minPenalty == -1) {
147 minPenalty = linkPenalty;
148 } else {
149 minPenalty = MIN2(minPenalty, linkPenalty);
150 }
151 }
152 }
153 if (minPenalty > 0) {
154 myEmptyTraveltime += STEPS2TIME(minPenalty);
155 myTimePenalty = STEPS2TIME(minPenalty);
156 }
157 }
158 } else if (isCrossing() && MSGlobals::gTLSPenalty > 0) {
159 // penalties are recorded for the entering link
160 for (const auto& ili : myLanes->front()->getIncomingLanes()) {
161 double penalty = STEPS2TIME(ili.viaLink->getMesoTLSPenalty());
162 if (!ili.viaLink->haveOffPriority()) {
163 penalty = MAX2(penalty, MSGlobals::gMinorPenalty);
164 }
165 if (penalty > 0) {
166 myEmptyTraveltime += penalty;
167 myTimePenalty = penalty;
168 }
169 }
171 const MSLink* link = myLanes->front()->getIncomingLanes()[0].viaLink;
172 if (!link->isTLSControlled() && !link->havePriority()) {
173 if (link->isTurnaround()) {
176 } else {
179 }
180 }
181 }
182}
183
184
185void
187 mySuccessors.clear();
188 myPredecessors.clear();
189 for (const MSEdge* edge : junction->getIncoming()) {
190 if (!edge->isInternal()) {
191 MSEdgeVector& succ = const_cast<MSEdgeVector&>(edge->mySuccessors);
192 MSConstEdgePairVector& succVia = const_cast<MSConstEdgePairVector&>(edge->myViaSuccessors);
193 MSEdgeVector& pred = const_cast<MSEdgeVector&>(edge->myPredecessors);
194 auto it = std::find(succ.begin(), succ.end(), this);
195 auto it2 = std::find(succVia.begin(), succVia.end(), std::make_pair(const_cast<const MSEdge*>(this), (const MSEdge*)nullptr));
196 auto it3 = std::find(pred.begin(), pred.end(), this);
197 if (it != succ.end()) {
198 succ.erase(it);
199 succVia.erase(it2);
200 }
201 if (it3 != pred.end()) {
202 pred.erase(it3);
203 }
204 }
205 }
206}
207
208void
210 for (MSLane* const lane : *myLanes) {
211 for (MSLink* const link : lane->getLinkCont()) {
212 link->initParallelLinks();
213 MSLane* const toL = link->getLane();
214 MSLane* const viaL = link->getViaLane();
215 if (toL != nullptr) {
216 MSEdge& to = toL->getEdge();
217 if (std::find(mySuccessors.begin(), mySuccessors.end(), &to) == mySuccessors.end()) {
218 mySuccessors.push_back(&to);
219 myViaSuccessors.push_back(std::make_pair(&to, (viaL == nullptr ? nullptr : &viaL->getEdge())));
220 }
221 if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
222 to.myPredecessors.push_back(this);
223 }
224 if (link->getDirection() != LinkDirection::TURN) {
225 myAmFringe = false;
226 }
227 }
228 if (viaL != nullptr) {
229 MSEdge& to = viaL->getEdge();
230 if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
231 to.myPredecessors.push_back(this);
232 }
233 }
234 }
235 lane->checkBufferType();
236 }
237 std::sort(mySuccessors.begin(), mySuccessors.end(), by_id_sorter());
239 recalcCache();
240
241 // extend lookup table for sublane model after all edges are read
242 if (myLanes->back()->getOpposite() != nullptr) {
243 MSLane* opposite = myLanes->back()->getOpposite();
244 MSLeaderInfo ahead(opposite->getWidth());
245 for (int j = 0; j < ahead.numSublanes(); ++j) {
247 }
248 }
249}
250
251
252void
258
259void
261 if (!myLanes->empty()) {
262 const bool allowChanging = allowsLaneChanging();
264 // may always initiate sublane-change
266 myLaneChanger = new MSLaneChangerSublane(myLanes.get(), allowChanging);
267 }
268 } else {
270 myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
271 } else if (myLanes->size() > 1 || canChangeToOpposite()) {
272 myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
273 }
274 }
275 }
276}
277
278
279bool
282 // allow changing only if all links leading to this internal lane have priority
283 // or they are controlled by a traffic light
284 for (const MSLane* const lane : *myLanes) {
285 const MSLink* const link = lane->getLogicalPredecessorLane()->getLinkTo(lane);
286 assert(link != nullptr);
287 const LinkState state = link->getState();
288 if ((state == LINKSTATE_MINOR && lane->getBidiLane() == nullptr)
289 || state == LINKSTATE_EQUAL
290 || state == LINKSTATE_STOP
291 || state == LINKSTATE_ALLWAY_STOP
292 || state == LINKSTATE_DEADEND) {
293 return false;
294 }
295 }
296 }
297 return true;
298}
299
300
301void
302MSEdge::addToAllowed(const SVCPermissions permissions, std::shared_ptr<const std::vector<MSLane*> > allowedLanes, AllowedLanesCont& laneCont) const {
303 if (!allowedLanes->empty()) {
304 // recheck whether we had this list to save memory
305 for (auto& allowed : laneCont) {
306 if (*allowed.second == *allowedLanes) {
307 allowed.first |= permissions;
308 return;
309 }
310 }
311 laneCont.push_back(std::make_pair(permissions, allowedLanes));
312 }
313}
314
315
318 SVCPermissions ignored = myMesoIgnoredVClasses & ~ignoreIgnored;
319 return (p | ignored) == ignored ? 0 : p;
320}
321
322
323void
324MSEdge::rebuildAllowedLanes(const bool onInit, bool updateVehicles) {
325 // hadPermissionChanges() only tracks transient (rerouter/TraCI-temporary)
326 // changes; a permanent change (e.g. traci.lane.setDisallowed /
327 // traci.edge.setAllowed) goes straight through MSLane::setPermissions and
328 // never registers there. Comparing the aggregated permissions before and
329 // after this rebuild catches that case too.
330 const SVCPermissions oldMinimumPermissions = myMinimumPermissions;
331 const SVCPermissions oldCombinedPermissions = myCombinedPermissions;
332 // rebuild myMinimumPermissions and myCombinedPermissions
335 bool lanesChangedPermission = false;
336 for (MSLane* const lane : *myLanes) {
337 // same dedicated lanes are ignored in meso to avoid capacity errors.
338 // Here we have to make sure that vehicles which are set to depart on
339 // such lanes trigger an error.
340 SVCPermissions allow = getMesoPermissions(lane->getPermissions(), SVC_PEDESTRIAN);
341 myMinimumPermissions &= allow;
342 myCombinedPermissions |= allow;
343 lanesChangedPermission |= lane->hadPermissionChanges();
344 }
345 if (!onInit && !myHaveTransientPermissions && lanesChangedPermission) {
347 // backup original structures when first needed
351 }
352 if (!onInit && (lanesChangedPermission
353 || myMinimumPermissions != oldMinimumPermissions
354 || myCombinedPermissions != oldCombinedPermissions)) {
355 // a runtime permission change (closure / re-opening, transient or
356 // permanent) must reach the CCH metric even though the speed table
357 // does not move
359 }
360 // rebuild myAllowed
361 myAllowed.clear();
363 myAllowed.push_back(std::make_pair(SVC_IGNORING, myLanes));
364 for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
365 if ((myCombinedPermissions & vclass) == vclass) {
366 std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
367 for (MSLane* const lane : *myLanes) {
368 if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
369 allowedLanes->push_back(lane);
370 }
371 }
373 }
374 }
375 }
376 if (onInit) {
379 } else {
380 rebuildAllowedTargets(updateVehicles);
381 for (MSEdge* pred : myPredecessors) {
382 if (myHaveTransientPermissions && !pred->myHaveTransientPermissions) {
383 pred->myOrigAllowed = pred->myAllowed;
384 pred->myOrigAllowedTargets = pred->myAllowedTargets;
385 pred->myOrigClassesViaSuccessorMap = pred->myClassesViaSuccessorMap;
386 pred->myHaveTransientPermissions = true;
387 }
388 pred->rebuildAllowedTargets(updateVehicles);
389 }
391 for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*this); s != nullptr; s = s->getNextSegment()) {
392 s->updatePermissions();
393 }
394 }
395 for (MSLane* const lane : *myLanes) {
396 for (MSLink* link : lane->getLinkCont()) {
397 link->updatePermissions();
398 }
399 for (auto ili : lane->getIncomingLanes()) {
400 ili.viaLink->updatePermissions();
401 }
402 }
403 // permissions of links entering this edge also depend on its new permissions,
404 // so they must be refreshed as well (important for connections via internal lanes)
405 for (MSEdge* const pred : myPredecessors) {
406 for (MSLane* const lane : *pred->myLanes) {
407 for (MSLink* link : lane->getLinkCont()) {
408 if (&link->getLane()->getEdge() == this) {
409 link->updatePermissions();
410 }
411 }
412 }
413 }
414 }
415}
416
417
418void
419MSEdge::rebuildAllowedTargets(const bool updateVehicles) {
420 myAllowedTargets.clear();
421 for (const MSEdge* target : mySuccessors) {
422 bool universalMap = true; // whether the mapping for SVC_IGNORING is also valid for all vehicle classes
423 std::shared_ptr<std::vector<MSLane*> > allLanes = std::make_shared<std::vector<MSLane*> >();
424 // compute the mapping for SVC_IGNORING
425 for (MSLane* const lane : *myLanes) {
426 SVCPermissions combinedTargetPermissions = 0;
427 for (const MSLink* const link : lane->getLinkCont()) {
428 if (&link->getLane()->getEdge() == target) {
429 allLanes->push_back(lane);
430 combinedTargetPermissions |= link->getLane()->getPermissions();
431 if (link->getViaLane() != nullptr &&
432 ((lane->getPermissions() & link->getLane()->getPermissions()) != link->getViaLane()->getPermissions())) {
433 // custom connection permissions
434 universalMap = false;
435 }
436 }
437 }
438 if (combinedTargetPermissions == 0 || (lane->getPermissions() & combinedTargetPermissions) != lane->getPermissions()) {
439 universalMap = false;
440 }
441 }
442 if (universalMap) {
443 if (myAllowed.empty()) {
444 // we have no lane specific permissions
445 myAllowedTargets[target].push_back(std::make_pair(myMinimumPermissions, myLanes));
446 } else {
447 for (const auto& i : myAllowed) {
448 addToAllowed(i.first, i.second, myAllowedTargets[target]);
449 }
450 }
451 } else {
452 addToAllowed(SVC_IGNORING, allLanes, myAllowedTargets[target]);
453 // compute the vclass specific mapping
454 for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
455 if ((myCombinedPermissions & vclass) == vclass) {
456 std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
457 for (MSLane* const lane : *myLanes) {
458 if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
459 for (const MSLink* const link : lane->getLinkCont()) {
460 if (link->getLane()->allowsVehicleClass((SUMOVehicleClass)vclass) && &link->getLane()->getEdge() == target && (link->getViaLane() == nullptr || link->getViaLane()->allowsVehicleClass((SUMOVehicleClass)vclass))) {
461 allowedLanes->push_back(lane);
462 }
463 }
464 }
465 }
467 }
468 }
469 }
470 }
471 if (updateVehicles) {
472 for (const MSLane* const lane : *myLanes) {
473 const MSLane::VehCont& vehs = lane->getVehiclesSecure();
474 for (MSVehicle* veh : vehs) {
475 veh->updateBestLanes(true);
476 }
477 lane->releaseVehicles();
478 }
479 }
480 myClassesSuccessorMap.clear();
482}
483
484
485// ------------ Access to the edge's lanes
486MSLane*
487MSEdge::leftLane(const MSLane* const lane) const {
488 return parallelLane(lane, 1);
489}
490
491
492MSLane*
493MSEdge::rightLane(const MSLane* const lane) const {
494 return parallelLane(lane, -1);
495}
496
497
498MSLane*
499MSEdge::parallelLane(const MSLane* const lane, int offset, bool includeOpposite) const {
500 const int resultIndex = lane->getIndex() + offset;
501 if (resultIndex >= getNumLanes() && includeOpposite) {
502 const MSEdge* opposite = getOppositeEdge();
503 if (opposite != nullptr && resultIndex < getNumLanes() + opposite->getNumLanes()) {
504 return opposite->getLanes()[opposite->getNumLanes() + getNumLanes() - resultIndex - 1];
505 }
506 return nullptr;
507 } else if (resultIndex >= (int)myLanes->size() || resultIndex < 0) {
508 return nullptr;
509 } else {
510 return (*myLanes)[resultIndex];
511 }
512}
513
514
515const std::vector<MSLane*>*
516MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
517 const auto& targets = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowedTargets : myAllowedTargets;
518 AllowedLanesByTarget::const_iterator i = targets.find(&destination);
519 if (i != targets.end()) {
520 for (const auto& allowed : i->second) {
521 if ((allowed.first & vclass) == vclass) {
522 return allowed.second.get();
523 }
524 }
525 }
526 return nullptr;
527}
528
529
530const std::vector<MSLane*>*
532 if ((myMinimumPermissions & vclass) == vclass) {
533 return myLanes.get();
534 } else {
535 if ((myCombinedPermissions & vclass) == vclass) {
536 for (const auto& allowed : myAllowed) {
537 if ((allowed.first & vclass) == vclass) {
538 return allowed.second.get();
539 }
540 }
541 }
542 return nullptr;
543 }
544}
545
546
547const std::vector<MSLane*>*
548MSEdge::allowedLanes(SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
549 const SVCPermissions& minP = ignoreTransientPermissions ? myOriginalMinimumPermissions : myMinimumPermissions;
550 if ((minP & vclass) == vclass) {
551 return myLanes.get();
552 } else {
553 const SVCPermissions comP = ignoreTransientPermissions ? myOriginalCombinedPermissions : myCombinedPermissions;
554 if ((comP & vclass) == vclass) {
555 const AllowedLanesCont& allowedCont = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowed : myAllowed;
556 for (const auto& allowed : allowedCont) {
557 if ((allowed.first & vclass) == vclass) {
558 return allowed.second.get();
559 }
560 }
561 }
562 return nullptr;
563 }
564}
565
566
567// ------------
573
574
580
581
582MSLane*
583MSEdge::getFreeLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos) const {
584 if (allowed == nullptr) {
585 allowed = allowedLanes(vclass);
586 }
587 MSLane* res = nullptr;
588 if (allowed != nullptr) {
589 double largestGap = 0;
590 MSLane* resByGap = nullptr;
591 double leastOccupancy = std::numeric_limits<double>::max();
592 for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i) {
593 const double occupancy = (*i)->getBruttoOccupancy();
594 if (occupancy < leastOccupancy) {
595 res = (*i);
596 leastOccupancy = occupancy;
597 }
598 const MSVehicle* last = (*i)->getLastFullVehicle();
599 const double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
600 if (lastGap > largestGap) {
601 largestGap = lastGap;
602 resByGap = (*i);
603 }
604 }
605 if (resByGap != nullptr) {
606 //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
607 res = resByGap;
608 }
609 }
610 return res;
611}
612
613
614MSLane*
615MSEdge::getProbableLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos, double maxSpeed) const {
616 if (allowed == nullptr) {
617 allowed = allowedLanes(vclass);
618 }
619 MSLane* res = nullptr;
620 if (allowed != nullptr) {
621 double largestGap = 0;
622 double largestSpeed = 0;
623 MSLane* resByGap = nullptr;
624 double leastOccupancy = std::numeric_limits<double>::max();
625 int aIndex = 0;
626 for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i, aIndex++) {
627 const double occupancy = (*i)->getBruttoOccupancy();
628 if (occupancy < leastOccupancy) {
629 res = (*i);
630 leastOccupancy = occupancy;
631 }
632 const MSVehicle* last = (*i)->getLastFullVehicle();
633 double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
634 // never insert to the left of a vehicle with a larger speedFactor
635 if (lastGap > largestGap && maxSpeed >= largestSpeed) {
636 largestGap = lastGap;
637 resByGap = (*i);
638 }
639 if (last != nullptr) {
640 largestSpeed = MAX2(largestSpeed, getVehicleMaxSpeed(last));
641 }
642 }
643 if (resByGap != nullptr) {
644 //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
645 res = resByGap;
646 }
647 }
648 return res;
649}
650
651
652double
653MSEdge::getDepartPosBound(const MSVehicle& veh, bool upper) const {
654 const SUMOVehicleParameter& pars = veh.getParameter();
655 double pos = getLength();
656 // determine the position
657 switch (pars.departPosProcedure) {
659 pos = pars.departPos;
660 if (pos < 0.) {
661 pos += myLength;
662 }
663 break;
665 // could be any position on the edge
666 break;
668 // could be any position on the edge due to multiple random attempts
669 break;
671 // many candidate positions, upper bound could be computed exactly
672 // with much effort
673 break;
675 if (upper) {
676 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
677 MSVehicle* last = (*i)->getLastFullVehicle();
678 if (last != nullptr) {
679 pos = MIN2(pos, last->getPositionOnLane());
680 }
681 }
682 } else {
683 pos = 0;
684 }
685 break;
688 if (!upper) {
689 pos = 0;
690 }
691 break;
692 default:
693 pos = MIN2(pos, veh.getVehicleType().getLength());
694 break;
695 }
696 return pos;
697}
698
699
700MSLane*
703 if ((int) myLanes->size() <= veh.getParameter().departLane || !(*myLanes)[veh.getParameter().departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
704 return nullptr;
705 }
706 return (*myLanes)[veh.getParameter().departLane];
707 }
708 return (*myLanes)[0];
709}
710
711
712MSLane*
715 int departLane = veh.getParameter().departLane;
718 departLane = myDefaultDepartLane;
719 }
720 switch (dld) {
722 if ((int) myLanes->size() <= departLane || !(*myLanes)[departLane]->allowsVehicleClass(veh.getVClass())) {
723 return nullptr;
724 }
725 return (*myLanes)[departLane];
729 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
731 if (veh.getRoute().size() == 1) {
732 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
733 } else {
735 }
738 veh.updateBestLanes(false, myLanes->front());
739 const std::vector<MSVehicle::LaneQ>& bl = veh.getBestLanes();
740 double bestLength = -1;
741 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
742 if ((*i).length > bestLength) {
743 bestLength = (*i).length;
744 }
745 }
746 // beyond a certain length, all lanes are suitable
747 // however, we still need to check departPos to avoid unsuitable insertion
748 // (this is only possible in some cases)
749 double departPos = 0;
750 if (bestLength > BEST_LANE_LOOKAHEAD) {
751 departPos = getDepartPosBound(veh);
752 bestLength = MIN2(bestLength - departPos, BEST_LANE_LOOKAHEAD);
753 }
754 std::vector<MSLane*>* bestLanes = new std::vector<MSLane*>();
755 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
756 if (((*i).length - departPos) >= bestLength) {
757 if (isInternal()) {
758 for (MSLane* lane : *myLanes) {
759 if (lane->getNormalSuccessorLane() == (*i).lane && lane->allowsVehicleClass(veh.getVClass())) {
760 bestLanes->push_back(lane);
761 }
762 }
763 } else if ((*i).lane->allowsVehicleClass(veh.getVClass())) {
764 bestLanes->push_back((*i).lane);
765 }
766 }
767 }
768 MSLane* ret = nullptr;
770 ret = getFreeLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
771 } else {
772 ret = getProbableLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false), getVehicleMaxSpeed(&veh));
773 }
774 delete bestLanes;
775 return ret;
776 }
780 default:
781 break;
782 }
783 if (!(*myLanes)[0]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
784 return nullptr;
785 }
786 return (*myLanes)[0];
787}
788
789
790MSLane*
791MSEdge::getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst, int routingMode) const {
792 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
793 if ((*i)->allowsVehicleClass(vClass, routingMode)) {
794 return *i;
795 }
796 }
797 return defaultFirst && !myLanes->empty() ? myLanes->front() : nullptr;
798}
799
800
801bool
803 const SUMOVehicleParameter& pars = v.getParameter();
804 const MSVehicleType& type = v.getVehicleType();
806 // departSpeed could have been rounded down in the output
807 double vMax = getVehicleMaxSpeed(&v) + SPEED_EPS;
808 if (pars.departSpeed > vMax) {
809 // check departLane (getVehicleMaxSpeed checks lane 0)
810 MSLane* departLane = MSGlobals::gMesoNet ? getDepartLaneMeso(v) : getDepartLane(dynamic_cast<MSVehicle&>(v));
811 if (departLane != nullptr) {
812 vMax = departLane->getVehicleMaxSpeed(&v);
814 // speedFactor could have been rounded down in the output
815 vMax *= (1 + SPEED_EPS);
816 }
817 // additive term must come after multiplication!
818 vMax += SPEED_EPS;
819 if (pars.departSpeed > vMax) {
820 if (type.getSpeedFactor().getParameter(1) > 0.) {
822 if (v.getChosenSpeedFactor() > type.getSpeedFactor().getParameter(0) + 2 * type.getSpeedFactor().getParameter(1)) {
823 // only warn for significant deviation
824 WRITE_WARNINGF(TL("Choosing new speed factor % for vehicle '%' to match departure speed % (max %)."),
825 toString(v.getChosenSpeedFactor()), pars.id, pars.departSpeed, vMax);
826 }
827 } else {
828 return false;
829 }
830 }
831 }
832 }
833 }
834 return true;
835}
836
837
838bool
839MSEdge::insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly, const bool forceCheck) const {
840 // when vaporizing, no vehicles are inserted, but checking needs to be successful to trigger removal
842 || v.getRouteValidity(true, checkOnly) != MSBaseVehicle::ROUTE_VALID) {
843 return checkOnly;
844 }
845 const SUMOVehicleParameter& pars = v.getParameter();
846 if (!validateDepartSpeed(v)) {
848 throw ProcessError(TLF("Departure speed for vehicle '%' is too high for the departure edge '%', time=%.",
849 pars.id, getID(), time2string(time)));
850 } else {
851 WRITE_WARNINGF(TL("Departure speed for vehicle '%' is too high for the departure edge '%', time=%."),
852 pars.id, getID(), time2string(time));
853 }
854 }
856 if (!forceCheck && myLastFailedInsertionTime == time) {
857 return false;
858 }
859 double pos = 0.0;
860 switch (pars.departPosProcedure) {
862 if (pars.departPos >= 0.) {
863 pos = pars.departPos;
864 } else {
865 pos = pars.departPos + getLength();
866 }
867 if (pos < 0 || pos > getLength()) {
868 WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
869 pos, v.getID(), time2string(time));
870 pos = getLength();
871 }
872 break;
876 break;
877 default:
878 break;
879 }
880 bool result = false;
881 MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this, pos);
882 MEVehicle* veh = static_cast<MEVehicle*>(&v);
883 int qIdx;
885 while (segment != nullptr && !result) {
886 if (checkOnly) {
887 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
888 } else {
889 result = segment->initialise(veh, time);
890 }
891 segment = segment->getNextSegment();
892 }
893 } else {
894 if (checkOnly) {
895 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
896 } else {
897 result = segment->initialise(veh, time);
898 }
899 }
900 return result;
901 }
902 if (checkOnly) {
906 }
907 switch (dld) {
911 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
912 if (insertionLane == nullptr) {
913 WRITE_WARNINGF(TL("Could not insert vehicle '%' on any lane of edge '%', time=%."),
914 v.getID(), getID(), time2string(time));
915 return false;
916 }
917 const double occupancy = insertionLane->getBruttoOccupancy();
918 return (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
920 }
921 default:
922 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
923 const double occupancy = (*i)->getBruttoOccupancy();
924 if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
926 return true;
927 }
928 }
929 }
930 return false;
931 }
932 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
933 if (insertionLane == nullptr) {
934 return false;
935 }
936
937 if (!forceCheck) {
938 if (myLastFailedInsertionTime == time) {
939 if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
940 // A vehicle was already rejected for the proposed insertionLane in this timestep
941 return false;
942 }
943 } else {
944 // last rejection occurred in a previous timestep, clear cache
946 }
947 }
948
949 bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
950
951 if (!success) {
952 // constraints may enforce explicit re-ordering so we need to try other vehicles after failure
953 if (!insertionLane->hasParameter("insertionOrder" + v.getID())) {
954 myFailedInsertionMemory.insert(insertionLane->getIndex());
955 }
956 }
957 return success;
958}
959
960
961void
963 if (myLaneChanger != nullptr) {
965 }
966}
967
968
969const MSEdge*
970MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
971 //@todo to be optimized
972 for (const MSLane* const l : *myLanes) {
973 for (const MSLink* const link : l->getLinkCont()) {
974 if (&link->getLane()->getEdge() == followerAfterInternal) {
975 if (link->getViaLane() != nullptr) {
976 if (link->getViaLane()->allowsVehicleClass(vClass)) {
977 return &link->getViaLane()->getEdge();
978 } else {
979 continue;
980 }
981 } else {
982 return nullptr; // network without internal links
983 }
984 }
985 }
986 }
987 return nullptr;
988}
989
990
991double
992MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
993 assert(followerAfterInternal != 0);
994 assert(!followerAfterInternal->isInternal());
995 double dist = 0.;
996 const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal, vClass);
997 // Take into account non-internal lengths until next non-internal edge
998 while (edge != nullptr && edge->isInternal()) {
999 dist += edge->getLength();
1000 edge = edge->getInternalFollowingEdge(followerAfterInternal, vClass);
1001 }
1002 return dist;
1003}
1004
1005
1006const MSEdge*
1008 const MSEdge* result = this;
1009 while (result->isInternal() && MSGlobals::gUsingInternalLanes) {
1010 assert(result->getPredecessors().size() == 1);
1011 result = result->getPredecessors().front();
1012 }
1013 return result;
1014}
1015
1016const MSEdge*
1018 const MSEdge* result = this;
1019 while (result->isInternal()) {
1020 assert(result->getSuccessors().size() == 1);
1021 result = result->getSuccessors().front();
1022 }
1023 return result;
1024}
1025
1026double
1028 double v = 0;
1029 double totalNumVehs = 0;
1031 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1032 const int numVehs = segment->getCarNumber();
1033 if (numVehs > 0) {
1034 v += numVehs * segment->getMeanSpeed();
1035 totalNumVehs += numVehs;
1036 }
1037 }
1038 if (totalNumVehs == 0) {
1039 return getLength() / myEmptyTraveltime; // may include tls-penalty
1040 }
1041 } else {
1042 for (const MSLane* const lane : *myLanes) {
1043 int numVehs = lane->getVehicleNumber();
1044 if (numVehs == 0) {
1045 // take speed limit but with lowest possible weight
1046 numVehs = 1;
1047 }
1048 v += numVehs * lane->getMeanSpeed();
1049 totalNumVehs += numVehs;
1050 }
1051 if (myBidiEdge != nullptr) {
1052 for (const MSLane* const lane : myBidiEdge->getLanes()) {
1053 if (lane->getVehicleNumber() > 0) {
1054 // do not route across edges which are already occupied in reverse direction
1055 return 0;
1056 }
1057 }
1058 }
1059 if (totalNumVehs == 0) {
1060 return getSpeedLimit();
1061 }
1062 }
1063 return v / totalNumVehs;
1064}
1065
1066
1067double
1069 double f = 0.;
1070 for (const MSLane* const lane : *myLanes) {
1071 f += lane->getFrictionCoefficient();
1072 }
1073 if (!myLanes->empty()) {
1074 return f / (double)myLanes->size();
1075 }
1076 return 1.;
1077}
1078
1079
1080double
1083 // no separate bicycle speeds in meso
1084 return getMeanSpeed();
1085 }
1086 double v = 0;
1087 double totalNumVehs = 0;
1088 for (const MSLane* const lane : *myLanes) {
1089 const int numVehs = lane->getVehicleNumber();
1090 v += numVehs * lane->getMeanSpeedBike();
1091 totalNumVehs += numVehs;
1092 }
1093 if (totalNumVehs == 0) {
1094 return getSpeedLimit();
1095 }
1096 return v / totalNumVehs;
1097}
1098
1099
1100double
1101MSEdge::getCurrentTravelTime(double minSpeed) const {
1102 assert(minSpeed > 0);
1103 if (!myAmDelayed) {
1104 return myEmptyTraveltime;
1105 }
1106 return getLength() / MAX2(minSpeed, getMeanSpeed());
1107}
1108
1109
1110double
1112 return MSRoutingEngine::getAssumedSpeed(this, nullptr);
1113}
1114
1115
1116bool
1117MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
1118 const DictType::iterator it = myDict.lower_bound(id);
1119 if (it == myDict.end() || it->first != id) {
1120 // id not in myDict
1121 const auto it2 = myDict.emplace_hint(it, id, ptr);
1122 myHashDict[it2->first] = ptr;
1123 while (ptr->getNumericalID() >= (int)myEdges.size()) {
1124 myEdges.push_back(nullptr);
1125 }
1126 myEdges[ptr->getNumericalID()] = ptr;
1127 return true;
1128 }
1129 return false;
1130}
1131
1132
1133MSEdge*
1134MSEdge::dictionary(const std::string_view& id) {
1135 auto it = myHashDict.find(id);
1136 if (it == myHashDict.end()) {
1137 return nullptr;
1138 }
1139 return it->second;
1140}
1141
1142
1143MSEdge*
1144MSEdge::dictionaryHint(const std::string& id, const int startIdx) {
1145 // this method is mainly useful when parsing connections from the net.xml which are sorted by "from" id
1146 if (myEdges[startIdx] != nullptr && myEdges[startIdx]->getID() == id) {
1147 return myEdges[startIdx];
1148 }
1149 if (startIdx + 1 < (int)myEdges.size() && myEdges[startIdx + 1] != nullptr && myEdges[startIdx + 1]->getID() == id) {
1150 return myEdges[startIdx + 1];
1151 }
1152 return dictionary(id);
1153}
1154
1155
1156const MSEdgeVector&
1158 return myEdges;
1159}
1160
1161
1162void
1164 // the keys point into myDict so we need to clear this one first
1165 myHashDict.clear();
1166 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1167 delete (*i).second;
1168 }
1169 myDict.clear();
1170 myEdges.clear();
1171}
1172
1173
1174void
1175MSEdge::insertIDs(std::vector<std::string>& into) {
1176 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1177 into.push_back((*i).first);
1178 }
1179}
1180
1181
1182void
1183MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
1184 const std::string& rid) {
1185 try {
1187 } catch (const InvalidArgument& e) {
1188 throw ProcessError("The edge '" + std::string(e.what()) + "' within the route " + rid + " is not known."
1189 + "\n The route can not be build.");
1190 }
1191}
1192
1193
1194void
1195MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
1196 const std::string& rid) {
1197 for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1198 const MSEdge* edge = MSEdge::dictionary(*i);
1199 // check whether the edge exists
1200 if (edge == nullptr) {
1201 throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
1202 + "\n The route can not be build.");
1203 }
1204 into.push_back(edge);
1205 }
1206}
1207
1208
1209double
1210MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
1211 assert(this != other);
1212 if (doBoundaryEstimate) {
1213 return myBoundary.distanceTo2D(other->myBoundary);
1214 }
1215 if (isTazConnector()) {
1216 if (other->isTazConnector()) {
1217 return myBoundary.distanceTo2D(other->myBoundary);
1218 }
1219 return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
1220 }
1221 if (other->isTazConnector()) {
1222 return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
1223 }
1224 return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
1225}
1226
1227
1228const Position
1230 return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
1231}
1232
1233
1234double
1236 // @note lanes might have different maximum speeds in theory
1237 return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
1238}
1239
1240
1241double
1243 // @note lanes might have different maximum speeds in theory
1244 return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit(svc);
1245}
1246
1247
1248double
1250 return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
1251}
1252
1253double
1255 // @note lanes might have different maximum speeds in theory
1256 return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
1257}
1258
1259
1260void
1261MSEdge::setMaxSpeed(const double val, const bool modified, const double jamThreshold) {
1262 assert(val >= 0);
1263 if (myLanes != nullptr) {
1264 for (MSLane* const lane : *myLanes) {
1265 lane->setMaxSpeed(val, modified, jamThreshold);
1266 }
1267 }
1268}
1269
1270
1271void
1273 if (t->isPerson()) {
1274 myPersons.insert(t);
1275 } else {
1276 myContainers.insert(t);
1277 }
1278}
1279
1280void
1282 std::set<MSTransportable*, ComparatorNumericalIdLess>& tc = t->isPerson() ? myPersons : myContainers;
1283 auto it = tc.find(t);
1284 if (it != tc.end()) {
1285 tc.erase(it);
1286 }
1287}
1288
1289std::vector<MSTransportable*>
1290MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
1291 std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
1292 if (includeRiding) {
1293 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1294 const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
1295 for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
1296 const std::vector<MSTransportable*>& persons = (*j)->getPersons();
1297 result.insert(result.end(), persons.begin(), persons.end());
1298 }
1299 (*i)->releaseVehicles();
1300 }
1301 }
1302 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1303 return result;
1304}
1305
1306
1307std::vector<MSTransportable*>
1308MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
1309 std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
1310 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1311 return result;
1312}
1313
1314
1315int
1317 const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
1318 const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
1319 if (pos1 != pos2) {
1320 return pos1 < pos2;
1321 }
1322 return c1->getID() < c2->getID();
1323}
1324
1325
1326void
1328 mySuccessors.push_back(edge);
1329 myViaSuccessors.push_back(std::make_pair(edge, via));
1330 if (isTazConnector() && edge->getFromJunction() != nullptr) {
1332 }
1333
1334 edge->myPredecessors.push_back(this);
1335 if (edge->isTazConnector() && getToJunction() != nullptr) {
1336 edge->myBoundary.add(getToJunction()->getPosition());
1337 }
1338}
1339
1340
1341const MSEdgeVector&
1343 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1344 return mySuccessors;
1345 }
1346#ifdef HAVE_FOX
1347 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1348#endif
1349 std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1350 if (i == myClassesSuccessorMap.end()) {
1351 // instantiate vector
1352 myClassesSuccessorMap[vClass];
1353 i = myClassesSuccessorMap.find(vClass);
1354 // this vClass is requested for the first time. rebuild all successors
1355 for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1356 if ((*it)->isTazConnector()) {
1357 i->second.push_back(*it);
1358 } else {
1359 const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1360 if (allowed != nullptr && allowed->size() > 0) {
1361 i->second.push_back(*it);
1362 }
1363 }
1364 }
1365 }
1366 // can use cached value
1367 return i->second;
1368}
1369
1370
1372MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
1373 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1374 return myViaSuccessors;
1375 }
1376#ifdef HAVE_FOX
1377 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1378#endif
1379 auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
1380 auto i = viaMap.find(vClass);
1381 if (i == viaMap.end()) {
1382 // instantiate vector
1383 MSConstEdgePairVector& result = viaMap[vClass];
1384 // this vClass is requested for the first time. rebuild all successors
1385 for (const auto& viaPair : myViaSuccessors) {
1386 if (viaPair.first->isTazConnector()) {
1387 result.push_back(viaPair);
1388 } else {
1389 const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
1390 if (allowed != nullptr && allowed->size() > 0) {
1391 result.push_back(viaPair);
1392 }
1393 }
1394 }
1395 i = viaMap.find(vClass);
1396 }
1397 return i->second;
1398}
1399
1400
1401void
1403 myFromJunction = from;
1404 myToJunction = to;
1405 if (!isTazConnector()) {
1406 myBoundary.add(from->getPosition());
1407 myBoundary.add(to->getPosition());
1408 }
1409}
1410
1411
1412bool
1414 return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1415 // do not change on curved internal lanes
1416 (!isInternal()
1418 && myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LinkDirection::STRAIGHT)));
1419}
1420
1421
1422const MSEdge*
1424 if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1425 return &(myLanes->back()->getOpposite()->getEdge());
1426 } else {
1427 return nullptr;
1428 }
1429}
1430
1431
1432bool
1434 for (const MSLane* const l : *myLanes) {
1435 for (const MSLink* const link : l->getLinkCont()) {
1436 if (!link->havePriority()) {
1437 return true;
1438 }
1439 }
1440 }
1441 return false;
1442}
1443
1444bool
1446 if (myLanes->size() == 1) {
1447 return false;
1448 }
1449 for (const MSLane* const l : *myLanes) {
1450 if (l->getIndex() <= index && !l->allowsChangingRight(svc) && l->getIndex() > 0) {
1451 return true;
1452 } else if (l->getIndex() >= index && !l->allowsChangingLeft(svc) && l->getIndex() < (int)(myLanes->size() - 1)) {
1453 return true;
1454 }
1455 }
1456 return false;
1457}
1458
1459void
1460MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1461 if (bidiID != "") {
1462 myBidiEdge = dictionary(bidiID);
1463 if (myBidiEdge == nullptr) {
1464 WRITE_ERRORF(TL("Bidi-edge '%' does not exist"), bidiID);
1465 }
1466 setBidiLanes();
1467 return;
1468 }
1470 return;
1471 }
1472 // legacy networks (no bidi attribute)
1474 for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1475 if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1476 if (myBidiEdge != nullptr && isSuperposable(*it)) {
1477 WRITE_WARNINGF(TL("Ambiguous superposable edges between junction '%' and '%'."), myToJunction->getID(), myFromJunction->getID());
1478 break;
1479 }
1480 if (isSuperposable(*it)) {
1481 myBidiEdge = *it;
1482 setBidiLanes();
1483 }
1484 }
1485 }
1486}
1487
1488
1489void
1491 assert(myBidiEdge != nullptr);
1492 if (getNumLanes() == 1 && myBidiEdge->getNumLanes() == 1) {
1493 // the other way round is set when this method runs for the bidiEdge
1494 getLanes()[0]->setBidiLane(myBidiEdge->getLanes()[0]);
1495 } else {
1496 // find lanes with matching reversed shapes
1497 int numBidiLanes = 0;
1498 for (MSLane* l1 : *myLanes) {
1499 for (MSLane* l2 : *myBidiEdge->myLanes) {
1500 if (l1->getShape().reverse().almostSame(l2->getShape(), POSITION_EPS * 2)) {
1501 l1->setBidiLane(l2);
1502 numBidiLanes++;
1503 }
1504 }
1505 }
1506 // warn only once for each pair
1507 if (numBidiLanes == 0 && getNumericalID() < myBidiEdge->getNumericalID()) {
1508 WRITE_WARNINGF(TL("Edge '%' and bidi edge '%' have no matching bidi lanes"), getID(), myBidiEdge->getID());
1509 }
1510 }
1511}
1512
1513
1514bool
1516 if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1517 return false;
1518 }
1519 std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1520 std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1521 do {
1522 if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1523 return false;
1524 }
1525 it1++;
1526 it2++;
1527 } while (it1 != myLanes->end());
1528
1529 return true;
1530}
1531
1532
1533void
1535#ifdef HAVE_FOX
1536 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1537#endif
1538 myWaiting.push_back(vehicle);
1539}
1540
1541
1542void
1543MSEdge::removeWaiting(const SUMOVehicle* vehicle) const {
1544#ifdef HAVE_FOX
1545 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1546#endif
1547 std::vector<SUMOVehicle*>::iterator it = std::find(myWaiting.begin(), myWaiting.end(), vehicle);
1548 if (it != myWaiting.end()) {
1549 myWaiting.erase(it);
1550 }
1551}
1552
1553
1555MSEdge::getWaitingVehicle(MSTransportable* transportable, const double position) const {
1556#ifdef HAVE_FOX
1557 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1558#endif
1559 for (SUMOVehicle* const vehicle : myWaiting) {
1560 if (transportable->isWaitingFor(vehicle)) {
1561 if (vehicle->isStoppedInRange(position, MSGlobals::gStopTolerance) ||
1562 (!vehicle->hasDeparted() &&
1563 (vehicle->getParameter().departProcedure == DepartDefinition::TRIGGERED ||
1564 vehicle->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED))) {
1565 return vehicle;
1566 }
1567 if (!vehicle->isLineStop(position) && vehicle->allowsBoarding(transportable)) {
1568 WRITE_WARNING((transportable->isPerson() ? "Person '" : "Container '")
1569 + transportable->getID() + "' at edge '" + getID() + "' position " + toString(position) + " cannot use waiting vehicle '"
1570 + vehicle->getID() + "' at position " + toString(vehicle->getPositionOnLane()) + " because it is too far away.");
1571 }
1572 }
1573 }
1574 return nullptr;
1575}
1576
1577std::vector<const SUMOVehicle*>
1579 std::vector<const SUMOVehicle*> result;
1581 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1582 std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
1583 result.insert(result.end(), segmentVehs.begin(), segmentVehs.end());
1584 }
1585 } else {
1586 for (MSLane* lane : getLanes()) {
1587 for (auto veh : lane->getVehiclesSecure()) {
1588 result.push_back(veh);
1589 }
1590 lane->releaseVehicles();
1591 }
1592 }
1593 return result;
1594}
1595
1596int
1598 int result = 0;
1599 SVCPermissions filter = SVCAll;
1601 filter = ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1602 } else if ((myCombinedPermissions & (SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1603 // filter out green verge
1604 filter = (SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1605 }
1606 for (const MSLane* const l : *myLanes) {
1607 if ((l->getPermissions() & filter) != 0) {
1608 result++;
1609 }
1610 }
1611 return result;
1612}
1613
1614int
1616 return (int)getVehicles().size();
1617}
1618
1619
1620bool
1624 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1625 if (segment->getCarNumber() > 0) {
1626 return false;
1627 }
1628 }
1629 } else {
1630 for (MSLane* lane : getLanes()) {
1631 if (lane->getVehicleNumber() > 0) {
1632 return false;
1633 }
1634 }
1635 }
1636 return true;
1637}
1638
1639
1640double
1642 double wtime = 0;
1644 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1645 wtime += segment->getWaitingSeconds();
1646 }
1647 } else {
1648 for (MSLane* lane : getLanes()) {
1649 wtime += lane->getWaitingSeconds();
1650 }
1651 }
1652 return wtime;
1653}
1654
1655
1656double
1658 if (myLanes->size() == 0) {
1659 return 0;
1660 }
1663 double sum = 0;
1664 for (const SUMOVehicle* veh : getVehicles()) {
1665 sum += dynamic_cast<const MEVehicle*>(veh)->getVehicleType().getLength();
1666 }
1667 return sum / (myLength * (double)myLanes->size());
1668 } else {
1669 double sum = 0;
1670 for (auto lane : getLanes()) {
1671 sum += lane->getNettoOccupancy();
1672 }
1673 return sum / (double)myLanes->size();
1674 }
1675}
1676
1677
1678double
1680 if (myLanes->size() == 0) {
1681 return 0;
1682 }
1683 double flow = 0;
1684 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1685 flow += (double) segment->getCarNumber() * segment->getMeanSpeed();
1686 }
1687 return 3600 * flow / (*myLanes)[0]->getLength();
1688}
1689
1690
1691double
1693 if (myLanes->size() == 0) {
1694 return 0;
1695 }
1696 double occ = 0;
1697 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1698 occ += segment->getBruttoOccupancy();
1699 }
1700 return occ / (*myLanes)[0]->getLength() / (double)(myLanes->size());
1701}
1702
1703double
1704MSEdge::getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double /*time*/) {
1705 return edge->getLength() / MIN2(MSRoutingEngine::getAssumedSpeed(edge, veh), veh->getMaxSpeed());
1706}
1707
1708
1709void
1711 // @note must be called after closeBuilding() to ensure successors and
1712 // predecessors are set
1713 if (isInternal() && myEdgeType == "") {
1714 const std::string typeBefore = getNormalBefore()->getEdgeType();
1715 if (typeBefore != "") {
1716 const std::string typeAfter = getNormalSuccessor()->getEdgeType();
1717 if (typeBefore == typeAfter) {
1718 myEdgeType = typeBefore;
1719 } else if (typeAfter != "") {
1720 MSNet* net = MSNet::getInstance();
1721 auto resBefore = net->getRestrictions(typeBefore);
1722 auto resAfter = net->getRestrictions(typeAfter);
1723 if (resBefore != nullptr && resAfter != nullptr) {
1724 // create new restrictions for this type-combination
1725 myEdgeType = typeBefore + "|" + typeAfter;
1726 if (net->getRestrictions(myEdgeType) == nullptr) {
1727 for (const auto& item : *resBefore) {
1728 const SUMOVehicleClass svc = item.first;
1729 const double speed = item.second;
1730 const auto it = (*resAfter).find(svc);
1731 if (it != (*resAfter).end()) {
1732 const double speed2 = it->second;
1733 const double newSpeed = (MSNet::getInstance()->hasJunctionHigherSpeeds()
1734 ? MAX2(speed, speed2) : (speed + speed2) / 2);
1735 net->addRestriction(myEdgeType, svc, newSpeed);
1736 }
1737 }
1738 }
1739 }
1740 }
1741 }
1742 }
1743}
1744
1745
1746double
1747MSEdge::getDistanceAt(double pos) const {
1748 // negative values of myDistances indicate descending kilometrage
1749 return fabs(myDistance + pos);
1750}
1751
1752
1753bool
1757
1758
1759std::pair<double, SUMOTime>
1760MSEdge::getLastBlocked(int index) const {
1761 if (myLaneChanger != nullptr) {
1762 return myLaneChanger->getLastBlocked(index);
1763 }
1764 return std::make_pair(-1, -1);
1765}
1766
1767
1768double
1772
1773
1774void
1776 myPersons.clear();
1777 myContainers.clear();
1778 myWaiting.clear();
1779}
1780
1781
1782const std::map<const MEVehicle*, std::pair<double, int> >&
1784 assert(MSGlobals::gUseMesoSim);
1785 if (myLastCacheUpdate < SIMSTEP) {
1787 auto old = std::move(myCachedMesoPos);
1788 myCachedMesoPos.clear(); // moved-from map is valid-but-unspecified; make it defined-empty
1789 int laneIndex = 0;
1790 const double now = SIMTIME;
1791 for (std::vector<MSLane*>::const_iterator msl = myLanes->begin(); msl != myLanes->end(); ++msl, ++laneIndex) {
1792 // go through the vehicles
1793 double segmentOffset = 0; // offset at start of current segment
1794 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this);
1795 segment != nullptr; segment = segment->getNextSegment()) {
1796 const double segLength = segment->getLength();
1797 const double lanesCovered = segment->numQueues() == 1 ? std::round(segment->getCapacity() / segLength) : 1.;
1798 if (laneIndex < segment->numQueues()) {
1799 // make a copy so we don't have to worry about synchronization
1800 std::vector<MEVehicle*> queue = segment->getQueue(laneIndex);
1801 const int queueSize = (int)queue.size();
1802 SUMOTime earliestExitTime = segment->getQueueBlockTime(laneIndex);
1803 int overlap = 0;
1804 double prevPos = std::numeric_limits<double>::max();
1805 for (int i = 0; i < queueSize; ++i) {
1806 const MEVehicle* const veh = queue[queueSize - i - 1];
1807 earliestExitTime = MAX2(earliestExitTime, veh->getEventTime());
1808 const double vehLength = veh->getVehicleType().getLengthWithGap();
1809 double maxPos = segmentOffset + segLength;
1810 auto it = old.find(veh);
1811 const double oldPos = it != old.end() ? it->second.first : 0.; // store the old position to prevent backwards moving vehicles
1812 if (i > 0) {
1813 earliestExitTime += segment->getMinTauWithVehLength(vehLength, veh->getVehicleType().getCarFollowModel().getHeadwayTime());
1814 maxPos = MIN2(maxPos, prevPos - vehLength / lanesCovered);
1815 }
1816 const double entry = veh->getLastEntryTimeSeconds();
1817 assert(STEPS2TIME(earliestExitTime) > entry);
1818 const double pos = MAX2(MIN2(segmentOffset + segLength * (now - entry) / (STEPS2TIME(earliestExitTime) - entry), maxPos), oldPos);
1819 // check if we overlap with the previous vehicle such that the gui has the chance to add some lateral offset
1820 if (overlap == 0 && prevPos - pos < vehLength) {
1821 overlap = lanesCovered > 1. ? -3 : -1;
1822 } else {
1823 overlap = 0;
1824 }
1825 myCachedMesoPos[veh] = std::make_pair(pos, overlap);
1826 prevPos = pos;
1827 }
1828 }
1829 segmentOffset += segLength;
1830 }
1831 }
1832 }
1833 return myCachedMesoPos;
1834}
1835
1836
1837double
1839 double result = std::numeric_limits<double>::max();
1840 for (const MSLane* l : *myLanes) {
1841 result = MIN2(result, l->getLength());
1842 }
1843 return result;
1844}
1845
1846
1847/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define BEST_LANE_LOOKAHEAD
Definition MSEdge.cpp:54
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:75
std::vector< std::pair< const MSEdge *, const MSEdge * > > MSConstEdgePairVector
Definition MSEdge.h:76
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:107
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SIMSTEP
Definition SUMOTime.h:69
#define SIMTIME
Definition SUMOTime.h:70
const SVCPermissions SVCAll
all VClasses are allowed
const SUMOVehicleClass SUMOVehicleClass_MAX
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.
@ SVC_PRIVATE
private vehicles
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_WHEELCHAIR
@ SVC_PEDESTRIAN
pedestrian
DepartLaneDefinition
Possible ways to choose a lane on depart.
@ RANDOM
The lane is chosen randomly.
@ BEST_FREE
The least occupied lane from best lanes.
@ GIVEN
The lane is given.
@ ALLOWED_FREE
The least occupied lane from lanes which allow the continuation.
@ DEFAULT
No information given; use default.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
@ FREE
The least occupied lane is used.
@ BEST_PROB
The lane most likely according the speedFactor (from best lanes)
@ RANDOM
A random position is chosen.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ FREE
A free position is chosen.
@ BASE
Back-at-zero position.
@ LAST
Insert behind the last vehicle as close as possible to still allow the specified departSpeed....
@ RANDOM_FREE
If a fixed number of random choices fails, a free position is chosen.
@ GIVEN
The speed is given.
const long long int VEHPARS_SPEEDFACTOR_SET
@ SPLIT
The departure is triggered by a train split.
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ TURN
The link is a 180 degree turn.
@ STRAIGHT
The link is a straight direction.
SumoXMLEdgeFunc
Numbers representing special SUMO-XML-attribute values for representing edge functions used in netbui...
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
@ LINKSTATE_STOP
This is an uncontrolled, minor link, has to stop.
@ LINKSTATE_EQUAL
This is an uncontrolled, right-before-left link.
@ LINKSTATE_DEADEND
This is a dead end link.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:57
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
double distanceTo2D(const Position &p) const
returns the euclidean distance in the x-y-plane
Definition Boundary.cpp:262
double getParameter(const int index) const
Returns the nth parameter of this distribution.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:397
A single mesoscopic segment (cell)
Definition MESegment.h:50
bool initialise(MEVehicle *veh, SUMOTime time)
Inserts (emits) vehicle into the segment.
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.
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition MESegment.h:253
A vehicle from the mesoscopic point of view.
Definition MEVehicle.h:42
double getLastEntryTimeSeconds() const
Returns the entry time for the current segment.
Definition MEVehicle.h:340
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves its current segment.
Definition MEVehicle.h:218
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getLength() const
Returns the vehicle's length.
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
const MSRoute & getRoute() const
Returns the current route.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition MSCFModel.h:355
Sorts edges by their ids.
Definition MSEdge.h:906
Sorts transportables by their positions.
Definition MSEdge.h:921
int operator()(const MSTransportable *const c1, const MSTransportable *const c2) const
comparing operator
Definition MSEdge.cpp:1316
A road/street connecting two junctions.
Definition MSEdge.h:78
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1157
SUMOVehicle * getWaitingVehicle(MSTransportable *transportable, const double position) const
Definition MSEdge.cpp:1555
void addToAllowed(const SVCPermissions permissions, std::shared_ptr< const std::vector< MSLane * > > allowedLanes, AllowedLanesCont &laneCont) const
Definition MSEdge.cpp:302
void changeLanes(SUMOTime t) const
Performs lane changing on this edge.
Definition MSEdge.cpp:962
double getBruttoOccupancy() const
Definition MSEdge.cpp:1692
SVCPermissions myCombinedPermissions
The union of lane permissions for this edge.
Definition MSEdge.h:995
double getFlow() const
return flow based on meanSpeed
Definition MSEdge.cpp:1679
Boundary myBoundary
The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start ...
Definition MSEdge.h:1080
double myWidth
Edge width [m].
Definition MSEdge.h:1025
AllowedLanesByTarget myAllowedTargets
From target edge to lanes allowed to be used to reach it.
Definition MSEdge.h:989
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition MSEdge.h:275
MSLane * getDepartLane(MSVehicle &veh) const
Finds a depart lane for the given vehicle parameters.
Definition MSEdge.cpp:713
SUMOTime myLastFailedInsertionTime
The time of last insertion failure.
Definition MSEdge.h:953
std::set< MSTransportable *, ComparatorNumericalIdLess > myContainers
Containers on the edge.
Definition MSEdge.h:979
SUMOTime myLastCacheUpdate
time stamp of mesoscopic vehicle positions
Definition MSEdge.h:1089
void setMaxSpeed(const double val, const bool modified=true, const double jamThreshold=-1)
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition MSEdge.cpp:1261
std::pair< double, SUMOTime > getLastBlocked(int index) const
retrieve properties of a blocked vehicle that wants to chane to the lane with the given index
Definition MSEdge.cpp:1760
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1163
void inferEdgeType()
Definition MSEdge.cpp:1710
void setJunctions(MSJunction *from, MSJunction *to)
Definition MSEdge.cpp:1402
double getMeanSpeedBike() const
get the mean speed of all bicycles on this edge
Definition MSEdge.cpp:1081
static MSEdgeVector myEdges
Static list of edges.
Definition MSEdge.h:1063
AllowedLanesCont myAllowed
Associative container from vehicle class to allowed-lanes.
Definition MSEdge.h:985
double myEmptyTraveltime
the traveltime on the empty edge (cached value for speedup)
Definition MSEdge.h:1031
bool myAmFringe
whether this edge is at the network fringe
Definition MSEdge.h:1043
static double getTravelTimeAggregated(const MSEdge *const edge, const SUMOVehicle *const veh, double time)
Definition MSEdge.cpp:1704
MSJunction * myToJunction
Definition MSEdge.h:973
void checkAndRegisterBiDirEdge(const std::string &bidiID="")
check and register the opposite superposable edge if any
Definition MSEdge.cpp:1460
virtual ~MSEdge()
Destructor.
Definition MSEdge.cpp:98
double getDepartPosBound(const MSVehicle &veh, bool upper=true) const
return upper bound for the depart position on this edge
Definition MSEdge.cpp:653
const double myDistance
the kilometrage/mileage at the start of the edge
Definition MSEdge.h:1022
void clearState()
Remove all transportables before quick-loading state.
Definition MSEdge.cpp:1775
MSLane * getDepartLaneMeso(SUMOVehicle &veh) const
consider given departLane parameter (only for validating speeds)
Definition MSEdge.cpp:701
bool hasTransientPermissions() const
Definition MSEdge.cpp:1754
const MSEdge * myBidiEdge
the oppositing superposable edge
Definition MSEdge.h:1102
MSLane * leftLane(const MSLane *const lane) const
Returns the lane left to the one given, 0 if the given lane is leftmost.
Definition MSEdge.cpp:487
std::string myEdgeType
the type of the edge (optionally used during network creation)
Definition MSEdge.h:1013
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:169
int getNumDrivingLanes() const
return the number of lanes that permit non-weak modes if the edge allows non weak modes and the numbe...
Definition MSEdge.cpp:1597
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1423
static void parseEdgesList(const std::string &desc, ConstMSEdgeVector &into, const std::string &rid)
Parses the given string assuming it contains a list of edge ids divided by spaces.
Definition MSEdge.cpp:1183
double getLengthGeometryFactor() const
return shape.length() / myLength
Definition MSEdge.cpp:1249
void addSuccessor(MSEdge *edge, const MSEdge *via=nullptr)
Adds an edge to the list of edges which may be reached from this edge and to the incoming of the othe...
Definition MSEdge.cpp:1327
friend class MSLaneChangerSublane
Definition MSEdge.h:88
std::vector< SUMOVehicle * > myWaiting
List of waiting vehicles.
Definition MSEdge.h:1083
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:1017
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
double getInternalFollowingLengthTo(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
returns the length of all internal edges on the junction until reaching the non-internal edge followe...
Definition MSEdge.cpp:992
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:265
std::vector< MSTransportable * > getSortedPersons(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's persons sorted by pos.
Definition MSEdge.cpp:1290
void postLoadInitLaneChanger()
Definition MSEdge.cpp:253
MSEdge(const std::string &id, int numericalID, const SumoXMLEdgeFunc function, const std::string &streetName, const std::string &edgeType, const std::string &routingType, int priority, double distance)
Constructor.
Definition MSEdge.cpp:69
bool isSuperposable(const MSEdge *other)
Definition MSEdge.cpp:1515
bool validateDepartSpeed(SUMOVehicle &v) const
check whether the given departSpeed is valid for this edge
Definition MSEdge.cpp:802
double getDistanceTo(const MSEdge *other, const bool doBoundaryEstimate=false) const
optimistic air distance heuristic for use in routing
Definition MSEdge.cpp:1210
static MSEdge * dictionaryHint(const std::string &id, const int startIdx)
Returns the MSEdge associated to the key id giving a hint with a numerical id.
Definition MSEdge.cpp:1144
MSLaneChanger * myLaneChanger
This member will do the lane-change.
Definition MSEdge.h:944
double getOccupancy() const
return mean occupancy on this edges lanes or segments
Definition MSEdge.cpp:1657
static int myDefaultDepartLane
Definition MSEdge.h:1068
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition MSEdge.cpp:1372
std::vector< MSTransportable * > getSortedContainers(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's containers sorted by pos.
Definition MSEdge.cpp:1308
const SumoXMLEdgeFunc myFunction
the purpose of the edge
Definition MSEdge.h:947
MSLane * getProbableLane(const std::vector< MSLane * > *allowed, const SUMOVehicleClass vclass, double departPos, double maxSpeed) const
Finds the most probable lane allowing the vehicle class.
Definition MSEdge.cpp:615
void recalcCache()
Recalculates the cached values.
Definition MSEdge.cpp:123
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
SVCPermissions myOriginalCombinedPermissions
The original union of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:1000
bool myAmDelayed
whether this edge had a vehicle with less than max speed on it
Definition MSEdge.h:1037
SVCPermissions myOriginalMinimumPermissions
The original intersection of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:998
std::map< SUMOVehicleClass, MSEdgeVector > myClassesSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1073
SUMOTime decVaporization(SUMOTime t)
Disables vaporization.
Definition MSEdge.cpp:576
MSEdgeVector myPredecessors
The preceeding edges.
Definition MSEdge.h:969
bool hasChangeProhibitions(SUMOVehicleClass svc, int index) const
return whether this edge prohibits changing for the given vClass when starting on the given lane inde...
Definition MSEdge.cpp:1445
void rebuildAllowedTargets(const bool updateVehicles=true)
Definition MSEdge.cpp:419
static SVCPermissions myMesoIgnoredVClasses
Definition MSEdge.h:1065
std::vector< std::pair< SVCPermissions, std::shared_ptr< const std::vector< MSLane * > > > > AllowedLanesCont
"Map" from vehicle class to allowed lanes
Definition MSEdge.h:81
const MSJunction * getToJunction() const
Definition MSEdge.h:428
double getLength() const
return the length of the edge
Definition MSEdge.h:695
void initialize(const std::vector< MSLane * > *lanes)
Initialize the edge.
Definition MSEdge.cpp:106
bool myHaveTransientPermissions
whether transient permission changes were applied to this edge or a predecessor
Definition MSEdge.h:1003
virtual void closeBuilding()
Definition MSEdge.cpp:209
static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored=0)
Definition MSEdge.cpp:317
bool canChangeToOpposite() const
whether this edge allows changing to the opposite direction edge
Definition MSEdge.cpp:1413
std::set< int > myFailedInsertionMemory
A cache for the rejected insertion attempts. Used to assure that no further insertion attempts are ma...
Definition MSEdge.h:958
const MSJunction * getFromJunction() const
Definition MSEdge.h:424
double getMeanSpeed() const
get the mean speed
Definition MSEdge.cpp:1027
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition MSEdge.h:1057
std::set< MSTransportable *, ComparatorNumericalIdLess > myPersons
Persons on the edge for drawing and pushbutton.
Definition MSEdge.h:976
bool isTazConnector() const
Definition MSEdge.h:293
int getNumLanes() const
Definition MSEdge.h:173
double getDistanceAt(double pos) const
Returns the kilometrage/mileage at the given offset along the edge.
Definition MSEdge.cpp:1747
const std::string & getRoutingType() const
Returns the type of the edge.
Definition MSEdge.h:327
MSConstEdgePairVector myViaSuccessors
Definition MSEdge.h:966
std::map< const MEVehicle *, std::pair< double, int > > myCachedMesoPos
Mesoscopic vehicle positions.
Definition MSEdge.h:1086
void setBidiLanes()
Definition MSEdge.cpp:1490
MSEdgeVector mySuccessors
The succeeding edges.
Definition MSEdge.h:964
static DepartLaneDefinition myDefaultDepartLaneDefinition
Definition MSEdge.h:1067
static std::unordered_map< std::string_view, MSEdge * > myHashDict
Definition MSEdge.h:1058
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:270
MSLane * rightLane(const MSLane *const lane) const
Returns the lane right to the one given, 0 if the given lane is rightmost.
Definition MSEdge.cpp:493
double getMinLength() const
return the minimum length of all lanes (only differs from getLength for curved internal lanes)
Definition MSEdge.cpp:1838
double getCurrentTravelTime(const double minSpeed=NUMERICAL_EPS) const
Computes and returns the current travel time for this edge.
Definition MSEdge.cpp:1101
std::map< SUMOVehicleClass, MSConstEdgePairVector > myOrigClassesViaSuccessorMap
Definition MSEdge.h:1077
AllowedLanesByTarget myOrigAllowedTargets
Definition MSEdge.h:990
int getNumericalID() const
Returns the numerical id of the edge.
Definition MSEdge.h:308
void resetTAZ(MSJunction *junction)
Definition MSEdge.cpp:186
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:444
bool insertVehicle(SUMOVehicle &v, SUMOTime time, const bool checkOnly=false, const bool forceCheck=false) const
Tries to insert the given vehicle into the network.
Definition MSEdge.cpp:839
static const Position getStopPosition(const SUMOVehicleParameter::Stop &stop)
return the coordinates of the center of the given stop
Definition MSEdge.cpp:1229
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1534
MSLane * parallelLane(const MSLane *const lane, int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to the given lane one or 0 if it does not exist.
Definition MSEdge.cpp:499
ReversedEdge< MSEdge, SUMOVehicle > * myReversedRoutingEdge
a reversed version for backward routing
Definition MSEdge.h:1105
const std::string & getEdgeType() const
Returns the type of the edge.
Definition MSEdge.h:321
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1117
std::vector< const SUMOVehicle * > getVehicles() const
return vehicles on this edges lanes or segments
Definition MSEdge.cpp:1578
static void insertIDs(std::vector< std::string > &into)
Inserts IDs of all known edges into the given vector.
Definition MSEdge.cpp:1175
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1254
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition MSEdge.cpp:569
MSJunction * myFromJunction
the junctions for this edge
Definition MSEdge.h:972
double getMeanFriction() const
get the mean friction over the lanes
Definition MSEdge.cpp:1068
std::map< std::string, MSEdge * > DictType
definition of the static dictionary type
Definition MSEdge.h:1052
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1433
double getPreference(const SUMOVTypeParameter &pars) const
Definition MSEdge.cpp:1769
std::map< SUMOVehicleClass, MSConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1076
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:1007
int getVehicleNumber() const
return total number of vehicles on this edges lanes or segments
Definition MSEdge.cpp:1615
const std::map< const MEVehicle *, std::pair< double, int > > & getMesoPositions() const
Definition MSEdge.cpp:1783
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:419
virtual void removeTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1281
SumoXMLEdgeFunc getFunction() const
Returns the edge type (SumoXMLEdgeFunc)
Definition MSEdge.h:260
bool allowsLaneChanging() const
Definition MSEdge.cpp:280
bool isEmpty() const
whether this edge has no vehicles
Definition MSEdge.cpp:1621
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition MSEdge.cpp:970
void buildLaneChanger()
Has to be called after all successors and predecessors have been set (after closeBuilding())
Definition MSEdge.cpp:260
double getRoutingSpeed() const
Returns the averaged speed used by the routing device.
Definition MSEdge.cpp:1111
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition MSEdge.h:799
void removeWaiting(const SUMOVehicle *vehicle) const
Removes a vehicle from the list of waiting vehicles.
Definition MSEdge.cpp:1543
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false, int routingMode=0) const
Definition MSEdge.cpp:791
std::vector< double > mySublaneSides
the right side for each sublane on this edge
Definition MSEdge.h:1046
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1342
std::shared_ptr< const std::vector< MSLane * > > myLanes
Container for the edge's lane; should be sorted: (right-hand-traffic) the more left the lane,...
Definition MSEdge.h:941
AllowedLanesCont myOrigAllowed
Definition MSEdge.h:986
double getWaitingSeconds() const
return accumulated waiting time for all vehicles on this edges lanes or segments
Definition MSEdge.cpp:1641
int myVaporizationRequests
Vaporizer counter.
Definition MSEdge.h:950
double myTimePenalty
flat penalty when computing traveltime
Definition MSEdge.h:1034
SVCPermissions myMinimumPermissions
The intersection of lane permissions for this edge.
Definition MSEdge.h:993
MSLane * getFreeLane(const std::vector< MSLane * > *allowed, const SUMOVehicleClass vclass, double departPos) const
Finds the emptiest lane allowing the vehicle class.
Definition MSEdge.cpp:583
void rebuildAllowedLanes(const bool onInit=false, bool updateVehicles=false)
Definition MSEdge.cpp:324
virtual void addTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1272
RailEdge< MSEdge, SUMOVehicle > * myRailwayRoutingEdge
Definition MSEdge.h:1106
double myLength
the length of the edge (cached value for speedup)
Definition MSEdge.h:1028
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition MSGlobals.h:171
static bool gUseMesoSim
Definition MSGlobals.h:106
static double gMinorPenalty
(minimum) time penalty for passing a minor link when routing
Definition MSGlobals.h:158
static bool gCheckRoutes
Definition MSGlobals.h:91
static double gTLSPenalty
scaled (minimum) time penalty for passing a tls link when routing
Definition MSGlobals.h:160
static double gTurnaroundPenalty
(minimum) time penalty for passing a turnaround link when routing
Definition MSGlobals.h:162
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static double gLateralResolution
Definition MSGlobals.h:100
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:149
static SUMOTime gLaneChangeDuration
Definition MSGlobals.h:97
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
static int gNumThreads
how many threads to use
Definition MSGlobals.h:152
The base class for an intersection.
Definition MSJunction.h:58
const ConstMSEdgeVector & getOutgoing() const
Definition MSJunction.h:114
const Position & getPosition(bool secondaryShape=false) const
const ConstMSEdgeVector & getIncoming() const
Definition MSJunction.h:108
Performs lane changing of vehicles.
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
std::pair< double, SUMOTime > getLastBlocked(int index) const
retrieve properties of a blocked vehicle that wants to chane to the lane with the given index
Representation of a lane in the micro simulation.
Definition MSLane.h:84
bool insertVehicle(MSVehicle &v)
Tries to insert the given vehicle.
Definition MSLane.cpp:692
bool empty() const
Returns true if there is not a single vehicle on the lane.
Definition MSLane.h:765
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition MSLane.h:119
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition MSLane.h:575
int getIndex() const
Returns the lane's index.
Definition MSLane.h:668
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3451
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2538
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4465
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
double getWidth() const
Returns the lane's width.
Definition MSLane.h:661
int numSublanes() const
The simulated network and simulation perfomer.
Definition MSNet.h:89
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:201
double getPreference(const std::string &routingType, const SUMOVTypeParameter &pars) const
retriefe edge type specific routing preference
Definition MSNet.cpp:392
bool hasJunctionHigherSpeeds() const
return whether the network was built with higher junction speeds
Definition MSNet.h:816
const std::map< SUMOVehicleClass, double > * getRestrictions(const std::string &id) const
Returns the restrictions for an edge type If no restrictions are present, 0 is returned.
Definition MSNet.cpp:382
void addRestriction(const std::string &id, const SUMOVehicleClass svc, const double speed)
Adds a restriction for an edge type.
Definition MSNet.cpp:376
const MESegment::MesoEdgeType & getMesoType(const std::string &typeID)
Returns edge type specific meso parameters if no type specific parameters have been loaded,...
Definition MSNet.cpp:440
int size() const
Returns the number of edges to pass.
Definition MSRoute.cpp:85
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition MSRoute.cpp:73
static void invalidateCCHEdge(const MSEdge *e)
a runtime permission change (closure / re-opening) hit this edge: invalidate the graph's primed conne...
static double getAssumedSpeed(const MSEdge *edge, const SUMOVehicle *veh)
return current travel speed assumption
virtual double getEdgePos(SUMOTime now) const
Definition MSStage.cpp:83
MSStage * getCurrentStage() const
Return the current stage.
bool isPerson() const override
Whether it is a person.
bool isWaitingFor(const SUMOVehicle *vehicle) const
Whether the transportable waits for the given vehicle in the current step.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
The car-following model and parameter.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getDesiredMaxSpeed() const
Returns the vehicles's desired maximum speed.
const Distribution_Parameterized & getSpeedFactor() const
Returns this type's speed factor.
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
double getLength() const
Get vehicle's length [m].
double computeChosenSpeedDeviation(double speedFactorOverride, SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
Base class for objects which have an id.
Definition Named.h:53
const std::string & getID() const
Returns the id.
Definition Named.h:73
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
static const T & getRandomFrom(const std::vector< T > &v, SumoRNG *rng=nullptr)
Returns a random element from the given vector.
Definition RandHelper.h:225
Representation of a vehicle, person, or container.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getChosenSpeedFactor() const =0
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual double getMaxSpeed() const =0
Returns the object's maximum speed (minimum of technical and desired maximum speed)
Structure representing possible vehicle parameter.
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual int getRouteValidity(bool update=true, bool silent=false, std::string *msgReturn=nullptr)=0
computes validity attributes for the current route
virtual void setChosenSpeedFactor(const double factor)=0
Definition of vehicle stop (position and duration)
std::string lane
The lane to stop at.
double startPos
The stopping position start.
double endPos
The stopping position end.
Structure representing possible vehicle parameter.
int departLane
(optional) The lane the vehicle shall depart from (index in edge)
double departSpeed
(optional) The initial speed of the vehicle
double speedFactor
individual speedFactor (overriding distribution from vType)
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
std::string id
The vehicle's id.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
A scoped lock which only triggers on condition.
static void tokenizeAndLookup(std::string_view input, std::vector< T * > &result)
edge type specific meso parameters
Definition MESegment.h:58