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