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