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 int priority,
73 double distance) :
74 Named(id), myNumericalID(numericalID), myLanes(nullptr),
75 myLaneChanger(nullptr), myFunction(function), myVaporizationRequests(0),
76 myLastFailedInsertionTime(-1),
77 myFromJunction(nullptr), myToJunction(nullptr),
78 myHaveTransientPermissions(false),
79 myOtherTazConnector(nullptr),
80 myStreetName(streetName),
81 myEdgeType(edgeType),
82 myPriority(priority),
83 myDistance(distance),
84 myWidth(0.),
85 myLength(0.),
86 myEmptyTraveltime(0.),
87 myTimePenalty(0.),
88 myAmDelayed(false),
89 myAmRoundabout(false),
90 myAmFringe(true),
91 myBidiEdge(nullptr)
92{ }
93
94
100
101
102void
103MSEdge::initialize(const std::vector<MSLane*>* lanes) {
104 assert(lanes != 0);
105 myLanes = std::shared_ptr<const std::vector<MSLane*> >(lanes);
108 }
109 for (MSLane* const lane : *lanes) {
110 lane->setRightSideOnEdge(myWidth, (int)mySublaneSides.size());
111 MSLeaderInfo ahead(lane->getWidth());
112 for (int j = 0; j < ahead.numSublanes(); ++j) {
114 }
115 myWidth += lane->getWidth();
116 }
117}
118
119
121 if (myLanes->empty()) {
122 return;
123 }
124 myLength = myLanes->front()->getLength();
125 myEmptyTraveltime = myLength / MAX2(getSpeedLimit(), NUMERICAL_EPS);
127 SUMOTime minorPenalty = 0;
128 bool haveTLSPenalty = MSGlobals::gTLSPenalty > 0;
131 minorPenalty = edgeType.minorPenalty;
132 haveTLSPenalty = edgeType.tlsPenalty > 0;
133 }
134 if (haveTLSPenalty || minorPenalty > 0) {
135 // add tls penalties to the minimum travel time
136 SUMOTime minPenalty = -1;
137 for (const MSLane* const l : *myLanes) {
138 for (const MSLink* const link : l->getLinkCont()) {
139 if (link->getLane()->isWalkingArea() && link->getLaneBefore()->isNormal()) {
140 continue;
141 }
142 SUMOTime linkPenalty = link->isTLSControlled() ? link->getMesoTLSPenalty() : (link->havePriority() ? 0 : minorPenalty);
143 if (minPenalty == -1) {
144 minPenalty = linkPenalty;
145 } else {
146 minPenalty = MIN2(minPenalty, linkPenalty);
147 }
148 }
149 }
150 if (minPenalty > 0) {
151 myEmptyTraveltime += STEPS2TIME(minPenalty);
152 myTimePenalty = STEPS2TIME(minPenalty);
153 }
154 }
155 } else if (isCrossing() && MSGlobals::gTLSPenalty > 0) {
156 // penalties are recorded for the entering link
157 for (const auto& ili : myLanes->front()->getIncomingLanes()) {
158 double penalty = STEPS2TIME(ili.viaLink->getMesoTLSPenalty());
159 if (!ili.viaLink->haveOffPriority()) {
160 penalty = MAX2(penalty, MSGlobals::gMinorPenalty);
161 }
162 if (penalty > 0) {
163 myEmptyTraveltime += penalty;
164 myTimePenalty = penalty;
165 }
166 }
168 const MSLink* link = myLanes->front()->getIncomingLanes()[0].viaLink;
169 if (!link->isTLSControlled() && !link->havePriority()) {
170 if (link->isTurnaround()) {
173 } else {
176 }
177 }
178 }
179}
180
181
182void
184 mySuccessors.clear();
185 myPredecessors.clear();
186 for (const MSEdge* edge : junction->getIncoming()) {
187 if (!edge->isInternal()) {
188 MSEdgeVector& succ = const_cast<MSEdgeVector&>(edge->mySuccessors);
189 MSConstEdgePairVector& succVia = const_cast<MSConstEdgePairVector&>(edge->myViaSuccessors);
190 MSEdgeVector& pred = const_cast<MSEdgeVector&>(edge->myPredecessors);
191 auto it = std::find(succ.begin(), succ.end(), this);
192 auto it2 = std::find(succVia.begin(), succVia.end(), std::make_pair(const_cast<const MSEdge*>(this), (const MSEdge*)nullptr));
193 auto it3 = std::find(pred.begin(), pred.end(), this);
194 if (it != succ.end()) {
195 succ.erase(it);
196 succVia.erase(it2);
197 }
198 if (it3 != pred.end()) {
199 pred.erase(it3);
200 }
201 }
202 }
203}
204
205void
207 for (MSLane* const lane : *myLanes) {
208 for (MSLink* const link : lane->getLinkCont()) {
209 link->initParallelLinks();
210 MSLane* const toL = link->getLane();
211 MSLane* const viaL = link->getViaLane();
212 if (toL != nullptr) {
213 MSEdge& to = toL->getEdge();
214 if (std::find(mySuccessors.begin(), mySuccessors.end(), &to) == mySuccessors.end()) {
215 mySuccessors.push_back(&to);
216 myViaSuccessors.push_back(std::make_pair(&to, (viaL == nullptr ? nullptr : &viaL->getEdge())));
217 }
218 if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
219 to.myPredecessors.push_back(this);
220 }
221 if (link->getDirection() != LinkDirection::TURN) {
222 myAmFringe = false;
223 }
224 }
225 if (viaL != nullptr) {
226 MSEdge& to = viaL->getEdge();
227 if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
228 to.myPredecessors.push_back(this);
229 }
230 }
231 }
232 lane->checkBufferType();
233 }
234 std::sort(mySuccessors.begin(), mySuccessors.end(), by_id_sorter());
236 recalcCache();
237
238 // extend lookup table for sublane model after all edges are read
239 if (myLanes->back()->getOpposite() != nullptr) {
240 MSLane* opposite = myLanes->back()->getOpposite();
241 MSLeaderInfo ahead(opposite->getWidth());
242 for (int j = 0; j < ahead.numSublanes(); ++j) {
244 }
245 }
246}
247
248
249void
252 if (!myLanes->empty()) {
254 }
255}
256
257
258void
260 if (!myLanes->empty()) {
261 const bool allowChanging = allowsLaneChanging();
263 // may always initiate sublane-change
265 myLaneChanger = new MSLaneChangerSublane(myLanes.get(), allowChanging);
266 }
267 } else {
269 myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
270 } else if (myLanes->size() > 1 || canChangeToOpposite()) {
271 myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
272 }
273 }
274 }
275}
276
277
278bool
281 // allow changing only if all links leading to this internal lane have priority
282 // or they are controlled by a traffic light
283 for (const MSLane* const lane : *myLanes) {
284 const MSLink* const link = lane->getLogicalPredecessorLane()->getLinkTo(lane);
285 assert(link != nullptr);
286 const LinkState state = link->getState();
287 if ((state == LINKSTATE_MINOR && lane->getBidiLane() == nullptr)
288 || state == LINKSTATE_EQUAL
289 || state == LINKSTATE_STOP
290 || state == LINKSTATE_ALLWAY_STOP
291 || state == LINKSTATE_DEADEND) {
292 return false;
293 }
294 }
295 }
296 return true;
297}
298
299
300void
301MSEdge::addToAllowed(const SVCPermissions permissions, std::shared_ptr<const std::vector<MSLane*> > allowedLanes, AllowedLanesCont& laneCont) const {
302 if (!allowedLanes->empty()) {
303 // recheck whether we had this list to save memory
304 for (auto& allowed : laneCont) {
305 if (*allowed.second == *allowedLanes) {
306 allowed.first |= permissions;
307 return;
308 }
309 }
310 laneCont.push_back(std::make_pair(permissions, allowedLanes));
311 }
312}
313
314
317 SVCPermissions ignored = myMesoIgnoredVClasses & ~ignoreIgnored;
318 return (p | ignored) == ignored ? 0 : p;
319}
320
321
322void
323MSEdge::rebuildAllowedLanes(const bool onInit, bool updateVehicles) {
324 // rebuild myMinimumPermissions and myCombinedPermissions
327 bool lanesChangedPermission = false;
328 for (MSLane* const lane : *myLanes) {
329 // same dedicated lanes are ignored in meso to avoid capacity errors.
330 // Here we have to make sure that vehicles which are set to depart on
331 // such lanes trigger an error.
332 SVCPermissions allow = getMesoPermissions(lane->getPermissions(), SVC_PEDESTRIAN);
333 myMinimumPermissions &= allow;
334 myCombinedPermissions |= allow;
335 lanesChangedPermission |= lane->hadPermissionChanges();
336 }
337 if (!onInit && !myHaveTransientPermissions && lanesChangedPermission) {
339 // backup original structures when first needed
343 }
344 // rebuild myAllowed
345 myAllowed.clear();
347 myAllowed.push_back(std::make_pair(SVC_IGNORING, myLanes));
348 for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
349 if ((myCombinedPermissions & vclass) == vclass) {
350 std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
351 for (MSLane* const lane : *myLanes) {
352 if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
353 allowedLanes->push_back(lane);
354 }
355 }
357 }
358 }
359 }
360 if (onInit) {
363 } else {
364 rebuildAllowedTargets(updateVehicles);
365 for (MSEdge* pred : myPredecessors) {
366 if (myHaveTransientPermissions && !pred->myHaveTransientPermissions) {
367 pred->myOrigAllowed = pred->myAllowed;
368 pred->myOrigAllowedTargets = pred->myAllowedTargets;
369 pred->myOrigClassesViaSuccessorMap = pred->myClassesViaSuccessorMap;
370 pred->myHaveTransientPermissions = true;
371 }
372 pred->rebuildAllowedTargets(updateVehicles);
373 }
375 for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*this); s != nullptr; s = s->getNextSegment()) {
376 s->updatePermissions();
377 }
378 }
379 }
380}
381
382
383void
384MSEdge::rebuildAllowedTargets(const bool updateVehicles) {
385 myAllowedTargets.clear();
386 for (const MSEdge* target : mySuccessors) {
387 bool universalMap = true; // whether the mapping for SVC_IGNORING is also valid for all vehicle classes
388 std::shared_ptr<std::vector<MSLane*> > allLanes = std::make_shared<std::vector<MSLane*> >();
389 // compute the mapping for SVC_IGNORING
390 for (MSLane* const lane : *myLanes) {
391 SVCPermissions combinedTargetPermissions = 0;
392 for (const MSLink* const link : lane->getLinkCont()) {
393 if (&link->getLane()->getEdge() == target) {
394 allLanes->push_back(lane);
395 combinedTargetPermissions |= link->getLane()->getPermissions();
396 if (link->getViaLane() != nullptr &&
397 ((lane->getPermissions() & link->getLane()->getPermissions()) != link->getViaLane()->getPermissions())) {
398 // custom connection permissions
399 universalMap = false;
400 }
401 }
402 }
403 if (combinedTargetPermissions == 0 || (lane->getPermissions() & combinedTargetPermissions) != lane->getPermissions()) {
404 universalMap = false;
405 }
406 }
407 if (universalMap) {
408 if (myAllowed.empty()) {
409 // we have no lane specific permissions
410 myAllowedTargets[target].push_back(std::make_pair(myMinimumPermissions, myLanes));
411 } else {
412 for (const auto& i : myAllowed) {
413 addToAllowed(i.first, i.second, myAllowedTargets[target]);
414 }
415 }
416 } else {
417 addToAllowed(SVC_IGNORING, allLanes, myAllowedTargets[target]);
418 // compute the vclass specific mapping
419 for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
420 if ((myCombinedPermissions & vclass) == vclass) {
421 std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
422 for (MSLane* const lane : *myLanes) {
423 if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
424 for (const MSLink* const link : lane->getLinkCont()) {
425 if (link->getLane()->allowsVehicleClass((SUMOVehicleClass)vclass) && &link->getLane()->getEdge() == target && (link->getViaLane() == nullptr || link->getViaLane()->allowsVehicleClass((SUMOVehicleClass)vclass))) {
426 allowedLanes->push_back(lane);
427 }
428 }
429 }
430 }
432 }
433 }
434 }
435 }
436 if (updateVehicles) {
437 for (const MSLane* const lane : *myLanes) {
438 const MSLane::VehCont& vehs = lane->getVehiclesSecure();
439 for (MSVehicle* veh : vehs) {
440 veh->updateBestLanes(true);
441 }
442 lane->releaseVehicles();
443 }
444 }
445 myClassesSuccessorMap.clear();
446}
447
448
449// ------------ Access to the edge's lanes
450MSLane*
451MSEdge::leftLane(const MSLane* const lane) const {
452 return parallelLane(lane, 1);
453}
454
455
456MSLane*
457MSEdge::rightLane(const MSLane* const lane) const {
458 return parallelLane(lane, -1);
459}
460
461
462MSLane*
463MSEdge::parallelLane(const MSLane* const lane, int offset, bool includeOpposite) const {
464 const int resultIndex = lane->getIndex() + offset;
465 if (resultIndex >= getNumLanes() && includeOpposite) {
466 const MSEdge* opposite = getOppositeEdge();
467 if (opposite != nullptr && resultIndex < getNumLanes() + opposite->getNumLanes()) {
468 return opposite->getLanes()[opposite->getNumLanes() + getNumLanes() - resultIndex - 1];
469 }
470 return nullptr;
471 } else if (resultIndex >= (int)myLanes->size() || resultIndex < 0) {
472 return nullptr;
473 } else {
474 return (*myLanes)[resultIndex];
475 }
476}
477
478
479const std::vector<MSLane*>*
480MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
481 const auto& targets = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowedTargets : myAllowedTargets;
482 AllowedLanesByTarget::const_iterator i = targets.find(&destination);
483 if (i != targets.end()) {
484 for (const auto& allowed : i->second) {
485 if ((allowed.first & vclass) == vclass) {
486 return allowed.second.get();
487 }
488 }
489 }
490 return nullptr;
491}
492
493
494const std::vector<MSLane*>*
496 if ((myMinimumPermissions & vclass) == vclass) {
497 return myLanes.get();
498 } else {
499 if ((myCombinedPermissions & vclass) == vclass) {
500 for (const auto& allowed : myAllowed) {
501 if ((allowed.first & vclass) == vclass) {
502 return allowed.second.get();
503 }
504 }
505 }
506 return nullptr;
507 }
508}
509
510
511// ------------
517
518
524
525
526MSLane*
527MSEdge::getFreeLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos) const {
528 if (allowed == nullptr) {
529 allowed = allowedLanes(vclass);
530 }
531 MSLane* res = nullptr;
532 if (allowed != nullptr) {
533 double largestGap = 0;
534 MSLane* resByGap = nullptr;
535 double leastOccupancy = std::numeric_limits<double>::max();
536 for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i) {
537 const double occupancy = (*i)->getBruttoOccupancy();
538 if (occupancy < leastOccupancy) {
539 res = (*i);
540 leastOccupancy = occupancy;
541 }
542 const MSVehicle* last = (*i)->getLastFullVehicle();
543 const double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
544 if (lastGap > largestGap) {
545 largestGap = lastGap;
546 resByGap = (*i);
547 }
548 }
549 if (resByGap != nullptr) {
550 //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
551 res = resByGap;
552 }
553 }
554 return res;
555}
556
557
558MSLane*
559MSEdge::getProbableLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos, double maxSpeed) const {
560 if (allowed == nullptr) {
561 allowed = allowedLanes(vclass);
562 }
563 MSLane* res = nullptr;
564 if (allowed != nullptr) {
565 double largestGap = 0;
566 double largestSpeed = 0;
567 MSLane* resByGap = nullptr;
568 double leastOccupancy = std::numeric_limits<double>::max();
569 int aIndex = 0;
570 for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i, aIndex++) {
571 const double occupancy = (*i)->getBruttoOccupancy();
572 if (occupancy < leastOccupancy) {
573 res = (*i);
574 leastOccupancy = occupancy;
575 }
576 const MSVehicle* last = (*i)->getLastFullVehicle();
577 double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
578 // never insert to the left of a vehicle with a larger speedFactor
579 if (lastGap > largestGap && maxSpeed >= largestSpeed) {
580 largestGap = lastGap;
581 resByGap = (*i);
582 }
583 if (last != nullptr) {
584 largestSpeed = MAX2(largestSpeed, getVehicleMaxSpeed(last));
585 }
586 }
587 if (resByGap != nullptr) {
588 //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
589 res = resByGap;
590 }
591 }
592 return res;
593}
594
595
596double
597MSEdge::getDepartPosBound(const MSVehicle& veh, bool upper) const {
598 const SUMOVehicleParameter& pars = veh.getParameter();
599 double pos = getLength();
600 // determine the position
601 switch (pars.departPosProcedure) {
603 pos = pars.departPos;
604 if (pos < 0.) {
605 pos += myLength;
606 }
607 break;
609 // could be any position on the edge
610 break;
612 // could be any position on the edge due to multiple random attempts
613 break;
615 // many candidate positions, upper bound could be computed exactly
616 // with much effort
617 break;
619 if (upper) {
620 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
621 MSVehicle* last = (*i)->getLastFullVehicle();
622 if (last != nullptr) {
623 pos = MIN2(pos, last->getPositionOnLane());
624 }
625 }
626 } else {
627 pos = 0;
628 }
629 break;
632 if (!upper) {
633 pos = 0;
634 }
635 break;
636 default:
637 pos = MIN2(pos, veh.getVehicleType().getLength());
638 break;
639 }
640 return pos;
641}
642
643MSLane*
646 if ((int) myLanes->size() <= veh.getParameter().departLane || !(*myLanes)[veh.getParameter().departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
647 return nullptr;
648 }
649 return (*myLanes)[veh.getParameter().departLane];
650 }
651 return (*myLanes)[0];
652}
653
654MSLane*
657 int departLane = veh.getParameter().departLane;
660 departLane = myDefaultDepartLane;
661 }
662 switch (dld) {
664 if ((int) myLanes->size() <= departLane || !(*myLanes)[departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
665 return nullptr;
666 }
667 return (*myLanes)[departLane];
671 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
673 if (veh.getRoute().size() == 1) {
674 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
675 } else {
677 }
680 veh.updateBestLanes(false, myLanes->front());
681 const std::vector<MSVehicle::LaneQ>& bl = veh.getBestLanes();
682 double bestLength = -1;
683 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
684 if ((*i).length > bestLength) {
685 bestLength = (*i).length;
686 }
687 }
688 // beyond a certain length, all lanes are suitable
689 // however, we still need to check departPos to avoid unsuitable insertion
690 // (this is only possible in some cases)
691 double departPos = 0;
692 if (bestLength > BEST_LANE_LOOKAHEAD) {
693 departPos = getDepartPosBound(veh);
694 bestLength = MIN2(bestLength - departPos, BEST_LANE_LOOKAHEAD);
695 }
696 std::vector<MSLane*>* bestLanes = new std::vector<MSLane*>();
697 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
698 if (((*i).length - departPos) >= bestLength) {
699 if (isInternal()) {
700 for (MSLane* lane : *myLanes) {
701 if (lane->getNormalSuccessorLane() == (*i).lane) {
702 bestLanes->push_back(lane);
703 }
704 }
705 } else {
706 bestLanes->push_back((*i).lane);
707 }
708 }
709 }
710 MSLane* ret = nullptr;
712 ret = getFreeLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
713 } else {
714 ret = getProbableLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false), getVehicleMaxSpeed(&veh));
715 }
716 delete bestLanes;
717 return ret;
718 }
722 default:
723 break;
724 }
725 if (!(*myLanes)[0]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
726 return nullptr;
727 }
728 return (*myLanes)[0];
729}
730
731
732MSLane*
733MSEdge::getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst) const {
734 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
735 if ((*i)->allowsVehicleClass(vClass)) {
736 return *i;
737 }
738 }
739 return defaultFirst && !myLanes->empty() ? myLanes->front() : nullptr;
740}
741
742
743bool
745 const SUMOVehicleParameter& pars = v.getParameter();
746 const MSVehicleType& type = v.getVehicleType();
748 // departSpeed could have been rounded down in the output
749 double vMax = getVehicleMaxSpeed(&v) + SPEED_EPS;
750 if (pars.departSpeed > vMax) {
751 // check departLane (getVehicleMaxSpeed checks lane 0)
752 MSLane* departLane = MSGlobals::gMesoNet ? getDepartLaneMeso(v) : getDepartLane(dynamic_cast<MSVehicle&>(v));
753 if (departLane != nullptr) {
754 vMax = departLane->getVehicleMaxSpeed(&v);
756 // speedFactor could have been rounded down in the output
757 vMax *= (1 + SPEED_EPS);
758 }
759 // additive term must come after multiplication!
760 vMax += SPEED_EPS;
761 if (pars.departSpeed > vMax) {
762 if (type.getSpeedFactor().getParameter(1) > 0.) {
764 if (v.getChosenSpeedFactor() > type.getSpeedFactor().getParameter(0) + 2 * type.getSpeedFactor().getParameter(1)) {
765 // only warn for significant deviation
766 WRITE_WARNINGF(TL("Choosing new speed factor % for vehicle '%' to match departure speed % (max %)."),
767 toString(v.getChosenSpeedFactor()), pars.id, pars.departSpeed, vMax);
768 }
769 } else {
770 return false;
771 }
772 }
773 }
774 }
775 }
776 return true;
777}
778
779
780bool
781MSEdge::insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly, const bool forceCheck) const {
782 // when vaporizing, no vehicles are inserted, but checking needs to be successful to trigger removal
784 || v.getRouteValidity(true, checkOnly) != MSBaseVehicle::ROUTE_VALID) {
785 return checkOnly;
786 }
787 const SUMOVehicleParameter& pars = v.getParameter();
788 if (!validateDepartSpeed(v)) {
789 const std::string errorMsg = "Departure speed for vehicle '" + pars.id + "' is too high for the departure edge '" + getID() + "'.";
791 throw ProcessError(errorMsg);
792 } else {
793 WRITE_WARNING(errorMsg);
794 }
795 }
797 if (!forceCheck && myLastFailedInsertionTime == time) {
798 return false;
799 }
800 double pos = 0.0;
801 switch (pars.departPosProcedure) {
803 if (pars.departPos >= 0.) {
804 pos = pars.departPos;
805 } else {
806 pos = pars.departPos + getLength();
807 }
808 if (pos < 0 || pos > getLength()) {
809 WRITE_WARNING("Invalid departPos " + toString(pos) + " given for vehicle '" +
810 v.getID() + "'. Inserting at lane end instead.");
811 pos = getLength();
812 }
813 break;
817 break;
818 default:
819 break;
820 }
821 bool result = false;
822 MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this, pos);
823 MEVehicle* veh = static_cast<MEVehicle*>(&v);
824 int qIdx;
826 while (segment != nullptr && !result) {
827 if (checkOnly) {
828 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
829 } else {
830 result = segment->initialise(veh, time);
831 }
832 segment = segment->getNextSegment();
833 }
834 } else {
835 if (checkOnly) {
836 result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
837 } else {
838 result = segment->initialise(veh, time);
839 }
840 }
841 return result;
842 }
843 if (checkOnly) {
844 switch (v.getParameter().departLaneProcedure) {
848 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
849 if (insertionLane == nullptr) {
850 WRITE_WARNING("could not insert vehicle '" + v.getID() + "' on any lane of edge '" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()));
851 return false;
852 }
853 const double occupancy = insertionLane->getBruttoOccupancy();
854 return (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
856 }
857 default:
858 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
859 const double occupancy = (*i)->getBruttoOccupancy();
860 if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
862 return true;
863 }
864 }
865 }
866 return false;
867 }
868 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
869 if (insertionLane == nullptr) {
870 return false;
871 }
872
873 if (!forceCheck) {
874 if (myLastFailedInsertionTime == time) {
875 if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
876 // A vehicle was already rejected for the proposed insertionLane in this timestep
877 return false;
878 }
879 } else {
880 // last rejection occurred in a previous timestep, clear cache
882 }
883 }
884
885 bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
886
887 if (!success) {
888 // constraints may enforce explicit re-ordering so we need to try other vehicles after failure
889 if (!insertionLane->hasParameter("insertionOrder" + v.getID())) {
890 myFailedInsertionMemory.insert(insertionLane->getIndex());
891 }
892 }
893 return success;
894}
895
896
897void
899 if (myLaneChanger != nullptr) {
901 }
902}
903
904
905const MSEdge*
906MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
907 //@todo to be optimized
908 for (const MSLane* const l : *myLanes) {
909 for (const MSLink* const link : l->getLinkCont()) {
910 if (&link->getLane()->getEdge() == followerAfterInternal) {
911 if (link->getViaLane() != nullptr) {
912 if (link->getViaLane()->allowsVehicleClass(vClass)) {
913 return &link->getViaLane()->getEdge();
914 } else {
915 continue;
916 }
917 } else {
918 return nullptr; // network without internal links
919 }
920 }
921 }
922 }
923 return nullptr;
924}
925
926
927double
928MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
929 assert(followerAfterInternal != 0);
930 assert(!followerAfterInternal->isInternal());
931 double dist = 0.;
932 const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal, vClass);
933 // Take into account non-internal lengths until next non-internal edge
934 while (edge != nullptr && edge->isInternal()) {
935 dist += edge->getLength();
936 edge = edge->getInternalFollowingEdge(followerAfterInternal, vClass);
937 }
938 return dist;
939}
940
941
942const MSEdge*
944 const MSEdge* result = this;
945 while (result->isInternal() && MSGlobals::gUsingInternalLanes) {
946 assert(result->getPredecessors().size() == 1);
947 result = result->getPredecessors().front();
948 }
949 return result;
950}
951
952const MSEdge*
954 const MSEdge* result = this;
955 while (result->isInternal()) {
956 assert(result->getSuccessors().size() == 1);
957 result = result->getSuccessors().front();
958 }
959 return result;
960}
961
962double
964 double v = 0;
965 double totalNumVehs = 0;
967 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
968 const int numVehs = segment->getCarNumber();
969 if (numVehs > 0) {
970 v += numVehs * segment->getMeanSpeed();
971 totalNumVehs += numVehs;
972 }
973 }
974 if (totalNumVehs == 0) {
975 return getLength() / myEmptyTraveltime; // may include tls-penalty
976 }
977 } else {
978 for (const MSLane* const lane : *myLanes) {
979 int numVehs = lane->getVehicleNumber();
980 if (numVehs == 0) {
981 // take speed limit but with lowest possible weight
982 numVehs = 1;
983 }
984 v += numVehs * lane->getMeanSpeed();
985 totalNumVehs += numVehs;
986 }
987 if (myBidiEdge != nullptr) {
988 for (const MSLane* const lane : myBidiEdge->getLanes()) {
989 if (lane->getVehicleNumber() > 0) {
990 // do not route across edges which are already occupied in reverse direction
991 return 0;
992 }
993 }
994 }
995 if (totalNumVehs == 0) {
996 return getSpeedLimit();
997 }
998 }
999 return v / totalNumVehs;
1000}
1001
1002
1003double
1005 double f = 0.;
1006 for (const MSLane* const lane : *myLanes) {
1007 f += lane->getFrictionCoefficient();
1008 }
1009 if (!myLanes->empty()) {
1010 return f / (double)myLanes->size();
1011 }
1012 return 1.;
1013}
1014
1015
1016double
1019 // no separate bicycle speeds in meso
1020 return getMeanSpeed();
1021 }
1022 double v = 0;
1023 double totalNumVehs = 0;
1024 for (const MSLane* const lane : *myLanes) {
1025 const int numVehs = lane->getVehicleNumber();
1026 v += numVehs * lane->getMeanSpeedBike();
1027 totalNumVehs += numVehs;
1028 }
1029 if (totalNumVehs == 0) {
1030 return getSpeedLimit();
1031 }
1032 return v / totalNumVehs;
1033}
1034
1035
1036double
1037MSEdge::getCurrentTravelTime(double minSpeed) const {
1038 assert(minSpeed > 0);
1039 if (!myAmDelayed) {
1040 return myEmptyTraveltime;
1041 }
1042 return getLength() / MAX2(minSpeed, getMeanSpeed());
1043}
1044
1045
1046double
1048 return MSRoutingEngine::getAssumedSpeed(this, nullptr);
1049}
1050
1051
1052bool
1053MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
1054 const DictType::iterator it = myDict.lower_bound(id);
1055 if (it == myDict.end() || it->first != id) {
1056 // id not in myDict
1057 myDict.emplace_hint(it, id, ptr);
1058 while (ptr->getNumericalID() >= (int)myEdges.size()) {
1059 myEdges.push_back(nullptr);
1060 }
1061 myEdges[ptr->getNumericalID()] = ptr;
1062 return true;
1063 }
1064 return false;
1065}
1066
1067
1068MSEdge*
1069MSEdge::dictionary(const std::string& id) {
1070 const DictType::iterator it = myDict.find(id);
1071 if (it == myDict.end()) {
1072 return nullptr;
1073 }
1074 return it->second;
1075}
1076
1077
1078MSEdge*
1079MSEdge::dictionaryHint(const std::string& id, const int startIdx) {
1080 // this method is mainly useful when parsing connections from the net.xml which are sorted by "from" id
1081 if (myEdges[startIdx] != nullptr && myEdges[startIdx]->getID() == id) {
1082 return myEdges[startIdx];
1083 }
1084 if (startIdx + 1 < (int)myEdges.size() && myEdges[startIdx + 1] != nullptr && myEdges[startIdx + 1]->getID() == id) {
1085 return myEdges[startIdx + 1];
1086 }
1087 return dictionary(id);
1088}
1089
1090
1091const MSEdgeVector&
1093 return myEdges;
1094}
1095
1096
1097void
1099 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1100 delete (*i).second;
1101 }
1102 myDict.clear();
1103 myEdges.clear();
1104}
1105
1106
1107void
1108MSEdge::insertIDs(std::vector<std::string>& into) {
1109 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1110 into.push_back((*i).first);
1111 }
1112}
1113
1114
1115void
1116MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
1117 const std::string& rid) {
1118 StringTokenizer st(desc);
1119 parseEdgesList(st.getVector(), into, rid);
1120}
1121
1122
1123void
1124MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
1125 const std::string& rid) {
1126 for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1127 const MSEdge* edge = MSEdge::dictionary(*i);
1128 // check whether the edge exists
1129 if (edge == nullptr) {
1130 throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
1131 + "\n The route can not be build.");
1132 }
1133 into.push_back(edge);
1134 }
1135}
1136
1137
1138double
1139MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
1140 assert(this != other);
1141 if (doBoundaryEstimate) {
1142 return myBoundary.distanceTo2D(other->myBoundary);
1143 }
1144 if (isTazConnector()) {
1145 if (other->isTazConnector()) {
1146 return myBoundary.distanceTo2D(other->myBoundary);
1147 }
1148 return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
1149 }
1150 if (other->isTazConnector()) {
1151 return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
1152 }
1153 return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
1154}
1155
1156
1157const Position
1159 return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
1160}
1161
1162
1163double
1165 // @note lanes might have different maximum speeds in theory
1166 return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
1167}
1168
1169
1170double
1172 return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
1173}
1174
1175double
1177 // @note lanes might have different maximum speeds in theory
1178 return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
1179}
1180
1181
1182void
1183MSEdge::setMaxSpeed(double val, double jamThreshold) {
1184 assert(val >= 0);
1185 if (myLanes != nullptr) {
1186 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1187 (*i)->setMaxSpeed(val, false, false, jamThreshold);
1188 }
1189 }
1190}
1191
1192
1193void
1195 if (t->isPerson()) {
1196 myPersons.insert(t);
1197 } else {
1198 myContainers.insert(t);
1199 }
1200}
1201
1202void
1204 std::set<MSTransportable*, ComparatorNumericalIdLess>& tc = t->isPerson() ? myPersons : myContainers;
1205 auto it = tc.find(t);
1206 if (it != tc.end()) {
1207 tc.erase(it);
1208 }
1209}
1210
1211std::vector<MSTransportable*>
1212MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
1213 std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
1214 if (includeRiding) {
1215 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1216 const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
1217 for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
1218 const std::vector<MSTransportable*>& persons = (*j)->getPersons();
1219 result.insert(result.end(), persons.begin(), persons.end());
1220 }
1221 (*i)->releaseVehicles();
1222 }
1223 }
1224 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1225 return result;
1226}
1227
1228
1229std::vector<MSTransportable*>
1230MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
1231 std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
1232 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1233 return result;
1234}
1235
1236
1237int
1239 const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
1240 const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
1241 if (pos1 != pos2) {
1242 return pos1 < pos2;
1243 }
1244 return c1->getID() < c2->getID();
1245}
1246
1247
1248void
1250 mySuccessors.push_back(edge);
1251 myViaSuccessors.push_back(std::make_pair(edge, via));
1252 if (isTazConnector() && edge->getFromJunction() != nullptr) {
1254 }
1255
1256 edge->myPredecessors.push_back(this);
1257 if (edge->isTazConnector() && getToJunction() != nullptr) {
1258 edge->myBoundary.add(getToJunction()->getPosition());
1259 }
1260}
1261
1262
1263const MSEdgeVector&
1265 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1266 return mySuccessors;
1267 }
1268#ifdef HAVE_FOX
1269 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1270#endif
1271 std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1272 if (i == myClassesSuccessorMap.end()) {
1273 // instantiate vector
1274 myClassesSuccessorMap[vClass];
1275 i = myClassesSuccessorMap.find(vClass);
1276 // this vClass is requested for the first time. rebuild all successors
1277 for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1278 if ((*it)->isTazConnector()) {
1279 i->second.push_back(*it);
1280 } else {
1281 const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1282 if (allowed != nullptr && allowed->size() > 0) {
1283 i->second.push_back(*it);
1284 }
1285 }
1286 }
1287 }
1288 // can use cached value
1289 return i->second;
1290}
1291
1292
1294MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
1295 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1296 return myViaSuccessors;
1297 }
1298#ifdef HAVE_FOX
1299 ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1300#endif
1301 auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
1302 auto i = viaMap.find(vClass);
1303 if (i != viaMap.end()) {
1304 // can use cached value
1305 return i->second;
1306 }
1307 // instantiate vector
1308 MSConstEdgePairVector& result = viaMap[vClass];
1309 // this vClass is requested for the first time. rebuild all successors
1310 for (const auto& viaPair : myViaSuccessors) {
1311 if (viaPair.first->isTazConnector()) {
1312 result.push_back(viaPair);
1313 } else {
1314 const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
1315 if (allowed != nullptr && allowed->size() > 0) {
1316 result.push_back(viaPair);
1317 }
1318 }
1319 }
1320 return result;
1321}
1322
1323
1324void
1326 myFromJunction = from;
1327 myToJunction = to;
1328 if (!isTazConnector()) {
1329 myBoundary.add(from->getPosition());
1330 myBoundary.add(to->getPosition());
1331 }
1332}
1333
1334
1335bool
1337 return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1338 // do not change on curved internal lanes
1339 (!isInternal()
1341 && myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LinkDirection::STRAIGHT)));
1342}
1343
1344
1345const MSEdge*
1347 if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1348 return &(myLanes->back()->getOpposite()->getEdge());
1349 } else {
1350 return nullptr;
1351 }
1352}
1353
1354
1355bool
1357 for (const MSLane* const l : *myLanes) {
1358 for (const MSLink* const link : l->getLinkCont()) {
1359 if (!link->havePriority()) {
1360 return true;
1361 }
1362 }
1363 }
1364 return false;
1365}
1366
1367bool
1369 if (myLanes->size() == 1) {
1370 return false;
1371 }
1372 for (const MSLane* const l : *myLanes) {
1373 if (l->getIndex() <= index && !l->allowsChangingRight(svc) && l->getIndex() > 0) {
1374 return true;
1375 } else if (l->getIndex() >= index && !l->allowsChangingLeft(svc) && l->getIndex() < (int)(myLanes->size() - 1)) {
1376 return true;
1377 }
1378 }
1379 return false;
1380}
1381
1382void
1383MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1384 if (bidiID != "") {
1385 myBidiEdge = dictionary(bidiID);
1386 if (myBidiEdge == nullptr) {
1387 WRITE_ERRORF(TL("Bidi-edge '%' does not exist"), bidiID);
1388 }
1389 setBidiLanes();
1390 return;
1391 }
1393 return;
1394 }
1395 // legacy networks (no bidi attribute)
1397 for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1398 if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1399 if (myBidiEdge != nullptr && isSuperposable(*it)) {
1400 WRITE_WARNINGF(TL("Ambiguous superposable edges between junction '%' and '%'."), myToJunction->getID(), myFromJunction->getID());
1401 break;
1402 }
1403 if (isSuperposable(*it)) {
1404 myBidiEdge = *it;
1405 setBidiLanes();
1406 }
1407 }
1408 }
1409}
1410
1411
1412void
1414 assert(myBidiEdge != nullptr);
1415 if (getNumLanes() == 1 && myBidiEdge->getNumLanes() == 1) {
1416 // the other way round is set when this method runs for the bidiEdge
1417 getLanes()[0]->setBidiLane(myBidiEdge->getLanes()[0]);
1418 } else {
1419 // find lanes with matching reversed shapes
1420 int numBidiLanes = 0;
1421 for (MSLane* l1 : *myLanes) {
1422 for (MSLane* l2 : *myBidiEdge->myLanes) {
1423 if (l1->getShape().reverse().almostSame(l2->getShape(), POSITION_EPS * 2)) {
1424 l1->setBidiLane(l2);
1425 numBidiLanes++;
1426 }
1427 }
1428 }
1429 // warn only once for each pair
1430 if (numBidiLanes == 0 && getNumericalID() < myBidiEdge->getNumericalID()) {
1431 WRITE_WARNINGF(TL("Edge '%' and bidi edge '%' have no matching bidi lanes"), getID(), myBidiEdge->getID());
1432 }
1433 }
1434}
1435
1436
1437bool
1439 if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1440 return false;
1441 }
1442 std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1443 std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1444 do {
1445 if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1446 return false;
1447 }
1448 it1++;
1449 it2++;
1450 } while (it1 != myLanes->end());
1451
1452 return true;
1453}
1454
1455
1456void
1458#ifdef HAVE_FOX
1459 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1460#endif
1461 myWaiting.push_back(vehicle);
1462}
1463
1464
1465void
1466MSEdge::removeWaiting(const SUMOVehicle* vehicle) const {
1467#ifdef HAVE_FOX
1468 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1469#endif
1470 std::vector<SUMOVehicle*>::iterator it = std::find(myWaiting.begin(), myWaiting.end(), vehicle);
1471 if (it != myWaiting.end()) {
1472 myWaiting.erase(it);
1473 }
1474}
1475
1476
1478MSEdge::getWaitingVehicle(MSTransportable* transportable, const double position) const {
1479#ifdef HAVE_FOX
1480 ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1481#endif
1482 for (SUMOVehicle* const vehicle : myWaiting) {
1483 if (transportable->isWaitingFor(vehicle)) {
1484 if (vehicle->isStoppedInRange(position, MSGlobals::gStopTolerance) ||
1485 (!vehicle->hasDeparted() &&
1486 (vehicle->getParameter().departProcedure == DepartDefinition::TRIGGERED ||
1487 vehicle->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED))) {
1488 return vehicle;
1489 }
1490 if (!vehicle->isLineStop(position) && vehicle->allowsBoarding(transportable)) {
1491 WRITE_WARNING((transportable->isPerson() ? "Person '" : "Container '")
1492 + transportable->getID() + "' at edge '" + getID() + "' position " + toString(position) + " cannot use waiting vehicle '"
1493 + vehicle->getID() + "' at position " + toString(vehicle->getPositionOnLane()) + " because it is too far away.");
1494 }
1495 }
1496 }
1497 return nullptr;
1498}
1499
1500std::vector<const SUMOVehicle*>
1502 std::vector<const SUMOVehicle*> result;
1504 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1505 std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
1506 result.insert(result.end(), segmentVehs.begin(), segmentVehs.end());
1507 }
1508 } else {
1509 for (MSLane* lane : getLanes()) {
1510 for (auto veh : lane->getVehiclesSecure()) {
1511 result.push_back(veh);
1512 }
1513 lane->releaseVehicles();
1514 }
1515 }
1516 return result;
1517}
1518
1519int
1521 int result = 0;
1522 SVCPermissions filter = SVCAll;
1524 filter = ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1525 } else if ((myCombinedPermissions & (SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1526 // filter out green verge
1527 filter = (SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1528 }
1529 for (const MSLane* const l : *myLanes) {
1530 if ((l->getPermissions() & filter) != 0) {
1531 result++;
1532 }
1533 }
1534 return result;
1535}
1536
1537int
1539 return (int)getVehicles().size();
1540}
1541
1542
1543bool
1547 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1548 if (segment->getCarNumber() > 0) {
1549 return false;
1550 }
1551 }
1552 } else {
1553 for (MSLane* lane : getLanes()) {
1554 if (lane->getVehicleNumber() > 0) {
1555 return false;
1556 }
1557 }
1558 }
1559 return true;
1560}
1561
1562
1563double
1565 double wtime = 0;
1567 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1568 wtime += segment->getWaitingSeconds();
1569 }
1570 } else {
1571 for (MSLane* lane : getLanes()) {
1572 wtime += lane->getWaitingSeconds();
1573 }
1574 }
1575 return wtime;
1576}
1577
1578
1579double
1581 if (myLanes->size() == 0) {
1582 return 0;
1583 }
1586 double sum = 0;
1587 for (const SUMOVehicle* veh : getVehicles()) {
1588 sum += dynamic_cast<const MEVehicle*>(veh)->getVehicleType().getLength();
1589 }
1590 return sum / (myLength * (double)myLanes->size());
1591 } else {
1592 double sum = 0;
1593 for (auto lane : getLanes()) {
1594 sum += lane->getNettoOccupancy();
1595 }
1596 return sum / (double)myLanes->size();
1597 }
1598}
1599
1600
1601double
1603 if (myLanes->size() == 0) {
1604 return 0;
1605 }
1606 double flow = 0;
1607 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1608 flow += (double) segment->getCarNumber() * segment->getMeanSpeed();
1609 }
1610 return 3600 * flow / (*myLanes)[0]->getLength();
1611}
1612
1613
1614double
1616 if (myLanes->size() == 0) {
1617 return 0;
1618 }
1619 double occ = 0;
1620 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1621 occ += segment->getBruttoOccupancy();
1622 }
1623 return occ / (*myLanes)[0]->getLength() / (double)(myLanes->size());
1624}
1625
1626double
1627MSEdge::getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double /*time*/) {
1628 return edge->getLength() / MIN2(MSRoutingEngine::getAssumedSpeed(edge, veh), veh->getMaxSpeed());
1629}
1630
1631
1632void
1634 // @note must be called after closeBuilding() to ensure successors and
1635 // predecessors are set
1636 if (isInternal() && myEdgeType == "") {
1637 const std::string typeBefore = getNormalBefore()->getEdgeType();
1638 if (typeBefore != "") {
1639 const std::string typeAfter = getNormalSuccessor()->getEdgeType();
1640 if (typeBefore == typeAfter) {
1641 myEdgeType = typeBefore;
1642 } else if (typeAfter != "") {
1643 MSNet* net = MSNet::getInstance();
1644 auto resBefore = net->getRestrictions(typeBefore);
1645 auto resAfter = net->getRestrictions(typeAfter);
1646 if (resBefore != nullptr && resAfter != nullptr) {
1647 // create new restrictions for this type-combination
1648 myEdgeType = typeBefore + "|" + typeAfter;
1649 if (net->getRestrictions(myEdgeType) == nullptr) {
1650 for (const auto& item : *resBefore) {
1651 const SUMOVehicleClass svc = item.first;
1652 const double speed = item.second;
1653 const auto it = (*resAfter).find(svc);
1654 if (it != (*resAfter).end()) {
1655 const double speed2 = it->second;
1656 const double newSpeed = (MSNet::getInstance()->hasJunctionHigherSpeeds()
1657 ? MAX2(speed, speed2) : (speed + speed2) / 2);
1658 net->addRestriction(myEdgeType, svc, newSpeed);
1659 }
1660 }
1661 }
1662 }
1663 }
1664 }
1665 }
1666}
1667
1668
1669double
1670MSEdge::getDistanceAt(double pos) const {
1671 // negative values of myDistances indicate descending kilometrage
1672 return fabs(myDistance + pos);
1673}
1674
1675
1676bool
1680
1681
1682std::pair<double, SUMOTime>
1683MSEdge::getLastBlocked(int index) const {
1684 if (myLaneChanger != nullptr) {
1685 return myLaneChanger->getLastBlocked(index);
1686 }
1687 return std::make_pair(-1, -1);
1688}
1689
1690void
1692 myPersons.clear();
1693 myContainers.clear();
1694 myWaiting.clear();
1695}
1696
1697/****************************************************************************/
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:288
#define WRITE_ERRORF(...)
Definition MsgHandler.h:297
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
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:76
T MAX2(T a, T b)
Definition StdDefs.h:82
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:879
Sorts transportables by their positions.
Definition MSEdge.h:894
int operator()(const MSTransportable *const c1, const MSTransportable *const c2) const
comparing operator
Definition MSEdge.cpp:1238
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1092
SUMOVehicle * getWaitingVehicle(MSTransportable *transportable, const double position) const
Definition MSEdge.cpp:1478
void addToAllowed(const SVCPermissions permissions, std::shared_ptr< const std::vector< MSLane * > > allowedLanes, AllowedLanesCont &laneCont) const
Definition MSEdge.cpp:301
void changeLanes(SUMOTime t) const
Performs lane changing on this edge.
Definition MSEdge.cpp:898
double getBruttoOccupancy() const
Definition MSEdge.cpp:1615
SVCPermissions myCombinedPermissions
The union of lane permissions for this edge.
Definition MSEdge.h:968
double getFlow() const
return flow based on meanSpead
Definition MSEdge.cpp:1602
Boundary myBoundary
The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start ...
Definition MSEdge.h:1049
double myWidth
Edge width [m].
Definition MSEdge.h:995
AllowedLanesByTarget myAllowedTargets
From target edge to lanes allowed to be used to reach it.
Definition MSEdge.h:962
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:655
SUMOTime myLastFailedInsertionTime
The time of last insertion failure.
Definition MSEdge.h:926
std::set< MSTransportable *, ComparatorNumericalIdLess > myContainers
Containers on the edge.
Definition MSEdge.h:952
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:1683
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1098
void inferEdgeType()
Definition MSEdge.cpp:1633
void setJunctions(MSJunction *from, MSJunction *to)
Definition MSEdge.cpp:1325
double getMeanSpeedBike() const
get the mean speed of all bicycles on this edge
Definition MSEdge.cpp:1017
static MSEdgeVector myEdges
Static list of edges.
Definition MSEdge.h:1032
AllowedLanesCont myAllowed
Associative container from vehicle class to allowed-lanes.
Definition MSEdge.h:958
double myEmptyTraveltime
the traveltime on the empty edge (cached value for speedup)
Definition MSEdge.h:1001
void updateMesoType()
update meso segment parameters
Definition MSEdge.cpp:250
bool myAmFringe
whether this edge is at the network fringe
Definition MSEdge.h:1013
static double getTravelTimeAggregated(const MSEdge *const edge, const SUMOVehicle *const veh, double time)
Definition MSEdge.cpp:1627
MSJunction * myToJunction
Definition MSEdge.h:946
void checkAndRegisterBiDirEdge(const std::string &bidiID="")
check and register the opposite superposable edge if any
Definition MSEdge.cpp:1383
virtual ~MSEdge()
Destructor.
Definition MSEdge.cpp:95
double getDepartPosBound(const MSVehicle &veh, bool upper=true) const
return upper bound for the depart position on this edge
Definition MSEdge.cpp:597
const double myDistance
the kilometrage/mileage at the start of the edge
Definition MSEdge.h:992
void clearState()
Remove all transportables before quick-loading state.
Definition MSEdge.cpp:1691
MSLane * getDepartLaneMeso(SUMOVehicle &veh) const
consider given departLane parameter (only for validating speeds)
Definition MSEdge.cpp:644
bool hasTransientPermissions() const
Definition MSEdge.cpp:1677
const MSEdge * myBidiEdge
the oppositing superposable edge
Definition MSEdge.h:1065
MSLane * leftLane(const MSLane *const lane) const
Returns the lane left to the one given, 0 if the given lane is leftmost.
Definition MSEdge.cpp:451
std::string myEdgeType
the type of the edge (optionally used during network creation)
Definition MSEdge.h:986
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:1520
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1346
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:1116
double getLengthGeometryFactor() const
return shape.length() / myLength
Definition MSEdge.cpp:1171
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:1249
friend class MSLaneChangerSublane
Definition MSEdge.h:87
std::vector< SUMOVehicle * > myWaiting
List of waiting vehicles.
Definition MSEdge.h:1052
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:953
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition MSEdge.cpp:480
double getInternalFollowingLengthTo(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
returns the length of all internal edges on the junction until reaching the non-internal edge followe...
Definition MSEdge.cpp:928
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:1212
bool isSuperposable(const MSEdge *other)
Definition MSEdge.cpp:1438
bool validateDepartSpeed(SUMOVehicle &v) const
check whether the given departSpeed is valid for this edge
Definition MSEdge.cpp:744
double getDistanceTo(const MSEdge *other, const bool doBoundaryEstimate=false) const
optimistic air distance heuristic for use in routing
Definition MSEdge.cpp:1139
void setMaxSpeed(double val, double jamThreshold=-1)
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition MSEdge.cpp:1183
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:1079
MSLaneChanger * myLaneChanger
This member will do the lane-change.
Definition MSEdge.h:917
double getOccupancy() const
return mean occupancy on this edges lanes or segments
Definition MSEdge.cpp:1580
static int myDefaultDepartLane
Definition MSEdge.h:1037
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition MSEdge.cpp:1294
std::vector< MSTransportable * > getSortedContainers(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's containers sorted by pos.
Definition MSEdge.cpp:1230
const SumoXMLEdgeFunc myFunction
the purpose of the edge
Definition MSEdge.h:920
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:559
void recalcCache()
Recalculates the cached values.
Definition MSEdge.cpp:120
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:1164
SVCPermissions myOriginalCombinedPermissions
The original union of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:973
bool myAmDelayed
whether this edge had a vehicle with less than max speed on it
Definition MSEdge.h:1007
SVCPermissions myOriginalMinimumPermissions
The original intersection of lane permissions for this edge (before temporary modifications)
Definition MSEdge.h:971
std::map< SUMOVehicleClass, MSEdgeVector > myClassesSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1042
SUMOTime decVaporization(SUMOTime t)
Disables vaporization.
Definition MSEdge.cpp:520
MSEdgeVector myPredecessors
The preceeding edges.
Definition MSEdge.h:942
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:1368
void rebuildAllowedTargets(const bool updateVehicles=true)
Definition MSEdge.cpp:384
static SVCPermissions myMesoIgnoredVClasses
Definition MSEdge.h:1034
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:418
double getLength() const
return the length of the edge
Definition MSEdge.h:685
void initialize(const std::vector< MSLane * > *lanes)
Initialize the edge.
Definition MSEdge.cpp:103
bool myHaveTransientPermissions
whether transient permission changes were applied to this edge or a predecessor
Definition MSEdge.h:976
virtual void closeBuilding()
Definition MSEdge.cpp:206
static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored=0)
Definition MSEdge.cpp:316
bool canChangeToOpposite() const
whether this edge allows changing to the opposite direction edge
Definition MSEdge.cpp:1336
std::set< int > myFailedInsertionMemory
A cache for the rejected insertion attempts. Used to assure that no further insertion attempts are ma...
Definition MSEdge.h:931
const MSJunction * getFromJunction() const
Definition MSEdge.h:414
double getMeanSpeed() const
get the mean speed
Definition MSEdge.cpp:963
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition MSEdge.h:1027
std::set< MSTransportable *, ComparatorNumericalIdLess > myPersons
Persons on the edge for drawing and pushbutton.
Definition MSEdge.h:949
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:1670
MSConstEdgePairVector myViaSuccessors
Definition MSEdge.h:939
void setBidiLanes()
Definition MSEdge.cpp:1413
MSEdgeVector mySuccessors
The succeeding edges.
Definition MSEdge.h:937
static DepartLaneDefinition myDefaultDepartLaneDefinition
Definition MSEdge.h:1036
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:457
double getCurrentTravelTime(const double minSpeed=NUMERICAL_EPS) const
Computes and returns the current travel time for this edge.
Definition MSEdge.cpp:1037
std::map< SUMOVehicleClass, MSConstEdgePairVector > myOrigClassesViaSuccessorMap
Definition MSEdge.h:1046
AllowedLanesByTarget myOrigAllowedTargets
Definition MSEdge.h:963
int getNumericalID() const
Returns the numerical id of the edge.
Definition MSEdge.h:306
void resetTAZ(MSJunction *junction)
Definition MSEdge.cpp:183
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:434
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:781
static const Position getStopPosition(const SUMOVehicleParameter::Stop &stop)
return the coordinates of the center of the given stop
Definition MSEdge.cpp:1158
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition MSEdge.cpp:1457
MSLane * parallelLane(const MSLane *const lane, int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to the given lane one or 0 if it does not exist.
Definition MSEdge.cpp:463
ReversedEdge< MSEdge, SUMOVehicle > * myReversedRoutingEdge
a reversed version for backward routing
Definition MSEdge.h:1068
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:1053
std::vector< const SUMOVehicle * > getVehicles() const
return vehicles on this edges lanes or segments
Definition MSEdge.cpp:1501
static void insertIDs(std::vector< std::string > &into)
Inserts IDs of all known edges into the given vector.
Definition MSEdge.cpp:1108
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1176
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition MSEdge.cpp:513
MSJunction * myFromJunction
the junctions for this edge
Definition MSEdge.h:945
double getMeanFriction() const
get the mean friction over the lanes
Definition MSEdge.cpp:1004
std::map< std::string, MSEdge * > DictType
definition of the static dictionary type
Definition MSEdge.h:1022
bool hasMinorLink() const
whether any lane has a minor link
Definition MSEdge.cpp:1356
std::map< SUMOVehicleClass, MSConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition MSEdge.h:1045
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:943
int getVehicleNumber() const
return total number of vehicles on this edges lanes or segments
Definition MSEdge.cpp:1538
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:409
virtual void removeTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1203
SumoXMLEdgeFunc getFunction() const
Returns the edge type (SumoXMLEdgeFunc)
Definition MSEdge.h:258
bool allowsLaneChanging() const
Definition MSEdge.cpp:279
bool isEmpty() const
whether this edge has no vehicles
Definition MSEdge.cpp:1544
MSEdge(const std::string &id, int numericalID, const SumoXMLEdgeFunc function, const std::string &streetName, const std::string &edgeType, int priority, double distance)
Constructor.
Definition MSEdge.cpp:68
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition MSEdge.cpp:906
void buildLaneChanger()
Has to be called after all sucessors and predecessors have been set (after closeBuilding())
Definition MSEdge.cpp:259
double getRoutingSpeed() const
Returns the averaged speed used by the routing device.
Definition MSEdge.cpp:1047
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition MSEdge.h:777
void removeWaiting(const SUMOVehicle *vehicle) const
Removes a vehicle from the list of waiting vehicles.
Definition MSEdge.cpp:1466
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false) const
Definition MSEdge.cpp:733
std::vector< double > mySublaneSides
the right side for each sublane on this edge
Definition MSEdge.h:1016
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1264
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:914
AllowedLanesCont myOrigAllowed
Definition MSEdge.h:959
double getWaitingSeconds() const
return accumated waiting time for all vehicles on this edges lanes or segments
Definition MSEdge.cpp:1564
int myVaporizationRequests
Vaporizer counter.
Definition MSEdge.h:923
double myTimePenalty
flat penalty when computing traveltime
Definition MSEdge.h:1004
SVCPermissions myMinimumPermissions
The intersection of lane permissions for this edge.
Definition MSEdge.h:966
MSLane * getFreeLane(const std::vector< MSLane * > *allowed, const SUMOVehicleClass vclass, double departPos) const
Finds the emptiest lane allowing the vehicle class.
Definition MSEdge.cpp:527
void rebuildAllowedLanes(const bool onInit=false, bool updateVehicles=false)
Definition MSEdge.cpp:323
virtual void addTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1194
RailEdge< MSEdge, SUMOVehicle > * myRailwayRoutingEdge
Definition MSEdge.h:1069
double myLength
the length of the edge (cached value for speedup)
Definition MSEdge.h:998
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:692
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:3385
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2478
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4372
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:186
bool hasJunctionHigherSpeeds() const
return whether the network was built with higher junction speeds
Definition MSNet.h:791
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:353
void addRestriction(const std::string &id, const SUMOVehicleClass svc, const double speed)
Adds a restriction for an edge type.
Definition MSNet.cpp:347
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:367
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
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:208
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)
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