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* succLane, LinkDirection dir, LinkState state, SUMOReal length, bool keepClear) :
70  myLane(succLane),
71  myIndex(-1),
72  myState(state),
73  myLastStateChange(SUMOTime_MIN),
74  myDirection(dir),
75  myLength(length),
76  myHasFoes(false),
77  myAmCont(false),
78  myKeepClear(keepClear),
79  myMesoTLSPenalty(0),
80  myJunction(0)
81 #else
82 MSLink::MSLink(MSLane * succLane, MSLane * via, LinkDirection dir, LinkState state, SUMOReal length, bool keepClear) :
83  myLane(succLane),
84  myIndex(-1),
85  myState(state),
86  myLastStateChange(SUMOTime_MIN),
87  myDirection(dir),
88  myLength(length),
89  myHasFoes(false),
90  myAmCont(false),
91  myKeepClear(keepClear),
92  myMesoTLSPenalty(0),
93  myJunctionInlane(via),
94  myInternalLaneBefore(0),
95  myJunction(0)
96 #endif
97 {}
98 
99 
101 
102 
103 void
105  const std::vector<MSLink*>& foeLinks,
106  const std::vector<MSLane*>& foeLanes,
107  MSLane* internalLaneBefore) {
108  myIndex = index;
109  myHasFoes = hasFoes;
110  myAmCont = isCont;
111  myFoeLinks = foeLinks;
112  for (std::vector<MSLane*>::const_iterator it_lane = foeLanes.begin(); it_lane != foeLanes.end(); ++it_lane) {
113  // cannot assign vector due to const-ness
114  myFoeLanes.push_back(*it_lane);
115  }
116  myJunction = const_cast<MSJunction*>(myLane->getEdge().getFromJunction()); // junctionGraph is initialized after the whole network is loaded
117 #ifdef HAVE_INTERNAL_LANES
118  myInternalLaneBefore = internalLaneBefore;
119  MSLane* lane = 0;
120  if (internalLaneBefore != 0) {
121  // this is an exit link. compute crossing points with all foeLanes
122  lane = internalLaneBefore;
123  //} else if (myLane->getEdge().isCrossing()) {
124  // // this is the link to a pedestrian crossing. compute crossing points with all foeLanes
125  // // @note not currently used by pedestrians
126  // lane = myLane;
127  }
128 #ifdef MSLink_DEBUG_CROSSING_POINTS
129  std::cout << " link " << myIndex << " to " << getViaLaneOrLane()->getID() << " internalLane=" << (lane == 0 ? "NULL" : lane->getID()) << " has foes: " << toString(foeLanes) << "\n";
130 #endif
131  if (lane != 0) {
132  const bool beforeInternalJunction = lane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().isInternal();
133  assert(lane->getIncomingLanes().size() == 1);
134  // compute crossing points
135  for (std::vector<const MSLane*>::const_iterator it_lane = myFoeLanes.begin(); it_lane != myFoeLanes.end(); ++it_lane) {
136  const bool sameTarget = myLane == (*it_lane)->getLinkCont()[0]->getLane();
137  if (sameTarget && !beforeInternalJunction) {
138  //if (myLane == (*it_lane)->getLinkCont()[0]->getLane()) {
139  // this foeLane has the same target and merges at the end (lane exits the junction)
140  myLengthsBehindCrossing.push_back(std::make_pair(0, 0)); // dummy value, never used
141 #ifdef MSLink_DEBUG_CROSSING_POINTS
142  std::cout
143  << " " << lane->getID()
144  << " merges with " << (*it_lane)->getID()
145  << " nextLane " << lane->getLinkCont()[0]->getViaLaneOrLane()->getID()
146  << " dist1=" << myLengthsBehindCrossing.back().first
147  << " dist2=" << myLengthsBehindCrossing.back().second
148  << "\n";
149 #endif
150  } else {
151  std::vector<SUMOReal> intersections1 = lane->getShape().intersectsAtLengths2D((*it_lane)->getShape());
152 #ifdef MSLink_DEBUG_CROSSING_POINTS
153  //std::cout << " intersections1=" << toString(intersections1) << "\n";
154 #endif
155  bool haveIntersection = true;
156  if (intersections1.size() == 0) {
157  intersections1.push_back(-10000.0); // disregard this foe (using maxdouble leads to nasty problems down the line)
158  haveIntersection = false;
159  } else if (intersections1.size() > 1) {
160  std::sort(intersections1.begin(), intersections1.end());
161  }
162  std::vector<SUMOReal> intersections2 = (*it_lane)->getShape().intersectsAtLengths2D(lane->getShape());
163 #ifdef MSLink_DEBUG_CROSSING_POINTS
164  //std::cout << " intersections2=" << toString(intersections2) << "\n";
165 #endif
166  if (intersections2.size() == 0) {
167  intersections2.push_back(0);
168  } else if (intersections2.size() > 1) {
169  std::sort(intersections2.begin(), intersections2.end());
170  }
171  if (haveIntersection) {
172  // lane width affects the crossing point
173  intersections1.back() -= (*it_lane)->getWidth() / 2;
174  intersections2.back() -= lane->getWidth() / 2;
175  // also length/geometry factor
176  intersections1.back() = lane->interpolateGeometryPosToLanePos(intersections1.back());
177  intersections2.back() = (*it_lane)->interpolateGeometryPosToLanePos(intersections2.back());
178 
179  if (internalLaneBefore->getLogicalPredecessorLane()->getEdge().isInternal() && !(*it_lane)->getEdge().isCrossing()) {
180  // wait at the internal junction
181  // (except for foes that are crossings since there is no internal junction)
182  intersections1.back() = 0;
183  }
184  }
185 
186  myLengthsBehindCrossing.push_back(std::make_pair(
187  lane->getLength() - intersections1.back(),
188  (*it_lane)->getLength() - intersections2.back()));
189 
190 #ifdef MSLink_DEBUG_CROSSING_POINTS
191  std::cout
192  << " intersection of " << lane->getID()
193  << " totalLength=" << lane->getLength()
194  << " with " << (*it_lane)->getID()
195  << " totalLength=" << (*it_lane)->getLength()
196  << " dist1=" << myLengthsBehindCrossing.back().first
197  << " dist2=" << myLengthsBehindCrossing.back().second
198  << "\n";
199 #endif
200  }
201  }
202  // check for overlap with internal lanes from the same source lane
203  const MSLane* pred = lane->getLogicalPredecessorLane();
204  // to avoid overlap with vehicles that came from pred (especially when pred has endOffset > 0)
205  // we add all other internal lanes from pred as foeLanes
206  const MSLinkCont& predLinks = pred->getLinkCont();
207  for (MSLinkCont::const_iterator it = predLinks.begin(); it != predLinks.end(); ++it) {
208  const MSLane* sibling = (*it)->getViaLane();
209  if (sibling != lane && sibling != 0) {
210  std::vector<SUMOReal> intersections1 = lane->getShape().intersectsAtLengths2D(sibling->getShape());
211 #ifdef MSLink_DEBUG_CROSSING_POINTS
212  //std::cout << " intersections1=" << toString(intersections1) << "\n";
213 #endif
214  if (intersections1.size() > 0) {
215  std::sort(intersections1.begin(), intersections1.end());
216  if (intersections1.back() > NUMERICAL_EPS) {
217  // siblings share a common shape up to the last crossing point so intersections are identical and only need to be computed once
218  myLengthsBehindCrossing.push_back(std::make_pair(
219  lane->getLength() - intersections1.back(),
220  sibling->getLength() - intersections1.back()));
221  myFoeLanes.push_back(sibling);
222 #ifdef MSLink_DEBUG_CROSSING_POINTS
223  std::cout << " adding same-origin foe" << sibling->getID()
224  << " dist1=" << myLengthsBehindCrossing.back().first
225  << " dist2=" << myLengthsBehindCrossing.back().second
226  << "\n";
227 #endif
228  }
229  }
230  }
231  }
232  }
233 #else
234  UNUSED_PARAMETER(internalLaneBefore);
235 #endif
236 }
237 
238 
239 std::pair<SUMOReal, SUMOReal>
240 getLastIntersections(const MSLane* lane, const MSLane* foe);
241 
242 void
243 MSLink::setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime, const SUMOReal arrivalSpeed, const SUMOReal leaveSpeed,
244  const bool setRequest, const SUMOTime arrivalTimeBraking, const SUMOReal arrivalSpeedBraking, const SUMOTime waitingTime, SUMOReal dist) {
245  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, approaching->getVehicleType().getLength());
246  myApproachingVehicles.insert(std::make_pair(approaching,
247  ApproachingVehicleInformation(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, setRequest,
248  arrivalTimeBraking, arrivalSpeedBraking, waitingTime, dist)));
249 }
250 
251 
252 void
254  myBlockedFoeLinks.insert(link);
255 }
256 
257 
258 
259 bool
261  for (std::set<MSLink*>::const_iterator i = myBlockedFoeLinks.begin(); i != myBlockedFoeLinks.end(); ++i) {
262  if ((*i)->isBlockingAnyone()) {
263  return true;
264  }
265  }
266  return false;
267 }
268 
269 
270 void
272  myApproachingVehicles.erase(veh);
273 }
274 
275 
278  std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.find(veh);
279  if (i != myApproachingVehicles.end()) {
280  return i->second;
281  } else {
282  return ApproachingVehicleInformation(-1000, -1000, 0, 0, false, -1000, 0, 0, 0);
283  }
284 }
285 
286 
287 SUMOTime
288 MSLink::getLeaveTime(const SUMOTime arrivalTime, const SUMOReal arrivalSpeed,
289  const SUMOReal leaveSpeed, const SUMOReal vehicleLength) const {
290  return arrivalTime + TIME2STEPS((getLength() + vehicleLength) / MAX2((SUMOReal)0.5 * (arrivalSpeed + leaveSpeed), NUMERICAL_EPS));
291 }
292 
293 
294 bool
295 MSLink::opened(SUMOTime arrivalTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed, SUMOReal vehicleLength,
296  SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime,
297  std::vector<const SUMOVehicle*>* collectFoes) const {
298  if (haveRed()) {
299  return false;
300  }
302  return true;
303  }
304  if (havePriority() && myState != LINKSTATE_ZIPPER) {
305  // zipper still needs to collect foes
306  return true;
307  }
308  if ((myState == LINKSTATE_STOP || myState == LINKSTATE_ALLWAY_STOP) && waitingTime == 0) {
309  return false;
310  }
311  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, vehicleLength);
312  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
314  if ((*i)->haveRed()) {
315  continue;
316  }
317  }
318  if ((*i)->blockedAtTime(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, myLane == (*i)->getLane(),
319  impatience, decel, waitingTime, collectFoes)) {
320  return false;
321  }
322  }
323  if (collectFoes != 0 && collectFoes->size() > 0) {
324  return false;
325  }
326  return true;
327 }
328 
329 
330 bool
331 MSLink::blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed,
332  bool sameTargetLane, SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime,
333  std::vector<const SUMOVehicle*>* collectFoes) const {
334  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
335  if (!i->second.willPass) {
336  continue;
337  }
339  assert(waitingTime > 0);
340  if (waitingTime > i->second.waitingTime) {
341  continue;
342  }
343  if (waitingTime == i->second.waitingTime && arrivalTime < i->second.arrivalTime) {
344  continue;
345  }
346  }
347  const SUMOTime foeArrivalTime = (SUMOTime)((1.0 - impatience) * i->second.arrivalTime + impatience * i->second.arrivalTimeBraking);
349  if (i->second.leavingTime < arrivalTime) {
350  // ego wants to be follower
351  if (sameTargetLane && (arrivalTime - i->second.leavingTime < lookAhead
352  || unsafeMergeSpeeds(i->second.leaveSpeed, arrivalSpeed,
353  i->first->getVehicleType().getCarFollowModel().getMaxDecel(), decel))) {
354  if (collectFoes == 0) {
355  return true;
356  } else {
357  collectFoes->push_back(i->first);
358  }
359  }
360  } else if (foeArrivalTime > leaveTime) {
361  // ego wants to be leader.
362  if (sameTargetLane && (foeArrivalTime - leaveTime < lookAhead
363  || unsafeMergeSpeeds(leaveSpeed, i->second.arrivalSpeedBraking,
364  decel, i->first->getVehicleType().getCarFollowModel().getMaxDecel()))) {
365  if (collectFoes == 0) {
366  return true;
367  } else {
368  collectFoes->push_back(i->first);
369  }
370  }
371  } else {
372  // even without considering safeHeadwayTime there is already a conflict
373  if (collectFoes == 0) {
374  return true;
375  } else {
376  collectFoes->push_back(i->first);
377  }
378  }
379  }
380  return false;
381 }
382 
383 
384 bool
386  MSVehicle* veh = lane->getLastVehicle();
387  SUMOReal distLeft = 0;
388  if (veh == 0) {
389  veh = lane->getPartialOccupator();
390  distLeft = lane->getLength() - lane->getPartialOccupatorEnd();
391  } else {
392  distLeft = lane->getLength() - veh->getPositionOnLane() + veh->getVehicleType().getLength();
393  }
394  if (veh == 0) {
395  return false;
396  } else {
397  assert(distLeft > 0);
398  // can we be sure that the vehicle leaves this lane in the next step?
399  bool result = distLeft > (veh->getSpeed() - veh->getCarFollowModel().getMaxDecel());
400  return result;
401  }
402 }
403 
404 
405 bool
406 MSLink::hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal speed, SUMOReal decel) const {
407  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
408  if ((*i)->blockedAtTime(arrivalTime, leaveTime, speed, speed, myLane == (*i)->getLane(), 0, decel, 0)) {
409  return true;
410  }
411  }
412  for (std::vector<const MSLane*>::const_iterator i = myFoeLanes.begin(); i != myFoeLanes.end(); ++i) {
413  if ((*i)->getVehicleNumber() > 0 || (*i)->getPartialOccupator() != 0) {
414  return true;
415  }
416  }
417  return false;
418 }
419 
420 
423  return myDirection;
424 }
425 
426 
427 void
429  if (myState != state) {
430  myLastStateChange = t;
431  }
432  myState = state;
433 }
434 
435 
436 MSLane*
438  return myLane;
439 }
440 
441 MSLane*
443  MSLane* approachedLane; //the lane approached by this link; this lane may be an internal lane
444 #ifdef HAVE_INTERNAL_LANES
445  if (myJunctionInlane != 0) { // if there is an internal lane
446  approachedLane = myJunctionInlane; //consider the internal lane as the approached lane
447  } else { //if ther is no internal lane
448  approachedLane = myLane;
449  }
450 #else
451  approachedLane = myLane;
452 #endif
453  const std::vector<MSLane::IncomingLaneInfo> possibleLanes = approachedLane->getIncomingLanes();
454  std::vector<MSLane::IncomingLaneInfo>::const_iterator i;
455  for (i = possibleLanes.begin(); i != possibleLanes.end(); i++) {
456  MSLane* lane = (*i).lane;
457  MSLinkCont outgoingLinks = lane->getLinkCont(); //the links outgoing from lane
458  for (MSLinkCont::const_iterator j = outgoingLinks.begin(); j != outgoingLinks.end(); j++) {
459  if ((*j) == this) {
460  return lane;
461  }
462  }
463  }
464  WRITE_WARNING("No approaching lane found for the link with the index " + toString(this->getIndex()) + ".");
465  return 0;
466 }
467 
468 
469 bool
471 #ifdef HAVE_INTERNAL_LANES
472  if (myJunctionInlane == 0 || myAmCont) {
473  return false;
474  } else {
475  MSLane* pred = myJunctionInlane->getLogicalPredecessorLane();
477  return false;
478  } else {
479  MSLane* pred2 = pred->getLogicalPredecessorLane();
480  assert(pred2 != 0);
481  MSLink* predLink = MSLinkContHelper::getConnectingLink(*pred2, *pred);
482  assert(predLink != 0);
483  return predLink->havePriority();
484  }
485  }
486 #else
487  return false;
488 #endif
489 }
490 
491 
492 void
493 MSLink::writeApproaching(OutputDevice& od, const std::string fromLaneID) const {
494  if (myApproachingVehicles.size() > 0) {
495  od.openTag("link");
496  od.writeAttr(SUMO_ATTR_FROM, fromLaneID);
497 #ifdef HAVE_INTERNAL_LANES
498  const std::string via = getViaLane() == 0 ? "" : getViaLane()->getID();
499 #else
500  const std::string via = "";
501 #endif
502  od.writeAttr(SUMO_ATTR_VIA, via);
503  od.writeAttr(SUMO_ATTR_TO, getLane() == 0 ? "" : getLane()->getID());
504  std::vector<std::pair<SUMOTime, const SUMOVehicle*> > toSort; // stabilize output
505  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator it = myApproachingVehicles.begin(); it != myApproachingVehicles.end(); ++it) {
506  toSort.push_back(std::make_pair(it->second.arrivalTime, it->first));
507  }
508  std::sort(toSort.begin(), toSort.end());
509  for (std::vector<std::pair<SUMOTime, const SUMOVehicle*> >::const_iterator it = toSort.begin(); it != toSort.end(); ++it) {
510  od.openTag("approaching");
511  const ApproachingVehicleInformation& avi = myApproachingVehicles.find(it->second)->second;
512  od.writeAttr(SUMO_ATTR_ID, it->second->getID());
513  od.writeAttr(SUMO_ATTR_IMPATIENCE, it->second->getImpatience());
514  od.writeAttr("arrivalTime", time2string(avi.arrivalTime));
515  od.writeAttr("arrivalTimeBraking", time2string(avi.arrivalTimeBraking));
516  od.writeAttr("leaveTime", time2string(avi.leavingTime));
517  od.writeAttr("arrivalSpeed", toString(avi.arrivalSpeed));
518  od.writeAttr("arrivalSpeedBraking", toString(avi.arrivalSpeedBraking));
519  od.writeAttr("leaveSpeed", toString(avi.leaveSpeed));
520  od.writeAttr("willPass", toString(avi.willPass));
521  od.closeTag();
522  }
523  od.closeTag();
524  }
525 }
526 
527 
528 #ifdef HAVE_INTERNAL_LANES
529 MSLane*
530 MSLink::getViaLane() const {
531  return myJunctionInlane;
532 }
533 
534 
535 bool
536 MSLink::isExitLink() const {
538  return MSGlobals::gUsingInternalLanes && myJunctionInlane == 0 && getLane()->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_NORMAL;
539 }
540 
541 
542 bool
544  return (MSGlobals::gUsingInternalLanes && myJunctionInlane != 0 && myJunctionInlane->getLogicalPredecessorLane()->getEdge().isInternal());
545 }
546 
547 bool
548 MSLink::fromInternalLane() const {
549  return (MSGlobals::gUsingInternalLanes && (
550  (myJunctionInlane == 0 && getLane()->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_NORMAL)
551  || (myJunctionInlane != 0 && myJunctionInlane->getLogicalPredecessorLane()->getEdge().isInternal())));
552 }
553 
555 MSLink::getLeaderInfo(SUMOReal dist, SUMOReal minGap, std::vector<const MSPerson*>* collectBlockers) const {
556  LinkLeaders result;
557  //gDebugFlag1 = true;
558  // this link needs to start at an internal lane (either an exit link or between two internal lanes)
559  if (fromInternalLane()) {
560  //if (gDebugFlag1) std::cout << SIMTIME << " getLeaderInfo link=" << getViaLaneOrLane()->getID() << "\n";
561  // this is an exit link
562  for (size_t i = 0; i < myFoeLanes.size(); ++i) {
563  const MSLane* foeLane = myFoeLanes[i];
564  // distance from the querying vehicle to the crossing point with foeLane
565  const SUMOReal distToCrossing = dist - myLengthsBehindCrossing[i].first;
566  const bool sameTarget = (myLane == foeLane->getLinkCont()[0]->getLane());
567  const bool sameSource = (myInternalLaneBefore != 0 && myInternalLaneBefore->getLogicalPredecessorLane() == foeLane->getLogicalPredecessorLane());
568  const SUMOReal crossingWidth = (sameTarget || sameSource) ? 0 : foeLane->getWidth();
569  const SUMOReal foeCrossingWidth = (sameTarget || sameSource) ? 0 : myInternalLaneBefore->getWidth();
570  //if (gDebugFlag1) std::cout << " distToCrossing=" << distToCrossing << " foeLane=" << foeLane->getID() << "\n";
571  if (distToCrossing + crossingWidth < 0) {
572  continue; // vehicle is behind the crossing point, continue with next foe lane
573  }
574  const SUMOReal foeDistToCrossing = foeLane->getLength() - myLengthsBehindCrossing[i].second;
575  // it is not sufficient to return the last vehicle on the foeLane because ego might be its leader
576  // therefore we return all vehicles on the lane
577  //
578  // special care must be taken for continuation lanes. (next lane is also internal)
579  // vehicles on these lanes should always block (gap = -1)
580  const bool contLane = (foeLane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL);
581  // vehicles on cont. lanes or on internal lanes with the same target as this link can never be ignored
582  const bool cannotIgnore = contLane || sameTarget || sameSource;
583  const MSLane::VehCont& vehicles = foeLane->getVehiclesSecure();
584  foeLane->releaseVehicles();
585  for (MSLane::VehCont::const_iterator it_veh = vehicles.begin(); it_veh != vehicles.end(); ++it_veh) {
586  MSVehicle* leader = *it_veh;
587  if (!cannotIgnore && !foeLane->getLinkCont()[0]->getApproaching(leader).willPass) {
588  continue;
589  }
590  if (cannotIgnore || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
591  // compute distance between vehicles on the the superimposition of both lanes
592  // where the crossing point is the common point
593  SUMOReal gap;
594  if (contLane && !sameSource) {
595  gap = -1; // always break for vehicles which are on a continuation lane
596  } else {
597  const SUMOReal leaderBack = leader->getPositionOnLane() - leader->getVehicleType().getLength();
598  const SUMOReal leaderBackDist = foeDistToCrossing - leaderBack;
599  //if (gDebugFlag1) std::cout << " distToCrossing=" << distToCrossing << " leader back=" << leaderBack << " backDist=" << leaderBackDist << "\n";
600  if (leaderBackDist + foeCrossingWidth < 0) {
601  // leader is completely past the crossing point
602  // or there is no crossing point
603  continue; // next vehicle
604  }
605  gap = distToCrossing - leaderBackDist - (sameTarget ? minGap : 0);
606  }
607  result.push_back(LinkLeader(leader, gap, cannotIgnore ? -1 : distToCrossing));
608  }
609 
610  }
611  MSVehicle* leader = foeLane->getPartialOccupator();
612  if (leader != 0) {
613  if (cannotIgnore || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
614  // compute distance between vehicles on the the superimposition of both lanes
615  // where the crossing point is the common point
616  SUMOReal gap;
617  if (contLane && !sameSource) {
618  gap = -1; // always break for vehicles which are on a continuation lane
619  } else {
620  const SUMOReal leaderBackDist = foeDistToCrossing - foeLane->getPartialOccupatorEnd();
621  //if (gDebugFlag1) std::cout << " distToCrossing=" << distToCrossing << " leader (partialOccupator) backDist=" << leaderBackDist << "\n";
622  if (leaderBackDist + foeCrossingWidth < 0) {
623  // leader is completely past the crossing point
624  // or there is no crossing point
625  continue; // next lane
626  }
627  gap = distToCrossing - leaderBackDist - (sameTarget ? minGap : 0);
628  }
629  result.push_back(LinkLeader(leader, gap, sameTarget ? -1 : distToCrossing));
630  }
631  }
632  // check for crossing pedestrians (keep driving if already on top of the crossing
633  const SUMOReal distToPeds = distToCrossing - MSPModel::SAFETY_GAP;
634  if (distToPeds >= -MSPModel::SAFETY_GAP && MSPModel::getModel()->blockedAtDist(foeLane, foeDistToCrossing, collectBlockers)) {
635  result.push_back(LinkLeader((MSVehicle*)0, -1, distToPeds));
636  }
637  }
638  }
639  return result;
640 }
641 #endif
642 
643 
644 MSLane*
646 #ifdef HAVE_INTERNAL_LANES
647  if (myJunctionInlane != 0) {
648  return myJunctionInlane;
649  }
650 #endif
651  return myLane;
652 }
653 
654 
655 void
657  if (myJunction != 0) {
658  myJunction->passedJunction(vehicle);
659  }
660 }
661 
662 
663 bool
664 MSLink::isLeader(const MSVehicle* ego, const MSVehicle* foe) {
665  if (myJunction != 0) {
666  return myJunction->isLeader(ego, foe);
667  } else {
668  // unregulated junction
669  return false;
670  }
671 }
672 
673 const MSLane*
675 #ifdef HAVE_INTERNAL_LANES
676  return myInternalLaneBefore;
677 #else
678  return 0;
679 #endif
680 }
681 
682 
683 SUMOReal
684 MSLink::getZipperSpeed(const MSVehicle* ego, const SUMOReal dist, SUMOReal vSafe,
685  SUMOTime arrivalTime,
686  std::vector<const SUMOVehicle*>* collectFoes) const {
687  //gDebugFlag1 = ego->getID() == "left.7";
688  if (myFoeLinks.size() == 0) {
689  // link should have LINKSTATE_MAJOR in this case
690  assert(false);
691  return vSafe;
692  } else if (myFoeLinks.size() > 1) {
693  throw ProcessError("Zipper junctions with more than two conflicting lanes are not supported (at junction '"
694  + myJunction->getID() + "')");
695  }
697  const SUMOReal secondsToArrival = STEPS2TIME(arrivalTime - now);
698  if (secondsToArrival > ZIPPER_ADAPT_TIME && dist > ZIPPER_ADAPT_DIST) {
699  //if (gDebugFlag1) std::cout << SIMTIME << " getZipperSpeed ego=" << ego->getID()
700  // << " dist=" << dist
701  // << " ignoring foes (arrival in " << STEPS2TIME(arrivalTime - now) << ")\n";
702  return vSafe;
703  }
704  //if (gDebugFlag1) std::cout << SIMTIME << " getZipperSpeed ego=" << ego->getID()
705  // << " egoAT=" << arrivalTime
706  // << " dist=" << dist
707  // << " vSafe=" << vSafe
708  // << " numFoes=" << collectFoes->size()
709  // << "\n";
710  MSLink* foeLink = myFoeLinks[0];
711  const SUMOReal vSafeOrig = vSafe;
712  for (std::vector<const SUMOVehicle*>::const_iterator i = collectFoes->begin(); i != collectFoes->end(); ++i) {
713  const MSVehicle* foe = dynamic_cast<const MSVehicle*>(*i);
714  assert(foe != 0);
715  const ApproachingVehicleInformation& avi = foeLink->getApproaching(foe);
716  if ( // ignore vehicles that arrive after us (unless they are ahead and we could easily brake for them)
717  ((avi.arrivalTime > arrivalTime) && !couldBrakeForLeader(dist, avi.dist, ego, foe)) ||
718  // also ignore vehicles that are behind us and are able to brake for us
719  couldBrakeForLeader(avi.dist, dist, foe, ego) ||
720  // resolve ties by lane index
721  (avi.arrivalTime == arrivalTime && avi.dist == dist && ego->getLane()->getIndex() < foe->getLane()->getIndex())) {
722  //if (gDebugFlag1) std::cout
723  // << " ignoring foe=" << foe->getID()
724  // << " foeAT=" << avi.arrivalTime
725  // << " foeDist=" << avi.dist
726  // << " foeSpeed=" << foe->getSpeed()
727  // << " egoSpeed=" << ego->getSpeed()
728  // << " deltaDist=" << avi.dist - dist
729  // << " delteSpeed=" << foe->getSpeed() - foe->getCarFollowModel().getMaxDecel() - ego->getSpeed()
730  // << "\n";
731  continue;
732  }
733  const SUMOReal gap = dist - foe->getVehicleType().getLength() - ego->getVehicleType().getMinGap() - avi.dist;
734  const SUMOReal follow = ego->getCarFollowModel().followSpeed(
735  ego, ego->getSpeed(), gap, foe->getSpeed(), foe->getCarFollowModel().getMaxDecel());
736  // speed adaption to follow the foe can be spread over secondsToArrival
737  const SUMOReal followInTime = vSafeOrig + (follow - vSafeOrig) / MAX2((SUMOReal)1, secondsToArrival / TS);
738  vSafe = MIN2(vSafe, followInTime);
739  //if (gDebugFlag1) std::cout << " adapting to foe=" << foe->getID()
740  // << " foeDist=" << avi.dist
741  // << " follow=" << follow
742  // << " followInTime=" << followInTime
743  // << " gap=" << gap
744  // << " foeSpeed=" << foe->getSpeed()
745  // << " follow=" << follow
746  // << " foeAT=" << avi.arrivalTime
747  // << " foeLT=" << avi.leavingTime
748  // << " foeAS=" << avi.arrivalSpeed
749  // << " vSafe=" << vSafe
750  // << "\n";
751  }
752  return vSafe;
753 }
754 
755 
756 bool
757 MSLink::couldBrakeForLeader(SUMOReal followDist, SUMOReal leaderDist, const MSVehicle* follow, const MSVehicle* leader) {
758  return (// leader is ahead of follower
759  followDist > leaderDist &&
760  // and follower could brake for 1 s to stay behind leader
761  followDist - leaderDist > follow->getSpeed() - follow->getCarFollowModel().getMaxDecel() - leader->getSpeed());
762 }
763 
764 
765 /****************************************************************************/
766 
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:257
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:467
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:80
long long int SUMOTime
Definition: SUMOTime.h:43
static const SUMOReal SAFETY_GAP
Definition: MSPModel.h:78
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:302
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:627
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:413
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.
SUMOReal getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:375
The base class for an intersection.
Definition: MSJunction.h:64
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:88
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
SUMOReal getLength() const
Get vehicle&#39;s length [m].
SUMOReal getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:391
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:160
T MAX2(T a, T b)
Definition: StdDefs.h:75
SUMOReal getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:340
#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:39
This is an uncontrolled, zipper-merge link.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:295
SUMOReal getPartialOccupatorEnd() const
Returns the position of the in-lapping vehicle&#39;s end.
Definition: MSLane.h:260
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:65
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:1308
void passedJunction(const MSVehicle *vehicle)
erase vehicle from myLinkLeaders
Definition: MSJunction.cpp:77
Representation of a vehicle.
Definition: SUMOVehicle.h:65
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
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.
T MIN2(T a, T b)
Definition: StdDefs.h:69
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:69
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:186
MSVehicle * getLastVehicle() const
returns the last vehicle
Definition: MSLane.cpp:880
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:54
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:398
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:247
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:242
The edge is a normal street.
Definition: MSEdge.h:93
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
Definition: MSBaseVehicle.h:93
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:348
static SUMOTime gIgnoreJunctionBlocker
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:72
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:322
MSVehicle * getPartialOccupator() const
Returns the vehicle which laps into this lane.
Definition: MSLane.h:252
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
const MSJunction * getFromJunction() const
Definition: MSEdge.h:372
#define NUMERICAL_EPS
Definition: config.h:160
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:947
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:385
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:589
The edge is an internal edge.
Definition: MSEdge.h:97
SUMOReal interpolateGeometryPosToLanePos(SUMOReal geometryPos) const
Definition: MSLane.h:345
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 ...
static bool gUseMesoSim
Definition: MSGlobals.h:87
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
bool isLeader(const MSVehicle *ego, const MSVehicle *foe)
Definition: MSJunction.cpp:83
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.