Eclipse SUMO - Simulation of Urban MObility
MSLink.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
21 // A connnection between lanes
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <iostream>
26 #include <algorithm>
27 #include <limits>
30 #include "MSNet.h"
31 #include "MSJunction.h"
32 #include "MSLink.h"
33 #include "MSLane.h"
36 #include "MSEdge.h"
37 #include "MSGlobals.h"
38 #include "MSVehicle.h"
41 
42 //#define MSLink_DEBUG_CROSSING_POINTS
43 //#define MSLink_DEBUG_CROSSING_POINTS_DETAILS
44 //#define MSLink_DEBUG_OPENED
45 //#define DEBUG_APPROACHING
46 //#define DEBUG_ZIPPER
47 //#define DEBUG_COND (myLane->getID()=="43[0]_0" && myLaneBefore->getID()==":33_0_0")
48 //#define DEBUG_COND (myLane->getID()=="end_0")
49 //#define DEBUG_COND (true)
50 //#define DEBUG_COND2(obj) (obj->isSelected())
51 #define DEBUG_COND2(obj) (obj->getID() == "train2")
52 //#define DEBUG_COND_ZIPPER (gDebugFlag1)
53 //#define DEBUG_COND_ZIPPER (true)
54 #define DEBUG_COND_ZIPPER (ego->isSelected())
55 
56 // ===========================================================================
57 // static member variables
58 // ===========================================================================
60 // additional caution is needed when approaching a zipper link
62 
63 const double MSLink::ZIPPER_ADAPT_DIST(100);
64 
65 // time to link in seconds below which adaptation should take place
66 #define ZIPPER_ADAPT_TIME 10
67 // the default safety gap when passing before oncoming pedestrians
68 #define JM_CROSSING_GAP_DEFAULT 10
69 
70 // minimim width between sibling lanes to qualify as non-overlapping
71 #define DIVERGENCE_MIN_WIDTH 2.5
72 
73 // ===========================================================================
74 // member method definitions
75 // ===========================================================================
76 MSLink::MSLink(MSLane* predLane, MSLane* succLane, MSLane* via, LinkDirection dir, LinkState state, double length, double foeVisibilityDistance, bool keepClear, MSTrafficLightLogic* logic, int tlIndex) :
77  myLane(succLane),
78  myLaneBefore(predLane),
79  myIndex(-1),
80  myTLIndex(tlIndex),
81  myLogic(logic),
82  myState(state),
83  myOffState(state),
84  myLastStateChange(SUMOTime_MIN / 2), // a large negative value, but avoid overflows when subtracting
85  myDirection(dir),
86  myLength(length),
87  myFoeVisibilityDistance(foeVisibilityDistance),
88  myHasFoes(false),
89  myAmCont(false),
90  myAmContOff(false),
91  myKeepClear(keepClear),
92  myInternalLane(via),
93  myInternalLaneBefore(nullptr),
94  myMesoTLSPenalty(0),
95  myGreenFraction(1),
96  myLateralShift(0),
97  myWalkingAreaFoe(nullptr),
98  myWalkingAreaFoeExit(nullptr),
99  myHavePedestrianCrossingFoe(false),
100  myParallelRight(nullptr),
101  myParallelLeft(nullptr),
102  myJunction(nullptr) {
103 
105  // detect lateral shift from lane geometries
106  //std::cout << "DEBUG link=" << myLaneBefore->getID() << "->" << getViaLaneOrLane()->getID() << " hasInternal=" << MSNet::getInstance()->hasInternalLinks() << " shapeBefore=" << myLaneBefore->getShape().back() << " shapeFront=" << getViaLaneOrLane()->getShape().front() << "\n";
107  if ((myInternalLane != nullptr || predLane->isInternal())
108  && myLaneBefore->getShape().back() != getViaLaneOrLane()->getShape().front()) {
110  const PositionVector& to = getViaLaneOrLane()->getShape();
111  const double dist = from.back().distanceTo2D(to.front());
112  // figure out direction of shift
113  try {
114  from.move2side(dist);
115  } catch (InvalidArgument&) {
116  }
117  myLateralShift = (from.back().distanceTo2D(to.front()) < dist) ? dist : -dist;
118  if (MSGlobals::gLefthand) {
119  myLateralShift *= -1;
120  }
121  //std::cout << " lateral shift link=" << myLaneBefore->getID() << "->" << getViaLaneOrLane()->getID() << " dist=" << dist << " shift=" << myLateralShift << "\n";
122  }
123  }
124 }
125 
126 
128 
129 
130 void
131 MSLink::setRequestInformation(int index, bool hasFoes, bool isCont,
132  const std::vector<MSLink*>& foeLinks,
133  const std::vector<MSLane*>& foeLanes,
134  MSLane* internalLaneBefore) {
135 //#ifdef MSLink_DEBUG_CROSSING_POINTS
136 // std::cout << " setRequestInformation() for junction " << getViaLaneOrLane()->getEdge().getFromJunction()->getID()
137 // << "\nInternalLanes = " << toString(getViaLaneOrLane()->getEdge().getFromJunction()->getInternalLanes())
138 // << std::endl;
139 //#endif
140  myIndex = index;
141  myHasFoes = hasFoes;
142  myAmCont = isCont;
143  myFoeLinks = foeLinks;
144  for (std::vector<MSLane*>::const_iterator it_lane = foeLanes.begin(); it_lane != foeLanes.end(); ++it_lane) {
145  // cannot assign vector due to const-ness
146  myFoeLanes.push_back(*it_lane);
147  }
148  myJunction = const_cast<MSJunction*>(myLane->getEdge().getFromJunction()); // junctionGraph is initialized after the whole network is loaded
149  myAmContOff = isCont && myLogic != nullptr && internalLaneBefore == nullptr && checkContOff();
150  myInternalLaneBefore = internalLaneBefore;
151  MSLane* lane = nullptr;
152  if (internalLaneBefore != nullptr) {
153  // this is an exit link. compute crossing points with all foeLanes
154  lane = internalLaneBefore;
155  //} else if (myLane->getEdge().isCrossing()) {
156  // // this is the link to a pedestrian crossing. compute crossing points with all foeLanes
157  // // @note not currently used by pedestrians
158  // lane = myLane;
159  }
160 #ifdef MSLink_DEBUG_CROSSING_POINTS
161  std::cout << " link " << myIndex << " to " << getViaLaneOrLane()->getID() << " internalLaneBefore=" << (lane == 0 ? "NULL" : lane->getID()) << " has foes: " << toString(foeLanes) << "\n";
162 #endif
163  if (lane != nullptr) {
164  const bool beforeInternalJunction = lane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().isInternal();
165  if (lane->getIncomingLanes().size() != 1) {
166  throw ProcessError("Internal lane '" + lane->getID() + "' has " + toString(lane->getIncomingLanes().size()) + " predecessors");
167  }
168  // compute crossing points
169  for (std::vector<const MSLane*>::const_iterator it_lane = myFoeLanes.begin(); it_lane != myFoeLanes.end(); ++it_lane) {
170  myHavePedestrianCrossingFoe = myHavePedestrianCrossingFoe || (*it_lane)->getEdge().isCrossing();
171  const bool sameTarget = myLane == (*it_lane)->getLinkCont()[0]->getLane();
172  if (sameTarget && !beforeInternalJunction && !contIntersect(lane, *it_lane)) {
173  //if (myLane == (*it_lane)->getLinkCont()[0]->getLane()) {
174  // this foeLane has the same target and merges at the end (lane exits the junction)
175  const MSLane* sibling = *it_lane;
176  const double minDist = MIN2(DIVERGENCE_MIN_WIDTH, 0.5 * (lane->getWidth() + sibling->getWidth()));
177  if (lane->getShape().back().distanceTo2D(sibling->getShape().back()) >= minDist) {
178  // account for lateral shift by the entry links
179  myLengthsBehindCrossing.push_back(std::make_pair(0, 0)); // dummy value, never used
180  } else {
181  const double distAfterDivergence = computeDistToDivergence(lane, sibling, minDist, false);
182  const double lbcLane = lane->interpolateGeometryPosToLanePos(distAfterDivergence);
183  const double lbcSibling = sibling->interpolateGeometryPosToLanePos(distAfterDivergence);
184  myLengthsBehindCrossing.push_back(std::make_pair(lbcLane, lbcSibling));
185 #ifdef MSLink_DEBUG_CROSSING_POINTS
186  std::cout
187  << " " << lane->getID()
188  << " merges with " << (*it_lane)->getID()
189  << " nextLane " << lane->getLinkCont()[0]->getViaLaneOrLane()->getID()
190  << " dist1=" << myLengthsBehindCrossing.back().first
191  << " dist2=" << myLengthsBehindCrossing.back().second
192  << "\n";
193 #endif
194  }
195  } else {
196  std::vector<double> intersections1 = lane->getShape().intersectsAtLengths2D((*it_lane)->getShape());
197 #ifdef MSLink_DEBUG_CROSSING_POINTS_DETAILS
198  std::cout << " intersections1=" << toString(intersections1) << "\n";
199 #endif
200  bool haveIntersection = true;
201  if (intersections1.size() == 0) {
202  intersections1.push_back(-10000.0); // disregard this foe (using maxdouble leads to nasty problems down the line)
203  haveIntersection = false;
204  } else if (intersections1.size() > 1) {
205  std::sort(intersections1.begin(), intersections1.end());
206  }
207  std::vector<double> intersections2 = (*it_lane)->getShape().intersectsAtLengths2D(lane->getShape());
208 #ifdef MSLink_DEBUG_CROSSING_POINTS_DETAILS
209  std::cout << " intersections2=" << toString(intersections2) << "\n";
210 #endif
211  if (intersections2.size() == 0) {
212  intersections2.push_back(0);
213  } else if (intersections2.size() > 1) {
214  std::sort(intersections2.begin(), intersections2.end());
215  }
216  if (haveIntersection) {
217  // lane width affects the crossing point
218  intersections1.back() -= (*it_lane)->getWidth() / 2;
219  intersections2.back() -= lane->getWidth() / 2;
220  // ensure negative offset for weird geometries
221  intersections1.back() = MAX2(0.0, intersections1.back());
222  intersections2.back() = MAX2(0.0, intersections2.back());
223 
224  // also length/geometry factor. (XXX: Why subtract width/2 *before* converting geometric position to lane pos? refs #3031)
225  intersections1.back() = lane->interpolateGeometryPosToLanePos(intersections1.back());
226  intersections2.back() = (*it_lane)->interpolateGeometryPosToLanePos(intersections2.back());
227 
228  if (internalLaneBefore->getLogicalPredecessorLane()->getEdge().isInternal() && !(*it_lane)->getEdge().isCrossing()) {
229  // wait at the internal junction
230  // (except for foes that are crossings since there is no internal junction)
231  intersections1.back() = 0;
232  }
233  }
234 
235  myLengthsBehindCrossing.push_back(std::make_pair(
236  lane->getLength() - intersections1.back(),
237  (*it_lane)->getLength() - intersections2.back()));
238 
239 #ifdef MSLink_DEBUG_CROSSING_POINTS
240  std::cout
241  << " intersection of " << lane->getID()
242  << " totalLength=" << lane->getLength()
243  << " with " << (*it_lane)->getID()
244  << " totalLength=" << (*it_lane)->getLength()
245  << " dist1=" << myLengthsBehindCrossing.back().first
246  << " dist2=" << myLengthsBehindCrossing.back().second
247  << "\n";
248 #endif
249  }
250  }
251  // check for overlap with internal lanes from the same source lane
252  const MSLane* pred = lane->getLogicalPredecessorLane();
253  // to avoid overlap with vehicles that came from pred (especially when pred has endOffset > 0)
254  // we add all other internal lanes from pred as foeLanes
255  for (const MSLink* const it : pred->getLinkCont()) {
256  const MSLane* sibling = it->getViaLane();
257  if (sibling != lane && sibling != nullptr) {
258  const double minDist = MIN2(DIVERGENCE_MIN_WIDTH, 0.5 * (lane->getWidth() + sibling->getWidth()));
259  if (lane->getShape().front().distanceTo2D(sibling->getShape().front()) >= minDist) {
260  // account for lateral shift by the entry links
261  continue;
262  }
263  const double distToDivergence = computeDistToDivergence(lane, sibling, minDist, true);
264  const double lbcLane = MAX2(0.0, lane->getLength() - lane->interpolateGeometryPosToLanePos(distToDivergence));
265  const double lbcSibling = MAX2(0.0, sibling->getLength() - sibling->interpolateGeometryPosToLanePos(distToDivergence));
266  myLengthsBehindCrossing.push_back(std::make_pair(lbcLane, lbcSibling));
267  myFoeLanes.push_back(sibling);
268 #ifdef MSLink_DEBUG_CROSSING_POINTS
269  std::cout << " adding same-origin foe" << sibling->getID()
270  << " dist1=" << myLengthsBehindCrossing.back().first
271  << " dist2=" << myLengthsBehindCrossing.back().second
272  << "\n";
273 #endif
274  }
275  }
276  }
278  // check for links with the same origin lane and the same destination edge
279  const MSEdge* myTarget = &myLane->getEdge();
280  // save foes for entry links
281  for (MSLink* const it : myLaneBefore->getLinkCont()) {
282  const MSEdge* target = &(it->getLane()->getEdge());
283  if (it == this) {
284  continue;
285  }
286  if (target == myTarget) {
287  mySublaneFoeLinks.push_back(it);
288 #ifdef MSLink_DEBUG_CROSSING_POINTS
289  std::cout << " sublaneFoeLink (same target): " << it->getViaLaneOrLane()->getID() << "\n";
290 #endif
291  } else if (myDirection != LinkDirection::STRAIGHT && it->getDirection() == LinkDirection::STRAIGHT) {
292  // potential turn conflicht
293  mySublaneFoeLinks2.push_back(it);
294 #ifdef MSLink_DEBUG_CROSSING_POINTS
295  std::cout << " sublaneFoeLink2 (other target: " << it->getViaLaneOrLane()->getID() << "\n";
296 #endif
297  }
298  }
299  // save foes for exit links
300  if (fromInternalLane()) {
301  //std::cout << " setRequestInformation link=" << getViaLaneOrLane()->getID() << " before=" << myLaneBefore->getID() << " before2=" << myLaneBefore->getIncomingLanes().front().lane->getID() << "\n";
302  for (const MSLink* const link : myLaneBefore->getIncomingLanes().front().lane->getLinkCont()) {
303  if (link->getViaLane() != myInternalLaneBefore && &link->getLane()->getEdge() == myTarget) {
304  //std::cout << " add sublaneFoe=" << (*it)->getViaLane()->getID() << "\n";
305  mySublaneFoeLanes.push_back(link->getViaLane());
306  }
307  }
308  }
309  }
310 }
311 
312 
313 double
314 MSLink::computeDistToDivergence(const MSLane* lane, const MSLane* sibling, double minDist, bool sameSource) const {
315  PositionVector l = lane->getShape();
316  PositionVector s = sibling->getShape();
317  if (!sameSource) {
318  l = l.reverse();
319  s = s.reverse();
320  }
321 
322  double lbcSibling = 0;
323  double lbcLane = 0;
324  //std::cout << " sameSource=" << sameSource << " minDist=" << minDist << " backDist=" << l.back().distanceTo2D(s.back()) << "\n";
325  if (l.back().distanceTo2D(s.back()) > minDist) {
326  // compute the final divergence point
327  // this position serves two purposes:
328  // 1) once the foe vehicle back (on sibling) has passed this point, we can safely ignore it
329  // 2) both vehicles are put into a cf-relationship while before the point.
330  // Since the actual crossing point is at the start of the junction,
331  // we want to make sure that both vehicles have the same distance to the crossing point and thus follow each other naturally
332  std::vector<double> distances = l.distances(s);
333 #ifdef MSLink_DEBUG_CROSSING_POINTS
334  std::cout << " distances=" << toString(distances) << "\n";
335 #endif
336  assert(distances.size() == l.size() + s.size());
337  if (distances.back() > minDist && distances[l.size() - 1] > minDist) {
338  // do a pairwise check between lane and sibling to make because we do not know which of them bends more
339  for (int j = (int)s.size() - 2; j >= 0; j--) {
340  const int i = j + (int)l.size();
341  const double segLength = s[j].distanceTo2D(s[j + 1]);
342  if (distances[i] > minDist) {
343  lbcSibling += segLength;
344  } else {
345  // assume no sharp bends and just interpolate the last segment
346  lbcSibling += segLength - (minDist - distances[i]) * segLength / (distances[i + 1] - distances[i]);
347  break;
348  }
349  }
350  for (int i = (int)l.size() - 2; i >= 0; i--) {
351  const double segLength = l[i].distanceTo2D(l[i + 1]);
352  if (distances[i] > minDist) {
353  lbcLane += segLength;
354  } else {
355  // assume no sharp bends and just interpolate the last segment
356  lbcLane += segLength - (minDist - distances[i]) * segLength / (distances[i + 1] - distances[i]);
357  break;
358  }
359  }
360  }
361  assert(lbcSibling >= -NUMERICAL_EPS);
362  assert(lbcLane >= -NUMERICAL_EPS);
363  }
364  const double distToDivergence1 = sibling->getLength() - lbcSibling;
365  const double distToDivergence2 = lane->getLength() - lbcLane;
366  const double distToDivergence = MIN3(
367  MAX2(distToDivergence1, distToDivergence2),
368  s.length2D(), l.length2D());
369 #ifdef MSLink_DEBUG_CROSSING_POINTS
370  std::cout << " distToDivergence=" << distToDivergence
371  << " distTD1=" << distToDivergence1
372  << " distTD2=" << distToDivergence2
373  << " length=" << l.length2D()
374  << " sibLength=" << s.length2D()
375  << "\n";
376 #endif
377  return distToDivergence;
378 }
379 
380 
381 bool
382 MSLink::contIntersect(const MSLane* lane, const MSLane* foe) {
383  if (foe->getLinkCont()[0]->getViaLane() != nullptr) {
384  std::vector<double> intersections = lane->getShape().intersectsAtLengths2D(foe->getShape());
385  return intersections.size() > 0;
386  }
387  return false;
388 }
389 
390 
391 void
392 MSLink::setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime, const double arrivalSpeed, const double leaveSpeed,
393  const bool setRequest, const SUMOTime arrivalTimeBraking, const double arrivalSpeedBraking, const SUMOTime waitingTime, double dist) {
394  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, approaching->getVehicleType().getLength());
395 #ifdef DEBUG_APPROACHING
396  if (DEBUG_COND2(approaching)) {
397  std::cout << SIMTIME << " Link '" << (myLaneBefore == 0 ? "NULL" : myLaneBefore->getID()) << "'->'" << (myLane == 0 ? "NULL" : myLane->getID()) << "' Adding approaching vehicle '" << approaching->getID() << "'\nCurrently registered vehicles:" << std::endl;
398  for (auto i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
399  std::cout << "'" << i->first->getID() << "'" << std::endl;
400  }
401  }
402 #endif
403  myApproachingVehicles.emplace(approaching,
404  ApproachingVehicleInformation(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, setRequest,
405  arrivalTimeBraking, arrivalSpeedBraking, waitingTime, dist, approaching->getSpeed()));
406 }
407 
408 
409 void
411 
412 #ifdef DEBUG_APPROACHING
413  if (DEBUG_COND2(approaching)) {
414  std::cout << SIMTIME << " Link '" << (myLaneBefore == 0 ? "NULL" : myLaneBefore->getID()) << "'->'" << (myLane == 0 ? "NULL" : myLane->getID()) << "' Adding approaching vehicle '" << approaching->getID() << "'\nCurrently registered vehicles:" << std::endl;
415  for (auto i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
416  std::cout << "'" << i->first->getID() << "'" << std::endl;
417  }
418  }
419 #endif
420  myApproachingVehicles.emplace(approaching, ai);
421 }
422 
423 
424 void
426  myBlockedFoeLinks.insert(link);
427 }
428 
429 
430 
431 bool
433  for (std::set<MSLink*>::const_iterator i = myBlockedFoeLinks.begin(); i != myBlockedFoeLinks.end(); ++i) {
434  if ((*i)->isBlockingAnyone()) {
435  return true;
436  }
437  }
438  return false;
439 }
440 
441 
442 void
444 
445 #ifdef DEBUG_APPROACHING
446  if (DEBUG_COND2(veh)) {
447  std::cout << SIMTIME << " Link '" << (myLaneBefore == 0 ? "NULL" : myLaneBefore->getID()) << "'->'" << (myLane == 0 ? "NULL" : myLane->getID()) << std::endl;
448  std::cout << "' Removing approaching vehicle '" << veh->getID() << "'\nCurrently registered vehicles:" << std::endl;
449  for (auto i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
450  std::cout << "'" << i->first->getID() << "'" << std::endl;
451  }
452  }
453 #endif
454  myApproachingVehicles.erase(veh);
455 }
456 
457 
460  auto i = myApproachingVehicles.find(veh);
461  if (i != myApproachingVehicles.end()) {
462  return i->second;
463  } else {
464  return ApproachingVehicleInformation(-1000, -1000, 0, 0, false, -1000, 0, 0, 0, 0);
465  }
466 }
467 
468 void
470  myApproachingVehicles.clear();
471 }
472 
473 SUMOTime
474 MSLink::getLeaveTime(const SUMOTime arrivalTime, const double arrivalSpeed,
475  const double leaveSpeed, const double vehicleLength) const {
476  return arrivalTime + TIME2STEPS((getLength() + vehicleLength) / MAX2(0.5 * (arrivalSpeed + leaveSpeed), NUMERICAL_EPS));
477 }
478 
479 
480 bool
481 MSLink::opened(SUMOTime arrivalTime, double arrivalSpeed, double leaveSpeed, double vehicleLength,
482  double impatience, double decel, SUMOTime waitingTime, double posLat,
483  BlockingFoes* collectFoes, bool ignoreRed, const SUMOTrafficObject* ego) const {
484  if (haveRed() && !ignoreRed) {
485  return false;
486  }
488  return true;
489  }
490  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, vehicleLength);
492  // check for foes on the same lane with the same target edge
493  for (const MSLink* foeLink : mySublaneFoeLinks) {
494  assert(myLane != foeLink->getLane());
495  for (const auto& it : foeLink->myApproachingVehicles) {
496  const SUMOVehicle* foe = it.first;
497  if (
498  // there only is a conflict if the paths cross
499  ((posLat < foe->getLateralPositionOnLane() && myLane->getIndex() > foeLink->myLane->getIndex())
500  || (posLat > foe->getLateralPositionOnLane() && myLane->getIndex() < foeLink->myLane->getIndex()))
501  // the vehicle that arrives later must yield
502  && (arrivalTime > it.second.arrivalTime
503  // if both vehicles arrive at the same time, the one
504  // to the left must yield
505  || (arrivalTime == it.second.arrivalTime && posLat > foe->getLateralPositionOnLane()))) {
506  if (blockedByFoe(foe, it.second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, false,
507  impatience, decel, waitingTime, ego)) {
508 #ifdef MSLink_DEBUG_OPENED
509  if (gDebugFlag1) {
510  std::cout << SIMTIME << " blocked by " << foe->getID() << " arrival=" << arrivalTime << " foeArrival=" << it.second.arrivalTime << "\n";
511  }
512 #endif
513  if (collectFoes == nullptr) {
514 #ifdef MSLink_DEBUG_OPENED
515  if (gDebugFlag1) {
516  std::cout << " link=" << getViaLaneOrLane()->getID() << " blocked by sublaneFoe=" << foe->getID() << " foeLink=" << foeLink->getViaLaneOrLane()->getID() << " posLat=" << posLat << "\n";
517  }
518 #endif
519  return false;
520  } else {
521  collectFoes->push_back(it.first);
522  }
523  }
524  }
525  }
526  }
527  // check for foes on the same lane with a different target edge
528  // (straight movers take precedence if the paths cross)
529  const int lhSign = MSGlobals::gLefthand ? -1 : 1;
530  for (const MSLink* foeLink : mySublaneFoeLinks2) {
532  for (const auto& it : foeLink->myApproachingVehicles) {
533  const SUMOVehicle* foe = it.first;
534  // there only is a conflict if the paths cross
536  && (posLat * lhSign > foe->getLateralPositionOnLane() * lhSign))
538  && (posLat * lhSign < foe->getLateralPositionOnLane() * lhSign))) {
539  if (blockedByFoe(foe, it.second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, false,
540  impatience, decel, waitingTime, ego)) {
541 #ifdef MSLink_DEBUG_OPENED
542  if (gDebugFlag1) {
543  std::cout << SIMTIME << " blocked by sublane foe " << foe->getID() << " arrival=" << arrivalTime << " foeArrival=" << it.second.arrivalTime << "\n";
544  }
545 #endif
546  if (collectFoes == nullptr) {
547  return false;
548  } else {
549  collectFoes->push_back(it.first);
550  }
551  }
552  }
553  }
554  }
555  }
557  // priority usually means the link is open but there are exceptions:
558  // zipper still needs to collect foes
559  // sublane model could have detected a conflict
560  return collectFoes == nullptr || collectFoes->size() == 0;
561  }
562  if ((myState == LINKSTATE_STOP || myState == LINKSTATE_ALLWAY_STOP) && waitingTime == 0) {
563  return false;
564  }
565 
566 #ifdef MSLink_DEBUG_OPENED
567  if (gDebugFlag1) {
568  std::cout << SIMTIME << " opened link=" << getViaLaneOrLane()->getID() << " foeLinks=" << myFoeLinks.size() << "\n";
569  }
570 #endif
571 
572  if (MSGlobals::gUseMesoSim && impatience == 1) {
573  return true;
574  }
575  for (const MSLink* const link : myFoeLinks) {
577  if (link->haveRed()) {
578  continue;
579  }
580  }
581 #ifdef MSLink_DEBUG_OPENED
582  if (gDebugFlag1) {
583  std::cout << " foeLink=" << link->getViaLaneOrLane()->getID() << " numApproaching=" << link->getApproaching().size() << "\n";
584  }
585 #endif
586  if (link->blockedAtTime(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, myLane == link->getLane(),
587  impatience, decel, waitingTime, collectFoes, ego)) {
588  return false;
589  }
590  }
591  if (collectFoes != nullptr && collectFoes->size() > 0) {
592  return false;
593  }
594  return true;
595 }
596 
597 
598 bool
599 MSLink::blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
600  bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
601  BlockingFoes* collectFoes, const SUMOTrafficObject* ego) const {
602  for (const auto& it : myApproachingVehicles) {
603 #ifdef MSLink_DEBUG_OPENED
604  if (gDebugFlag1) {
605  if (ego != nullptr
606  && ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_FOE_SPEED, 0) >= it.second.speed
608  std::stringstream stream; // to reduce output interleaving from different threads
609  stream << SIMTIME << " " << myApproachingVehicles.size() << " foe link=" << getViaLaneOrLane()->getID()
610  << " foeVeh=" << it.first->getID() << " (below ignore speed)"
611  << " ignoreFoeProb=" << ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_FOE_PROB, 0)
612  << "\n";
613  std::cout << stream.str();
614  }
615  }
616 #endif
617  if (it.first != ego
618  && (ego == nullptr
620  || ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_FOE_SPEED, 0) < it.second.speed
622  && blockedByFoe(it.first, it.second, arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, sameTargetLane,
623  impatience, decel, waitingTime, ego)) {
624  if (collectFoes == nullptr) {
625  return true;
626  } else {
627  collectFoes->push_back(it.first);
628  }
629  }
630  }
631  return false;
632 }
633 
634 
635 bool
637  SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
638  bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
639  const SUMOTrafficObject* ego) const {
640 #ifdef MSLink_DEBUG_OPENED
641  if (gDebugFlag1) {
642  std::stringstream stream; // to reduce output interleaving from different threads
643  stream << " foe link=" << getViaLaneOrLane()->getID()
644  << " foeVeh=" << veh->getID()
645  << " req=" << avi.willPass
646  << " aT=" << avi.arrivalTime
647  << " lT=" << avi.leavingTime
648  << "\n";
649  std::cout << stream.str();
650  }
651 #endif
652  if (!avi.willPass) {
653  return false;
654  }
656  assert(waitingTime > 0);
657  if (waitingTime > avi.waitingTime) {
658  return false;
659  }
660  if (waitingTime == avi.waitingTime && arrivalTime < avi.arrivalTime) {
661  return false;
662  }
663  }
664  const SUMOTime foeArrivalTime = (SUMOTime)((1.0 - impatience) * avi.arrivalTime + impatience * avi.arrivalTimeBraking);
665  const SUMOTime lookAhead = (myState == LINKSTATE_ZIPPER
667  : (ego == nullptr
670  //if (ego != 0) std::cout << SIMTIME << " ego=" << ego->getID() << " jmTimegapMinor=" << ego->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_TIMEGAP_MINOR, -1) << " lookAhead=" << lookAhead << "\n";
671 #ifdef MSLink_DEBUG_OPENED
672  if (gDebugFlag1) {
673  std::stringstream stream; // to reduce output interleaving from different threads
674  stream << " imp=" << impatience << " fATb=" << avi.arrivalTimeBraking << " fAT2=" << foeArrivalTime << " lA=" << lookAhead << " egoAT=" << arrivalTime << " egoLT=" << leaveTime << "\n";
675  std::cout << stream.str();
676  }
677 #endif
678  if (avi.leavingTime < arrivalTime) {
679  // ego wants to be follower
680  if (sameTargetLane && (arrivalTime - avi.leavingTime < lookAhead
681  || unsafeMergeSpeeds(avi.leaveSpeed, arrivalSpeed,
682  veh->getVehicleType().getCarFollowModel().getMaxDecel(), decel))) {
683 #ifdef MSLink_DEBUG_OPENED
684  if (gDebugFlag1) {
685  std::cout << " blocked (cannot follow)\n";
686  }
687 #endif
688  return true;
689  }
690  } else if (foeArrivalTime > leaveTime + lookAhead) {
691  // ego wants to be leader.
692  if (sameTargetLane && unsafeMergeSpeeds(leaveSpeed, avi.arrivalSpeedBraking,
693  decel, veh->getVehicleType().getCarFollowModel().getMaxDecel())) {
694 #ifdef MSLink_DEBUG_OPENED
695  if (gDebugFlag1) {
696  std::cout << " blocked (cannot lead)\n";
697  }
698 #endif
699  return true;
700  }
701  } else {
702  // even without considering safeHeadwayTime there is already a conflict
703 #ifdef MSLink_DEBUG_OPENED
704  if (gDebugFlag1) {
705  std::cout << " blocked (hard conflict)\n";
706  }
707 #endif
708  return true;
709  }
710  return false;
711 }
712 
713 
714 bool
715 MSLink::hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, double speed, double decel) const {
716  for (const MSLink* const link : myFoeLinks) {
717  if (link->blockedAtTime(arrivalTime, leaveTime, speed, speed, myLane == link->getLane(), 0, decel, 0)) {
718  return true;
719  }
720  }
721  for (const MSLane* const lane : myFoeLanes) {
722  if (lane->getVehicleNumberWithPartials() > 0) {
723  return true;
724  }
725  }
726  return false;
727 }
728 
729 
730 std::pair<const SUMOVehicle*, const MSLink*>
731 MSLink::getFirstApproachingFoe(const MSLink* wrapAround) const {
732  double closetDist = std::numeric_limits<double>::max();
733  const SUMOVehicle* closest = nullptr;
734  const MSLink* foeLink = nullptr;
735  for (MSLink* link : myFoeLinks) {
736  for (const auto& it : link->myApproachingVehicles) {
737  //std::cout << " link=" << getDescription() << " foeLink_in=" << link->getLaneBefore()->getID() << " wrapAround=" << wrapAround->getDescription() << "\n";
738  if (link->getLaneBefore() == wrapAround->getLaneBefore()) {
739  return std::make_pair(nullptr, wrapAround);
740  } else if (it.second.dist < closetDist) {
741  closetDist = it.second.dist;
742  if (it.second.willPass) {
743  closest = it.first;
744  foeLink = link;
745  }
746  }
747  }
748  }
749  return std::make_pair(closest, foeLink);
750 }
751 
752 
753 void
755  if (myState != state) {
756  myLastStateChange = t;
757  }
758  myState = state;
759 }
760 
761 
762 bool
763 MSLink::isCont() const {
764  // when a traffic light is switched off minor roads have their cont status revoked
766 }
767 
768 
769 bool
771  if (myInternalLane == nullptr || myAmCont || myHavePedestrianCrossingFoe) {
772  return false;
773  } else {
775  if (!pred->getEdge().isInternal()) {
776  return false;
777  } else {
778  const MSLane* const pred2 = pred->getLogicalPredecessorLane();
779  assert(pred2 != nullptr);
780  const MSLink* const predLink = pred2->getLinkTo(pred);
781  assert(predLink != nullptr);
782  return predLink->havePriority() || predLink->haveYellow();
783  }
784  }
785 }
786 
787 
788 bool
790  if (myInternalLane == nullptr || myAmCont || myHavePedestrianCrossingFoe) {
791  return false;
792  } else {
794  if (!pred->getEdge().isInternal()) {
795  return false;
796  } else {
797  const MSLane* const pred2 = pred->getLogicalPredecessorLane();
798  assert(pred2 != nullptr);
799  const MSLink* const predLink = pred2->getLinkTo(pred);
800  assert(predLink != nullptr);
801  return predLink->getState() == LINKSTATE_TL_GREEN_MAJOR || predLink->getState() == LINKSTATE_TL_RED;
802  }
803  }
804 }
805 
806 
807 void
808 MSLink::writeApproaching(OutputDevice& od, const std::string fromLaneID) const {
809  if (myApproachingVehicles.size() > 0) {
810  od.openTag("link");
811  od.writeAttr(SUMO_ATTR_FROM, fromLaneID);
812  const std::string via = getViaLane() == nullptr ? "" : getViaLane()->getID();
813  od.writeAttr(SUMO_ATTR_VIA, via);
814  od.writeAttr(SUMO_ATTR_TO, getLane() == nullptr ? "" : getLane()->getID());
815  std::vector<std::pair<SUMOTime, const SUMOVehicle*> > toSort; // stabilize output
816  for (auto it : myApproachingVehicles) {
817  toSort.push_back(std::make_pair(it.second.arrivalTime, it.first));
818  }
819  std::sort(toSort.begin(), toSort.end());
820  for (std::vector<std::pair<SUMOTime, const SUMOVehicle*> >::const_iterator it = toSort.begin(); it != toSort.end(); ++it) {
821  od.openTag("approaching");
822  const ApproachingVehicleInformation& avi = myApproachingVehicles.find(it->second)->second;
823  od.writeAttr(SUMO_ATTR_ID, it->second->getID());
824  od.writeAttr(SUMO_ATTR_IMPATIENCE, it->second->getImpatience());
825  od.writeAttr("arrivalTime", time2string(avi.arrivalTime));
826  od.writeAttr("arrivalTimeBraking", time2string(avi.arrivalTimeBraking));
827  od.writeAttr("leaveTime", time2string(avi.leavingTime));
828  od.writeAttr("arrivalSpeed", toString(avi.arrivalSpeed));
829  od.writeAttr("arrivalSpeedBraking", toString(avi.arrivalSpeedBraking));
830  od.writeAttr("leaveSpeed", toString(avi.leaveSpeed));
831  od.writeAttr("willPass", toString(avi.willPass));
832  od.closeTag();
833  }
834  od.closeTag();
835  }
836 }
837 
838 
839 double
841  double len = 0.;
842  MSLane* lane = myInternalLane;
843 
844  while (lane != nullptr && lane->isInternal()) {
845  len += lane->getLength();
846  lane = lane->getLinkCont()[0]->getViaLane();
847  }
848  return len;
849 }
850 
851 double
853  double len = 0.;
854  const MSLane* lane = myInternalLane;
855 
856  while (lane != nullptr && lane->isInternal()) {
857  len += lane->getLength();
858  if (lane->getIncomingLanes().size() == 1) {
859  lane = lane->getIncomingLanes()[0].lane;
860  } else {
861  break;
862  }
863  }
864  return len;
865 }
866 
867 
868 double
870  MSLane* via = myInternalLane;
871  double totalDist = 0.;
872  bool foundCrossing = false;
873  while (via != nullptr) {
874  MSLink* link = via->getLinkCont()[0];
875  double dist = link->getLengthBeforeCrossing(foeLane);
876  if (dist != INVALID_DOUBLE) {
877  // found conflicting lane
878  totalDist += dist;
879  foundCrossing = true;
880  break;
881  } else {
882  totalDist += via->getLength();
883  via = link->getViaLane();
884  }
885  }
886  if (foundCrossing) {
887  return totalDist;
888  } else {
889  return INVALID_DOUBLE;
890  }
891 }
892 
893 
894 double
896  int foe_ix;
897  for (foe_ix = 0; foe_ix != (int)myFoeLanes.size(); ++foe_ix) {
898  if (myFoeLanes[foe_ix] == foeLane) {
899  break;
900  }
901  }
902  if (foe_ix == (int)myFoeLanes.size()) {
903  // no conflict with the given lane, indicate by returning -1
904 #ifdef MSLink_DEBUG_CROSSING_POINTS
905  std::cout << "No crossing of lanes '" << foeLane->getID() << "' and '" << myInternalLaneBefore->getID() << "'" << std::endl;
906 #endif
907  return INVALID_DOUBLE;
908  } else {
909  // found conflicting lane index
910  double dist = myInternalLaneBefore->getLength() - myLengthsBehindCrossing[foe_ix].first;
911  if (dist == -10000.) {
912  // this is the value in myLengthsBehindCrossing, if the relation allows intersection but none is present for the actual geometry.
913  return INVALID_DOUBLE;
914  }
915 #ifdef MSLink_DEBUG_CROSSING_POINTS
916  std::cout << "Crossing of lanes '" << myInternalLaneBefore->getID() << "' and '" << foeLane->getID()
917  << "' at distance " << dist << " (approach along '"
918  << myInternalLaneBefore->getEntryLink()->getLaneBefore()->getID() << "')" << std::endl;
919 #endif
920  return dist;
921  }
922 }
923 
924 
925 bool
928  return myInternalLane != nullptr && myInternalLaneBefore == nullptr;
929  } else {
930  return false;
931  }
932 }
933 
934 bool
936  // either a non-cont entry link or the link after a cont-link
937  return !myAmCont && (isEntryLink() || (myInternalLaneBefore != nullptr && myInternalLane != nullptr));
938 }
939 
940 bool
943  return myInternalLaneBefore != nullptr && myInternalLane == nullptr;
944  } else {
945  return false;
946  }
947 }
948 
949 bool
952  return (getInternalLaneBefore() != nullptr
953  && myInternalLaneBefore->getIncomingLanes().size() == 1
954  && myInternalLaneBefore->getIncomingLanes().front().viaLink->isInternalJunctionLink());
955  } else {
956  return false;
957  }
958 }
959 
960 
961 const MSLink*
963  MSLane* lane = myInternalLane;
964  const MSLink* link = nullptr;
965  while (lane != nullptr) {
966  link = lane->getLinkCont()[0];
967  lane = link->getViaLane();
968  }
969  return link;
970 }
971 
972 
973 const MSLink*
975  const MSLink* link = this;
976  while (link->myLaneBefore->isInternal()) {
977  assert(myLaneBefore->getIncomingLanes().size() == 1);
978  link = link->myLaneBefore->getIncomingLanes().front().viaLink;
979  }
980  return link;
981 }
982 
983 
984 bool
986  return getInternalLaneBefore() != nullptr && myInternalLane != nullptr;
987 }
988 
989 
991 MSLink::getLeaderInfo(const MSVehicle* ego, double dist, std::vector<const MSPerson*>* collectBlockers, bool isShadowLink) const {
992  LinkLeaders result;
993  // this link needs to start at an internal lane (either an exit link or between two internal lanes)
994  // or it must be queried by the pedestrian model (ego == 0)
995  if (ego != nullptr && (!fromInternalLane() || ego->getLaneChangeModel().isOpposite())) {
996  // ignore link leaders
997  return result;
998  }
999  //gDebugFlag1 = true;
1000  if (gDebugFlag1) {
1001  std::cout << SIMTIME << " getLeaderInfo link=" << getViaLaneOrLane()->getID() << " dist=" << dist << " isShadowLink=" << isShadowLink << "\n";
1002  }
1003  // this is an exit link
1004  for (int i = 0; i < (int)myFoeLanes.size(); ++i) {
1005  const MSLane* foeLane = myFoeLanes[i];
1006  const MSLink* foeExitLink = foeLane->getLinkCont()[0];
1007  // distance from the querying vehicle to the crossing point with foeLane
1008  double distToCrossing = dist - myLengthsBehindCrossing[i].first;
1009  const bool sameTarget = (myLane == foeExitLink->getLane()) && !isInternalJunctionLink();
1010  const bool sameSource = (myInternalLaneBefore != nullptr && myInternalLaneBefore->getLogicalPredecessorLane() == foeLane->getLogicalPredecessorLane());
1011  const double crossingWidth = (sameTarget || sameSource) ? 0 : foeLane->getWidth();
1012  const double foeCrossingWidth = (sameTarget || sameSource) ? 0 : myInternalLaneBefore->getWidth();
1013  // special treatment of contLane foe only applies if this lane is not a contLane or contLane follower itself
1014  const bool contLane = (foeExitLink->getViaLaneOrLane()->getEdge().isInternal() && !(
1016  if (gDebugFlag1) {
1017  std::cout << " distToCrossing=" << distToCrossing << " foeLane=" << foeLane->getID() << " cWidth=" << crossingWidth
1018  << " ijl=" << isInternalJunctionLink() << " sT=" << sameTarget << " sS=" << sameSource
1019  << " lbc=" << myLengthsBehindCrossing[i].first
1020  << " flbc=" << myLengthsBehindCrossing[i].second
1021  << " contLane=" << contLane
1022  << " state=" << toString(myState)
1023  << " foeState=" << toString(foeExitLink->getState())
1024  << "\n";
1025  }
1026  if (distToCrossing + crossingWidth < 0 && !sameTarget
1027  && (ego == nullptr || !MSGlobals::gComputeLC || distToCrossing + crossingWidth + ego->getVehicleType().getLength() < 0)) {
1028  continue; // vehicle is behind the crossing point, continue with next foe lane
1029  }
1030  bool ignoreGreenCont = false;
1031  if (contLane) {
1032  const MSLink* entry = getLaneBefore()->getEntryLink();
1033  const MSLink* foeEntry = foeLane->getEntryLink();
1034  if (entry != nullptr && entry->haveGreen()
1035  && foeEntry != nullptr && foeEntry->haveGreen()
1036  && entry->myLaneBefore != foeEntry->myLaneBefore) {
1037  // ignore vehicles before an internaljunction as long as they are still in green minor mode
1038  ignoreGreenCont = true;
1039  }
1040  }
1041  const double foeDistToCrossing = foeLane->getLength() - myLengthsBehindCrossing[i].second;
1042  // it is not sufficient to return the last vehicle on the foeLane because ego might be its leader
1043  // therefore we return all vehicles on the lane
1044  //
1045  // special care must be taken for continuation lanes. (next lane is also internal)
1046  // vehicles on these lanes should always block (gap = -1)
1047  // vehicles on cont. lanes or on internal lanes with the same target as this link can never be ignored
1048  MSLane::AnyVehicleIterator end = foeLane->anyVehiclesEnd();
1049  for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != end; ++it_veh) {
1050  MSVehicle* leader = (MSVehicle*)*it_veh;
1051  const double leaderBack = leader->getBackPositionOnLane(foeLane);
1052  const double leaderBackDist = foeDistToCrossing - leaderBack;
1053  const bool pastTheCrossingPoint = leaderBackDist + foeCrossingWidth < 0;
1054  const bool foeIsBicycleTurn = (leader->getVehicleType().getVehicleClass() == SVC_BICYCLE
1055  && foeLane->getIncomingLanes().front().viaLink->getDirection() == LinkDirection::LEFT);
1056  const bool ignoreIndirectBicycleTurn = pastTheCrossingPoint && foeIsBicycleTurn;
1057  const bool cannotIgnore = ((contLane && !ignoreIndirectBicycleTurn) || sameTarget || sameSource) && ego != nullptr;
1058  const bool inTheWay = (((!pastTheCrossingPoint && distToCrossing > 0) || (sameTarget && distToCrossing > leaderBackDist - leader->getLength()))
1059  && leaderBackDist < leader->getVehicleType().getLength()
1060  && (!foeExitLink->isInternalJunctionLink() || foeIsBicycleTurn));
1061  const bool isOpposite = leader->getLaneChangeModel().isOpposite();
1062  if (gDebugFlag1) {
1063  std::cout << " candidate leader=" << leader->getID()
1064  << " cannotIgnore=" << cannotIgnore
1065  << " fdtc=" << foeDistToCrossing
1066  << " lb=" << leaderBack
1067  << " lbd=" << leaderBackDist
1068  << " fcwidth=" << foeCrossingWidth
1069  << " foePastCP=" << pastTheCrossingPoint
1070  << " inTheWay=" << inTheWay
1071  << " willPass=" << foeExitLink->getApproaching(leader).willPass
1072  << " isFrontOnLane=" << leader->isFrontOnLane(foeLane)
1073  << " ignoreGreenCont=" << ignoreGreenCont
1074  << " isOpposite=" << isOpposite << "\n";
1075  }
1076  if (leader == ego) {
1077  continue;
1078  }
1079  // ignore greenCont foe vehicles that are not in the way
1080  if (ignoreGreenCont && !inTheWay) {
1081  continue;
1082  }
1083  // after entering the conflict area, ignore foe vehicles that are not in the way
1084  if (distToCrossing < -POSITION_EPS && !inTheWay
1085  && (ego == nullptr || !MSGlobals::gComputeLC || distToCrossing < -ego->getVehicleType().getLength())) {
1086  continue;
1087  }
1088  // ignore foe vehicles that will not pass
1089  if ((!cannotIgnore || leader->isStopped() || sameTarget)
1090  && !foeExitLink->getApproaching(leader).willPass
1091  && leader->isFrontOnLane(foeLane)
1092  && !isOpposite
1093  && !inTheWay
1094  // do not ignore vehicles that have already entered the roundabout (they might block the way to the exit)
1095  && !myLane->getEdge().isRoundabout()
1096  // willPass is false if the vehicle is already on the stopping edge
1097  && !leader->willStop()) {
1098  continue;
1099  }
1100  if (MSGlobals::gSublane && ego != nullptr && (sameSource || sameTarget)) {
1101  const double posLat = ego->getLateralPositionOnLane();
1102  const double posLatLeader = leader->getLateralPositionOnLane() + leader->getLatOffset(foeLane);
1103  const double latGap = (fabs(posLat - posLatLeader)
1104  - 0.5 * (ego->getVehicleType().getWidth() + leader->getVehicleType().getWidth()));
1105  if (gDebugFlag1) {
1106  std::cout << " sublaneFoe lane=" << myInternalLaneBefore->getID()
1107  << " sameSource=" << sameSource
1108  << " sameTarget=" << sameTarget
1109  << " foeLane=" << foeLane->getID()
1110  << " leader=" << leader->getID()
1111  << " egoLane=" << ego->getLane()->getID()
1112  << " leaderLane=" << leader->getLane()->getID()
1113  << " egoLat=" << posLat
1114  << " leaderLat=" << posLatLeader
1115  << " leaderLatOffset=" << leader->getLatOffset(foeLane)
1116  << " latGap=" << latGap
1117  << "\n";
1118  }
1119  if (latGap > 0) {
1120  const MSLink* foeEntryLink = foeLane->getIncomingLanes().front().viaLink;
1121  if (sameSource) {
1122  // for lanes from the same edge, higer index implies a
1123  // connection further to the left
1124  const bool leaderFromRight = (myIndex > foeEntryLink->getIndex());
1125  if ((posLat > posLatLeader) == leaderFromRight) {
1126  // ignore speed since lanes diverge
1127  continue;
1128  }
1129  } else {
1130  // for lanes from different edges we cannot rely on the
1131  // index due to wrap-around issues
1132  if (myDirection != foeEntryLink->getDirection()) {
1133  bool leaderFromRight = foeEntryLink->getDirection() < myDirection;
1134  // leader vehicle should not move towards ego
1135  if (MSGlobals::gLefthand) {
1136  leaderFromRight = !leaderFromRight;
1137  }
1138  if ((posLat > posLatLeader) == leaderFromRight
1139  // leader should keep lateral position or move away from ego
1140  && (leader->getLaneChangeModel().getSpeedLat() == 0
1141  || leaderFromRight == (leader->getLaneChangeModel().getSpeedLat() < latGap))
1142  && (ego->getLaneChangeModel().getSpeedLat() == 0
1143  || leaderFromRight == (ego->getLaneChangeModel().getSpeedLat() > latGap))) {
1144  continue;
1145  }
1146  } else {
1147  // XXX figure out relative direction somehow
1148  }
1149  }
1150  }
1151  }
1153  // compute distance between vehicles on the the superimposition of both lanes
1154  // where the crossing point is the common point
1155  double gap;
1156  bool fromLeft = true;
1157  if (ego == nullptr) {
1158  // request from pedestrian model. return distance between leaderBack and crossing point
1159  //std::cout << " foeLane=" << foeLane->getID() << " leaderBack=" << leaderBack << " foeDistToCrossing=" << foeDistToCrossing << " foeLength=" << foeLane->getLength() << " foebehind=" << myLengthsBehindCrossing[i].second << " dist=" << dist << " behind=" << myLengthsBehindCrossing[i].first << "\n";
1160  gap = leaderBackDist;
1161  // distToCrossing should not take into account the with of the foe lane
1162  // (which was subtracted in setRequestInformation)
1163  // Instead, the width of the foe vehicle is used directly by the caller.
1164  distToCrossing += foeLane->getWidth() / 2;
1165  if (gap + foeCrossingWidth < 0) {
1166  // leader is completely past the crossing point
1167  // or there is no crossing point
1168  continue; // next vehicle
1169  }
1170  // we need to determine whether the vehicle passes the
1171  // crossing from the left or the right (heuristic)
1172  fromLeft = foeDistToCrossing > 0.5 * foeLane->getLength();
1173  } else if ((contLane && !sameSource && !ignoreIndirectBicycleTurn) || isOpposite) {
1174  gap = -std::numeric_limits<double>::max(); // always break for vehicles which are on a continuation lane or for opposite-direction vehicles
1175  } else {
1176  if (gDebugFlag1) {
1177  std::cout << " distToCrossing=" << distToCrossing << " leader back=" << leaderBack << " backDist=" << leaderBackDist
1178  << " blockedStrategic=" << leader->getLaneChangeModel().isStrategicBlocked()
1179  //<< " stateRight=" << toString((LaneChangeAction)leader->getLaneChangeModel().getSavedState(-1).second)
1180  << "\n";
1181  }
1182  if (leaderBackDist + foeCrossingWidth < 0 && !sameTarget) {
1183  // leader is completely past the crossing point
1184  // or there is no crossing point
1185  continue; // next vehicle
1186  }
1187  gap = distToCrossing - ego->getVehicleType().getMinGap() - leaderBackDist - foeCrossingWidth;
1188  // factor 2 is to give some slack for lane-changing
1189  if (gap < leader->getVehicleType().getLength() * 2 && leader->getLaneChangeModel().isStrategicBlocked()) {
1190  // do not encroach on leader when it tries to change lanes
1191  gap = -std::numeric_limits<double>::max();
1192  }
1193  }
1194  // if the foe is already moving off the intersection, we may
1195  // advance up to the crossing point unless we have the same target or same source
1196  // (for sameSource, the crossing point indicates the point of divergence)
1197  const bool stopAsap = leader->isFrontOnLane(foeLane) ? cannotIgnore : (sameTarget || sameSource);
1198  if (gDebugFlag1) {
1199  std::cout << " leader=" << leader->getID() << " contLane=" << contLane << " cannotIgnore=" << cannotIgnore << " stopAsap=" << stopAsap << "\n";
1200  }
1201  result.emplace_back(leader, gap, stopAsap ? -1 : distToCrossing, fromLeft, inTheWay);
1202  }
1203 
1204  }
1205  if (ego != nullptr && MSNet::getInstance()->hasPersons()) {
1206  // check for crossing pedestrians (keep driving if already on top of the crossing
1207  const double distToPeds = distToCrossing - MSPModel::SAFETY_GAP;
1208  const double vehWidth = ego->getVehicleType().getWidth() + MSPModel::SAFETY_GAP; // + configurable safety gap
1210  // @check lefthand?!
1211  const bool wayIn = myLengthsBehindCrossing[i].first < myLaneBefore->getLength() * 0.5;
1212  const double vehSideOffset = (foeDistToCrossing + myLaneBefore->getWidth() * 0.5 - vehWidth * 0.5
1213  + ego->getLateralPositionOnLane() * (wayIn ? -1 : 1));
1214  // can access the movement model here since we already checked for existing persons above
1215  if (distToPeds >= -MSPModel::SAFETY_GAP && MSNet::getInstance()->getPersonControl().getMovementModel()->blockedAtDist(foeLane, vehSideOffset, vehWidth,
1217  collectBlockers)) {
1218  result.emplace_back(nullptr, -1, distToPeds);
1219  }
1220  }
1221  }
1222 
1223  //std::cout << SIMTIME << " ego=" << Named::getIDSecure(ego) << " link=" << getViaLaneOrLane()->getID() << " myWalkingAreaFoe=" << Named::getIDSecure(myWalkingAreaFoe) << "\n";
1224  if (ego != nullptr) {
1225  checkWalkingAreaFoe(ego, myWalkingAreaFoe, collectBlockers, result);
1226  checkWalkingAreaFoe(ego, myWalkingAreaFoeExit, collectBlockers, result);
1227  }
1228 
1229  if (MSGlobals::gLateralResolution > 0 && ego != nullptr && !isShadowLink) {
1230  // check for foes on the same lane
1231  for (std::vector<MSLane*>::const_iterator it = mySublaneFoeLanes.begin(); it != mySublaneFoeLanes.end(); ++it) {
1232  const MSLane* foeLane = *it;
1233  MSLane::AnyVehicleIterator end = foeLane->anyVehiclesEnd();
1234  for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != end; ++it_veh) {
1235  MSVehicle* leader = (MSVehicle*)*it_veh;
1236  if (leader == ego) {
1237  continue;
1238  }
1239  const double maxLength = MAX2(myInternalLaneBefore->getLength(), foeLane->getLength());
1240  const double gap = dist - maxLength - ego->getVehicleType().getMinGap() + leader->getBackPositionOnLane(foeLane);
1241  if (gap < -(ego->getVehicleType().getMinGap() + leader->getLength())) {
1242  // ego is ahead of leader
1243  continue;
1244  }
1245 
1246  const double posLat = ego->getLateralPositionOnLane();
1247  const double posLatLeader = leader->getLateralPositionOnLane() + leader->getLatOffset(foeLane);
1248  if (gDebugFlag1) {
1249  std::cout << " sublaneFoe lane=" << myInternalLaneBefore->getID()
1250  << " foeLane=" << foeLane->getID()
1251  << " leader=" << leader->getID()
1252  << " egoLane=" << ego->getLane()->getID()
1253  << " leaderLane=" << leader->getLane()->getID()
1254  << " egoLat=" << posLat
1255  << " leaderLat=" << posLatLeader
1256  << " leaderLatOffset=" << leader->getLatOffset(foeLane)
1257  << " egoIndex=" << myInternalLaneBefore->getIndex()
1258  << " foeIndex=" << foeLane->getIndex()
1259  << " dist=" << dist
1260  << " leaderBack=" << leader->getBackPositionOnLane(foeLane)
1261  << "\n";
1262  }
1263  // there only is a conflict if the paths cross
1264  if ((posLat < posLatLeader && myInternalLaneBefore->getIndex() > foeLane->getIndex())
1265  || (posLat > posLatLeader && myInternalLaneBefore->getIndex() < foeLane->getIndex())) {
1266  if (gDebugFlag1) {
1267  std::cout << SIMTIME << " blocked by " << leader->getID() << " (sublane split) foeLane=" << foeLane->getID() << "\n";
1268  }
1269  result.emplace_back(leader, gap, -1);
1270  }
1271  }
1272  }
1273  }
1274  return result;
1275 }
1276 
1277 
1278 void
1279 MSLink::checkWalkingAreaFoe(const MSVehicle* ego, const MSLane* foeLane, std::vector<const MSPerson*>* collectBlockers, LinkLeaders& result) const {
1280  if (foeLane != nullptr && foeLane->getEdge().getPersons().size() > 0) {
1281  // pedestrians may be on an arbitrary path across this
1282  // walkingarea. make sure to keep enough distance.
1283  // This is a simple but conservative solution that could be improved
1284  // by ignoring pedestrians that are "obviously" not on a collision course
1285  double distToPeds = std::numeric_limits<double>::max();
1286  for (MSTransportable* t : foeLane->getEdge().getPersons()) {
1287  MSPerson* p = static_cast<MSPerson*>(t);
1288  const double dist = ego->getPosition().distanceTo2D(p->getPosition()) - p->getVehicleType().getLength();
1289  if (p->getSpeed() > 0 || dist < MSPModel::SAFETY_GAP / 2) {
1290  distToPeds = MIN2(distToPeds, dist - MSPModel::SAFETY_GAP);
1291  if (collectBlockers != nullptr) {
1292  collectBlockers->push_back(p);
1293  }
1294  }
1295  }
1296  if (distToPeds != std::numeric_limits<double>::max()) {
1297  result.emplace_back(nullptr, -1, distToPeds);
1298  }
1299  }
1300 }
1301 
1302 
1303 MSLink*
1304 MSLink::getParallelLink(int direction) const {
1305  if (direction == -1) {
1306  return myParallelRight;
1307  } else if (direction == 1) {
1308  return myParallelLeft;
1309  } else {
1310  assert(false);
1311  return nullptr;
1312  }
1313 }
1314 
1315 
1316 MSLink*
1318  const MSLane* const before = getLaneBefore()->getParallelLane(direction);
1319  const MSLane* const after = getLane()->getParallelLane(direction);
1320  if (before != nullptr && after != nullptr) {
1321  for (MSLink* const link : before->getLinkCont()) {
1322  if (link->getLane() == after) {
1323  return link;
1324  }
1325  }
1326  }
1327  return nullptr;
1328 }
1329 
1330 
1331 double
1332 MSLink::getZipperSpeed(const MSVehicle* ego, const double dist, double vSafe,
1333  SUMOTime arrivalTime,
1334  BlockingFoes* collectFoes) const {
1335  if (myFoeLinks.size() == 0) {
1336  // link should have LINKSTATE_MAJOR in this case
1337  assert(false);
1338  return vSafe;
1339  } else if (myFoeLinks.size() > 1) {
1340  throw ProcessError("Zipper junctions with more than two conflicting lanes are not supported (at junction '"
1341  + myJunction->getID() + "')");
1342  }
1344  const double secondsToArrival = STEPS2TIME(arrivalTime - now);
1345  if (secondsToArrival > ZIPPER_ADAPT_TIME && dist > ZIPPER_ADAPT_DIST) {
1346 #ifdef DEBUG_ZIPPER
1347  if (DEBUG_COND_ZIPPER) DEBUGOUT(SIMTIME << " getZipperSpeed ego=" << ego->getID()
1348  << " dist=" << dist << " ignoring foes (arrival in " << STEPS2TIME(arrivalTime - now) << ")\n")
1349 #endif
1350  return vSafe;
1351  }
1352 #ifdef DEBUG_ZIPPER
1353  if (DEBUG_COND_ZIPPER) DEBUGOUT(SIMTIME << " getZipperSpeed ego=" << ego->getID()
1354  << " egoAT=" << arrivalTime
1355  << " dist=" << dist
1356  << " vSafe=" << vSafe
1357  << " numFoes=" << collectFoes->size()
1358  << "\n")
1359 #endif
1360  MSLink* foeLink = myFoeLinks[0];
1361  for (const auto& item : *collectFoes) {
1362  const MSVehicle* foe = dynamic_cast<const MSVehicle*>(item);
1363  assert(foe != 0);
1364  const ApproachingVehicleInformation& avi = foeLink->getApproaching(foe);
1365  const double foeDist = (foe->isActive() ? avi.dist : MAX2(0.0, avi.dist -
1366  STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - foe->getLastActionTime()) * avi.speed));
1367 
1368  if ( // ignore vehicles that arrive after us (unless they are ahead and we could easily brake for them)
1369  ((avi.arrivalTime > arrivalTime) && !couldBrakeForLeader(dist, foeDist, ego, foe)) ||
1370  // also ignore vehicles that are behind us and are able to brake for us
1371  couldBrakeForLeader(foeDist, dist, foe, ego) ||
1372  // resolve ties by lane index
1373  (avi.arrivalTime == arrivalTime && foeDist == dist && ego->getLane()->getIndex() < foe->getLane()->getIndex())) {
1374 #ifdef DEBUG_ZIPPER
1375  if (DEBUG_COND_ZIPPER) std::cout
1376  << " ignoring foe=" << foe->getID()
1377  << " foeAT=" << avi.arrivalTime
1378  << " foeDist=" << avi.dist
1379  << " foeDist2=" << foeDist
1380  << " foeSpeed=" << avi.speed
1381  << " egoSpeed=" << ego->getSpeed()
1382  << " deltaDist=" << foeDist - dist
1383  << " delteSpeed=" << avi.speed - foe->getCarFollowModel().getMaxDecel() - ego->getSpeed()
1384  << " egoCouldBrake=" << couldBrakeForLeader(dist, foeDist, ego, foe)
1385  << " foeCouldBrake=" << couldBrakeForLeader(foeDist, dist, foe, ego)
1386  << "\n";
1387 #endif
1388  continue;
1389  }
1390  // the idea behind speed adaption is three-fold:
1391  // 1) ego needs to be in a car-following relationship with foe eventually
1392  // thus, the ego speed should be equal to the follow speed once the foe enters
1393  // the zipper junction
1394  // 2) ego vehicle needs to put a certain distance beteen himself and foe (safeGap)
1395  // achieving this distance can be spread over time but computing
1396  // safeGap is subject to estimation errors of future speeds
1397  // 3) deceleration can be spread out over the time until true
1398  // car-following happens, at the start of speed adaptions, smaller
1399  // decelerations should be sufficient
1400 
1401  // we cannot trust avi.arrivalSpeed if the foe has leader vehicles that are accelerating
1402  // lets try to extrapolate
1403  const double uMax = foe->getLane()->getVehicleMaxSpeed(foe);
1404  const double uAccel = foe->getCarFollowModel().estimateSpeedAfterDistance(foeDist, avi.speed, foe->getCarFollowModel().getMaxAccel());
1405  const double uEnd = MIN2(uMax, uAccel);
1406  const double uAvg = (avi.speed + uEnd) / 2;
1407  const double tf0 = foeDist / MAX2(NUMERICAL_EPS, uAvg);
1408  const double tf = MAX2(1.0, ceil((tf0) / TS) * TS);
1409 
1410  const double vMax = ego->getLane()->getVehicleMaxSpeed(ego);
1411  const double vAccel = ego->getCarFollowModel().estimateSpeedAfterDistance(dist, ego->getSpeed(), ego->getCarFollowModel().getMaxAccel());
1412  const double vEnd = MIN3(vMax, vAccel, uEnd);
1413  const double vAvg = (ego->getSpeed() + vEnd) / 2;
1414  const double te0 = dist / MAX2(NUMERICAL_EPS, vAvg);
1415  const double te = MAX2(1.0, ceil((te0) / TS) * TS);
1416 
1417  const double gap = dist - foe->getVehicleType().getLength() - ego->getVehicleType().getMinGap() - foeDist;
1418  const double safeGap = ego->getCarFollowModel().getSecureGap(ego, foe, vEnd, uEnd, foe->getCarFollowModel().getMaxDecel());
1419  // round t to next step size
1420  // increase gap to safeGap by the time foe reaches link
1421  // gap + u*t - (t * v + a * t^2 / 2) = safeGap
1422  const double deltaGap = gap + tf * uAvg - safeGap - vAvg * tf;
1423  const double a = 2 * deltaGap / (tf * tf);
1424  const double vSafeGap = ego->getSpeed() + ACCEL2SPEED(a);
1425  const double vFollow = ego->getCarFollowModel().followSpeed(
1426  ego, ego->getSpeed(), gap, avi.speed, foe->getCarFollowModel().getMaxDecel(), foe);
1427 
1428  // scale behavior based on ego time to link (te)
1429  const double w = MIN2(1.0, te / 10);
1430  const double maxDecel = w * ego->getCarFollowModel().getMaxDecel() + (1 - w) * ego->getCarFollowModel().getEmergencyDecel();
1431  const double vZipper = MAX3(vFollow, ego->getSpeed() - ACCEL2SPEED(maxDecel), w * vSafeGap + (1 - w) * vFollow);
1432 
1433  vSafe = MIN2(vSafe, vZipper);
1434 #ifdef DEBUG_ZIPPER
1435  if (DEBUG_COND_ZIPPER) std::cout << " adapting to foe=" << foe->getID()
1436  << " foeDist=" << foeDist
1437  << " foeSpeed=" << avi.speed
1438  << " foeAS=" << avi.arrivalSpeed
1439  << " egoSpeed=" << ego->getSpeed()
1440  << " uMax=" << uMax
1441  << " uAccel=" << uAccel
1442  << " uEnd=" << uEnd
1443  << " uAvg=" << uAvg
1444  << " gap=" << gap
1445  << " safeGap=" << safeGap
1446  << "\n "
1447  << " tf=" << tf
1448  << " te=" << te
1449  << " dg=" << deltaGap
1450  << " aSafeGap=" << a
1451  << " vMax=" << vMax
1452  << " vAccel=" << vAccel
1453  << " vEnd=" << vEnd
1454  << " vSafeGap=" << vSafeGap
1455  << " vFollow=" << vFollow
1456  << " w=" << w
1457  << " maxDecel=" << maxDecel
1458  << " vZipper=" << vZipper
1459  << " vSafe=" << vSafe
1460  << "\n";
1461 #endif
1462  }
1463  return vSafe;
1464 }
1465 
1466 
1467 bool
1468 MSLink::couldBrakeForLeader(double followDist, double leaderDist, const MSVehicle* follow, const MSVehicle* leader) {
1469  return (// leader is ahead of follower
1470  followDist > leaderDist &&
1471  // and follower could brake for 1 s to stay behind leader
1472  followDist - leaderDist > follow->getSpeed() - follow->getCarFollowModel().getMaxDecel() - leader->getSpeed());
1473 }
1474 
1475 
1476 void
1480 }
1481 
1482 bool
1484  // check whether this link gets to keep its cont status switching the tls off
1485  // @note: this could also be pre-computed in netconvert
1486  // we check whether there is any major link from this edge
1487  for (const MSLane* cand : myLaneBefore->getEdge().getLanes()) {
1488  for (const MSLink* link : cand->getLinkCont()) {
1489  if (link->getOffState() == LINKSTATE_TL_OFF_NOSIGNAL) {
1490  return true;
1491  }
1492  }
1493  }
1494  return false;
1495 }
1496 
1497 std::string
1499  return myLaneBefore->getID() + "->" + getViaLaneOrLane()->getID();
1500 }
1501 
1502 
1503 /****************************************************************************/
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:49
#define SUMOTime_MIN
Definition: SUMOTime.h:33
#define TS
Definition: SUMOTime.h:40
#define SIMTIME
Definition: SUMOTime.h:60
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
@ SVC_BICYCLE
vehicle is a bicycle
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ PARTRIGHT
The link is a partial right direction.
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
@ LINKSTATE_STOP
This is an uncontrolled, minor link, has to stop.
@ LINKSTATE_TL_GREEN_MAJOR
The link has green light, may pass.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
@ LINKSTATE_TL_OFF_BLINKING
The link is controlled by a tls which is off and blinks, has to brake.
@ LINKSTATE_TL_RED
The link has red light (must brake)
@ LINKSTATE_TL_OFF_NOSIGNAL
The link is controlled by a tls which is off, not blinking, may pass.
@ SUMO_ATTR_JM_IGNORE_FOE_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_JM_IGNORE_FOE_PROB
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_JM_CROSSING_GAP
@ SUMO_ATTR_IMPATIENCE
@ SUMO_ATTR_ID
@ SUMO_ATTR_JM_TIMEGAP_MINOR
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:31
const double INVALID_DOUBLE
Definition: StdDefs.h:62
T MIN3(T a, T b, T c)
Definition: StdDefs.h:86
#define DEBUGOUT(msg)
Definition: StdDefs.h:135
T MIN2(T a, T b)
Definition: StdDefs.h:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
T MAX3(T a, T b, T c)
Definition: StdDefs.h:93
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
double getLength() const
Returns the vehicle's length.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
double estimateSpeedAfterDistance(const double dist, const double v, const double accel) const
Definition: MSCFModel.cpp:701
virtual double getSecureGap(const MSVehicle *const, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.h:328
double getEmergencyDecel() const
Get the vehicle type's maximal phisically possible deceleration [m/s^2].
Definition: MSCFModel.h:224
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const =0
Computes the vehicle's follow speed (no dawdling)
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition: MSCFModel.h:208
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:216
A road/street connecting two junctions.
Definition: MSEdge.h:77
const std::set< MSTransportable * > & getPersons() const
Returns this edge's persons set.
Definition: MSEdge.h:192
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:166
const MSJunction * getFromJunction() const
Definition: MSEdge.h:388
bool isRoundabout() const
Definition: MSEdge.h:674
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:256
static bool gUseMesoSim
Definition: MSGlobals.h:88
static double gLateralResolution
Definition: MSGlobals.h:82
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Definition: MSGlobals.h:112
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition: MSGlobals.h:136
static SUMOTime gIgnoreJunctionBlocker
Definition: MSGlobals.h:70
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition: MSGlobals.h:130
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:66
The base class for an intersection.
Definition: MSJunction.h:58
AnyVehicleIterator is a structure, which manages the iteration through all vehicles on the lane,...
Definition: MSLane.h:102
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:640
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2211
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction
Definition: MSLane.h:438
const MSLink * getEntryLink() const
Returns the entry link if this is an internal lane, else nullptr.
Definition: MSLane.cpp:2151
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2128
double getLength() const
Returns the lane's length.
Definition: MSLane.h:539
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:517
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:562
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:825
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:2542
bool isInternal() const
Definition: MSLane.cpp:2036
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:673
const PositionVector & getShape() const
Returns this lane's shape.
Definition: MSLane.h:476
double interpolateGeometryPosToLanePos(double geometryPos) const
Definition: MSLane.h:509
AnyVehicleIterator anyVehiclesBegin() const
begin iterator for iterating over all vehicles touching this lane in downstream direction
Definition: MSLane.h:432
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:555
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:171
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:313
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:388
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:986
virtual bool blockedAtDist(const MSLane *lane, double vehSide, double vehWidth, double oncomingGap, std::vector< const MSPerson * > *collectBlockers)
whether a pedestrian is blocking the crossing of lane for the given vehicle bondaries
Definition: MSPModel.h:78
static const double SAFETY_GAP
Definition: MSPModel.h:110
The parent class for traffic light logics.
MSPModel * getMovementModel()
Returns the default movement model for this kind of transportables.
virtual double getSpeed() const
the current speed of the transportable
const MSVehicleType & getVehicleType() const
Returns the object's "vehicle" type.
Position getPosition(const double) const
Return current position (x/y, cartesian)
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
bool willStop() const
Returns whether the vehicle will stop on the current edge.
Definition: MSVehicle.cpp:1437
SUMOTime getLastActionTime() const
Returns the time of the vehicle's last action point.
Definition: MSVehicle.h:510
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:637
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
Definition: MSVehicle.h:603
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:4135
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4699
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1122
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition: MSVehicle.cpp:4046
double getLatOffset(const MSLane *lane) const
Get the offset that that must be added to interpret myState.myPosLat for the given lane.
Definition: MSVehicle.cpp:5523
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:411
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:458
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:550
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:930
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getLength() const
Get vehicle's length [m].
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
const SUMOVTypeParameter & getParameter() const
const std::string & getID() const
Returns the id.
Definition: Named.h:73
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:239
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:241
A list of positions.
double length2D() const
Returns the length.
std::vector< double > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
PositionVector reverse() const
reverse position vector
static double rand(std::mt19937 *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:51
Representation of a vehicle, person, or container.
virtual std::mt19937 * getRNG() const =0
Returns the associated RNG for this object.
virtual double getSpeed() const =0
Returns the object's current speed.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
double getJMParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
Representation of a vehicle.
Definition: SUMOVehicle.h:58
virtual double getLateralPositionOnLane() const =0
Get the vehicle's lateral position on the lane.