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) {
868 }
869 switch (dld) {
873 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
874 if (insertionLane == nullptr) {
875 WRITE_WARNINGF(TL("Could not insert vehicle '%' on any lane of edge '%', time=%."),
876 v.getID(), getID(), time2string(time));
877 return false;
878 }
879 const double occupancy = insertionLane->getBruttoOccupancy();
880 return (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
882 }
883 default:
884 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
885 const double occupancy = (*i)->getBruttoOccupancy();
886 if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
888 return true;
889 }
890 }
891 }
892 return false;
893 }
894 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
895 if (insertionLane == nullptr) {
896 return false;
897 }
898
899 if (!forceCheck) {
900 if (myLastFailedInsertionTime == time) {
901 if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
902 // A vehicle was already rejected for the proposed insertionLane in this timestep
903 return false;
904 }
905 } else {
906 // last rejection occurred in a previous timestep, clear cache
908 }
909 }
910
911 bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
912
913 if (!success) {
914 // constraints may enforce explicit re-ordering so we need to try other vehicles after failure
915 if (!insertionLane->hasParameter("insertionOrder" + v.getID())) {
916 myFailedInsertionMemory.insert(insertionLane->getIndex());
917 }
918 }
919 return success;
920}
921
922
923void
925 if (myLaneChanger != nullptr) {
927 }
928}
929
930
931const MSEdge*
932MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
933 //@todo to be optimized
934 for (const MSLane* const l : *myLanes) {
935 for (const MSLink* const link : l->getLinkCont()) {
936 if (&link->getLane()->getEdge() == followerAfterInternal) {
937 if (link->getViaLane() != nullptr) {
938 if (link->getViaLane()->allowsVehicleClass(vClass)) {
939 return &link->getViaLane()->getEdge();
940 } else {
941 continue;
942 }
943 } else {
944 return nullptr; // network without internal links
945 }
946 }
947 }
948 }
949 return nullptr;
950}
951
952
953double
954MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
955 assert(followerAfterInternal != 0);
956 assert(!followerAfterInternal->isInternal());
957 double dist = 0.;
958 const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal, vClass);
959 // Take into account non-internal lengths until next non-internal edge
960 while (edge != nullptr && edge->isInternal()) {
961 dist += edge->getLength();
962 edge = edge->getInternalFollowingEdge(followerAfterInternal, vClass);
963 }
964 return dist;
965}
966
967
968const MSEdge*
970 const MSEdge* result = this;
971 while (result->isInternal() && MSGlobals::gUsingInternalLanes) {
972 assert(result->getPredecessors().size() == 1);
973 result = result->getPredecessors().front();
974 }
975 return result;
976}
977
978const MSEdge*
980 const MSEdge* result = this;
981 while (result->isInternal()) {
982 assert(result->getSuccessors().size() == 1);
983 result = result->getSuccessors().front();
984 }
985 return result;
986}
987
988double
990 double v = 0;
991 double totalNumVehs = 0;
993 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
994 const int numVehs = segment->getCarNumber();
995 if (numVehs > 0) {
996 v += numVehs * segment->getMeanSpeed();
997 totalNumVehs += numVehs;
998 }
999 }
1000 if (totalNumVehs == 0) {
1001 return getLength() / myEmptyTraveltime; // may include tls-penalty
1002 }
1003 } else {
1004 for (const MSLane* const lane : *myLanes) {
1005 int numVehs = lane->getVehicleNumber();
1006 if (numVehs == 0) {
1007 // take speed limit but with lowest possible weight
1008 numVehs = 1;
1009 }
1010 v += numVehs * lane->getMeanSpeed();
1011 totalNumVehs += numVehs;
1012 }
1013 if (myBidiEdge != nullptr) {
1014 for (const MSLane* const lane : myBidiEdge->getLanes()) {
1015 if (lane->getVehicleNumber() > 0) {
1016 // do not route across edges which are already occupied in reverse direction
1017 return 0;
1018 }
1019 }
1020 }
1021 if (totalNumVehs == 0) {
1022 return getSpeedLimit();
1023 }
1024 }
1025 return v / totalNumVehs;
1026}
1027
1028
1029double
1031 double f = 0.;
1032 for (const MSLane* const lane : *myLanes) {
1033 f += lane->getFrictionCoefficient();
1034 }
1035 if (!myLanes->empty()) {
1036 return f / (double)myLanes->size();
1037 }
1038 return 1.;
1039}
1040
1041
1042double
1045 // no separate bicycle speeds in meso
1046 return getMeanSpeed();
1047 }
1048 double v = 0;
1049 double totalNumVehs = 0;
1050 for (const MSLane* const lane : *myLanes) {
1051 const int numVehs = lane->getVehicleNumber();
1052 v += numVehs * lane->getMeanSpeedBike();
1053 totalNumVehs += numVehs;
1054 }
1055 if (totalNumVehs == 0) {
1056 return getSpeedLimit();
1057 }
1058 return v / totalNumVehs;
1059}
1060
1061
1062double
1063MSEdge::getCurrentTravelTime(double minSpeed) const {
1064 assert(minSpeed > 0);
1065 if (!myAmDelayed) {
1066 return myEmptyTraveltime;
1067 }
1068 return getLength() / MAX2(minSpeed, getMeanSpeed());
1069}
1070
1071
1072double
1074 return MSRoutingEngine::getAssumedSpeed(this, nullptr);
1075}
1076
1077
1078bool
1079MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
1080 const DictType::iterator it = myDict.lower_bound(id);
1081 if (it == myDict.end() || it->first != id) {
1082 // id not in myDict
1083 myDict.emplace_hint(it, id, ptr);
1084 while (ptr->getNumericalID() >= (int)myEdges.size()) {
1085 myEdges.push_back(nullptr);
1086 }
1087 myEdges[ptr->getNumericalID()] = ptr;
1088 return true;
1089 }
1090 return false;
1091}
1092
1093
1094MSEdge*
1095MSEdge::dictionary(const std::string& id) {
1096 const DictType::iterator it = myDict.find(id);
1097 if (it == myDict.end()) {
1098 return nullptr;
1099 }
1100 return it->second;
1101}
1102
1103
1104MSEdge*
1105MSEdge::dictionaryHint(const std::string& id, const int startIdx) {
1106 // this method is mainly useful when parsing connections from the net.xml which are sorted by "from" id
1107 if (myEdges[startIdx] != nullptr && myEdges[startIdx]->getID() == id) {
1108 return myEdges[startIdx];
1109 }
1110 if (startIdx + 1 < (int)myEdges.size() && myEdges[startIdx + 1] != nullptr && myEdges[startIdx + 1]->getID() == id) {
1111 return myEdges[startIdx + 1];
1112 }
1113 return dictionary(id);
1114}
1115
1116
1117const MSEdgeVector&
1119 return myEdges;
1120}
1121
1122
1123void
1125 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1126 delete (*i).second;
1127 }
1128 myDict.clear();
1129 myEdges.clear();
1130}
1131
1132
1133void
1134MSEdge::insertIDs(std::vector<std::string>& into) {
1135 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1136 into.push_back((*i).first);
1137 }
1138}
1139
1140
1141void
1142MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
1143 const std::string& rid) {
1144 StringTokenizer st(desc);
1145 parseEdgesList(st.getVector(), into, rid);
1146}
1147
1148
1149void
1150MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
1151 const std::string& rid) {
1152 for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1153 const MSEdge* edge = MSEdge::dictionary(*i);
1154 // check whether the edge exists
1155 if (edge == nullptr) {
1156 throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
1157 + "\n The route can not be build.");
1158 }
1159 into.push_back(edge);
1160 }
1161}
1162
1163
1164double
1165MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
1166 assert(this != other);
1167 if (doBoundaryEstimate) {
1168 return myBoundary.distanceTo2D(other->myBoundary);
1169 }
1170 if (isTazConnector()) {
1171 if (other->isTazConnector()) {
1172 return myBoundary.distanceTo2D(other->myBoundary);
1173 }
1174 return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
1175 }
1176 if (other->isTazConnector()) {
1177 return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
1178 }
1179 return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
1180}
1181
1182
1183const Position
1185 return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
1186}
1187
1188
1189double
1191 // @note lanes might have different maximum speeds in theory
1192 return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
1193}
1194
1195
1196double
1198 return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
1199}
1200
1201double
1203 // @note lanes might have different maximum speeds in theory
1204 return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
1205}
1206
1207
1208void
1209MSEdge::setMaxSpeed(const double val, const bool modified, const double jamThreshold) {
1210 assert(val >= 0);
1211 if (myLanes != nullptr) {
1212 for (MSLane* const lane : *myLanes) {
1213 lane->setMaxSpeed(val, modified, jamThreshold);
1214 }
1215 }
1216}
1217
1218
1219void
1221 if (t->isPerson()) {
1222 myPersons.insert(t);
1223 } else {
1224 myContainers.insert(t);
1225 }
1226}
1227
1228void
1230 std::set<MSTransportable*, ComparatorNumericalIdLess>& tc = t->isPerson() ? myPersons : myContainers;
1231 auto it = tc.find(t);
1232 if (it != tc.end()) {
1233 tc.erase(it);
1234 }
1235}
1236
1237std::vector<MSTransportable*>
1238MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
1239 std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
1240 if (includeRiding) {
1241 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1242 const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
1243 for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
1244 const std::vector<MSTransportable*>& persons = (*j)->getPersons();
1245 result.insert(result.end(), persons.begin(), persons.end());
1246 }
1247 (*i)->releaseVehicles();
1248 }
1249 }
1250 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1251 return result;
1252}
1253
1254
1255std::vector<MSTransportable*>
1256MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
1257 std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
1258 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1259 return result;
1260}
1261
1262
1263int
1265 const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
1266 const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
1267 if (pos1 != pos2) {
1268 return pos1 < pos2;
1269 }
1270 return c1->getID() < c2->getID();
1271}
1272
1273
1274void
1276 mySuccessors.push_back(edge);
1277 myViaSuccessors.push_back(std::make_pair(edge, via));
1278 if (isTazConnector() && edge->getFromJunction() != nullptr) {
1280 }
1281
1282 edge->myPredecessors.push_back(this);
1283 if (edge->isTazConnector() && getToJunction() != nullptr) {
1284 edge->myBoundary.add(getToJunction()->getPosition());
1285 }
1286}
1287
1288
1289const MSEdgeVector&
1291 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1292 return mySuccessors;
1293 }
1294#ifdef HAVE_FOX
1295 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1296#endif
1297 std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1298 if (i == myClassesSuccessorMap.end()) {
1299 // instantiate vector
1300 myClassesSuccessorMap[vClass];
1301 i = myClassesSuccessorMap.find(vClass);
1302 // this vClass is requested for the first time. rebuild all successors
1303 for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1304 if ((*it)->isTazConnector()) {
1305 i->second.push_back(*it);
1306 } else {
1307 const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1308 if (allowed != nullptr && allowed->size() > 0) {
1309 i->second.push_back(*it);
1310 }
1311 }
1312 }
1313 }
1314 // can use cached value
1315 return i->second;
1316}
1317
1318
1320MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
1321 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1322 return myViaSuccessors;
1323 }
1324#ifdef HAVE_FOX
1325 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1326#endif
1327 auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
1328 auto i = viaMap.find(vClass);
1329 if (i != viaMap.end()) {
1330 // can use cached value
1331 return i->second;
1332 }
1333 // instantiate vector
1334 MSConstEdgePairVector& result = viaMap[vClass];
1335 // this vClass is requested for the first time. rebuild all successors
1336 for (const auto& viaPair : myViaSuccessors) {
1337 if (viaPair.first->isTazConnector()) {
1338 result.push_back(viaPair);
1339 } else {
1340 const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
1341 if (allowed != nullptr && allowed->size() > 0) {
1342 result.push_back(viaPair);
1343 }
1344 }
1345 }
1346 return result;
1347}
1348
1349
1350void
1352 myFromJunction = from;
1353 myToJunction = to;
1354 if (!isTazConnector()) {
1355 myBoundary.add(from->getPosition());
1356 myBoundary.add(to->getPosition());
1357 }
1358}
1359
1360
1361bool
1363 return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1364 // do not change on curved internal lanes
1365 (!isInternal()
1367 && myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LinkDirection::STRAIGHT)));
1368}
1369
1370
1371const MSEdge*
1373 if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1374 return &(myLanes->back()->getOpposite()->getEdge());
1375 } else {
1376 return nullptr;
1377 }
1378}
1379
1380
1381bool
1383 for (const MSLane* const l : *myLanes) {
1384 for (const MSLink* const link : l->getLinkCont()) {
1385 if (!link->havePriority()) {
1386 return true;
1387 }
1388 }
1389 }
1390 return false;
1391}
1392
1393bool
1395 if (myLanes->size() == 1) {
1396 return false;
1397 }
1398 for (const MSLane* const l : *myLanes) {
1399 if (l->getIndex() <= index && !l->allowsChangingRight(svc) && l->getIndex() > 0) {
1400 return true;
1401 } else if (l->getIndex() >= index && !l->allowsChangingLeft(svc) && l->getIndex() < (int)(myLanes->size() - 1)) {
1402 return true;
1403 }
1404 }
1405 return false;
1406}
1407
1408void
1409MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1410 if (bidiID != "") {
1411 myBidiEdge = dictionary(bidiID);
1412 if (myBidiEdge == nullptr) {
1413 WRITE_ERRORF(TL("Bidi-edge '%' does not exist"), bidiID);
1414 }
1415 setBidiLanes();
1416 return;
1417 }
1419 return;
1420 }
1421 // legacy networks (no bidi attribute)
1423 for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1424 if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1425 if (myBidiEdge != nullptr && isSuperposable(*it)) {
1426 WRITE_WARNINGF(TL("Ambiguous superposable edges between junction '%' and '%'."), myToJunction->getID(), myFromJunction->getID());
1427 break;
1428 }
1429 if (isSuperposable(*it)) {
1430 myBidiEdge = *it;
1431 setBidiLanes();
1432 }
1433 }
1434 }
1435}
1436
1437
1438void
1440 assert(myBidiEdge != nullptr);
1441 if (getNumLanes() == 1 && myBidiEdge->getNumLanes() == 1) {
1442 // the other way round is set when this method runs for the bidiEdge
1443 getLanes()[0]->setBidiLane(myBidiEdge->getLanes()[0]);
1444 } else {
1445 // find lanes with matching reversed shapes
1446 int numBidiLanes = 0;
1447 for (MSLane* l1 : *myLanes) {
1448 for (MSLane* l2 : *myBidiEdge->myLanes) {
1449 if (l1->getShape().reverse().almostSame(l2->getShape(), POSITION_EPS * 2)) {
1450 l1->setBidiLane(l2);
1451 numBidiLanes++;
1452 }
1453 }
1454 }
1455 // warn only once for each pair
1456 if (numBidiLanes == 0 && getNumericalID() < myBidiEdge->getNumericalID()) {
1457 WRITE_WARNINGF(TL("Edge '%' and bidi edge '%' have no matching bidi lanes"), getID(), myBidiEdge->getID());
1458 }
1459 }
1460}
1461
1462
1463bool
1465 if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1466 return false;
1467 }
1468 std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1469 std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1470 do {
1471 if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1472 return false;
1473 }
1474 it1++;
1475 it2++;
1476 } while (it1 != myLanes->end());
1477
1478 return true;
1479}
1480
1481
1482void
1484#ifdef HAVE_FOX
1485 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1486#endif
1487 myWaiting.push_back(vehicle);
1488}
1489
1490
1491void
1492MSEdge::removeWaiting(const SUMOVehicle* vehicle) const {
1493#ifdef HAVE_FOX
1494 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1495#endif
1496 std::vector<SUMOVehicle*>::iterator it = std::find(myWaiting.begin(), myWaiting.end(), vehicle);
1497 if (it != myWaiting.end()) {
1498 myWaiting.erase(it);
1499 }
1500}
1501
1502
1504MSEdge::getWaitingVehicle(MSTransportable* transportable, const double position) const {
1505#ifdef HAVE_FOX
1506 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1507#endif
1508 for (SUMOVehicle* const vehicle : myWaiting) {
1509 if (transportable->isWaitingFor(vehicle)) {
1510 if (vehicle->isStoppedInRange(position, MSGlobals::gStopTolerance) ||
1511 (!vehicle->hasDeparted() &&
1512 (vehicle->getParameter().departProcedure == DepartDefinition::TRIGGERED ||
1513 vehicle->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED))) {
1514 return vehicle;
1515 }
1516 if (!vehicle->isLineStop(position) && vehicle->allowsBoarding(transportable)) {
1517 WRITE_WARNING((transportable->isPerson() ? "Person '" : "Container '")
1518 + transportable->getID() + "' at edge '" + getID() + "' position " + toString(position) + " cannot use waiting vehicle '"
1519 + vehicle->getID() + "' at position " + toString(vehicle->getPositionOnLane()) + " because it is too far away.");
1520 }
1521 }
1522 }
1523 return nullptr;
1524}
1525
1526std::vector<const SUMOVehicle*>
1528 std::vector<const SUMOVehicle*> result;
1530 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1531 std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
1532 result.insert(result.end(), segmentVehs.begin(), segmentVehs.end());
1533 }
1534 } else {
1535 for (MSLane* lane : getLanes()) {
1536 for (auto veh : lane->getVehiclesSecure()) {
1537 result.push_back(veh);
1538 }
1539 lane->releaseVehicles();
1540 }
1541 }
1542 return result;
1543}
1544
1545int
1547 int result = 0;
1548 SVCPermissions filter = SVCAll;
1550 filter = ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1551 } else if ((myCombinedPermissions & (SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1552 // filter out green verge
1553 filter = (SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1554 }
1555 for (const MSLane* const l : *myLanes) {
1556 if ((l->getPermissions() & filter) != 0) {
1557 result++;
1558 }
1559 }
1560 return result;
1561}
1562
1563int
1565 return (int)getVehicles().size();
1566}
1567
1568
1569bool
1573 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1574 if (segment->getCarNumber() > 0) {
1575 return false;
1576 }
1577 }
1578 } else {
1579 for (MSLane* lane : getLanes()) {
1580 if (lane->getVehicleNumber() > 0) {
1581 return false;
1582 }
1583 }
1584 }
1585 return true;
1586}
1587
1588
1589double
1591 double wtime = 0;
1593 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1594 wtime += segment->getWaitingSeconds();
1595 }
1596 } else {
1597 for (MSLane* lane : getLanes()) {
1598 wtime += lane->getWaitingSeconds();
1599 }
1600 }
1601 return wtime;
1602}
1603
1604
1605double
1607 if (myLanes->size() == 0) {
1608 return 0;
1609 }
1612 double sum = 0;
1613 for (const SUMOVehicle* veh : getVehicles()) {
1614 sum += dynamic_cast<const MEVehicle*>(veh)->getVehicleType().getLength();
1615 }
1616 return sum / (myLength * (double)myLanes->size());
1617 } else {
1618 double sum = 0;
1619 for (auto lane : getLanes()) {
1620 sum += lane->getNettoOccupancy();
1621 }
1622 return sum / (double)myLanes->size();
1623 }
1624}
1625
1626
1627double
1629 if (myLanes->size() == 0) {
1630 return 0;
1631 }
1632 double flow = 0;
1633 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1634 flow += (double) segment->getCarNumber() * segment->getMeanSpeed();
1635 }
1636 return 3600 * flow / (*myLanes)[0]->getLength();
1637}
1638
1639
1640double
1642 if (myLanes->size() == 0) {
1643 return 0;
1644 }
1645 double occ = 0;
1646 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1647 occ += segment->getBruttoOccupancy();
1648 }
1649 return occ / (*myLanes)[0]->getLength() / (double)(myLanes->size());
1650}
1651
1652double
1653MSEdge::getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double /*time*/) {
1654 return edge->getLength() / MIN2(MSRoutingEngine::getAssumedSpeed(edge, veh), veh->getMaxSpeed());
1655}
1656
1657
1658void
1660 // @note must be called after closeBuilding() to ensure successors and
1661 // predecessors are set
1662 if (isInternal() && myEdgeType == "") {
1663 const std::string typeBefore = getNormalBefore()->getEdgeType();
1664 if (typeBefore != "") {
1665 const std::string typeAfter = getNormalSuccessor()->getEdgeType();
1666 if (typeBefore == typeAfter) {
1667 myEdgeType = typeBefore;
1668 } else if (typeAfter != "") {
1669 MSNet* net = MSNet::getInstance();
1670 auto resBefore = net->getRestrictions(typeBefore);
1671 auto resAfter = net->getRestrictions(typeAfter);
1672 if (resBefore != nullptr && resAfter != nullptr) {
1673 // create new restrictions for this type-combination
1674 myEdgeType = typeBefore + "|" + typeAfter;
1675 if (net->getRestrictions(myEdgeType) == nullptr) {
1676 for (const auto& item : *resBefore) {
1677 const SUMOVehicleClass svc = item.first;
1678 const double speed = item.second;
1679 const auto it = (*resAfter).find(svc);
1680 if (it != (*resAfter).end()) {
1681 const double speed2 = it->second;
1682 const double newSpeed = (MSNet::getInstance()->hasJunctionHigherSpeeds()
1683 ? MAX2(speed, speed2) : (speed + speed2) / 2);
1684 net->addRestriction(myEdgeType, svc, newSpeed);
1685 }
1686 }
1687 }
1688 }
1689 }
1690 }
1691 }
1692}
1693
1694
1695double
1696MSEdge::getDistanceAt(double pos) const {
1697 // negative values of myDistances indicate descending kilometrage
1698 return fabs(myDistance + pos);
1699}
1700
1701
1702bool
1706
1707
1708std::pair<double, SUMOTime>
1709MSEdge::getLastBlocked(int index) const {
1710 if (myLaneChanger != nullptr) {
1711 return myLaneChanger->getLastBlocked(index);
1712 }
1713 return std::make_pair(-1, -1);
1714}
1715
1716
1717double
1721
1722void
1724 myPersons.clear();
1725 myContainers.clear();
1726 myWaiting.clear();
1727}
1728
1729/****************************************************************************/
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: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:339
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:889
Sorts transportables by their positions.
Definition MSEdge.h:904
int operator()(const MSTransportable *const c1, const MSTransportable *const c2) const
comparing operator
Definition MSEdge.cpp:1264
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1118
SUMOVehicle * getWaitingVehicle(MSTransportable *transportable, const double position) const
Definition MSEdge.cpp:1504
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:924
double getBruttoOccupancy() const
Definition MSEdge.cpp:1641
SVCPermissions myCombinedPermissions
The union of lane permissions for this edge.
Definition MSEdge.h:978
double getFlow() const
return flow based on meanSpead
Definition MSEdge.cpp:1628
Boundary myBoundary
The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start ...
Definition MSEdge.h:1062
double myWidth
Edge width [m].
Definition MSEdge.h:1008
AllowedLanesByTarget myAllowedTargets
From target edge to lanes allowed to be used to reach it.
Definition MSEdge.h:972
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:936
std::set< MSTransportable *, ComparatorNumericalIdLess > myContainers
Containers on the edge.
Definition MSEdge.h:962
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:1209
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:1709
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1124
void inferEdgeType()
Definition MSEdge.cpp:1659
void setJunctions(MSJunction *from, MSJunction *to)
Definition MSEdge.cpp:1351
double getMeanSpeedBike() const
get the mean speed of all bicycles on this edge
Definition MSEdge.cpp:1043
static MSEdgeVector myEdges
Static list of edges.
Definition MSEdge.h:1045
AllowedLanesCont myAllowed
Associative container from vehicle class to allowed-lanes.
Definition MSEdge.h:968
double myEmptyTraveltime
the traveltime on the empty edge (cached value for speedup)
Definition MSEdge.h:1014
bool myAmFringe
whether this edge is at the network fringe
Definition MSEdge.h:1026
static double getTravelTimeAggregated(const MSEdge *const edge, const SUMOVehicle *const veh, double time)
Definition MSEdge.cpp:1653
MSJunction * myToJunction
Definition MSEdge.h:956
void checkAndRegisterBiDirEdge(const std::string &bidiID="")
check and register the opposite superposable edge if any
Definition MSEdge.cpp:1409
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:1005
void clearState()
Remove all transportables before quick-loading state.
Definition MSEdge.cpp:1723
MSLane * getDepartLaneMeso(SUMOVehicle &veh) const
consider given departLane parameter (only for validating speeds)
Definition MSEdge.cpp:664
bool hasTransientPermissions() const
Definition MSEdge.cpp:1703
const MSEdge * myBidiEdge
the oppositing superposable edge
Definition MSEdge.h:1078
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:996
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:1546
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1372
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:1142
double getLengthGeometryFactor() const
return shape.length() / myLength
Definition MSEdge.cpp:1197
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:1275
friend class MSLaneChangerSublane
Definition MSEdge.h:87
std::vector< SUMOVehicle * > myWaiting
List of waiting vehicles.
Definition MSEdge.h:1065
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:979
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:954
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:1238
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:1464
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:1165
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:1105
MSLaneChanger * myLaneChanger
This member will do the lane-change.
Definition MSEdge.h:927
double getOccupancy() const
return mean occupancy on this edges lanes or segments
Definition MSEdge.cpp:1606
static int myDefaultDepartLane
Definition MSEdge.h:1050
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition MSEdge.cpp:1320
std::vector< MSTransportable * > getSortedContainers(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's containers sorted by pos.
Definition MSEdge.cpp:1256
const SumoXMLEdgeFunc myFunction
the purpose of the edge
Definition MSEdge.h:930
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:1190
SVCPermissions myOriginalCombinedPermissions
The original union of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:983
bool myAmDelayed
whether this edge had a vehicle with less than max speed on it
Definition MSEdge.h:1020
SVCPermissions myOriginalMinimumPermissions
The original intersection of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:981
std::map< SUMOVehicleClass, MSEdgeVector > myClassesSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1055
SUMOTime decVaporization(SUMOTime t)
Disables vaporization.
Definition MSEdge.cpp:540
MSEdgeVector myPredecessors
The preceeding edges.
Definition MSEdge.h:952
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:1394
void rebuildAllowedTargets(const bool updateVehicles=true)
Definition MSEdge.cpp:384
static SVCPermissions myMesoIgnoredVClasses
Definition MSEdge.h:1047
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:986
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:1362
std::set< int > myFailedInsertionMemory
A cache for the rejected insertion attempts. Used to assure that no further insertion attempts are ma...
Definition MSEdge.h:941
const MSJunction * getFromJunction() const
Definition MSEdge.h:423
double getMeanSpeed() const
get the mean speed
Definition MSEdge.cpp:989
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition MSEdge.h:1040
std::set< MSTransportable *, ComparatorNumericalIdLess > myPersons
Persons on the edge for drawing and pushbutton.
Definition MSEdge.h:959
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:1696
const std::string & getRoutingType() const
Returns the type of the edge.
Definition MSEdge.h:326
MSConstEdgePairVector myViaSuccessors
Definition MSEdge.h:949
void setBidiLanes()
Definition MSEdge.cpp:1439
MSEdgeVector mySuccessors
The succeeding edges.
Definition MSEdge.h:947
static DepartLaneDefinition myDefaultDepartLaneDefinition
Definition MSEdge.h:1049
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:1063
std::map< SUMOVehicleClass, MSConstEdgePairVector > myOrigClassesViaSuccessorMap
Definition MSEdge.h:1059
AllowedLanesByTarget myOrigAllowedTargets
Definition MSEdge.h:973
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:1184
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1483
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:1081
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:1079
std::vector< const SUMOVehicle * > getVehicles() const
return vehicles on this edges lanes or segments
Definition MSEdge.cpp:1527
static void insertIDs(std::vector< std::string > &into)
Inserts IDs of all known edges into the given vector.
Definition MSEdge.cpp:1134
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1202
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition MSEdge.cpp:533
MSJunction * myFromJunction
the junctions for this edge
Definition MSEdge.h:955
double getMeanFriction() const
get the mean friction over the lanes
Definition MSEdge.cpp:1030
std::map< std::string, MSEdge * > DictType
definition of the static dictionary type
Definition MSEdge.h:1035
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1382
double getPreference(const SUMOVTypeParameter &pars) const
Definition MSEdge.cpp:1718
std::map< SUMOVehicleClass, MSConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1058
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:969
int getVehicleNumber() const
return total number of vehicles on this edges lanes or segments
Definition MSEdge.cpp:1564
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:418
virtual void removeTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1229
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:1570
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition MSEdge.cpp:932
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:1073
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition MSEdge.h:788
void removeWaiting(const SUMOVehicle *vehicle) const
Removes a vehicle from the list of waiting vehicles.
Definition MSEdge.cpp:1492
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:1029
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1290
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:924
AllowedLanesCont myOrigAllowed
Definition MSEdge.h:969
double getWaitingSeconds() const
return accumated waiting time for all vehicles on this edges lanes or segments
Definition MSEdge.cpp:1590
int myVaporizationRequests
Vaporizer counter.
Definition MSEdge.h:933
double myTimePenalty
flat penalty when computing traveltime
Definition MSEdge.h:1017
SVCPermissions myMinimumPermissions
The intersection of lane permissions for this edge.
Definition MSEdge.h:976
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:1220
RailEdge< MSEdge, SUMOVehicle > * myRailwayRoutingEdge
Definition MSEdge.h:1082
double myLength
the length of the edge (cached value for speedup)
Definition MSEdge.h:1011
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:689
bool empty() const
Returns true if there is not a single vehicle on the lane.
Definition MSLane.h:750
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:653
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3423
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2510
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4410
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:775
double getWidth() const
Returns the lane's width.
Definition MSLane.h:646
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:378
bool hasJunctionHigherSpeeds() const
return whether the network was built with higher junction speeds
Definition MSNet.h:806
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:368
void addRestriction(const std::string &id, const SUMOVehicleClass svc, const double speed)
Adds a restriction for an edge type.
Definition MSNet.cpp:362
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:426
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