SUMO - Simulation of Urban MObility
MSLink.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A connnection between lanes
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
13 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <iostream>
34 #include <algorithm>
35 #include <limits>
37 #include "MSNet.h"
38 #include "MSJunction.h"
39 #include "MSLink.h"
40 #include "MSLane.h"
42 #include "MSEdge.h"
43 #include "MSGlobals.h"
44 #include "MSVehicle.h"
47 
48 #ifdef CHECK_MEMORY_LEAKS
49 #include <foreign/nvwa/debug_new.h>
50 #endif // CHECK_MEMORY_LEAKS
51 
52 //#define MSLink_DEBUG_CROSSING_POINTS
53 
54 // ===========================================================================
55 // static member variables
56 // ===========================================================================
58 // additional caution is needed when approaching a zipper link
60 
62 
63 // time to link in seconds below which adaptation should take place
64 #define ZIPPER_ADAPT_TIME 10
65 
66 // ===========================================================================
67 // member method definitions
68 // ===========================================================================
69 #ifndef HAVE_INTERNAL_LANES
70 MSLink::MSLink(MSLane* predLane, MSLane* succLane, LinkDirection dir, LinkState state, SUMOReal length, SUMOReal foeVisibilityDistance, bool keepClear, MSTrafficLightLogic* logic, int tlIndex) :
71  myLane(succLane),
72  myLaneBefore(predLane),
73  myIndex(-1),
74  myTLIndex(tlIndex),
75  myLogic(logic),
76  myState(state),
77  myLastStateChange(SUMOTime_MIN),
78  myDirection(dir),
79  myLength(length),
80  myFoeVisibilityDistance(foeVisibilityDistance),
81  myHasFoes(false),
82  myAmCont(false),
83  myKeepClear(keepClear),
84  myMesoTLSPenalty(0),
85  myGreenFraction(1),
86  myParallelRight(0),
87  myParallelLeft(0),
88  myJunction(0) {
89 }
90 #else
91 MSLink::MSLink(MSLane* predLane, MSLane* succLane, MSLane* via, LinkDirection dir, LinkState state, SUMOReal length, SUMOReal foeVisibilityDistance, bool keepClear, MSTrafficLightLogic* logic, int tlIndex) :
92  myLane(succLane),
93  myLaneBefore(predLane),
94  myIndex(-1),
95  myTLIndex(tlIndex),
96  myLogic(logic),
97  myState(state),
99  myDirection(dir),
100  myLength(length),
101  myFoeVisibilityDistance(foeVisibilityDistance),
102  myHasFoes(false),
103  myAmCont(false),
105  myInternalLane(via),
106  myInternalLaneBefore(0),
107  myMesoTLSPenalty(0),
108  myGreenFraction(1),
109  myParallelRight(0),
110  myParallelLeft(0),
111  myJunction(0) {
112 }
113 #endif
114 
115 
117 
118 
119 void
121  const std::vector<MSLink*>& foeLinks,
122  const std::vector<MSLane*>& foeLanes,
123  MSLane* internalLaneBefore) {
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 #ifdef HAVE_INTERNAL_LANES
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() << " internalLane=" << (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  assert(lane->getIncomingLanes().size() == 1);
150  // compute crossing points
151  for (std::vector<const MSLane*>::const_iterator it_lane = myFoeLanes.begin(); it_lane != myFoeLanes.end(); ++it_lane) {
152  const bool sameTarget = myLane == (*it_lane)->getLinkCont()[0]->getLane();
153  if (sameTarget && !beforeInternalJunction) {
154  //if (myLane == (*it_lane)->getLinkCont()[0]->getLane()) {
155  // this foeLane has the same target and merges at the end (lane exits the junction)
156  myLengthsBehindCrossing.push_back(std::make_pair(0, 0)); // dummy value, never used
157 #ifdef MSLink_DEBUG_CROSSING_POINTS
158  std::cout
159  << " " << lane->getID()
160  << " merges with " << (*it_lane)->getID()
161  << " nextLane " << lane->getLinkCont()[0]->getViaLaneOrLane()->getID()
162  << " dist1=" << myLengthsBehindCrossing.back().first
163  << " dist2=" << myLengthsBehindCrossing.back().second
164  << "\n";
165 #endif
166  } else {
167  std::vector<SUMOReal> intersections1 = lane->getShape().intersectsAtLengths2D((*it_lane)->getShape());
168 #ifdef MSLink_DEBUG_CROSSING_POINTS
169  //std::cout << " intersections1=" << toString(intersections1) << "\n";
170 #endif
171  bool haveIntersection = true;
172  if (intersections1.size() == 0) {
173  intersections1.push_back(-10000.0); // disregard this foe (using maxdouble leads to nasty problems down the line)
174  haveIntersection = false;
175  } else if (intersections1.size() > 1) {
176  std::sort(intersections1.begin(), intersections1.end());
177  }
178  std::vector<SUMOReal> intersections2 = (*it_lane)->getShape().intersectsAtLengths2D(lane->getShape());
179 #ifdef MSLink_DEBUG_CROSSING_POINTS
180  //std::cout << " intersections2=" << toString(intersections2) << "\n";
181 #endif
182  if (intersections2.size() == 0) {
183  intersections2.push_back(0);
184  } else if (intersections2.size() > 1) {
185  std::sort(intersections2.begin(), intersections2.end());
186  }
187  if (haveIntersection) {
188  // lane width affects the crossing point
189  intersections1.back() -= (*it_lane)->getWidth() / 2;
190  intersections2.back() -= lane->getWidth() / 2;
191  // also length/geometry factor
192  intersections1.back() = lane->interpolateGeometryPosToLanePos(intersections1.back());
193  intersections2.back() = (*it_lane)->interpolateGeometryPosToLanePos(intersections2.back());
194 
195  if (internalLaneBefore->getLogicalPredecessorLane()->getEdge().isInternal() && !(*it_lane)->getEdge().isCrossing()) {
196  // wait at the internal junction
197  // (except for foes that are crossings since there is no internal junction)
198  intersections1.back() = 0;
199  }
200  }
201 
202  myLengthsBehindCrossing.push_back(std::make_pair(
203  lane->getLength() - intersections1.back(),
204  (*it_lane)->getLength() - intersections2.back()));
205 
206 #ifdef MSLink_DEBUG_CROSSING_POINTS
207  std::cout
208  << " intersection of " << lane->getID()
209  << " totalLength=" << lane->getLength()
210  << " with " << (*it_lane)->getID()
211  << " totalLength=" << (*it_lane)->getLength()
212  << " dist1=" << myLengthsBehindCrossing.back().first
213  << " dist2=" << myLengthsBehindCrossing.back().second
214  << "\n";
215 #endif
216  }
217  }
218  // check for overlap with internal lanes from the same source lane
219  const MSLane* pred = lane->getLogicalPredecessorLane();
220  // to avoid overlap with vehicles that came from pred (especially when pred has endOffset > 0)
221  // we add all other internal lanes from pred as foeLanes
222  const MSLinkCont& predLinks = pred->getLinkCont();
223  for (MSLinkCont::const_iterator it = predLinks.begin(); it != predLinks.end(); ++it) {
224  const MSLane* sibling = (*it)->getViaLane();
225  if (sibling != lane && sibling != 0) {
226  std::vector<SUMOReal> intersections1 = lane->getShape().intersectsAtLengths2D(sibling->getShape());
227 #ifdef MSLink_DEBUG_CROSSING_POINTS
228  //std::cout << " intersections1=" << toString(intersections1) << "\n";
229 #endif
230  if (intersections1.size() > 0) {
231  std::sort(intersections1.begin(), intersections1.end());
232  if (intersections1.back() > NUMERICAL_EPS) {
233  // siblings share a common shape up to the last crossing point so intersections are identical and only need to be computed once
234  myLengthsBehindCrossing.push_back(std::make_pair(
235  lane->getLength() - intersections1.back(),
236  sibling->getLength() - intersections1.back()));
237  myFoeLanes.push_back(sibling);
238 #ifdef MSLink_DEBUG_CROSSING_POINTS
239  std::cout << " adding same-origin foe" << sibling->getID()
240  << " dist1=" << myLengthsBehindCrossing.back().first
241  << " dist2=" << myLengthsBehindCrossing.back().second
242  << "\n";
243 #endif
244  }
245  }
246  }
247  }
248  }
249 #else
250  UNUSED_PARAMETER(internalLaneBefore);
251 #endif
253  // check for links with the same origin lane and the same destination edge
254  const MSEdge* myTarget = &myLane->getEdge();
255  const MSLinkCont& predLinks = myLaneBefore->getLinkCont();
256  for (MSLinkCont::const_iterator it = predLinks.begin(); it != predLinks.end(); ++it) {
257  const MSEdge* target = &((*it)->getLane()->getEdge());
258  if (*it != this && target == myTarget) {
259  mySublaneFoeLinks.push_back(*it);
260  }
261  }
262  }
263 }
264 
265 
266 std::pair<SUMOReal, SUMOReal>
267 getLastIntersections(const MSLane* lane, const MSLane* foe);
268 
269 void
270 MSLink::setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime, const SUMOReal arrivalSpeed, const SUMOReal leaveSpeed,
271  const bool setRequest, const SUMOTime arrivalTimeBraking, const SUMOReal arrivalSpeedBraking, const SUMOTime waitingTime, SUMOReal dist) {
272  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, approaching->getVehicleType().getLength());
273  myApproachingVehicles.insert(std::make_pair(approaching,
274  ApproachingVehicleInformation(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, setRequest,
275  arrivalTimeBraking, arrivalSpeedBraking, waitingTime, dist)));
276 }
277 
278 
279 void
281  myBlockedFoeLinks.insert(link);
282 }
283 
284 
285 
286 bool
288  for (std::set<MSLink*>::const_iterator i = myBlockedFoeLinks.begin(); i != myBlockedFoeLinks.end(); ++i) {
289  if ((*i)->isBlockingAnyone()) {
290  return true;
291  }
292  }
293  return false;
294 }
295 
296 
297 void
299  myApproachingVehicles.erase(veh);
300 }
301 
302 
305  std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.find(veh);
306  if (i != myApproachingVehicles.end()) {
307  return i->second;
308  } else {
309  return ApproachingVehicleInformation(-1000, -1000, 0, 0, false, -1000, 0, 0, 0);
310  }
311 }
312 
313 
314 SUMOTime
315 MSLink::getLeaveTime(const SUMOTime arrivalTime, const SUMOReal arrivalSpeed,
316  const SUMOReal leaveSpeed, const SUMOReal vehicleLength) const {
317  return arrivalTime + TIME2STEPS((getLength() + vehicleLength) / MAX2((SUMOReal)0.5 * (arrivalSpeed + leaveSpeed), NUMERICAL_EPS));
318 }
319 
320 
321 bool
322 MSLink::opened(SUMOTime arrivalTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed, SUMOReal vehicleLength,
323  SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime, SUMOReal posLat,
324  std::vector<const SUMOVehicle*>* collectFoes) const {
325  if (haveRed()) {
326  return false;
327  }
329  return true;
330  }
331  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, vehicleLength);
333  // check for foes on the same lane
334  for (std::vector<MSLink*>::const_iterator it = mySublaneFoeLinks.begin(); it != mySublaneFoeLinks.end(); ++it) {
335  const MSLink* foeLink = *it;
336  assert(myLane != foeLink->getLane());
337  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = foeLink->myApproachingVehicles.begin(); i != foeLink->myApproachingVehicles.end(); ++i) {
338  const SUMOVehicle* foe = i->first;
339  if (
340  // there only is a conflict if the paths cross
341  ((posLat < foe->getLateralPositionOnLane() && myLane->getIndex() > foeLink->myLane->getIndex())
342  || (posLat > foe->getLateralPositionOnLane() && myLane->getIndex() < foeLink->myLane->getIndex()))
343  // the vehicle that arrives later must yield
344  && (arrivalTime > i->second.arrivalTime
345  // if both vehicles arrive at the same time, the one
346  // to the left must yield
347  || (arrivalTime == i->second.arrivalTime && posLat > foe->getLateralPositionOnLane()))) {
348  if (blockedByFoe(i->first, i->second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, false,
349  impatience, decel, waitingTime)) {
350  //std::cout << SIMTIME << " blocked by " << foe->getID() << " arrival=" << arrivalTime << " foeArrival=" << i->second.arrivalTime << "\n";
351  if (collectFoes == 0) {
352  //std::cout << " link=" << getViaLaneOrLane()->getID() << " blocked by sublaneFoe=" << foe->getID() << " foeLink=" << foeLink->getViaLaneOrLane()->getID() << " posLat=" << posLat << "\n";
353  return false;
354  } else {
355  collectFoes->push_back(i->first);
356  }
357  }
358  }
359  }
360  }
361  }
362  if (havePriority() && myState != LINKSTATE_ZIPPER) {
363  // priority usually means the link is open but there are exceptions:
364  // zipper still needs to collect foes
365  // sublane model could have detected a conflict
366  return collectFoes == 0 || collectFoes->size() == 0;
367  }
368  if ((myState == LINKSTATE_STOP || myState == LINKSTATE_ALLWAY_STOP) && waitingTime == 0) {
369  return false;
370  }
371  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
373  if ((*i)->haveRed()) {
374  continue;
375  }
376  }
377  if ((*i)->blockedAtTime(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, myLane == (*i)->getLane(),
378  impatience, decel, waitingTime, collectFoes)) {
379  return false;
380  }
381  }
382  if (collectFoes != 0 && collectFoes->size() > 0) {
383  return false;
384  }
385  return true;
386 }
387 
388 
389 bool
390 MSLink::blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed,
391  bool sameTargetLane, SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime,
392  std::vector<const SUMOVehicle*>* collectFoes) const {
393  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
394  if (blockedByFoe(i->first, i->second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, sameTargetLane,
395  impatience, decel, waitingTime)) {
396  if (collectFoes == 0) {
397  return true;
398  } else {
399  collectFoes->push_back(i->first);
400  }
401  }
402  }
403  return false;
404 }
405 
406 
407 bool
408 MSLink::blockedByFoe(const SUMOVehicle* veh, const ApproachingVehicleInformation& avi, SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed,
409  bool sameTargetLane, SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime) const {
410  if (!avi.willPass) {
411  return false;
412  }
414  assert(waitingTime > 0);
415  if (waitingTime > avi.waitingTime) {
416  return false;
417  }
418  if (waitingTime == avi.waitingTime && arrivalTime < avi.arrivalTime) {
419  return false;
420  }
421  }
422  const SUMOTime foeArrivalTime = (SUMOTime)((1.0 - impatience) * avi.arrivalTime + impatience * avi.arrivalTimeBraking);
424  if (avi.leavingTime < arrivalTime) {
425  // ego wants to be follower
426  if (sameTargetLane && (arrivalTime - avi.leavingTime < lookAhead
427  || unsafeMergeSpeeds(avi.leaveSpeed, arrivalSpeed,
428  veh->getVehicleType().getCarFollowModel().getMaxDecel(), decel))) {
429  return true;
430  }
431  } else if (foeArrivalTime > leaveTime) {
432  // ego wants to be leader.
433  if (sameTargetLane && (foeArrivalTime - leaveTime < lookAhead
434  || unsafeMergeSpeeds(leaveSpeed, avi.arrivalSpeedBraking,
435  decel, veh->getVehicleType().getCarFollowModel().getMaxDecel()))) {
436  return true;
437  }
438  } else {
439  // even without considering safeHeadwayTime there is already a conflict
440  return true;
441  }
442  return false;
443 }
444 
445 
446 bool
448  MSVehicle* veh = lane->getLastAnyVehicle();
449  SUMOReal distLeft = 0;
450  if (veh == 0) {
451  return false;
452  } else {
453  distLeft = lane->getLength() - veh->getBackPositionOnLane(lane);
454  assert(distLeft > 0);
455  // can we be sure that the vehicle leaves this lane in the next step?
456  bool result = distLeft > (veh->getSpeed() - veh->getCarFollowModel().getMaxDecel());
457  return result;
458  }
459 }
460 
461 
462 bool
463 MSLink::hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal speed, SUMOReal decel) const {
464  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
465  if ((*i)->blockedAtTime(arrivalTime, leaveTime, speed, speed, myLane == (*i)->getLane(), 0, decel, 0)) {
466  return true;
467  }
468  }
469  for (std::vector<const MSLane*>::const_iterator i = myFoeLanes.begin(); i != myFoeLanes.end(); ++i) {
470  if ((*i)->getVehicleNumberWithPartials() > 0) {
471  return true;
472  }
473  }
474  return false;
475 }
476 
477 
480  return myDirection;
481 }
482 
483 
484 void
486  if (myState != state) {
487  myLastStateChange = t;
488  }
489  myState = state;
490 }
491 
492 
493 MSLane*
495  return myLane;
496 }
497 
498 bool
500 #ifdef HAVE_INTERNAL_LANES
501  if (myInternalLane == 0 || myAmCont) {
502  return false;
503  } else {
504  MSLane* pred = myInternalLane->getLogicalPredecessorLane();
506  return false;
507  } else {
508  MSLane* pred2 = pred->getLogicalPredecessorLane();
509  assert(pred2 != 0);
510  MSLink* predLink = MSLinkContHelper::getConnectingLink(*pred2, *pred);
511  assert(predLink != 0);
512  return predLink->havePriority();
513  }
514  }
515 #else
516  return false;
517 #endif
518 }
519 
520 
521 void
522 MSLink::writeApproaching(OutputDevice& od, const std::string fromLaneID) const {
523  if (myApproachingVehicles.size() > 0) {
524  od.openTag("link");
525  od.writeAttr(SUMO_ATTR_FROM, fromLaneID);
526 #ifdef HAVE_INTERNAL_LANES
527  const std::string via = getViaLane() == 0 ? "" : getViaLane()->getID();
528 #else
529  const std::string via = "";
530 #endif
531  od.writeAttr(SUMO_ATTR_VIA, via);
532  od.writeAttr(SUMO_ATTR_TO, getLane() == 0 ? "" : getLane()->getID());
533  std::vector<std::pair<SUMOTime, const SUMOVehicle*> > toSort; // stabilize output
534  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator it = myApproachingVehicles.begin(); it != myApproachingVehicles.end(); ++it) {
535  toSort.push_back(std::make_pair(it->second.arrivalTime, it->first));
536  }
537  std::sort(toSort.begin(), toSort.end());
538  for (std::vector<std::pair<SUMOTime, const SUMOVehicle*> >::const_iterator it = toSort.begin(); it != toSort.end(); ++it) {
539  od.openTag("approaching");
540  const ApproachingVehicleInformation& avi = myApproachingVehicles.find(it->second)->second;
541  od.writeAttr(SUMO_ATTR_ID, it->second->getID());
542  od.writeAttr(SUMO_ATTR_IMPATIENCE, it->second->getImpatience());
543  od.writeAttr("arrivalTime", time2string(avi.arrivalTime));
544  od.writeAttr("arrivalTimeBraking", time2string(avi.arrivalTimeBraking));
545  od.writeAttr("leaveTime", time2string(avi.leavingTime));
546  od.writeAttr("arrivalSpeed", toString(avi.arrivalSpeed));
547  od.writeAttr("arrivalSpeedBraking", toString(avi.arrivalSpeedBraking));
548  od.writeAttr("leaveSpeed", toString(avi.leaveSpeed));
549  od.writeAttr("willPass", toString(avi.willPass));
550  od.closeTag();
551  }
552  od.closeTag();
553  }
554 }
555 
556 
557 SUMOReal
559  SUMOReal len = 0.;
560 #ifdef HAVE_INTERNAL_LANES
561  MSLane* lane = myInternalLane;
562 
563  while (lane != 0 && lane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
564  len += lane->getLength();
565  lane = lane->getLinkCont()[0]->getViaLane();
566  }
567 #endif
568  return len;
569 }
570 
571 
572 #ifdef HAVE_INTERNAL_LANES
573 MSLane*
574 MSLink::getViaLane() const {
575  return myInternalLane;
576 }
577 
578 
579 bool
580 MSLink::isExitLink() const {
583 }
584 
585 
586 bool
588  return getInternalLaneBefore() != 0 && myInternalLane != 0;
589 }
590 
591 bool
592 MSLink::fromInternalLane() const {
593  return isExitLink() || isInternalJunctionLink();
594 }
595 
597 MSLink::getLeaderInfo(const MSVehicle* ego, SUMOReal dist, std::vector<const MSPerson*>* collectBlockers) const {
598  LinkLeaders result;
599  if (ego->getLaneChangeModel().isOpposite()) {
600  // ignore link leaders
601  return result;
602  }
603  //gDebugFlag1 = true;
604  // this link needs to start at an internal lane (either an exit link or between two internal lanes)
605  if (fromInternalLane()) {
606  //if (gDebugFlag1) std::cout << SIMTIME << " getLeaderInfo link=" << getViaLaneOrLane()->getID() << "\n";
607  // this is an exit link
608  for (int i = 0; i < (int)myFoeLanes.size(); ++i) {
609  const MSLane* foeLane = myFoeLanes[i];
610  // distance from the querying vehicle to the crossing point with foeLane
611  const SUMOReal distToCrossing = dist - myLengthsBehindCrossing[i].first;
612  const bool sameTarget = (myLane == foeLane->getLinkCont()[0]->getLane());
613  const bool sameSource = (myInternalLaneBefore != 0 && myInternalLaneBefore->getLogicalPredecessorLane() == foeLane->getLogicalPredecessorLane());
614  const SUMOReal crossingWidth = (sameTarget || sameSource) ? 0 : foeLane->getWidth();
615  const SUMOReal foeCrossingWidth = (sameTarget || sameSource) ? 0 : myInternalLaneBefore->getWidth();
616  if (gDebugFlag1) {
617  std::cout << " distToCrossing=" << distToCrossing << " foeLane=" << foeLane->getID() << "\n";
618  }
619  if (distToCrossing + crossingWidth < 0) {
620  continue; // vehicle is behind the crossing point, continue with next foe lane
621  }
622  const SUMOReal foeDistToCrossing = foeLane->getLength() - myLengthsBehindCrossing[i].second;
623  // it is not sufficient to return the last vehicle on the foeLane because ego might be its leader
624  // therefore we return all vehicles on the lane
625  //
626  // special care must be taken for continuation lanes. (next lane is also internal)
627  // vehicles on these lanes should always block (gap = -1)
628  const bool contLane = (foeLane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL);
629  // vehicles on cont. lanes or on internal lanes with the same target as this link can never be ignored
630  const bool cannotIgnore = contLane || sameTarget || sameSource;
632  for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != end; ++it_veh) {
633  MSVehicle* leader = (MSVehicle*)*it_veh;
634  const bool isOpposite = leader->getLaneChangeModel().isOpposite();
635  if (gDebugFlag1) {
636  std::cout << " candiate leader=" << leader->getID()
637  << " cannotIgnore=" << cannotIgnore
638  << " willPass=" << foeLane->getLinkCont()[0]->getApproaching(leader).willPass
639  << " isFrontOnLane=" << leader->isFrontOnLane(foeLane)
640  << " isOpposite=" << isOpposite << "\n";
641  }
642  if (!cannotIgnore && !foeLane->getLinkCont()[0]->getApproaching(leader).willPass && leader->isFrontOnLane(foeLane) && !isOpposite) {
643  continue;
644  }
645  if (cannotIgnore || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
646  // compute distance between vehicles on the the superimposition of both lanes
647  // where the crossing point is the common point
648  SUMOReal gap;
649  if ((contLane && !sameSource) || isOpposite) {
650  gap = -1; // always break for vehicles which are on a continuation lane or for opposite-direction vehicles
651  } else {
652  const SUMOReal leaderBack = leader->getBackPositionOnLane(foeLane);
653  const SUMOReal leaderBackDist = foeDistToCrossing - leaderBack;
654  if (gDebugFlag1) {
655  std::cout << " distToCrossing=" << distToCrossing << " leader back=" << leaderBack << " backDist=" << leaderBackDist << "\n";
656  }
657  if (leaderBackDist + foeCrossingWidth < 0) {
658  // leader is completely past the crossing point
659  // or there is no crossing point
660  continue; // next vehicle
661  }
662  gap = distToCrossing - leaderBackDist - (sameTarget ? ego->getVehicleType().getMinGap() : 0);
663  }
664  if (gDebugFlag1) {
665  std::cout << " leader=" << leader->getID() << " contLane=" << contLane << " cannotIgnore=" << cannotIgnore << "\n";
666  }
667  // if the foe is already moving off the intersection, we may
668  // advance up to the crossing point unless we have the same target
669  const bool stopAsap = leader->isFrontOnLane(foeLane) ? cannotIgnore : sameTarget;
670  result.push_back(LinkLeader(leader, gap, stopAsap ? -1 : distToCrossing));
671  }
672 
673  }
674  // check for crossing pedestrians (keep driving if already on top of the crossing
675  const SUMOReal distToPeds = distToCrossing - MSPModel::SAFETY_GAP;
676  if (distToPeds >= -MSPModel::SAFETY_GAP && MSPModel::getModel()->blockedAtDist(foeLane, foeDistToCrossing, collectBlockers)) {
677  result.push_back(LinkLeader((MSVehicle*)0, -1, distToPeds));
678  }
679  }
680  }
681  return result;
682 }
683 #endif
684 
685 
686 MSLane*
688 #ifdef HAVE_INTERNAL_LANES
689  if (myInternalLane != 0) {
690  return myInternalLane;
691  }
692 #endif
693  return myLane;
694 }
695 
696 
697 const MSLane*
699 #ifdef HAVE_INTERNAL_LANES
700  // XXX this branch is superfluous
701  if (myInternalLaneBefore != 0) {
702  if (myLaneBefore != myInternalLaneBefore) {
703  throw ProcessError("lane before mismatch!");
704  }
705  }
706 #endif
707  return myLaneBefore;
708 }
709 
710 
711 MSLink*
712 MSLink::getParallelLink(int direction) const {
713  if (direction == -1) {
714  return myParallelRight;
715  } else if (direction == 1) {
716  return myParallelLeft;
717  } else {
718  assert(false);
719  return 0;
720  }
721 }
722 
723 
724 MSLink*
726  MSLane* before = getLaneBefore()->getParallelLane(direction);
727  MSLane* after = getViaLaneOrLane()->getParallelLane(direction);
728  if (before != 0 && after != 0) {
729  return MSLinkContHelper::getConnectingLink(*before, *after);
730  } else {
731  return 0;
732  }
733 }
734 
735 void
737  if (myJunction != 0) {
738  myJunction->passedJunction(vehicle);
739  }
740 }
741 
742 
743 bool
744 MSLink::isLeader(const MSVehicle* ego, const MSVehicle* foe) {
745  if (myJunction != 0) {
746  return myJunction->isLeader(ego, foe);
747  } else {
748  // unregulated junction
749  return false;
750  }
751 }
752 
753 const MSLane*
755 #ifdef HAVE_INTERNAL_LANES
756  return myInternalLaneBefore;
757 #else
758  return 0;
759 #endif
760 }
761 
762 
763 SUMOReal
764 MSLink::getZipperSpeed(const MSVehicle* ego, const SUMOReal dist, SUMOReal vSafe,
765  SUMOTime arrivalTime,
766  std::vector<const SUMOVehicle*>* collectFoes) const {
767  //gDebugFlag1 = ego->getID() == "left.7";
768  if (myFoeLinks.size() == 0) {
769  // link should have LINKSTATE_MAJOR in this case
770  assert(false);
771  return vSafe;
772  } else if (myFoeLinks.size() > 1) {
773  throw ProcessError("Zipper junctions with more than two conflicting lanes are not supported (at junction '"
774  + myJunction->getID() + "')");
775  }
777  const SUMOReal secondsToArrival = STEPS2TIME(arrivalTime - now);
778  if (secondsToArrival > ZIPPER_ADAPT_TIME && dist > ZIPPER_ADAPT_DIST) {
779  //if (gDebugFlag1) std::cout << SIMTIME << " getZipperSpeed ego=" << ego->getID()
780  // << " dist=" << dist
781  // << " ignoring foes (arrival in " << STEPS2TIME(arrivalTime - now) << ")\n";
782  return vSafe;
783  }
784  //if (gDebugFlag1) std::cout << SIMTIME << " getZipperSpeed ego=" << ego->getID()
785  // << " egoAT=" << arrivalTime
786  // << " dist=" << dist
787  // << " vSafe=" << vSafe
788  // << " numFoes=" << collectFoes->size()
789  // << "\n";
790  MSLink* foeLink = myFoeLinks[0];
791  const SUMOReal vSafeOrig = vSafe;
792  for (std::vector<const SUMOVehicle*>::const_iterator i = collectFoes->begin(); i != collectFoes->end(); ++i) {
793  const MSVehicle* foe = dynamic_cast<const MSVehicle*>(*i);
794  assert(foe != 0);
795  const ApproachingVehicleInformation& avi = foeLink->getApproaching(foe);
796  if ( // ignore vehicles that arrive after us (unless they are ahead and we could easily brake for them)
797  ((avi.arrivalTime > arrivalTime) && !couldBrakeForLeader(dist, avi.dist, ego, foe)) ||
798  // also ignore vehicles that are behind us and are able to brake for us
799  couldBrakeForLeader(avi.dist, dist, foe, ego) ||
800  // resolve ties by lane index
801  (avi.arrivalTime == arrivalTime && avi.dist == dist && ego->getLane()->getIndex() < foe->getLane()->getIndex())) {
802  //if (gDebugFlag1) std::cout
803  // << " ignoring foe=" << foe->getID()
804  // << " foeAT=" << avi.arrivalTime
805  // << " foeDist=" << avi.dist
806  // << " foeSpeed=" << foe->getSpeed()
807  // << " egoSpeed=" << ego->getSpeed()
808  // << " deltaDist=" << avi.dist - dist
809  // << " delteSpeed=" << foe->getSpeed() - foe->getCarFollowModel().getMaxDecel() - ego->getSpeed()
810  // << "\n";
811  continue;
812  }
813  const SUMOReal gap = dist - foe->getVehicleType().getLength() - ego->getVehicleType().getMinGap() - avi.dist;
814  const SUMOReal follow = ego->getCarFollowModel().followSpeed(
815  ego, ego->getSpeed(), gap, foe->getSpeed(), foe->getCarFollowModel().getMaxDecel());
816  // speed adaption to follow the foe can be spread over secondsToArrival
817  const SUMOReal followInTime = vSafeOrig + (follow - vSafeOrig) / MAX2((SUMOReal)1, secondsToArrival / TS);
818  vSafe = MIN2(vSafe, followInTime);
819  //if (gDebugFlag1) std::cout << " adapting to foe=" << foe->getID()
820  // << " foeDist=" << avi.dist
821  // << " follow=" << follow
822  // << " followInTime=" << followInTime
823  // << " gap=" << gap
824  // << " foeSpeed=" << foe->getSpeed()
825  // << " follow=" << follow
826  // << " foeAT=" << avi.arrivalTime
827  // << " foeLT=" << avi.leavingTime
828  // << " foeAS=" << avi.arrivalSpeed
829  // << " vSafe=" << vSafe
830  // << "\n";
831  }
832  return vSafe;
833 }
834 
835 
836 bool
837 MSLink::couldBrakeForLeader(SUMOReal followDist, SUMOReal leaderDist, const MSVehicle* follow, const MSVehicle* leader) {
838  return (// leader is ahead of follower
839  followDist > leaderDist &&
840  // and follower could brake for 1 s to stay behind leader
841  followDist - leaderDist > follow->getSpeed() - follow->getCarFollowModel().getMaxDecel() - leader->getSpeed());
842 }
843 
844 
845 void
849 }
850 
851 /****************************************************************************/
852 
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:37
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:571
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1466
long long int SUMOTime
Definition: SUMOTime.h:43
static const SUMOReal SAFETY_GAP
Definition: MSPModel.h:81
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:783
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:536
This is an uncontrolled, minor link, has to stop.
SUMOReal getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:480
The base class for an intersection.
Definition: MSJunction.h:64
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:60
SUMOReal getLength() const
Get vehicle&#39;s length [m].
SUMOReal getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:496
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
T MAX2(T a, T b)
Definition: StdDefs.h:70
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
#define TS
Definition: SUMOTime.h:52
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:255
This is an uncontrolled, all-way stop link.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
This is an uncontrolled, zipper-merge link.
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:2881
const MSCFModel & getCarFollowModel() const
Returns the vehicle type&#39;s car following model definition (const version)
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
#define SUMOTime_MIN
Definition: SUMOTime.h:45
const std::string & getID() const
Returns the id.
Definition: Named.h:66
A road/street connecting two junctions.
Definition: MSEdge.h:80
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:1994
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
void passedJunction(const MSVehicle *vehicle)
erase vehicle from myLinkLeaders
Definition: MSJunction.cpp:77
Representation of a vehicle.
Definition: SUMOVehicle.h:67
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
static MSPModel * getModel()
Definition: MSPModel.cpp:63
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:1594
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
virtual SUMOReal followSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const =0
Computes the vehicle&#39;s follow speed (no dawdling)
T MIN2(T a, T b)
Definition: StdDefs.h:64
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:73
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:503
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:254
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:249
virtual SUMOReal getLateralPositionOnLane() const =0
Get the vehicle&#39;s lateral position on the lane.
The edge is a normal street.
Definition: MSEdge.h:93
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
static SUMOReal gLateralResolution
Definition: MSGlobals.h:89
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:442
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:2419
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:391
SUMOReal getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:2359
static SUMOTime gIgnoreJunctionBlocker
Definition: MSGlobals.h:77
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:427
The parent class for traffic light logics.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:208
const MSJunction * getFromJunction() const
Definition: MSEdge.h:369
#define NUMERICAL_EPS
Definition: config.h:158
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1545
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:488
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:708
The edge is an internal edge.
Definition: MSEdge.h:97
SUMOReal interpolateGeometryPosToLanePos(SUMOReal geometryPos) const
Definition: MSLane.h:450
std::vector< SUMOReal > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
AnyVehicleIterator anyVehiclesBegin() const
begin iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:386
static bool gUseMesoSim
Definition: MSGlobals.h:95
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
bool isLeader(const MSVehicle *ego, const MSVehicle *foe)
Definition: MSJunction.cpp:83
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
const std::string & getID() const
Returns the name of the vehicle.