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