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