SUMO - Simulation of Urban MObility
MSLane.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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
23 // Representation of a lane in the micro simulation
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #include <config.h>
31 
32 #include <cmath>
33 #include <bitset>
34 #include <iostream>
35 #include <cassert>
36 #include <functional>
37 #include <algorithm>
38 #include <iterator>
39 #include <exception>
40 #include <climits>
41 #include <set>
43 #include <utils/common/StdDefs.h>
45 #include <utils/common/ToString.h>
48 #include <utils/geom/GeomHelper.h>
51 #include "MSNet.h"
52 #include "MSVehicleType.h"
53 #include "MSEdge.h"
54 #include "MSEdgeControl.h"
55 #include "MSJunction.h"
56 #include "MSLogicJunction.h"
57 #include "MSLink.h"
58 #include "MSLane.h"
59 #include "MSVehicleTransfer.h"
60 #include "MSGlobals.h"
61 #include "MSVehicleControl.h"
62 #include "MSInsertionControl.h"
63 #include "MSVehicleControl.h"
64 #include "MSLeaderInfo.h"
65 #include "MSVehicle.h"
66 
67 //#define DEBUG_INSERTION
68 //#define DEBUG_PLAN_MOVE
69 //#define DEBUG_EXEC_MOVE
70 //#define DEBUG_CONTEXT
71 //#define DEBUG_OPPOSITE
72 //#define DEBUG_VEHICLE_CONTAINER
73 //#define DEBUG_COLLISIONS
74 //#define DEBUG_JUNCTION_COLLISIONS
75 //#define DEBUG_PEDESTRIAN_COLLISIONS
76 //#define DEBUG_LANE_SORTER
77 //#define DEBUG_NO_CONNECTION
78 //#define DEBUG_SURROUNDING
79 
80 //#define DEBUG_COND (false)
81 //#define DEBUG_COND (getID() == "undefined")
82 //#define DEBUG_COND2(obj) ((obj != 0 && (obj)->getID() == "disabled"))
83 #define DEBUG_COND2(obj) ((obj != 0 && (obj)->isSelected()))
84 //#define DEBUG_COND (getID() == "ego")
85 //#define DEBUG_COND2(obj) ((obj != 0 && (obj)->getID() == "ego"))
86 
87 // ===========================================================================
88 // static member definitions
89 // ===========================================================================
95 
96 // ===========================================================================
97 // internal class method definitions
98 // ===========================================================================
99 
100 
103  if (nextIsMyVehicles()) {
104  if (myI1 != myI1End) {
105  myI1 += myDirection;
106  } else if (myI3 != myI3End) {
107  myI3 += myDirection;
108  }
109  // else: already at end
110  } else {
111  myI2 += myDirection;
112  }
113  //if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::operator++ lane=" << myLane->getID() << " myI1=" << myI1 << " myI2=" << myI2 << "\n";
114  return *this;
115 }
116 
117 
118 const MSVehicle*
120  if (nextIsMyVehicles()) {
121  if (myI1 != myI1End) {
122  return myLane->myVehicles[myI1];
123  } else if (myI3 != myI3End) {
124  return myLane->myTmpVehicles[myI3];
125  } else {
126  return nullptr;
127  }
128  } else {
129  return myLane->myPartialVehicles[myI2];
130  }
131 }
132 
133 
134 bool
136  //if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::nextIsMyVehicles lane=" << myLane->getID()
137  // << " myI1=" << myI1
138  // << " myI2=" << myI2
139  // << "\n";
140  if (myI1 == myI1End && myI3 == myI3End) {
141  if (myI2 != myI2End) {
142  return false;
143  } else {
144  return true; // @note. must be caught
145  }
146  } else {
147  if (myI2 == myI2End) {
148  return true;
149  } else {
151  //if (DEBUG_COND2(myLane)) std::cout << " "
152  // << " veh1=" << candFull->getID()
153  // << " isTmp=" << (myI1 == myI1End)
154  // << " veh2=" << myLane->myPartialVehicles[myI2]->getID()
155  // << " pos1=" << cand->getPositionOnLane(myLane)
156  // << " pos2=" << myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)
157  // << "\n";
158  if (cand->getPositionOnLane() < myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)) {
159  return myDownstream;
160  } else {
161  return !myDownstream;
162  }
163  }
164  }
165 }
166 
167 
168 // ===========================================================================
169 // member method definitions
170 // ===========================================================================
171 MSLane::MSLane(const std::string& id, double maxSpeed, double length, MSEdge* const edge,
172  int numericalID, const PositionVector& shape, double width,
173  SVCPermissions permissions, int index, bool isRampAccel) :
174  Named(id),
175  myNumericalID(numericalID), myShape(shape), myIndex(index),
176  myVehicles(), myLength(length), myWidth(width), myStopOffsets(),
177  myEdge(edge), myMaxSpeed(maxSpeed),
178  myPermissions(permissions),
179  myOriginalPermissions(permissions),
180  myLogicalPredecessorLane(nullptr),
182  myCanonicalSuccessorLane(nullptr),
184  myLeaderInfo(this, nullptr, 0),
185  myFollowerInfo(this, nullptr, 0),
186  myLeaderInfoTmp(this, nullptr, 0),
189  myLengthGeometryFactor(MAX2(POSITION_EPS, myShape.length()) / myLength), // factor should not be 0
190  myIsRampAccel(isRampAccel),
191  myRightSideOnEdge(0), // initialized in MSEdge::initialize
193  myNeedsCollisionCheck(false)
194 {
195  // initialized in MSEdge::initialize
196  initRestrictions();// may be reloaded again from initialized in MSEdge::closeBuilding
197 }
198 
199 
201  for (MSLinkCont::iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
202  delete *i;
203  }
204 }
205 
206 
207 void
209  // simplify unit testing without MSNet instance
211 
212 }
213 
214 
215 void
217  myLinks.push_back(link);
218 }
219 
220 
221 void
222 MSLane::addNeigh(const std::string& id) {
223  myNeighs.push_back(id);
224  // warn about lengths after loading the second lane of the pair
225  if (getOpposite() != nullptr && getLength() != getOpposite()->getLength()) {
226  WRITE_WARNING("Unequal lengths of neigh lane '" + getID() + "' and lane '" + id + "' (" + toString(getLength())
227  + ", " + toString(getOpposite()->getLength()) + ")");
228  }
229 }
230 
231 
232 // ------ interaction with MSMoveReminder ------
233 void
235  myMoveReminders.push_back(rem);
236  for (VehCont::iterator veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
237  (*veh)->addReminder(rem);
238  }
239  // XXX: Here, the partial occupators are ignored!? Refs. #3255
240 }
241 
242 
243 double
245  myNeedsCollisionCheck = true; // always check
246 #ifdef DEBUG_CONTEXT
247  if (DEBUG_COND2(v)) {
248  std::cout << SIMTIME << " setPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
249  }
250 #endif
251  // XXX update occupancy here?
252  myPartialVehicles.push_back(v);
253  return myLength;
254 }
255 
256 
257 void
259 #ifdef DEBUG_CONTEXT
260  if (DEBUG_COND2(v)) {
261  std::cout << SIMTIME << " resetPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
262  }
263 #endif
264  for (VehCont::iterator i = myPartialVehicles.begin(); i != myPartialVehicles.end(); ++i) {
265  if (v == *i) {
266  myPartialVehicles.erase(i);
267  // XXX update occupancy here?
268  //std::cout << " removed from myPartialVehicles\n";
269  return;
270  }
271  }
272  assert(false);
273 }
274 
275 
276 void
278 #ifdef DEBUG_CONTEXT
279  if (DEBUG_COND2(v)) {
280  std::cout << SIMTIME << " setManeuverReservation. lane=" << getID() << " veh=" << v->getID() << "\n";
281  }
282 #endif
283  myManeuverReservations.push_back(v);
284 }
285 
286 
287 void
289 #ifdef DEBUG_CONTEXT
290  if (DEBUG_COND2(v)) {
291  std::cout << SIMTIME << " resetManeuverReservation(): lane=" << getID() << " veh=" << v->getID() << "\n";
292  }
293 #endif
294  for (VehCont::iterator i = myManeuverReservations.begin(); i != myManeuverReservations.end(); ++i) {
295  if (v == *i) {
296  myManeuverReservations.erase(i);
297  return;
298  }
299  }
300  assert(false);
301 }
302 
303 
304 // ------ Vehicle emission ------
305 void
306 MSLane::incorporateVehicle(MSVehicle* veh, double pos, double speed, double posLat, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
307  myNeedsCollisionCheck = true;
308  assert(pos <= myLength);
309  bool wasInactive = myVehicles.size() == 0;
310  veh->enterLaneAtInsertion(this, pos, speed, posLat, notification);
311  if (at == myVehicles.end()) {
312  // vehicle will be the first on the lane
313  myVehicles.push_back(veh);
314  } else {
315  myVehicles.insert(at, veh);
316  }
319  myEdge->markDelayed();
320  if (wasInactive) {
322  }
323 }
324 
325 
326 bool
327 MSLane::lastInsertion(MSVehicle& veh, double mspeed, double posLat, bool patchSpeed) {
328  double pos = getLength() - POSITION_EPS;
329  MSVehicle* leader = getLastAnyVehicle();
330  // back position of leader relative to this lane
331  double leaderBack;
332  if (leader == nullptr) {
334  veh.setTentativeLaneAndPosition(this, pos, posLat);
335  veh.updateBestLanes(false, this);
336  std::pair<MSVehicle* const, double> leaderInfo = getLeader(&veh, pos, veh.getBestLanesContinuation(), veh.getCarFollowModel().brakeGap(mspeed));
337  leader = leaderInfo.first;
338  leaderBack = pos + leaderInfo.second + veh.getVehicleType().getMinGap();
339  } else {
340  leaderBack = leader->getBackPositionOnLane(this);
341  //std::cout << " leaderPos=" << leader->getPositionOnLane(this) << " leaderBack=" << leader->getBackPositionOnLane(this) << " leaderLane=" << leader->getLane()->getID() << "\n";
342  }
343  if (leader == nullptr) {
344  // insert at the end of this lane
345  return isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
346  } else {
347  // try to insert behind the leader
348  const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(mspeed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap() + POSITION_EPS;
349  if (leaderBack >= frontGapNeeded) {
350  pos = MIN2(pos, leaderBack - frontGapNeeded);
351  bool result = isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
352  //if (!result) std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
353  return result;
354  }
355  //std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
356  }
357  return false;
358 }
359 
360 
361 bool
362 MSLane::freeInsertion(MSVehicle& veh, double mspeed, double posLat,
363  MSMoveReminder::Notification notification) {
364  bool adaptableSpeed = true;
365  // try to insert teleporting vehicles fully on this lane
366  const double minPos = (notification == MSMoveReminder::NOTIFICATION_TELEPORT ?
367  MIN2(myLength, veh.getVehicleType().getLength()) : 0);
368  veh.setTentativeLaneAndPosition(this, minPos, 0);
369  if (myVehicles.size() == 0) {
370  // ensure sufficient gap to followers on predecessor lanes
371  const double backOffset = minPos - veh.getVehicleType().getLength();
372  const double missingRearGap = getMissingRearGap(&veh, backOffset, mspeed);
373  if (missingRearGap > 0) {
374  if (minPos + missingRearGap <= myLength) {
375  // @note. The rear gap is tailored to mspeed. If it changes due
376  // to a leader vehicle (on subsequent lanes) insertion will
377  // still fail. Under the right combination of acceleration and
378  // deceleration values there might be another insertion
379  // positions that would be successful be we do not look for it.
380  //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " unclear @(340)\n";
381  return isInsertionSuccess(&veh, mspeed, minPos + missingRearGap, posLat, adaptableSpeed, notification);
382  } else {
383  return false;
384  }
385  } else {
386  return isInsertionSuccess(&veh, mspeed, minPos, posLat, adaptableSpeed, notification);
387  }
388 
389  } else {
390  // check whether the vehicle can be put behind the last one if there is such
391  MSVehicle* leader = getFirstFullVehicle(); // @todo reproduction of bogus old behavior. see #1961
392  const double leaderPos = leader->getBackPositionOnLane(this);
393  const double speed = adaptableSpeed ? leader->getSpeed() : mspeed;
394  const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
395  if (leaderPos >= frontGapNeeded) {
396  const double tspeed = MIN2(veh.getCarFollowModel().insertionFollowSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()), mspeed);
397  // check whether we can insert our vehicle behind the last vehicle on the lane
398  if (isInsertionSuccess(&veh, tspeed, minPos, posLat, adaptableSpeed, notification)) {
399  //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " pos=" << minPos<< " speed=" << speed << " tspeed=" << tspeed << " frontGapNeeded=" << frontGapNeeded << " lead=" << leader->getID() << " lPos=" << leaderPos << "\n vehsOnLane=" << toString(myVehicles) << " @(358)\n";
400  return true;
401  }
402  }
403  }
404  // go through the lane, look for free positions (starting after the last vehicle)
405  MSLane::VehCont::iterator predIt = myVehicles.begin();
406  while (predIt != myVehicles.end()) {
407  // get leader (may be zero) and follower
408  // @todo compute secure position in regard to sublane-model
409  const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : nullptr;
410  if (leader == nullptr && myPartialVehicles.size() > 0) {
411  leader = myPartialVehicles.front();
412  }
413  const MSVehicle* follower = *predIt;
414 
415  // patch speed if allowed
416  double speed = mspeed;
417  if (adaptableSpeed && leader != nullptr) {
418  speed = MIN2(leader->getSpeed(), mspeed);
419  }
420 
421  // compute the space needed to not collide with leader
422  double frontMax = getLength();
423  if (leader != nullptr) {
424  double leaderRearPos = leader->getBackPositionOnLane(this);
425  double frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
426  frontMax = leaderRearPos - frontGapNeeded;
427  }
428  // compute the space needed to not let the follower collide
429  const double followPos = follower->getPositionOnLane() + follower->getVehicleType().getMinGap();
430  const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
431  const double backMin = followPos + backGapNeeded + veh.getVehicleType().getLength();
432 
433  // check whether there is enough room (given some extra space for rounding errors)
434  if (frontMax > minPos && backMin + POSITION_EPS < frontMax) {
435  // try to insert vehicle (should be always ok)
436  if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, posLat, adaptableSpeed, notification)) {
437  //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " @(393)\n";
438  return true;
439  }
440  }
441  ++predIt;
442  }
443  // first check at lane's begin
444  //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " fail final\n";
445  return false;
446 }
447 
448 
449 double
450 MSLane::getDepartSpeed(const MSVehicle& veh, bool& patchSpeed) {
451  double speed = 0;
452  const SUMOVehicleParameter& pars = veh.getParameter();
453  switch (pars.departSpeedProcedure) {
454  case DEPART_SPEED_GIVEN:
455  speed = pars.departSpeed;
456  patchSpeed = false;
457  break;
458  case DEPART_SPEED_RANDOM:
459  speed = RandHelper::rand(getVehicleMaxSpeed(&veh));
460  patchSpeed = true; // @todo check
461  break;
462  case DEPART_SPEED_MAX:
463  speed = getVehicleMaxSpeed(&veh);
464  patchSpeed = true; // @todo check
465  break;
467  default:
468  // speed = 0 was set before
469  patchSpeed = false; // @todo check
470  break;
471  }
472  return speed;
473 }
474 
475 
476 double
478  const SUMOVehicleParameter& pars = veh.getParameter();
479  switch (pars.departPosLatProcedure) {
480  case DEPART_POSLAT_GIVEN:
481  return pars.departPosLat;
482  case DEPART_POSLAT_RIGHT:
483  return -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
484  case DEPART_POSLAT_LEFT:
485  return getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
487  return RandHelper::rand(getWidth() - veh.getVehicleType().getWidth()) - getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
490  // @note:
491  // case DEPART_POSLAT_FREE
492  // case DEPART_POSLAT_RANDOM_FREE
493  // are not handled here because they involve multiple insertion attempts
494  default:
495  return 0;
496  }
497 }
498 
499 
500 bool
502  double pos = 0;
503  bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
504  const SUMOVehicleParameter& pars = veh.getParameter();
505  double speed = getDepartSpeed(veh, patchSpeed);
506  double posLat = getDepartPosLat(veh);
507 
508  // determine the position
509  switch (pars.departPosProcedure) {
510  case DEPART_POS_GIVEN:
511  pos = pars.departPos;
512  if (pos < 0.) {
513  pos += myLength;
514  }
515  break;
516  case DEPART_POS_RANDOM:
517  pos = RandHelper::rand(getLength());
518  break;
519  case DEPART_POS_RANDOM_FREE: {
520  for (int i = 0; i < 10; i++) {
521  // we will try some random positions ...
522  pos = RandHelper::rand(getLength());
523  posLat = getDepartPosLat(veh); // could be random as well
524  if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
525  return true;
526  }
527  }
528  // ... and if that doesn't work, we put the vehicle to the free position
529  return freeInsertion(veh, speed, posLat);
530  }
531  break;
532  case DEPART_POS_FREE:
533  return freeInsertion(veh, speed, posLat);
534  case DEPART_POS_LAST:
535  return lastInsertion(veh, speed, posLat, patchSpeed);
536  case DEPART_POS_BASE:
537  case DEPART_POS_DEFAULT:
538  default:
539  pos = veh.basePos(myEdge);
540  break;
541  }
542  // determine the lateral position for special cases
544  switch (pars.departPosLatProcedure) {
546  for (int i = 0; i < 10; i++) {
547  // we will try some random positions ...
548  posLat = RandHelper::rand(getWidth()) - getWidth() * 0.5;
549  if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
550  return true;
551  }
552  }
553  FALLTHROUGH;
554  }
555  // no break! continue with DEPART_POSLAT_FREE
556  case DEPART_POSLAT_FREE: {
557  // systematically test all positions until a free lateral position is found
558  double posLatMin = -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
559  double posLatMax = getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
560  for (double posLat = posLatMin; posLat < posLatMax; posLat += MSGlobals::gLateralResolution) {
561  if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
562  return true;
563  }
564  }
565  return false;
566  }
567  default:
568  break;
569  }
570  }
571  // try to insert
572  return isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
573 }
574 
575 
576 bool
577 MSLane::checkFailure(const MSVehicle* aVehicle, double& speed, double& dist, const double nspeed, const bool patchSpeed, const std::string errorMsg) const {
578  if (nspeed < speed) {
579  if (patchSpeed) {
580  speed = MIN2(nspeed, speed);
581  dist = aVehicle->getCarFollowModel().brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
582  } else if (speed > 0) {
584  // Check whether vehicle can stop at the given distance when applying emergency braking
585  double emergencyBrakeGap = 0.5 * speed * speed / aVehicle->getCarFollowModel().getEmergencyDecel();
586  if (emergencyBrakeGap <= dist) {
587  // Vehicle may stop in time with emergency deceleration
588  // stil, emit a warning
589  WRITE_WARNING("Vehicle '" + aVehicle->getID() + "' is inserted in emergency situation.");
590  return false;
591  }
592  }
593 
594  if (errorMsg != "") {
595  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (" + errorMsg + ")!");
597  }
598  return true;
599  }
600  }
601  return false;
602 }
603 
604 
605 bool
607  double speed, double pos, double posLat, bool patchSpeed,
608  MSMoveReminder::Notification notification) {
609  if (pos < 0 || pos > myLength) {
610  // we may not start there
611  WRITE_WARNING("Invalid departPos " + toString(pos) + " given for vehicle '" +
612  aVehicle->getID() + "'. Inserting at lane end instead.");
613  pos = myLength;
614  }
615 
616 #ifdef DEBUG_INSERTION
617  if (DEBUG_COND2(aVehicle)) {
618  std::cout << "\nIS_INSERTION_SUCCESS\n"
619  << SIMTIME << " lane=" << getID()
620  << " veh '" << aVehicle->getID() << "'\n";
621  }
622 #endif
623 
624  aVehicle->setTentativeLaneAndPosition(this, pos, posLat);
625  aVehicle->updateBestLanes(false, this);
626  const MSCFModel& cfModel = aVehicle->getCarFollowModel();
627  const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
628  std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
629  double seen = getLength() - pos; // == distance from insertion position until the end of the currentLane
630  double dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
631 
632  // before looping through the continuation lanes, check if a stop is scheduled on this lane
633  // (the code is duplicated in the loop)
634  if (aVehicle->hasStops()) {
635  const MSVehicle::Stop& nextStop = aVehicle->getNextStop();
636  if (nextStop.lane == this) {
637  std::stringstream msg;
638  msg << "scheduled stop on lane '" << myID << "' too close";
639  const double distToStop = nextStop.pars.endPos - pos;
640  if (checkFailure(aVehicle, speed, dist, cfModel.stopSpeed(aVehicle, speed, distToStop),
641  patchSpeed, msg.str())) {
642  // we may not drive with the given velocity - we cannot stop at the stop
643  return false;
644  }
645  }
646  }
647 
648  const MSRoute& r = aVehicle->getRoute();
649  MSRouteIterator ce = r.begin();
650  int nRouteSuccs = 1;
651  MSLane* currentLane = this;
652  MSLane* nextLane = this;
654  while (seen < dist && ri != bestLaneConts.end()) {
655  // get the next link used...
656  MSLinkCont::const_iterator link = succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
657  if (currentLane->isLinkEnd(link)) {
658  if (&currentLane->getEdge() == r.getLastEdge()) {
659  // reached the end of the route
661  if (checkFailure(aVehicle, speed, dist, cfModel.freeSpeed(aVehicle, speed, seen, aVehicle->getParameter().arrivalSpeed, true),
662  patchSpeed, "arrival speed too low")) {
663  // we may not drive with the given velocity - we cannot match the specified arrival speed
664  return false;
665  }
666  }
667  } else {
668  // lane does not continue
669  if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
670  patchSpeed, "junction too close")) {
671  // we may not drive with the given velocity - we cannot stop at the junction
672  return false;
673  }
674  }
675  break;
676  }
677 
678  if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(), cfModel.getMaxDecel(), 0, posLat)
679  || !(*link)->havePriority()) {
680  // have to stop at junction
681  std::string errorMsg = "";
682  const LinkState state = (*link)->getState();
683  if (state == LINKSTATE_MINOR
684  || state == LINKSTATE_EQUAL
685  || state == LINKSTATE_STOP
686  || state == LINKSTATE_ALLWAY_STOP) {
687  // no sense in trying later
688  errorMsg = "unpriorised junction too close";
689  }
690  if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
691  patchSpeed, errorMsg)) {
692  // we may not drive with the given velocity - we cannot stop at the junction in time
693  return false;
694  }
695 #ifdef DEBUG_INSERTION
696  if DEBUG_COND2(aVehicle) {
697  std::cout << "trying insertion before minor link: "
698  << "insertion speed = " << speed << " dist=" << dist
699  << "\n";
700  }
701 #endif
702  break;
703  }
704  // get the next used lane (including internal)
705  nextLane = (*link)->getViaLaneOrLane();
706  // check how next lane affects the journey
707  if (nextLane != nullptr) {
708 
709  // check if there are stops on the next lane that should be regarded
710  // (this block is duplicated before the loop to deal with the insertion lane)
711  if (aVehicle->hasStops()) {
712  const MSVehicle::Stop& nextStop = aVehicle->getNextStop();
713  if (nextStop.lane == nextLane) {
714  std::stringstream msg;
715  msg << "scheduled stop on lane '" << nextStop.lane->getID() << "' too close";
716  const double distToStop = seen + nextStop.pars.endPos;
717  if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, distToStop),
718  patchSpeed, msg.str())) {
719  // we may not drive with the given velocity - we cannot stop at the stop
720  return false;
721  }
722  }
723  }
724 
725  // check leader on next lane
726  MSLeaderInfo leaders = nextLane->getLastVehicleInformation(aVehicle, 0, 0);
727  if (leaders.hasVehicles()) {
728  const double nspeed = nextLane->safeInsertionSpeed(aVehicle, seen, leaders, speed);
729 #ifdef DEBUG_INSERTION
730  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
731  << " leader on lane '" << nextLane->getID() << "': " << leaders.toString() << " nspeed=" << nspeed << "\n";
732 #endif
733  if (nspeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "")) {
734  // we may not drive with the given velocity - we crash into the leader
735 #ifdef DEBUG_INSERTION
736  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
737  << " isInsertionSuccess lane=" << getID()
738  << " veh=" << aVehicle->getID()
739  << " pos=" << pos
740  << " posLat=" << posLat
741  << " patchSpeed=" << patchSpeed
742  << " speed=" << speed
743  << " nspeed=" << nspeed
744  << " nextLane=" << nextLane->getID()
745  << " lead=" << leaders.toString()
746 // << " gap=" << gap
747  << " failed (@641)!\n";
748 #endif
749  return false;
750  }
751  }
752  if (!nextLane->checkForPedestrians(aVehicle, speed, dist, -seen, patchSpeed)) {
753  return false;
754  }
755  // check next lane's maximum velocity
756  const double nspeed = cfModel.freeSpeed(aVehicle, speed, seen, nextLane->getVehicleMaxSpeed(aVehicle), true);
757  if (nspeed < speed) {
758  if (patchSpeed) {
759  speed = nspeed;
760  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
761  } else {
762  // we may not drive with the given velocity - we would be too fast on the next lane
763  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (slow lane ahead)!");
765  return false;
766  }
767  }
768  // check traffic on next junction
769  // we cannot use (*link)->opened because a vehicle without priority
770  // may already be comitted to blocking the link and unable to stop
771  const SUMOTime leaveTime = (*link)->getLeaveTime(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength());
772  if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
773  if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen), patchSpeed, "")) {
774  // we may not drive with the given velocity - we crash at the junction
775  return false;
776  }
777  }
778  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
779  seen += nextLane->getLength();
780  currentLane = nextLane;
781  if ((*link)->getViaLane() == nullptr) {
782  nRouteSuccs++;
783  ++ce;
784  ++ri;
785  }
786  }
787  }
788 
789  // get the pointer to the vehicle next in front of the given position
790  MSLeaderInfo leaders = getLastVehicleInformation(aVehicle, 0, pos);
791  //if (aVehicle->getID() == "disabled") std::cout << " leaders=" << leaders.toString() << "\n";
792  const double nspeed = safeInsertionSpeed(aVehicle, -pos, leaders, speed);
793  if (nspeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "")) {
794  // we may not drive with the given velocity - we crash into the leader
795 #ifdef DEBUG_INSERTION
796  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
797  << " isInsertionSuccess lane=" << getID()
798  << " veh=" << aVehicle->getID()
799  << " pos=" << pos
800  << " posLat=" << posLat
801  << " patchSpeed=" << patchSpeed
802  << " speed=" << speed
803  << " nspeed=" << nspeed
804  << " nextLane=" << nextLane->getID()
805  << " leaders=" << leaders.toString()
806  << " failed (@700)!\n";
807 #endif
808  return false;
809  }
810 #ifdef DEBUG_INSERTION
811  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
812  << " speed = " << speed
813  << " nspeed = " << nspeed
814  << std::endl;
815 #endif
816 
817  MSLeaderDistanceInfo followers = getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
818  for (int i = 0; i < followers.numSublanes(); ++i) {
819  const MSVehicle* follower = followers[i].first;
820  if (follower != nullptr) {
821  const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), speed, cfModel.getMaxDecel());
822  if (followers[i].second < backGapNeeded) {
823  // too close to the follower on this lane
824 #ifdef DEBUG_INSERTION
825  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
826  << " isInsertionSuccess lane=" << getID()
827  << " veh=" << aVehicle->getID()
828  << " pos=" << pos
829  << " posLat=" << posLat
830  << " patchSpeed=" << patchSpeed
831  << " speed=" << speed
832  << " nspeed=" << nspeed
833  << " follower=" << follower->getID()
834  << " backGapNeeded=" << backGapNeeded
835  << " gap=" << followers[i].second
836  << " failure (@719)!\n";
837 #endif
838  return false;
839  }
840  }
841  }
842 
843  if (!checkForPedestrians(aVehicle, speed, dist, pos, patchSpeed)) {
844  return false;
845  }
846 
847  MSLane* shadowLane = aVehicle->getLaneChangeModel().getShadowLane(this);
848 #ifdef DEBUG_INSERTION
849  if (DEBUG_COND2(aVehicle)) {
850  std::cout << " shadowLane=" << Named::getIDSecure(shadowLane) << "\n";
851  }
852 #endif
853  if (shadowLane != nullptr) {
854  MSLeaderDistanceInfo followers = shadowLane->getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
855  for (int i = 0; i < followers.numSublanes(); ++i) {
856  const MSVehicle* follower = followers[i].first;
857  if (follower != nullptr) {
858  const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), speed, cfModel.getMaxDecel());
859  if (followers[i].second < backGapNeeded) {
860  // too close to the follower on this lane
861 #ifdef DEBUG_INSERTION
862  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
863  << " isInsertionSuccess shadowlane=" << shadowLane->getID()
864  << " veh=" << aVehicle->getID()
865  << " pos=" << pos
866  << " posLat=" << posLat
867  << " patchSpeed=" << patchSpeed
868  << " speed=" << speed
869  << " nspeed=" << nspeed
870  << " follower=" << follower->getID()
871  << " backGapNeeded=" << backGapNeeded
872  << " gap=" << followers[i].second
873  << " failure (@812)!\n";
874 #endif
875  return false;
876  }
877  }
878  }
879  const MSLeaderInfo& ahead = shadowLane->getLastVehicleInformation(nullptr, 0, aVehicle->getPositionOnLane(), false);
880  for (int i = 0; i < ahead.numSublanes(); ++i) {
881  const MSVehicle* veh = ahead[i];
882  if (veh != nullptr) {
883  const double gap = veh->getBackPositionOnLane(shadowLane) - aVehicle->getPositionOnLane() - aVehicle->getVehicleType().getMinGap();
884  const double gapNeeded = aVehicle->getCarFollowModel().getSecureGap(speed, veh->getSpeed(), veh->getCarFollowModel().getMaxDecel());
885  if (gap < gapNeeded) {
886  // too close to the shadow leader
887 #ifdef DEBUG_INSERTION
888  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
889  << " isInsertionSuccess shadowlane=" << shadowLane->getID()
890  << " veh=" << aVehicle->getID()
891  << " pos=" << pos
892  << " posLat=" << posLat
893  << " patchSpeed=" << patchSpeed
894  << " speed=" << speed
895  << " nspeed=" << nspeed
896  << " leader=" << veh->getID()
897  << " gapNeeded=" << gapNeeded
898  << " gap=" << gap
899  << " failure (@842)!\n";
900 #endif
901  return false;
902  }
903  }
904  }
905  }
906  if (followers.numFreeSublanes() > 0) {
907  // check approaching vehicles to prevent rear-end collisions
908  const double backOffset = pos - aVehicle->getVehicleType().getLength();
909  const double missingRearGap = getMissingRearGap(aVehicle, backOffset, speed);
910  if (missingRearGap > 0) {
911  // too close to a follower
912 #ifdef DEBUG_INSERTION
913  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
914  << " isInsertionSuccess lane=" << getID()
915  << " veh=" << aVehicle->getID()
916  << " pos=" << pos
917  << " posLat=" << posLat
918  << " patchSpeed=" << patchSpeed
919  << " speed=" << speed
920  << " nspeed=" << nspeed
921  << " missingRearGap=" << missingRearGap
922  << " failure (@728)!\n";
923 #endif
924  return false;
925  }
926  }
927  // may got negative while adaptation
928  if (speed < 0) {
929 #ifdef DEBUG_INSERTION
930  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
931  << " isInsertionSuccess lane=" << getID()
932  << " veh=" << aVehicle->getID()
933  << " pos=" << pos
934  << " posLat=" << posLat
935  << " patchSpeed=" << patchSpeed
936  << " speed=" << speed
937  << " nspeed=" << nspeed
938  << " failed (@733)!\n";
939 #endif
940  return false;
941  }
942  // enter
943  incorporateVehicle(aVehicle, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos)), notification);
944 #ifdef DEBUG_INSERTION
945  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
946  << " isInsertionSuccess lane=" << getID()
947  << " veh=" << aVehicle->getID()
948  << " pos=" << pos
949  << " posLat=" << posLat
950  << " patchSpeed=" << patchSpeed
951  << " speed=" << speed
952  << " nspeed=" << nspeed
953  << "\n myVehicles=" << toString(myVehicles)
954  << " myPartial=" << toString(myPartialVehicles)
955  << " myManeuverReservations=" << toString(myManeuverReservations)
956  << "\n leaders=" << leaders.toString()
957  << "\n success!\n";
958 #endif
959  return true;
960 }
961 
962 
963 void
964 MSLane::forceVehicleInsertion(MSVehicle* veh, double pos, MSMoveReminder::Notification notification, double posLat) {
965  veh->updateBestLanes(true, this);
966  bool dummy;
967  const double speed = veh->hasDeparted() ? veh->getSpeed() : getDepartSpeed(*veh, dummy);
968  incorporateVehicle(veh, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos)), notification);
969 }
970 
971 
972 double
973 MSLane::safeInsertionSpeed(const MSVehicle* veh, double seen, const MSLeaderInfo& leaders, double speed) {
974  double nspeed = speed;
975 #ifdef DEBUG_INSERTION
976  if (DEBUG_COND2(veh)) {
977  std::cout << SIMTIME << " safeInsertionSpeed veh=" << veh->getID() << " speed=" << speed << "\n";
978  }
979 #endif
980  for (int i = 0; i < leaders.numSublanes(); ++i) {
981  const MSVehicle* leader = leaders[i];
982  if (leader != nullptr) {
983  const double gap = leader->getBackPositionOnLane(this) + seen - veh->getVehicleType().getMinGap();
984  if (gap < 0) {
985  return INVALID_SPEED;
986  }
987  nspeed = MIN2(nspeed,
988  veh->getCarFollowModel().insertionFollowSpeed(veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()));
989 #ifdef DEBUG_INSERTION
990  if (DEBUG_COND2(veh)) {
991  std::cout << " leader=" << leader->getID() << " nspeed=" << nspeed << "\n";
992  }
993 #endif
994  }
995  }
996  return nspeed;
997 }
998 
999 
1000 // ------ Handling vehicles lapping into lanes ------
1001 const MSLeaderInfo&
1002 MSLane::getLastVehicleInformation(const MSVehicle* ego, double latOffset, double minPos, bool allowCached) const {
1003  if (myLeaderInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || minPos > 0 || !allowCached) {
1004  myLeaderInfoTmp = MSLeaderInfo(this, ego, latOffset);
1006  int freeSublanes = 1; // number of sublanes for which no leader was found
1007  //if (ego->getID() == "disabled" && SIMTIME == 58) {
1008  // std::cout << "DEBUG\n";
1009  //}
1010  const MSVehicle* veh = *last;
1011  while (freeSublanes > 0 && veh != nullptr) {
1012 #ifdef DEBUG_PLAN_MOVE
1013  if (DEBUG_COND2(ego)) {
1014  gDebugFlag1 = true;
1015  std::cout << " getLastVehicleInformation lane=" << getID() << " minPos=" << minPos << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
1016  }
1017 #endif
1018  if (veh != ego && veh->getPositionOnLane(this) >= minPos) {
1019  const double latOffset = veh->getLatOffset(this);
1020  freeSublanes = myLeaderInfoTmp.addLeader(veh, true, latOffset);
1021 #ifdef DEBUG_PLAN_MOVE
1022  if (DEBUG_COND2(ego)) {
1023  std::cout << " latOffset=" << latOffset << " newLeaders=" << myLeaderInfoTmp.toString() << "\n";
1024  }
1025 #endif
1026  }
1027  veh = *(++last);
1028  }
1029  if (ego == nullptr && minPos == 0) {
1030  // update cached value
1033  }
1034 #ifdef DEBUG_PLAN_MOVE
1035  //if (DEBUG_COND2(ego)) std::cout << SIMTIME
1036  // << " getLastVehicleInformation lane=" << getID()
1037  // << " ego=" << Named::getIDSecure(ego)
1038  // << "\n"
1039  // << " vehicles=" << toString(myVehicles)
1040  // << " partials=" << toString(myPartialVehicles)
1041  // << "\n"
1042  // << " result=" << myLeaderInfoTmp.toString()
1043  // << " cached=" << myLeaderInfo.toString()
1044  // << " myLeaderInfoTime=" << myLeaderInfoTime
1045  // << "\n";
1046  gDebugFlag1 = false;
1047 #endif
1048  return myLeaderInfoTmp;
1049  }
1050  return myLeaderInfo;
1051 }
1052 
1053 
1054 const MSLeaderInfo&
1055 MSLane::getFirstVehicleInformation(const MSVehicle* ego, double latOffset, bool onlyFrontOnLane, double maxPos, bool allowCached) const {
1056  if (myFollowerInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || maxPos < myLength || !allowCached || onlyFrontOnLane) {
1057  // XXX separate cache for onlyFrontOnLane = true
1058  myLeaderInfoTmp = MSLeaderInfo(this, ego, latOffset);
1060  int freeSublanes = 1; // number of sublanes for which no leader was found
1061  const MSVehicle* veh = *first;
1062  while (freeSublanes > 0 && veh != nullptr) {
1063 #ifdef DEBUG_PLAN_MOVE
1064  if (DEBUG_COND2(ego)) {
1065  std::cout << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << " maxPos=" << maxPos << "\n";
1066  }
1067 #endif
1068  if (veh != ego && veh->getPositionOnLane(this) <= maxPos
1069  && (!onlyFrontOnLane || veh->isFrontOnLane(this))) {
1070  //const double latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
1071  const double latOffset = veh->getLatOffset(this);
1072 #ifdef DEBUG_PLAN_MOVE
1073  if (DEBUG_COND2(ego)) {
1074  std::cout << " veh=" << veh->getID() << " latOffset=" << latOffset << "\n";
1075  }
1076 #endif
1077  freeSublanes = myLeaderInfoTmp.addLeader(veh, true, latOffset);
1078  }
1079  veh = *(++first);
1080  }
1081  if (ego == nullptr && maxPos == std::numeric_limits<double>::max()) {
1082  // update cached value
1085  }
1086 #ifdef DEBUG_PLAN_MOVE
1087  //if (DEBUG_COND2(ego)) std::cout << SIMTIME
1088  // << " getFirstVehicleInformation lane=" << getID()
1089  // << " ego=" << Named::getIDSecure(ego)
1090  // << "\n"
1091  // << " vehicles=" << toString(myVehicles)
1092  // << " partials=" << toString(myPartialVehicles)
1093  // << "\n"
1094  // << " result=" << myLeaderInfoTmp.toString()
1095  // //<< " cached=" << myLeaderInfo.toString()
1096  // << " myLeaderInfoTime=" << myLeaderInfoTime
1097  // << "\n";
1098 #endif
1099  return myLeaderInfoTmp;
1100  }
1101  return myFollowerInfo;
1102 }
1103 
1104 
1105 // ------ ------
1106 void
1108  assert(myVehicles.size() != 0);
1109  double cumulatedVehLength = 0.;
1110  MSLeaderInfo leaders(this);
1111 
1112  // iterate over myVehicles, myPartialVehicles, and myManeuverReservations merge-sort style
1113  VehCont::reverse_iterator veh = myVehicles.rbegin();
1114  VehCont::reverse_iterator vehPart = myPartialVehicles.rbegin();
1115  VehCont::reverse_iterator vehRes = myManeuverReservations.rbegin();
1116 #ifdef DEBUG_PLAN_MOVE
1117  if (DEBUG_COND) std::cout
1118  << "\n"
1119  << SIMTIME
1120  << " planMovements() lane=" << getID()
1121  << "\n vehicles=" << toString(myVehicles)
1122  << "\n partials=" << toString(myPartialVehicles)
1123  << "\n reservations=" << toString(myManeuverReservations)
1124  << "\n";
1125 #endif
1127  for (; veh != myVehicles.rend(); ++veh) {
1128 #ifdef DEBUG_PLAN_MOVE
1129  if (DEBUG_COND2((*veh))) {
1130  std::cout << " plan move for: " << (*veh)->getID();
1131  }
1132 #endif
1133  updateLeaderInfo(*veh, vehPart, vehRes, leaders);
1134 #ifdef DEBUG_PLAN_MOVE
1135  if (DEBUG_COND2((*veh))) {
1136  std::cout << " leaders=" << leaders.toString() << "\n";
1137  }
1138 #endif
1139  (*veh)->planMove(t, leaders, cumulatedVehLength);
1140  cumulatedVehLength += (*veh)->getVehicleType().getLengthWithGap();
1141  leaders.addLeader(*veh, false, 0);
1142  }
1143 }
1144 
1145 void
1147  for (MSVehicle* veh : myVehicles) {
1148  veh->setApproachingForAllLinks(t);
1149  }
1150 }
1151 
1152 void
1153 MSLane::updateLeaderInfo(const MSVehicle* veh, VehCont::reverse_iterator& vehPart, VehCont::reverse_iterator& vehRes, MSLeaderInfo& ahead) const {
1154  bool morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1155  bool moreReservationsAhead = vehRes != myManeuverReservations.rend();
1156  bool nextToConsiderIsPartial;
1157 
1158  // Determine relevant leaders for veh
1159  while (moreReservationsAhead || morePartialVehsAhead) {
1160  if ((!moreReservationsAhead || (*vehRes)->getPositionOnLane(this) <= veh->getPositionOnLane())
1161  && (!morePartialVehsAhead || (*vehPart)->getPositionOnLane(this) <= veh->getPositionOnLane())) {
1162  // All relevant downstream vehicles have been collected.
1163  break;
1164  }
1165 
1166  // Check whether next farthest relevant vehicle downstream is a partial vehicle or a maneuver reservation
1167  if (moreReservationsAhead && !morePartialVehsAhead) {
1168  nextToConsiderIsPartial = false;
1169  } else if (morePartialVehsAhead && !moreReservationsAhead) {
1170  nextToConsiderIsPartial = true;
1171  } else {
1172  assert(morePartialVehsAhead && moreReservationsAhead);
1173  // Add farthest downstream vehicle first
1174  nextToConsiderIsPartial = (*vehPart)->getPositionOnLane(this) > (*vehRes)->getPositionOnLane(this);
1175  }
1176  // Add appropriate leader information
1177  if (nextToConsiderIsPartial) {
1178  const double latOffset = (*vehPart)->getLatOffset(this);
1179 #ifdef DEBUG_PLAN_MOVE
1180  if (DEBUG_COND) {
1181  std::cout << " partial ahead: " << (*vehPart)->getID() << " latOffset=" << latOffset << "\n";
1182  }
1183 #endif
1184  ahead.addLeader(*vehPart, false, latOffset);
1185  ++vehPart;
1186  morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1187  } else {
1188  const double latOffset = (*vehRes)->getLatOffset(this);
1189 #ifdef DEBUG_PLAN_MOVE
1190  if (DEBUG_COND) {
1191  std::cout << " reservation ahead: " << (*vehRes)->getID() << " latOffset=" << latOffset << "\n";
1192  }
1193 #endif
1194  ahead.addLeader(*vehRes, false, latOffset);
1195  ++vehRes;
1196  moreReservationsAhead = vehRes != myManeuverReservations.rend();
1197  }
1198  }
1199 }
1200 
1201 
1202 void
1203 MSLane::detectCollisions(SUMOTime timestep, const std::string& stage) {
1204  myNeedsCollisionCheck = false;
1205 #ifdef DEBUG_COLLISIONS
1206  if (DEBUG_COND) {
1207  std::vector<const MSVehicle*> all;
1208  for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
1209  all.push_back(*last);
1210  }
1211  std::cout << SIMTIME << " detectCollisions stage=" << stage << " lane=" << getID() << ":\n"
1212  << " vehs=" << toString(myVehicles) << "\n"
1213  << " part=" << toString(myPartialVehicles) << "\n"
1214  << " all=" << toString(all) << "\n"
1215  << "\n";
1216  }
1217 #endif
1218 
1219  if (myVehicles.size() == 0 || myCollisionAction == COLLISION_ACTION_NONE) {
1220  return;
1221  }
1222  std::set<const MSVehicle*, ComparatorNumericalIdLess> toRemove;
1223  std::set<const MSVehicle*> toTeleport;
1225  // no sublanes
1226  VehCont::reverse_iterator lastVeh = myVehicles.rend() - 1;
1227  for (VehCont::reverse_iterator pred = myVehicles.rbegin(); pred != lastVeh; ++pred) {
1228  VehCont::reverse_iterator veh = pred + 1;
1229  detectCollisionBetween(timestep, stage, *veh, *pred, toRemove, toTeleport);
1230  }
1231  if (myPartialVehicles.size() > 0) {
1232  detectCollisionBetween(timestep, stage, *lastVeh, myPartialVehicles.front(), toRemove, toTeleport);
1233  }
1234  } else {
1235  // in the sublane-case it is insufficient to check the vehicles ordered
1236  // by their front position as there might be more than 2 vehicles next to each
1237  // other on the same lane
1238  // instead, a moving-window approach is used where all vehicles that
1239  // overlap in the longitudinal direction receive pairwise checks
1240  // XXX for efficiency, all lanes of an edge should be checked together
1241  // (lanechanger-style)
1242 
1243  // XXX quick hack: check each in myVehicles against all others
1244  for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != anyVehiclesEnd(); ++veh) {
1245  MSVehicle* follow = (MSVehicle*)*veh;
1246  for (AnyVehicleIterator veh2 = anyVehiclesBegin(); veh2 != anyVehiclesEnd(); ++veh2) {
1247  MSVehicle* lead = (MSVehicle*)*veh2;
1248  if (lead == follow) {
1249  continue;
1250  }
1251  if (lead->getPositionOnLane(this) < follow->getPositionOnLane(this)) {
1252  continue;
1253  }
1254  if (detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
1255  // XXX what about collisions with multiple leaders at once?
1256  break;
1257  }
1258  }
1259  if (follow->getLaneChangeModel().getShadowLane() != nullptr && follow->getLane() == this) {
1260  // check whether follow collides on the shadow lane
1261  const MSLane* shadowLane = follow->getLaneChangeModel().getShadowLane();
1262  MSLeaderInfo ahead = shadowLane->getLastVehicleInformation(follow,
1263  getRightSideOnEdge() - shadowLane->getRightSideOnEdge(),
1264  follow->getPositionOnLane());
1265  for (int i = 0; i < ahead.numSublanes(); ++i) {
1266  MSVehicle* lead = const_cast<MSVehicle*>(ahead[i]);
1267  if (lead != nullptr && lead != follow && shadowLane->detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
1268  break;
1269  }
1270  }
1271  }
1272  }
1273  }
1274 
1276  myNeedsCollisionCheck = true; // always check
1277 #ifdef DEBUG_JUNCTION_COLLISIONS
1278  if (DEBUG_COND) {
1279  std::cout << SIMTIME << " detect junction Collisions stage=" << stage << " lane=" << getID() << ":\n"
1280  << " vehs=" << toString(myVehicles) << "\n"
1281  << " part=" << toString(myPartialVehicles) << "\n"
1282  << "\n";
1283  }
1284 #endif
1285  assert(myLinks.size() == 1);
1286  //std::cout << SIMTIME << " checkJunctionCollisions " << getID() << "\n";
1287  const std::vector<const MSLane*>& foeLanes = myLinks.front()->getFoeLanes();
1288  for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != anyVehiclesEnd(); ++veh) {
1289  MSVehicle* collider = const_cast<MSVehicle*>(*veh);
1290  //std::cout << " collider " << collider->getID() << "\n";
1291  PositionVector colliderBoundary = collider->getBoundingBox();
1292  for (std::vector<const MSLane*>::const_iterator it = foeLanes.begin(); it != foeLanes.end(); ++it) {
1293  const MSLane* foeLane = *it;
1294  //std::cout << " foeLane " << foeLane->getID() << "\n";
1295  MSLane::AnyVehicleIterator end = foeLane->anyVehiclesEnd();
1296  for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != end; ++it_veh) {
1297  MSVehicle* victim = (MSVehicle*)*it_veh;
1298  if (victim == collider) {
1299  // may happen if the vehicles lane and shadow lane are siblings
1300  continue;
1301  }
1302  //std::cout << " victim " << victim->getID() << "\n";
1303 #ifdef DEBUG_JUNCTION_COLLISIONS
1304  if (DEBUG_COND && DEBUG_COND2(collider)) {
1305  std::cout << SIMTIME << " foe=" << victim->getID() << " bound=" << colliderBoundary << " foeBound=" << victim->getBoundingBox() << "\n";
1306  }
1307 #endif
1308  if (colliderBoundary.overlapsWith(victim->getBoundingBox())) {
1309  // make a detailed check
1310  if (collider->getBoundingPoly().overlapsWith(victim->getBoundingPoly())) {
1311  handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1312  }
1313  }
1314  }
1315  detectPedestrianJunctionCollision(collider, colliderBoundary, foeLane, timestep, stage);
1316  }
1317  if (myLinks.front()->getWalkingAreaFoe() != nullptr) {
1318  detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoe(), timestep, stage);
1319  }
1320  }
1321  }
1322 
1323  if (myEdge->getPersons().size() > 0 && MSPModel::getModel()->hasPedestrians(this)) {
1324 #ifdef DEBUG_PEDESTRIAN_COLLISIONS
1325  if (DEBUG_COND) {
1326  std::cout << SIMTIME << " detect pedestrian collisions stage=" << stage << " lane=" << getID() << "\n";
1327  }
1328 #endif
1330  for (AnyVehicleIterator it_v = anyVehiclesBegin(); it_v != v_end; ++it_v) {
1331  const MSVehicle* v = *it_v;
1332  const double back = v->getBackPositionOnLane(this);
1333  const double length = v->getVehicleType().getLength();
1334  const double right = v->getRightSideOnEdge(this) - getRightSideOnEdge();
1335  PersonDist leader = MSPModel::getModel()->nextBlocking(this, back, right, right + v->getVehicleType().getWidth());
1336 #ifdef DEBUG_PEDESTRIAN_COLLISIONS
1337  if (DEBUG_COND && DEBUG_COND2(v)) {
1338  std::cout << SIMTIME << " back=" << back << " right=" << right << " person=" << Named::getIDSecure(leader.first) << " dist=" << leader.second << "\n";
1339  }
1340 #endif
1341  if (leader.first != 0 && leader.second < length) {
1342  WRITE_WARNING(
1343  "Vehicle '" + v->getID()
1344  + "' collision with person '" + leader.first->getID()
1345  + "', lane='" + getID()
1346  + "', gap=" + toString(leader.second - length)
1347  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep())
1348  + " stage=" + stage + ".");
1350  }
1351  }
1352  }
1353 
1354 
1355  for (std::set<const MSVehicle*, ComparatorNumericalIdLess>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) {
1356  MSVehicle* veh = const_cast<MSVehicle*>(*it);
1357  MSLane* vehLane = veh->getLane();
1359  if (toTeleport.count(veh) > 0) {
1360  MSVehicleTransfer::getInstance()->add(timestep, veh);
1361  } else {
1364  }
1365  }
1366 }
1367 
1368 
1369 void
1370 MSLane::detectPedestrianJunctionCollision(const MSVehicle* collider, const PositionVector& colliderBoundary, const MSLane* foeLane,
1371  SUMOTime timestep, const std::string& stage) {
1372  if (foeLane->getEdge().getPersons().size() > 0 && MSPModel::getModel()->hasPedestrians(foeLane)) {
1373 #ifdef DEBUG_PEDESTRIAN_COLLISIONS
1374  if (DEBUG_COND) {
1375  std::cout << SIMTIME << " detect pedestrian junction collisions stage=" << stage << " lane=" << getID() << " foeLane=" << foeLane->getID() << "\n";
1376  }
1377 #endif
1378  const std::vector<MSTransportable*>& persons = foeLane->getEdge().getSortedPersons(timestep);
1379  for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
1380 #ifdef DEBUG_PEDESTRIAN_COLLISIONS
1381  if (DEBUG_COND) {
1382  std::cout << " collider=" << collider->getID()
1383  << " ped=" << (*it_p)->getID()
1384  << " colliderBoundary=" << colliderBoundary
1385  << " pedBoundary=" << (*it_p)->getBoundingBox()
1386  << "\n";
1387  }
1388 #endif
1389  if (colliderBoundary.overlapsWith((*it_p)->getBoundingBox())) {
1390  WRITE_WARNING(
1391  "Vehicle '" + collider->getID()
1392  + "' collision with person '" + (*it_p)->getID()
1393  + "', lane='" + getID()
1394  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep())
1395  + " stage=" + stage + ".");
1397  }
1398  }
1399  }
1400 }
1401 
1402 bool
1403 MSLane::detectCollisionBetween(SUMOTime timestep, const std::string& stage, MSVehicle* collider, MSVehicle* victim,
1404  std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1405  std::set<const MSVehicle*>& toTeleport) const {
1406  if (myCollisionAction == COLLISION_ACTION_TELEPORT && ((victim->hasInfluencer() && victim->getInfluencer().isRemoteAffected(timestep)) ||
1407  (collider->hasInfluencer() && collider->getInfluencer().isRemoteAffected(timestep)))) {
1408  return false;
1409  }
1410 
1411  // No self-collisions! (This is assumed to be ensured at caller side)
1412  if (collider == victim) {
1413  return false;
1414  }
1415 
1416  const bool colliderOpposite = collider->getLaneChangeModel().isOpposite();
1417  const bool bothOpposite = victim->getLaneChangeModel().isOpposite() && colliderOpposite;
1418  if (bothOpposite) {
1419  std::swap(victim, collider);
1420  }
1421  const double colliderPos = colliderOpposite ? collider->getBackPositionOnLane(this) : collider->getPositionOnLane(this);
1423  double gap = victim->getBackPositionOnLane(this) - colliderPos - minGapFactor * collider->getVehicleType().getMinGap();
1424  if (bothOpposite) {
1425  gap = -gap - 2 * myCollisionMinGapFactor * collider->getVehicleType().getMinGap();
1426  }
1427 #ifdef DEBUG_COLLISIONS
1428  if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
1429  std::cout << SIMTIME
1430  << " thisLane=" << getID()
1431  << " collider=" << collider->getID()
1432  << " victim=" << victim->getID()
1433  << " colliderLane=" << collider->getLane()->getID()
1434  << " victimLane=" << victim->getLane()->getID()
1435  << " colliderPos=" << colliderPos
1436  << " victimBackPos=" << victim->getBackPositionOnLane(this)
1437  << " colliderLat=" << collider->getCenterOnEdge(this)
1438  << " victimLat=" << victim->getCenterOnEdge(this)
1439  << " minGap=" << collider->getVehicleType().getMinGap()
1440  << " minGapFactor=" << minGapFactor
1441  << " gap=" << gap
1442  << "\n";
1443  }
1444 #endif
1445  if (gap < -NUMERICAL_EPS) {
1446  double latGap = 0;
1448  latGap = (fabs(victim->getCenterOnEdge(this) - collider->getCenterOnEdge(this))
1449  - 0.5 * fabs(victim->getVehicleType().getWidth() + collider->getVehicleType().getWidth()));
1450  if (latGap + NUMERICAL_EPS > 0) {
1451  return false;
1452  }
1453  }
1455  && collider->getLaneChangeModel().isChangingLanes()
1456  && victim->getLaneChangeModel().isChangingLanes()
1457  && victim->getLane() != this) {
1458  // synchroneous lane change maneuver
1459  return false;
1460  }
1461  handleCollisionBetween(timestep, stage, collider, victim, gap, latGap, toRemove, toTeleport);
1462  return true;
1463  }
1464  return false;
1465 }
1466 
1467 
1468 void
1469 MSLane::handleCollisionBetween(SUMOTime timestep, const std::string& stage, MSVehicle* collider, MSVehicle* victim,
1470  double gap, double latGap, std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1471  std::set<const MSVehicle*>& toTeleport) const {
1472  std::string collisionType = (collider->getLaneChangeModel().isOpposite() != victim->getLaneChangeModel().isOpposite() ?
1473  "frontal collision" : "collision");
1474  // in frontal collisions the opposite vehicle is the collider
1475  if (victim->getLaneChangeModel().isOpposite() && !collider->getLaneChangeModel().isOpposite()) {
1476  std::swap(collider, victim);
1477  }
1478  std::string prefix = "Vehicle '" + collider->getID() + "'; " + collisionType + " with vehicle '" + victim->getID() ;
1479  if (myCollisionStopTime > 0) {
1480  if (collider->collisionStopTime() >= 0 && victim->collisionStopTime() >= 0) {
1481  return;
1482  }
1483  std::string dummyError;
1486  stop.busstop = "";
1487  stop.containerstop = "";
1488  stop.chargingStation = "";
1489  stop.parkingarea = "";
1490  stop.until = 0;
1491  stop.triggered = false;
1492  stop.containerTriggered = false;
1493  stop.parking = false;
1494  stop.index = 0;
1495  const double collisionAngle = RAD2DEG(fabs(GeomHelper::angleDiff(victim->getAngle(), collider->getAngle())));
1496  // determine new speeds from collision angle (@todo account for vehicle mass)
1497  double victimSpeed = victim->getSpeed();
1498  double colliderSpeed = collider->getSpeed();
1499  // double victimOrigSpeed = victim->getSpeed();
1500  // double colliderOrigSpeed = collider->getSpeed();
1501  if (collisionAngle < 45) {
1502  // rear-end collisions
1503  colliderSpeed = MIN2(colliderSpeed, victimSpeed);
1504  } else if (collisionAngle < 135) {
1505  // side collision
1506  colliderSpeed /= 2;
1507  victimSpeed /= 2;
1508  } else {
1509  // frontal collision
1510  colliderSpeed = 0;
1511  victimSpeed = 0;
1512  }
1513  const double victimStopPos = MIN2(victim->getLane()->getLength(),
1514  victim->getPositionOnLane() + victim->getCarFollowModel().brakeGap(victimSpeed, victim->getCarFollowModel().getEmergencyDecel(), 0));
1515  if (victim->collisionStopTime() < 0) {
1516  stop.lane = victim->getLane()->getID();
1517  // @todo: push victim forward?
1518  stop.startPos = victimStopPos;
1519  stop.endPos = stop.startPos;
1521  victim->addStop(stop, dummyError, 0, true);
1522  }
1523  if (collider->collisionStopTime() < 0) {
1524  stop.lane = collider->getLane()->getID();
1525  stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
1526  MAX2(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength()));
1527  stop.endPos = stop.startPos;
1528  collider->addStop(stop, dummyError, 0, true);
1529  }
1530  //std::cout << " collisionAngle=" << collisionAngle
1531  // << "\n vPos=" << victim->getPositionOnLane() << " vStop=" << victimStopPos << " vSpeed=" << victimOrigSpeed << " vSpeed2=" << victimSpeed << " vSpeed3=" << victim->getSpeed()
1532  // << "\n cPos=" << collider->getPositionOnLane() << " cStop=" << stop.startPos << " cSpeed=" << colliderOrigSpeed << " cSpeed2=" << colliderSpeed << " cSpeed3=" << collider->getSpeed()
1533  // << "\n";
1534  } else {
1535  switch (myCollisionAction) {
1536  case COLLISION_ACTION_WARN:
1537  break;
1539  prefix = "Teleporting vehicle '" + collider->getID() + "'; " + collisionType + " with vehicle '" + victim->getID() ;
1540  toRemove.insert(collider);
1541  toTeleport.insert(collider);
1542  break;
1543  case COLLISION_ACTION_REMOVE: {
1544  prefix = "Removing " + collisionType + " participants: vehicle '" + collider->getID() + "', vehicle '" + victim->getID();
1545  bool removeCollider = true;
1546  bool removeVictim = true;
1547  removeVictim = !(victim->hasInfluencer() && victim->getInfluencer().isRemoteAffected(timestep));
1548  removeCollider = !(collider->hasInfluencer() && collider->getInfluencer().isRemoteAffected(timestep));
1549  if (removeVictim) {
1550  toRemove.insert(victim);
1551  }
1552  if (removeCollider) {
1553  toRemove.insert(collider);
1554  }
1555  if (!removeVictim) {
1556  if (!removeCollider) {
1557  prefix = "Keeping remote-controlled " + collisionType + " participants: vehicle '" + collider->getID() + "', vehicle '" + victim->getID();
1558  } else {
1559  prefix = "Removing " + collisionType + " participant: vehicle '" + collider->getID() + "', keeping remote-controlled vehicle '" + victim->getID();
1560  }
1561  } else if (!removeCollider) {
1562  prefix = "Keeping remote-controlled " + collisionType + " participant: vehicle '" + collider->getID() + "', removing vehicle '" + victim->getID();
1563  }
1564  break;
1565  }
1566  default:
1567  break;
1568  }
1569  }
1570  WRITE_WARNING(prefix
1571  + "', lane='" + getID()
1572  + "', gap=" + toString(gap)
1573  + (MSAbstractLaneChangeModel::haveLateralDynamics() ? "', latGap=" + toString(latGap) : "")
1574  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep())
1575  + " stage=" + stage + ".");
1576 #ifdef DEBUG_COLLISIONS
1577  if (DEBUG_COND2(collider)) {
1578  toRemove.erase(collider);
1579  toTeleport.erase(collider);
1580  }
1581  if (DEBUG_COND2(victim)) {
1582  toRemove.erase(victim);
1583  toTeleport.erase(victim);
1584  }
1585 #endif
1589 }
1590 
1591 
1592 bool
1593 MSLane::executeMovements(SUMOTime t, std::vector<MSLane*>& lanesWithVehiclesToIntegrate) {
1594  myNeedsCollisionCheck = true;
1595  // iterate over vehicles in reverse so that move reminders will be called in the correct order
1596  for (VehCont::reverse_iterator i = myVehicles.rbegin(); i != myVehicles.rend();) {
1597  MSVehicle* veh = *i;
1598  // length is needed later when the vehicle may not exist anymore
1599  const double length = veh->getVehicleType().getLengthWithGap();
1600  const double nettoLength = veh->getVehicleType().getLength();
1601  const bool moved = veh->executeMove();
1602  MSLane* const target = veh->getLane();
1603  if (veh->hasArrived()) {
1604  // vehicle has reached its arrival position
1605 #ifdef DEBUG_EXEC_MOVE
1606  if DEBUG_COND2(veh) {
1607  std::cout << SIMTIME << " veh " << veh->getID() << " has arrived." << std::endl;
1608  }
1609 #endif
1612  } else if (target != nullptr && moved) {
1613  if (target->getEdge().isVaporizing()) {
1614  // vehicle has reached a vaporizing edge
1617  } else {
1618  // vehicle has entered a new lane (leaveLane and workOnMoveReminders were already called in MSVehicle::executeMove)
1619  target->myVehBuffer.push_back(veh);
1620  lanesWithVehiclesToIntegrate.push_back(target);
1621  }
1622  } else if (veh->isParking()) {
1623  // vehicle started to park
1625  myParkingVehicles.insert(veh);
1626  } else if (veh->getPositionOnLane() > getLength()) {
1627  // for any reasons the vehicle is beyond its lane...
1628  // this should never happen because it is handled in MSVehicle::executeMove
1629  assert(false);
1630  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; beyond end of lane, target lane='" + getID() + "', time=" +
1631  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1634  } else if (veh->collisionStopTime() == 0) {
1635  veh->resumeFromStopping();
1637  WRITE_WARNING("Removing vehicle '" + veh->getID() + "' after earlier collision, lane='" + veh->getLane()->getID() + ", time=" +
1638  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1642  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "' after earlier collision, lane='" + veh->getLane()->getID() + ", time=" +
1643  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1644  MSVehicleTransfer::getInstance()->add(MSNet::getInstance()->getCurrentTimeStep(), veh);
1645  } else {
1646  ++i;
1647  continue;
1648  }
1649  } else {
1650  ++i;
1651  continue;
1652  }
1653  myBruttoVehicleLengthSum -= length;
1654  myNettoVehicleLengthSum -= nettoLength;
1655  ++i;
1656  i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
1657  }
1658  if (myVehicles.size() > 0) {
1660  MSVehicle* veh = myVehicles.back(); // the vehice at the front of the queue
1661  if (!veh->isStopped() && veh->getLane() == this) {
1662  const bool wrongLane = !veh->getLane()->appropriate(veh);
1664  const bool r2 = MSGlobals::gTimeToGridlockHighways > 0 && veh->getWaitingTime() > MSGlobals::gTimeToGridlockHighways && veh->getLane()->getSpeedLimit() > 69. / 3.6 && wrongLane;
1665  if (r1 || r2) {
1666  const MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
1667  const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
1668  const std::string reason = (wrongLane ? " (wrong lane)" : (minorLink ? " (yield)" : " (jam)"));
1669  MSVehicle* veh = *(myVehicles.end() - 1);
1672  myVehicles.erase(myVehicles.end() - 1);
1673  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long"
1674  + reason
1675  + (r2 ? " (highway)" : "")
1676  + ", lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1677  if (wrongLane) {
1679  } else if (minorLink) {
1681  } else {
1683  }
1685  }
1686  } // else look for a (waiting) vehicle that isn't stopped?
1687  }
1688  } else {
1689  // avoid numerical instability
1692  }
1694  // trigger sorting of vehicles as their order may have changed
1695  lanesWithVehiclesToIntegrate.push_back(this);
1696  }
1697  return myVehicles.size() == 0;
1698 }
1699 
1700 
1701 const MSEdge*
1703  const MSEdge* e = myEdge;
1704  while (e->isInternal()) {
1705  e = e->getSuccessors()[0];
1706  }
1707  return e;
1708 }
1709 
1710 
1711 const MSLane*
1713  if (!this->isInternal()) {
1714  return nullptr;
1715  }
1716  offset = 0.;
1717  const MSLane* firstInternal = this;
1719  while (pred != nullptr && pred->isInternal()) {
1720  firstInternal = pred;
1721  offset += pred->getLength();
1722  pred = firstInternal->getCanonicalPredecessorLane();
1723  }
1724  return firstInternal;
1725 }
1726 
1727 
1728 // ------ Static (sic!) container methods ------
1729 bool
1730 MSLane::dictionary(const std::string& id, MSLane* ptr) {
1731  DictType::iterator it = myDict.find(id);
1732  if (it == myDict.end()) {
1733  // id not in myDict.
1734  myDict.insert(DictType::value_type(id, ptr));
1735  return true;
1736  }
1737  return false;
1738 }
1739 
1740 
1741 MSLane*
1742 MSLane::dictionary(const std::string& id) {
1743  DictType::iterator it = myDict.find(id);
1744  if (it == myDict.end()) {
1745  // id not in myDict.
1746  return nullptr;
1747  }
1748  return it->second;
1749 }
1750 
1751 
1752 void
1754  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1755  delete(*i).second;
1756  }
1757  myDict.clear();
1758 }
1759 
1760 
1761 void
1762 MSLane::insertIDs(std::vector<std::string>& into) {
1763  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1764  into.push_back((*i).first);
1765  }
1766 }
1767 
1768 
1769 template<class RTREE> void
1770 MSLane::fill(RTREE& into) {
1771  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1772  MSLane* l = (*i).second;
1773  Boundary b = l->getShape().getBoxBoundary();
1774  b.grow(3.);
1775  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1776  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1777  into.Insert(cmin, cmax, l);
1778  }
1779 }
1780 
1781 template void MSLane::fill<NamedRTree>(NamedRTree& into);
1782 template void MSLane::fill<LANE_RTREE_QUAL>(LANE_RTREE_QUAL& into);
1783 
1784 // ------ ------
1785 bool
1787  if (myEdge->isInternal()) {
1788  return true;
1789  }
1790  if (veh->succEdge(1) == nullptr) {
1791  assert((int)veh->getBestLanes().size() > veh->getLaneIndex());
1792  if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
1793  return true;
1794  } else {
1795  return false;
1796  }
1797  }
1798  MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
1799  return (link != myLinks.end());
1800 }
1801 
1802 
1803 bool
1805  myNeedsCollisionCheck = true;
1806  bool wasInactive = myVehicles.size() == 0;
1807  sort(myVehBuffer.begin(), myVehBuffer.end(), vehicle_position_sorter(this));
1808  for (std::vector<MSVehicle*>::const_iterator i = myVehBuffer.begin(); i != myVehBuffer.end(); ++i) {
1809  MSVehicle* veh = *i;
1810  assert(veh->getLane() == this);
1811  myVehicles.insert(myVehicles.begin(), veh);
1814  //if (true) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " veh=" << veh->getID() << " (on lane " << veh->getLane()->getID() << ") into lane=" << getID() << " myBrutto=" << myBruttoVehicleLengthSum << "\n";
1815  myEdge->markDelayed();
1816  }
1817  myVehBuffer.clear();
1818  //std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " myVehicles1=" << toString(myVehicles);
1819  if (MSGlobals::gLateralResolution > 0 || myNeighs.size() > 0) {
1820  sort(myVehicles.begin(), myVehicles.end(), vehicle_natural_position_sorter(this));
1821  }
1823 #ifdef DEBUG_VEHICLE_CONTAINER
1824  if (DEBUG_COND) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID()
1825  << " vhicles=" << toString(myVehicles) << " partials=" << toString(myPartialVehicles) << "\n";
1826 #endif
1827  return wasInactive && myVehicles.size() != 0;
1828 }
1829 
1830 
1831 void
1833  if (myPartialVehicles.size() > 1) {
1835  }
1836 }
1837 
1838 
1839 void
1841  if (myManeuverReservations.size() > 1) {
1842 #ifdef DEBUG_CONTEXT
1843  if DEBUG_COND {
1844  std::cout << "sortManeuverReservations on lane " << getID()
1845  << "\nBefore sort: " << toString(myManeuverReservations) << std::endl;
1846  }
1847 #endif
1849 #ifdef DEBUG_CONTEXT
1850  if DEBUG_COND {
1851  std::cout << "After sort: " << toString(myManeuverReservations) << std::endl;
1852  }
1853 #endif
1854  }
1855 }
1856 
1857 
1858 bool
1859 MSLane::isLinkEnd(MSLinkCont::const_iterator& i) const {
1860  return i == myLinks.end();
1861 }
1862 
1863 
1864 bool
1865 MSLane::isLinkEnd(MSLinkCont::iterator& i) {
1866  return i == myLinks.end();
1867 }
1868 
1869 bool
1871  return myVehicles.empty() && myPartialVehicles.empty();
1872 }
1873 
1874 bool
1876  return myEdge->isInternal();
1877 }
1878 
1879 MSVehicle*
1881  if (myVehicles.size() == 0) {
1882  return nullptr;
1883  }
1884  return myVehicles.front();
1885 }
1886 
1887 
1888 MSVehicle*
1890  if (myVehicles.size() == 0) {
1891  return nullptr;
1892  }
1893  return myVehicles.back();
1894 }
1895 
1896 
1897 MSVehicle*
1899  // all vehicles in myVehicles should have positions smaller or equal to
1900  // those in myPartialVehicles
1901  if (myVehicles.size() > 0) {
1902  return myVehicles.front();
1903  }
1904  if (myPartialVehicles.size() > 0) {
1905  return myPartialVehicles.front();
1906  }
1907  return nullptr;
1908 }
1909 
1910 
1911 MSVehicle*
1913  MSVehicle* result = nullptr;
1914  if (myVehicles.size() > 0) {
1915  result = myVehicles.back();
1916  }
1917  if (myPartialVehicles.size() > 0
1918  && (result == nullptr || result->getPositionOnLane(this) < myPartialVehicles.back()->getPositionOnLane(this))) {
1919  result = myPartialVehicles.back();
1920  }
1921  return result;
1922 }
1923 
1924 
1925 MSLinkCont::const_iterator
1926 MSLane::succLinkSec(const SUMOVehicle& veh, int nRouteSuccs,
1927  const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
1928  const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
1929  // check whether the vehicle tried to look beyond its route
1930  if (nRouteEdge == nullptr) {
1931  // return end (no succeeding link) if so
1932  return succLinkSource.myLinks.end();
1933  }
1934  // if we are on an internal lane there should only be one link and it must be allowed
1935  if (succLinkSource.isInternal()) {
1936  assert(succLinkSource.myLinks.size() == 1);
1937  // could have been disallowed dynamically with a rerouter or via TraCI
1938  // assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
1939  return succLinkSource.myLinks.begin();
1940  }
1941  // a link may be used if
1942  // 1) there is a destination lane ((*link)->getLane()!=0)
1943  // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
1944  // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
1945 
1946  // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
1947  // "conts" stores the best continuations of our current lane
1948  // we should never return an arbitrary link since this may cause collisions
1949 
1950  MSLinkCont::const_iterator link;
1951  if (nRouteSuccs < (int)conts.size()) {
1952  // we go through the links in our list and return the matching one
1953  for (link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
1954  if ((*link)->getLane() != nullptr && (*link)->getLane()->myEdge == nRouteEdge && (*link)->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
1955  // we should use the link if it connects us to the best lane
1956  if ((*link)->getLane() == conts[nRouteSuccs]) {
1957  return link;
1958  }
1959  }
1960  }
1961  } else {
1962  // the source lane is a dead end (no continuations exist)
1963  return succLinkSource.myLinks.end();
1964  }
1965  // the only case where this should happen is for a disconnected route (deliberately ignored)
1966 #ifdef DEBUG_NO_CONNECTION
1967  // the "'" around the ids are missing intentionally in the message below because it slows messaging down, resulting in test timeouts
1968  WRITE_WARNING("Could not find connection between lane " + succLinkSource.getID() + " and lane " + conts[nRouteSuccs]->getID() +
1969  " for vehicle " + veh.getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1970 #endif
1971  return succLinkSource.myLinks.end();
1972 }
1973 
1974 const MSLinkCont&
1976  return myLinks;
1977 }
1978 
1979 
1981 MSLink*
1982 MSLane::getLinkTo(const MSLane* target) const {
1983  MSLinkCont::const_iterator l = myLinks.begin();
1984  if (target->isInternal()) {
1985  while (l != myLinks.end()) {
1986  if ((*l)->getViaLane()->getID() == target->getID()) {
1987  return *l;
1988  }
1989  ++l;
1990  }
1991  } else {
1992  while (l != myLinks.end()) {
1993  if ((*l)->getLane()->getID() == target->getID()) {
1994  return *l;
1995  }
1996  ++l;
1997  }
1998  }
1999  return nullptr;
2000 }
2001 
2002 MSLink*
2004  if (!isInternal()) {
2005  return nullptr;
2006  }
2007  const MSLane* internal = this;
2008  const MSLane* lane = this->getCanonicalPredecessorLane();
2009  assert(lane != 0);
2010  while (lane->isInternal()) {
2011  internal = lane;
2012  lane = lane->getCanonicalPredecessorLane();
2013  assert(lane != 0);
2014  }
2015  return lane->getLinkTo(internal);
2016 }
2017 
2018 
2019 void
2020 MSLane::setMaxSpeed(double val) {
2021  myMaxSpeed = val;
2022  myEdge->recalcCache();
2023 }
2024 
2025 
2026 void
2027 MSLane::setLength(double val) {
2028  myLength = val;
2029  myEdge->recalcCache();
2030 }
2031 
2032 
2033 void
2035  //if (getID() == "disabled_lane") std::cout << SIMTIME << " swapAfterLaneChange lane=" << getID() << " myVehicles=" << toString(myVehicles) << " myTmpVehicles=" << toString(myTmpVehicles) << "\n";
2037  myTmpVehicles.clear();
2038  // this needs to be done after finishing lane-changing for all lanes on the
2039  // current edge (MSLaneChanger::updateLanes())
2041 }
2042 
2043 
2044 MSVehicle*
2045 MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
2046  assert(remVehicle->getLane() == this);
2047  for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
2048  if (remVehicle == *it) {
2049  if (notify) {
2050  remVehicle->leaveLane(notification);
2051  }
2052  myVehicles.erase(it);
2055  break;
2056  }
2057  }
2058  return remVehicle;
2059 }
2060 
2061 
2062 MSLane*
2063 MSLane::getParallelLane(int offset) const {
2064  return myEdge->parallelLane(this, offset);
2065 }
2066 
2067 
2068 void
2070  IncomingLaneInfo ili;
2071  ili.lane = lane;
2072  ili.viaLink = viaLink;
2073  ili.length = lane->getLength();
2074  myIncomingLanes.push_back(ili);
2075 }
2076 
2077 
2078 void
2079 MSLane::addApproachingLane(MSLane* lane, bool warnMultiCon) {
2080  MSEdge* approachingEdge = &lane->getEdge();
2081  if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
2082  myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
2083  } else if (!approachingEdge->isInternal() && warnMultiCon) {
2084  // whenever a normal edge connects twice, there is a corresponding
2085  // internal edge wich connects twice, one warning is sufficient
2086  WRITE_WARNING("Lane '" + getID() + "' is approached multiple times from edge '" + approachingEdge->getID() + "'. This may cause collisions.");
2087  }
2088  myApproachingLanes[approachingEdge].push_back(lane);
2089 }
2090 
2091 
2092 bool
2094  return myApproachingLanes.find(edge) != myApproachingLanes.end();
2095 }
2096 
2097 
2098 bool
2099 MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
2100  std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
2101  if (i == myApproachingLanes.end()) {
2102  return false;
2103  }
2104  const std::vector<MSLane*>& lanes = (*i).second;
2105  return find(lanes.begin(), lanes.end(), lane) != lanes.end();
2106 }
2107 
2108 
2110 public:
2111  inline int operator()(const std::pair<const MSVehicle*, double>& p1, const std::pair<const MSVehicle*, double>& p2) const {
2112  return p1.second < p2.second;
2113  }
2114 };
2115 
2116 
2117 double MSLane::getMissingRearGap(const MSVehicle* leader, double backOffset, double leaderSpeed) const {
2118  // this follows the same logic as getFollowerOnConsecutive. we do a tree
2119  // search and check for the vehicle with the largest missing rear gap within
2120  // relevant range
2121  double result = 0;
2122  const double leaderDecel = leader->getCarFollowModel().getMaxDecel();
2123  CLeaderDist followerInfo = getFollowersOnConsecutive(leader, backOffset, false)[0];
2124  const MSVehicle* v = followerInfo.first;
2125  if (v != nullptr) {
2126  result = v->getCarFollowModel().getSecureGap(v->getSpeed(), leaderSpeed, leaderDecel) - followerInfo.second;
2127  }
2128  return result;
2129 }
2130 
2131 
2132 double
2135  const double maxSpeed = getSpeedLimit() * vc.getMaxSpeedFactor();
2136  // NOTE: For the euler update this is an upper bound on the actual braking distance (see ticket #860)
2137  return maxSpeed * maxSpeed * 0.5 / vc.getMinDeceleration();
2138 }
2139 
2140 
2141 
2142 std::pair<MSVehicle* const, double>
2143 MSLane::getLeader(const MSVehicle* veh, const double vehPos, const std::vector<MSLane*>& bestLaneConts, double dist, bool checkTmpVehicles) const {
2144  // get the leading vehicle for (shadow) veh
2145  // XXX this only works as long as all lanes of an edge have equal length
2146 #ifdef DEBUG_CONTEXT
2147  if (DEBUG_COND2(veh)) {
2148  std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " vehs=" << toString(myVehicles) << " tmpVehs=" << toString(myTmpVehicles) << "\n";
2149  }
2150 #endif
2151  if (checkTmpVehicles) {
2152  for (VehCont::const_iterator last = myTmpVehicles.begin(); last != myTmpVehicles.end(); ++last) {
2153  // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2154  MSVehicle* pred = (MSVehicle*)*last;
2155  if (pred == veh) {
2156  continue;
2157  }
2158 #ifdef DEBUG_CONTEXT
2159  if (DEBUG_COND2(veh)) {
2160  std::cout << std::setprecision(gPrecision) << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
2161  }
2162 #endif
2163  if (pred->getPositionOnLane() >= vehPos) {
2164  return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2165  }
2166  }
2167  } else {
2168  for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
2169  // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2170  MSVehicle* pred = (MSVehicle*)*last;
2171  if (pred == veh) {
2172  continue;
2173  }
2174 #ifdef DEBUG_CONTEXT
2175  if (DEBUG_COND2(veh)) {
2176  std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos
2177  << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << " predBack=" << pred->getBackPositionOnLane(this) << "\n";
2178  }
2179 #endif
2180  if (pred->getPositionOnLane(this) >= vehPos) {
2181  return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2182  }
2183  }
2184  }
2185  // XXX from here on the code mirrors MSLaneChanger::getRealLeader
2186  if (bestLaneConts.size() > 0) {
2187  double seen = getLength() - vehPos;
2188  double speed = veh->getSpeed();
2189  if (dist < 0) {
2190  dist = veh->getCarFollowModel().brakeGap(speed) + veh->getVehicleType().getMinGap();
2191  }
2192 #ifdef DEBUG_CONTEXT
2193  if (DEBUG_COND2(veh)) {
2194  std::cout << " getLeader lane=" << getID() << " seen=" << seen << " dist=" << dist << "\n";
2195  }
2196 #endif
2197  if (seen > dist) {
2198  return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
2199  }
2200  return getLeaderOnConsecutive(dist, seen, speed, *veh, bestLaneConts);
2201  } else {
2202  return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2203  }
2204 }
2205 
2206 
2207 std::pair<MSVehicle* const, double>
2208 MSLane::getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle& veh,
2209  const std::vector<MSLane*>& bestLaneConts) const {
2210 #ifdef DEBUG_CONTEXT
2211  if (DEBUG_COND2(&veh)) {
2212  std::cout << " getLeaderOnConsecutive lane=" << getID() << " ego=" << veh.getID() << " seen=" << seen << " dist=" << dist << " conts=" << toString(bestLaneConts) << "\n";
2213  }
2214 #endif
2215  if (seen > dist && !isInternal()) {
2216  return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2217  }
2218  int view = 1;
2219  // loop over following lanes
2220  if (myPartialVehicles.size() > 0) {
2221  // XXX
2222  MSVehicle* pred = myPartialVehicles.front();
2223  const double gap = seen - (getLength() - pred->getBackPositionOnLane(this)) - veh.getVehicleType().getMinGap();
2224 #ifdef DEBUG_CONTEXT
2225  if (DEBUG_COND2(&veh)) {
2226  std::cout << " predGap=" << gap << " partials=" << toString(myPartialVehicles) << "\n";
2227  }
2228 #endif
2229  // make sure pred is really a leader and not doing continous lane-changing behind ego
2230  if (gap > 0) {
2231  return std::pair<MSVehicle* const, double>(pred, gap);
2232  }
2233  }
2234  const MSLane* nextLane = this;
2235  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
2236  do {
2237  nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
2238  // get the next link used
2239  MSLinkCont::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
2240  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
2241  veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane()) || (*link)->haveRed()) {
2242 #ifdef DEBUG_CONTEXT
2243  if (DEBUG_COND2(&veh)) {
2244  std::cout << " cannot continue after nextLane=" << nextLane->getID() << "\n";
2245  }
2246 #endif
2247  nextLane->releaseVehicles();
2248  break;
2249  }
2250  // check for link leaders
2251 #ifdef DEBUG_CONTEXT
2252  if (DEBUG_COND2(&veh)) {
2253  gDebugFlag1 = true;
2254  }
2255 #endif
2256  const bool laneChanging = veh.getLane() != this;
2257  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
2258 #ifdef DEBUG_CONTEXT
2259  gDebugFlag1 = false;
2260 #endif
2261  nextLane->releaseVehicles();
2262  if (linkLeaders.size() > 0) {
2263  std::pair<MSVehicle*, double> result;
2264  double shortestGap = std::numeric_limits<double>::max();
2265  for (auto ll : linkLeaders) {
2266  double gap = ll.vehAndGap.second;
2267  MSVehicle* lVeh = ll.vehAndGap.first;
2268  if (lVeh != nullptr) {
2269  // leader is a vehicle, not a pedestrian
2270  gap += lVeh->getCarFollowModel().brakeGap(lVeh->getSpeed(), lVeh->getCarFollowModel().getMaxDecel(), 0);
2271  }
2272 #ifdef DEBUG_CONTEXT
2273  if (DEBUG_COND2(&veh)) {
2274  std::cout << " linkLeader candidate " << Named::getIDSecure(lVeh)
2275  << " isLeader=" << veh.isLeader(*link, lVeh)
2276  << " gap=" << ll.vehAndGap.second
2277  << " gap+brakeing=" << gap
2278  << "\n";
2279  }
2280 #endif
2281  // in the context of lane-changing, all candidates are leaders
2282  if (lVeh != nullptr && !laneChanging && !veh.isLeader(*link, lVeh)) {
2283  continue;
2284  }
2285  if (gap < shortestGap) {
2286  shortestGap = gap;
2287  result = ll.vehAndGap;
2288  }
2289  }
2290  if (shortestGap != std::numeric_limits<double>::max()) {
2291 #ifdef DEBUG_CONTEXT
2292  if (DEBUG_COND2(&veh)) {
2293  std::cout << " found linkLeader after nextLane=" << nextLane->getID() << "\n";
2294  }
2295 #endif
2296  return result;
2297  }
2298  }
2299  bool nextInternal = (*link)->getViaLane() != nullptr;
2300  nextLane = (*link)->getViaLaneOrLane();
2301  if (nextLane == nullptr) {
2302  break;
2303  }
2304  nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
2305  MSVehicle* leader = nextLane->getLastAnyVehicle();
2306  if (leader != nullptr) {
2307 #ifdef DEBUG_CONTEXT
2308  if (DEBUG_COND2(&veh)) {
2309  std::cout << " found leader " << leader->getID() << " on nextLane=" << nextLane->getID() << "\n";
2310  }
2311 #endif
2312  const double dist = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
2313  nextLane->releaseVehicles();
2314  return std::make_pair(leader, dist);
2315  }
2316  nextLane->releaseVehicles();
2317  if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
2318  dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
2319  }
2320  seen += nextLane->getLength();
2321  if (seen <= dist) {
2322  // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
2323  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
2324  }
2325  if (!nextInternal) {
2326  view++;
2327  }
2328  } while (seen <= dist || nextLane->isInternal());
2329  return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2330 }
2331 
2332 
2333 std::pair<MSVehicle* const, double>
2334 MSLane::getCriticalLeader(double dist, double seen, double speed, const MSVehicle& veh) const {
2335 #ifdef DEBUG_CONTEXT
2336  if (DEBUG_COND2(&veh)) {
2337  std::cout << SIMTIME << " getCriticalLeader. lane=" << getID() << " veh=" << veh.getID() << "\n";
2338  }
2339 #endif
2340  const std::vector<MSLane*>& bestLaneConts = veh.getBestLanesContinuation(this);
2341  std::pair<MSVehicle*, double> result = std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2342  double safeSpeed = std::numeric_limits<double>::max();
2343  int view = 1;
2344  // loop over following lanes
2345  // @note: we don't check the partial occupator for this lane since it was
2346  // already checked in MSLaneChanger::getRealLeader()
2347  const MSLane* nextLane = this;
2348  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
2349  do {
2350  // get the next link used
2351  MSLinkCont::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
2352  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
2353  veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane()) || (*link)->haveRed()) {
2354  return result;
2355  }
2356  // check for link leaders
2357  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
2358  for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
2359  const MSVehicle* leader = (*it).vehAndGap.first;
2360  if (leader != nullptr && leader != result.first) {
2361  // XXX ignoring pedestrians here!
2362  // XXX ignoring the fact that the link leader may alread by following us
2363  // XXX ignoring the fact that we may drive up to the crossing point
2364  const double tmpSpeed = veh.getSafeFollowSpeed((*it).vehAndGap, seen, nextLane, (*it).distToCrossing);
2365 #ifdef DEBUG_CONTEXT
2366  if (DEBUG_COND2(&veh)) {
2367  std::cout << " linkLeader=" << leader->getID() << " gap=" << result.second << " tmpSpeed=" << tmpSpeed << " safeSpeed=" << safeSpeed << "\n";
2368  }
2369 #endif
2370  if (tmpSpeed < safeSpeed) {
2371  safeSpeed = tmpSpeed;
2372  result = (*it).vehAndGap;
2373  }
2374  }
2375  }
2376  bool nextInternal = (*link)->getViaLane() != nullptr;
2377  nextLane = (*link)->getViaLaneOrLane();
2378  if (nextLane == nullptr) {
2379  break;
2380  }
2381  MSVehicle* leader = nextLane->getLastAnyVehicle();
2382  if (leader != nullptr && leader != result.first) {
2383  const double gap = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
2384  const double tmpSpeed = veh.getCarFollowModel().insertionFollowSpeed(leader, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
2385  if (tmpSpeed < safeSpeed) {
2386  safeSpeed = tmpSpeed;
2387  result = std::make_pair(leader, gap);
2388  }
2389  }
2390  if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
2391  dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
2392  }
2393  seen += nextLane->getLength();
2394  if (seen <= dist) {
2395  // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
2396  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
2397  }
2398  if (!nextInternal) {
2399  view++;
2400  }
2401  } while (seen <= dist || nextLane->isInternal());
2402  return result;
2403 }
2404 
2405 
2406 MSLane*
2408  if (myLogicalPredecessorLane == nullptr) {
2410  // get only those edges which connect to this lane
2411  for (MSEdgeVector::iterator i = pred.begin(); i != pred.end();) {
2412  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
2413  if (j == myIncomingLanes.end()) {
2414  i = pred.erase(i);
2415  } else {
2416  ++i;
2417  }
2418  }
2419  // get the lane with the "straightest" connection
2420  if (pred.size() != 0) {
2421  std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
2422  MSEdge* best = *pred.begin();
2423  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
2424  myLogicalPredecessorLane = j->lane;
2425  }
2426  }
2427  return myLogicalPredecessorLane;
2428 }
2429 
2430 
2431 MSLane*
2433  for (std::vector<IncomingLaneInfo>::const_iterator i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
2434  MSLane* cand = (*i).lane;
2435  if (&(cand->getEdge()) == &fromEdge) {
2436  return (*i).lane;
2437  }
2438  }
2439  return nullptr;
2440 }
2441 
2442 MSLane*
2444  if (myCanonicalPredecessorLane != nullptr) {
2446  }
2447  if (myIncomingLanes.size() == 0) {
2448  return nullptr;
2449  }
2450  // myCanonicalPredecessorLane has not yet been determined and there exist incoming lanes
2451  std::vector<IncomingLaneInfo> candidateLanes = myIncomingLanes;
2452  // get the lane with the priorized (or if this does not apply the "straightest") connection
2453  std::sort(candidateLanes.begin(), candidateLanes.end(), incoming_lane_priority_sorter(this));
2454  IncomingLaneInfo best = *(candidateLanes.begin());
2455 #ifdef DEBUG_LANE_SORTER
2456  std::cout << "\nBest predecessor lane for lane '" << myID << "': '" << best.lane->getID() << "'" << std::endl;
2457 #endif
2458  myCanonicalPredecessorLane = best.lane;
2460 }
2461 
2462 MSLane*
2464  if (myCanonicalSuccessorLane != nullptr) {
2465  return myCanonicalSuccessorLane;
2466  }
2467  if (myLinks.size() == 0) {
2468  return nullptr;
2469  }
2470  // myCanonicalSuccessorLane has not yet been determined and there exist outgoing links
2471  std::vector<MSLink*> candidateLinks = myLinks;
2472  // get the lane with the priorized (or if this does not apply the "straightest") connection
2473  std::sort(candidateLinks.begin(), candidateLinks.end(), outgoing_lane_priority_sorter(this));
2474  MSLane* best = (*candidateLinks.begin())->getViaLaneOrLane();
2475 #ifdef DEBUG_LANE_SORTER
2476  std::cout << "\nBest successor lane for lane '" << myID << "': '" << best->getID() << "'" << std::endl;
2477 #endif
2478  myCanonicalSuccessorLane = best;
2479  return myCanonicalSuccessorLane;
2480 }
2481 
2482 
2483 LinkState
2486  if (pred == nullptr) {
2487  return LINKSTATE_DEADEND;
2488  } else {
2489  return MSLinkContHelper::getConnectingLink(*pred, *this)->getState();
2490  }
2491 }
2492 
2493 
2494 const std::vector<std::pair<const MSLane*, const MSEdge*> >
2496  std::vector<std::pair<const MSLane*, const MSEdge*> > result;
2497  for (const MSLink* link : myLinks) {
2498  assert(link->getLane() != nullptr);
2499  result.push_back(std::make_pair(link->getLane(), link->getViaLane() == nullptr ? nullptr : &link->getViaLane()->getEdge()));
2500  }
2501  return result;
2502 }
2503 
2504 
2505 void
2509 }
2510 
2511 
2512 void
2516 }
2517 
2518 
2519 int
2521  for (MSLinkCont::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
2522  if ((*i)->getLane()->getEdge().isCrossing()) {
2523  return (int)(i - myLinks.begin());
2524  }
2525  }
2526  return -1;
2527 }
2528 
2529 // ------------ Current state retrieval
2530 double
2532  double fractions = myPartialVehicles.size() > 0 ? MIN2(myLength, myLength - myPartialVehicles.front()->getBackPositionOnLane(this)) : 0;
2534  if (myVehicles.size() != 0) {
2535  MSVehicle* lastVeh = myVehicles.front();
2536  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
2537  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
2538  }
2539  }
2540  releaseVehicles();
2541  return MIN2(1., (myBruttoVehicleLengthSum + fractions) / myLength);
2542 }
2543 
2544 
2545 double
2547  double fractions = myPartialVehicles.size() > 0 ? MIN2(myLength, myLength - myPartialVehicles.front()->getBackPositionOnLane(this)) : 0;
2549  if (myVehicles.size() != 0) {
2550  MSVehicle* lastVeh = myVehicles.front();
2551  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
2552  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
2553  }
2554  }
2555  releaseVehicles();
2556  return (myNettoVehicleLengthSum + fractions) / myLength;
2557 }
2558 
2559 
2560 double
2562  if (myVehicles.size() == 0) {
2563  return 0;
2564  }
2565  double wtime = 0;
2566  for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
2567  wtime += (*i)->getWaitingSeconds();
2568  }
2569  return wtime;
2570 }
2571 
2572 
2573 double
2575  if (myVehicles.size() == 0) {
2576  return myMaxSpeed;
2577  }
2578  double v = 0;
2579  const MSLane::VehCont& vehs = getVehiclesSecure();
2580  for (VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2581  v += (*i)->getSpeed();
2582  }
2583  double ret = v / (double) myVehicles.size();
2584  releaseVehicles();
2585  return ret;
2586 }
2587 
2588 
2589 double
2591  double ret = 0;
2592  const MSLane::VehCont& vehs = getVehiclesSecure();
2593  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2594  ret += (*i)->getCO2Emissions();
2595  }
2596  releaseVehicles();
2597  return ret;
2598 }
2599 
2600 
2601 double
2603  double ret = 0;
2604  const MSLane::VehCont& vehs = getVehiclesSecure();
2605  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2606  ret += (*i)->getCOEmissions();
2607  }
2608  releaseVehicles();
2609  return ret;
2610 }
2611 
2612 
2613 double
2615  double ret = 0;
2616  const MSLane::VehCont& vehs = getVehiclesSecure();
2617  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2618  ret += (*i)->getPMxEmissions();
2619  }
2620  releaseVehicles();
2621  return ret;
2622 }
2623 
2624 
2625 double
2627  double ret = 0;
2628  const MSLane::VehCont& vehs = getVehiclesSecure();
2629  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2630  ret += (*i)->getNOxEmissions();
2631  }
2632  releaseVehicles();
2633  return ret;
2634 }
2635 
2636 
2637 double
2639  double ret = 0;
2640  const MSLane::VehCont& vehs = getVehiclesSecure();
2641  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2642  ret += (*i)->getHCEmissions();
2643  }
2644  releaseVehicles();
2645  return ret;
2646 }
2647 
2648 
2649 double
2651  double ret = 0;
2652  const MSLane::VehCont& vehs = getVehiclesSecure();
2653  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2654  ret += (*i)->getFuelConsumption();
2655  }
2656  releaseVehicles();
2657  return ret;
2658 }
2659 
2660 
2661 double
2663  double ret = 0;
2664  const MSLane::VehCont& vehs = getVehiclesSecure();
2665  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2666  ret += (*i)->getElectricityConsumption();
2667  }
2668  releaseVehicles();
2669  return ret;
2670 }
2671 
2672 
2673 double
2675  double ret = 0;
2676  const MSLane::VehCont& vehs = getVehiclesSecure();
2677  if (vehs.size() == 0) {
2678  releaseVehicles();
2679  return 0;
2680  }
2681  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2682  double sv = (*i)->getHarmonoise_NoiseEmissions();
2683  ret += (double) pow(10., (sv / 10.));
2684  }
2685  releaseVehicles();
2686  return HelpersHarmonoise::sum(ret);
2687 }
2688 
2689 
2690 bool
2691 MSLane::VehPosition::operator()(const MSVehicle* cmp, double pos) const {
2692  return cmp->getPositionOnLane() >= pos;
2693 }
2694 
2695 
2696 int
2698  return v1->getBackPositionOnLane(myLane) > v2->getBackPositionOnLane(myLane);
2699 }
2700 
2701 int
2703  const double pos1 = v1->getBackPositionOnLane(myLane);
2704  const double pos2 = v2->getBackPositionOnLane(myLane);
2705  if (pos1 != pos2) {
2706  return pos1 < pos2;
2707  } else {
2709  }
2710 }
2711 
2713  myEdge(e),
2714  myLaneDir(e->getLanes()[0]->getShape().angleAt2D(0)) {
2715 }
2716 
2717 
2718 int
2719 MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
2720 // std::cout << "\nby_connections_to_sorter()";
2721 
2722  const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
2723  const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
2724  double s1 = 0;
2725  if (ae1 != nullptr && ae1->size() != 0) {
2726 // std::cout << "\nsize 1 = " << ae1->size()
2727 // << " anglediff 1 = " << fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
2728 // << "\nallowed lanes: ";
2729 // for (std::vector<MSLane*>::const_iterator j = ae1->begin(); j != ae1->end(); ++j){
2730 // std::cout << "\n" << (*j)->getID();
2731 // }
2732  s1 = (double) ae1->size() + fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
2733  }
2734  double s2 = 0;
2735  if (ae2 != nullptr && ae2->size() != 0) {
2736 // std::cout << "\nsize 2 = " << ae2->size()
2737 // << " anglediff 2 = " << fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
2738 // << "\nallowed lanes: ";
2739 // for (std::vector<MSLane*>::const_iterator j = ae2->begin(); j != ae2->end(); ++j){
2740 // std::cout << "\n" << (*j)->getID();
2741 // }
2742  s2 = (double) ae2->size() + fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
2743  }
2744 
2745 // std::cout << "\ne1 = " << e1->getID() << " e2 = " << e2->getID()
2746 // << "\ns1 = " << s1 << " s2 = " << s2
2747 // << std::endl;
2748 
2749  return s1 < s2;
2750 }
2751 
2752 
2754  myLane(targetLane),
2755  myLaneDir(targetLane->getShape().angleAt2D(0)) {}
2756 
2757 int
2759  const MSLane* noninternal1 = laneInfo1.lane;
2760  while (noninternal1->isInternal()) {
2761  assert(noninternal1->getIncomingLanes().size() == 1);
2762  noninternal1 = noninternal1->getIncomingLanes()[0].lane;
2763  }
2764  MSLane* noninternal2 = laneInfo2.lane;
2765  while (noninternal2->isInternal()) {
2766  assert(noninternal2->getIncomingLanes().size() == 1);
2767  noninternal2 = noninternal2->getIncomingLanes()[0].lane;
2768  }
2769 
2770  MSLink* link1 = noninternal1->getLinkTo(myLane);
2771  MSLink* link2 = noninternal2->getLinkTo(myLane);
2772 
2773 #ifdef DEBUG_LANE_SORTER
2774  std::cout << "\nincoming_lane_priority sorter()\n"
2775  << "noninternal predecessor for lane '" << laneInfo1.lane->getID()
2776  << "': '" << noninternal1->getID() << "'\n"
2777  << "noninternal predecessor for lane '" << laneInfo2.lane->getID()
2778  << "': '" << noninternal2->getID() << "'\n";
2779 #endif
2780 
2781  assert(laneInfo1.lane->isInternal() || link1 == laneInfo1.viaLink);
2782  assert(link1 != 0);
2783  assert(link2 != 0);
2784 
2785  // check priority between links
2786  bool priorized1 = true;
2787  bool priorized2 = true;
2788 
2789  std::vector<MSLink*>::const_iterator j;
2790 #ifdef DEBUG_LANE_SORTER
2791  std::cout << "FoeLinks of '" << noninternal1->getID() << "'" << std::endl;
2792 #endif
2793  for (j = link1->getFoeLinks().begin(); j != link1->getFoeLinks().end(); ++j) {
2794 #ifdef DEBUG_LANE_SORTER
2795  std::cout << (*j)->getLaneBefore()->getID() << std::endl;
2796 #endif
2797  if (*j == link2) {
2798  priorized1 = false;
2799  break;
2800  }
2801  }
2802 
2803 #ifdef DEBUG_LANE_SORTER
2804  std::cout << "FoeLinks of '" << noninternal2->getID() << "'" << std::endl;
2805 #endif
2806  for (j = link2->getFoeLinks().begin(); j != link2->getFoeLinks().end(); ++j) {
2807 #ifdef DEBUG_LANE_SORTER
2808  std::cout << (*j)->getLaneBefore()->getID() << std::endl;
2809 #endif
2810  // either link1 is priorized, or it should not appear in link2's foes
2811  if (*j == link2) {
2812  priorized2 = false;
2813  break;
2814  }
2815  }
2816  // if one link is subordinate, the other must be priorized
2817  assert(priorized1 || priorized2);
2818  if (priorized1 != priorized2) {
2819  return priorized1;
2820  }
2821 
2822  // both are priorized, compare angle difference
2823  double d1 = fabs(GeomHelper::angleDiff(noninternal1->getShape().angleAt2D(0), myLaneDir));
2824  double d2 = fabs(GeomHelper::angleDiff(noninternal2->getShape().angleAt2D(0), myLaneDir));
2825 
2826  return d2 > d1;
2827 }
2828 
2829 
2830 
2832  myLane(sourceLane),
2833  myLaneDir(sourceLane->getShape().angleAt2D(0)) {}
2834 
2835 int
2837  const MSLane* target1 = link1->getLane();
2838  const MSLane* target2 = link2->getLane();
2839  if (target2 == nullptr) {
2840  return true;
2841  }
2842  if (target1 == nullptr) {
2843  return false;
2844  }
2845 
2846 #ifdef DEBUG_LANE_SORTER
2847  std::cout << "\noutgoing_lane_priority sorter()\n"
2848  << "noninternal successors for lane '" << myLane->getID()
2849  << "': '" << target1->getID() << "' and "
2850  << "'" << target2->getID() << "'\n";
2851 #endif
2852 
2853  // priority of targets
2854  int priority1 = target1->getEdge().getPriority();
2855  int priority2 = target2->getEdge().getPriority();
2856 
2857  if (priority1 != priority2) {
2858  return priority1 > priority2;
2859  }
2860 
2861  // if priority of targets coincides, use angle difference
2862 
2863  // both are priorized, compare angle difference
2864  double d1 = fabs(GeomHelper::angleDiff(target1->getShape().angleAt2D(0), myLaneDir));
2865  double d2 = fabs(GeomHelper::angleDiff(target2->getShape().angleAt2D(0), myLaneDir));
2866 
2867  return d2 > d1;
2868 }
2869 
2870 void
2872  myParkingVehicles.insert(veh);
2873 }
2874 
2875 
2876 void
2878  myParkingVehicles.erase(veh);
2879 }
2880 
2881 void
2883  out.openTag(SUMO_TAG_LANE);
2884  out.writeAttr("id", getID()); // using "id" instead of SUMO_ATTR_ID makes the value only show up in xml state
2887  out.closeTag();
2888  out.closeTag();
2889 }
2890 
2891 
2892 void
2893 MSLane::loadState(std::vector<std::string>& vehIds, MSVehicleControl& vc) {
2894  for (std::vector<std::string>::const_iterator it = vehIds.begin(); it != vehIds.end(); ++it) {
2895  MSVehicle* v = dynamic_cast<MSVehicle*>(vc.getVehicle(*it));
2896  // vehicle could be removed due to options
2897  if (v != nullptr) {
2898  v->updateBestLanes(false, this);
2901  v->processNextStop(v->getSpeed());
2902  }
2903  }
2904 }
2905 
2906 
2907 double
2909  if (myStopOffsets.size() == 0) {
2910  return 0.;
2911  }
2912  if ((myStopOffsets.begin()->first & veh->getVClass()) != 0) {
2913  return myStopOffsets.begin()->second;
2914  } else {
2915  return 0.;
2916  }
2917 }
2918 
2919 
2920 
2922 MSLane::getFollowersOnConsecutive(const MSVehicle* ego, double backOffset,
2923  bool allSublanes, double searchDist, bool ignoreMinorLinks) const {
2924  // get the follower vehicle on the lane to change to
2925  const double egoPos = backOffset + ego->getVehicleType().getLength();
2926 #ifdef DEBUG_CONTEXT
2927  if (DEBUG_COND2(ego)) {
2928  std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
2929  << " backOffset=" << backOffset << " pos=" << egoPos
2930  << " allSub=" << allSublanes << " searchDist=" << searchDist << " ignoreMinor=" << ignoreMinorLinks
2931  << "\n";
2932  }
2933 #endif
2934  assert(ego != 0);
2935  const double egoLatDist = ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
2936  MSCriticalFollowerDistanceInfo result(this, allSublanes ? nullptr : ego, allSublanes ? 0 : egoLatDist);
2938  for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
2939  const MSVehicle* veh = *last;
2940 #ifdef DEBUG_CONTEXT
2941  if (DEBUG_COND2(ego)) {
2942  std::cout << " veh=" << veh->getID() << " lane=" << veh->getLane()->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
2943  }
2944 #endif
2945  if (veh != ego && veh->getPositionOnLane(this) < egoPos) {
2946  //const double latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
2947  const double latOffset = veh->getLatOffset(this);
2948  const double dist = backOffset - veh->getPositionOnLane(this) - veh->getVehicleType().getMinGap();
2949  result.addFollower(veh, ego, dist, latOffset);
2950 #ifdef DEBUG_CONTEXT
2951  if (DEBUG_COND2(ego)) {
2952  std::cout << " (1) added veh=" << veh->getID() << " latOffset=" << latOffset << " result=" << result.toString() << "\n";
2953  }
2954 #endif
2955  }
2956  }
2957 #ifdef DEBUG_CONTEXT
2958  if (DEBUG_COND2(ego)) {
2959  std::cout << " result.numFreeSublanes=" << result.numFreeSublanes() << "\n";
2960  }
2961 #endif
2962  if (result.numFreeSublanes() > 0) {
2963  // do a tree search among all follower lanes and check for the most
2964  // important vehicle (the one requiring the largest reargap)
2965  // to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
2966  // deceleration of potential follower vehicles
2967  if (searchDist == -1) {
2968  searchDist = getMaximumBrakeDist() - backOffset;
2969  }
2970 
2971  std::set<MSLane*> visited;
2972  std::vector<MSLane::IncomingLaneInfo> newFound;
2973  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
2974  while (toExamine.size() != 0) {
2975  for (std::vector<MSLane::IncomingLaneInfo>::iterator it = toExamine.begin(); it != toExamine.end(); ++it) {
2976  MSLane* next = (*it).lane;
2977  searchDist = MAX2(searchDist, next->getMaximumBrakeDist() - backOffset);
2978  MSLeaderInfo first = next->getFirstVehicleInformation(nullptr, 0, false, std::numeric_limits<double>::max(), false);
2979  MSLeaderInfo firstFront = next->getFirstVehicleInformation(nullptr, 0, true);
2980 #ifdef DEBUG_CONTEXT
2981  if (DEBUG_COND2(ego)) {
2982  std::cout << " next=" << next->getID() << " seen=" << (*it).length << " first=" << first.toString() << " firstFront=" << firstFront.toString() << "\n";
2983  gDebugFlag1 = true; // for calling getLeaderInfo
2984  }
2985 #endif
2986  if (backOffset + (*it).length - next->getLength() < 0) {
2987  // check for junction foes that would interfere with lane changing
2988  const MSLink::LinkLeaders linkLeaders = (*it).viaLink->getLeaderInfo(ego, -backOffset);
2989  for (const auto& ll : linkLeaders) {
2990  if (ll.vehAndGap.first != nullptr) {
2991  const bool egoIsLeader = ll.vehAndGap.first->isLeader((*it).viaLink, ego);
2992  const double gap = egoIsLeader ? NUMERICAL_EPS : ll.vehAndGap.second;
2993  result.addFollower(ll.vehAndGap.first, ego, gap);
2994 #ifdef DEBUG_CONTEXT
2995  if (DEBUG_COND2(ego)) {
2996  std::cout << SIMTIME << " ego=" << ego->getID() << " link=" << (*it).viaLink->getViaLaneOrLane()->getID()
2997  << " (3) added veh=" << Named::getIDSecure(ll.vehAndGap.first)
2998  << " gap=" << ll.vehAndGap.second << " dtC=" << ll.distToCrossing
2999  << " egoIsLeader=" << egoIsLeader << " gap2=" << gap
3000  << "\n";
3001  }
3002 #endif
3003  }
3004  }
3005  }
3006 #ifdef DEBUG_CONTEXT
3007  if (DEBUG_COND2(ego)) gDebugFlag1 = false;
3008 #endif
3009 
3010  for (int i = 0; i < first.numSublanes(); ++i) {
3011  // NOTE: I added this because getFirstVehicleInformation() returns the ego as first if it partially laps into next.
3012  // EDIT: Disabled the previous changes (see commented code in next line and fourth upcoming) as I realized that this
3013  // did not completely fix the issue (to conserve test results). Refs #4727 (Leo)
3014  const MSVehicle* v = /* first[i] == ego ? firstFront[i] :*/ first[i];
3015  double agap = 0;
3016 
3017  if (v != nullptr && v != ego) {
3018  if (!v->isFrontOnLane(next)) {
3019  // the front of v is already on divergent trajectory from the ego vehicle
3020  // for which this method is called (in the context of MSLaneChanger).
3021  // Therefore, technically v is not a follower but only an obstruction and
3022  // the gap is not between the front of v and the back of ego
3023  // but rather between the flank of v and the back of ego.
3024  agap = (*it).length - next->getLength() + backOffset
3026  - v->getVehicleType().getMinGap();
3027 #ifdef DEBUG_CONTEXT
3028  if (DEBUG_COND2(ego)) {
3029  std::cout << " agap1=" << agap << "\n";
3030  }
3031 #endif
3032  if (agap > 0 && &v->getLane()->getEdge() != &ego->getLane()->getEdge()) {
3033  // Only if ego overlaps we treat v as if it were a real follower
3034  // Otherwise we ignore it and look for another follower
3035  v = firstFront[i];
3036  if (v != nullptr && v != ego) {
3037  agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3038  } else {
3039  v = nullptr;
3040  }
3041  }
3042  } else {
3043  agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3044  if (!(*it).viaLink->havePriority() && !ego->onFurtherEdge(&(*it).lane->getEdge())
3045  && ego->isOnRoad() // during insertion, this can lead to collisions because ego's further lanes are not set (see #3053)
3046  ) {
3047  // if v comes from a minor side road it should not block lane changing
3048  agap = MAX2(agap, 0.0);
3049  }
3050  }
3051  result.addFollower(v, ego, agap, 0, i);
3052 #ifdef DEBUG_CONTEXT
3053  if (DEBUG_COND2(ego)) {
3054  std::cout << " (2) added veh=" << Named::getIDSecure(v) << " agap=" << agap << " next=" << next->getID() << " result=" << result.toString() << "\n";
3055  }
3056 #endif
3057  }
3058  }
3059  if ((*it).length < searchDist) {
3060  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
3061  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
3062  if (visited.find((*j).lane) == visited.end() && ((*j).viaLink->havePriority() || !ignoreMinorLinks)) {
3063  visited.insert((*j).lane);
3065  ili.lane = (*j).lane;
3066  ili.length = (*j).length + (*it).length;
3067  ili.viaLink = (*j).viaLink;
3068  newFound.push_back(ili);
3069  }
3070  }
3071  }
3072  }
3073  toExamine.clear();
3074  swap(newFound, toExamine);
3075  }
3076  //return result;
3077 
3078  }
3079  return result;
3080 }
3081 
3082 
3083 void
3084 MSLane::getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle* ego,
3085  const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result) const {
3086  if (seen > dist) {
3087  return;
3088  }
3089  // check partial vehicles (they might be on a different route and thus not
3090  // found when iterating along bestLaneConts)
3091  for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
3092  MSVehicle* veh = *it;
3093  if (!veh->isFrontOnLane(this)) {
3094  result.addLeader(veh, seen, veh->getLatOffset(this));
3095  } else {
3096  break;
3097  }
3098  }
3099  const MSLane* nextLane = this;
3100  int view = 1;
3101  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
3102  // loop over following lanes
3103  while (seen < dist && result.numFreeSublanes() > 0) {
3104  // get the next link used
3105  MSLinkCont::const_iterator link = succLinkSec(*ego, view, *nextLane, bestLaneConts);
3106  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, ego->getVehicleType().getLength(),
3107  ego->getImpatience(), ego->getCarFollowModel().getMaxDecel(), 0, ego->getLateralPositionOnLane()) || (*link)->haveRed()) {
3108  break;
3109  }
3110  // check for link leaders
3111  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(ego, seen);
3112  if (linkLeaders.size() > 0) {
3113  const MSLink::LinkLeader ll = linkLeaders[0];
3114  if (ll.vehAndGap.first != 0 && ego->isLeader(*link, ll.vehAndGap.first)) {
3115  // add link leader to all sublanes and return
3116  for (int i = 0; i < result.numSublanes(); ++i) {
3117  MSVehicle* veh = ll.vehAndGap.first;
3118 #ifdef DEBUG_CONTEXT
3119  if (DEBUG_COND2(ego)) {
3120  std::cout << " linkleader=" << veh->getID() << " gap=" << ll.vehAndGap.second << "\n";
3121  }
3122 #endif
3123  result.addLeader(veh, ll.vehAndGap.second, 0);
3124  }
3125  return; ;
3126  } // XXX else, deal with pedestrians
3127  }
3128  bool nextInternal = (*link)->getViaLane() != nullptr;
3129  nextLane = (*link)->getViaLaneOrLane();
3130  if (nextLane == nullptr) {
3131  break;
3132  }
3133 
3134  MSLeaderInfo leaders = nextLane->getLastVehicleInformation(nullptr, 0, 0, false);
3135 #ifdef DEBUG_CONTEXT
3136  if (DEBUG_COND2(ego)) {
3137  std::cout << SIMTIME << " getLeadersOnConsecutive lane=" << getID() << " nextLane=" << nextLane->getID() << " leaders=" << leaders.toString() << "\n";
3138  }
3139 #endif
3140  // @todo check alignment issues if the lane width changes
3141  const int iMax = MIN2(leaders.numSublanes(), result.numSublanes());
3142  for (int i = 0; i < iMax; ++i) {
3143  const MSVehicle* veh = leaders[i];
3144  if (veh != nullptr) {
3145 #ifdef DEBUG_CONTEXT
3146  if (DEBUG_COND2(ego)) std::cout << " lead=" << veh->getID()
3147  << " seen=" << seen
3148  << " minGap=" << ego->getVehicleType().getMinGap()
3149  << " backPos=" << veh->getBackPositionOnLane(nextLane)
3150  << " gap=" << seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane)
3151  << "\n";
3152 #endif
3153  result.addLeader(veh, seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane), 0, i);
3154  }
3155  }
3156 
3157  if (nextLane->getVehicleMaxSpeed(ego) < speed) {
3158  dist = ego->getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(ego));
3159  }
3160  seen += nextLane->getLength();
3161  if (seen <= dist) {
3162  // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
3163  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
3164  }
3165  if (!nextInternal) {
3166  view++;
3167  }
3168  }
3169 }
3170 
3171 
3172 
3173 MSVehicle*
3175  for (VehCont::const_reverse_iterator i = myPartialVehicles.rbegin(); i != myPartialVehicles.rend(); ++i) {
3176  MSVehicle* veh = *i;
3177  if (veh->isFrontOnLane(this)
3178  && veh != ego
3179  && veh->getPositionOnLane() <= ego->getPositionOnLane()) {
3180 #ifdef DEBUG_CONTEXT
3181  if (DEBUG_COND2(ego)) {
3182  std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " found=" << veh->getID() << "\n";
3183  }
3184 #endif
3185  return veh;
3186  }
3187  }
3188 #ifdef DEBUG_CONTEXT
3189  if (DEBUG_COND2(ego)) {
3190  std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " nothing found. partials=" << toString(myPartialVehicles) << "\n";
3191  }
3192 #endif
3193  return nullptr;
3194 }
3195 
3198  MSLeaderInfo result(this);
3199  for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
3200  MSVehicle* veh = *it;
3201  if (!veh->isFrontOnLane(this)) {
3202  result.addLeader(veh, false, veh->getLatOffset(this));
3203  } else {
3204  break;
3205  }
3206  }
3207  return result;
3208 }
3209 
3210 
3211 std::set<MSVehicle*>
3212 MSLane::getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr<LaneCoverageInfo> checkedLanes) const {
3213  assert(checkedLanes != nullptr);
3214  if (checkedLanes->find(this) != checkedLanes->end()) {
3215 #ifdef DEBUG_SURROUNDING
3216  std::cout << "Skipping previously scanned lane: " << getID() << std::endl;
3217 #endif
3218  return std::set<MSVehicle*>();
3219  } else {
3220  // Add this lane's coverage to the lane coverage info
3221  (*checkedLanes)[this] = std::make_pair(MAX2(0.0, startPos-upstreamDist), MIN2(startPos+downstreamDist, getLength()));
3222  }
3223 #ifdef DEBUG_SURROUNDING
3224  std::cout << "Scanning on lane " << myID << "(downstr. " << downstreamDist << ", upstr. " << upstreamDist << ", startPos " << startPos << "): " << std::endl;
3225 #endif
3226  std::set<MSVehicle*> foundVehicles = getVehiclesInRange(MAX2(0., startPos-upstreamDist), MIN2(myLength, startPos + downstreamDist));
3227  if (startPos < upstreamDist) {
3228  // scan incoming lanes
3229  for (const IncomingLaneInfo& incomingInfo : getIncomingLanes()){
3230  MSLane* incoming = incomingInfo.lane;
3231 #ifdef DEBUG_SURROUNDING
3232  std::cout << "Checking on incoming: " << incoming->getID() << std::endl;
3233  if (checkedLanes->find(incoming) != checkedLanes->end()) {
3234  std::cout << "Skipping previous: " << incoming->getID() << std::endl;
3235  }
3236 #endif
3237  std::set<MSVehicle*> newVehs = incoming->getSurroundingVehicles(incoming->getLength(), 0.0, upstreamDist-startPos, checkedLanes);
3238  foundVehicles.insert(newVehs.begin(), newVehs.end());
3239  }
3240  }
3241 
3242  if (getLength() < startPos + downstreamDist) {
3243  // scan successive lanes
3244  const MSLinkCont& lc = getLinkCont();
3245  for (MSLink* l : lc) {
3246 #ifdef DEBUG_SURROUNDING
3247  std::cout << "Checking on outgoing: " << l->getViaLaneOrLane()->getID() << std::endl;
3248 #endif
3249  std::set<MSVehicle*> newVehs = l->getViaLaneOrLane()->getSurroundingVehicles(0.0, downstreamDist - (myLength - startPos), upstreamDist, checkedLanes);
3250  foundVehicles.insert(newVehs.begin(), newVehs.end());
3251  }
3252  }
3253 #ifdef DEBUG_SURROUNDING
3254  std::cout << "On lane (2) " << myID << ": \nFound vehicles: " << std::endl;
3255  for (MSVehicle* v : foundVehicles) {
3256  std::cout << v->getID() << " pos = " << v->getPositionOnLane() << std::endl;
3257  }
3258 #endif
3259  return foundVehicles;
3260 }
3261 
3262 
3263 std::set<MSVehicle*>
3264 MSLane::getVehiclesInRange(double a, double b) const {
3265  std::set<MSVehicle*> res;
3266  const VehCont& vehs = getVehiclesSecure();
3267 
3268  const int nV = (int)vehs.size();
3269  if (nV == 0) {
3270  releaseVehicles();
3271  return res;
3272  }
3273 
3274  // query interval to lane dimensions
3275  a = MAX2(0., a);
3276  b = MIN2(myLength, b);
3277 
3278  // Find indices ia (min with veh in interval)
3279  // and ib (max with veh in interval)
3280  int ia = 0, ib = nV-1;
3281  while (ia != nV) {
3282  if(vehs[ia]->getPositionOnLane() >= a) {
3283  break;
3284  }
3285  ++ia;
3286  }
3287  while (ib != -1) {
3288  if(vehs[ib]->getBackPositionOnLane() <= b){
3289  break;
3290  }
3291  --ib;
3292  }
3293 
3294  res.insert(vehs.begin()+ia, vehs.begin()+ib+1);
3295  releaseVehicles();
3296  return res;
3297 }
3298 
3299 std::vector<const MSJunction*>
3300 MSLane::getUpcomingJunctions(double pos, double range, const std::vector<MSLane*>& contLanes) const {
3301  // set of upcoming junctions and the corresponding conflict links
3302  std::vector<const MSJunction*> junctions;
3303  for (auto l : getUpcomingLinks(pos, range, contLanes)) {
3304  junctions.insert(junctions.end(), l->getJunction());
3305  }
3306  return junctions;
3307 }
3308 
3309 
3310 std::vector<const MSLink*>
3311 MSLane::getUpcomingLinks(double pos, double range, const std::vector<MSLane*>& contLanes) const {
3312 #ifdef DEBUG_SURROUNDING
3313  std::cout << "getUpcoming links on lane '" << getID() << "' with pos=" << pos
3314  << " range=" << range << std::endl;
3315 #endif
3316  // set of upcoming junctions and the corresponding conflict links
3317  std::vector<const MSLink*> links;
3318 
3319  // Currently scanned lane
3320  const MSLane* lane = this;
3321 
3322  // continuation lanes for the vehicle
3323  std::vector<MSLane*>::const_iterator contLanesIt = contLanes.begin();
3324  // scanned distance so far
3325  double dist = 0.0;
3326  // link to be crossed by the vehicle
3327  MSLink* link = nullptr;
3328  if (lane->isInternal()) {
3329  assert(*contLanesIt == nullptr); // is called with vehicle's bestLane structure
3330  link = lane->getEntryLink();
3331  links.insert(links.end(), link);
3332  dist += link->getInternalLengthsAfter();
3333  // next non-internal lane behind junction
3334  lane = link->getLane();
3335  pos = 0.0;
3336  assert(*(contLanesIt+1) == lane);
3337  }
3338  while (++contLanesIt != contLanes.end()) {
3339  assert(!lane->isInternal());
3340  dist += lane->getLength() - pos;
3341  pos = 0.;
3342 #ifdef DEBUG_SURROUNDING
3343  std::cout << "Distance until end of lane '" << lane->getID() << "' is " << dist << "." << std::endl;
3344 #endif
3345  if (dist > range) {
3346  break;
3347  }
3348  link = lane->getLinkTo(*contLanesIt);
3349  if (link!=nullptr) {
3350  links.insert(links.end(), link);
3351  }
3352  lane = *contLanesIt;
3353  }
3354  return links;
3355 }
3356 
3357 
3358 MSLane*
3360  if (myNeighs.size() == 1) {
3361  return dictionary(myNeighs[0]);
3362  }
3363  return nullptr;
3364 }
3365 
3366 
3367 double
3368 MSLane::getOppositePos(double pos) const {
3369  MSLane* opposite = getOpposite();
3370  if (opposite == nullptr) {
3371  assert(false);
3372  throw ProcessError("Lane '" + getID() + "' cannot compute oppositePos as there is no opposite lane.");
3373  }
3374  // XXX transformations for curved geometries
3375  return MAX2(0., opposite->getLength() - pos);
3376 
3377 }
3378 
3379 std::pair<MSVehicle* const, double>
3380 MSLane::getFollower(const MSVehicle* ego, double egoPos, double dist, bool ignoreMinorLinks) const {
3381  for (AnyVehicleIterator first = anyVehiclesUpstreamBegin(); first != anyVehiclesUpstreamEnd(); ++first) {
3382  // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
3383  MSVehicle* pred = (MSVehicle*)*first;
3384 #ifdef DEBUG_CONTEXT
3385  if (DEBUG_COND2(ego)) {
3386  std::cout << " getFollower lane=" << getID() << " egoPos=" << egoPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << "\n";
3387  }
3388 #endif
3389  if (pred->getPositionOnLane(this) < egoPos && pred != ego) {
3390  return std::pair<MSVehicle* const, double>(pred, egoPos - pred->getPositionOnLane(this) - ego->getVehicleType().getLength() - pred->getVehicleType().getMinGap());
3391  }
3392  }
3393  const double backOffset = egoPos - ego->getVehicleType().getLength();
3394  CLeaderDist result = getFollowersOnConsecutive(ego, backOffset, true, dist, ignoreMinorLinks)[0];
3395  return std::make_pair(const_cast<MSVehicle*>(result.first), result.second);
3396 }
3397 
3398 std::pair<MSVehicle* const, double>
3399 MSLane::getOppositeLeader(const MSVehicle* ego, double dist, bool oppositeDir) const {
3400 #ifdef DEBUG_OPPOSITE
3401  if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeLeader lane=" << getID()
3402  << " ego=" << ego->getID()
3403  << " pos=" << ego->getPositionOnLane()
3404  << " posOnOpposite=" << getOppositePos(ego->getPositionOnLane())
3405  << " dist=" << dist
3406  << " oppositeDir=" << oppositeDir
3407  << "\n";
3408 #endif
3409  if (!oppositeDir) {
3410  return getLeader(ego, getOppositePos(ego->getPositionOnLane()), ego->getBestLanesContinuation(this));
3411  } else {
3412  const double egoLength = ego->getVehicleType().getLength();
3413  const double egoPos = ego->getLaneChangeModel().isOpposite() ? ego->getPositionOnLane() : getOppositePos(ego->getPositionOnLane());
3414  std::pair<MSVehicle* const, double> result = getFollower(ego, egoPos + egoLength, dist, true);
3415  result.second -= ego->getVehicleType().getMinGap();
3416  return result;
3417  }
3418 }
3419 
3420 
3421 std::pair<MSVehicle* const, double>
3423 #ifdef DEBUG_OPPOSITE
3424  if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeFollower lane=" << getID()
3425  << " ego=" << ego->getID()
3426  << " backPos=" << ego->getBackPositionOnLane()
3427  << " posOnOpposite=" << getOppositePos(ego->getBackPositionOnLane())
3428  << "\n";
3429 #endif
3430  if (ego->getLaneChangeModel().isOpposite()) {
3431  std::pair<MSVehicle* const, double> result = getFollower(ego, getOppositePos(ego->getPositionOnLane()), -1, true);
3432  return result;
3433  } else {
3434  std::pair<MSVehicle* const, double> result = getLeader(ego, getOppositePos(ego->getPositionOnLane() - ego->getVehicleType().getLength()), std::vector<MSLane*>());
3435  if (result.first != nullptr) {
3436  if (result.first->getLaneChangeModel().isOpposite()) {
3437  result.second -= result.first->getVehicleType().getLength();
3438  } else {
3439  if (result.second > POSITION_EPS) {
3440  // follower can be safely ignored since it is going the other way
3441  return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3442  }
3443  }
3444  }
3445  return result;
3446  }
3447 }
3448 
3449 
3450 void
3452  const std::string action = oc.getString("collision.action");
3453  if (action == "none") {
3455  } else if (action == "warn") {
3457  } else if (action == "teleport") {
3459  } else if (action == "remove") {
3461  } else {
3462  WRITE_ERROR("Invalid collision.action '" + action + "'.");
3463  }
3464  myCheckJunctionCollisions = oc.getBool("collision.check-junctions");
3465  myCollisionStopTime = string2time(oc.getString("collision.stoptime"));
3466  myCollisionMinGapFactor = oc.getFloat("collision.mingap-factor");
3467 }
3468 
3469 
3470 void
3471 MSLane::setPermissions(SVCPermissions permissions, long long transientID) {
3472  if (transientID == CHANGE_PERMISSIONS_PERMANENT) {
3473  myPermissions = permissions;
3474  myOriginalPermissions = permissions;
3475  } else {
3476  myPermissionChanges[transientID] = permissions;
3478  }
3479 }
3480 
3481 
3482 void
3483 MSLane::resetPermissions(long long transientID) {
3484  myPermissionChanges.erase(transientID);
3485  if (myPermissionChanges.empty()) {
3487  } else {
3488  // combine all permission changes
3490  for (const auto& item : myPermissionChanges) {
3491  myPermissions &= item.second;
3492  }
3493  }
3494 }
3495 
3496 
3497 bool
3498 MSLane::checkForPedestrians(const MSVehicle* aVehicle, double& speed, double& dist, double pos, bool patchSpeed) const {
3499  if (getEdge().getPersons().size() > 0 && MSPModel::getModel()->hasPedestrians(this)) {
3500 #ifdef DEBUG_INSERTION
3501  if (DEBUG_COND2(aVehicle)) {
3502  std::cout << SIMTIME << " check for pedestrians on lane=" << getID() << " pos=" << pos << "\n";
3503  }
3504 #endif
3505  PersonDist leader = MSPModel::getModel()->nextBlocking(this, pos - aVehicle->getVehicleType().getLength(),
3506  aVehicle->getRightSideOnLane(), aVehicle->getRightSideOnLane() + aVehicle->getVehicleType().getWidth(), ceil(speed / aVehicle->getCarFollowModel().getMaxDecel()));
3507  if (leader.first != 0) {
3508  const double gap = leader.second - aVehicle->getVehicleType().getLengthWithGap();
3509  const double stopSpeed = aVehicle->getCarFollowModel().stopSpeed(aVehicle, speed, gap);
3510  if (gap < 0 || checkFailure(aVehicle, speed, dist, stopSpeed, patchSpeed, "")) {
3511  // we may not drive with the given velocity - we crash into the pedestrian
3512 #ifdef DEBUG_INSERTION
3513  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
3514  << " isInsertionSuccess lane=" << getID()
3515  << " veh=" << aVehicle->getID()
3516  << " pos=" << pos
3517  << " posLat=" << aVehicle->getLateralPositionOnLane()
3518  << " patchSpeed=" << patchSpeed
3519  << " speed=" << speed
3520  << " stopSpeed=" << stopSpeed
3521  << " pedestrianLeader=" << leader.first->getID()
3522  << " failed (@796)!\n";
3523 #endif
3524  return false;
3525  }
3526  }
3527  }
3528  return true;
3529 }
3530 
3531 /****************************************************************************/
3532 
void detectPedestrianJunctionCollision(const MSVehicle *collider, const PositionVector &colliderBoundary, const MSLane *foeLane, SUMOTime timestep, const std::string &stage)
detect whether a vehicle collids with pedestrians on the junction
Definition: MSLane.cpp:1370
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:785
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:32
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, bool ignoreMinorLinks) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane) ...
Definition: MSLane.cpp:3380
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition: MSLane.cpp:2531
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
void loadState(std::vector< std::string > &vehIDs, MSVehicleControl &vc)
Loads the state of this segment with the given parameters.
Definition: MSLane.cpp:2893
static double gLateralResolution
Definition: MSGlobals.h:85
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
SVCPermissions myPermissions
The vClass permissions for this lane.
Definition: MSLane.h:1273
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:2407
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:131
VehCont myVehicles
The lane&#39;s vehicles. This container holds all vehicles that have their front (longitudinally) and the...
Definition: MSLane.h:1220
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:492
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time tau (i...
Definition: MSCFModel.h:313
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:129
virtual double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false) const
Computes the vehicle&#39;s safe speed without a leader.
Definition: MSCFModel.cpp:268
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:125
double getNOxEmissions() const
Returns the sum of last step NOx emissions.
Definition: MSLane.cpp:2626
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:640
A free lateral position is chosen.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:79
The position is given.
long long int SUMOTime
Definition: SUMOTime.h:36
MSVehicle * getFirstFullVehicle() const
returns the first vehicle for which this lane is responsible or 0
Definition: MSLane.cpp:1889
At the leftmost side of the lane.
virtual int addLeader(const MSVehicle *veh, bool beyond, double latOffset=0)
bool detectCollisionBetween(SUMOTime timestep, const std::string &stage, MSVehicle *collider, MSVehicle *victim, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toRemove, std::set< const MSVehicle *> &toTeleport) const
detect whether there is a collision between the two vehicles
Definition: MSLane.cpp:1403
MSLane(const std::string &id, double maxSpeed, double length, MSEdge *const edge, int numericalID, const PositionVector &shape, double width, SVCPermissions permissions, int index, bool isRampAccel)
Constructor.
Definition: MSLane.cpp:171
int getPriority() const
Returns the priority of the edge.
Definition: MSEdge.h:274
double getAngle() const
Returns the vehicle&#39;s direction in radians.
Definition: MSVehicle.h:685
void informVehicleStateListener(const SUMOVehicle *const vehicle, VehicleState to, const std::string &info="")
Informs all added listeners about a vehicle&#39;s state change.
Definition: MSNet.cpp:855
PositionVector getBoundingPoly() const
get bounding polygon
Definition: MSVehicle.cpp:5178
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition: MSLane.cpp:2697
void sortManeuverReservations()
sorts myManeuverReservations
Definition: MSLane.cpp:1840
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:629
const MSEdge * getNextNormal() const
Returns the lane&#39;s follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:1702
std::string containerstop
(Optional) container stop if one is assigned to the stop
static void insertIDs(std::vector< std::string > &into)
Adds the ids of all stored lanes into the given vector.
Definition: MSLane.cpp:1762
std::set< MSVehicle * > getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr< LaneCoverageInfo > checkedLanes) const
Returns all vehicles closer than downstreamDist along the along the road network starting on the give...
Definition: MSLane.cpp:3212
void enterLaneAtInsertion(MSLane *enteredLane, double pos, double speed, double posLat, MSMoveReminder::Notification notification)
Update when the vehicle enters a new lane in the emit step.
Definition: MSVehicle.cpp:4197
void updateLeaderInfo(const MSVehicle *veh, VehCont::reverse_iterator &vehPart, VehCont::reverse_iterator &vehRes, MSLeaderInfo &ahead) const
This updates the MSLeaderInfo argument with respect to the given MSVehicle. All leader-vehicles on th...
Definition: MSLane.cpp:1153
Sorts lanes (IncomingLaneInfos) by their priority or, if this doesn&#39;t apply, wrt. the angle differenc...
Definition: MSLane.h:1425
MSLane * parallelLane(const MSLane *const lane, int offset) const
Returns the lane with the given offset parallel to the given lane one or 0 if it does not exist...
Definition: MSEdge.cpp:375
virtual bool hasPedestrians(const MSLane *lane)
whether the given lane has pedestrians on it
Definition: MSPModel.h:85
virtual void removeParking(MSVehicle *veh)
remove parking vehicle. This must be syncrhonized when running with GUI
Definition: MSLane.cpp:2877
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir) const
Definition: MSLane.cpp:3399
#define LANE_RTREE_QUAL
Definition: Helper.h:77
bool parking
whether the vehicle is removed from the net while stopping
double getMaxSpeedFactor() const
return the maximum speed factor for all vehicles that ever entered the network
begin/end of the description of a single lane
bool hasDeparted() const
Returns whether this vehicle has already departed.
bool checkFailure(const MSVehicle *aVehicle, double &speed, double &dist, const double nspeed, const bool patchSpeed, const std::string errorMsg) const
Definition: MSLane.cpp:577
Stop & getNextStop()
Definition: MSVehicle.cpp:5478
int myI2
index for myPartialVehicles
Definition: MSLane.h:158
bool resumeFromStopping()
Definition: MSVehicle.cpp:5427
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:565
double getFuelConsumption() const
Returns the sum of last step fuel consumption.
Definition: MSLane.cpp:2650
SUMOTime duration
The stopping duration.
The speed is given.
bool isInsertionSuccess(MSVehicle *vehicle, double speed, double pos, double posLat, bool recheckNextLanes, MSMoveReminder::Notification notification)
Tries to insert the given vehicle with the given state (speed and pos)
Definition: MSLane.cpp:606
void registerTeleportYield()
register one non-collision-related teleport
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition: MSLane.cpp:1770
double getMaximumBrakeDist() const
compute maximum braking distance on this lane
Definition: MSLane.cpp:2133
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:27
The vehicle arrived at a junction.
void setMaxSpeed(double val)
Sets a new maximum speed for the lane (used by TraCI and MSCalibrator)
Definition: MSLane.cpp:2020
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition: MSVehicle.h:935
void recalcCache()
Recalculates the cached values.
Definition: MSEdge.cpp:126
This is an uncontrolled, minor link, has to stop.
const MSEdgeVector & getPredecessors() const
Definition: MSEdge.h:338
static bool haveLateralDynamics()
whether any kind of lateral dynamics is active
std::vector< IncomingLaneInfo > myIncomingLanes
All direct predecessor lanes.
Definition: MSLane.h:1282
The position is given.
The car-following model abstraction.
Definition: MSCFModel.h:57
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
int myI2End
end index for myPartialVehicles
Definition: MSLane.h:164
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:403
std::vector< const MSJunction * > getUpcomingJunctions(double pos, double range, const std::vector< MSLane *> &contLanes) const
Returns all upcoming junctions within given range along the given (non-internal) continuation lanes m...
Definition: MSLane.cpp:3300
void addLink(MSLink *link)
Delayed initialization.
Definition: MSLane.cpp:216
MSLane * myCanonicalPredecessorLane
Similar to LogicalPredecessorLane,.
Definition: MSLane.h:1288
int myIndex
The lane index.
Definition: MSLane.h:1207
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:61
virtual bool integrateNewVehicle(SUMOTime t)
Insert buffered vehicle into the real lane.
Definition: MSLane.cpp:1804
The lateral position is chosen randomly.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle&#39;s parameter (including departure definition)
static double myCollisionMinGapFactor
Definition: MSLane.h:1352
SUMOTime myLeaderInfoTime
time step for which myLeaderInfo was last updated
Definition: MSLane.h:1314
If a fixed number of random choices fails, a free lateral position is chosen.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
bool operator()(const MSVehicle *cmp, double pos) const
compares vehicle position to the detector position
Definition: MSLane.cpp:2691
AnyVehicleIterator is a structure, which manages the iteration through all vehicles on the lane...
Definition: MSLane.h:107
static SUMOTime myCollisionStopTime
Definition: MSLane.h:1351
Notification
Definition of a vehicle state.
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition: MSLane.cpp:288
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
A RT-tree for efficient storing of SUMO&#39;s Named objects.
Definition: NamedRTree.h:65
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition: MSLane.cpp:2045
double myBruttoVehicleLengthSum
The current length of all vehicles on this lane, including their minGaps.
Definition: MSLane.h:1294
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1912
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:390
const MSEdge *const myEdge
Definition: MSLane.h:1415
std::map< long long, SVCPermissions > myPermissionChanges
Definition: MSLane.h:1336
This is a dead end link.
void addIncomingLane(MSLane *lane, MSLink *viaLink)
Definition: MSLane.cpp:2069
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
T MAX2(T a, T b)
Definition: StdDefs.h:76
double getPMxEmissions() const
Returns the sum of last step PMx emissions.
Definition: MSLane.cpp:2614
by_connections_to_sorter(const MSEdge *const e)
constructor
Definition: MSLane.cpp:2712
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
std::set< MSVehicle * > getVehiclesInRange(double a, double b) const
Returns all vehicles on the lane overlapping with the interval [a,b].
Definition: MSLane.cpp:3264
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:514
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:406
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:456
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:71
The speed is chosen randomly.
PositionVector getBoundingBox() const
get bounding rectangle
Definition: MSVehicle.cpp:5165
bool isLinkEnd(MSLinkCont::const_iterator &i) const
Definition: MSLane.cpp:1859
static void initCollisionOptions(const OptionsCont &oc)
Definition: MSLane.cpp:3451
virtual void addMoveReminder(MSMoveReminder *rem)
Add a move-reminder to move-reminder container.
Definition: MSLane.cpp:234
const MSRoute & getRoute() const
Returns the current route.
MSLink * getLinkTo(const MSLane *) const
returns the link to the given lane or 0, if it is not connected
Definition: MSLane.cpp:1982
double getCollisionMinGapFactor() const
Get the factor of minGap that must be maintained to avoid a collision event.
Definition: MSCFModel.h:240
The vehicle got vaporized.
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2506
SUMOTime until
The time at which the vehicle may continue its journey.
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, bool collision=false, MSRouteIterator *searchStart=0)
Adds a stop.
Definition: MSVehicle.cpp:1338
double getRightSideOnLane() const
Get the vehicle&#39;s lateral position on the lane:
Definition: MSVehicle.cpp:4931
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:88
MSLane * getCanonicalPredecessorLane() const
Definition: MSLane.cpp:2443
This is an uncontrolled, right-before-left link.
bool executeMove()
Executes planned vehicle movements with regards to right-of-way.
Definition: MSVehicle.cpp:3368
double getSafeFollowSpeed(const std::pair< const MSVehicle *, double > leaderInfo, const double seen, const MSLane *const lane, double distToCrossing) const
compute safe speed for following the given leader
Definition: MSVehicle.cpp:2633
void addNeigh(const std::string &id)
Adds a neighbor to this lane.
Definition: MSLane.cpp:222
#define RAD2DEG(x)
Definition: GeomHelper.h:39
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle&#39;s end speed shall be chosen.
const std::string & getID() const
Returns the id.
Definition: Named.h:78
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
const SVCPermissions SVCAll
all VClasses are allowed
void gotActive(MSLane *l)
Informs the control that the given lane got active.
virtual double insertionStopSpeed(const MSVehicle *const veh, double speed, double gap) const
Computes the vehicle&#39;s safe speed for approaching an obstacle at insertion without constraints due to...
Definition: MSCFModel.cpp:290
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:244
VehCont myPartialVehicles
The lane&#39;s partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1232
std::vector< MSTransportable * > getSortedPersons(SUMOTime timestep, bool includeRiding=false) const
Returns this edge&#39;s persons sorted by pos.
Definition: MSEdge.cpp:929
The position is chosen randomly.
static bool myCheckJunctionCollisions
Definition: MSLane.h:1350
This is an uncontrolled, all-way stop link.
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition: MSLane.cpp:277
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:530
int myI1End
end index for myVehicles
Definition: MSLane.h:162
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge) ...
Definition: MSVehicle.cpp:948
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
virtual double insertionFollowSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel) const
Computes the vehicle&#39;s safe speed (no dawdling) This method is used during the insertion stage...
Definition: MSCFModel.cpp:279
int myDirection
index delta
Definition: MSLane.h:170
std::string parkingarea
(Optional) parking area if one is assigned to the stop
PositionVector myShape
The shape of the lane.
Definition: MSLane.h:1204
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
int myI3
index for myTmpVehicles
Definition: MSLane.h:160
The speed is given.
MSLane * getCanonicalSuccessorLane() const
Definition: MSLane.cpp:2463
std::set< const MSVehicle * > myParkingVehicles
Definition: MSLane.h:1253
void getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle *ego, const std::vector< MSLane *> &bestLaneConts, MSLeaderDistanceInfo &result) const
Returns the immediate leaders and the distance to them (as getLeaderOnConsecutive but for the sublane...
Definition: MSLane.cpp:3084
bool myDownstream
iteration direction
Definition: MSLane.h:168
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4307
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:363
#define SIMTIME
Definition: SUMOTime.h:65
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:3790
int getLaneIndex() const
Definition: MSVehicle.cpp:4914
std::vector< std::string > myNeighs
Definition: MSLane.h:1333
bool isLeader(const MSLink *link, const MSVehicle *veh) const
whether the given vehicle must be followed at the given junction
Definition: MSVehicle.cpp:5607
static CollisionAction myCollisionAction
the action to take on collisions
Definition: MSLane.h:1349
const std::string & getEdgeType() const
Returns the type of the edge.
Definition: MSEdge.h:268
std::map< std::string, MSLane *> DictType
definition of the static dictionary type
Definition: MSLane.h:1339
static CollisionAction getCollisionAction()
Definition: MSLane.h:1136
MSLinkCont myLinks
Definition: MSLane.h:1301
virtual void detectCollisions(SUMOTime timestep, const std::string &stage)
Check if vehicles are too close.
Definition: MSLane.cpp:1203
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition: MSLane.h:1342
Sorts lanes (their origin link) by the priority of their noninternal target edges or...
Definition: MSLane.h:1445
bool isInternal() const
Definition: MSLane.cpp:1875
std::string busstop
(Optional) bus stop if one is assigned to the stop
#define SUMOTime_MIN
Definition: SUMOTime.h:38
void addApproachingLane(MSLane *lane, bool warnMultiCon)
Definition: MSLane.cpp:2079
double departSpeed
(optional) The initial speed of the vehicle
virtual const MSEdge * succEdge(int nSuccs) const =0
Returns the nSuccs&#39;th successor of edge the vehicle is currently at.
A road/street connecting two junctions.
Definition: MSEdge.h:75
void leaveLane(const MSMoveReminder::Notification reason, const MSLane *approachedLane=0)
Update of members if vehicle leaves a new lane in the lane change step or at arrival.
Definition: MSVehicle.cpp:4257
virtual int addLeader(const MSVehicle *veh, double gap, double latOffset=0, int sublane=-1)
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:4975
bool insertVehicle(MSVehicle &v)
Tries to insert the given vehicle.
Definition: MSLane.cpp:501
No information given; use default.
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:891
double myLength
Lane length [m].
Definition: MSLane.h:1256
void resetPermissions(long long transientID)
Definition: MSLane.cpp:3483
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle&#39;s initial speed shall be chosen.
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
Definition: MSLane.h:1236
void setPermissions(SVCPermissions permissions, long long transientID)
Sets the permissions to the given value. If a transientID is given, the permissions are recored as te...
Definition: MSLane.cpp:3471
int operator()(const IncomingLaneInfo &lane1, const IncomingLaneInfo &lane2) const
comparing operator
Definition: MSLane.cpp:2758
MSLink * getEntryLink() const
Returns the entry link if this is an internal lane, else 0.
Definition: MSLane.cpp:2003
const MSVehicle * operator*()
Definition: MSLane.cpp:119
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
int getCrossingIndex() const
return the index of the link to the next crossing if this is walkingArea, else -1 ...
Definition: MSLane.cpp:2520
The vehicle is involved in a collision.
Definition: MSNet.h:516
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:258
double getCO2Emissions() const
Returns the sum of last step CO2 emissions.
Definition: MSLane.cpp:2590
const bool myIsRampAccel
whether this lane is an acceleration lane
Definition: MSLane.h:1322
virtual double getSecureGap(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
Representation of a vehicle.
Definition: SUMOVehicle.h:60
static bool gCheckRoutes
Definition: MSGlobals.h:79
double startPos
The stopping position start.
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
int operator()(const std::pair< const MSVehicle *, double > &p1, const std::pair< const MSVehicle *, double > &p2) const
Definition: MSLane.cpp:2111
void setLength(double val)
Sets a new length for the lane (used by TraCI only)
Definition: MSLane.cpp:2027
static MSPModel * getModel()
Definition: MSPModel.cpp:59
This is an uncontrolled, minor link, has to brake.
Sorts vehicles by their position (descending)
Definition: MSLane.h:1358
double myRightSideOnEdge
the combined width of all lanes with lower index on myEdge
Definition: MSLane.h:1325
std::string chargingStation
(Optional) charging station if one is assigned to the stop
bool lastInsertion(MSVehicle &veh, double mspeed, double posLat, bool patchSpeed)
inserts vehicle as close as possible to the last vehicle on this lane (or at the end of the lane if t...
Definition: MSLane.cpp:327
SVCPermissions myOriginalPermissions
The original vClass permissions for this lane (before temporary modifications)
Definition: MSLane.h:1276
outgoing_lane_priority_sorter(const MSLane *sourceLane)
constructor
Definition: MSLane.cpp:2831
A list of positions.
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:4325
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2513
virtual void setJunctionApproaches(const SUMOTime t)
Register junction approaches for all vehicles after velocities have been planned. ...
Definition: MSLane.cpp:1146
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:4668
double getEmergencyDecel() const
Get the vehicle type&#39;s maximal phisically possible deceleration [m/s^2].
Definition: MSCFModel.h:226
const MSLeaderInfo & getLastVehicleInformation(const MSVehicle *ego, double latOffset, double minPos=0, bool allowCached=true) const
Returns the last vehicles on the lane.
Definition: MSLane.cpp:1002
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:316
const std::set< MSTransportable * > & getPersons() const
Returns this edge&#39;s persons set.
Definition: MSEdge.h:171
double getCenterOnEdge(const MSLane *lane=0) const
Get the vehicle&#39;s lateral position on the edge of the given lane (or its current edge if lane == 0) ...
Definition: MSVehicle.cpp:4943
double getMinDeceleration() const
return the minimum deceleration capability for all vehicles that ever entered the network ...
const std::map< SUMOVehicleClass, double > * myRestrictions
The vClass speed restrictions for this lane.
Definition: MSLane.h:1279
bool isEmpty() const
Definition: MSLane.cpp:1870
bool triggered
whether an arriving person lets the vehicle continue
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition: MSLane.cpp:3422
bool checkForPedestrians(const MSVehicle *aVehicle, double &speed, double &dist, double pos, bool patchSpeed) const
check whether pedestrians on this lane interfere with vehicle insertion
Definition: MSLane.cpp:3498
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:58
The vehicle arrived at its destination (is deleted)
double safeInsertionSpeed(const MSVehicle *veh, double seen, const MSLeaderInfo &leaders, double speed)
return the maximum safe speed for insertion behind leaders (a negative value indicates that safe inse...
Definition: MSLane.cpp:973
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:506
const std::map< SUMOVehicleClass, double > * getRestrictions(const std::string &id) const
Returns the restrictions for an edge type If no restrictions are present, 0 is returned.
Definition: MSNet.cpp:302
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
Definition: MSVehicle.h:994
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
int operator()(const MSLink *link1, const MSLink *link2) const
comparing operator
Definition: MSLane.cpp:2836
Sorts edges by their angle relative to the given edge (straight comes first)
Definition: MSLane.h:1404
The maximum speed is used.
std::string toString() const
print a debugging representation
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:964
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:263
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:42
T MIN2(T a, T b)
Definition: StdDefs.h:70
MSVehicle * getPartialBehind(const MSVehicle *ego) const
Definition: MSLane.cpp:3174
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:119
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:418
void add(const SUMOTime t, MSVehicle *veh)
Adds a vehicle to this transfer object.
AnyVehicleIterator anyVehiclesBegin() const
begin iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:412
#define POSITION_EPS
Definition: config.h:172
LinkState getIncomingLinkState() const
get the state of the link from the logical predecessor to this lane
Definition: MSLane.cpp:2484
double getImpatience() const
Returns this vehicles impatience.
No information given; use default.
virtual bool executeMovements(SUMOTime t, std::vector< MSLane *> &lanesWithVehiclesToIntegrate)
Executes planned vehicle movements with regards to right-of-way.
Definition: MSLane.cpp:1593
std::pair< MSVehicle *const, double > getLeader(const MSVehicle *veh, const double vehPos, const std::vector< MSLane *> &bestLaneConts, double dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
Definition: MSLane.cpp:2143
CollisionAction
Definition: MSLane.h:179
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
Definition: MSVehicle.cpp:934
virtual PersonDist nextBlocking(const MSLane *lane, double minPos, double minRight, double maxLeft, double stopTime=0)
returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or 0 ...
Definition: MSPModel.h:91
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:301
bool hasInfluencer() const
Definition: MSVehicle.h:1640
int myRightmostSublane
the index of the rightmost sublane of this lane on myEdge
Definition: MSLane.h:1327
MSLane * myLogicalPredecessorLane
Definition: MSLane.h:1285
double endPos
The stopping position end.
double getMinGap() const
Get the free space in front of vehicles of this class.
SUMOTime collisionStopTime() const
Returns the remaining time a vehicle needs to stop due to a collision. A negative value indicates tha...
Definition: MSVehicle.cpp:1621
Something on a lane to be noticed about vehicle movement.
const std::vector< std::pair< const MSLane *, const MSEdge * > > getOutgoingViaLanes() const
get the list of outgoing lanes
Definition: MSLane.cpp:2495
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:218
double basePos(const MSEdge *edge) const
departure position where the vehicle fits fully onto the edge (if possible)
Definition: MSVehicle.cpp:1863
MSLane * getOpposite() const
return the opposite direction lane for lane changing or 0
Definition: MSLane.cpp:3359
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns the information whether the given polygon overlaps with this.
AnyVehicleIterator anyVehiclesUpstreamBegin() const
begin iterator for iterating over all vehicles touching this lane in upstream direction ...
Definition: MSLane.h:424
virtual void swapAfterLaneChange(SUMOTime t)
moves myTmpVehicles int myVehicles after a lane change procedure
Definition: MSLane.cpp:2034
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:225
void registerTeleportJam()
register one non-collision-related teleport
double getHCEmissions() const
Returns the sum of last step HC emissions.
Definition: MSLane.cpp:2638
If a fixed number of random choices fails, a free position is chosen.
std::map< MSEdge *, std::vector< MSLane * > > myApproachingLanes
All direct internal and direct (disregarding internal predecessors) non-internal predecessor lanes of...
Definition: MSLane.h:1304
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:90
const MSLane * lane
The lane to stop at.
Definition: MSVehicle.h:925
bool containerTriggered
whether an arriving container lets the vehicle continue
static MSLinkCont::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane *> &conts)
Definition: MSLane.cpp:1926
int operator()(const MSEdge *const e1, const MSEdge *const e2) const
comparing operator
Definition: MSLane.cpp:2719
Base class for objects which have an id.
Definition: Named.h:58
std::map< SVCPermissions, double > myStopOffsets
Definition: MSLane.h:1264
int myNumericalID
Unique numerical ID (set on reading by netload)
Definition: MSLane.h:1201
std::vector< MSMoveReminder *> myMoveReminders
This lane&#39;s move reminder.
Definition: MSLane.h:1346
VehCont myManeuverReservations
The vehicles which registered maneuvering into the lane within their current action step...
Definition: MSLane.h:1248
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:440
double getRightSideOnEdge() const
Definition: MSLane.h:1027
incoming_lane_priority_sorter(const MSLane *targetLane)
constructor
Definition: MSLane.cpp:2753
MSLeaderInfo getPartialBeyond() const
get all vehicles that are inlapping from consecutive edges
Definition: MSLane.cpp:3197
std::string lane
The lane to stop at.
void initRestrictions()
initialized vClass-specific speed limits
Definition: MSLane.cpp:208
AnyVehicleIterator & operator++()
Definition: MSLane.cpp:102
static MSVehicleTransfer * getInstance()
Returns the instance of this object.
double departPosLat
(optional) The lateral position the vehicle shall depart from
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:247
std::pair< const MSPerson *, double > PersonDist
Definition: MSPModel.h:38
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition: MSLane.cpp:1880
void sortPartialVehicles()
sorts myPartialVehicles
Definition: MSLane.cpp:1832
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:981
void markDelayed() const
Definition: MSEdge.h:627
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
bool freeInsertion(MSVehicle &veh, double speed, double posLat, MSMoveReminder::Notification notification=MSMoveReminder::NOTIFICATION_DEPARTED)
Tries to insert the given vehicle on any place.
Definition: MSLane.cpp:362
virtual std::string toString() const
print a debugging representation
double getElectricityConsumption() const
Returns the sum of last step electricity consumption.
Definition: MSLane.cpp:2662
double departPos
(optional) The position the vehicle shall depart from
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1730
static SUMOTime gTimeToGridlockHighways
Definition: MSGlobals.h:63
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:35
int addFollower(const MSVehicle *veh, const MSVehicle *ego, double gap, double latOffset=0, int sublane=-1)
std::string myID
The name of the object.
Definition: Named.h:130
SUMOVehicleClass getVClass() const
Returns the vehicle&#39;s access class.
The vehicle has departed (was inserted into the network)
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:5488
void scheduleVehicleRemoval(SUMOVehicle *veh)
Removes a vehicle after it has ended.
double getCOEmissions() const
Returns the sum of last step CO emissions.
Definition: MSLane.cpp:2602
Structure representing possible vehicle parameter.
std::pair< MSVehicle *const, double > getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle &veh, const std::vector< MSLane *> &bestLaneConts) const
Returns the immediate leader and the distance to him.
Definition: MSLane.cpp:2208
int myI1
index for myVehicles
Definition: MSLane.h:156
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:3368
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
static bool gUnitTests
whether unit tests are being run
Definition: MSGlobals.h:118
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
Definition: MSVehicle.cpp:1646
void setTentativeLaneAndPosition(MSLane *lane, double pos, double posLat=0)
set tentative lane and position during insertion to ensure that all cfmodels work (some of them requi...
Definition: MSVehicle.cpp:4921
#define M_PI
Definition: odrSpiral.cpp:40
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:369
static void clear()
Clears the dictionary.
Definition: MSLane.cpp:1753
const MSLane * getFirstInternalInConnection(double &offset) const
Returns 0 if the lane is not internal. Otherwise the first part of the connection (sequence of intern...
Definition: MSLane.cpp:1712
bool nextIsMyVehicles() const
Definition: MSLane.cpp:135
int myI3End
end index for myTmpVehicles
Definition: MSLane.h:166
MSEdge *const myEdge
The lane&#39;s edge, for routing only.
Definition: MSLane.h:1267
Definition of vehicle stop (position and duration)
At the rightmost side of the lane.
bool hasVehicles() const
Definition: MSLeaderInfo.h:96
At the center of the lane.
const MSLane * myLane
the lane that is being iterated
Definition: MSLane.h:154
A storage for options typed value containers)
Definition: OptionsCont.h:92
void handleCollisionBetween(SUMOTime timestep, const std::string &stage, MSVehicle *collider, MSVehicle *victim, double gap, double latGap, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toRemove, std::set< const MSVehicle *> &toTeleport) const
take action upon collision
Definition: MSLane.cpp:1469
double angleAt2D(int pos) const
get angle in certain position of position vector
int index
at which position in the stops list
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1898
bool isApproachedFrom(MSEdge *const edge)
Definition: MSLane.cpp:2093
double getHarmonoise_NoiseEmissions() const
Returns the sum of last step noise emissions.
Definition: MSLane.cpp:2674
double getStopOffset(const MSVehicle *veh) const
Returns vehicle class specific stopOffset for the vehicle.
Definition: MSLane.cpp:2908
#define INVALID_SPEED
Definition: MSCFModel.h:33
std::pair< MSVehicle *const, double > getCriticalLeader(double dist, double seen, double speed, const MSVehicle &veh) const
Returns the most dangerous leader and the distance to him.
Definition: MSLane.cpp:2334
static SUMOTime gTimeToGridlock
Definition: MSGlobals.h:60
double getLength() const
Get vehicle&#39;s length [m].
AnyVehicleIterator anyVehiclesUpstreamEnd() const
end iterator for iterating over all vehicles touching this lane in upstream direction ...
Definition: MSLane.h:430
const MSLeaderInfo & getFirstVehicleInformation(const MSVehicle *ego, double latOffset, bool onlyFrontOnLane, double maxPos=std::numeric_limits< double >::max(), bool allowCached=true) const
analogue to getLastVehicleInformation but in the upstream direction
Definition: MSLane.cpp:1055
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs&#39;th successor of edge the vehicle is currently at.
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:60
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition: MSLane.cpp:2702
bool isRemoteAffected(SUMOTime t) const
Definition: MSVehicle.cpp:683
void saveState(OutputDevice &out)
Saves the state of this lane into the given stream.
Definition: MSLane.cpp:2882
MSLeaderInfo myLeaderInfo
leaders on all sublanes as seen by approaching vehicles (cached)
Definition: MSLane.h:1307
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:3701
MSLane * myCanonicalSuccessorLane
Main successor lane,.
Definition: MSLane.h:1291
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
#define DEBUG_COND2(obj)
Definition: MSLane.cpp:83
void registerCollision()
registers one collision-related teleport
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:359
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
double myNettoVehicleLengthSum
The current length of all vehicles on this lane, excluding their minGaps.
Definition: MSLane.h:1297
double getMeanSpeed() const
Returns the mean speed on this lane.
Definition: MSLane.cpp:2574
#define NUMERICAL_EPS
Definition: config.h:148
MSLeaderInfo myFollowerInfo
followers on all sublanes as seen by vehicles on consecutive lanes (cached)
Definition: MSLane.h:1309
int numSublanes() const
Definition: MSLeaderInfo.h:88
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
virtual ~MSLane()
Destructor.
Definition: MSLane.cpp:200
MSLane * getShadowLane() const
Returns the lane the vehicle&#39;s shadow is on during continuous/sublane lane change.
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:70
void addParking(MSVehicle *veh)
add parking vehicle. This should only used during state loading
Definition: MSLane.cpp:2871
int numFreeSublanes() const
Definition: MSLeaderInfo.h:92
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1585
No information given; use default.
A free position is chosen.
The class responsible for building and deletion of vehicles.
double getMissingRearGap(const MSVehicle *leader, double backOffset, double leaderSpeed) const
return by how much further the leader must be inserted to avoid rear end collisions ...
Definition: MSLane.cpp:2117
const double myLengthGeometryFactor
precomputed myShape.length / myLength
Definition: MSLane.h:1319
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:71
MSLeaderInfo myLeaderInfoTmp
Definition: MSLane.h:1311
Insert behind the last vehicle as close as possible to still allow the specified departSpeed. Fallback to DEPART_POS_BASE if there is no vehicle on the departLane yet.
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1975
double getRightSideOnEdge(const MSLane *lane=0) const
Get the vehicle&#39;s lateral position on the edge of the given lane (or its current edge if lane == 0) ...
Definition: MSVehicle.cpp:4937
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:4319
VehCont myVehBuffer
Buffer for vehicles that moved from their previous lane onto this one. Integrated after all vehicles ...
Definition: MSLane.h:1240
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
Definition: GeomHelper.cpp:167
bool isParking() const
Returns whether the vehicle is parking.
Definition: MSVehicle.cpp:1627
double getDepartPosLat(const MSVehicle &veh)
Definition: MSLane.cpp:477
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:483
static const long CHANGE_PERMISSIONS_PERMANENT
Definition: MSLane.h:1140
MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle *ego, double backOffset, bool allSublanes, double searchDist=-1, bool ignoreMinorLinks=false) const
return the sublane followers with the largest missing rear gap among all predecessor lanes (within di...
Definition: MSLane.cpp:2922
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:137
SUMOTime myFollowerInfoTime
time step for which myFollowerInfo was last updated
Definition: MSLane.h:1316
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:436
#define DEBUG_COND
Definition: MESegment.cpp:54
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:82
double myMaxSpeed
Lane-wide speedlimit [m/s].
Definition: MSLane.h:1270
double getNettoOccupancy() const
Returns the netto (excluding minGaps) occupancy of this lane during the last step (including minGaps)...
Definition: MSLane.cpp:2546
static double sum(double val)
Computes the resulting noise.
const std::string & getID() const
Returns the name of the vehicle.
void registerTeleportWrongLane()
register one non-collision-related teleport
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
std::vector< const MSLink * > getUpcomingLinks(double pos, double range, const std::vector< MSLane *> &contLanes) const
Returns all upcoming junctions within given range along the given (non-internal) continuation lanes m...
Definition: MSLane.cpp:3311
Back-at-zero position.
double getWaitingSeconds() const
Returns the overall waiting time on this lane.
Definition: MSLane.cpp:2561
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
void descheduleDeparture(const SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
bool myNeedsCollisionCheck
whether a collision check is currently needed
Definition: MSLane.h:1330
const double myWidth
Lane width [m].
Definition: MSLane.h:1259
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
virtual double stopSpeed(const MSVehicle *const veh, const double speed, double gap) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
virtual void incorporateVehicle(MSVehicle *veh, double pos, double speed, double posLat, const MSLane::VehCont::iterator &at, MSMoveReminder::Notification notification=MSMoveReminder::NOTIFICATION_DEPARTED)
Inserts the vehicle into this lane, and informs it about entering the network.
Definition: MSLane.cpp:306
virtual bool appropriate(const MSVehicle *veh)
Definition: MSLane.cpp:1786
The vehicle is being teleported.
virtual void planMovements(const SUMOTime t)
Compute safe velocities for all vehicles based on positions and speeds from the last time step...
Definition: MSLane.cpp:1107
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2063
Definition of vehicle stop (position and duration)
Definition: MSVehicle.h:919
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.
double getDepartSpeed(const MSVehicle &veh, bool &patchSpeed)
Definition: MSLane.cpp:450
#define FALLTHROUGH
Definition: StdDefs.h:38
DepartPosLatDefinition departPosLatProcedure
Information how the vehicle shall choose the lateral departure position.