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