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