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