SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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),
96  myLastStateChange(SUMOTime_MIN),
97  myDirection(dir),
98  myLength(length),
99  myFoeVisibilityDistance(foeVisibilityDistance),
100  myHasFoes(false),
101  myAmCont(false),
102  myKeepClear(keepClear),
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
117 MSLink::setRequestInformation(int index, bool hasFoes, bool isCont,
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 
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:91
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:257
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:571
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:82
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1433
long long int SUMOTime
Definition: SUMOTime.h:43
static const SUMOReal SAFETY_GAP
Definition: MSPModel.h:78
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:758
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:535
virtual SUMOReal followSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const =0
Computes the vehicle's follow speed (no dawdling)
This is an uncontrolled, minor link, has to stop.
SUMOReal getLength() const
Returns the lane's length.
Definition: MSLane.h:480
The base class for an intersection.
Definition: MSJunction.h:64
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
SUMOReal getLength() const
Get vehicle's length [m].
SUMOReal getWidth() const
Returns the lane'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:75
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
#define TS
Definition: SUMOTime.h:52
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:254
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
const MSCFModel & getCarFollowModel() const
Returns the vehicle type'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:1954
void passedJunction(const MSVehicle *vehicle)
erase vehicle from myLinkLeaders
Definition: MSJunction.cpp:77
Representation of a vehicle.
Definition: SUMOVehicle.h:66
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:1561
#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.
T MIN2(T a, T b)
Definition: StdDefs.h:69
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:73
SUMOReal getMaxDecel() const
Get the vehicle type's maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
virtual SUMOReal getLateralPositionOnLane() const =0
Get the vehicle's lateral position on the lane.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
int getIndex() const
Returns the lane'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
The edge is a normal street.
Definition: MSEdge.h:93
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
static SUMOReal gLateralResolution
Definition: MSGlobals.h:89
SUMOReal getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:441
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:2258
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's position relative to the given lane.
Definition: MSVehicle.cpp:2198
static SUMOTime gIgnoreJunctionBlocker
Definition: MSGlobals.h:77
const PositionVector & getShape() const
Returns this lane'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:214
const MSJunction * getFromJunction() const
Definition: MSEdge.h:383
#define NUMERICAL_EPS
Definition: config.h:161
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1512
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:487
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.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle's type.