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 && myHaveTransientPermissions ? 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
663
664MSLane*
667 if ((int) myLanes->size() <= veh.getParameter().departLane || !(*myLanes)[veh.getParameter().departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
668 return nullptr;
669 }
670 return (*myLanes)[veh.getParameter().departLane];
671 }
672 return (*myLanes)[0];
673}
674
675
676MSLane*
679 int departLane = veh.getParameter().departLane;
682 departLane = myDefaultDepartLane;
683 }
684 switch (dld) {
686 if ((int) myLanes->size() <= departLane || !(*myLanes)[departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
687 return nullptr;
688 }
689 return (*myLanes)[departLane];
693 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
695 if (veh.getRoute().size() == 1) {
696 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
697 } else {
699 }
702 veh.updateBestLanes(false, myLanes->front());
703 const std::vector<MSVehicle::LaneQ>& bl = veh.getBestLanes();
704 double bestLength = -1;
705 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
706 if ((*i).length > bestLength) {
707 bestLength = (*i).length;
708 }
709 }
710 // beyond a certain length, all lanes are suitable
711 // however, we still need to check departPos to avoid unsuitable insertion
712 // (this is only possible in some cases)
713 double departPos = 0;
714 if (bestLength > BEST_LANE_LOOKAHEAD) {
715 departPos = getDepartPosBound(veh);
716 bestLength = MIN2(bestLength - departPos, BEST_LANE_LOOKAHEAD);
717 }
718 std::vector<MSLane*>* bestLanes = new std::vector<MSLane*>();
719 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
720 if (((*i).length - departPos) >= bestLength) {
721 if (isInternal()) {
722 for (MSLane* lane : *myLanes) {
723 if (lane->getNormalSuccessorLane() == (*i).lane) {
724 bestLanes->push_back(lane);
725 }
726 }
727 } else {
728 bestLanes->push_back((*i).lane);
729 }
730 }
731 }
732 MSLane* ret = nullptr;
734 ret = getFreeLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
735 } else {
736 ret = getProbableLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false), getVehicleMaxSpeed(&veh));
737 }
738 delete bestLanes;
739 return ret;
740 }
744 default:
745 break;
746 }
747 if (!(*myLanes)[0]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
748 return nullptr;
749 }
750 return (*myLanes)[0];
751}
752
753
754MSLane*
755MSEdge::getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst, int routingMode) const {
756 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
757 if ((*i)->allowsVehicleClass(vClass, routingMode)) {
758 return *i;
759 }
760 }
761 return defaultFirst && !myLanes->empty() ? myLanes->front() : nullptr;
762}
763
764
765bool
767 const SUMOVehicleParameter& pars = v.getParameter();
768 const MSVehicleType& type = v.getVehicleType();
770 // departSpeed could have been rounded down in the output
771 double vMax = getVehicleMaxSpeed(&v) + SPEED_EPS;
772 if (pars.departSpeed > vMax) {
773 // check departLane (getVehicleMaxSpeed checks lane 0)
774 MSLane* departLane = MSGlobals::gMesoNet ? getDepartLaneMeso(v) : getDepartLane(dynamic_cast<MSVehicle&>(v));
775 if (departLane != nullptr) {
776 vMax = departLane->getVehicleMaxSpeed(&v);
778 // speedFactor could have been rounded down in the output
779 vMax *= (1 + SPEED_EPS);
780 }
781 // additive term must come after multiplication!
782 vMax += SPEED_EPS;
783 if (pars.departSpeed > vMax) {
784 if (type.getSpeedFactor().getParameter(1) > 0.) {
786 if (v.getChosenSpeedFactor() > type.getSpeedFactor().getParameter(0) + 2 * type.getSpeedFactor().getParameter(1)) {
787 // only warn for significant deviation
788 WRITE_WARNINGF(TL("Choosing new speed factor % for vehicle '%' to match departure speed % (max %)."),
789 toString(v.getChosenSpeedFactor()), pars.id, pars.departSpeed, vMax);
790 }
791 } else {
792 return false;
793 }
794 }
795 }
796 }
797 }
798 return true;
799}
800
801
802bool
803MSEdge::insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly, const bool forceCheck) const {
804 // when vaporizing, no vehicles are inserted, but checking needs to be successful to trigger removal
806 || v.getRouteValidity(true, checkOnly) != MSBaseVehicle::ROUTE_VALID) {
807 return checkOnly;
808 }
809 const SUMOVehicleParameter& pars = v.getParameter();
810 if (!validateDepartSpeed(v)) {
812 throw ProcessError(TLF("Departure speed for vehicle '%' is too high for the departure edge '%', time=%.",
813 pars.id, getID(), time2string(time)));
814 } else {
815 WRITE_WARNINGF(TL("Departure speed for vehicle '%' is too high for the departure edge '%', time=%."),
816 pars.id, getID(), time2string(time));
817 }
818 }
820 if (!forceCheck && myLastFailedInsertionTime == time) {
821 return false;
822 }
823 double pos = 0.0;
824 switch (pars.departPosProcedure) {
826 if (pars.departPos >= 0.) {
827 pos = pars.departPos;
828 } else {
829 pos = pars.departPos + getLength();
830 }
831 if (pos < 0 || pos > getLength()) {
832 WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
833 pos, v.getID(), time2string(time));
834 pos = getLength();
835 }
836 break;
840 break;
841 default:
842 break;
843 }
844 bool result = false;
845 MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this, pos);
846 MEVehicle* veh = static_cast<MEVehicle*>(&v);
847 int qIdx;
849 while (segment != nullptr && !result) {
850 if (checkOnly) {
851 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
852 } else {
853 result = segment->initialise(veh, time);
854 }
855 segment = segment->getNextSegment();
856 }
857 } else {
858 if (checkOnly) {
859 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
860 } else {
861 result = segment->initialise(veh, time);
862 }
863 }
864 return result;
865 }
866 if (checkOnly) {
870 }
871 switch (dld) {
875 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
876 if (insertionLane == nullptr) {
877 WRITE_WARNINGF(TL("Could not insert vehicle '%' on any lane of edge '%', time=%."),
878 v.getID(), getID(), time2string(time));
879 return false;
880 }
881 const double occupancy = insertionLane->getBruttoOccupancy();
882 return (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
884 }
885 default:
886 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
887 const double occupancy = (*i)->getBruttoOccupancy();
888 if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
890 return true;
891 }
892 }
893 }
894 return false;
895 }
896 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
897 if (insertionLane == nullptr) {
898 return false;
899 }
900
901 if (!forceCheck) {
902 if (myLastFailedInsertionTime == time) {
903 if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
904 // A vehicle was already rejected for the proposed insertionLane in this timestep
905 return false;
906 }
907 } else {
908 // last rejection occurred in a previous timestep, clear cache
910 }
911 }
912
913 bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
914
915 if (!success) {
916 // constraints may enforce explicit re-ordering so we need to try other vehicles after failure
917 if (!insertionLane->hasParameter("insertionOrder" + v.getID())) {
918 myFailedInsertionMemory.insert(insertionLane->getIndex());
919 }
920 }
921 return success;
922}
923
924
925void
927 if (myLaneChanger != nullptr) {
929 }
930}
931
932
933const MSEdge*
934MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
935 //@todo to be optimized
936 for (const MSLane* const l : *myLanes) {
937 for (const MSLink* const link : l->getLinkCont()) {
938 if (&link->getLane()->getEdge() == followerAfterInternal) {
939 if (link->getViaLane() != nullptr) {
940 if (link->getViaLane()->allowsVehicleClass(vClass)) {
941 return &link->getViaLane()->getEdge();
942 } else {
943 continue;
944 }
945 } else {
946 return nullptr; // network without internal links
947 }
948 }
949 }
950 }
951 return nullptr;
952}
953
954
955double
956MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
957 assert(followerAfterInternal != 0);
958 assert(!followerAfterInternal->isInternal());
959 double dist = 0.;
960 const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal, vClass);
961 // Take into account non-internal lengths until next non-internal edge
962 while (edge != nullptr && edge->isInternal()) {
963 dist += edge->getLength();
964 edge = edge->getInternalFollowingEdge(followerAfterInternal, vClass);
965 }
966 return dist;
967}
968
969
970const MSEdge*
972 const MSEdge* result = this;
973 while (result->isInternal() && MSGlobals::gUsingInternalLanes) {
974 assert(result->getPredecessors().size() == 1);
975 result = result->getPredecessors().front();
976 }
977 return result;
978}
979
980const MSEdge*
982 const MSEdge* result = this;
983 while (result->isInternal()) {
984 assert(result->getSuccessors().size() == 1);
985 result = result->getSuccessors().front();
986 }
987 return result;
988}
989
990double
992 double v = 0;
993 double totalNumVehs = 0;
995 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
996 const int numVehs = segment->getCarNumber();
997 if (numVehs > 0) {
998 v += numVehs * segment->getMeanSpeed();
999 totalNumVehs += numVehs;
1000 }
1001 }
1002 if (totalNumVehs == 0) {
1003 return getLength() / myEmptyTraveltime; // may include tls-penalty
1004 }
1005 } else {
1006 for (const MSLane* const lane : *myLanes) {
1007 int numVehs = lane->getVehicleNumber();
1008 if (numVehs == 0) {
1009 // take speed limit but with lowest possible weight
1010 numVehs = 1;
1011 }
1012 v += numVehs * lane->getMeanSpeed();
1013 totalNumVehs += numVehs;
1014 }
1015 if (myBidiEdge != nullptr) {
1016 for (const MSLane* const lane : myBidiEdge->getLanes()) {
1017 if (lane->getVehicleNumber() > 0) {
1018 // do not route across edges which are already occupied in reverse direction
1019 return 0;
1020 }
1021 }
1022 }
1023 if (totalNumVehs == 0) {
1024 return getSpeedLimit();
1025 }
1026 }
1027 return v / totalNumVehs;
1028}
1029
1030
1031double
1033 double f = 0.;
1034 for (const MSLane* const lane : *myLanes) {
1035 f += lane->getFrictionCoefficient();
1036 }
1037 if (!myLanes->empty()) {
1038 return f / (double)myLanes->size();
1039 }
1040 return 1.;
1041}
1042
1043
1044double
1047 // no separate bicycle speeds in meso
1048 return getMeanSpeed();
1049 }
1050 double v = 0;
1051 double totalNumVehs = 0;
1052 for (const MSLane* const lane : *myLanes) {
1053 const int numVehs = lane->getVehicleNumber();
1054 v += numVehs * lane->getMeanSpeedBike();
1055 totalNumVehs += numVehs;
1056 }
1057 if (totalNumVehs == 0) {
1058 return getSpeedLimit();
1059 }
1060 return v / totalNumVehs;
1061}
1062
1063
1064double
1065MSEdge::getCurrentTravelTime(double minSpeed) const {
1066 assert(minSpeed > 0);
1067 if (!myAmDelayed) {
1068 return myEmptyTraveltime;
1069 }
1070 return getLength() / MAX2(minSpeed, getMeanSpeed());
1071}
1072
1073
1074double
1076 return MSRoutingEngine::getAssumedSpeed(this, nullptr);
1077}
1078
1079
1080bool
1081MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
1082 const DictType::iterator it = myDict.lower_bound(id);
1083 if (it == myDict.end() || it->first != id) {
1084 // id not in myDict
1085 myDict.emplace_hint(it, id, ptr);
1086 while (ptr->getNumericalID() >= (int)myEdges.size()) {
1087 myEdges.push_back(nullptr);
1088 }
1089 myEdges[ptr->getNumericalID()] = ptr;
1090 return true;
1091 }
1092 return false;
1093}
1094
1095
1096MSEdge*
1097MSEdge::dictionary(const std::string& id) {
1098 const DictType::iterator it = myDict.find(id);
1099 if (it == myDict.end()) {
1100 return nullptr;
1101 }
1102 return it->second;
1103}
1104
1105
1106MSEdge*
1107MSEdge::dictionaryHint(const std::string& id, const int startIdx) {
1108 // this method is mainly useful when parsing connections from the net.xml which are sorted by "from" id
1109 if (myEdges[startIdx] != nullptr && myEdges[startIdx]->getID() == id) {
1110 return myEdges[startIdx];
1111 }
1112 if (startIdx + 1 < (int)myEdges.size() && myEdges[startIdx + 1] != nullptr && myEdges[startIdx + 1]->getID() == id) {
1113 return myEdges[startIdx + 1];
1114 }
1115 return dictionary(id);
1116}
1117
1118
1119const MSEdgeVector&
1121 return myEdges;
1122}
1123
1124
1125void
1127 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1128 delete (*i).second;
1129 }
1130 myDict.clear();
1131 myEdges.clear();
1132}
1133
1134
1135void
1136MSEdge::insertIDs(std::vector<std::string>& into) {
1137 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1138 into.push_back((*i).first);
1139 }
1140}
1141
1142
1143void
1144MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
1145 const std::string& rid) {
1146 StringTokenizer st(desc);
1147 parseEdgesList(st.getVector(), into, rid);
1148}
1149
1150
1151void
1152MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
1153 const std::string& rid) {
1154 for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1155 const MSEdge* edge = MSEdge::dictionary(*i);
1156 // check whether the edge exists
1157 if (edge == nullptr) {
1158 throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
1159 + "\n The route can not be build.");
1160 }
1161 into.push_back(edge);
1162 }
1163}
1164
1165
1166double
1167MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
1168 assert(this != other);
1169 if (doBoundaryEstimate) {
1170 return myBoundary.distanceTo2D(other->myBoundary);
1171 }
1172 if (isTazConnector()) {
1173 if (other->isTazConnector()) {
1174 return myBoundary.distanceTo2D(other->myBoundary);
1175 }
1176 return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
1177 }
1178 if (other->isTazConnector()) {
1179 return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
1180 }
1181 return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
1182}
1183
1184
1185const Position
1187 return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
1188}
1189
1190
1191double
1193 // @note lanes might have different maximum speeds in theory
1194 return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
1195}
1196
1197
1198double
1200 return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
1201}
1202
1203double
1205 // @note lanes might have different maximum speeds in theory
1206 return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
1207}
1208
1209
1210void
1211MSEdge::setMaxSpeed(const double val, const bool modified, const double jamThreshold) {
1212 assert(val >= 0);
1213 if (myLanes != nullptr) {
1214 for (MSLane* const lane : *myLanes) {
1215 lane->setMaxSpeed(val, modified, jamThreshold);
1216 }
1217 }
1218}
1219
1220
1221void
1223 if (t->isPerson()) {
1224 myPersons.insert(t);
1225 } else {
1226 myContainers.insert(t);
1227 }
1228}
1229
1230void
1232 std::set<MSTransportable*, ComparatorNumericalIdLess>& tc = t->isPerson() ? myPersons : myContainers;
1233 auto it = tc.find(t);
1234 if (it != tc.end()) {
1235 tc.erase(it);
1236 }
1237}
1238
1239std::vector<MSTransportable*>
1240MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
1241 std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
1242 if (includeRiding) {
1243 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1244 const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
1245 for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
1246 const std::vector<MSTransportable*>& persons = (*j)->getPersons();
1247 result.insert(result.end(), persons.begin(), persons.end());
1248 }
1249 (*i)->releaseVehicles();
1250 }
1251 }
1252 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1253 return result;
1254}
1255
1256
1257std::vector<MSTransportable*>
1258MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
1259 std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
1260 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1261 return result;
1262}
1263
1264
1265int
1267 const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
1268 const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
1269 if (pos1 != pos2) {
1270 return pos1 < pos2;
1271 }
1272 return c1->getID() < c2->getID();
1273}
1274
1275
1276void
1278 mySuccessors.push_back(edge);
1279 myViaSuccessors.push_back(std::make_pair(edge, via));
1280 if (isTazConnector() && edge->getFromJunction() != nullptr) {
1282 }
1283
1284 edge->myPredecessors.push_back(this);
1285 if (edge->isTazConnector() && getToJunction() != nullptr) {
1286 edge->myBoundary.add(getToJunction()->getPosition());
1287 }
1288}
1289
1290
1291const MSEdgeVector&
1293 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1294 return mySuccessors;
1295 }
1296#ifdef HAVE_FOX
1297 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1298#endif
1299 std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1300 if (i == myClassesSuccessorMap.end()) {
1301 // instantiate vector
1302 myClassesSuccessorMap[vClass];
1303 i = myClassesSuccessorMap.find(vClass);
1304 // this vClass is requested for the first time. rebuild all successors
1305 for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1306 if ((*it)->isTazConnector()) {
1307 i->second.push_back(*it);
1308 } else {
1309 const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1310 if (allowed != nullptr && allowed->size() > 0) {
1311 i->second.push_back(*it);
1312 }
1313 }
1314 }
1315 }
1316 // can use cached value
1317 return i->second;
1318}
1319
1320
1322MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
1323 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1324 return myViaSuccessors;
1325 }
1326#ifdef HAVE_FOX
1327 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1328#endif
1329 auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
1330 auto i = viaMap.find(vClass);
1331 if (i != viaMap.end()) {
1332 // can use cached value
1333 return i->second;
1334 }
1335 // instantiate vector
1336 MSConstEdgePairVector& result = viaMap[vClass];
1337 // this vClass is requested for the first time. rebuild all successors
1338 for (const auto& viaPair : myViaSuccessors) {
1339 if (viaPair.first->isTazConnector()) {
1340 result.push_back(viaPair);
1341 } else {
1342 const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
1343 if (allowed != nullptr && allowed->size() > 0) {
1344 result.push_back(viaPair);
1345 }
1346 }
1347 }
1348 return result;
1349}
1350
1351
1352void
1354 myFromJunction = from;
1355 myToJunction = to;
1356 if (!isTazConnector()) {
1357 myBoundary.add(from->getPosition());
1358 myBoundary.add(to->getPosition());
1359 }
1360}
1361
1362
1363bool
1365 return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1366 // do not change on curved internal lanes
1367 (!isInternal()
1369 && myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LinkDirection::STRAIGHT)));
1370}
1371
1372
1373const MSEdge*
1375 if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1376 return &(myLanes->back()->getOpposite()->getEdge());
1377 } else {
1378 return nullptr;
1379 }
1380}
1381
1382
1383bool
1385 for (const MSLane* const l : *myLanes) {
1386 for (const MSLink* const link : l->getLinkCont()) {
1387 if (!link->havePriority()) {
1388 return true;
1389 }
1390 }
1391 }
1392 return false;
1393}
1394
1395bool
1397 if (myLanes->size() == 1) {
1398 return false;
1399 }
1400 for (const MSLane* const l : *myLanes) {
1401 if (l->getIndex() <= index && !l->allowsChangingRight(svc) && l->getIndex() > 0) {
1402 return true;
1403 } else if (l->getIndex() >= index && !l->allowsChangingLeft(svc) && l->getIndex() < (int)(myLanes->size() - 1)) {
1404 return true;
1405 }
1406 }
1407 return false;
1408}
1409
1410void
1411MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1412 if (bidiID != "") {
1413 myBidiEdge = dictionary(bidiID);
1414 if (myBidiEdge == nullptr) {
1415 WRITE_ERRORF(TL("Bidi-edge '%' does not exist"), bidiID);
1416 }
1417 setBidiLanes();
1418 return;
1419 }
1421 return;
1422 }
1423 // legacy networks (no bidi attribute)
1425 for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1426 if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1427 if (myBidiEdge != nullptr && isSuperposable(*it)) {
1428 WRITE_WARNINGF(TL("Ambiguous superposable edges between junction '%' and '%'."), myToJunction->getID(), myFromJunction->getID());
1429 break;
1430 }
1431 if (isSuperposable(*it)) {
1432 myBidiEdge = *it;
1433 setBidiLanes();
1434 }
1435 }
1436 }
1437}
1438
1439
1440void
1442 assert(myBidiEdge != nullptr);
1443 if (getNumLanes() == 1 && myBidiEdge->getNumLanes() == 1) {
1444 // the other way round is set when this method runs for the bidiEdge
1445 getLanes()[0]->setBidiLane(myBidiEdge->getLanes()[0]);
1446 } else {
1447 // find lanes with matching reversed shapes
1448 int numBidiLanes = 0;
1449 for (MSLane* l1 : *myLanes) {
1450 for (MSLane* l2 : *myBidiEdge->myLanes) {
1451 if (l1->getShape().reverse().almostSame(l2->getShape(), POSITION_EPS * 2)) {
1452 l1->setBidiLane(l2);
1453 numBidiLanes++;
1454 }
1455 }
1456 }
1457 // warn only once for each pair
1458 if (numBidiLanes == 0 && getNumericalID() < myBidiEdge->getNumericalID()) {
1459 WRITE_WARNINGF(TL("Edge '%' and bidi edge '%' have no matching bidi lanes"), getID(), myBidiEdge->getID());
1460 }
1461 }
1462}
1463
1464
1465bool
1467 if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1468 return false;
1469 }
1470 std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1471 std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1472 do {
1473 if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1474 return false;
1475 }
1476 it1++;
1477 it2++;
1478 } while (it1 != myLanes->end());
1479
1480 return true;
1481}
1482
1483
1484void
1486#ifdef HAVE_FOX
1487 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1488#endif
1489 myWaiting.push_back(vehicle);
1490}
1491
1492
1493void
1494MSEdge::removeWaiting(const SUMOVehicle* vehicle) const {
1495#ifdef HAVE_FOX
1496 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1497#endif
1498 std::vector<SUMOVehicle*>::iterator it = std::find(myWaiting.begin(), myWaiting.end(), vehicle);
1499 if (it != myWaiting.end()) {
1500 myWaiting.erase(it);
1501 }
1502}
1503
1504
1506MSEdge::getWaitingVehicle(MSTransportable* transportable, const double position) const {
1507#ifdef HAVE_FOX
1508 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1509#endif
1510 for (SUMOVehicle* const vehicle : myWaiting) {
1511 if (transportable->isWaitingFor(vehicle)) {
1512 if (vehicle->isStoppedInRange(position, MSGlobals::gStopTolerance) ||
1513 (!vehicle->hasDeparted() &&
1514 (vehicle->getParameter().departProcedure == DepartDefinition::TRIGGERED ||
1515 vehicle->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED))) {
1516 return vehicle;
1517 }
1518 if (!vehicle->isLineStop(position) && vehicle->allowsBoarding(transportable)) {
1519 WRITE_WARNING((transportable->isPerson() ? "Person '" : "Container '")
1520 + transportable->getID() + "' at edge '" + getID() + "' position " + toString(position) + " cannot use waiting vehicle '"
1521 + vehicle->getID() + "' at position " + toString(vehicle->getPositionOnLane()) + " because it is too far away.");
1522 }
1523 }
1524 }
1525 return nullptr;
1526}
1527
1528std::vector<const SUMOVehicle*>
1530 std::vector<const SUMOVehicle*> result;
1532 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1533 std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
1534 result.insert(result.end(), segmentVehs.begin(), segmentVehs.end());
1535 }
1536 } else {
1537 for (MSLane* lane : getLanes()) {
1538 for (auto veh : lane->getVehiclesSecure()) {
1539 result.push_back(veh);
1540 }
1541 lane->releaseVehicles();
1542 }
1543 }
1544 return result;
1545}
1546
1547int
1549 int result = 0;
1550 SVCPermissions filter = SVCAll;
1552 filter = ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1553 } else if ((myCombinedPermissions & (SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1554 // filter out green verge
1555 filter = (SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1556 }
1557 for (const MSLane* const l : *myLanes) {
1558 if ((l->getPermissions() & filter) != 0) {
1559 result++;
1560 }
1561 }
1562 return result;
1563}
1564
1565int
1567 return (int)getVehicles().size();
1568}
1569
1570
1571bool
1575 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1576 if (segment->getCarNumber() > 0) {
1577 return false;
1578 }
1579 }
1580 } else {
1581 for (MSLane* lane : getLanes()) {
1582 if (lane->getVehicleNumber() > 0) {
1583 return false;
1584 }
1585 }
1586 }
1587 return true;
1588}
1589
1590
1591double
1593 double wtime = 0;
1595 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1596 wtime += segment->getWaitingSeconds();
1597 }
1598 } else {
1599 for (MSLane* lane : getLanes()) {
1600 wtime += lane->getWaitingSeconds();
1601 }
1602 }
1603 return wtime;
1604}
1605
1606
1607double
1609 if (myLanes->size() == 0) {
1610 return 0;
1611 }
1614 double sum = 0;
1615 for (const SUMOVehicle* veh : getVehicles()) {
1616 sum += dynamic_cast<const MEVehicle*>(veh)->getVehicleType().getLength();
1617 }
1618 return sum / (myLength * (double)myLanes->size());
1619 } else {
1620 double sum = 0;
1621 for (auto lane : getLanes()) {
1622 sum += lane->getNettoOccupancy();
1623 }
1624 return sum / (double)myLanes->size();
1625 }
1626}
1627
1628
1629double
1631 if (myLanes->size() == 0) {
1632 return 0;
1633 }
1634 double flow = 0;
1635 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1636 flow += (double) segment->getCarNumber() * segment->getMeanSpeed();
1637 }
1638 return 3600 * flow / (*myLanes)[0]->getLength();
1639}
1640
1641
1642double
1644 if (myLanes->size() == 0) {
1645 return 0;
1646 }
1647 double occ = 0;
1648 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1649 occ += segment->getBruttoOccupancy();
1650 }
1651 return occ / (*myLanes)[0]->getLength() / (double)(myLanes->size());
1652}
1653
1654double
1655MSEdge::getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double /*time*/) {
1656 return edge->getLength() / MIN2(MSRoutingEngine::getAssumedSpeed(edge, veh), veh->getMaxSpeed());
1657}
1658
1659
1660void
1662 // @note must be called after closeBuilding() to ensure successors and
1663 // predecessors are set
1664 if (isInternal() && myEdgeType == "") {
1665 const std::string typeBefore = getNormalBefore()->getEdgeType();
1666 if (typeBefore != "") {
1667 const std::string typeAfter = getNormalSuccessor()->getEdgeType();
1668 if (typeBefore == typeAfter) {
1669 myEdgeType = typeBefore;
1670 } else if (typeAfter != "") {
1671 MSNet* net = MSNet::getInstance();
1672 auto resBefore = net->getRestrictions(typeBefore);
1673 auto resAfter = net->getRestrictions(typeAfter);
1674 if (resBefore != nullptr && resAfter != nullptr) {
1675 // create new restrictions for this type-combination
1676 myEdgeType = typeBefore + "|" + typeAfter;
1677 if (net->getRestrictions(myEdgeType) == nullptr) {
1678 for (const auto& item : *resBefore) {
1679 const SUMOVehicleClass svc = item.first;
1680 const double speed = item.second;
1681 const auto it = (*resAfter).find(svc);
1682 if (it != (*resAfter).end()) {
1683 const double speed2 = it->second;
1684 const double newSpeed = (MSNet::getInstance()->hasJunctionHigherSpeeds()
1685 ? MAX2(speed, speed2) : (speed + speed2) / 2);
1686 net->addRestriction(myEdgeType, svc, newSpeed);
1687 }
1688 }
1689 }
1690 }
1691 }
1692 }
1693 }
1694}
1695
1696
1697double
1698MSEdge::getDistanceAt(double pos) const {
1699 // negative values of myDistances indicate descending kilometrage
1700 return fabs(myDistance + pos);
1701}
1702
1703
1704bool
1708
1709
1710std::pair<double, SUMOTime>
1711MSEdge::getLastBlocked(int index) const {
1712 if (myLaneChanger != nullptr) {
1713 return myLaneChanger->getLastBlocked(index);
1714 }
1715 return std::make_pair(-1, -1);
1716}
1717
1718
1719double
1723
1724
1725void
1727 myPersons.clear();
1728 myContainers.clear();
1729 myWaiting.clear();
1730}
1731
1732
1733const std::map<const MEVehicle*, std::pair<double, int> >&
1735 assert(MSGlobals::gUseMesoSim);
1736 if (myLastCacheUpdate < SIMSTEP) {
1738 myCachedMesoPos.clear();
1739 int laneIndex = 0;
1740 const double now = SIMTIME;
1741 for (std::vector<MSLane*>::const_iterator msl = myLanes->begin(); msl != myLanes->end(); ++msl, ++laneIndex) {
1742 // go through the vehicles
1743 double segmentOffset = 0; // offset at start of current segment
1744 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this);
1745 segment != nullptr; segment = segment->getNextSegment()) {
1746 const double length = segment->getLength();
1747 if (laneIndex < segment->numQueues()) {
1748 // make a copy so we don't have to worry about synchronization
1749 std::vector<MEVehicle*> queue = segment->getQueue(laneIndex);
1750 const int queueSize = (int)queue.size();
1751 SUMOTime earliestExitTime = segment->getQueueBlockTime(laneIndex);
1752 int overlap = 0;
1753 double prevPos = std::numeric_limits<double>::max();
1754 for (int i = 0; i < queueSize; ++i) {
1755 const MEVehicle* const veh = queue[queueSize - i - 1];
1756 earliestExitTime = MAX2(earliestExitTime, veh->getEventTime());
1757 const double vehLength = veh->getVehicleType().getLengthWithGap();
1758 if (i > 0) {
1759 earliestExitTime += segment->getMinTauWithVehLength(vehLength, veh->getVehicleType().getCarFollowModel().getHeadwayTime());
1760 }
1761 const double entry = veh->getLastEntryTimeSeconds();
1762 const double pos = segmentOffset + length * (now - entry) / (STEPS2TIME(earliestExitTime) - entry);
1763 // check if we overlap with the previous vehicle such that the gui has the chance to add some lateral offset
1764 if (overlap == 0 && prevPos - pos < vehLength) {
1765 overlap = 1;
1766 } else {
1767 overlap = 0;
1768 }
1769 myCachedMesoPos[veh] = std::make_pair(pos, overlap);
1770 prevPos = pos;
1771 }
1772 }
1773 segmentOffset += length;
1774 }
1775 }
1776 }
1777 return myCachedMesoPos;
1778}
1779
1780
1781/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define BEST_LANE_LOOKAHEAD
Definition MSEdge.cpp:54
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
std::vector< std::pair< const MSEdge *, const MSEdge * > > MSConstEdgePairVector
Definition MSEdge.h:75
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:73
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SIMSTEP
Definition SUMOTime.h:64
#define SIMTIME
Definition SUMOTime.h:65
const SVCPermissions SVCAll
all VClasses are allowed
const SUMOVehicleClass SUMOVehicleClass_MAX
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_PRIVATE
private vehicles
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_WHEELCHAIR
@ SVC_PEDESTRIAN
pedestrian
DepartLaneDefinition
Possible ways to choose a lane on depart.
@ RANDOM
The lane is chosen randomly.
@ BEST_FREE
The least occupied lane from best lanes.
@ GIVEN
The lane is given.
@ ALLOWED_FREE
The least occupied lane from lanes which allow the continuation.
@ DEFAULT
No information given; use default.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
@ FREE
The least occupied lane is used.
@ BEST_PROB
The lane most likely according the speedFactor (from best lanes)
@ RANDOM
A random position is chosen.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ FREE
A free position is chosen.
@ BASE
Back-at-zero position.
@ LAST
Insert behind the last vehicle as close as possible to still allow the specified departSpeed....
@ RANDOM_FREE
If a fixed number of random choices fails, a free position is chosen.
@ GIVEN
The speed is given.
const long long int VEHPARS_SPEEDFACTOR_SET
@ SPLIT
The departure is triggered by a train split.
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ TURN
The link is a 180 degree turn.
@ STRAIGHT
The link is a straight direction.
SumoXMLEdgeFunc
Numbers representing special SUMO-XML-attribute values for representing edge functions used in netbui...
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
@ LINKSTATE_STOP
This is an uncontrolled, minor link, has to stop.
@ LINKSTATE_EQUAL
This is an uncontrolled, right-before-left link.
@ LINKSTATE_DEADEND
This is a dead end link.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
double distanceTo2D(const Position &p) const
returns the euclidean distance in the x-y-plane
Definition Boundary.cpp:262
double getParameter(const int index) const
Returns the nth parameter of this distribution.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp: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:243
A vehicle from the mesoscopic point of view.
Definition MEVehicle.h:42
double getLastEntryTimeSeconds() const
Returns the entry time for the current segment.
Definition MEVehicle.h:305
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves its current segment.
Definition MEVehicle.h:211
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.
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition MSCFModel.h:339
Sorts edges by their ids.
Definition MSEdge.h:891
Sorts transportables by their positions.
Definition MSEdge.h:906
int operator()(const MSTransportable *const c1, const MSTransportable *const c2) const
comparing operator
Definition MSEdge.cpp:1266
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1120
SUMOVehicle * getWaitingVehicle(MSTransportable *transportable, const double position) const
Definition MSEdge.cpp:1506
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:926
double getBruttoOccupancy() const
Definition MSEdge.cpp:1643
SVCPermissions myCombinedPermissions
The union of lane permissions for this edge.
Definition MSEdge.h:980
double getFlow() const
return flow based on meanSpead
Definition MSEdge.cpp:1630
Boundary myBoundary
The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start ...
Definition MSEdge.h:1064
double myWidth
Edge width [m].
Definition MSEdge.h:1010
AllowedLanesByTarget myAllowedTargets
From target edge to lanes allowed to be used to reach it.
Definition MSEdge.h:974
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:677
SUMOTime myLastFailedInsertionTime
The time of last insertion failure.
Definition MSEdge.h:938
std::set< MSTransportable *, ComparatorNumericalIdLess > myContainers
Containers on the edge.
Definition MSEdge.h:964
SUMOTime myLastCacheUpdate
time stamp of mesoscopic vehicle positions
Definition MSEdge.h:1073
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:1211
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:1711
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1126
void inferEdgeType()
Definition MSEdge.cpp:1661
void setJunctions(MSJunction *from, MSJunction *to)
Definition MSEdge.cpp:1353
double getMeanSpeedBike() const
get the mean speed of all bicycles on this edge
Definition MSEdge.cpp:1045
static MSEdgeVector myEdges
Static list of edges.
Definition MSEdge.h:1047
AllowedLanesCont myAllowed
Associative container from vehicle class to allowed-lanes.
Definition MSEdge.h:970
double myEmptyTraveltime
the traveltime on the empty edge (cached value for speedup)
Definition MSEdge.h:1016
bool myAmFringe
whether this edge is at the network fringe
Definition MSEdge.h:1028
static double getTravelTimeAggregated(const MSEdge *const edge, const SUMOVehicle *const veh, double time)
Definition MSEdge.cpp:1655
MSJunction * myToJunction
Definition MSEdge.h:958
void checkAndRegisterBiDirEdge(const std::string &bidiID="")
check and register the opposite superposable edge if any
Definition MSEdge.cpp:1411
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:1007
void clearState()
Remove all transportables before quick-loading state.
Definition MSEdge.cpp:1726
MSLane * getDepartLaneMeso(SUMOVehicle &veh) const
consider given departLane parameter (only for validating speeds)
Definition MSEdge.cpp:665
bool hasTransientPermissions() const
Definition MSEdge.cpp:1705
const MSEdge * myBidiEdge
the oppositing superposable edge
Definition MSEdge.h:1086
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:998
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:1548
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1374
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:1144
double getLengthGeometryFactor() const
return shape.length() / myLength
Definition MSEdge.cpp:1199
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:1277
friend class MSLaneChangerSublane
Definition MSEdge.h:87
std::vector< SUMOVehicle * > myWaiting
List of waiting vehicles.
Definition MSEdge.h:1067
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:981
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:956
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:1240
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:1466
bool validateDepartSpeed(SUMOVehicle &v) const
check whether the given departSpeed is valid for this edge
Definition MSEdge.cpp:766
double getDistanceTo(const MSEdge *other, const bool doBoundaryEstimate=false) const
optimistic air distance heuristic for use in routing
Definition MSEdge.cpp:1167
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:1107
MSLaneChanger * myLaneChanger
This member will do the lane-change.
Definition MSEdge.h:929
double getOccupancy() const
return mean occupancy on this edges lanes or segments
Definition MSEdge.cpp:1608
static int myDefaultDepartLane
Definition MSEdge.h:1052
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition MSEdge.cpp:1322
std::vector< MSTransportable * > getSortedContainers(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's containers sorted by pos.
Definition MSEdge.cpp:1258
const SumoXMLEdgeFunc myFunction
the purpose of the edge
Definition MSEdge.h:932
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:1192
SVCPermissions myOriginalCombinedPermissions
The original union of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:985
bool myAmDelayed
whether this edge had a vehicle with less than max speed on it
Definition MSEdge.h:1022
SVCPermissions myOriginalMinimumPermissions
The original intersection of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:983
std::map< SUMOVehicleClass, MSEdgeVector > myClassesSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1057
SUMOTime decVaporization(SUMOTime t)
Disables vaporization.
Definition MSEdge.cpp:540
MSEdgeVector myPredecessors
The preceeding edges.
Definition MSEdge.h:954
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:1396
void rebuildAllowedTargets(const bool updateVehicles=true)
Definition MSEdge.cpp:384
static SVCPermissions myMesoIgnoredVClasses
Definition MSEdge.h:1049
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:988
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:1364
std::set< int > myFailedInsertionMemory
A cache for the rejected insertion attempts. Used to assure that no further insertion attempts are ma...
Definition MSEdge.h:943
const MSJunction * getFromJunction() const
Definition MSEdge.h:423
double getMeanSpeed() const
get the mean speed
Definition MSEdge.cpp:991
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition MSEdge.h:1042
std::set< MSTransportable *, ComparatorNumericalIdLess > myPersons
Persons on the edge for drawing and pushbutton.
Definition MSEdge.h:961
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:1698
const std::string & getRoutingType() const
Returns the type of the edge.
Definition MSEdge.h:326
MSConstEdgePairVector myViaSuccessors
Definition MSEdge.h:951
std::map< const MEVehicle *, std::pair< double, int > > myCachedMesoPos
Mesoscopic vehicle positions.
Definition MSEdge.h:1070
void setBidiLanes()
Definition MSEdge.cpp:1441
MSEdgeVector mySuccessors
The succeeding edges.
Definition MSEdge.h:949
static DepartLaneDefinition myDefaultDepartLaneDefinition
Definition MSEdge.h:1051
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:1065
std::map< SUMOVehicleClass, MSConstEdgePairVector > myOrigClassesViaSuccessorMap
Definition MSEdge.h:1061
AllowedLanesByTarget myOrigAllowedTargets
Definition MSEdge.h:975
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:803
static const Position getStopPosition(const SUMOVehicleParameter::Stop &stop)
return the coordinates of the center of the given stop
Definition MSEdge.cpp:1186
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1485
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:1089
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:1081
std::vector< const SUMOVehicle * > getVehicles() const
return vehicles on this edges lanes or segments
Definition MSEdge.cpp:1529
static void insertIDs(std::vector< std::string > &into)
Inserts IDs of all known edges into the given vector.
Definition MSEdge.cpp:1136
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1204
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition MSEdge.cpp:533
MSJunction * myFromJunction
the junctions for this edge
Definition MSEdge.h:957
double getMeanFriction() const
get the mean friction over the lanes
Definition MSEdge.cpp:1032
std::map< std::string, MSEdge * > DictType
definition of the static dictionary type
Definition MSEdge.h:1037
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1384
double getPreference(const SUMOVTypeParameter &pars) const
Definition MSEdge.cpp:1720
std::map< SUMOVehicleClass, MSConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1060
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:971
int getVehicleNumber() const
return total number of vehicles on this edges lanes or segments
Definition MSEdge.cpp:1566
const std::map< const MEVehicle *, std::pair< double, int > > & getMesoPositions() const
Definition MSEdge.cpp:1734
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:418
virtual void removeTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1231
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:1572
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition MSEdge.cpp:934
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:1075
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:1494
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false, int routingMode=0) const
Definition MSEdge.cpp:755
std::vector< double > mySublaneSides
the right side for each sublane on this edge
Definition MSEdge.h:1031
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1292
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:926
AllowedLanesCont myOrigAllowed
Definition MSEdge.h:971
double getWaitingSeconds() const
return accumated waiting time for all vehicles on this edges lanes or segments
Definition MSEdge.cpp:1592
int myVaporizationRequests
Vaporizer counter.
Definition MSEdge.h:935
double myTimePenalty
flat penalty when computing traveltime
Definition MSEdge.h:1019
SVCPermissions myMinimumPermissions
The intersection of lane permissions for this edge.
Definition MSEdge.h:978
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:1222
RailEdge< MSEdge, SUMOVehicle > * myRailwayRoutingEdge
Definition MSEdge.h:1090
double myLength
the length of the edge (cached value for speedup)
Definition MSEdge.h:1013
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition MSGlobals.h:171
static bool gUseMesoSim
Definition MSGlobals.h:106
static double gMinorPenalty
(minimum) time penalty for passing a minor link when routing
Definition MSGlobals.h:158
static bool gCheckRoutes
Definition MSGlobals.h:91
static double gTLSPenalty
scaled (minimum) time penalty for passing a tls link when routing
Definition MSGlobals.h:160
static double gTurnaroundPenalty
(minimum) time penalty for passing a turnaround link when routing
Definition MSGlobals.h:162
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static double gLateralResolution
Definition MSGlobals.h:100
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:149
static SUMOTime gLaneChangeDuration
Definition MSGlobals.h:97
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
static int gNumThreads
how many threads to use
Definition MSGlobals.h:152
The base class for an intersection.
Definition MSJunction.h:58
const ConstMSEdgeVector & getOutgoing() const
Definition MSJunction.h:114
const Position & getPosition(bool secondaryShape=false) const
const ConstMSEdgeVector & getIncoming() const
Definition MSJunction.h:108
Performs lane changing of vehicles.
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
std::pair< double, SUMOTime > getLastBlocked(int index) const
retrieve properties of a blocked vehicle that wants to chane to the lane with the given index
Representation of a lane in the micro simulation.
Definition MSLane.h:84
bool insertVehicle(MSVehicle &v)
Tries to insert the given vehicle.
Definition MSLane.cpp:690
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:3433
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2520
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4419
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:379
bool hasJunctionHigherSpeeds() const
return whether the network was built with higher junction speeds
Definition MSNet.h:816
const std::map< SUMOVehicleClass, double > * getRestrictions(const std::string &id) const
Returns the restrictions for an edge type If no restrictions are present, 0 is returned.
Definition MSNet.cpp:369
void addRestriction(const std::string &id, const SUMOVehicleClass svc, const double speed)
Adds a restriction for an edge type.
Definition MSNet.cpp:363
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:427
int size() const
Returns the number of edges to pass.
Definition MSRoute.cpp:85
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition MSRoute.cpp:73
static double getAssumedSpeed(const MSEdge *edge, const SUMOVehicle *veh)
return current travel speed assumption
virtual double getEdgePos(SUMOTime now) const
Definition MSStage.cpp:83
MSStage * getCurrentStage() const
Return the current stage.
bool isPerson() const override
Whether it is a person.
bool isWaitingFor(const SUMOVehicle *vehicle) const
Whether the transportable waits for the given vehicle in the current step.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
The car-following model and parameter.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getDesiredMaxSpeed() const
Returns the vehicles's desired maximum speed.
const Distribution_Parameterized & getSpeedFactor() const
Returns this type's speed factor.
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
double getLength() const
Get vehicle's length [m].
double computeChosenSpeedDeviation(double speedFactorOverride, SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
Base class for objects which have an id.
Definition Named.h: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
double speedFactor
individual speedFactor (overriding distribution from vType)
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
std::string id
The vehicle's id.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
A scoped lock which only triggers on condition.
std::vector< std::string > getVector()
return vector of strings
edge type specific meso parameters
Definition MESegment.h:58