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