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 }
380}
381
382
383void
384MSEdge::rebuildAllowedTargets(const bool updateVehicles) {
385 myAllowedTargets.clear();
386 for (const MSEdge* target : mySuccessors) {
387 bool universalMap = true; // whether the mapping for SVC_IGNORING is also valid for all vehicle classes
388 std::shared_ptr<std::vector<MSLane*> > allLanes = std::make_shared<std::vector<MSLane*> >();
389 // compute the mapping for SVC_IGNORING
390 for (MSLane* const lane : *myLanes) {
391 SVCPermissions combinedTargetPermissions = 0;
392 for (const MSLink* const link : lane->getLinkCont()) {
393 if (&link->getLane()->getEdge() == target) {
394 allLanes->push_back(lane);
395 combinedTargetPermissions |= link->getLane()->getPermissions();
396 if (link->getViaLane() != nullptr &&
397 ((lane->getPermissions() & link->getLane()->getPermissions()) != link->getViaLane()->getPermissions())) {
398 // custom connection permissions
399 universalMap = false;
400 }
401 }
402 }
403 if (combinedTargetPermissions == 0 || (lane->getPermissions() & combinedTargetPermissions) != lane->getPermissions()) {
404 universalMap = false;
405 }
406 }
407 if (universalMap) {
408 if (myAllowed.empty()) {
409 // we have no lane specific permissions
410 myAllowedTargets[target].push_back(std::make_pair(myMinimumPermissions, myLanes));
411 } else {
412 for (const auto& i : myAllowed) {
413 addToAllowed(i.first, i.second, myAllowedTargets[target]);
414 }
415 }
416 } else {
417 addToAllowed(SVC_IGNORING, allLanes, myAllowedTargets[target]);
418 // compute the vclass specific mapping
419 for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
420 if ((myCombinedPermissions & vclass) == vclass) {
421 std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
422 for (MSLane* const lane : *myLanes) {
423 if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
424 for (const MSLink* const link : lane->getLinkCont()) {
425 if (link->getLane()->allowsVehicleClass((SUMOVehicleClass)vclass) && &link->getLane()->getEdge() == target && (link->getViaLane() == nullptr || link->getViaLane()->allowsVehicleClass((SUMOVehicleClass)vclass))) {
426 allowedLanes->push_back(lane);
427 }
428 }
429 }
430 }
432 }
433 }
434 }
435 }
436 if (updateVehicles) {
437 for (const MSLane* const lane : *myLanes) {
438 const MSLane::VehCont& vehs = lane->getVehiclesSecure();
439 for (MSVehicle* veh : vehs) {
440 veh->updateBestLanes(true);
441 }
442 lane->releaseVehicles();
443 }
444 }
445 myClassesSuccessorMap.clear();
446}
447
448
449// ------------ Access to the edge's lanes
450MSLane*
451MSEdge::leftLane(const MSLane* const lane) const {
452 return parallelLane(lane, 1);
453}
454
455
456MSLane*
457MSEdge::rightLane(const MSLane* const lane) const {
458 return parallelLane(lane, -1);
459}
460
461
462MSLane*
463MSEdge::parallelLane(const MSLane* const lane, int offset, bool includeOpposite) const {
464 const int resultIndex = lane->getIndex() + offset;
465 if (resultIndex >= getNumLanes() && includeOpposite) {
466 const MSEdge* opposite = getOppositeEdge();
467 if (opposite != nullptr && resultIndex < getNumLanes() + opposite->getNumLanes()) {
468 return opposite->getLanes()[opposite->getNumLanes() + getNumLanes() - resultIndex - 1];
469 }
470 return nullptr;
471 } else if (resultIndex >= (int)myLanes->size() || resultIndex < 0) {
472 return nullptr;
473 } else {
474 return (*myLanes)[resultIndex];
475 }
476}
477
478
479const std::vector<MSLane*>*
480MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
481 const auto& targets = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowedTargets : myAllowedTargets;
482 AllowedLanesByTarget::const_iterator i = targets.find(&destination);
483 if (i != targets.end()) {
484 for (const auto& allowed : i->second) {
485 if ((allowed.first & vclass) == vclass) {
486 return allowed.second.get();
487 }
488 }
489 }
490 return nullptr;
491}
492
493
494const std::vector<MSLane*>*
496 if ((myMinimumPermissions & vclass) == vclass) {
497 return myLanes.get();
498 } else {
499 if ((myCombinedPermissions & vclass) == vclass) {
500 for (const auto& allowed : myAllowed) {
501 if ((allowed.first & vclass) == vclass) {
502 return allowed.second.get();
503 }
504 }
505 }
506 return nullptr;
507 }
508}
509
510
511const std::vector<MSLane*>*
512MSEdge::allowedLanes(SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
513 const SVCPermissions& minP = ignoreTransientPermissions ? myOriginalMinimumPermissions : myMinimumPermissions;
514 if ((minP & vclass) == vclass) {
515 return myLanes.get();
516 } else {
517 const SVCPermissions comP = ignoreTransientPermissions ? myOriginalCombinedPermissions : myCombinedPermissions;
518 if ((comP & vclass) == vclass) {
519 const AllowedLanesCont& allowedCont = ignoreTransientPermissions ? myOrigAllowed : myAllowed;
520 for (const auto& allowed : allowedCont) {
521 if ((allowed.first & vclass) == vclass) {
522 return allowed.second.get();
523 }
524 }
525 }
526 return nullptr;
527 }
528}
529
530
531// ------------
537
538
544
545
546MSLane*
547MSEdge::getFreeLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos) const {
548 if (allowed == nullptr) {
549 allowed = allowedLanes(vclass);
550 }
551 MSLane* res = nullptr;
552 if (allowed != nullptr) {
553 double largestGap = 0;
554 MSLane* resByGap = nullptr;
555 double leastOccupancy = std::numeric_limits<double>::max();
556 for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i) {
557 const double occupancy = (*i)->getBruttoOccupancy();
558 if (occupancy < leastOccupancy) {
559 res = (*i);
560 leastOccupancy = occupancy;
561 }
562 const MSVehicle* last = (*i)->getLastFullVehicle();
563 const double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
564 if (lastGap > largestGap) {
565 largestGap = lastGap;
566 resByGap = (*i);
567 }
568 }
569 if (resByGap != nullptr) {
570 //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
571 res = resByGap;
572 }
573 }
574 return res;
575}
576
577
578MSLane*
579MSEdge::getProbableLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos, double maxSpeed) const {
580 if (allowed == nullptr) {
581 allowed = allowedLanes(vclass);
582 }
583 MSLane* res = nullptr;
584 if (allowed != nullptr) {
585 double largestGap = 0;
586 double largestSpeed = 0;
587 MSLane* resByGap = nullptr;
588 double leastOccupancy = std::numeric_limits<double>::max();
589 int aIndex = 0;
590 for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i, aIndex++) {
591 const double occupancy = (*i)->getBruttoOccupancy();
592 if (occupancy < leastOccupancy) {
593 res = (*i);
594 leastOccupancy = occupancy;
595 }
596 const MSVehicle* last = (*i)->getLastFullVehicle();
597 double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
598 // never insert to the left of a vehicle with a larger speedFactor
599 if (lastGap > largestGap && maxSpeed >= largestSpeed) {
600 largestGap = lastGap;
601 resByGap = (*i);
602 }
603 if (last != nullptr) {
604 largestSpeed = MAX2(largestSpeed, getVehicleMaxSpeed(last));
605 }
606 }
607 if (resByGap != nullptr) {
608 //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
609 res = resByGap;
610 }
611 }
612 return res;
613}
614
615
616double
617MSEdge::getDepartPosBound(const MSVehicle& veh, bool upper) const {
618 const SUMOVehicleParameter& pars = veh.getParameter();
619 double pos = getLength();
620 // determine the position
621 switch (pars.departPosProcedure) {
623 pos = pars.departPos;
624 if (pos < 0.) {
625 pos += myLength;
626 }
627 break;
629 // could be any position on the edge
630 break;
632 // could be any position on the edge due to multiple random attempts
633 break;
635 // many candidate positions, upper bound could be computed exactly
636 // with much effort
637 break;
639 if (upper) {
640 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
641 MSVehicle* last = (*i)->getLastFullVehicle();
642 if (last != nullptr) {
643 pos = MIN2(pos, last->getPositionOnLane());
644 }
645 }
646 } else {
647 pos = 0;
648 }
649 break;
652 if (!upper) {
653 pos = 0;
654 }
655 break;
656 default:
657 pos = MIN2(pos, veh.getVehicleType().getLength());
658 break;
659 }
660 return pos;
661}
662
663MSLane*
666 if ((int) myLanes->size() <= veh.getParameter().departLane || !(*myLanes)[veh.getParameter().departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
667 return nullptr;
668 }
669 return (*myLanes)[veh.getParameter().departLane];
670 }
671 return (*myLanes)[0];
672}
673
674MSLane*
677 int departLane = veh.getParameter().departLane;
680 departLane = myDefaultDepartLane;
681 }
682 switch (dld) {
684 if ((int) myLanes->size() <= departLane || !(*myLanes)[departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
685 return nullptr;
686 }
687 return (*myLanes)[departLane];
691 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
693 if (veh.getRoute().size() == 1) {
694 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
695 } else {
697 }
700 veh.updateBestLanes(false, myLanes->front());
701 const std::vector<MSVehicle::LaneQ>& bl = veh.getBestLanes();
702 double bestLength = -1;
703 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
704 if ((*i).length > bestLength) {
705 bestLength = (*i).length;
706 }
707 }
708 // beyond a certain length, all lanes are suitable
709 // however, we still need to check departPos to avoid unsuitable insertion
710 // (this is only possible in some cases)
711 double departPos = 0;
712 if (bestLength > BEST_LANE_LOOKAHEAD) {
713 departPos = getDepartPosBound(veh);
714 bestLength = MIN2(bestLength - departPos, BEST_LANE_LOOKAHEAD);
715 }
716 std::vector<MSLane*>* bestLanes = new std::vector<MSLane*>();
717 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
718 if (((*i).length - departPos) >= bestLength) {
719 if (isInternal()) {
720 for (MSLane* lane : *myLanes) {
721 if (lane->getNormalSuccessorLane() == (*i).lane) {
722 bestLanes->push_back(lane);
723 }
724 }
725 } else {
726 bestLanes->push_back((*i).lane);
727 }
728 }
729 }
730 MSLane* ret = nullptr;
732 ret = getFreeLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
733 } else {
734 ret = getProbableLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false), getVehicleMaxSpeed(&veh));
735 }
736 delete bestLanes;
737 return ret;
738 }
742 default:
743 break;
744 }
745 if (!(*myLanes)[0]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
746 return nullptr;
747 }
748 return (*myLanes)[0];
749}
750
751
752MSLane*
753MSEdge::getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst, int routingMode) const {
754 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
755 if ((*i)->allowsVehicleClass(vClass, routingMode)) {
756 return *i;
757 }
758 }
759 return defaultFirst && !myLanes->empty() ? myLanes->front() : nullptr;
760}
761
762
763bool
765 const SUMOVehicleParameter& pars = v.getParameter();
766 const MSVehicleType& type = v.getVehicleType();
768 // departSpeed could have been rounded down in the output
769 double vMax = getVehicleMaxSpeed(&v) + SPEED_EPS;
770 if (pars.departSpeed > vMax) {
771 // check departLane (getVehicleMaxSpeed checks lane 0)
772 MSLane* departLane = MSGlobals::gMesoNet ? getDepartLaneMeso(v) : getDepartLane(dynamic_cast<MSVehicle&>(v));
773 if (departLane != nullptr) {
774 vMax = departLane->getVehicleMaxSpeed(&v);
776 // speedFactor could have been rounded down in the output
777 vMax *= (1 + SPEED_EPS);
778 }
779 // additive term must come after multiplication!
780 vMax += SPEED_EPS;
781 if (pars.departSpeed > vMax) {
782 if (type.getSpeedFactor().getParameter(1) > 0.) {
784 if (v.getChosenSpeedFactor() > type.getSpeedFactor().getParameter(0) + 2 * type.getSpeedFactor().getParameter(1)) {
785 // only warn for significant deviation
786 WRITE_WARNINGF(TL("Choosing new speed factor % for vehicle '%' to match departure speed % (max %)."),
787 toString(v.getChosenSpeedFactor()), pars.id, pars.departSpeed, vMax);
788 }
789 } else {
790 return false;
791 }
792 }
793 }
794 }
795 }
796 return true;
797}
798
799
800bool
801MSEdge::insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly, const bool forceCheck) const {
802 // when vaporizing, no vehicles are inserted, but checking needs to be successful to trigger removal
804 || v.getRouteValidity(true, checkOnly) != MSBaseVehicle::ROUTE_VALID) {
805 return checkOnly;
806 }
807 const SUMOVehicleParameter& pars = v.getParameter();
808 if (!validateDepartSpeed(v)) {
810 throw ProcessError(TLF("Departure speed for vehicle '%' is too high for the departure edge '%', time=%.",
811 pars.id, getID(), time2string(time)));
812 } else {
813 WRITE_WARNINGF(TL("Departure speed for vehicle '%' is too high for the departure edge '%', time=%."),
814 pars.id, getID(), time2string(time));
815 }
816 }
818 if (!forceCheck && myLastFailedInsertionTime == time) {
819 return false;
820 }
821 double pos = 0.0;
822 switch (pars.departPosProcedure) {
824 if (pars.departPos >= 0.) {
825 pos = pars.departPos;
826 } else {
827 pos = pars.departPos + getLength();
828 }
829 if (pos < 0 || pos > getLength()) {
830 WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
831 pos, v.getID(), time2string(time));
832 pos = getLength();
833 }
834 break;
838 break;
839 default:
840 break;
841 }
842 bool result = false;
843 MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this, pos);
844 MEVehicle* veh = static_cast<MEVehicle*>(&v);
845 int qIdx;
847 while (segment != nullptr && !result) {
848 if (checkOnly) {
849 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
850 } else {
851 result = segment->initialise(veh, time);
852 }
853 segment = segment->getNextSegment();
854 }
855 } else {
856 if (checkOnly) {
857 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
858 } else {
859 result = segment->initialise(veh, time);
860 }
861 }
862 return result;
863 }
864 if (checkOnly) {
865 switch (v.getParameter().departLaneProcedure) {
869 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
870 if (insertionLane == nullptr) {
871 WRITE_WARNINGF(TL("Could not insert vehicle '%' on any lane of edge '%', time=%."),
872 v.getID(), getID(), time2string(time));
873 return false;
874 }
875 const double occupancy = insertionLane->getBruttoOccupancy();
876 return (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
878 }
879 default:
880 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
881 const double occupancy = (*i)->getBruttoOccupancy();
882 if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
884 return true;
885 }
886 }
887 }
888 return false;
889 }
890 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
891 if (insertionLane == nullptr) {
892 return false;
893 }
894
895 if (!forceCheck) {
896 if (myLastFailedInsertionTime == time) {
897 if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
898 // A vehicle was already rejected for the proposed insertionLane in this timestep
899 return false;
900 }
901 } else {
902 // last rejection occurred in a previous timestep, clear cache
904 }
905 }
906
907 bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
908
909 if (!success) {
910 // constraints may enforce explicit re-ordering so we need to try other vehicles after failure
911 if (!insertionLane->hasParameter("insertionOrder" + v.getID())) {
912 myFailedInsertionMemory.insert(insertionLane->getIndex());
913 }
914 }
915 return success;
916}
917
918
919void
921 if (myLaneChanger != nullptr) {
923 }
924}
925
926
927const MSEdge*
928MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
929 //@todo to be optimized
930 for (const MSLane* const l : *myLanes) {
931 for (const MSLink* const link : l->getLinkCont()) {
932 if (&link->getLane()->getEdge() == followerAfterInternal) {
933 if (link->getViaLane() != nullptr) {
934 if (link->getViaLane()->allowsVehicleClass(vClass)) {
935 return &link->getViaLane()->getEdge();
936 } else {
937 continue;
938 }
939 } else {
940 return nullptr; // network without internal links
941 }
942 }
943 }
944 }
945 return nullptr;
946}
947
948
949double
950MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
951 assert(followerAfterInternal != 0);
952 assert(!followerAfterInternal->isInternal());
953 double dist = 0.;
954 const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal, vClass);
955 // Take into account non-internal lengths until next non-internal edge
956 while (edge != nullptr && edge->isInternal()) {
957 dist += edge->getLength();
958 edge = edge->getInternalFollowingEdge(followerAfterInternal, vClass);
959 }
960 return dist;
961}
962
963
964const MSEdge*
966 const MSEdge* result = this;
967 while (result->isInternal() && MSGlobals::gUsingInternalLanes) {
968 assert(result->getPredecessors().size() == 1);
969 result = result->getPredecessors().front();
970 }
971 return result;
972}
973
974const MSEdge*
976 const MSEdge* result = this;
977 while (result->isInternal()) {
978 assert(result->getSuccessors().size() == 1);
979 result = result->getSuccessors().front();
980 }
981 return result;
982}
983
984double
986 double v = 0;
987 double totalNumVehs = 0;
989 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
990 const int numVehs = segment->getCarNumber();
991 if (numVehs > 0) {
992 v += numVehs * segment->getMeanSpeed();
993 totalNumVehs += numVehs;
994 }
995 }
996 if (totalNumVehs == 0) {
997 return getLength() / myEmptyTraveltime; // may include tls-penalty
998 }
999 } else {
1000 for (const MSLane* const lane : *myLanes) {
1001 int numVehs = lane->getVehicleNumber();
1002 if (numVehs == 0) {
1003 // take speed limit but with lowest possible weight
1004 numVehs = 1;
1005 }
1006 v += numVehs * lane->getMeanSpeed();
1007 totalNumVehs += numVehs;
1008 }
1009 if (myBidiEdge != nullptr) {
1010 for (const MSLane* const lane : myBidiEdge->getLanes()) {
1011 if (lane->getVehicleNumber() > 0) {
1012 // do not route across edges which are already occupied in reverse direction
1013 return 0;
1014 }
1015 }
1016 }
1017 if (totalNumVehs == 0) {
1018 return getSpeedLimit();
1019 }
1020 }
1021 return v / totalNumVehs;
1022}
1023
1024
1025double
1027 double f = 0.;
1028 for (const MSLane* const lane : *myLanes) {
1029 f += lane->getFrictionCoefficient();
1030 }
1031 if (!myLanes->empty()) {
1032 return f / (double)myLanes->size();
1033 }
1034 return 1.;
1035}
1036
1037
1038double
1041 // no separate bicycle speeds in meso
1042 return getMeanSpeed();
1043 }
1044 double v = 0;
1045 double totalNumVehs = 0;
1046 for (const MSLane* const lane : *myLanes) {
1047 const int numVehs = lane->getVehicleNumber();
1048 v += numVehs * lane->getMeanSpeedBike();
1049 totalNumVehs += numVehs;
1050 }
1051 if (totalNumVehs == 0) {
1052 return getSpeedLimit();
1053 }
1054 return v / totalNumVehs;
1055}
1056
1057
1058double
1059MSEdge::getCurrentTravelTime(double minSpeed) const {
1060 assert(minSpeed > 0);
1061 if (!myAmDelayed) {
1062 return myEmptyTraveltime;
1063 }
1064 return getLength() / MAX2(minSpeed, getMeanSpeed());
1065}
1066
1067
1068double
1070 return MSRoutingEngine::getAssumedSpeed(this, nullptr);
1071}
1072
1073
1074bool
1075MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
1076 const DictType::iterator it = myDict.lower_bound(id);
1077 if (it == myDict.end() || it->first != id) {
1078 // id not in myDict
1079 myDict.emplace_hint(it, id, ptr);
1080 while (ptr->getNumericalID() >= (int)myEdges.size()) {
1081 myEdges.push_back(nullptr);
1082 }
1083 myEdges[ptr->getNumericalID()] = ptr;
1084 return true;
1085 }
1086 return false;
1087}
1088
1089
1090MSEdge*
1091MSEdge::dictionary(const std::string& id) {
1092 const DictType::iterator it = myDict.find(id);
1093 if (it == myDict.end()) {
1094 return nullptr;
1095 }
1096 return it->second;
1097}
1098
1099
1100MSEdge*
1101MSEdge::dictionaryHint(const std::string& id, const int startIdx) {
1102 // this method is mainly useful when parsing connections from the net.xml which are sorted by "from" id
1103 if (myEdges[startIdx] != nullptr && myEdges[startIdx]->getID() == id) {
1104 return myEdges[startIdx];
1105 }
1106 if (startIdx + 1 < (int)myEdges.size() && myEdges[startIdx + 1] != nullptr && myEdges[startIdx + 1]->getID() == id) {
1107 return myEdges[startIdx + 1];
1108 }
1109 return dictionary(id);
1110}
1111
1112
1113const MSEdgeVector&
1115 return myEdges;
1116}
1117
1118
1119void
1121 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1122 delete (*i).second;
1123 }
1124 myDict.clear();
1125 myEdges.clear();
1126}
1127
1128
1129void
1130MSEdge::insertIDs(std::vector<std::string>& into) {
1131 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1132 into.push_back((*i).first);
1133 }
1134}
1135
1136
1137void
1138MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
1139 const std::string& rid) {
1140 StringTokenizer st(desc);
1141 parseEdgesList(st.getVector(), into, rid);
1142}
1143
1144
1145void
1146MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
1147 const std::string& rid) {
1148 for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1149 const MSEdge* edge = MSEdge::dictionary(*i);
1150 // check whether the edge exists
1151 if (edge == nullptr) {
1152 throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
1153 + "\n The route can not be build.");
1154 }
1155 into.push_back(edge);
1156 }
1157}
1158
1159
1160double
1161MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
1162 assert(this != other);
1163 if (doBoundaryEstimate) {
1164 return myBoundary.distanceTo2D(other->myBoundary);
1165 }
1166 if (isTazConnector()) {
1167 if (other->isTazConnector()) {
1168 return myBoundary.distanceTo2D(other->myBoundary);
1169 }
1170 return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
1171 }
1172 if (other->isTazConnector()) {
1173 return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
1174 }
1175 return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
1176}
1177
1178
1179const Position
1181 return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
1182}
1183
1184
1185double
1187 // @note lanes might have different maximum speeds in theory
1188 return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
1189}
1190
1191
1192double
1194 return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
1195}
1196
1197double
1199 // @note lanes might have different maximum speeds in theory
1200 return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
1201}
1202
1203
1204void
1205MSEdge::setMaxSpeed(double val, double jamThreshold) {
1206 assert(val >= 0);
1207 if (myLanes != nullptr) {
1208 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1209 (*i)->setMaxSpeed(val, false, false, jamThreshold);
1210 }
1211 }
1212}
1213
1214
1215void
1217 if (t->isPerson()) {
1218 myPersons.insert(t);
1219 } else {
1220 myContainers.insert(t);
1221 }
1222}
1223
1224void
1226 std::set<MSTransportable*, ComparatorNumericalIdLess>& tc = t->isPerson() ? myPersons : myContainers;
1227 auto it = tc.find(t);
1228 if (it != tc.end()) {
1229 tc.erase(it);
1230 }
1231}
1232
1233std::vector<MSTransportable*>
1234MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
1235 std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
1236 if (includeRiding) {
1237 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1238 const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
1239 for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
1240 const std::vector<MSTransportable*>& persons = (*j)->getPersons();
1241 result.insert(result.end(), persons.begin(), persons.end());
1242 }
1243 (*i)->releaseVehicles();
1244 }
1245 }
1246 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1247 return result;
1248}
1249
1250
1251std::vector<MSTransportable*>
1252MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
1253 std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
1254 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1255 return result;
1256}
1257
1258
1259int
1261 const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
1262 const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
1263 if (pos1 != pos2) {
1264 return pos1 < pos2;
1265 }
1266 return c1->getID() < c2->getID();
1267}
1268
1269
1270void
1272 mySuccessors.push_back(edge);
1273 myViaSuccessors.push_back(std::make_pair(edge, via));
1274 if (isTazConnector() && edge->getFromJunction() != nullptr) {
1276 }
1277
1278 edge->myPredecessors.push_back(this);
1279 if (edge->isTazConnector() && getToJunction() != nullptr) {
1280 edge->myBoundary.add(getToJunction()->getPosition());
1281 }
1282}
1283
1284
1285const MSEdgeVector&
1287 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1288 return mySuccessors;
1289 }
1290#ifdef HAVE_FOX
1291 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1292#endif
1293 std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1294 if (i == myClassesSuccessorMap.end()) {
1295 // instantiate vector
1296 myClassesSuccessorMap[vClass];
1297 i = myClassesSuccessorMap.find(vClass);
1298 // this vClass is requested for the first time. rebuild all successors
1299 for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1300 if ((*it)->isTazConnector()) {
1301 i->second.push_back(*it);
1302 } else {
1303 const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1304 if (allowed != nullptr && allowed->size() > 0) {
1305 i->second.push_back(*it);
1306 }
1307 }
1308 }
1309 }
1310 // can use cached value
1311 return i->second;
1312}
1313
1314
1316MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
1317 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1318 return myViaSuccessors;
1319 }
1320#ifdef HAVE_FOX
1321 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1322#endif
1323 auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
1324 auto i = viaMap.find(vClass);
1325 if (i != viaMap.end()) {
1326 // can use cached value
1327 return i->second;
1328 }
1329 // instantiate vector
1330 MSConstEdgePairVector& result = viaMap[vClass];
1331 // this vClass is requested for the first time. rebuild all successors
1332 for (const auto& viaPair : myViaSuccessors) {
1333 if (viaPair.first->isTazConnector()) {
1334 result.push_back(viaPair);
1335 } else {
1336 const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
1337 if (allowed != nullptr && allowed->size() > 0) {
1338 result.push_back(viaPair);
1339 }
1340 }
1341 }
1342 return result;
1343}
1344
1345
1346void
1348 myFromJunction = from;
1349 myToJunction = to;
1350 if (!isTazConnector()) {
1351 myBoundary.add(from->getPosition());
1352 myBoundary.add(to->getPosition());
1353 }
1354}
1355
1356
1357bool
1359 return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1360 // do not change on curved internal lanes
1361 (!isInternal()
1363 && myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LinkDirection::STRAIGHT)));
1364}
1365
1366
1367const MSEdge*
1369 if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1370 return &(myLanes->back()->getOpposite()->getEdge());
1371 } else {
1372 return nullptr;
1373 }
1374}
1375
1376
1377bool
1379 for (const MSLane* const l : *myLanes) {
1380 for (const MSLink* const link : l->getLinkCont()) {
1381 if (!link->havePriority()) {
1382 return true;
1383 }
1384 }
1385 }
1386 return false;
1387}
1388
1389bool
1391 if (myLanes->size() == 1) {
1392 return false;
1393 }
1394 for (const MSLane* const l : *myLanes) {
1395 if (l->getIndex() <= index && !l->allowsChangingRight(svc) && l->getIndex() > 0) {
1396 return true;
1397 } else if (l->getIndex() >= index && !l->allowsChangingLeft(svc) && l->getIndex() < (int)(myLanes->size() - 1)) {
1398 return true;
1399 }
1400 }
1401 return false;
1402}
1403
1404void
1405MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1406 if (bidiID != "") {
1407 myBidiEdge = dictionary(bidiID);
1408 if (myBidiEdge == nullptr) {
1409 WRITE_ERRORF(TL("Bidi-edge '%' does not exist"), bidiID);
1410 }
1411 setBidiLanes();
1412 return;
1413 }
1415 return;
1416 }
1417 // legacy networks (no bidi attribute)
1419 for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1420 if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1421 if (myBidiEdge != nullptr && isSuperposable(*it)) {
1422 WRITE_WARNINGF(TL("Ambiguous superposable edges between junction '%' and '%'."), myToJunction->getID(), myFromJunction->getID());
1423 break;
1424 }
1425 if (isSuperposable(*it)) {
1426 myBidiEdge = *it;
1427 setBidiLanes();
1428 }
1429 }
1430 }
1431}
1432
1433
1434void
1436 assert(myBidiEdge != nullptr);
1437 if (getNumLanes() == 1 && myBidiEdge->getNumLanes() == 1) {
1438 // the other way round is set when this method runs for the bidiEdge
1439 getLanes()[0]->setBidiLane(myBidiEdge->getLanes()[0]);
1440 } else {
1441 // find lanes with matching reversed shapes
1442 int numBidiLanes = 0;
1443 for (MSLane* l1 : *myLanes) {
1444 for (MSLane* l2 : *myBidiEdge->myLanes) {
1445 if (l1->getShape().reverse().almostSame(l2->getShape(), POSITION_EPS * 2)) {
1446 l1->setBidiLane(l2);
1447 numBidiLanes++;
1448 }
1449 }
1450 }
1451 // warn only once for each pair
1452 if (numBidiLanes == 0 && getNumericalID() < myBidiEdge->getNumericalID()) {
1453 WRITE_WARNINGF(TL("Edge '%' and bidi edge '%' have no matching bidi lanes"), getID(), myBidiEdge->getID());
1454 }
1455 }
1456}
1457
1458
1459bool
1461 if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1462 return false;
1463 }
1464 std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1465 std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1466 do {
1467 if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1468 return false;
1469 }
1470 it1++;
1471 it2++;
1472 } while (it1 != myLanes->end());
1473
1474 return true;
1475}
1476
1477
1478void
1480#ifdef HAVE_FOX
1481 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1482#endif
1483 myWaiting.push_back(vehicle);
1484}
1485
1486
1487void
1488MSEdge::removeWaiting(const SUMOVehicle* vehicle) const {
1489#ifdef HAVE_FOX
1490 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1491#endif
1492 std::vector<SUMOVehicle*>::iterator it = std::find(myWaiting.begin(), myWaiting.end(), vehicle);
1493 if (it != myWaiting.end()) {
1494 myWaiting.erase(it);
1495 }
1496}
1497
1498
1500MSEdge::getWaitingVehicle(MSTransportable* transportable, const double position) const {
1501#ifdef HAVE_FOX
1502 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1503#endif
1504 for (SUMOVehicle* const vehicle : myWaiting) {
1505 if (transportable->isWaitingFor(vehicle)) {
1506 if (vehicle->isStoppedInRange(position, MSGlobals::gStopTolerance) ||
1507 (!vehicle->hasDeparted() &&
1508 (vehicle->getParameter().departProcedure == DepartDefinition::TRIGGERED ||
1509 vehicle->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED))) {
1510 return vehicle;
1511 }
1512 if (!vehicle->isLineStop(position) && vehicle->allowsBoarding(transportable)) {
1513 WRITE_WARNING((transportable->isPerson() ? "Person '" : "Container '")
1514 + transportable->getID() + "' at edge '" + getID() + "' position " + toString(position) + " cannot use waiting vehicle '"
1515 + vehicle->getID() + "' at position " + toString(vehicle->getPositionOnLane()) + " because it is too far away.");
1516 }
1517 }
1518 }
1519 return nullptr;
1520}
1521
1522std::vector<const SUMOVehicle*>
1524 std::vector<const SUMOVehicle*> result;
1526 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1527 std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
1528 result.insert(result.end(), segmentVehs.begin(), segmentVehs.end());
1529 }
1530 } else {
1531 for (MSLane* lane : getLanes()) {
1532 for (auto veh : lane->getVehiclesSecure()) {
1533 result.push_back(veh);
1534 }
1535 lane->releaseVehicles();
1536 }
1537 }
1538 return result;
1539}
1540
1541int
1543 int result = 0;
1544 SVCPermissions filter = SVCAll;
1546 filter = ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1547 } else if ((myCombinedPermissions & (SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1548 // filter out green verge
1549 filter = (SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1550 }
1551 for (const MSLane* const l : *myLanes) {
1552 if ((l->getPermissions() & filter) != 0) {
1553 result++;
1554 }
1555 }
1556 return result;
1557}
1558
1559int
1561 return (int)getVehicles().size();
1562}
1563
1564
1565bool
1569 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1570 if (segment->getCarNumber() > 0) {
1571 return false;
1572 }
1573 }
1574 } else {
1575 for (MSLane* lane : getLanes()) {
1576 if (lane->getVehicleNumber() > 0) {
1577 return false;
1578 }
1579 }
1580 }
1581 return true;
1582}
1583
1584
1585double
1587 double wtime = 0;
1589 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1590 wtime += segment->getWaitingSeconds();
1591 }
1592 } else {
1593 for (MSLane* lane : getLanes()) {
1594 wtime += lane->getWaitingSeconds();
1595 }
1596 }
1597 return wtime;
1598}
1599
1600
1601double
1603 if (myLanes->size() == 0) {
1604 return 0;
1605 }
1608 double sum = 0;
1609 for (const SUMOVehicle* veh : getVehicles()) {
1610 sum += dynamic_cast<const MEVehicle*>(veh)->getVehicleType().getLength();
1611 }
1612 return sum / (myLength * (double)myLanes->size());
1613 } else {
1614 double sum = 0;
1615 for (auto lane : getLanes()) {
1616 sum += lane->getNettoOccupancy();
1617 }
1618 return sum / (double)myLanes->size();
1619 }
1620}
1621
1622
1623double
1625 if (myLanes->size() == 0) {
1626 return 0;
1627 }
1628 double flow = 0;
1629 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1630 flow += (double) segment->getCarNumber() * segment->getMeanSpeed();
1631 }
1632 return 3600 * flow / (*myLanes)[0]->getLength();
1633}
1634
1635
1636double
1638 if (myLanes->size() == 0) {
1639 return 0;
1640 }
1641 double occ = 0;
1642 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1643 occ += segment->getBruttoOccupancy();
1644 }
1645 return occ / (*myLanes)[0]->getLength() / (double)(myLanes->size());
1646}
1647
1648double
1649MSEdge::getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double /*time*/) {
1650 return edge->getLength() / MIN2(MSRoutingEngine::getAssumedSpeed(edge, veh), veh->getMaxSpeed());
1651}
1652
1653
1654void
1656 // @note must be called after closeBuilding() to ensure successors and
1657 // predecessors are set
1658 if (isInternal() && myEdgeType == "") {
1659 const std::string typeBefore = getNormalBefore()->getEdgeType();
1660 if (typeBefore != "") {
1661 const std::string typeAfter = getNormalSuccessor()->getEdgeType();
1662 if (typeBefore == typeAfter) {
1663 myEdgeType = typeBefore;
1664 } else if (typeAfter != "") {
1665 MSNet* net = MSNet::getInstance();
1666 auto resBefore = net->getRestrictions(typeBefore);
1667 auto resAfter = net->getRestrictions(typeAfter);
1668 if (resBefore != nullptr && resAfter != nullptr) {
1669 // create new restrictions for this type-combination
1670 myEdgeType = typeBefore + "|" + typeAfter;
1671 if (net->getRestrictions(myEdgeType) == nullptr) {
1672 for (const auto& item : *resBefore) {
1673 const SUMOVehicleClass svc = item.first;
1674 const double speed = item.second;
1675 const auto it = (*resAfter).find(svc);
1676 if (it != (*resAfter).end()) {
1677 const double speed2 = it->second;
1678 const double newSpeed = (MSNet::getInstance()->hasJunctionHigherSpeeds()
1679 ? MAX2(speed, speed2) : (speed + speed2) / 2);
1680 net->addRestriction(myEdgeType, svc, newSpeed);
1681 }
1682 }
1683 }
1684 }
1685 }
1686 }
1687 }
1688}
1689
1690
1691double
1692MSEdge::getDistanceAt(double pos) const {
1693 // negative values of myDistances indicate descending kilometrage
1694 return fabs(myDistance + pos);
1695}
1696
1697
1698bool
1702
1703
1704std::pair<double, SUMOTime>
1705MSEdge::getLastBlocked(int index) const {
1706 if (myLaneChanger != nullptr) {
1707 return myLaneChanger->getLastBlocked(index);
1708 }
1709 return std::make_pair(-1, -1);
1710}
1711
1712
1713double
1717
1718void
1720 myPersons.clear();
1721 myContainers.clear();
1722 myWaiting.clear();
1723}
1724
1725/****************************************************************************/
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
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:46
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:330
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:238
A vehicle from the mesoscopic point of view.
Definition MEVehicle.h:42
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getLength() const
Returns the vehicle's length.
const MSRoute & getRoute() const
Returns the current route.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
Sorts edges by their ids.
Definition MSEdge.h:887
Sorts transportables by their positions.
Definition MSEdge.h:902
int operator()(const MSTransportable *const c1, const MSTransportable *const c2) const
comparing operator
Definition MSEdge.cpp:1260
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1114
SUMOVehicle * getWaitingVehicle(MSTransportable *transportable, const double position) const
Definition MSEdge.cpp:1500
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:920
double getBruttoOccupancy() const
Definition MSEdge.cpp:1637
SVCPermissions myCombinedPermissions
The union of lane permissions for this edge.
Definition MSEdge.h:976
double getFlow() const
return flow based on meanSpead
Definition MSEdge.cpp:1624
Boundary myBoundary
The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start ...
Definition MSEdge.h:1060
double myWidth
Edge width [m].
Definition MSEdge.h:1006
AllowedLanesByTarget myAllowedTargets
From target edge to lanes allowed to be used to reach it.
Definition MSEdge.h:970
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:675
SUMOTime myLastFailedInsertionTime
The time of last insertion failure.
Definition MSEdge.h:934
std::set< MSTransportable *, ComparatorNumericalIdLess > myContainers
Containers on the edge.
Definition MSEdge.h:960
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:1705
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1120
void inferEdgeType()
Definition MSEdge.cpp:1655
void setJunctions(MSJunction *from, MSJunction *to)
Definition MSEdge.cpp:1347
double getMeanSpeedBike() const
get the mean speed of all bicycles on this edge
Definition MSEdge.cpp:1039
static MSEdgeVector myEdges
Static list of edges.
Definition MSEdge.h:1043
AllowedLanesCont myAllowed
Associative container from vehicle class to allowed-lanes.
Definition MSEdge.h:966
double myEmptyTraveltime
the traveltime on the empty edge (cached value for speedup)
Definition MSEdge.h:1012
bool myAmFringe
whether this edge is at the network fringe
Definition MSEdge.h:1024
static double getTravelTimeAggregated(const MSEdge *const edge, const SUMOVehicle *const veh, double time)
Definition MSEdge.cpp:1649
MSJunction * myToJunction
Definition MSEdge.h:954
void checkAndRegisterBiDirEdge(const std::string &bidiID="")
check and register the opposite superposable edge if any
Definition MSEdge.cpp:1405
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:617
const double myDistance
the kilometrage/mileage at the start of the edge
Definition MSEdge.h:1003
void clearState()
Remove all transportables before quick-loading state.
Definition MSEdge.cpp:1719
MSLane * getDepartLaneMeso(SUMOVehicle &veh) const
consider given departLane parameter (only for validating speeds)
Definition MSEdge.cpp:664
bool hasTransientPermissions() const
Definition MSEdge.cpp:1699
const MSEdge * myBidiEdge
the oppositing superposable edge
Definition MSEdge.h:1076
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:451
std::string myEdgeType
the type of the edge (optionally used during network creation)
Definition MSEdge.h:994
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:1542
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1368
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:1138
double getLengthGeometryFactor() const
return shape.length() / myLength
Definition MSEdge.cpp:1193
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:1271
friend class MSLaneChangerSublane
Definition MSEdge.h:87
std::vector< SUMOVehicle * > myWaiting
List of waiting vehicles.
Definition MSEdge.h:1063
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:975
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition MSEdge.cpp:480
double 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:950
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:1234
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:1460
bool validateDepartSpeed(SUMOVehicle &v) const
check whether the given departSpeed is valid for this edge
Definition MSEdge.cpp:764
double getDistanceTo(const MSEdge *other, const bool doBoundaryEstimate=false) const
optimistic air distance heuristic for use in routing
Definition MSEdge.cpp:1161
void setMaxSpeed(double val, double jamThreshold=-1)
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition MSEdge.cpp:1205
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:1101
MSLaneChanger * myLaneChanger
This member will do the lane-change.
Definition MSEdge.h:925
double getOccupancy() const
return mean occupancy on this edges lanes or segments
Definition MSEdge.cpp:1602
static int myDefaultDepartLane
Definition MSEdge.h:1048
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition MSEdge.cpp:1316
std::vector< MSTransportable * > getSortedContainers(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's containers sorted by pos.
Definition MSEdge.cpp:1252
const SumoXMLEdgeFunc myFunction
the purpose of the edge
Definition MSEdge.h:928
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:579
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:1186
SVCPermissions myOriginalCombinedPermissions
The original union of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:981
bool myAmDelayed
whether this edge had a vehicle with less than max speed on it
Definition MSEdge.h:1018
SVCPermissions myOriginalMinimumPermissions
The original intersection of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:979
std::map< SUMOVehicleClass, MSEdgeVector > myClassesSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1053
SUMOTime decVaporization(SUMOTime t)
Disables vaporization.
Definition MSEdge.cpp:540
MSEdgeVector myPredecessors
The preceeding edges.
Definition MSEdge.h:950
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:1390
void rebuildAllowedTargets(const bool updateVehicles=true)
Definition MSEdge.cpp:384
static SVCPermissions myMesoIgnoredVClasses
Definition MSEdge.h:1045
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:984
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:1358
std::set< int > myFailedInsertionMemory
A cache for the rejected insertion attempts. Used to assure that no further insertion attempts are ma...
Definition MSEdge.h:939
const MSJunction * getFromJunction() const
Definition MSEdge.h:423
double getMeanSpeed() const
get the mean speed
Definition MSEdge.cpp:985
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition MSEdge.h:1038
std::set< MSTransportable *, ComparatorNumericalIdLess > myPersons
Persons on the edge for drawing and pushbutton.
Definition MSEdge.h:957
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:1692
const std::string & getRoutingType() const
Returns the type of the edge.
Definition MSEdge.h:326
MSConstEdgePairVector myViaSuccessors
Definition MSEdge.h:947
void setBidiLanes()
Definition MSEdge.cpp:1435
MSEdgeVector mySuccessors
The succeeding edges.
Definition MSEdge.h:945
static DepartLaneDefinition myDefaultDepartLaneDefinition
Definition MSEdge.h:1047
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:457
double getCurrentTravelTime(const double minSpeed=NUMERICAL_EPS) const
Computes and returns the current travel time for this edge.
Definition MSEdge.cpp:1059
std::map< SUMOVehicleClass, MSConstEdgePairVector > myOrigClassesViaSuccessorMap
Definition MSEdge.h:1057
AllowedLanesByTarget myOrigAllowedTargets
Definition MSEdge.h:971
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:801
static const Position getStopPosition(const SUMOVehicleParameter::Stop &stop)
return the coordinates of the center of the given stop
Definition MSEdge.cpp:1180
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1479
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:463
ReversedEdge< MSEdge, SUMOVehicle > * myReversedRoutingEdge
a reversed version for backward routing
Definition MSEdge.h:1079
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:1075
std::vector< const SUMOVehicle * > getVehicles() const
return vehicles on this edges lanes or segments
Definition MSEdge.cpp:1523
static void insertIDs(std::vector< std::string > &into)
Inserts IDs of all known edges into the given vector.
Definition MSEdge.cpp:1130
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1198
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition MSEdge.cpp:533
MSJunction * myFromJunction
the junctions for this edge
Definition MSEdge.h:953
double getMeanFriction() const
get the mean friction over the lanes
Definition MSEdge.cpp:1026
std::map< std::string, MSEdge * > DictType
definition of the static dictionary type
Definition MSEdge.h:1033
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1378
double getPreference(const SUMOVTypeParameter &pars) const
Definition MSEdge.cpp:1714
std::map< SUMOVehicleClass, MSConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1056
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:965
int getVehicleNumber() const
return total number of vehicles on this edges lanes or segments
Definition MSEdge.cpp:1560
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:418
virtual void removeTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1225
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:1566
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition MSEdge.cpp:928
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:1069
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition MSEdge.h:786
void removeWaiting(const SUMOVehicle *vehicle) const
Removes a vehicle from the list of waiting vehicles.
Definition MSEdge.cpp:1488
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false, int routingMode=0) const
Definition MSEdge.cpp:753
std::vector< double > mySublaneSides
the right side for each sublane on this edge
Definition MSEdge.h:1027
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1286
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:922
AllowedLanesCont myOrigAllowed
Definition MSEdge.h:967
double getWaitingSeconds() const
return accumated waiting time for all vehicles on this edges lanes or segments
Definition MSEdge.cpp:1586
int myVaporizationRequests
Vaporizer counter.
Definition MSEdge.h:931
double myTimePenalty
flat penalty when computing traveltime
Definition MSEdge.h:1015
SVCPermissions myMinimumPermissions
The intersection of lane permissions for this edge.
Definition MSEdge.h:974
MSLane * getFreeLane(const std::vector< MSLane * > *allowed, const SUMOVehicleClass vclass, double departPos) const
Finds the emptiest lane allowing the vehicle class.
Definition MSEdge.cpp:547
void rebuildAllowedLanes(const bool onInit=false, bool updateVehicles=false)
Definition MSEdge.cpp:323
virtual void addTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1216
RailEdge< MSEdge, SUMOVehicle > * myRailwayRoutingEdge
Definition MSEdge.h:1080
double myLength
the length of the edge (cached value for speedup)
Definition MSEdge.h:1009
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition MSGlobals.h:168
static bool gUseMesoSim
Definition MSGlobals.h:106
static double gMinorPenalty
(minimum) time penalty for passing a minor link when routing
Definition MSGlobals.h:155
static bool gCheckRoutes
Definition MSGlobals.h:91
static double gTLSPenalty
scaled (minimum) time penalty for passing a tls link when routing
Definition MSGlobals.h:157
static double gTurnaroundPenalty
(minimum) time penalty for passing a turnaround link when routing
Definition MSGlobals.h:159
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:112
static double gLateralResolution
Definition MSGlobals.h:100
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:146
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:149
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:690
bool empty() const
Returns true if there is not a single vehicle on the lane.
Definition MSLane.h:745
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:648
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3410
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2496
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4397
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:770
double getWidth() const
Returns the lane's width.
Definition MSLane.h:641
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:187
double getPreference(const std::string &routingType, const SUMOVTypeParameter &pars) const
retriefe edge type specific routing preference
Definition MSNet.cpp:365
bool hasJunctionHigherSpeeds() const
return whether the network was built with higher junction speeds
Definition MSNet.h:803
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:355
void addRestriction(const std::string &id, const SUMOVehicleClass svc, const double speed)
Adds a restriction for an edge type.
Definition MSNet.cpp:349
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:413
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.
double getLength() const
Get vehicle's length [m].
double computeChosenSpeedDeviation(SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
Base class for objects which have an id.
Definition Named.h:54
const std::string & getID() const
Returns the id.
Definition Named.h:74
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
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