Eclipse SUMO - Simulation of Urban MObility
MSLink.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // A connnection between lanes
18 /****************************************************************************/
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <iostream>
26 #include <algorithm>
27 #include <limits>
30 #include "MSNet.h"
31 #include "MSJunction.h"
32 #include "MSLink.h"
33 #include "MSLane.h"
35 #include "MSEdge.h"
36 #include "MSGlobals.h"
37 #include "MSVehicle.h"
40 
41 //#define MSLink_DEBUG_CROSSING_POINTS
42 //#define MSLink_DEBUG_OPENED
43 //#define DEBUG_APPROACHING
44 //#define DEBUG_ZIPPER
45 //#define DEBUG_COND (myLane->getID()=="43[0]_0" && myLaneBefore->getID()==":33_0_0")
46 //#define DEBUG_COND (myLane->getID()=="end_0")
47 //#define DEBUG_COND (true)
48 //#define DEBUG_COND2(obj) (obj->isSelected())
49 //#define DEBUG_COND_ZIPPER (gDebugFlag1)
50 //#define DEBUG_COND_ZIPPER (true)
51 #define DEBUG_COND_ZIPPER (ego->isSelected())
52 
53 // ===========================================================================
54 // static member variables
55 // ===========================================================================
57 // additional caution is needed when approaching a zipper link
59 
60 const double MSLink::ZIPPER_ADAPT_DIST(100);
61 
62 // time to link in seconds below which adaptation should take place
63 #define ZIPPER_ADAPT_TIME 10
64 // the default safety gap when passing before oncoming pedestrians
65 #define JM_CROSSING_GAP_DEFAULT 10
66 
67 // minimim width between sibling lanes to qualify as non-overlapping
68 #define DIVERGENCE_MIN_WIDTH 2.5
69 
70 // ===========================================================================
71 // member method definitions
72 // ===========================================================================
73 MSLink::MSLink(MSLane* predLane, MSLane* succLane, MSLane* via, LinkDirection dir, LinkState state, double length, double foeVisibilityDistance, bool keepClear, MSTrafficLightLogic* logic, int tlIndex) :
74  myLane(succLane),
75  myLaneBefore(predLane),
76  myIndex(-1),
77  myTLIndex(tlIndex),
78  myLogic(logic),
79  myState(state),
80  myOffState(state),
81  myLastStateChange(SUMOTime_MIN / 2), // a large negative value, but avoid overflows when subtracting
82  myDirection(dir),
83  myLength(length),
84  myFoeVisibilityDistance(foeVisibilityDistance),
85  myHasFoes(false),
86  myAmCont(false),
87  myAmContOff(false),
88  myKeepClear(keepClear),
89  myInternalLane(via),
90  myInternalLaneBefore(nullptr),
91  myMesoTLSPenalty(0),
92  myGreenFraction(1),
93  myLateralShift(0),
94  myWalkingAreaFoe(nullptr),
95  myWalkingAreaFoeExit(nullptr),
96  myHavePedestrianCrossingFoe(false),
97  myParallelRight(nullptr),
98  myParallelLeft(nullptr),
99  myJunction(nullptr) {
100 
102  // detect lateral shift from lane geometries
103  //std::cout << "DEBUG link=" << myLaneBefore->getID() << "->" << getViaLaneOrLane()->getID() << " hasInternal=" << MSNet::getInstance()->hasInternalLinks() << " shapeBefore=" << myLaneBefore->getShape().back() << " shapeFront=" << getViaLaneOrLane()->getShape().front() << "\n";
104  if ((myInternalLane != nullptr || predLane->isInternal())
105  && myLaneBefore->getShape().back() != getViaLaneOrLane()->getShape().front()) {
107  const PositionVector& to = getViaLaneOrLane()->getShape();
108  const double dist = from.back().distanceTo2D(to.front());
109  // figure out direction of shift
110  try {
111  from.move2side(dist);
112  } catch (InvalidArgument&) {
113  }
114  myLateralShift = (from.back().distanceTo2D(to.front()) < dist) ? dist : -dist;
115  //std::cout << " lateral shift link=" << myLaneBefore->getID() << "->" << getViaLaneOrLane()->getID() << " dist=" << dist << " shift=" << myLateralShift << "\n";
116  }
117  }
118 }
119 
120 
122 
123 
124 void
125 MSLink::setRequestInformation(int index, bool hasFoes, bool isCont,
126  const std::vector<MSLink*>& foeLinks,
127  const std::vector<MSLane*>& foeLanes,
128  MSLane* internalLaneBefore) {
129 //#ifdef MSLink_DEBUG_CROSSING_POINTS
130 // std::cout << " setRequestInformation() for junction " << getViaLaneOrLane()->getEdge().getFromJunction()->getID()
131 // << "\nInternalLanes = " << toString(getViaLaneOrLane()->getEdge().getFromJunction()->getInternalLanes())
132 // << std::endl;
133 //#endif
134  myIndex = index;
135  myHasFoes = hasFoes;
136  myAmCont = isCont;
137  myFoeLinks = foeLinks;
138  for (std::vector<MSLane*>::const_iterator it_lane = foeLanes.begin(); it_lane != foeLanes.end(); ++it_lane) {
139  // cannot assign vector due to const-ness
140  myFoeLanes.push_back(*it_lane);
141  }
142  myJunction = const_cast<MSJunction*>(myLane->getEdge().getFromJunction()); // junctionGraph is initialized after the whole network is loaded
143  myAmContOff = isCont && myLogic != nullptr && internalLaneBefore == nullptr && checkContOff();
144  myInternalLaneBefore = internalLaneBefore;
145  MSLane* lane = nullptr;
146  if (internalLaneBefore != nullptr) {
147  // this is an exit link. compute crossing points with all foeLanes
148  lane = internalLaneBefore;
149  //} else if (myLane->getEdge().isCrossing()) {
150  // // this is the link to a pedestrian crossing. compute crossing points with all foeLanes
151  // // @note not currently used by pedestrians
152  // lane = myLane;
153  }
154 #ifdef MSLink_DEBUG_CROSSING_POINTS
155  std::cout << " link " << myIndex << " to " << getViaLaneOrLane()->getID() << " internalLaneBefore=" << (lane == 0 ? "NULL" : lane->getID()) << " has foes: " << toString(foeLanes) << "\n";
156 #endif
157  if (lane != nullptr) {
158  const bool beforeInternalJunction = lane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().isInternal();
159  if (lane->getIncomingLanes().size() != 1) {
160  throw ProcessError("Internal lane '" + lane->getID() + "' has " + toString(lane->getIncomingLanes().size()) + " predecessors");
161  }
162  // compute crossing points
163  for (std::vector<const MSLane*>::const_iterator it_lane = myFoeLanes.begin(); it_lane != myFoeLanes.end(); ++it_lane) {
164  myHavePedestrianCrossingFoe = myHavePedestrianCrossingFoe || (*it_lane)->getEdge().isCrossing();
165  const bool sameTarget = myLane == (*it_lane)->getLinkCont()[0]->getLane();
166  if (sameTarget && !beforeInternalJunction && !contIntersect(lane, *it_lane)) {
167  //if (myLane == (*it_lane)->getLinkCont()[0]->getLane()) {
168  // this foeLane has the same target and merges at the end (lane exits the junction)
169  myLengthsBehindCrossing.push_back(std::make_pair(0, 0)); // dummy value, never used
170 #ifdef MSLink_DEBUG_CROSSING_POINTS
171  std::cout
172  << " " << lane->getID()
173  << " merges with " << (*it_lane)->getID()
174  << " nextLane " << lane->getLinkCont()[0]->getViaLaneOrLane()->getID()
175  << " dist1=" << myLengthsBehindCrossing.back().first
176  << " dist2=" << myLengthsBehindCrossing.back().second
177  << "\n";
178 #endif
179  } else {
180  std::vector<double> intersections1 = lane->getShape().intersectsAtLengths2D((*it_lane)->getShape());
181 #ifdef MSLink_DEBUG_CROSSING_POINTS
182 // std::cout << " intersections1=" << toString(intersections1) << "\n";
183 #endif
184  bool haveIntersection = true;
185  if (intersections1.size() == 0) {
186  intersections1.push_back(-10000.0); // disregard this foe (using maxdouble leads to nasty problems down the line)
187  haveIntersection = false;
188  } else if (intersections1.size() > 1) {
189  std::sort(intersections1.begin(), intersections1.end());
190  }
191  std::vector<double> intersections2 = (*it_lane)->getShape().intersectsAtLengths2D(lane->getShape());
192 #ifdef MSLink_DEBUG_CROSSING_POINTS
193  //std::cout << " intersections2=" << toString(intersections2) << "\n";
194 #endif
195  if (intersections2.size() == 0) {
196  intersections2.push_back(0);
197  } else if (intersections2.size() > 1) {
198  std::sort(intersections2.begin(), intersections2.end());
199  }
200  if (haveIntersection) {
201  // lane width affects the crossing point
202  intersections1.back() -= (*it_lane)->getWidth() / 2;
203  intersections2.back() -= lane->getWidth() / 2;
204  // ensure negative offset for weird geometries
205  intersections1.back() = MAX2(0.0, intersections1.back());
206  intersections2.back() = MAX2(0.0, intersections2.back());
207 
208  // also length/geometry factor. (XXX: Why subtract width/2 *before* converting geometric position to lane pos? refs #3031)
209  intersections1.back() = lane->interpolateGeometryPosToLanePos(intersections1.back());
210  intersections2.back() = (*it_lane)->interpolateGeometryPosToLanePos(intersections2.back());
211 
212  if (internalLaneBefore->getLogicalPredecessorLane()->getEdge().isInternal() && !(*it_lane)->getEdge().isCrossing()) {
213  // wait at the internal junction
214  // (except for foes that are crossings since there is no internal junction)
215  intersections1.back() = 0;
216  }
217  }
218 
219  myLengthsBehindCrossing.push_back(std::make_pair(
220  lane->getLength() - intersections1.back(),
221  (*it_lane)->getLength() - intersections2.back()));
222 
223 #ifdef MSLink_DEBUG_CROSSING_POINTS
224  std::cout
225  << " intersection of " << lane->getID()
226  << " totalLength=" << lane->getLength()
227  << " with " << (*it_lane)->getID()
228  << " totalLength=" << (*it_lane)->getLength()
229  << " dist1=" << myLengthsBehindCrossing.back().first
230  << " dist2=" << myLengthsBehindCrossing.back().second
231  << "\n";
232 #endif
233  }
234  }
235  // check for overlap with internal lanes from the same source lane
236  const MSLane* pred = lane->getLogicalPredecessorLane();
237  // to avoid overlap with vehicles that came from pred (especially when pred has endOffset > 0)
238  // we add all other internal lanes from pred as foeLanes
239  for (const MSLink* const it : pred->getLinkCont()) {
240  const MSLane* sibling = it->getViaLane();
241  if (sibling != lane && sibling != nullptr) {
242  const double minDist = MIN2(DIVERGENCE_MIN_WIDTH, 0.5 * (lane->getWidth() + sibling->getWidth()));
243  const PositionVector& l = lane->getShape();
244  const PositionVector& s = sibling->getShape();
245  if (l.front().distanceTo2D(s.front()) >= minDist) {
246  // account for lateral shift by the entry links
247  continue;
248  }
249  double lbcSibling = 0;
250  double lbcLane = 0;
251  if (l.back().distanceTo2D(s.back()) > minDist) {
252  // compute the final divergence point
253  // this position serves two purposes:
254  // 1) once the foe vehicle back (on sibling) has passed this point, we can safely ignore it
255  // 2) both vehicles are put into a cf-relationship while before the point.
256  // Since the actual crossing point is at the start of the junction,
257  // we want to make sure that both vehicles have the same distance to the crossing point and thus follow each other naturally
258  std::vector<double> distances = l.distances(s);
259 #ifdef MSLink_DEBUG_CROSSING_POINTS
260  std::cout << " distances=" << toString(distances) << "\n";
261 #endif
262  assert(distances.size() == l.size() + s.size());
263  if (distances.back() > minDist && distances[l.size() - 1] > minDist) {
264  // do a pairwise check between lane and sibling to make because we do not know which of them bends more
265  for (int j = (int)s.size() - 2; j >= 0; j--) {
266  const int i = j + (int)l.size();
267  const double segLength = s[j].distanceTo2D(s[j + 1]);
268  if (distances[i] > minDist) {
269  lbcSibling += segLength;
270  } else {
271  // assume no sharp bends and just interpolate the last segment
272  lbcSibling += segLength - (minDist - distances[i]) * segLength / (distances[i + 1] - distances[i]);
273  break;
274  }
275  }
276  for (int i = (int)l.size() - 2; i >= 0; i--) {
277  const double segLength = l[i].distanceTo2D(l[i + 1]);
278  if (distances[i] > minDist) {
279  lbcLane += segLength;
280  } else {
281  // assume no sharp bends and just interpolate the last segment
282  lbcLane += segLength - (minDist - distances[i]) * segLength / (distances[i + 1] - distances[i]);
283  break;
284  }
285  }
286  }
287  assert(lbcSibling >= -NUMERICAL_EPS);
288  assert(lbcLane >= -NUMERICAL_EPS);
289  }
290  const double distToDivergence1 = sibling->getLength() - lbcSibling;
291  const double distToDivergence2 = lane->getLength() - lbcLane;
292  const double distToDivergence = MIN3(
293  MAX2(distToDivergence1, distToDivergence2),
294  sibling->getLength(), lane->getLength());
295  lbcLane = MAX2(0.0, lane->getLength() - distToDivergence);
296  lbcLane = lane->interpolateGeometryPosToLanePos(lbcLane);
297  lbcSibling = MAX2(0.0, sibling->getLength() - distToDivergence);
298  lbcSibling = lane->interpolateGeometryPosToLanePos(lbcSibling);
299  myLengthsBehindCrossing.push_back(std::make_pair(lbcLane, lbcSibling));
300  myFoeLanes.push_back(sibling);
301 #ifdef MSLink_DEBUG_CROSSING_POINTS
302  std::cout << " distToDivergence=" << distToDivergence
303  << " distTD1=" << distToDivergence1
304  << " distTD2=" << distToDivergence2
305  << " length=" << lane->getLength()
306  << " sibLength=" << sibling->getLength()
307  << "\n";
308  std::cout << " adding same-origin foe" << sibling->getID()
309  << " dist1=" << myLengthsBehindCrossing.back().first
310  << " dist2=" << myLengthsBehindCrossing.back().second
311  << "\n";
312 #endif
313  }
314  }
315  }
317  // check for links with the same origin lane and the same destination edge
318  const MSEdge* myTarget = &myLane->getEdge();
319  // save foes for entry links
320  for (MSLink* const it : myLaneBefore->getLinkCont()) {
321  const MSEdge* target = &(it->getLane()->getEdge());
322  if (it == this) {
323  continue;
324  }
325  if (target == myTarget) {
326  mySublaneFoeLinks.push_back(it);
327 #ifdef MSLink_DEBUG_CROSSING_POINTS
328  std::cout << " sublaneFoeLink (same target): " << it->getViaLaneOrLane()->getID() << "\n";
329 #endif
330  } else if (myDirection != LINKDIR_STRAIGHT && it->getDirection() == LINKDIR_STRAIGHT) {
331  // potential turn conflicht
332  mySublaneFoeLinks2.push_back(it);
333 #ifdef MSLink_DEBUG_CROSSING_POINTS
334  std::cout << " sublaneFoeLink2 (other target: " << it->getViaLaneOrLane()->getID() << "\n";
335 #endif
336  }
337  }
338  // save foes for exit links
339  if (fromInternalLane()) {
340  //std::cout << " setRequestInformation link=" << getViaLaneOrLane()->getID() << " before=" << myLaneBefore->getID() << " before2=" << myLaneBefore->getIncomingLanes().front().lane->getID() << "\n";
341  const MSLinkCont& predLinks2 = myLaneBefore->getIncomingLanes().front().lane->getLinkCont();
342  for (MSLinkCont::const_iterator it = predLinks2.begin(); it != predLinks2.end(); ++it) {
343  const MSEdge* target = &((*it)->getLane()->getEdge());
344  if ((*it)->getViaLane() != myInternalLaneBefore && target == myTarget) {
345  //std::cout << " add sublaneFoe=" << (*it)->getViaLane()->getID() << "\n";
346  mySublaneFoeLanes.push_back((*it)->getViaLane());
347  }
348  }
349  }
350  }
351 }
352 
353 
354 bool
355 MSLink::contIntersect(const MSLane* lane, const MSLane* foe) {
356  if (foe->getLinkCont()[0]->getViaLane() != nullptr) {
357  std::vector<double> intersections = lane->getShape().intersectsAtLengths2D(foe->getShape());
358  return intersections.size() > 0;
359  }
360  return false;
361 }
362 
363 
364 void
365 MSLink::setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime, const double arrivalSpeed, const double leaveSpeed,
366  const bool setRequest, const SUMOTime arrivalTimeBraking, const double arrivalSpeedBraking, const SUMOTime waitingTime, double dist) {
367  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, approaching->getVehicleType().getLength());
368 #ifdef DEBUG_APPROACHING
369  if (DEBUG_COND2(approaching)) {
370  std::cout << SIMTIME << " Link ''" << (myLaneBefore == 0 ? "NULL" : myLaneBefore->getID()) << "'->'" << (myLane == 0 ? "NULL" : myLane->getID()) << "' Adding approaching vehicle '" << approaching->getID() << "'\nCurrently registered vehicles:" << std::endl;
371  for (auto i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
372  std::cout << "'" << i->first->getID() << "'" << std::endl;
373  }
374  }
375 #endif
376  myApproachingVehicles.emplace(approaching,
377  ApproachingVehicleInformation(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, setRequest,
378  arrivalTimeBraking, arrivalSpeedBraking, waitingTime, dist, approaching->getSpeed()));
379 }
380 
381 
382 void
384 
385 #ifdef DEBUG_APPROACHING
386  if (DEBUG_COND2(approaching)) {
387  std::cout << SIMTIME << " Link ''" << (myLaneBefore == 0 ? "NULL" : myLaneBefore->getID()) << "'->'" << (myLane == 0 ? "NULL" : myLane->getID()) << "' Adding approaching vehicle '" << approaching->getID() << "'\nCurrently registered vehicles:" << std::endl;
388  for (auto i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
389  std::cout << "'" << i->first->getID() << "'" << std::endl;
390  }
391  }
392 #endif
393  myApproachingVehicles.emplace(approaching, ai);
394 }
395 
396 
397 void
399  myBlockedFoeLinks.insert(link);
400 }
401 
402 
403 
404 bool
406  for (std::set<MSLink*>::const_iterator i = myBlockedFoeLinks.begin(); i != myBlockedFoeLinks.end(); ++i) {
407  if ((*i)->isBlockingAnyone()) {
408  return true;
409  }
410  }
411  return false;
412 }
413 
414 
415 void
417 
418 #ifdef DEBUG_APPROACHING
419  if (DEBUG_COND2(veh)) {
420  std::cout << SIMTIME << " Link ''" << (myLaneBefore == 0 ? "NULL" : myLaneBefore->getID()) << "'->'" << (myLane == 0 ? "NULL" : myLane->getID()) << std::endl;
421  std::cout << "' Removing approaching vehicle '" << veh->getID() << "'\nCurrently registered vehicles:" << std::endl;
422  for (auto i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
423  std::cout << "'" << i->first->getID() << "'" << std::endl;
424  }
425  }
426 #endif
427  myApproachingVehicles.erase(veh);
428 }
429 
430 
433  auto i = myApproachingVehicles.find(veh);
434  if (i != myApproachingVehicles.end()) {
435  return i->second;
436  } else {
437  return ApproachingVehicleInformation(-1000, -1000, 0, 0, false, -1000, 0, 0, 0, 0);
438  }
439 }
440 
441 
442 SUMOTime
443 MSLink::getLeaveTime(const SUMOTime arrivalTime, const double arrivalSpeed,
444  const double leaveSpeed, const double vehicleLength) const {
445  return arrivalTime + TIME2STEPS((getLength() + vehicleLength) / MAX2(0.5 * (arrivalSpeed + leaveSpeed), NUMERICAL_EPS));
446 }
447 
448 
449 bool
450 MSLink::opened(SUMOTime arrivalTime, double arrivalSpeed, double leaveSpeed, double vehicleLength,
451  double impatience, double decel, SUMOTime waitingTime, double posLat,
452  BlockingFoes* collectFoes, bool ignoreRed, const SUMOVehicle* ego) const {
453  if (haveRed() && !ignoreRed) {
454  return false;
455  }
457  return true;
458  }
459  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, vehicleLength);
461  // check for foes on the same lane with the same target edge
462  for (const MSLink* foeLink : mySublaneFoeLinks) {
463  assert(myLane != foeLink->getLane());
464  for (const auto& it : foeLink->myApproachingVehicles) {
465  const SUMOVehicle* foe = it.first;
466  if (
467  // there only is a conflict if the paths cross
468  ((posLat < foe->getLateralPositionOnLane() && myLane->getIndex() > foeLink->myLane->getIndex())
469  || (posLat > foe->getLateralPositionOnLane() && myLane->getIndex() < foeLink->myLane->getIndex()))
470  // the vehicle that arrives later must yield
471  && (arrivalTime > it.second.arrivalTime
472  // if both vehicles arrive at the same time, the one
473  // to the left must yield
474  || (arrivalTime == it.second.arrivalTime && posLat > foe->getLateralPositionOnLane()))) {
475  if (blockedByFoe(foe, it.second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, false,
476  impatience, decel, waitingTime, ego)) {
477 #ifdef MSLink_DEBUG_OPENED
478  if (gDebugFlag1) {
479  std::cout << SIMTIME << " blocked by " << foe->getID() << " arrival=" << arrivalTime << " foeArrival=" << it.second.arrivalTime << "\n";
480  }
481 #endif
482  if (collectFoes == nullptr) {
483 #ifdef MSLink_DEBUG_OPENED
484  if (gDebugFlag1) {
485  std::cout << " link=" << getViaLaneOrLane()->getID() << " blocked by sublaneFoe=" << foe->getID() << " foeLink=" << foeLink->getViaLaneOrLane()->getID() << " posLat=" << posLat << "\n";
486  }
487 #endif
488  return false;
489  } else {
490  collectFoes->push_back(it.first);
491  }
492  }
493  }
494  }
495  }
496  // check for foes on the same lane with a different target edge
497  // (straight movers take precedence if the paths cross)
498  const int lhSign = MSNet::getInstance()->lefthand() ? -1 : 1;
499  for (const MSLink* foeLink : mySublaneFoeLinks2) {
500  assert(myDirection != LINKDIR_STRAIGHT);
501  for (const auto& it : foeLink->myApproachingVehicles) {
502  const SUMOVehicle* foe = it.first;
503  // there only is a conflict if the paths cross
505  && (posLat * lhSign > foe->getLateralPositionOnLane() * lhSign))
507  && (posLat * lhSign < foe->getLateralPositionOnLane() * lhSign))) {
508  if (blockedByFoe(foe, it.second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, false,
509  impatience, decel, waitingTime, ego)) {
510 #ifdef MSLink_DEBUG_OPENED
511  if (gDebugFlag1) {
512  std::cout << SIMTIME << " blocked by sublane foe " << foe->getID() << " arrival=" << arrivalTime << " foeArrival=" << it.second.arrivalTime << "\n";
513  }
514 #endif
515  if (collectFoes == nullptr) {
516  return false;
517  } else {
518  collectFoes->push_back(it.first);
519  }
520  }
521  }
522  }
523  }
524  }
525  if (havePriority() && myState != LINKSTATE_ZIPPER) {
526  // priority usually means the link is open but there are exceptions:
527  // zipper still needs to collect foes
528  // sublane model could have detected a conflict
529  return collectFoes == nullptr || collectFoes->size() == 0;
530  }
531  if ((myState == LINKSTATE_STOP || myState == LINKSTATE_ALLWAY_STOP) && waitingTime == 0) {
532  return false;
533  }
534 
535 #ifdef MSLink_DEBUG_OPENED
536  if (gDebugFlag1) {
537  std::cout << SIMTIME << " opened link=" << getViaLaneOrLane()->getID() << " foeLinks=" << myFoeLinks.size() << "\n";
538  }
539 #endif
540 
541  if (MSGlobals::gUseMesoSim && impatience == 1) {
542  return true;
543  }
544  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
546  if ((*i)->haveRed()) {
547  continue;
548  }
549  }
550 #ifdef MSLink_DEBUG_OPENED
551  if (gDebugFlag1) {
552  std::cout << " foeLink=" << (*i)->getViaLaneOrLane()->getID() << " numApproaching=" << (*i)->getApproaching().size() << "\n";
553  }
554 #endif
555  if ((*i)->blockedAtTime(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, myLane == (*i)->getLane(),
556  impatience, decel, waitingTime, collectFoes, ego)) {
557  return false;
558  }
559  }
560  if (collectFoes != nullptr && collectFoes->size() > 0) {
561  return false;
562  }
563  return true;
564 }
565 
566 
567 bool
568 MSLink::blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
569  bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
570  BlockingFoes* collectFoes, const SUMOVehicle* ego) const {
571  for (const auto& it : myApproachingVehicles) {
572 #ifdef MSLink_DEBUG_OPENED
573  if (gDebugFlag1) {
574  if (ego != nullptr
575  && ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_FOE_SPEED, 0) >= it.second.speed
577  std::stringstream stream; // to reduce output interleaving from different threads
578  stream << SIMTIME << " " << myApproachingVehicles.size() << " foe link=" << getViaLaneOrLane()->getID()
579  << " foeVeh=" << it.first->getID() << " (below ignore speed)"
580  << " ignoreFoeProb=" << ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_FOE_PROB, 0)
581  << "\n";
582  std::cout << stream.str();
583  }
584  }
585 #endif
586  if (it.first != ego
587  && (ego == nullptr
589  || ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_FOE_SPEED, 0) < it.second.speed
591  && blockedByFoe(it.first, it.second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, sameTargetLane,
592  impatience, decel, waitingTime, ego)) {
593  if (collectFoes == nullptr) {
594  return true;
595  } else {
596  collectFoes->push_back(it.first);
597  }
598  }
599  }
600  return false;
601 }
602 
603 
604 bool
606  SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
607  bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
608  const SUMOVehicle* ego) const {
609 #ifdef MSLink_DEBUG_OPENED
610  if (gDebugFlag1) {
611  std::stringstream stream; // to reduce output interleaving from different threads
612  stream << " foe link=" << getViaLaneOrLane()->getID()
613  << " foeVeh=" << veh->getID()
614  << " req=" << avi.willPass
615  << " aT=" << avi.arrivalTime
616  << " lT=" << avi.leavingTime
617  << "\n";
618  std::cout << stream.str();
619  }
620 #endif
621  if (!avi.willPass) {
622  return false;
623  }
625  assert(waitingTime > 0);
626  if (waitingTime > avi.waitingTime) {
627  return false;
628  }
629  if (waitingTime == avi.waitingTime && arrivalTime < avi.arrivalTime) {
630  return false;
631  }
632  }
633  const SUMOTime foeArrivalTime = (SUMOTime)((1.0 - impatience) * avi.arrivalTime + impatience * avi.arrivalTimeBraking);
634  const SUMOTime lookAhead = (myState == LINKSTATE_ZIPPER
636  : (ego == nullptr
639  //if (ego != 0) std::cout << SIMTIME << " ego=" << ego->getID() << " jmTimegapMinor=" << ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_TIMEGAP_MINOR, -1) << " lookAhead=" << lookAhead << "\n";
640 #ifdef MSLink_DEBUG_OPENED
641  if (gDebugFlag1) {
642  std::stringstream stream; // to reduce output interleaving from different threads
643  stream << " imp=" << impatience << " fATb=" << avi.arrivalTimeBraking << " fAT2=" << foeArrivalTime << " lA=" << lookAhead << " egoAT=" << arrivalTime << " egoLT=" << leaveTime << "\n";
644  std::cout << stream.str();
645  }
646 #endif
647  if (avi.leavingTime < arrivalTime) {
648  // ego wants to be follower
649  if (sameTargetLane && (arrivalTime - avi.leavingTime < lookAhead
650  || unsafeMergeSpeeds(avi.leaveSpeed, arrivalSpeed,
651  veh->getVehicleType().getCarFollowModel().getMaxDecel(), decel))) {
652 #ifdef MSLink_DEBUG_OPENED
653  if (gDebugFlag1) {
654  std::cout << " blocked (cannot follow)\n";
655  }
656 #endif
657  return true;
658  }
659  } else if (foeArrivalTime > leaveTime + lookAhead) {
660  // ego wants to be leader.
661  if (sameTargetLane && unsafeMergeSpeeds(leaveSpeed, avi.arrivalSpeedBraking,
662  decel, veh->getVehicleType().getCarFollowModel().getMaxDecel())) {
663 #ifdef MSLink_DEBUG_OPENED
664  if (gDebugFlag1) {
665  std::cout << " blocked (cannot lead)\n";
666  }
667 #endif
668  return true;
669  }
670  } else {
671  // even without considering safeHeadwayTime there is already a conflict
672 #ifdef MSLink_DEBUG_OPENED
673  if (gDebugFlag1) {
674  std::cout << " blocked (hard conflict)\n";
675  }
676 #endif
677  return true;
678  }
679  return false;
680 }
681 
682 
683 bool
684 MSLink::hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, double speed, double decel) const {
685  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
686  if ((*i)->blockedAtTime(arrivalTime, leaveTime, speed, speed, myLane == (*i)->getLane(), 0, decel, 0)) {
687  return true;
688  }
689  }
690  for (std::vector<const MSLane*>::const_iterator i = myFoeLanes.begin(); i != myFoeLanes.end(); ++i) {
691  if ((*i)->getVehicleNumberWithPartials() > 0) {
692  return true;
693  }
694  }
695  return false;
696 }
697 
698 
699 std::pair<const SUMOVehicle*, const MSLink*>
701  double closetDist = std::numeric_limits<double>::max();
702  const SUMOVehicle* closest = nullptr;
703  const MSLink* foeLink = nullptr;
704  for (MSLink* link : myFoeLinks) {
705  for (const auto& it : link->myApproachingVehicles) {
706  if (it.second.dist < closetDist) {
707  closetDist = it.second.dist;
708  if (it.second.willPass) {
709  closest = it.first;
710  foeLink = link;
711  }
712  }
713  }
714  }
715  return std::make_pair(closest, foeLink);
716 }
717 
718 
721  return myDirection;
722 }
723 
724 
725 void
727  if (myState != state) {
728  myLastStateChange = t;
729  }
730  myState = state;
731 }
732 
733 
734 MSLane*
736  return myLane;
737 }
738 
739 
740 bool
741 MSLink::isCont() const {
742  // when a traffic light is switched off minor roads have their cont status revoked
744 }
745 
746 
747 bool
749  if (myInternalLane == nullptr || myAmCont || myHavePedestrianCrossingFoe) {
750  return false;
751  } else {
753  if (!pred->getEdge().isInternal()) {
754  return false;
755  } else {
756  MSLane* pred2 = pred->getLogicalPredecessorLane();
757  assert(pred2 != 0);
758  MSLink* predLink = MSLinkContHelper::getConnectingLink(*pred2, *pred);
759  assert(predLink != 0);
760  return predLink->havePriority() || predLink->haveYellow();
761  }
762  }
763 }
764 
765 
766 void
767 MSLink::writeApproaching(OutputDevice& od, const std::string fromLaneID) const {
768  if (myApproachingVehicles.size() > 0) {
769  od.openTag("link");
770  od.writeAttr(SUMO_ATTR_FROM, fromLaneID);
771  const std::string via = getViaLane() == nullptr ? "" : getViaLane()->getID();
772  od.writeAttr(SUMO_ATTR_VIA, via);
773  od.writeAttr(SUMO_ATTR_TO, getLane() == nullptr ? "" : getLane()->getID());
774  std::vector<std::pair<SUMOTime, const SUMOVehicle*> > toSort; // stabilize output
775  for (auto it : myApproachingVehicles) {
776  toSort.push_back(std::make_pair(it.second.arrivalTime, it.first));
777  }
778  std::sort(toSort.begin(), toSort.end());
779  for (std::vector<std::pair<SUMOTime, const SUMOVehicle*> >::const_iterator it = toSort.begin(); it != toSort.end(); ++it) {
780  od.openTag("approaching");
781  const ApproachingVehicleInformation& avi = myApproachingVehicles.find(it->second)->second;
782  od.writeAttr(SUMO_ATTR_ID, it->second->getID());
783  od.writeAttr(SUMO_ATTR_IMPATIENCE, it->second->getImpatience());
784  od.writeAttr("arrivalTime", time2string(avi.arrivalTime));
785  od.writeAttr("arrivalTimeBraking", time2string(avi.arrivalTimeBraking));
786  od.writeAttr("leaveTime", time2string(avi.leavingTime));
787  od.writeAttr("arrivalSpeed", toString(avi.arrivalSpeed));
788  od.writeAttr("arrivalSpeedBraking", toString(avi.arrivalSpeedBraking));
789  od.writeAttr("leaveSpeed", toString(avi.leaveSpeed));
790  od.writeAttr("willPass", toString(avi.willPass));
791  od.closeTag();
792  }
793  od.closeTag();
794  }
795 }
796 
797 
798 double
800  double len = 0.;
801  MSLane* lane = myInternalLane;
802 
803  while (lane != nullptr && lane->isInternal()) {
804  len += lane->getLength();
805  lane = lane->getLinkCont()[0]->getViaLane();
806  }
807  return len;
808 }
809 
810 double
812  double len = 0.;
813  const MSLane* lane = myInternalLane;
814 
815  while (lane != nullptr && lane->isInternal()) {
816  len += lane->getLength();
817  if (lane->getIncomingLanes().size() == 1) {
818  lane = lane->getIncomingLanes()[0].lane;
819  } else {
820  break;
821  }
822  }
823  return len;
824 }
825 
826 
827 double
829  MSLane* via = myInternalLane;
830  double totalDist = 0.;
831  bool foundCrossing = false;
832  while (via != nullptr) {
833  MSLink* link = via->getLinkCont()[0];
834  double dist = link->getLengthBeforeCrossing(foeLane);
835  if (dist != INVALID_DOUBLE) {
836  // found conflicting lane
837  totalDist += dist;
838  foundCrossing = true;
839  break;
840  } else {
841  totalDist += via->getLength();
842  via = link->getViaLane();
843  }
844  }
845  if (foundCrossing) {
846  return totalDist;
847  } else {
848  return INVALID_DOUBLE;
849  }
850 }
851 
852 
853 double
855  int foe_ix;
856  for (foe_ix = 0; foe_ix != (int)myFoeLanes.size(); ++foe_ix) {
857  if (myFoeLanes[foe_ix] == foeLane) {
858  break;
859  }
860  }
861  if (foe_ix == (int)myFoeLanes.size()) {
862  // no conflict with the given lane, indicate by returning -1
863 #ifdef MSLink_DEBUG_CROSSING_POINTS
864  std::cout << "No crossing of lanes '" << foeLane->getID() << "' and '" << myInternalLaneBefore->getID() << "'" << std::endl;
865 #endif
866  return INVALID_DOUBLE;
867  } else {
868  // found conflicting lane index
869  double dist = myInternalLaneBefore->getLength() - myLengthsBehindCrossing[foe_ix].first;
870  if (dist == -10000.) {
871  // this is the value in myLengthsBehindCrossing, if the relation allows intersection but none is present for the actual geometry.
872  return INVALID_DOUBLE;
873  }
874 #ifdef MSLink_DEBUG_CROSSING_POINTS
875  std::cout << "Crossing of lanes '" << myInternalLaneBefore->getID() << "' and '" << foeLane->getID()
876  << "' at distance " << dist << " (approach along '"
877  << myInternalLaneBefore->getEntryLink()->getLaneBefore()->getID() << "')" << std::endl;
878 #endif
879  return dist;
880  }
881 }
882 
883 
884 MSLane*
886  return myInternalLane;
887 }
888 
889 
890 bool
893  return myInternalLane != nullptr && myInternalLaneBefore == nullptr;
894  } else {
895  return false;
896  }
897 }
898 
899 bool
901  // either a non-cont entry link or the link after a cont-link
902  return !myAmCont && (isEntryLink() || (myInternalLaneBefore != nullptr && myInternalLane != nullptr));
903 }
904 
905 bool
908  return myInternalLaneBefore != nullptr && myInternalLane == nullptr;
909  } else {
910  return false;
911  }
912 }
913 
914 bool
917  return (getInternalLaneBefore() != nullptr
918  && myInternalLaneBefore->getIncomingLanes().size() == 1
919  && myInternalLaneBefore->getIncomingLanes().front().viaLink->isInternalJunctionLink());
920  } else {
921  return false;
922  }
923 }
924 
925 
926 MSLink*
928  MSLane* lane = myInternalLane;
929  MSLink* link = nullptr;
930  while (lane != nullptr) {
931  link = lane->getLinkCont()[0];
932  lane = link->getViaLane();
933  }
934  return link;
935 }
936 
937 
938 bool
940  return getInternalLaneBefore() != nullptr && myInternalLane != nullptr;
941 }
942 
943 bool
945  return myInternalLaneBefore != nullptr;
946 }
947 
949 MSLink::getLeaderInfo(const MSVehicle* ego, double dist, std::vector<const MSPerson*>* collectBlockers, bool isShadowLink) const {
950  LinkLeaders result;
951  if (ego != nullptr && ego->getLaneChangeModel().isOpposite()) {
952  // ignore link leaders
953  return result;
954  }
955  //gDebugFlag1 = true;
956  // this link needs to start at an internal lane (either an exit link or between two internal lanes)
957  // or it must be queried by the pedestrian model (ego == 0)
958  if (fromInternalLane() || ego == nullptr) {
959  if (gDebugFlag1) {
960  std::cout << SIMTIME << " getLeaderInfo link=" << getViaLaneOrLane()->getID() << " dist=" << dist << " isShadowLink=" << isShadowLink << "\n";
961  }
962  // this is an exit link
963  for (int i = 0; i < (int)myFoeLanes.size(); ++i) {
964  const MSLane* foeLane = myFoeLanes[i];
965  // distance from the querying vehicle to the crossing point with foeLane
966  double distToCrossing = dist - myLengthsBehindCrossing[i].first;
967  const bool sameTarget = (myLane == foeLane->getLinkCont()[0]->getLane()) && !isInternalJunctionLink();
968  const bool sameSource = (myInternalLaneBefore != nullptr && myInternalLaneBefore->getLogicalPredecessorLane() == foeLane->getLogicalPredecessorLane());
969  const double crossingWidth = (sameTarget || sameSource) ? 0 : foeLane->getWidth();
970  const double foeCrossingWidth = (sameTarget || sameSource) ? 0 : myInternalLaneBefore->getWidth();
971  if (gDebugFlag1) {
972  std::cout << " distToCrossing=" << distToCrossing << " foeLane=" << foeLane->getID() << " cWidth=" << crossingWidth
973  << " ijl=" << isInternalJunctionLink() << " sT=" << sameTarget << " sS=" << sameSource
974  << " lbc=" << myLengthsBehindCrossing[i].first
975  << " flbc=" << myLengthsBehindCrossing[i].second
976  << "\n";
977  }
978  // special treatment of contLane foe only applies if this lane is not a contLane or contLane follower itself
979  const bool contLane = (foeLane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().isInternal() && !(
981  if (distToCrossing + crossingWidth < 0
982  && (ego == nullptr || !MSGlobals::gComputeLC || distToCrossing + crossingWidth + ego->getVehicleType().getLength() < 0)) {
983  continue; // vehicle is behind the crossing point, continue with next foe lane
984  }
985  const double foeDistToCrossing = foeLane->getLength() - myLengthsBehindCrossing[i].second;
986  // it is not sufficient to return the last vehicle on the foeLane because ego might be its leader
987  // therefore we return all vehicles on the lane
988  //
989  // special care must be taken for continuation lanes. (next lane is also internal)
990  // vehicles on these lanes should always block (gap = -1)
991  // vehicles on cont. lanes or on internal lanes with the same target as this link can never be ignored
993  for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != end; ++it_veh) {
994  MSVehicle* leader = (MSVehicle*)*it_veh;
995  const double leaderBack = leader->getBackPositionOnLane(foeLane);
996  const double leaderBackDist = foeDistToCrossing - leaderBack;
997  const bool pastTheCrossingPoint = leaderBackDist + foeCrossingWidth < 0;
998  const bool ignoreIndirectBicycleTurn = (pastTheCrossingPoint
999  && leader->getVehicleType().getVehicleClass() == SVC_BICYCLE
1000  && foeLane->getIncomingLanes().front().viaLink->getDirection() == LINKDIR_LEFT);
1001  const bool cannotIgnore = ((contLane && !ignoreIndirectBicycleTurn) || sameTarget || sameSource) && ego != nullptr;
1002  const bool inTheWay = !pastTheCrossingPoint && leaderBackDist < leader->getVehicleType().getLength();
1003  const bool isOpposite = leader->getLaneChangeModel().isOpposite();
1004  if (gDebugFlag1) {
1005  std::cout << " candiate leader=" << leader->getID()
1006  << " cannotIgnore=" << cannotIgnore
1007  << " fdtc=" << foeDistToCrossing
1008  << " lb=" << leaderBack
1009  << " lbd=" << leaderBackDist
1010  << " fcwidth=" << foeCrossingWidth
1011  << " foePastCP=" << pastTheCrossingPoint
1012  << " inTheWay=" << inTheWay
1013  << " willPass=" << foeLane->getLinkCont()[0]->getApproaching(leader).willPass
1014  << " isFrontOnLane=" << leader->isFrontOnLane(foeLane)
1015  << " isOpposite=" << isOpposite << "\n";
1016  }
1017  if (leader == ego) {
1018  continue;
1019  }
1020  // after entering the conflict area, ignore foe vehicles that are not in the way
1021  if (distToCrossing < -POSITION_EPS && !inTheWay
1022  && (ego == nullptr || !MSGlobals::gComputeLC || distToCrossing < -ego->getVehicleType().getLength())) {
1023  continue;
1024  }
1025  // ignore foe vehicles that will not pass
1026  if ((!cannotIgnore || leader->isStopped() || sameTarget)
1027  && !foeLane->getLinkCont()[0]->getApproaching(leader).willPass
1028  && leader->isFrontOnLane(foeLane)
1029  && !isOpposite
1030  && !inTheWay
1031  // willPass is false if the vehicle is already on the stopping edge
1032  && !leader->willStop()) {
1033  continue;
1034  }
1035  if (cannotIgnore || inTheWay || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
1036  // compute distance between vehicles on the the superimposition of both lanes
1037  // where the crossing point is the common point
1038  double gap;
1039  bool fromLeft = true;
1040  if (ego == nullptr) {
1041  // request from pedestrian model. return distance between leaderBack and crossing point
1042  //std::cout << " foeLane=" << foeLane->getID() << " leaderBack=" << leaderBack << " foeDistToCrossing=" << foeDistToCrossing << " foeLength=" << foeLane->getLength() << " foebehind=" << myLengthsBehindCrossing[i].second << " dist=" << dist << " behind=" << myLengthsBehindCrossing[i].first << "\n";
1043  gap = leaderBackDist;
1044  // distToCrossing should not take into account the with of the foe lane
1045  // (which was subtracted in setRequestInformation)
1046  // Instead, the width of the foe vehicle is used directly by the caller.
1047  distToCrossing += foeLane->getWidth() / 2;
1048  if (gap + foeCrossingWidth < 0) {
1049  // leader is completely past the crossing point
1050  // or there is no crossing point
1051  continue; // next vehicle
1052  }
1053  // we need to determine whether the vehicle passes the
1054  // crossing from the left or the right (heuristic)
1055  fromLeft = foeDistToCrossing > 0.5 * foeLane->getLength();
1056  } else if ((contLane && !sameSource && !ignoreIndirectBicycleTurn) || isOpposite) {
1057  gap = -1; // always break for vehicles which are on a continuation lane or for opposite-direction vehicles
1058  } else {
1059  if (gDebugFlag1) {
1060  std::cout << " distToCrossing=" << distToCrossing << " leader back=" << leaderBack << " backDist=" << leaderBackDist
1061  << " blockedStrategic=" << leader->getLaneChangeModel().isStrategicBlocked()
1062  //<< " stateRight=" << toString((LaneChangeAction)leader->getLaneChangeModel().getSavedState(-1).second)
1063  << "\n";
1064  }
1065  if (leaderBackDist + foeCrossingWidth < 0) {
1066  // leader is completely past the crossing point
1067  // or there is no crossing point
1068  continue; // next vehicle
1069  }
1070  gap = distToCrossing - ego->getVehicleType().getMinGap() - leaderBackDist - foeCrossingWidth;
1071  if (gap < leader->getVehicleType().getLength() && leader->getLaneChangeModel().isStrategicBlocked()) {
1072  // do not encroach on leader when it tries to change lanes
1073  gap = -1;
1074  }
1075  }
1076  // if the foe is already moving off the intersection, we may
1077  // advance up to the crossing point unless we have the same target or same source
1078  // (for sameSource, the crossing point indicates the point of divergence)
1079  const bool stopAsap = leader->isFrontOnLane(foeLane) ? cannotIgnore : (sameTarget || sameSource);
1080  if (gDebugFlag1) {
1081  std::cout << " leader=" << leader->getID() << " contLane=" << contLane << " cannotIgnore=" << cannotIgnore << " stopAsap=" << stopAsap << "\n";
1082  }
1083  result.push_back(LinkLeader(leader, gap, stopAsap ? -1 : distToCrossing, fromLeft));
1084  }
1085 
1086  }
1087  if (ego != nullptr && MSNet::getInstance()->hasPersons()) {
1088  // check for crossing pedestrians (keep driving if already on top of the crossing
1089  const double distToPeds = distToCrossing - MSPModel::SAFETY_GAP;
1090  const double vehWidth = ego->getVehicleType().getWidth() + MSPModel::SAFETY_GAP; // + configurable safety gap
1092  // @check lefthand?!
1093  const bool wayIn = myLengthsBehindCrossing[i].first < myLaneBefore->getLength() * 0.5;
1094  const double vehSideOffset = (foeDistToCrossing + myLaneBefore->getWidth() * 0.5 - vehWidth * 0.5
1095  + ego->getLateralPositionOnLane() * (wayIn ? -1 : 1));
1096  if (distToPeds >= -MSPModel::SAFETY_GAP && MSPModel::getModel()->blockedAtDist(foeLane, vehSideOffset, vehWidth,
1098  collectBlockers)) {
1099  result.push_back(LinkLeader((MSVehicle*)nullptr, -1, distToPeds));
1100  }
1101  }
1102  }
1103 
1104  //std::cout << SIMTIME << " ego=" << Named::getIDSecure(ego) << " link=" << getViaLaneOrLane()->getID() << " myWalkingAreaFoe=" << Named::getIDSecure(myWalkingAreaFoe) << "\n";
1105  if (ego != nullptr) {
1106  checkWalkingAreaFoe(ego, myWalkingAreaFoe, collectBlockers, result);
1107  checkWalkingAreaFoe(ego, myWalkingAreaFoeExit, collectBlockers, result);
1108  }
1109 
1110  if (MSGlobals::gLateralResolution > 0 && ego != nullptr && !isShadowLink) {
1111  // check for foes on the same lane
1112  for (std::vector<MSLane*>::const_iterator it = mySublaneFoeLanes.begin(); it != mySublaneFoeLanes.end(); ++it) {
1113  const MSLane* foeLane = *it;
1114  MSLane::AnyVehicleIterator end = foeLane->anyVehiclesEnd();
1115  for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != end; ++it_veh) {
1116  MSVehicle* leader = (MSVehicle*)*it_veh;
1117  if (leader == ego) {
1118  continue;
1119  }
1120  const double maxLength = MAX2(myInternalLaneBefore->getLength(), foeLane->getLength());
1121  const double gap = dist - maxLength - ego->getVehicleType().getMinGap() + leader->getBackPositionOnLane(foeLane);
1122  if (gap < -(ego->getVehicleType().getMinGap() + leader->getLength())) {
1123  // ego is ahead of leader
1124  continue;
1125  }
1126 
1127  const double posLat = ego->getLateralPositionOnLane();
1128  const double posLatLeader = leader->getLateralPositionOnLane() + leader->getLatOffset(foeLane);
1129  if (gDebugFlag1) {
1130  std::cout << " sublaneFoe lane=" << myInternalLaneBefore->getID()
1131  << " foeLane=" << foeLane->getID()
1132  << " leader=" << leader->getID()
1133  << " egoLane=" << ego->getLane()->getID()
1134  << " leaderLane=" << leader->getLane()->getID()
1135  << " egoLat=" << posLat
1136  << " leaderLat=" << posLatLeader
1137  << " leaderLatOffset=" << leader->getLatOffset(foeLane)
1138  << " egoIndex=" << myInternalLaneBefore->getIndex()
1139  << " foeIndex=" << foeLane->getIndex()
1140  << " dist=" << dist
1141  << " leaderBack=" << leader->getBackPositionOnLane(foeLane)
1142  << "\n";
1143  }
1144  // there only is a conflict if the paths cross
1145  if ((posLat < posLatLeader && myInternalLaneBefore->getIndex() > foeLane->getIndex())
1146  || (posLat > posLatLeader && myInternalLaneBefore->getIndex() < foeLane->getIndex())) {
1147  if (gDebugFlag1) {
1148  std::cout << SIMTIME << " blocked by " << leader->getID() << " (sublane split) foeLane=" << foeLane->getID() << "\n";
1149  }
1150  result.push_back(LinkLeader(leader, gap, -1));
1151  }
1152  }
1153  }
1154  }
1155  }
1156  return result;
1157 }
1158 
1159 
1160 void
1161 MSLink::checkWalkingAreaFoe(const MSVehicle* ego, const MSLane* foeLane, std::vector<const MSPerson*>* collectBlockers, LinkLeaders& result) const {
1162  if (foeLane != nullptr && foeLane->getEdge().getPersons().size() > 0) {
1163  // pedestrians may be on an arbitrary path across this
1164  // walkingarea. make sure to keep enough distance.
1165  // This is a simple but conservative solution that could be improved
1166  // by ignoring pedestrians that are "obviously" not on a collision course
1167  double distToPeds = std::numeric_limits<double>::max();
1168  for (MSTransportable* t : foeLane->getEdge().getPersons()) {
1169  MSPerson* p = static_cast<MSPerson*>(t);
1170  const double dist = ego->getPosition().distanceTo2D(p->getPosition()) - p->getVehicleType().getLength();
1171  if (p->getSpeed() > 0 || dist < MSPModel::SAFETY_GAP / 2) {
1172  distToPeds = MIN2(distToPeds, dist - MSPModel::SAFETY_GAP);
1173  if (collectBlockers != nullptr) {
1174  collectBlockers->push_back(p);
1175  }
1176  }
1177  }
1178  if (distToPeds != std::numeric_limits<double>::max()) {
1179  result.push_back(LinkLeader((MSVehicle*)nullptr, -1, distToPeds));
1180  }
1181  }
1182 }
1183 
1184 
1185 MSLane*
1187  if (myInternalLane != nullptr) {
1188  return myInternalLane;
1189  }
1190  return myLane;
1191 }
1192 
1193 
1194 const MSLane*
1196  if (myInternalLaneBefore != nullptr) {
1198  throw ProcessError("lane before mismatch!");
1199  }
1200  }
1201  return myLaneBefore;
1202 }
1203 
1204 
1205 MSLink*
1206 MSLink::getParallelLink(int direction) const {
1207  if (direction == -1) {
1208  return myParallelRight;
1209  } else if (direction == 1) {
1210  return myParallelLeft;
1211  } else {
1212  assert(false);
1213  return nullptr;
1214  }
1215 }
1216 
1217 
1218 MSLink*
1220  MSLane* before = getLaneBefore()->getParallelLane(direction);
1221  MSLane* after = getLane()->getParallelLane(direction);
1222  if (before != nullptr && after != nullptr) {
1223  return MSLinkContHelper::getConnectingLink(*before, *after);
1224  } else {
1225  return nullptr;
1226  }
1227 }
1228 
1229 
1230 const MSLane*
1232  return myInternalLaneBefore;
1233 }
1234 
1235 
1236 double
1237 MSLink::getZipperSpeed(const MSVehicle* ego, const double dist, double vSafe,
1238  SUMOTime arrivalTime,
1239  BlockingFoes* collectFoes) const {
1240  if (myFoeLinks.size() == 0) {
1241  // link should have LINKSTATE_MAJOR in this case
1242  assert(false);
1243  return vSafe;
1244  } else if (myFoeLinks.size() > 1) {
1245  throw ProcessError("Zipper junctions with more than two conflicting lanes are not supported (at junction '"
1246  + myJunction->getID() + "')");
1247  }
1249  const double secondsToArrival = STEPS2TIME(arrivalTime - now);
1250  if (secondsToArrival > ZIPPER_ADAPT_TIME && dist > ZIPPER_ADAPT_DIST) {
1251 #ifdef DEBUG_ZIPPER
1252  if (DEBUG_COND_ZIPPER) DEBUGOUT(SIMTIME << " getZipperSpeed ego=" << ego->getID()
1253  << " dist=" << dist << " ignoring foes (arrival in " << STEPS2TIME(arrivalTime - now) << ")\n")
1254 #endif
1255  return vSafe;
1256  }
1257 #ifdef DEBUG_ZIPPER
1258  if (DEBUG_COND_ZIPPER) DEBUGOUT(SIMTIME << " getZipperSpeed ego=" << ego->getID()
1259  << " egoAT=" << arrivalTime
1260  << " dist=" << dist
1261  << " vSafe=" << vSafe
1262  << " numFoes=" << collectFoes->size()
1263  << "\n")
1264 #endif
1265  MSLink* foeLink = myFoeLinks[0];
1266  for (const auto& item : *collectFoes) {
1267  const MSVehicle* foe = dynamic_cast<const MSVehicle*>(item);
1268  assert(foe != 0);
1269  const ApproachingVehicleInformation& avi = foeLink->getApproaching(foe);
1270  const double foeDist = (foe->isActive() ? avi.dist : MAX2(0.0, avi.dist -
1271  STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - foe->getLastActionTime()) * avi.speed));
1272 
1273  if ( // ignore vehicles that arrive after us (unless they are ahead and we could easily brake for them)
1274  ((avi.arrivalTime > arrivalTime) && !couldBrakeForLeader(dist, foeDist, ego, foe)) ||
1275  // also ignore vehicles that are behind us and are able to brake for us
1276  couldBrakeForLeader(foeDist, dist, foe, ego) ||
1277  // resolve ties by lane index
1278  (avi.arrivalTime == arrivalTime && foeDist == dist && ego->getLane()->getIndex() < foe->getLane()->getIndex())) {
1279 #ifdef DEBUG_ZIPPER
1280  if (DEBUG_COND_ZIPPER) std::cout
1281  << " ignoring foe=" << foe->getID()
1282  << " foeAT=" << avi.arrivalTime
1283  << " foeDist=" << avi.dist
1284  << " foeDist2=" << foeDist
1285  << " foeSpeed=" << avi.speed
1286  << " egoSpeed=" << ego->getSpeed()
1287  << " deltaDist=" << foeDist - dist
1288  << " delteSpeed=" << avi.speed - foe->getCarFollowModel().getMaxDecel() - ego->getSpeed()
1289  << " egoCouldBrake=" << couldBrakeForLeader(dist, foeDist, ego, foe)
1290  << " foeCouldBrake=" << couldBrakeForLeader(foeDist, dist, foe, ego)
1291  << "\n";
1292 #endif
1293  continue;
1294  }
1295  // the idea behind speed adaption is three-fold:
1296  // 1) ego needs to be in a car-following relationship with foe eventually
1297  // thus, the ego speed should be equal to the follow speed once the foe enters
1298  // the zipper junction
1299  // 2) ego vehicle needs to put a certain distance beteen himself and foe (safeGap)
1300  // achieving this distance can be spread over time but computing
1301  // safeGap is subject to estimation errors of future speeds
1302  // 3) deceleration can be spread out over the time until true
1303  // car-following happens, at the start of speed adaptions, smaller
1304  // decelerations should be sufficient
1305 
1306  // we cannot trust avi.arrivalSpeed if the foe has leader vehicles that are accelerating
1307  // lets try to extrapolate
1308  const double uMax = foe->getLane()->getVehicleMaxSpeed(foe);
1309  const double uAccel = foe->getCarFollowModel().estimateSpeedAfterDistance(foeDist, avi.speed, foe->getCarFollowModel().getMaxAccel());
1310  const double uEnd = MIN2(uMax, uAccel);
1311  const double uAvg = (avi.speed + uEnd) / 2;
1312  const double tf0 = foeDist / MAX2(NUMERICAL_EPS, uAvg);
1313  const double tf = MAX2(1.0, ceil((tf0) / TS) * TS);
1314 
1315  const double vMax = ego->getLane()->getVehicleMaxSpeed(ego);
1316  const double vAccel = ego->getCarFollowModel().estimateSpeedAfterDistance(dist, ego->getSpeed(), ego->getCarFollowModel().getMaxAccel());
1317  const double vEnd = MIN3(vMax, vAccel, uEnd);
1318  const double vAvg = (ego->getSpeed() + vEnd) / 2;
1319  const double te0 = dist / MAX2(NUMERICAL_EPS, vAvg);
1320  const double te = MAX2(1.0, ceil((te0) / TS) * TS);
1321 
1322  const double gap = dist - foe->getVehicleType().getLength() - ego->getVehicleType().getMinGap() - foeDist;
1323  const double safeGap = ego->getCarFollowModel().getSecureGap(ego, foe, vEnd, uEnd, foe->getCarFollowModel().getMaxDecel());
1324  // round t to next step size
1325  // increase gap to safeGap by the time foe reaches link
1326  // gap + u*t - (t * v + a * t^2 / 2) = safeGap
1327  const double deltaGap = gap + tf * uAvg - safeGap - vAvg * tf;
1328  const double a = 2 * deltaGap / (tf * tf);
1329  const double vSafeGap = ego->getSpeed() + ACCEL2SPEED(a);
1330  const double vFollow = ego->getCarFollowModel().followSpeed(
1331  ego, ego->getSpeed(), gap, avi.speed, foe->getCarFollowModel().getMaxDecel(), foe);
1332 
1333  // scale behavior based on ego time to link (te)
1334  const double w = MIN2(1.0, te / 10);
1335  const double maxDecel = w * ego->getCarFollowModel().getMaxDecel() + (1 - w) * ego->getCarFollowModel().getEmergencyDecel();
1336  const double vZipper = MAX3(vFollow, ego->getSpeed() - ACCEL2SPEED(maxDecel), w * vSafeGap + (1 - w) * vFollow);
1337 
1338  vSafe = MIN2(vSafe, vZipper);
1339 #ifdef DEBUG_ZIPPER
1340  if (DEBUG_COND_ZIPPER) std::cout << " adapting to foe=" << foe->getID()
1341  << " foeDist=" << foeDist
1342  << " foeSpeed=" << avi.speed
1343  << " foeAS=" << avi.arrivalSpeed
1344  << " egoSpeed=" << ego->getSpeed()
1345  << " uMax=" << uMax
1346  << " uAccel=" << uAccel
1347  << " uEnd=" << uEnd
1348  << " uAvg=" << uAvg
1349  << " gap=" << gap
1350  << " safeGap=" << safeGap
1351  << "\n "
1352  << " tf=" << tf
1353  << " te=" << te
1354  << " dg=" << deltaGap
1355  << " aSafeGap=" << a
1356  << " vMax=" << vMax
1357  << " vAccel=" << vAccel
1358  << " vEnd=" << vEnd
1359  << " vSafeGap=" << vSafeGap
1360  << " vFollow=" << vFollow
1361  << " w=" << w
1362  << " maxDecel=" << maxDecel
1363  << " vZipper=" << vZipper
1364  << " vSafe=" << vSafe
1365  << "\n";
1366 #endif
1367  }
1368  return vSafe;
1369 }
1370 
1371 
1372 bool
1373 MSLink::couldBrakeForLeader(double followDist, double leaderDist, const MSVehicle* follow, const MSVehicle* leader) {
1374  return (// leader is ahead of follower
1375  followDist > leaderDist &&
1376  // and follower could brake for 1 s to stay behind leader
1377  followDist - leaderDist > follow->getSpeed() - follow->getCarFollowModel().getMaxDecel() - leader->getSpeed());
1378 }
1379 
1380 
1381 void
1385 }
1386 
1387 bool
1389  // check whether this link gets to keep its cont status switching the tls off
1390  // @note: this could also be pre-computed in netconvert
1391  // we check whether there is any major link from this edge
1392  for (const MSLane* cand : myLaneBefore->getEdge().getLanes()) {
1393  for (const MSLink* link : cand->getLinkCont()) {
1394  if (link->getOffState() == LINKSTATE_TL_OFF_NOSIGNAL) {
1395  return true;
1396  }
1397  }
1398  }
1399  return false;
1400 }
1401 
1402 std::string
1404  return myLaneBefore->getID() + "->" + getViaLaneOrLane()->getID();
1405 }
1406 
1407 /****************************************************************************/
1408 
MSCFModel::getMaxAccel
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition: MSCFModel.h:209
MIN2
T MIN2(T a, T b)
Definition: StdDefs.h:73
MSEdge::getPersons
const std::set< MSTransportable * > & getPersons() const
Returns this edge's persons set.
Definition: MSEdge.h:176
MSCFModel::getMaxDecel
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:217
MSNet.h
MSLane
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
MSVehicle::isStopped
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1737
MSVehicle::isActive
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
Definition: MSVehicle.h:590
SUMOVehicle::getRNG
virtual std::mt19937 * getRNG() const =0
Returns the associated RNG for this vehicle.
LINKSTATE_TL_OFF_BLINKING
@ LINKSTATE_TL_OFF_BLINKING
The link is controlled by a tls which is off and blinks, has to brake.
Definition: SUMOXMLDefinitions.h:1151
MSJunction
The base class for an intersection.
Definition: MSJunction.h:60
OutputDevice
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:63
PositionVector::intersectsAtLengths2D
std::vector< double > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
Definition: PositionVector.cpp:1008
MSGlobals::gComputeLC
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Definition: MSGlobals.h:120
NUMERICAL_EPS
#define NUMERICAL_EPS
Definition: config.h:148
LINKSTATE_TL_OFF_NOSIGNAL
@ LINKSTATE_TL_OFF_NOSIGNAL
The link is controlled by a tls which is off, not blinking, may pass.
Definition: SUMOXMLDefinitions.h:1153
SUMOTrafficObject::getVehicleType
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle's type.
MSVehicle::getLatOffset
double getLatOffset(const MSLane *lane) const
Get the offset that that must be added to interpret myState.myPosLat for the given lane.
Definition: MSVehicle.cpp:5371
ACCEL2SPEED
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:52
MSCFModel::getSecureGap
virtual double getSecureGap(const MSVehicle *const, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.h:329
SUMOTrafficObject::getID
virtual const std::string & getID() const =0
Get the vehicle's ID.
LINKDIR_PARTRIGHT
@ LINKDIR_PARTRIGHT
The link is a partial right direction.
Definition: SUMOXMLDefinitions.h:1190
MSPerson
Definition: MSPerson.h:63
MSPModel::SAFETY_GAP
static const double SAFETY_GAP
Definition: MSPModel.h:110
MSBaseVehicle::getLength
double getLength() const
Returns the vehicle's length.
Definition: MSBaseVehicle.h:410
SUMOTime
long long int SUMOTime
Definition: SUMOTime.h:34
SUMOVehicle
Representation of a vehicle.
Definition: SUMOVehicle.h:60
MSPModel::blockedAtDist
virtual bool blockedAtDist(const MSLane *lane, double vehSide, double vehWidth, double oncomingGap, std::vector< const MSPerson * > *collectBlockers)
whether a pedestrian is blocking the crossing of lane for the given vehicle bondaries
Definition: MSPModel.h:76
SVC_BICYCLE
@ SVC_BICYCLE
vehicle is a bicycle
Definition: SUMOVehicleClass.h:179
DEBUGOUT
#define DEBUGOUT(msg)
Definition: StdDefs.h:135
MSNet::hasPersons
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:353
MSGlobals::gUseMesoSim
static bool gUseMesoSim
Definition: MSGlobals.h:90
SUMO_ATTR_ID
@ SUMO_ATTR_ID
Definition: SUMOXMLDefinitions.h:378
MSEdge.h
MAX3
T MAX3(T a, T b, T c)
Definition: StdDefs.h:93
LinkDirection
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
Definition: SUMOXMLDefinitions.h:1176
MSTransportable
Definition: MSTransportable.h:58
PositionVector
A list of positions.
Definition: PositionVector.h:45
MSVehicle::getCarFollowModel
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:893
SUMO_ATTR_JM_IGNORE_FOE_PROB
@ SUMO_ATTR_JM_IGNORE_FOE_PROB
Definition: SUMOXMLDefinitions.h:619
SUMO_ATTR_JM_TIMEGAP_MINOR
@ SUMO_ATTR_JM_TIMEGAP_MINOR
Definition: SUMOXMLDefinitions.h:621
MSLane::getIncomingLanes
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:818
MSGlobals::gLateralResolution
static double gLateralResolution
Definition: MSGlobals.h:84
MSVehicle.h
OutputDevice::closeTag
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
Definition: OutputDevice.cpp:253
SUMO_ATTR_JM_IGNORE_FOE_SPEED
@ SUMO_ATTR_JM_IGNORE_FOE_SPEED
Definition: SUMOXMLDefinitions.h:618
MSVehicle::getLateralPositionOnLane
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:429
SUMOTime_MIN
#define SUMOTime_MIN
Definition: SUMOTime.h:36
SUMO_ATTR_TO
@ SUMO_ATTR_TO
Definition: SUMOXMLDefinitions.h:640
LINKDIR_RIGHT
@ LINKDIR_RIGHT
The link is a (hard) right direction.
Definition: SUMOXMLDefinitions.h:1186
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:79
MSEdge::isInternal
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:235
MSVehicle::getPosition
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1269
OutputDevice::writeAttr
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:255
MSEdge::getFromJunction
const MSJunction * getFromJunction() const
Definition: MSEdge.h:359
LinkState
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
Definition: SUMOXMLDefinitions.h:1137
RandHelper::rand
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:53
LINKDIR_STRAIGHT
@ LINKDIR_STRAIGHT
The link is a straight direction.
Definition: SUMOXMLDefinitions.h:1178
SIMTIME
#define SIMTIME
Definition: SUMOTime.h:63
MSLane::interpolateGeometryPosToLanePos
double interpolateGeometryPosToLanePos(double geometryPos) const
Definition: MSLane.h:510
MSVehicleType::getCarFollowModel
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
Definition: MSVehicleType.h:140
MSVehicleType::getWidth
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
Definition: MSVehicleType.h:246
TIME2STEPS
#define TIME2STEPS(x)
Definition: SUMOTime.h:58
MSJunction.h
TS
#define TS
Definition: SUMOTime.h:43
MSNet::lefthand
bool lefthand() const
return whether the network was built for lefthand traffic
Definition: MSNet.h:663
MSVehicle::getLastActionTime
SUMOTime getLastActionTime() const
Returns the time of the vehicle's last action point.
Definition: MSVehicle.h:520
MSNet::getCurrentTimeStep
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:283
DEBUG_COND2
#define DEBUG_COND2(obj)
Definition: MESegment.cpp:54
STEPS2TIME
#define STEPS2TIME(x)
Definition: SUMOTime.h:56
LINKSTATE_ZIPPER
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
Definition: SUMOXMLDefinitions.h:1165
MSLane::getLength
double getLength() const
Returns the lane's length.
Definition: MSLane.h:540
OutputDevice.h
MSGlobals::gIgnoreJunctionBlocker
static SUMOTime gIgnoreJunctionBlocker
Definition: MSGlobals.h:72
ProcessError
Definition: UtilExceptions.h:39
MSVehicle::getLaneChangeModel
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4680
MSAbstractLaneChangeModel::isOpposite
bool isOpposite() const
Definition: MSAbstractLaneChangeModel.h:535
SUMOVehicle::getLateralPositionOnLane
virtual double getLateralPositionOnLane() const =0
Get the vehicle's lateral position on the lane.
time2string
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:67
MSGlobals.h
MSVehicleType::getMinGap
double getMinGap() const
Get the free space in front of vehicles of this class.
Definition: MSVehicleType.h:125
MSEdge
A road/street connecting two junctions.
Definition: MSEdge.h:78
LINKDIR_LEFT
@ LINKDIR_LEFT
The link is a (hard) left direction.
Definition: SUMOXMLDefinitions.h:1184
MSTrafficLightLogic
The parent class for traffic light logics.
Definition: MSTrafficLightLogic.h:55
MSTransportable::getPosition
Position getPosition(const double) const
Return current position (x/y, cartesian)
Definition: MSTransportable.h:581
MSBaseVehicle::getVehicleType
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
Definition: MSBaseVehicle.h:123
MSLane::getLinkCont
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:2110
MSLane::anyVehiclesEnd
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction
Definition: MSLane.h:439
MSLane::getLogicalPredecessorLane
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:2543
MSPerson.h
MSGlobals::gUsingInternalLanes
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:68
SUMO_ATTR_FROM
@ SUMO_ATTR_FROM
Definition: SUMOXMLDefinitions.h:639
MSVehicle::getLane
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:560
MSLane::getEdge
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:669
Position::distanceTo2D
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:243
SUMO_ATTR_JM_CROSSING_GAP
@ SUMO_ATTR_JM_CROSSING_GAP
Definition: SUMOXMLDefinitions.h:613
MSVehicle::willStop
bool willStop() const
Returns whether the vehicle will stop on the current edge.
Definition: MSVehicle.cpp:1743
OutputDevice::openTag
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
Definition: OutputDevice.cpp:239
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:47
MSLane::getShape
const PositionVector & getShape() const
Returns this lane's shape.
Definition: MSLane.h:477
SUMO_ATTR_VIA
@ SUMO_ATTR_VIA
Definition: SUMOXMLDefinitions.h:723
MSNet::getInstance
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:167
MSTransportable::getSpeed
virtual double getSpeed() const
the current speed of the transportable
Definition: MSTransportable.cpp:734
SUMO_ATTR_IMPATIENCE
@ SUMO_ATTR_IMPATIENCE
Definition: SUMOXMLDefinitions.h:796
MSTransportable::getVehicleType
const MSVehicleType & getVehicleType() const
Returns the vehicle's type.
Definition: MSTransportable.h:606
MSVehicleType::getLength
double getLength() const
Get vehicle's length [m].
Definition: MSVehicleType.h:109
InvalidArgument
Definition: UtilExceptions.h:56
PositionVector::distances
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
Definition: PositionVector.cpp:1239
INVALID_DOUBLE
const double INVALID_DOUBLE
Definition: StdDefs.h:62
MSPModel.h
MSVehicleType::getParameter
const SUMOVTypeParameter & getParameter() const
Definition: MSVehicleType.h:560
MSCFModel::getEmergencyDecel
double getEmergencyDecel() const
Get the vehicle type's maximal phisically possible deceleration [m/s^2].
Definition: MSCFModel.h:225
MSBaseVehicle::getID
const std::string & getID() const
Returns the name of the vehicle.
Definition: MSBaseVehicle.cpp:138
MSLane::getParallelLane
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2198
MSAbstractLaneChangeModel::isStrategicBlocked
bool isStrategicBlocked() const
Definition: MSAbstractLaneChangeModel.cpp:974
MSEdge::getLanes
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:167
MSVehicle::getBackPositionOnLane
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition: MSVehicle.cpp:4057
MSLane::getWidth
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:556
MSPModel::getModel
static MSPModel * getModel()
Definition: MSPModel.cpp:63
MSVehicle::getWaitingTime
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:624
LINKSTATE_ALLWAY_STOP
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
Definition: SUMOXMLDefinitions.h:1163
config.h
MSLane::isInternal
bool isInternal() const
Definition: MSLane.cpp:2010
gDebugFlag1
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:32
MSVehicle::getSpeed
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:476
RandHelper.h
MSVehicle::isFrontOnLane
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:4146
MSLane.h
MSLane::getVehicleMaxSpeed
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:518
MSVehicleType::getVehicleClass
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
Definition: MSVehicleType.h:184
MSCFModel::estimateSpeedAfterDistance
double estimateSpeedAfterDistance(const double dist, const double v, const double accel) const
Definition: MSCFModel.cpp:702
LINKDIR_PARTLEFT
@ LINKDIR_PARTLEFT
The link is a partial left direction.
Definition: SUMOXMLDefinitions.h:1188
MIN3
T MIN3(T a, T b, T c)
Definition: StdDefs.h:86
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:76
POSITION_EPS
#define POSITION_EPS
Definition: config.h:172
MSCFModel::followSpeed
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const =0
Computes the vehicle's follow speed (no dawdling)
MSLane::AnyVehicleIterator
AnyVehicleIterator is a structure, which manages the iteration through all vehicles on the lane,...
Definition: MSLane.h:109
MSLane::getIndex
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:563
SUMOVTypeParameter::getJMParam
double getJMParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
Definition: SUMOVTypeParameter.cpp:504
PositionVector::move2side
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
Definition: PositionVector.cpp:1103
SUMOTrafficObject::getSpeed
virtual double getSpeed() const =0
Returns the vehicle's current speed.
MSAbstractLaneChangeModel.h
MSLane::getEntryLink
MSLink * getEntryLink() const
Returns the entry link if this is an internal lane, else 0.
Definition: MSLane.cpp:2138
MSLane::anyVehiclesBegin
AnyVehicleIterator anyVehiclesBegin() const
begin iterator for iterating over all vehicles touching this lane in downstream direction
Definition: MSLane.h:433
LINKSTATE_STOP
@ LINKSTATE_STOP
This is an uncontrolled, minor link, has to stop.
Definition: SUMOXMLDefinitions.h:1161
MSVehicle
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:79