Eclipse SUMO - Simulation of Urban MObility
MSLaneChanger.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2002-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
23 // Performs lane changing of vehicles
24 /****************************************************************************/
25 #include <config.h>
26 
27 #include "MSLaneChanger.h"
28 #include "MSNet.h"
29 #include "MSLink.h"
30 #include "MSVehicle.h"
31 #include "MSVehicleType.h"
32 #include "MSVehicleTransfer.h"
33 #include "MSStop.h"
34 #include "MSGlobals.h"
35 #include <cassert>
36 #include <iterator>
37 #include <cstdlib>
38 #include <cmath>
43 
44 #define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0
45 #define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR 0.0
46 #define OPPOSITE_OVERTAKING_SAFETY_FACTOR 1.2
47 // XXX maxLookAhead should be higher if all leaders are stopped and lower when they are jammed/queued
48 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0 // just a guess
49 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0 // just a guess
50 // this is used for finding oncoming vehicles while driving in the opposite direction
51 #define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 1000.0 // just a guess
52 // do not attempt overtaking maneuvers that would exceed this distance
53 #define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE 1000.0 // just a guess
54 #define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD 5 // (m)
55 
56 // halting time to signal yielding in deadlock
57 #define OPPOSITE_OVERTAKING_DEADLOCK_WAIT 1 // (s)
58 
59 // ===========================================================================
60 // debug defines
61 // ===========================================================================
62 
63 //#define DEBUG_CONTINUE_CHANGE
64 //#define DEBUG_CHECK_CHANGE
65 //#define DEBUG_SURROUNDING_VEHICLES // debug getRealFollower() and getRealLeader()
66 //#define DEBUG_CHANGE_OPPOSITE
67 //#define DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
68 //#define DEBUG_CHANGE_OPPOSITE_DEADLOCK
69 //#define DEBUG_ACTIONSTEPS
70 //#define DEBUG_STATE
71 //#define DEBUG_CANDIDATE
72 //#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
73 #define DEBUG_COND (vehicle->isSelected())
74 //#define DEBUG_COND (true)
75 
76 
77 
78 // ===========================================================================
79 // ChangeElem member method definitions
80 // ===========================================================================
82  lead(nullptr),
83  lane(_lane),
84  hoppedVeh(nullptr),
85  lastBlocked(nullptr),
86  firstBlocked(nullptr),
87  lastStopped(nullptr),
88  ahead(_lane->getWidth()),
89  aheadNext(_lane->getWidth(), nullptr, 0.) {
90 }
91 
92 void
94  //std::cout << SIMTIME << " registerHop lane=" << lane->getID() << " veh=" << vehicle->getID() << "\n";
95  lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
96  dens += vehicle->getVehicleType().getLengthWithGap();
97  hoppedVeh = vehicle;
98 }
99 
100 
101 // ===========================================================================
102 // member method definitions
103 // ===========================================================================
104 MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging) :
105  myAllowsChanging(allowChanging),
106  myChangeToOpposite(lanes->front()->getEdge().canChangeToOpposite()) {
107 
108  // Fill the changer with the lane-data.
109  myChanger.reserve(lanes->size());
110  for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
111  myChanger.push_back(ChangeElem(*lane));
112  myChanger.back().mayChangeRight = lane != lanes->begin();
113  myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
114  if ((*lane)->isInternal()) {
115  // avoid changing on internal sibling lane
116  if (myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
117  myChanger.back().mayChangeRight = false;
118  }
119  if (myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
120  myChanger.back().mayChangeLeft = false;
121  }
122  // avoid changing if lanes have different lengths
123  if (myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
124  //std::cout << " cannot change right from lane=" << (*lane)->getID() << " len=" << (*lane)->getLength() << " to=" << (*(lane - 1))->getID() << " len2=" << (*(lane - 1))->getLength() << "\n";
125  myChanger.back().mayChangeRight = false;
126  }
127  if (myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
128  //std::cout << " cannot change left from lane=" << (*lane)->getID() << " len=" << (*lane)->getLength() << " to=" << (*(lane + 1))->getID() << " len2=" << (*(lane + 1))->getLength() << "\n";
129  myChanger.back().mayChangeLeft = false;
130  }
131  }
132  }
133 }
134 
135 
137 }
138 
139 
140 void
142  // This is what happens in one timestep. After initialization of the
143  // changer, each vehicle will try to change. After that the changer
144  // needs an update to prevent multiple changes of one vehicle.
145  // Finally, the change-result has to be given back to the lanes.
146  initChanger();
147  try {
148  while (vehInChanger()) {
149  const bool haveChanged = change();
150  updateChanger(haveChanged);
151  }
152  updateLanes(t);
153  } catch (const ProcessError&) {
154  // clean up locks or the gui may hang
155  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
156  ce->lane->releaseVehicles();
157  }
158  throw;
159  }
160 }
161 
162 
163 void
165  // Prepare myChanger with a safe state.
166  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
167  ce->lead = nullptr;
168  ce->hoppedVeh = nullptr;
169  ce->lastBlocked = nullptr;
170  ce->firstBlocked = nullptr;
171  ce->lastStopped = nullptr;
172  ce->dens = 0;
173  ce->lane->getVehiclesSecure();
174 
175  //std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
176  }
177 }
178 
179 
180 void
181 MSLaneChanger::updateChanger(bool vehHasChanged) {
182  assert(veh(myCandi) != 0);
183 
184  // "Push" the vehicles to the back, i.e. follower becomes vehicle,
185  // vehicle becomes leader, and leader becomes predecessor of vehicle,
186  // if it exists.
187  if (!vehHasChanged) {
188  //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " has new lead=" << veh(myCandi)->getID() << "\n";
189  myCandi->lead = veh(myCandi);
190  }
191 
192  MSLane::VehCont& vehicles = myCandi->lane->myVehicles;
193  vehicles.pop_back();
194  //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " vehicles=" << toString(myCandi->lane->myVehicles) << "\n";
195 }
196 
197 
198 void
200 
201  // Update the lane's vehicle-container.
202  // First: it is bad style to change other classes members, but for
203  // this release, other attempts were too time-consuming. In a next
204  // release we will change from this lane-centered design to a vehicle-
205  // centered. This will solve many problems.
206  // Second: this swap would be faster if vehicle-containers would have
207  // been pointers, but then I had to change too much of the MSLane code.
208  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
209  //std::cout << SIMTIME << " updateLanes lane=" << ce->lane->getID() << " myVehicles=" << toString(ce->lane->myVehicles) << " myTmpVehicles=" << toString(ce->lane->myTmpVehicles) << "\n";
210  ce->lane->swapAfterLaneChange(t);
211  ce->lane->releaseVehicles();
212  }
213 }
214 
215 
218  // Find the vehicle in myChanger with the largest position. If there
219  // is no vehicle in myChanger (shouldn't happen) , return myChanger.end().
220  ChangerIt max = myChanger.end();
221 #ifdef DEBUG_CANDIDATE
222  std::cout << SIMTIME << " findCandidate() on edge " << myChanger.begin()->lane->getEdge().getID() << std::endl;
223 #endif
224 
225  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
226  if (veh(ce) == nullptr) {
227  continue;
228  }
229 #ifdef DEBUG_CANDIDATE
230  std::cout << " lane = " << ce->lane->getID() << "\n";
231  std::cout << " check vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
232 #endif
233  if (max == myChanger.end()) {
234 #ifdef DEBUG_CANDIDATE
235  std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
236 #endif
237  max = ce;
238  continue;
239  }
240  assert(veh(ce) != 0);
241  assert(veh(max) != 0);
242  if (veh(max)->getPositionOnLane() < veh(ce)->getPositionOnLane()) {
243 #ifdef DEBUG_CANDIDATE
244  std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << " oldMaxPos=" << veh(max)->getPositionOnLane() << "\n";
245 #endif
246  max = ce;
247  }
248  }
249  assert(max != myChanger.end());
250  assert(veh(max) != 0);
251  return max;
252 }
253 
254 
255 bool
256 MSLaneChanger::mayChange(int direction) const {
257  if (direction == 0) {
258  return true;
259  }
260  if (!myAllowsChanging) {
261  return false;
262  }
264  if (direction == -1) {
265  return myCandi->mayChangeRight && (myCandi - 1)->lane->allowsVehicleClass(svc) && myCandi->lane->allowsChangingRight(svc);
266  } else if (direction == 1) {
267  return myCandi->mayChangeLeft && (myCandi + 1)->lane->allowsVehicleClass(svc) && myCandi->lane->allowsChangingLeft(svc);
268  } else {
269  return false;
270  }
271 }
272 
273 
274 bool
276  // Find change-candidate. If it is on an allowed lane, try to change
277  // to the right (there is a rule in Germany that you have to change
278  // to the right, unless you are overtaking). If change to the right
279  // isn't possible, check if there is a possibility to overtake (on the
280  // left.
281  // If candidate isn't on an allowed lane, changing to an allowed has
282  // priority.
283 
284 #ifdef DEBUG_ACTIONSTEPS
285 // std::cout<< "\nCHANGE" << std::endl;
286 #endif
287 
288 
290  MSVehicle* vehicle = veh(myCandi);
291  vehicle->getLaneChangeModel().clearNeighbors();
292 
293  if (vehicle->getLaneChangeModel().isChangingLanes() && !vehicle->getLaneChangeModel().alreadyChanged()) {
294  return continueChange(vehicle, myCandi);
295  }
296  if (!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
297  registerUnchanged(vehicle);
298  if (vehicle->isStoppedOnLane()) {
299  myCandi->lastStopped = vehicle;
300  }
301  return false;
302  }
303 
304  if (!vehicle->isActive()) {
305 #ifdef DEBUG_ACTIONSTEPS
306  if (DEBUG_COND) {
307  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
308  }
309 #endif
310  bool changed = false;
311  const int oldstate = vehicle->getLaneChangeModel().getOwnState();
312  // let TraCI influence the wish to change lanes during non-actionsteps
313  checkTraCICommands(vehicle);
314  if (oldstate != vehicle->getLaneChangeModel().getOwnState()) {
315  changed = applyTraCICommands(vehicle);
316  }
317  if (!changed) {
318  registerUnchanged(vehicle);
319  }
320  return changed;
321  }
322 
323  // Check for changes to the opposite lane if vehicle is active
324  std::pair<MSVehicle* const, double> leader = getRealLeader(myCandi);
325  if (myChanger.size() == 1 || vehicle->getLaneChangeModel().isOpposite() || (!mayChange(-1) && !mayChange(1))) {
326  if (changeOpposite(vehicle, leader, myCandi->lastStopped)) {
327  return true;
328  }
329  registerUnchanged(vehicle);
330  return false;
331  }
332 
333  vehicle->updateBestLanes(); // needed?
334  for (int i = 0; i < (int) myChanger.size(); ++i) {
335  vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
336  }
337 
338  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
339  // check whether the vehicle wants and is able to change to right lane
340  int stateRight = 0;
341  if (mayChange(-1)) {
342  stateRight = checkChangeWithinEdge(-1, leader, preb);
343  // change if the vehicle wants to and is allowed to change
344  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_BLOCKED) == 0) {
345  vehicle->getLaneChangeModel().setOwnState(stateRight);
346  return startChange(vehicle, myCandi, -1);
347  }
348  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_URGENT) != 0) {
349  (myCandi - 1)->lastBlocked = vehicle;
350  if ((myCandi - 1)->firstBlocked == nullptr) {
351  (myCandi - 1)->firstBlocked = vehicle;
352  }
353  }
354  }
355 
356  // check whether the vehicle wants and is able to change to left lane
357  int stateLeft = 0;
358  if (mayChange(1)) {
359  stateLeft = checkChangeWithinEdge(1, leader, preb);
360  // change if the vehicle wants to and is allowed to change
361  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_BLOCKED) == 0) {
362  vehicle->getLaneChangeModel().setOwnState(stateLeft);
363  return startChange(vehicle, myCandi, 1);
364  }
365  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_URGENT) != 0) {
366  (myCandi + 1)->lastBlocked = vehicle;
367  if ((myCandi + 1)->firstBlocked == nullptr) {
368  (myCandi + 1)->firstBlocked = vehicle;
369  }
370  }
371  }
372 
373  if ((stateRight & LCA_URGENT) != 0 && (stateLeft & LCA_URGENT) != 0) {
374  // ... wants to go to the left AND to the right
375  // just let them go to the right lane...
376  stateLeft = 0;
377  }
378  vehicle->getLaneChangeModel().setOwnState(stateRight | stateLeft);
379 
380  // only emergency vehicles should change to the opposite side on a
381  // multi-lane road (or vehicles that need to stop on the opposite side)
382  if ((vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
383  || hasOppositeStop(vehicle))
384  && changeOpposite(vehicle, leader, myCandi->lastStopped)) {
385  return true;
386  }
387 
388  registerUnchanged(vehicle);
389  return false;
390 }
391 
392 
393 void
395  //std::cout << SIMTIME << " registerUnchanged lane=" << myCandi->lane->getID() << " veh=" << vehicle->getID() << "\n";
396  myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
397  myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
398  vehicle->getLaneChangeModel().unchanged();
399 }
400 
401 
402 
403 void
405 #ifdef DEBUG_STATE
406  const int oldstate = vehicle->getLaneChangeModel().getOwnState();
407 #endif
409 #ifdef DEBUG_STATE
410  if (DEBUG_COND) {
411  const int newstate = vehicle->getLaneChangeModel().getOwnState();
412  std::cout << SIMTIME
413  << " veh=" << vehicle->getID()
414  << " oldState=" << toString((LaneChangeAction) oldstate)
415  << " newState=" << toString((LaneChangeAction) newstate)
416  << ((newstate & LCA_BLOCKED) != 0 ? " (blocked)" : "")
417  << ((newstate & LCA_OVERLAPPING) != 0 ? " (overlap)" : "")
418  << "\n";
419  }
420 #endif
421 }
422 
423 
424 bool
426  // Execute request if not blocked
427  bool changed = false;
428  const int state = vehicle->getLaneChangeModel().getOwnState();
429  const int dir = (state & LCA_RIGHT) != 0 ? -1 : ((state & LCA_LEFT) != 0 ? 1 : 0);
430  const bool execute = dir != 0 && ((state & LCA_BLOCKED) == 0);
431  if (execute) {
432  ChangerIt to = myCandi + dir;
433  bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(myCandi->lane, to->lane, dir);
434  if (continuous) {
435  changed = continueChange(vehicle, myCandi);
436  } else {
437  // insert vehicle into target lane
438  to->registerHop(vehicle);
439  changed = true;
440  }
441  }
442  return changed;
443 }
444 
445 
446 bool
447 MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
448  if (vehicle->isRemoteControlled()) {
449  registerUnchanged(vehicle);
450  return false;
451  }
452  ChangerIt to = from + direction;
453  // @todo delay entering the target lane until the vehicle intersects it
454  // physically (considering lane width and vehicle width)
455  //if (to->lane->getID() == "beg_1") std::cout << SIMTIME << " startChange to lane=" << to->lane->getID() << " myTmpVehiclesBefore=" << toString(to->lane->myTmpVehicles) << "\n";
456  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
457  if (continuous) {
458  return continueChange(vehicle, myCandi);
459  } else {
460  to->registerHop(vehicle);
461  to->lane->requireCollisionCheck();
462  return true;
463  }
464 }
465 
466 bool
469  const int direction = lcm.isOpposite() ? -lcm.getLaneChangeDirection() : lcm.getLaneChangeDirection();
470  const bool pastMidpoint = lcm.updateCompletion(); // computes lcm.mySpeedLat as a side effect
471  const double speedLat = lcm.isOpposite() ? -lcm.getSpeedLat() : lcm.getSpeedLat();
472  vehicle->myState.myPosLat += SPEED2DIST(speedLat);
474  //std::cout << SIMTIME << " veh=" << vehicle->getID() << " dir=" << direction << " pm=" << pastMidpoint << " speedLat=" << speedLat << " posLat=" << vehicle->myState.myPosLat << "\n";
475  if (pastMidpoint) {
476  MSLane* source = myCandi->lane;
477  MSLane* target = source->getParallelLane(direction);
478  vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
479  lcm.primaryLaneChanged(source, target, direction);
480  if (&source->getEdge() == &target->getEdge()) {
481  ChangerIt to = from + direction;
482  to->registerHop(vehicle);
483  }
484  target->requireCollisionCheck();
485  } else {
486  from->registerHop(vehicle);
487  from->lane->requireCollisionCheck();
488  }
489  if (!lcm.isChangingLanes()) {
490  vehicle->myState.myPosLat = 0;
491  lcm.endLaneChangeManeuver();
492  }
493  lcm.updateShadowLane();
494  if (lcm.getShadowLane() != nullptr && &lcm.getShadowLane()->getEdge() == &vehicle->getLane()->getEdge()) {
495  // set as hoppedVeh on the shadow lane so it is found as leader on both lanes
496  myChanger[lcm.getShadowLane()->getIndex()].hoppedVeh = vehicle;
498  }
499  vehicle->myAngle = vehicle->computeAngle();
500  if (lcm.isOpposite()) {
501  vehicle->myAngle += M_PI;
502  }
503 
504 #ifdef DEBUG_CONTINUE_CHANGE
505  if (DEBUG_COND) {
506  std::cout << SIMTIME
507  << " continueChange veh=" << vehicle->getID()
508  << " from=" << Named::getIDSecure(from->lane)
509  << " dir=" << direction
510  << " speedLat=" << speedLat
511  << " pastMidpoint=" << pastMidpoint
512  << " posLat=" << vehicle->getLateralPositionOnLane()
513  << " completion=" << lcm.getLaneChangeCompletion()
514  << " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
515  //<< " shadowHopped=" << Named::getIDSecure(shadow->lane)
516  << "\n";
517  }
518 #endif
519  return pastMidpoint && lcm.getShadowLane() == nullptr;
520 }
521 
522 
523 std::pair<MSVehicle* const, double>
525  assert(veh(myCandi) != 0);
526  MSVehicle* vehicle = veh(myCandi);
527 #ifdef DEBUG_SURROUNDING_VEHICLES
528  if (DEBUG_COND) {
529  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl;
530  }
531 #endif
532  // get the leading vehicle on the lane to change to
533  MSVehicle* neighLead = target->lead;
534 
535 #ifdef DEBUG_SURROUNDING_VEHICLES
536  if (DEBUG_COND) {
537  if (neighLead != 0) {
538  std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl;
539  }
540  }
541 #endif
542 
543  // check whether the hopped vehicle became the leader
544  if (target->hoppedVeh != nullptr) {
545  double hoppedPos = target->hoppedVeh->getPositionOnLane();
546 #ifdef DEBUG_SURROUNDING_VEHICLES
547  if (DEBUG_COND) {
548  std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl;
549  }
550 #endif
551  if (hoppedPos > vehicle->getPositionOnLane() && (neighLead == nullptr || neighLead->getPositionOnLane() > hoppedPos)) {
552  neighLead = target->hoppedVeh;
553  //if (vehicle->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n";
554  }
555  }
556  // extra check for shared lane
557  const bool checkBidi = target->lane->getBidiLane() != nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
558  if (neighLead == nullptr || checkBidi) {
559 #ifdef DEBUG_SURROUNDING_VEHICLES
560  if (DEBUG_COND) {
561  std::cout << "Looking for leader on consecutive lanes." << std::endl;
562  }
563 #endif
564  // There's no leader on the target lane. Look for leaders on consecutive lanes.
565  // (there might also be partial leaders due to continuous lane changing or bidiLane)
566  MSLane* targetLane = target->lane;
567  const double egoBack = vehicle->getBackPositionOnLane();
568  double leaderBack = targetLane->getLength();
569  if (neighLead != nullptr) {
570  leaderBack = neighLead->getBackPositionOnLane(targetLane);
571  }
572  for (MSVehicle* pl : targetLane->myPartialVehicles) {
573  double plBack = pl->getBackPositionOnLane(targetLane);
574  if (pl->isBidiOn(targetLane)) {
575  plBack -= pl->getVehicleType().getLengthWithGap();
576  }
577  const double plPos = plBack + pl->getVehicleType().getLength();
578 #ifdef DEBUG_SURROUNDING_VEHICLES
579  if (DEBUG_COND) {
580  std::cout << " partial=" << pl->getID() << " plBack=" << plBack << " plPos=" << plPos << " leaderBack=" << leaderBack << " egoBack=" << egoBack << "\n";
581  }
582 #endif
583  if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
584  neighLead = pl;
585  leaderBack = plBack;
586  }
587  }
588  if (neighLead != nullptr) {
589 #ifdef DEBUG_SURROUNDING_VEHICLES
590  if (DEBUG_COND) {
591  std::cout << " found leader=" << neighLead->getID() << " (partial)\n";
592  }
593 #endif
594  const double gap = leaderBack - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
595  return std::pair<MSVehicle*, double>(neighLead, gap);
596  }
597  double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
598  double speed = vehicle->getSpeed();
599  double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
600  if (target->lane->getBidiLane() != nullptr) {
601  dist += target->lane->getBidiLane()->getMaximumBrakeDist();
602  }
603  // always check for link leaders while on an internal lane
604  if (seen > dist && !myCandi->lane->isInternal()) {
605 #ifdef DEBUG_SURROUNDING_VEHICLES
606  if (DEBUG_COND) {
607  std::cout << " found no leader within dist=" << dist << "\n";
608  }
609 #endif
610  return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
611  }
612  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(targetLane);
613 
614  std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
615 #ifdef DEBUG_SURROUNDING_VEHICLES
616  if (DEBUG_COND) {
617  std::cout << " found consecutiveLeader=" << Named::getIDSecure(result.first) << "\n";
618  }
619 #endif
620  return result;
621  } else {
622 #ifdef DEBUG_SURROUNDING_VEHICLES
623  if (DEBUG_COND) {
624  std::cout << " found leader=" << neighLead->getID() << "\n";
625  }
626 #endif
627  return std::pair<MSVehicle* const, double>(neighLead, neighLead->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap());
628  }
629 }
630 
631 
632 std::pair<MSVehicle* const, double>
634  assert(veh(myCandi) != 0);
635  MSVehicle* vehicle = veh(myCandi);
636 #ifdef DEBUG_SURROUNDING_VEHICLES
637  if (DEBUG_COND) {
638  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl;
639  }
640 #endif
641  const double candiPos = vehicle->getPositionOnLane();
642  MSVehicle* neighFollow = nullptr;
643  if (target != myCandi) {
644  neighFollow = veh(target);
645  } else {
646  // veh(target) would return the ego vehicle so we use its predecessor instead
647  if (target->lane->myVehicles.size() > 1) {
648  neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
649  }
650  }
651 
652 #ifdef DEBUG_SURROUNDING_VEHICLES
653  if (DEBUG_COND) {
654  if (neighFollow != 0) {
655  std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl;
656  } else {
657  std::cout << "veh(target) returns none." << std::endl;
658  }
659  }
660 #endif
661 
662 
663 #ifdef DEBUG_SURROUNDING_VEHICLES
664  if (DEBUG_COND) {
665  if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
666  std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
667  }
668  }
669 #endif
670 
671  // check whether the hopped vehicle became the follower
672  neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
673 
674 
675 #ifdef DEBUG_SURROUNDING_VEHICLES
676  if (DEBUG_COND) {
677  MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
678  if (partialBehind != 0 && partialBehind != neighFollow) {
679  std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() << "' at position " << partialBehind->getPositionOnLane() << " is closer." << std::endl;
680  }
681  }
682 #endif
683  // or a follower which is partially lapping into the target lane
684  neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
685 
686  if (neighFollow == nullptr) {
687  CLeaderDist consecutiveFollower = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true)[0];
688 #ifdef DEBUG_SURROUNDING_VEHICLES
689  if (DEBUG_COND) {
690  if (consecutiveFollower.first == 0) {
691  std::cout << "no follower found." << std::endl;
692  } else {
693  std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl;
694  }
695  }
696 #endif
697  return std::make_pair(const_cast<MSVehicle*>(consecutiveFollower.first), consecutiveFollower.second);
698  } else {
699 #ifdef DEBUG_SURROUNDING_VEHICLES
700  if (DEBUG_COND) {
701  std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl;
702  }
703 #endif
704  return std::pair<MSVehicle* const, double>(neighFollow,
705  vehicle->getPositionOnLane() - vehicle->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
706  }
707 }
708 
709 
710 MSVehicle*
711 MSLaneChanger::getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2) {
712  if (follow1 == nullptr || follow1->getPositionOnLane() > maxPos) {
713  return follow2;
714  } else if (follow2 == nullptr || follow2->getPositionOnLane() > maxPos) {
715  return follow1;
716  } else {
717  if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
718  return follow1;
719  } else {
720  return follow2;
721  }
722  }
723 }
724 
725 int
727  int laneOffset,
728  const std::pair<MSVehicle* const, double>& leader,
729  const std::vector<MSVehicle::LaneQ>& preb) const {
730 
731  std::pair<MSVehicle*, double> follower = getRealFollower(myCandi);
732  std::pair<MSVehicle* const, double> neighLead = getRealLeader(myCandi + laneOffset);
733  std::pair<MSVehicle*, double> neighFollow = getRealFollower(myCandi + laneOffset);
734  if (neighLead.first != nullptr && neighLead.first == neighFollow.first) {
735  // vehicles should not be leader and follower at the same time to avoid
736  // contradictory behavior
737  neighFollow.first = 0;
738  }
739  ChangerIt target = myCandi + laneOffset;
740  return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
741 }
742 
743 int
745  int laneOffset,
746  const MSLane* targetLane,
747  const std::pair<MSVehicle* const, double>& leader,
748  const std::pair<MSVehicle* const, double>& follower,
749  const std::pair<MSVehicle* const, double>& neighLead,
750  const std::pair<MSVehicle* const, double>& neighFollow,
751  const std::vector<MSVehicle::LaneQ>& preb) const {
752 
753  MSVehicle* vehicle = veh(myCandi);
754 
755 #ifdef DEBUG_CHECK_CHANGE
756  if (DEBUG_COND) {
757  std::cout
758  << "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'"
759  << std::endl;
760  }
761 #endif
762 
763  int blocked = 0;
764  int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
765  int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
766  // overlap
767  if (neighFollow.first != nullptr && neighFollow.second < 0) {
768  blocked |= (blockedByFollower | LCA_OVERLAPPING);
769 
770  // Debug (Leo)
771 #ifdef DEBUG_CHECK_CHANGE
772  if (DEBUG_COND) {
773  std::cout << SIMTIME
774  << " overlapping with follower..."
775  << std::endl;
776  }
777 #endif
778 
779  }
780  if (neighLead.first != nullptr && neighLead.second < 0) {
781  blocked |= (blockedByLeader | LCA_OVERLAPPING);
782 
783 #ifdef DEBUG_CHECK_CHANGE
784  if (DEBUG_COND) {
785  std::cout << SIMTIME
786  << " overlapping with leader..."
787  << std::endl;
788  }
789 #endif
790 
791  }
792  double secureFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
793  double secureBackGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
794  double secureOrigFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
795 
796  const double tauRemainder = vehicle->getActionStepLength() == DELTA_T ? 0 : MAX2(vehicle->getCarFollowModel().getHeadwayTime() - TS, 0.);
797  // safe back gap
798  if ((blocked & blockedByFollower) == 0 && neighFollow.first != nullptr) {
799  // Calculate secure gap conservatively with vNextFollower / vNextLeader as
800  // extrapolated speeds after the driver's expected reaction time (tau).
801  // NOTE: there exists a possible source for collisions if the follower and the leader
802  // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
803 
804  // Expected reaction time (tau) for the follower-vehicle.
805  // (subtracted TS since at this point the vehicles' states are already updated)
806  const double vNextFollower = neighFollow.first->getSpeed() + MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
807  const double vNextLeader = vehicle->getSpeed() + MIN2(0., tauRemainder * vehicle->getAcceleration());
808  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
809  secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
810  vNextLeader, vehicle->getCarFollowModel().getMaxDecel());
811 #ifdef DEBUG_CHECK_CHANGE
812  if (DEBUG_COND) {
813  std::cout << SIMTIME
814  << " follower=" << neighFollow.first->getID()
815  << " backGap=" << neighFollow.second
816  << " vNextFollower=" << vNextFollower
817  << " vNextEgo=" << vNextLeader
818  << " secureGap=" << secureBackGap
819  << " safetyFactor=" << vehicle->getLaneChangeModel().getSafetyFactor()
820  << " blocked=" << (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor())
821  << "\n";
822  }
823 #endif
824  if (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
825  if (vehicle->getLaneChangeModel().isOpposite()
826  && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
827  // during opposite direction driving, the vehicle are handled in
828  // downstream rather than upstream order, the neighFollower may have
829  // been the actual follower in this simulation step and should not
830  // block changing in this case
831 #ifdef DEBUG_CHECK_CHANGE
832  if (DEBUG_COND) {
833  std::cout << " ignoring opposite follower who changed in this step\n";
834  }
835 #endif
836  } else {
837  blocked |= blockedByFollower;
838  }
839  }
840  }
841 
842  // safe front gap
843  if ((blocked & blockedByLeader) == 0 && neighLead.first != nullptr) {
844  // Calculate secure gap conservatively with vNextFollower / vNextLeader as
845  // extrapolated speeds after the driver's expected reaction time (tau).
846  // NOTE: there exists a possible source for collisions if the follower and the leader
847  // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
848 
849  // Expected reaction time (tau) for the follower-vehicle.
850  // (subtracted TS since at this point the vehicles' states are already updated)
851  const double vNextFollower = vehicle->getSpeed() + MAX2(0., tauRemainder * vehicle->getAcceleration());
852  const double vNextLeader = neighLead.first->getSpeed() + MIN2(0., tauRemainder * neighLead.first->getAcceleration());
853  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
854  secureFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead.first, vNextFollower,
855  vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel());
856 #ifdef DEBUG_CHECK_CHANGE
857  if (DEBUG_COND) {
858  std::cout << SIMTIME
859  << " leader=" << neighLead.first->getID()
860  << " frontGap=" << neighLead.second
861  << " vNextEgo=" << vNextFollower
862  << " vNextLeader=" << vNextLeader
863  << " secureGap=" << secureFrontGap
864  << " safetyFactor=" << vehicle->getLaneChangeModel().getSafetyFactor()
865  << " blocked=" << (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor())
866  << "\n";
867  }
868 #endif
869  if (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
870  blocked |= blockedByLeader;
871  }
872  }
873  if (blocked == 0 && targetLane->hasPedestrians()) {
874  PersonDist nextLeader = targetLane->nextBlocking(vehicle->getBackPositionOnLane(),
875  vehicle->getRightSideOnLane(), vehicle->getRightSideOnLane() + vehicle->getVehicleType().getWidth(),
876  ceil(vehicle->getSpeed() / vehicle->getCarFollowModel().getMaxDecel()));
877  if (nextLeader.first != 0) {
878  const double brakeGap = vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed());
879  // returned gap value is relative to backPosition
880  const double gap = nextLeader.second - vehicle->getVehicleType().getLengthWithGap();
881 #ifdef DEBUG_CHECK_CHANGE
882  if (DEBUG_COND) {
883  std::cout << SIMTIME << " pedestrian on road " + leader.first->getID() << " gap=" << gap << " brakeGap=" << brakeGap << "\n";
884  }
885 #endif
886  if (brakeGap > gap) {
887  blocked |= blockedByLeader;
888 #ifdef DEBUG_CHECK_CHANGE
889  if (DEBUG_COND) {
890  std::cout << SIMTIME << " blocked by pedestrian " + leader.first->getID() << "\n";
891  }
892 #endif
893  }
894  }
895  }
896 
897  if (leader.first != nullptr) {
898  secureOrigFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle, leader.first, vehicle->getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
899  }
900 
901  MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
902  int state = blocked | vehicle->getLaneChangeModel().wantsChange(
903  laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
904 
905  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != nullptr) {
906  // do a more careful (but expensive) check to ensure that a
907  // safety-critical leader is not being overlooked
908  // while changing on an intersection, it is not sufficient to abort the
909  // search with a leader on the current lane because all linkLeaders must
910  // be considered as well
911  const double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
912  const double speed = vehicle->getSpeed();
913  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
914  if (seen < dist || myCandi->lane->isInternal()) {
915  std::pair<MSVehicle* const, double> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
916  if (neighLead2.first != nullptr && neighLead2.first != neighLead.first) {
917  const double secureGap = vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead2.first, vehicle->getSpeed(),
918  neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
919  const double secureGap2 = secureGap * vehicle->getLaneChangeModel().getSafetyFactor();
920 #ifdef DEBUG_SURROUNDING_VEHICLES
921  if (DEBUG_COND) {
922  std::cout << SIMTIME << " found critical leader=" << neighLead2.first->getID()
923  << " gap=" << neighLead2.second << " secGap=" << secureGap << " secGap2=" << secureGap2 << "\n";
924  }
925 #endif
926  if (neighLead2.second < secureGap2) {
927  state |= blockedByLeader;
928  }
929  }
930  }
931  }
932  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
933  // ensure that merging is safe for any upcoming zipper links after changing
934  if (vehicle->unsafeLinkAhead(targetLane)) {
935  state |= blockedByLeader;
936  }
937  }
938 
939  if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
940  // Ensure that a continuous lane change manoeuvre can be completed before the next turning movement.
941  // Assume lateral position == 0. (If this should change in the future add + laneOffset*vehicle->getLateralPositionOnLane() to distToNeighLane)
942  const double distToNeighLane = 0.5 * (vehicle->getLane()->getWidth() + targetLane->getWidth());
943  // Extrapolate the LC duration if operating with speed dependent lateral speed.
944  const MSAbstractLaneChangeModel& lcm = vehicle->getLaneChangeModel();
945  const double assumedDecel = lcm.getAssumedDecelForLaneChangeDuration();
946  const double estimatedLCDuration = lcm.estimateLCDuration(vehicle->getSpeed(), distToNeighLane, assumedDecel, (state & LCA_URGENT) != 0);
947  if (estimatedLCDuration == -1) {
948  // Can't guarantee that LC will succeed if vehicle is braking -> assert(lcm.myMaxSpeedLatStanding==0)
949 #ifdef DEBUG_CHECK_CHANGE
950  if (DEBUG_COND) {
951  std::cout << SIMTIME << " checkChange() too slow to guarantee completion of continuous lane change."
952  << "\nestimatedLCDuration=" << estimatedLCDuration
953  << "\ndistToNeighLane=" << distToNeighLane
954  << std::endl;
955  }
956 #endif
957  state |= LCA_INSUFFICIENT_SPEED;
958  } else {
959  // Compute covered distance, when braking for the whole lc duration
960  const double decel = vehicle->getCarFollowModel().getMaxDecel() * estimatedLCDuration;
961  const double avgSpeed = 0.5 * (
962  MAX2(0., vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
963  MAX2(0., vehicle->getSpeed() - decel));
964  // Distance required for lane change.
965  const double space2change = avgSpeed * estimatedLCDuration;
966  // Available distance for LC maneuver (distance till next turn)
967  double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
968 #ifdef DEBUG_CHECK_CHANGE
969  if (DEBUG_COND) {
970  std::cout << SIMTIME << " checkChange() checking continuous lane change..."
971  << "\ndistToNeighLane=" << distToNeighLane
972  << " estimatedLCDuration=" << estimatedLCDuration
973  << " space2change=" << space2change
974  << " avgSpeed=" << avgSpeed
975  << std::endl;
976  }
977 #endif
978 
979  // for finding turns it doesn't matter whether we look along the current lane or the target lane
980  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
981  int view = 1;
982  const MSLane* nextLane = vehicle->getLane();
983  std::vector<MSLink*>::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
984  while (!nextLane->isLinkEnd(link) && seen <= space2change) {
985  if ((*link)->getDirection() == LinkDirection::LEFT || (*link)->getDirection() == LinkDirection::RIGHT
986  // the lanes after an internal junction are on different
987  // edges and do not allow lane-changing
988  || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
989  ) {
990  state |= LCA_INSUFFICIENT_SPACE;
991  break;
992  }
993  if ((*link)->getViaLane() == nullptr) {
994  view++;
995  }
996  nextLane = (*link)->getViaLaneOrLane();
997  seen += nextLane->getLength();
998  // get the next link used
999  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1000  }
1001 #ifdef DEBUG_CHECK_CHANGE
1002  if (DEBUG_COND) {
1003  std::cout << " available distance=" << seen << std::endl;
1004  }
1005 #endif
1006  if (nextLane->isLinkEnd(link) && seen < space2change) {
1007 #ifdef DEBUG_CHECK_CHANGE
1008  if (DEBUG_COND) {
1009  std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
1010  }
1011 #endif
1012  state |= LCA_INSUFFICIENT_SPACE;
1013  }
1014 
1015  if ((state & LCA_BLOCKED) == 0) {
1016  // check for dangerous leaders in case the target lane changes laterally between
1017  // now and the lane-changing midpoint
1018  const double speed = vehicle->getSpeed();
1019  seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
1020  nextLane = vehicle->getLane();
1021  view = 1;
1022  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
1023  std::vector<MSLink*>::const_iterator nextLink = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1024  while (!nextLane->isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1025  nextLane = (*nextLink)->getViaLaneOrLane();
1026  const MSLane* const parallelLane = nextLane->getParallelLane(laneOffset);
1027  if (parallelLane == nullptr) {
1028  state |= LCA_INSUFFICIENT_SPACE;
1029  break;
1030  } else {
1031  std::pair<MSVehicle* const, double> neighLead2 = parallelLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
1032  if (neighLead2.first != nullptr && neighLead2.first != neighLead.first
1033  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead2.first,
1034  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1035  state |= blockedByLeader;
1036  break;
1037  }
1038  }
1039  if ((*nextLink)->getViaLane() == nullptr) {
1040  view++;
1041  }
1042  seen += nextLane->getLength();
1043  // get the next link used
1044  nextLink = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1045  }
1046  }
1047  }
1048  }
1049  const int oldstate = state;
1050  // let TraCI influence the wish to change lanes and the security to take
1051  state = vehicle->influenceChangeDecision(state);
1052 #ifdef DEBUG_CHECK_CHANGE
1053  if (DEBUG_COND) {
1054  std::cout << SIMTIME
1055  << " veh=" << vehicle->getID()
1056  << " oldState=" << toString((LaneChangeAction)oldstate)
1057  << " newState=" << toString((LaneChangeAction)state)
1058  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
1059  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
1060  << "\n";
1061  }
1062 #endif
1063 
1064  if (state & LCA_WANTS_LANECHANGE && blocked == 0) {
1065  blocked = vehicle->getLaneChangeModel().checkChangeBeforeCommitting(vehicle, state);
1066  state |= blocked;
1067  }
1068  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
1069  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
1070  // this lane change will be executed, save gaps
1071  vehicle->getLaneChangeModel().setFollowerGaps(neighFollow, secureBackGap);
1072  vehicle->getLaneChangeModel().setLeaderGaps(neighLead, secureFrontGap);
1073  vehicle->getLaneChangeModel().setOrigLeaderGaps(leader, secureOrigFrontGap);
1074  }
1075  if (laneOffset != 0) {
1076  vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollow, neighLead);
1077  }
1078  return state;
1079 }
1080 
1081 bool
1083  if (vehicle->hasStops()) {
1084  const MSStop& stop = vehicle->getNextStop();
1085  if (stop.isOpposite && vehicle->nextStopDist() < OPPOSITE_OVERTAKING_MAX_LOOKAHEAD) {
1086  return true;
1087  }
1088  }
1089  return false;
1090 }
1091 
1092 
1093 bool
1094 MSLaneChanger::checkOppositeStop(MSVehicle* vehicle, const MSLane* oncomingLane, const MSLane* opposite, std::pair<MSVehicle*, double> leader) {
1095  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1096  double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1097  std::pair<MSVehicle*, double> neighLead(nullptr, -1);
1098  std::pair<MSVehicle*, double> oncoming(nullptr, -1);
1099  const std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, vehicle->getNextStop().lane, -1);
1100  const int laneIndex = vehicle->getLaneChangeModel().getNormalizedLaneIndex();
1101  const int bestOffset = preb[laneIndex].bestLaneOffset;
1102  //std::cout << SIMTIME << " veh=" << vehicle->getID() << " laneIndex=" << laneIndex << " bestOffset=" << bestOffset << " target=" << target->getID() << "\n";
1103 
1104  // compute safety constraints (assume vehicle is safe once stop is reached)
1105  const double spaceToStop = vehicle->nextStopDist();
1106  const double timeToStopForward = spaceToStop / MAX2(vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxAccel());
1107  const double timeToStopLateral = (MSGlobals::gLaneChangeDuration > 0
1110  ? bestOffset * SUMO_const_laneWidth / vehicle->getVehicleType().getMaxSpeedLat()
1111  : 0.));
1112  const double timeToStop = MAX2(timeToStopForward, timeToStopLateral);
1113  if (!isOpposite) {
1114  // we keep neighLead distinct from oncoming because it determines blocking on the neigh lane
1115  // but also look for an oncoming leader to compute safety constraint
1116  const double searchDist = timeToStop * oncomingLane->getSpeedLimit() * 2 + spaceToStop;
1117  neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1118  oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax);
1119  } else {
1120  double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
1121  oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1122  oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax);
1123  }
1124  double oncomingSpeed;
1125  const double surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1126  if (!isOpposite && surplusGap < 0) {
1127 #ifdef DEBUG_CHANGE_OPPOSITE
1128  if (DEBUG_COND) {
1129  std::cout << " cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1130  << " timeToStopForward=" << timeToStopForward << " timeToStopLateral=" << timeToStopLateral << " surplusGap=" << surplusGap << "\n";
1131  }
1132 #endif
1133  return false;
1134  }
1135 
1136  if (bestOffset > 0) {
1137  MSLane* const target = preb[laneIndex + 1].lane;
1138  neighLead = target->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_MAX_LOOKAHEAD, true);
1139  std::pair<MSVehicle* const, double> neighFollow = target->getOppositeFollower(vehicle);
1140  return checkChangeOpposite(vehicle, 1, target, leader, neighLead, neighFollow, preb);
1141  } else {
1142  // return prematurely (due to foe?)
1143  //return checkChangeOpposite(vehicle, -1, target, leader, neighLead, neighFollow, preb);
1144  return false;
1145  }
1146 }
1147 
1148 
1149 std::vector<MSVehicle::LaneQ>
1150 MSLaneChanger::getBestLanesOpposite(MSVehicle* vehicle, const MSLane* stopLane, double oppositeLength) {
1151  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1152  const MSEdge* forward = isOpposite ? vehicle->getLane()->getEdge().getOppositeEdge()->getNormalSuccessor() : vehicle->getLane()->getEdge().getNormalSuccessor();
1153  const MSEdge* opposite = forward->getOppositeEdge();
1154  const int numForward = forward->getNumLanes();
1155  const int numOpposite = opposite->getNumLanes();
1156  const std::vector<MSLane*>& oLanes = opposite->getLanes();
1157  std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
1158  for (int i = 0; i < numOpposite; i++) {
1159  preb.push_back(preb.back());
1160  preb.back().lane = oLanes[numOpposite - 1 - i];
1161  preb.back().length = oppositeLength;
1162  if (isOpposite) {
1163  preb.back().bestLaneOffset = -1 - i;
1164  //std::cout << " oi=" << i << " bestOffset =" << preb.back().bestLaneOffset << "\n";
1165  }
1166  }
1167  if (stopLane != nullptr) {
1168  const int stopIndex = numForward + numOpposite - stopLane->getIndex() - 1;
1169  for (int i = 0; i < (int)preb.size(); i++) {
1170  preb[i].bestLaneOffset = stopIndex - i;
1171  preb[i].length = vehicle->getLaneChangeModel().getForwardPos() + vehicle->nextStopDist();
1172  //std::cout << " oi2=" << i << " stopIndex=" << stopIndex << " bestOffset =" << preb[i].bestLaneOffset << " stopDist=" << vehicle->nextStopDist() << " length=" << preb[i].length << "\n";
1173  }
1174  }
1175 #ifdef DEBUG_CHANGE_OPPOSITE
1176  if (DEBUG_COND) {
1177  std::cout << SIMTIME << " getBestLanesOpposite " << vehicle->getID() << " isOpposite=" << isOpposite << "\n";
1178  for (int i = 0; i < (int)preb.size(); i++) {
1179  std::cout << " i=" << i << " lane=" << preb[i].lane->getID() << " bestOffset=" << preb[i].bestLaneOffset << " length=" << preb[i].length << "\n";
1180  }
1181  }
1182 #endif
1183  return preb;
1184 }
1185 
1186 
1187 bool
1188 MSLaneChanger::changeOpposite(MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, MSVehicle* lastStopped) {
1189  // Evaluate lane-changing between opposite direction lanes
1190  if (!myChangeToOpposite) {
1191  return false;
1192  }
1193  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1194  MSLane* source = vehicle->getMutableLane();
1195  MSLane* opposite = isOpposite ? source->getParallelLane(1) : source->getOpposite();
1196 
1197 #ifdef DEBUG_CHANGE_OPPOSITE
1199  if (DEBUG_COND) {
1200  std::cout << SIMTIME << " veh=" << vehicle->getID() << " considerChangeOpposite source=" << source->getID()
1201  << " opposite=" << Named::getIDSecure(opposite) << " lead=" << Named::getIDSecure(leader.first) << " isOpposite=" << isOpposite << "\n";
1202  }
1203 #endif
1204  //There is no lane for opposite driving
1205  if (opposite == nullptr) {
1206  return false;
1207  }
1208  if (vehicle->isStopped()) {
1209  // stopped vehicles obviously should not change lanes. Usually this is
1210  // prevent by appropriate bestLane distances
1211  return false;
1212  }
1213  int ret = 0;
1214  ret = vehicle->influenceChangeDecision(ret);
1215  bool oppositeChangeByTraci = false;
1216  // Check whether a lane change to the opposite direction was requested via TraCI
1217  if ((ret & (LCA_TRACI)) != 0) {
1218  if (isOpposite && (ret & LCA_LEFT) != 0) {
1219  // stay on the opposite side
1220  return false;
1221  }
1222  oppositeChangeByTraci = true;
1223  }
1224  if (!isOpposite && !oppositeChangeByTraci && !source->allowsChangingLeft(vehicle->getVClass())) {
1225  // lane changing explicitly forbidden from this lane
1226 #ifdef DEBUG_CHANGE_OPPOSITE
1227  if (DEBUG_COND) {
1228  std::cout << " not overtaking due to changeLeft restriction\n";
1229  }
1230 #endif
1231  return false;
1232  }
1233 
1234  //lane for opposite driving is not permitted
1235  if (!opposite->allowsVehicleClass(vehicle->getVClass())) {
1236  return false;
1237  }
1238 
1239  const MSLane* oncomingLane = isOpposite ? source : opposite;
1240  //const MSLane* forwardLane = isOpposite ? opposite : source;
1241  // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
1242  int direction = isOpposite ? -1 : 1;
1243  std::pair<MSVehicle*, double> neighLead(nullptr, -1);
1244 
1245  // distance that can safely be driven on the opposite side
1246  double surplusGap = std::numeric_limits<double>::max();
1247 
1248  // we need to find two vehicles:
1249  // 1) the leader that shall be overtaken (not necessarily the current leader but one of its leaders that has enough space in front)
1250  // 2) the oncoming vehicle (we need to look past vehicles that are currently overtaking through the opposite direction themselves)
1251  //
1252  // if the vehicle is driving normally, then the search for 1) starts on the current lane and 2) on the opposite lane
1253  // if the vehicle is driving on the opposite side then 1) is found on the neighboring lane and 2) on the current lane
1254 
1255  std::pair<MSVehicle*, double> overtaken(nullptr, -1);
1256  // oncoming vehicle that is driving in the "correct" direction
1257  std::pair<MSVehicle*, double> oncoming(nullptr, -1);
1258  // oncoming vehicle that is driving against the flow
1259  std::pair<MSVehicle*, double> oncomingOpposite(nullptr, -1);
1260  // the maximum speed while overtaking (may be lowered if slow vehicles are
1261  // currently overtaking ahead of vehicle)
1262  double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1263  double oncomingSpeed = oncomingLane->getSpeedLimit();
1264 
1265  // check for opposite direction stop
1266  if (!oppositeChangeByTraci && hasOppositeStop(vehicle)) {
1267  return checkOppositeStop(vehicle, oncomingLane, opposite, leader);
1268  }
1269 
1270  if (!isOpposite && leader.first == nullptr && !oppositeChangeByTraci) {
1271  // no reason to change unless there is a leader
1272  // or we are changing back to the propper direction
1273  // XXX also check whether the leader is so far away as to be irrelevant
1274  return false;
1275  }
1276  if (!isOpposite && !oppositeChangeByTraci
1277  && vehicle->getVClass() != SVC_EMERGENCY
1278  && leader.first != nullptr) {
1279  if (leader.first->signalSet(MSGlobals::gLefthand
1281  // do not try to overtake a vehicle that is about to turn left or wants
1282  // to change left itself
1283 #ifdef DEBUG_CHANGE_OPPOSITE
1284  if (DEBUG_COND) {
1285  std::cout << " not overtaking leader " << leader.first->getID() << " that has blinker set\n";
1286  }
1287 #endif
1288  if (lastStopped != nullptr && vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT) {
1289  neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1290  const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
1291  resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1292  }
1293  return false;
1294  } else if (leader.second < 0) {
1295  // leaders is either a junction leader (that cannot be overtaken) or something else is wrong
1296 #ifdef DEBUG_CHANGE_OPPOSITE
1297  if (DEBUG_COND) {
1298  std::cout << " not overtaking leader " << leader.first->getID() << " with gap " << leader.second << "\n";
1299  }
1300 #endif
1301  return false;
1302  }
1303  }
1304 
1305  // checks for overtaking space
1306  double timeToOvertake = std::numeric_limits<double>::max();
1307  double spaceToOvertake = std::numeric_limits<double>::max();
1308  double maxSpaceToOvertake = 0;
1309 
1310  if (oppositeChangeByTraci) {
1311  timeToOvertake = STEPS2TIME(vehicle->getInfluencer().getLaneTimeLineDuration());//todo discuss concept
1312  spaceToOvertake = timeToOvertake * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1313  } else {
1314  if (isOpposite) {
1315  // -1 will use getMaximumBrakeDist() as look-ahead distance
1316  neighLead = opposite->getOppositeLeader(vehicle, -1, false);
1317  // make sure that overlapping vehicles on the neighboring lane are found by starting search at the back position
1318  overtaken = opposite->getLeader(vehicle, opposite->getOppositePos(vehicle->getBackPositionOnLane()), vehicle->getBestLanesContinuation(opposite));
1319  overtaken.second -= vehicle->getVehicleType().getLength();
1320  if (overtaken.first == nullptr && neighLead.first != nullptr) {
1321  overtaken = neighLead;
1322  }
1323  if (overtaken.first != nullptr) {
1324  overtaken = getColumnleader(maxSpaceToOvertake, vehicle, overtaken);
1325  }
1326 #ifdef DEBUG_CHANGE_OPPOSITE
1327  if (DEBUG_COND) {
1328  std::cout << " leaderOnSource=" << Named::getIDSecure(oncoming.first) << " gap=" << oncoming.second << "\n";
1329  std::cout << " leaderOnTarget=" << Named::getIDSecure(neighLead.first) << " gap=" << neighLead.second << "\n";
1330  std::cout << " overtaken=" << Named::getIDSecure(overtaken.first) << " gap=" << overtaken.second << "\n";
1331  }
1332 #endif
1333  } else {
1334  overtaken = getColumnleader(maxSpaceToOvertake, vehicle, leader);
1335  }
1336 
1337  if (overtaken.first == 0) {
1338  if (!isOpposite) {
1339  // no reason to change to the opposite side
1340 #ifdef DEBUG_CHANGE_OPPOSITE
1341  if (DEBUG_COND) {
1342  std::cout << " no leader found\n";
1343  }
1344 #endif
1346  neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1347  resolveDeadlock(vehicle, leader, neighLead, std::make_pair(nullptr, leader.second));
1348  }
1349  return false;
1350  }
1351  } else {
1352 #ifdef DEBUG_CHANGE_OPPOSITE
1353  if (DEBUG_COND) {
1354  std::cout << " compute time/space to overtake for columnLeader=" << overtaken.first->getID() << " egoGap=" << overtaken.second << "\n";
1355  }
1356 #endif
1357  // if we have limited space to overtake, we may have to limit our maximum maneuver speed
1358  vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, maxSpaceToOvertake));
1359  // there might be leader vehicles on the opposite side that also drive
1360  // against the flow which are slower than ego (must be factored into
1361  // overtaking time)
1362  computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1363 #ifdef DEBUG_CHANGE_OPPOSITE
1364  if (DEBUG_COND) {
1365  std::cout << SIMTIME
1366  << " veh=" << vehicle->getID()
1367  << " changeOpposite opposite=" << opposite->getID()
1368  << " lead=" << Named::getIDSecure(leader.first)
1369  << " maxSpaceToOvertake=" << maxSpaceToOvertake
1370  << " vMax=" << vMax
1371  << " timeToOvertake=" << timeToOvertake
1372  << " spaceToOvertake=" << spaceToOvertake
1373  << "\n";
1374  }
1375 #endif
1376 
1377  if (!isOpposite && spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
1378 #ifdef DEBUG_CHANGE_OPPOSITE
1379  if (DEBUG_COND) {
1380  std::cout << " cannot changeOpposite (cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
1381  }
1382 #endif
1383  neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1384  bool wait = false;
1386  wait = resolveDeadlock(vehicle, leader, neighLead, overtaken);
1387  }
1388  if (!wait && lastStopped != nullptr) {
1389  const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
1390 #ifdef DEBUG_CHANGE_OPPOSITE
1391  if (DEBUG_COND) {
1392  std::cout << " lastStopped=" << Named::getIDSecure(lastStopped) << " gap=" << lastStoppedGap << "\n";
1393  }
1394 #endif
1395  avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1396  }
1397  return false;
1398  }
1399  }
1400 
1401  // if we have a leader vehicle that is driving in the opposite
1402  // direction, it may slow us down (update vMax)
1403  if (!isOpposite) {
1404  assert(timeToOvertake != std::numeric_limits<double>::max());
1405  assert(spaceToOvertake != std::numeric_limits<double>::max());
1406  // we keep neighLead distinct from oncoming because it determines blocking on the neigh lane
1407  // but also look for an oncoming leader to compute safety constraint
1408  double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 2 + spaceToOvertake;
1409  neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1410  oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1411  oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
1412  } else {
1413  double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
1414  oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1415  oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1416  oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
1417  }
1418  if (oncoming.first != nullptr && (oncoming.first->isStopped()
1419  || oncoming.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT)) {
1420  // finish overtaking within the available space
1421  const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1422  if (oncomingGap > 0) {
1423  vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, oncomingGap));
1424  }
1425 #ifdef DEBUG_CHANGE_OPPOSITE
1426  if (DEBUG_COND) {
1427  std::cout << " oncoming=" << oncoming.first->getID() << " stopped=" << oncoming.first->isStopped()
1428  << " halting=" << oncoming.first->getWaitingSeconds()
1429  << " oncomingGap=" << oncomingGap
1430  << " vMaxGap=" << getMaxOvertakingSpeed(vehicle, oncomingGap)
1431  << " vMax=" << vMax << "\n";
1432  }
1433 #endif
1434  }
1435 
1436  if (overtaken.first != nullptr && vMax != vehicle->getLane()->getVehicleMaxSpeed(vehicle)) {
1437  // recompute overtaking time with slow opposite leader
1438  computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1439 #ifdef DEBUG_CHANGE_OPPOSITE
1440  if (DEBUG_COND) {
1441  std::cout << " recomputed overtaking time with vMax=" << vMax
1442  << " timeToOvertake=" << timeToOvertake
1443  << " spaceToOvertake=" << spaceToOvertake
1444  << "\n";
1445  }
1446 #endif
1447  }
1448  if (!isOpposite) {
1449  if (spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
1450 #ifdef DEBUG_CHANGE_OPPOSITE
1451  if (DEBUG_COND) {
1452  std::cout << " cannot changeOpposite (check2: cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
1453  }
1454 #endif
1455  resolveDeadlock(vehicle, leader, neighLead, overtaken);
1456  return false;
1457  }
1458  // check for upcoming stops
1459  if (vehicle->nextStopDist() < spaceToOvertake) {
1460 #ifdef DEBUG_CHANGE_OPPOSITE
1461  if (DEBUG_COND) {
1462  std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
1463  }
1464 #endif
1465  return false;
1466  }
1467  assert(timeToOvertake != std::numeric_limits<double>::max());
1468  assert(spaceToOvertake != std::numeric_limits<double>::max());
1469  }
1470 
1471  // check for dangerous oncoming leader
1472  surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1473  if (oncomingOpposite.first != nullptr) {
1474  double oncomingSpeed2;
1475  const double conservativeTime = ceil(timeToOvertake / TS) * TS;
1476  const double conservativeSpace = conservativeTime * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1477  const double surplusGap2 = computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2, true);
1478 #ifdef DEBUG_CHANGE_OPPOSITE
1479  if (DEBUG_COND) {
1480  std::cout << " oncomingOpposite=" << oncomingOpposite.first->getID() << " speed=" << oncomingSpeed2 << " gap=" << oncomingOpposite.second << " surplusGap2=" << surplusGap2 << "\n";
1481  }
1482 #endif
1483  surplusGap = MIN2(surplusGap, surplusGap2);
1484  oncomingSpeed = MAX2(oncomingSpeed, oncomingSpeed2);
1485  if (!isOpposite && surplusGap >= 0 && oncoming.first != nullptr && oncoming.first->isStopped()
1486  && oncomingOpposite.second > oncoming.second) {
1487  // even if ego can change back and forth successfully, we have to
1488  // make sure that the oncoming vehicle can also finish its lane
1489  // change in time
1490  const double oSpeed = MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1491  // conservative estimate
1492  const double closingSpeed = (vehicle->getLane()->getVehicleMaxSpeed(vehicle)
1493  + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1494  const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1495  double ooTTO = ooSTO / oSpeed;
1496  // round to multiples of step length (TS)
1497  ooTTO = ceil(ooTTO / TS) * TS;
1498  const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1499 #ifdef DEBUG_CHANGE_OPPOSITE
1500  if (DEBUG_COND) {
1501  std::cout << " oSpeed=" << oSpeed << " ooSTO=" << ooSTO << " ooTTO=" << ooTTO << " surplusGap3=" << surplusGap3 << "\n";
1502  }
1503 #endif
1504  surplusGap = MIN2(surplusGap, surplusGap3);
1505  }
1506  }
1507  if (!isOpposite && surplusGap < 0) {
1508 #ifdef DEBUG_CHANGE_OPPOSITE
1509  if (DEBUG_COND) {
1510  std::cout << " cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap << ")\n";
1511  }
1512 #endif
1513 
1514 #ifdef DEBUG_CHANGE_OPPOSITE
1515  if (DEBUG_COND) {
1516  if (oncoming.first->getLaneChangeModel().isOpposite()) {
1517  std::cout << SIMTIME << " ego=" << vehicle->getID() << " does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() << " (but the leader is also opposite)\n";
1518  }
1519  }
1520 #endif
1521  avoidDeadlock(vehicle, neighLead, overtaken, leader);
1522  return false;
1523  }
1524  }
1525  // compute remaining space on the opposite side
1526  // 1. the part that remains on the current lane
1527  double usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane();
1528 
1529  if (usableDist < spaceToOvertake) {
1530  // look forward along the next lanes
1531  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
1532  assert(bestLaneConts.size() >= 1);
1533  std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1534  while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1535 #ifdef DEBUG_CHANGE_OPPOSITE
1536  if (DEBUG_COND) {
1537  std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n";
1538  }
1539 #endif
1540  if ((*it)->getOpposite() == nullptr || !(*it)->getOpposite()->allowsVehicleClass(vehicle->getVClass())) {
1541  // opposite lane ends
1542  break;
1543  }
1544  // do not overtake past a minor link or turn
1545  const MSLane* const prev = *(it - 1);
1546  if (prev != nullptr) {
1547  const MSLink* link = prev->getLinkTo(*it);
1548  if (link == nullptr || link->getState() == LINKSTATE_ZIPPER
1550  || (!link->havePriority()
1551  // consider traci-influence
1552  && (!vehicle->hasInfluencer() || vehicle->getInfluencer().getRespectJunctionPriority())
1553  // consider junction model parameters
1554  && ((!link->haveRed() && !link->haveYellow()) || !vehicle->ignoreRed(link, true)))) {
1555 #ifdef DEBUG_CHANGE_OPPOSITE
1556  if (DEBUG_COND) {
1557  std::cout << " stop lookahead at link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID()) << " state=" << (link == 0 ? "?" : toString(link->getState())) << " ignoreRed=" << vehicle->ignoreRed(link, true) << "\n";
1558  }
1559 #endif
1560  break;
1561  }
1562  }
1563  usableDist += (*it)->getLength();
1564  ++it;
1565  }
1566  }
1567  if (!isOpposite && usableDist < spaceToOvertake) {
1568 #ifdef DEBUG_CHANGE_OPPOSITE
1569  if (DEBUG_COND) {
1570  std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n";
1571  }
1572 #endif
1573  return false;
1574  }
1575  if (!isOpposite && MSNet::getInstance()->hasElevation() && !overtaken.first->isStopped()) {
1576  // do not overtake before the top of a hill
1577  double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 1.5 * vehicle->getLaneChangeModel().getOppositeSafetyFactor() + spaceToOvertake;
1578  int view = vehicle->getLane()->isInternal() ? 1 : 0;
1579  bool foundHill = vehicle->getSlope() > 0;
1580  if (foundHilltop(vehicle, foundHill, searchDist, vehicle->getBestLanesContinuation(), view, vehicle->getPositionOnLane(), vehicle->getPosition().z(), OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD)) {
1581  return false;
1582  }
1583  }
1584 #ifdef DEBUG_CHANGE_OPPOSITE
1585  if (DEBUG_COND) {
1586  std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
1587  }
1588 #endif
1589  // compute wish to change
1590  std::pair<MSVehicle* const, double> neighFollow = opposite->getOppositeFollower(vehicle);
1591  double oppositeLength = vehicle->getBestLanes().back().length;
1592  if (isOpposite) {
1593  const bool canOvertake = spaceToOvertake <= OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE;
1594  oppositeLength = computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1595  leader.first = nullptr;
1596  if (neighLead.first != nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1597  // ignore oncoming vehicle on the target lane (it might even change back in this step)
1598  neighLead.first = nullptr;
1599  }
1600  } else {
1601  if (leader.first != nullptr && neighLead.first != nullptr && leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT
1602  && vehicle->getVehicleType().getVehicleClass() != SVC_EMERGENCY) {
1603 #ifdef DEBUG_CHANGE_OPPOSITE
1604  if (DEBUG_COND) {
1605  std::cout << " not changing to avoid deadlock\n";
1606  }
1607 #endif
1608  return false;
1609  }
1610  if (neighLead.first != nullptr && neighLead.first->isStopped()) {
1611  // do not start overtaking if the opposite side has been waitin for longer
1612  if (yieldToOppositeWaiting(vehicle, neighLead.first, 10)) {
1613  return false;
1614  }
1615  }
1616  if (oncoming.first != nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1617  // only abort the current column of overtaking vehicles if the opposite side has been waiting long enough
1618  if (yieldToOppositeWaiting(vehicle, oncoming.first, 10, TIME2STEPS(60))) {
1619  return false;
1620  }
1621  }
1622  }
1623  std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, nullptr, oppositeLength);
1624  return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1625 }
1626 
1627 
1628 bool
1630  std::pair<MSVehicle*, double> neighLead,
1631  std::pair<MSVehicle*, double> overtaken,
1632  std::pair<MSVehicle*, double> leader) {
1633  assert(!vehicle->getLaneChangeModel().isOpposite());
1634 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1635  if (DEBUG_COND) {
1636  std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1637  << " neighLead=" << Named::getIDSecure(neighLead.first)
1638  << " overtaken=" << Named::getIDSecure(overtaken.first)
1639  << " leader=" << Named::getIDSecure(leader.first)
1640  << "\n";
1641  }
1642 #endif
1643  if (leader.first == nullptr || neighLead.first == nullptr || overtaken.first == nullptr) {
1644  return false;
1645  } else if (!neighLead.first->isStopped()
1647  // possibly there is an oncoming vehicle before the stoppled leader that
1648  // could drive due to our yielding
1649  auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1650  neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1651  neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1652 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1653  if (DEBUG_COND) {
1654  std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
1655  }
1656 #endif
1657  if (neighLead.first == nullptr) {
1658  return false;
1659  }
1660  }
1661 
1662  const bool yield = (yieldToDeadlockOncoming(vehicle, neighLead.first, overtaken.second)
1663  || leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT);
1664  if (neighLead.first->isStopped()
1665  && (overtaken.first->isStopped()
1666  || leader.first->getLaneChangeModel().isOpposite()
1667  || yield)) {
1668 
1669  // estimate required gap
1670  double requiredGap = MAX2(vehicle->getVehicleType().getLengthWithGap(), neighLead.first->getVehicleType().getLengthWithGap());
1671  requiredGap = MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1672  requiredGap = MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1673  requiredGap += 1;
1674  const double distToStop = neighLead.second - requiredGap;
1675 
1676  // find the next non-stopped vehicle behind neighLead
1677  double neighStoppedBack = vehicle->getVehicleType().getMinGap();
1678  while (neighLead.first != nullptr && neighLead.first->isStopped()) {
1679  const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1680  if (neighStoppedBack + nextGap > overtaken.second) {
1681  break;
1682  }
1683  neighStoppedBack += nextGap;
1684  auto neighLeadFollow = neighLead.first->getFollower();
1685  neighLead.second = neighLeadFollow.second;
1686  neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1687 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1688  if (DEBUG_COND) {
1689  std::cout << " neighLeadFollower=" << Named::getIDSecure(neighLead.first) << "\n";
1690  }
1691 #endif
1692  if (neighStoppedBack > overtaken.second) {
1693  break;
1694  }
1695  }
1696 
1697  const double leaderBGap = leader.first->getBrakeGap();
1698  const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->getBestLanesContinuation(), overtaken.second, true).second;
1699  const double extraGap = MAX2(leaderBGap, leaderFGap);
1700  const double gapWithEgo = leader.second + extraGap - neighStoppedBack - vehicle->getVehicleType().getLengthWithGap();
1701 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1702  if (DEBUG_COND) {
1703  std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1704  << " neighLeadGap=" << neighLead.second
1705  << " leaderGap=" << leader.second
1706  << " bGap=" << leaderBGap
1707  << " fGap=" << leaderFGap
1708  << " eGap=" << extraGap
1709  << " neighStoppedBack=" << neighStoppedBack
1710  << " neighStoppedBackPos=" << vehicle->getPositionOnLane() + neighStoppedBack
1711  << " requiredGap=" << requiredGap
1712  << " gapWithEgo=" << gapWithEgo
1713  << " yield=" << yield
1714  << "\n";
1715  }
1716 #endif
1717  // vehicle must fit behind leader and still leave required gap
1718  if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1719  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
1720  const double currentDist = preb[vehicle->getLane()->getIndex()].length;
1721  const double stopPos = vehicle->getPositionOnLane() + distToStop;
1722 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1723  if (DEBUG_COND) {
1724  std::cout << " currentDist=" << currentDist << " stopPos=" << stopPos << " lGap+eGap=" << leader.second + extraGap << " distToStop=" << distToStop << "\n";
1725  }
1726 #endif
1727  if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1728  const double blockerLength = currentDist - stopPos;
1729  const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
1730 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1731  if (DEBUG_COND) {
1732  std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1733  << " blockerLength=" << blockerLength
1734  << " reserved=" << reserved
1735  << "\n";
1736  }
1737 #endif
1738  return reserved;
1739  }
1740  }
1741  }
1742  return false;
1743 }
1744 
1745 
1746 bool
1747 MSLaneChanger::yieldToDeadlockOncoming(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist) {
1748  if (vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT && stoppedNeigh != nullptr) {
1749  // is there a vehicle waiting behind stoppedNeigh that is encouraged by
1750  // halting ego? Due to edge-ordering it might change-opposite this step
1751  // and not be visible as leader
1752  std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
1753  double followerGap = stoppedNeigh->getVehicleType().getLengthWithGap();
1754  while (follower.first != nullptr && followerGap < dist && follower.first->isStopped()) {
1755  followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1756  follower = follower.first->getFollower(dist);
1757  };
1758  if (follower.first != nullptr) {
1759  followerGap += follower.second;
1760  }
1761 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1762  if (DEBUG_COND) {
1763  std::cout << SIMTIME << " veh=" << vehicle->getID() << " yieldToDeadlockOncoming"
1764  << " dist=" << dist << " follower=" << Named::getIDSecure(follower.first) << " fGap=" << followerGap
1765  << "\n";
1766  }
1767 #endif
1768  return follower.first != nullptr && followerGap < dist && !follower.first->isStopped();
1769  }
1770  return false;
1771 }
1772 
1773 
1774 bool
1775 MSLaneChanger::yieldToOppositeWaiting(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist, SUMOTime deltaWait) {
1776  std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
1777  while (follower.first != nullptr && follower.second < dist && follower.first->isStopped()) {
1778  follower = follower.first->getFollower(dist);
1779  };
1780 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1781  if (DEBUG_COND && follower.first != nullptr) {
1782  std::cout << SIMTIME << " yieldToOppositeWaiting veh=" << vehicle->getID() << " stoppedNeigh=" << stoppedNeigh->getID()
1783  << " oncoming=" << follower.first->getID()
1784  << " wait=" << follower.first->getWaitingSeconds()
1785  << " vehWait=" << vehicle->getWaitingSeconds()
1786  << " deltaWait=" << STEPS2TIME(deltaWait)
1787  << "\n";
1788  }
1789 #endif
1790  if (follower.first != nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->getWaitingTime() + deltaWait) {
1791  return true;
1792  }
1793  return false;
1794 }
1795 
1796 
1797 bool
1799  std::pair<MSVehicle* const, double> leader,
1800  std::pair<MSVehicle*, double> neighLead,
1801  std::pair<MSVehicle*, double> overtaken) {
1802  const double deadLockZone = overtaken.second;
1803 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1804  if (DEBUG_COND) {
1805  std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock waiting=" << vehicle->getWaitingSeconds()
1806  << " leader=" << Named::getIDSecure(leader.first)
1807  << " gap=" << leader.second
1808  << "\n";
1809  }
1810 #endif
1812  && leader.first != nullptr && leader.second > vehicle->getVehicleType().getLengthWithGap()) {
1813  // assume vehicle is halting to avoid deadlock (since there is enough
1814  // space to drive further)
1815  // keep halting as long as there is an oncoming vehicle
1816  std::pair<MSVehicle* const, double> oncomingOpposite = getOncomingOppositeVehicle(vehicle, std::make_pair(nullptr, -1), leader.second);
1817 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1818  if (DEBUG_COND) {
1819  std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
1820  << " leader=" << leader.first->getID()
1821  << " leaderGap=" << leader.second
1822  << " neighLead=" << Named::getIDSecure(neighLead.first)
1823  << " deadLockZone=" << deadLockZone
1824  << "\n";
1825  }
1826 #endif
1827  if (neighLead.first != nullptr && !neighLead.first->isStopped()) {
1828  // possibly there is an oncoming vehicle before the stoppled leader that
1829  // could drive due to our yielding
1830  auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1831  neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1832  neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1833 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1834  if (DEBUG_COND) {
1835  std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
1836  }
1837 #endif
1838  }
1839 
1840  if (oncomingOpposite.first != nullptr ||
1841  (neighLead.first != nullptr && neighLead.first->isStopped()
1842  && yieldToDeadlockOncoming(vehicle, neighLead.first, deadLockZone))) {
1843  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
1844  const double currentDist = preb[vehicle->getLane()->getIndex()].length;
1845  // mirror code in patchSpeed
1846  const double blockerLength = currentDist - vehicle->getPositionOnLane() - 1 - vehicle->getVehicleType().getMinGap() - NUMERICAL_EPS;
1847  const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
1848 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1849  if (DEBUG_COND) {
1850  std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
1851  << " leader=" << leader.first->getID()
1852  << " leaderGap=" << leader.second
1853  << " oncoming=" << Named::getIDSecure(oncomingOpposite.first)
1854  << " currentDist=" << currentDist
1855  << " blockerLength=" << blockerLength
1856  << " reserved=" << reserved
1857  << "\n";
1858  }
1859 #else
1860  UNUSED_PARAMETER(reserved);
1861 #endif
1862  return true;
1863  }
1864  }
1865  return false;
1866 }
1867 
1868 
1869 double
1870 MSLaneChanger::computeSafeOppositeLength(MSVehicle* vehicle, double oppositeLength, const MSLane* source, double usableDist,
1871  std::pair<MSVehicle*, double> oncoming, double vMax, double oncomingSpeed,
1872  std::pair<MSVehicle*, double> neighLead,
1873  std::pair<MSVehicle*, double> overtaken,
1874  std::pair<MSVehicle*, double> neighFollow,
1875  double surplusGap, const MSLane* opposite,
1876  bool canOvertake) {
1877  // compute the remaining distance that can be driven on the opposite side
1878  // this value will put into oppositeLength of the opposite lanes
1879  // @note: length counts from the start of the current lane
1880  // @note: see MSLaneChangeModel::LC2013::_wantsChange @1092 (isOpposite()
1881  // position on the target lane
1882  const double forwardPos = source->getOppositePos(vehicle->getPositionOnLane());
1883 
1884  // consider usableDist (due to minor links or end of opposite lanes)
1885  oppositeLength = MIN2(oppositeLength, usableDist + forwardPos);
1886  // consider upcoming stops
1887  oppositeLength = MIN2(oppositeLength, vehicle->nextStopDist() + forwardPos);
1888 #ifdef DEBUG_CHANGE_OPPOSITE
1889  if (DEBUG_COND) {
1890  std::cout << " laneQLength=" << oppositeLength << " usableDist=" << usableDist << " forwardPos=" << forwardPos << " stopDist=" << vehicle->nextStopDist() << "\n";
1891  }
1892 #endif
1893  // consider oncoming leaders
1894  const MSVehicle* oncomingVeh = oncoming.first;
1895  if (oncomingVeh != 0) {
1896  if (!oncomingVeh->getLaneChangeModel().isOpposite() && oncomingVeh->getLaneChangeModel().getShadowLane() != source) {
1897  double egoSpeedFraction = 0.5;
1898  if (oncomingSpeed > 0) {
1899  egoSpeedFraction = MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1900  }
1901  oppositeLength = MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1902 #ifdef DEBUG_CHANGE_OPPOSITE
1903  if (DEBUG_COND) {
1904  std::cout << SIMTIME << " found oncoming leader=" << oncomingVeh->getID() << " gap=" << oncoming.second
1905  << " egoSpeedFraction=" << egoSpeedFraction << " newDist=" << oppositeLength << "\n";
1906  }
1907 #endif
1908  } else {
1909 #ifdef DEBUG_CHANGE_OPPOSITE
1910  if (DEBUG_COND) {
1911  std::cout << SIMTIME << " opposite leader=" << oncomingVeh->getID() << " gap=" << oncoming.second << " is driving against the flow\n";
1912  }
1913 #endif
1914  }
1915  if (neighLead.first != nullptr) {
1916  if (overtaken.first == nullptr) {
1917 #ifdef DEBUG_CHANGE_OPPOSITE
1918  if (DEBUG_COND) {
1919  std::cout << SIMTIME << " ego=" << vehicle->getID() << " did not find columnleader to overtake\n";
1920  }
1921 #endif
1922  } else if (oncomingVeh != nullptr && oncomingVeh->isStopped()
1923  && neighLead.second > 0
1924  && neighFollow.second > 0
1925  && yieldToOppositeWaiting(vehicle, oncomingVeh, 10, TIME2STEPS(60))) {
1926  // merge back into the forward lane
1927  oppositeLength = forwardPos + neighLead.second;
1928  } else {
1929  if (surplusGap > 0) {
1930  // exaggerate remaining dist so that the vehicle continues
1931  // overtaking (otherwise the lane change model might abort prematurely)
1932  oppositeLength += 1000;
1933  } else {
1934  // return from the opposite side ahead of the unpassable column (unless overlapping)
1935  if (overtaken.second > 0) {
1936  oppositeLength = MIN2(oppositeLength, forwardPos + overtaken.second);
1937  }
1938  // (don't set the distance so low as to imply emergency braking)
1939  oppositeLength = MAX2(oppositeLength, forwardPos + vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed()));
1940  }
1941 #ifdef DEBUG_CHANGE_OPPOSITE
1942  if (DEBUG_COND) {
1943  std::cout << SIMTIME << " ego=" << vehicle->getID() << " is overtaking " << overtaken.first->getID()
1944  << " surplusGap=" << surplusGap
1945  << " final laneQLength=" << oppositeLength
1946  << "\n";
1947  }
1948 #endif
1949  }
1950  }
1951  } else {
1952  if (overtaken.first == nullptr || !canOvertake) {
1953  // there is no reason to stay on the opposite side
1954  std::pair<MSVehicle* const, double> oppFollow = opposite->getOppositeFollower(vehicle);
1955  if (oppFollow.first == nullptr) {
1956  oppositeLength = forwardPos;
1957  } else {
1958  const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1959  oppFollow.first, vehicle, oppFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel());
1960 #ifdef DEBUG_CHANGE_OPPOSITE
1961  if (DEBUG_COND) {
1962  std::cout << SIMTIME << " ego=" << vehicle->getID() << " neighFollow=" << oppFollow.first->getID() << " gap=" << oppFollow.second << " secureGap=" << secureGap << "\n";
1963  }
1964 #endif
1965  if (oppFollow.second > secureGap) {
1966  // back gap is safe for immidiate return
1967  oppositeLength = forwardPos;
1968  }
1969  }
1970  }
1971  }
1972 #ifdef DEBUG_CHANGE_OPPOSITE
1973  if (DEBUG_COND) {
1974  std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << oppositeLength - forwardPos << " forwardPos=" << forwardPos << " oppositeLength=" << oppositeLength << "\n";
1975  }
1976 #endif
1977  return oppositeLength;
1978 }
1979 
1980 
1981 std::pair<MSVehicle* const, double>
1982 MSLaneChanger::getOncomingVehicle(const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
1983  double searchDist, double& vMax, const MSVehicle* overtaken, MSLane::MinorLinkMode mLinkMode) {
1984  double gap = oncoming.second;
1985  while (oncoming.first != nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
1986  searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() + MAX2(0.0, oncoming.second));
1987  // leader is itself overtaking through the opposite side. find real oncoming vehicle
1988  gap += oncoming.first->getVehicleType().getLengthWithGap();
1989  if (oncoming.first != overtaken) {
1990  vMax = MIN2(vMax, oncoming.first->getSpeed());
1991  } // else: might be the case if we are overtaking a vehicle that is stopped on the opposite side
1992 #ifdef DEBUG_CHANGE_OPPOSITE
1993  if (gDebugFlag5) {
1994  std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " isOpposite gap=" << oncoming.second
1995  << " totalGap=" << gap << " searchDist=" << searchDist << " vMax=" << vMax << "\n";
1996  }
1997 #endif
1998  if (searchDist < 0) {
1999  break;
2000  }
2001  // getOppositeLeader resets the search postion by ego length and may thus create cycles
2002  if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2003  opposite = oncoming.first->getLane();
2004  }
2005  oncoming = opposite->getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2006  if (oncoming.first != nullptr) {
2007  gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2008 #ifdef DEBUG_CHANGE_OPPOSITE
2009  if (gDebugFlag5) {
2010  std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " gap=" << oncoming.second << " totalGap=" << gap << "\n";
2011  }
2012 #endif
2013  }
2014  }
2015  oncoming.second = gap;
2016  return oncoming;
2017 }
2018 
2019 
2020 std::pair<MSVehicle* const, double>
2021 MSLaneChanger::getOncomingOppositeVehicle(const MSVehicle* vehicle, std::pair<MSVehicle*, double> overtaken, double searchDist) {
2022  double gap = 0;
2023  const MSVehicle* front = nullptr;
2024  if (overtaken.first != nullptr) {
2025  gap += overtaken.second + overtaken.first->getVehicleType().getLengthWithGap();
2026  front = overtaken.first;
2027  } else {
2028  // only for special situations (i.e. traci-triggered)
2029  front = vehicle;
2030  }
2031  // we only need to look for the next leader: If it's driving in the forward
2032  // direction, it "protects" from oncoming opposite vehicles.
2033  // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
2034  const bool checkTmpVehicles = front->getLane() == vehicle->getLane();
2035  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
2036  while (conts.size() > 0 && conts.front() != front->getLane()) {
2037  conts.erase(conts.begin());
2038  }
2039  std::pair<MSVehicle* const, double> oncoming = front->getLane()->getLeader(front, front->getPositionOnLane(), conts, searchDist, checkTmpVehicles);
2040  if (oncoming.first != nullptr) {
2041  const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2042  const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2043 #ifdef DEBUG_CHANGE_OPPOSITE
2044  if (gDebugFlag5) {
2045  std::cout << SIMTIME
2046  << " front=" << front->getID() << " searchDist=" << searchDist
2047  << " oncomingOpposite=" << oncoming.first->getID()
2048  << " gap=" << oncoming.second
2049  << " isOpposite=" << isOpposite
2050  << " shadowLane=" << Named::getIDSecure(shadowLane)
2051  << "\n";
2052  }
2053 #endif
2054  if (isOpposite && shadowLane != front->getLane()) {
2055  // distance was to back position (but the vehicle is oncoming)
2056  oncoming.second -= oncoming.first->getVehicleType().getLength();
2057  oncoming.second += gap;
2058  return oncoming;
2059  }
2060  }
2061  return std::make_pair(nullptr, -1);
2062 }
2063 
2064 
2065 double
2066 MSLaneChanger::computeSurplusGap(const MSVehicle* vehicle, const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
2067  double timeToOvertake, double spaceToOvertake, double& oncomingSpeed, bool oncomingOpposite) {
2068  double surplusGap = std::numeric_limits<double>::max();
2069  const MSVehicle* oncomingVeh = oncoming.first;
2070  if (oncomingVeh != 0 && (oncomingOpposite
2071  || (!oncomingVeh->getLaneChangeModel().isOpposite()
2072  && oncomingVeh->getLaneChangeModel().getShadowLane() != opposite))) {
2073  // conservative: assume that the oncoming vehicle accelerates to its maximum speed
2074  // unless it has been standing (then assume it is trying to let us pass
2075  // to avoid deadlock)
2076  oncomingSpeed = (oncomingVeh->isStopped() || oncomingVeh->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT
2077  ? 0 : oncomingVeh->getLane()->getVehicleMaxSpeed(oncomingVeh));
2078  const double safetyGap = ((oncomingSpeed + vehicle->getLane()->getVehicleMaxSpeed(vehicle))
2079  * vehicle->getCarFollowModel().getHeadwayTime()
2081  surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2082 #ifdef DEBUG_CHANGE_OPPOSITE
2083  if (DEBUG_COND) {
2084  std::cout << SIMTIME
2085  << " oncoming=" << oncomingVeh->getID()
2086  << " oGap=" << oncoming.second
2087  << " oSpeed=" << oncomingSpeed
2088  << " sto=" << spaceToOvertake
2089  << " tto=" << timeToOvertake
2090  << " safetyGap=" << safetyGap
2091  << " surplusGap=" << surplusGap
2092  << "\n";
2093  }
2094 #endif
2095  }
2096  return surplusGap;
2097 }
2098 
2099 bool
2100 MSLaneChanger::foundHilltop(MSVehicle* vehicle, bool foundHill, double searchDist, const std::vector<MSLane*>& bestLanes, int view, double pos, double lastMax, double hilltopThreshold) {
2101  if (view >= (int)bestLanes.size()) {
2102  return false;
2103  }
2104  MSLane* lane = bestLanes[view];
2105  double laneDist = 0;
2106  const PositionVector& shape = lane->getShape();
2107  double lastZ = lastMax;
2108  for (int i = 1; i < (int)shape.size(); i++) {
2109  const double dist = lane->interpolateGeometryPosToLanePos(shape[i - 1].distanceTo(shape[i]));
2110  laneDist += dist;
2111  if (laneDist > pos) {
2112  const double z = shape[i].z();
2113  if (z > lastMax) {
2114  lastMax = z;
2115  }
2116  if (z > lastZ) {
2117  foundHill = true;
2118  }
2119  lastZ = z;
2120 #ifdef DEBUG_CHANGE_OPPOSITE
2121  if (DEBUG_COND) {
2122  std::cout << SIMTIME << " foundHill=" << foundHill << " searchDist=" << searchDist << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2123  }
2124 #endif
2125  if (foundHill && z < lastMax) {
2126  const double drop = lastMax - z;
2127  //std::cout << SIMTIME << " searchDist=" << searchDist << " hillDrop=" << drop << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2128  if (drop > hilltopThreshold) {
2129 #ifdef DEBUG_CHANGE_OPPOSITE
2130  if (DEBUG_COND) {
2131  std::cout << " cannot changeOpposite before the top of a hill searchDist=" << searchDist << " hillDrop=" << drop
2132  << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2133  }
2134 #endif
2135  return true;
2136  }
2137  }
2138  if (pos == 0) {
2139  searchDist -= dist;
2140  } else {
2141  searchDist -= laneDist - pos;
2142  pos = 0;
2143  }
2144  if (searchDist <= 0) {
2145  return false;
2146  }
2147  }
2148  }
2149  return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2150 }
2151 
2152 
2153 bool
2155  MSVehicle* vehicle,
2156  int laneOffset,
2157  MSLane* targetLane,
2158  const std::pair<MSVehicle* const, double>& leader,
2159  const std::pair<MSVehicle* const, double>& neighLead,
2160  const std::pair<MSVehicle* const, double>& neighFollow,
2161  const std::vector<MSVehicle::LaneQ>& preb) {
2162  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
2163  MSLane* source = vehicle->getMutableLane();
2164  const std::pair<MSVehicle* const, double> follower(nullptr, -1);
2165  int state = checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2166  vehicle->getLaneChangeModel().setOwnState(state);
2167  bool changingAllowed = (state & LCA_BLOCKED) == 0;
2168  // change if the vehicle wants to and is allowed to change
2169  if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed
2170  // do not change to the opposite direction for cooperative reasons
2171  && (isOpposite || (state & LCA_COOPERATIVE) == 0)) {
2172  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(source, targetLane, laneOffset);
2173 #ifdef DEBUG_CHANGE_OPPOSITE
2174  if (DEBUG_COND) {
2175  std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset << " opposite=" << Named::getIDSecure(targetLane)
2176  << " state=" << toString((LaneChangeAction)state) << "\n";
2177  }
2178 #endif
2179  if (continuous) {
2180  continueChange(vehicle, myCandi);
2181  }
2182  return true;
2183  }
2184 #ifdef DEBUG_CHANGE_OPPOSITE
2185  if (DEBUG_COND) {
2186  std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset
2187  << " opposite=" << Named::getIDSecure(targetLane) << " state=" << toString((LaneChangeAction)state) << "\n";
2188  }
2189 #endif
2190  return false;
2191 }
2192 
2193 
2194 void
2195 MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, double vMax, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake) {
2196  // Assumptions:
2197  // - leader maintains the current speed
2198  // - vehicle merges with maxSpeed ahead of leader
2199  // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
2200 
2201  // first compute these values for the case where vehicle is accelerating
2202  // without upper bound on speed
2203  const double v = vehicle->getSpeed();
2204  const double u = leader->getAcceleration() > 0 ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
2205  const double a = vehicle->getCarFollowModel().getMaxAccel();
2206  const double d = vehicle->getCarFollowModel().getMaxDecel();
2207  const double g = MAX2(0.0, (
2208  // drive up to the rear of leader
2209  gap + vehicle->getVehicleType().getMinGap()
2210  // drive head-to-head with the leader
2211  + leader->getVehicleType().getLengthWithGap()
2212  // drive past the leader
2213  + vehicle->getVehicleType().getLength()
2214  // allow for safe gap between leader and vehicle
2215  + leader->getCarFollowModel().getSecureGap(leader, vehicle, u, vMax, d))
2216  // time to move between lanes
2217  + (MSGlobals::gSublane ? vMax * vehicle->getLane()->getWidth() / vehicle->getVehicleType().getMaxSpeedLat() : 0));
2218  const double sign = -1; // XXX recheck
2219  // v*t + t*t*a*0.5 = g + u*t
2220  // solve t
2221  // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
2222  double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2223 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2224  if (DEBUG_COND) {
2225  std::cout << " computeOvertakingTime v=" << v << " vMax=" << vMax << " u=" << u << " a=" << a << " d=" << d << " gap=" << gap << " g=" << g << " t=" << t
2226  << " distEgo=" << v* t + t* t* a * 0.5 << " distLead=" << g + u* t
2227  << "\n";
2228  }
2229 #endif
2230  assert(t >= 0);
2231  if (vMax <= u) {
2232  // do not try to overtake faster leader
2233  timeToOvertake = std::numeric_limits<double>::max();
2234  spaceToOvertake = std::numeric_limits<double>::max();
2235  return;
2236  }
2237 
2238  // allow for a safety time gap
2240  // round to multiples of step length (TS)
2241  if (u > 0) {
2242  t = ceil(t / TS) * TS;
2243  }
2244 
2246  const double timeToMaxSpeed = (vMax - v) / a;
2247 
2248 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2249  if (DEBUG_COND) {
2250  std::cout << " t=" << t << " tvMax=" << timeToMaxSpeed << "\n";
2251  }
2252 #endif
2253  if (t <= timeToMaxSpeed) {
2254  timeToOvertake = t;
2255  spaceToOvertake = v * t + t * t * a * 0.5;
2256 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2257  if (DEBUG_COND) {
2258  std::cout << " sto=" << spaceToOvertake << "\n";
2259  }
2260 #endif
2261  } else {
2262  // space until max speed is reached
2263  const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2264  const double m = timeToMaxSpeed;
2265  // s + (t-m) * vMax = g + u*t
2266  // solve t
2267  t = (g - s + m * vMax) / (vMax - u);
2268  if (t < 0) {
2269  // cannot overtake in time
2270 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2271  if (DEBUG_COND) {
2272  std::cout << " t2=" << t << "\n";
2273  }
2274 #endif
2275  timeToOvertake = std::numeric_limits<double>::max();
2276  spaceToOvertake = std::numeric_limits<double>::max();
2277  return;
2278  } else {
2279  // allow for a safety time gap
2281  // round to multiples of step length (TS)
2282  if (u > 0) {
2283  t = ceil(t / TS) * TS;
2284  }
2285  timeToOvertake = t;
2286  spaceToOvertake = s + (t - m) * vMax;
2287 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2288  if (DEBUG_COND) {
2289  std::cout << " t2=" << t << " s=" << s << " sto=" << spaceToOvertake << " m=" << m << "\n";
2290  }
2291 #endif
2292  }
2293  }
2294  const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
2295  timeToOvertake *= safetyFactor;
2296  if (STEPS2TIME(leader->getStopDuration()) < timeToOvertake) {
2297  spaceToOvertake *= safetyFactor;
2298  }
2299  double frac = fmod(timeToOvertake, TS);
2300  if (frac > 0) {
2301  // round to full sim step
2302  timeToOvertake += TS - frac;
2303  }
2304 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2305  if (DEBUG_COND) {
2306  if (safetyFactor != 1) {
2307  std::cout << " applying safetyFactor=" << safetyFactor
2308  << " leaderStopTime=" << STEPS2TIME(leader->getStopDuration())
2309  << " tto=" << timeToOvertake << " sto=" << spaceToOvertake << "\n";
2310  }
2311  }
2312 #endif
2313 }
2314 
2315 
2316 
2317 std::pair<MSVehicle*, double>
2318 MSLaneChanger::getColumnleader(double& maxSpace, MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, double maxLookAhead) {
2319  assert(leader.first != 0);
2320  const MSLane* source = vehicle->getLane();
2321  // find a leader vehicle with sufficient space ahead for merging back
2322  const double overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
2323  const double mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
2324  std::pair<MSVehicle*, double> columnLeader = leader;
2325  double egoGap = leader.second;
2326  bool foundSpaceAhead = false;
2327  double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2328  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
2329  if (maxLookAhead == std::numeric_limits<double>::max()) {
2330  maxLookAhead = (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
2333  maxLookAhead = MAX2(maxLookAhead, mergeBrakeGap + 10
2334  + vehicle->getVehicleType().getLengthWithGap()
2335  + leader.first->getVehicleType().getLengthWithGap());
2336  }
2337 #ifdef DEBUG_CHANGE_OPPOSITE
2338  if (DEBUG_COND) {
2339  std::cout << " getColumnleader vehicle=" << vehicle->getID() << " leader=" << leader.first->getID() << " gap=" << leader.second << " maxLookAhead=" << maxLookAhead << "\n";
2340  }
2341 #endif
2342  const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
2343  while (!foundSpaceAhead) {
2344  const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2345  columnLeader.first, vehicle,
2346  columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
2347  + columnLeader.first->getVehicleType().getMinGap()
2348  + vehicle->getVehicleType().getLengthWithGap());
2349 
2350 
2351  // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
2352  const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge());
2353  double searchStart = columnLeader.first->getPositionOnLane();
2354  std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2355  columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2356  checkTmpVehicles);
2357  std::set<MSVehicle*> seenLeaders;
2358  while (leadLead.first != nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2359 #ifdef DEBUG_CHANGE_OPPOSITE
2360  if (DEBUG_COND) {
2361  std::cout << " skipping opposite leadLead=" << leadLead.first->getID() << " gap=" << leadLead.second << "\n";
2362  }
2363 #endif
2364  if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2365  leadLead.first = nullptr;
2366  break;
2367  }
2368  seenLeaders.insert(leadLead.first);
2369  // found via shadow lane, skip it
2370  const double searchStart2 = searchStart + MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2371  leadLead = columnLeader.first->getLane()->getLeader(
2372  columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2373  checkTmpVehicles);
2374  leadLead.second += (searchStart2 - searchStart);
2375  }
2376  if (leadLead.first == nullptr) {
2377  double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2378  double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2379  if (!columnLeader.first->isStopped()) {
2380  // if the leader is stopped we can trade space for time
2381  requiredSpace += safetyFactor * mergeBrakeGap;
2382  }
2383 #ifdef DEBUG_CHANGE_OPPOSITE
2384  if (DEBUG_COND) {
2385  std::cout << " no direct leader found after columnLeader " << columnLeader.first->getID()
2386  << " availableSpace=" << availableSpace
2387  << " reqAfterLeader=" << requiredSpaceAfterLeader
2388  << " ovSpeed=" << overtakingSpeed
2389  << " reqBGap=" << mergeBrakeGap
2390  << " reqMin=" << requiredSpace / safetyFactor
2391  << " req=" << requiredSpace
2392  << "\n";
2393  }
2394 #endif
2395  if (availableSpace > requiredSpace) {
2396  foundSpaceAhead = true;
2397  } else {
2398  // maybe the columnleader is stopped before a junction or takes a different turn.
2399  // try to find another columnleader on successive lanes
2400  const bool allowMinor = vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY;
2401  bool contsEnd = false;
2402  const MSLane* next = getLaneAfter(columnLeader.first->getLane(), conts, allowMinor, contsEnd);
2403 #ifdef DEBUG_CHANGE_OPPOSITE
2404  if (DEBUG_COND) {
2405  std::cout << " look for another leader on lane " << Named::getIDSecure(next) << "\n";
2406  }
2407 #endif
2408  while (next != nullptr && seen < maxLookAhead) {
2409  seen += next->getLength();
2410  MSVehicle* cand = next->getLastAnyVehicle();
2411  if (cand == nullptr) {
2412  availableSpace += next->getLength();
2413  if (availableSpace > requiredSpace) {
2414  foundSpaceAhead = true;
2415  break;
2416  }
2417  next = getLaneAfter(next, conts, allowMinor, contsEnd);
2418  } else {
2419  availableSpace += cand->getBackPositionOnLane();
2420  if (availableSpace > requiredSpace) {
2421  foundSpaceAhead = true;
2422  break;
2423  } else {
2424  return getColumnleader(maxSpace, vehicle, std::make_pair(cand, availableSpace + cand->getPositionOnLane()), maxLookAhead - seen);
2425  }
2426  }
2427  }
2428 #ifdef DEBUG_CHANGE_OPPOSITE
2429  if (DEBUG_COND) {
2430  std::cout << " foundSpaceAhead=" << foundSpaceAhead << " availableSpace=" << availableSpace << " next=" << Named::getIDSecure(next) << " contsEnd=" << contsEnd << " conts=" << toString(conts) << "\n";
2431  }
2432 #endif
2433  if (!foundSpaceAhead && contsEnd) {
2434  foundSpaceAhead = true;
2435  availableSpace = requiredSpace;
2436  }
2437  if (!foundSpaceAhead) {
2438  return std::make_pair(nullptr, -1);
2439  }
2440  }
2441  maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2442  } else {
2443  const double sGap = vehicle->getCarFollowModel().getSecureGap(vehicle, leadLead.first,
2444  overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2445  double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2446  if (!columnLeader.first->isStopped()) {
2447  // if the leader is stopped we can trade space for time
2448  requiredSpace += safetyFactor * sGap;
2449  }
2450 #ifdef DEBUG_CHANGE_OPPOSITE
2451  if (DEBUG_COND) {
2452  std::cout << " leader's leader " << leadLead.first->getID() << " space=" << leadLead.second
2453  << " reqAfterLeader=" << requiredSpaceAfterLeader
2454  << " ovSpeed=" << overtakingSpeed
2455  << " reqSGap=" << sGap
2456  << " reqMin=" << requiredSpace / safetyFactor
2457  << " req=" << requiredSpace
2458  << "\n";
2459  }
2460 #endif
2461  if (leadLead.second > requiredSpace) {
2462  foundSpaceAhead = true;
2463  maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2464  } else {
2465 
2466  if (leadLead.second < 0) {
2467  // must be a junction leader or some other dangerous situation
2468 #ifdef DEBUG_CHANGE_OPPOSITE
2469  if (DEBUG_COND) {
2470  std::cout << " leader's leader " << leadLead.first->getID() << " gap=" << leadLead.second << " is junction leader (aborting)\n";
2471  }
2472 #endif
2473  return std::make_pair(nullptr, -1);
2474  }
2475 
2476 #ifdef DEBUG_CHANGE_OPPOSITE
2477  if (DEBUG_COND) {
2478  std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n";
2479  }
2480 #endif
2481  seen += MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2482  if (seen > maxLookAhead) {
2483 #ifdef DEBUG_CHANGE_OPPOSITE
2484  if (DEBUG_COND) {
2485  std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n";
2486  }
2487 #endif
2488  return std::make_pair(nullptr, -1);
2489  }
2490  // see if merging after leadLead is possible
2491  egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2492  columnLeader = leadLead;
2493 #ifdef DEBUG_CHANGE_OPPOSITE
2494  if (DEBUG_COND) {
2495  std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
2496  }
2497 #endif
2498  }
2499  }
2500  }
2501  columnLeader.second = egoGap;
2502  return columnLeader;
2503 }
2504 
2505 
2506 const MSLane*
2507 MSLaneChanger::getLaneAfter(const MSLane* lane, const std::vector<MSLane*>& conts, bool allowMinor, bool& contsEnd) {
2508  for (auto it = conts.begin(); it != conts.end(); ++it) {
2509  if (*it == lane) {
2510  if (it + 1 != conts.end()) {
2511  // abort on minor link
2512  const MSLane* next = *(it + 1);
2513  const MSLink* link = lane->getLinkTo(next);
2514  if (link == nullptr || (!allowMinor && !link->havePriority())) {
2515  return nullptr;
2516  }
2517  return next;
2518  } else {
2519  contsEnd = true;
2520  return nullptr;
2521  }
2522  }
2523  }
2524  return nullptr;
2525 }
2526 
2527 double
2528 MSLaneChanger::getMaxOvertakingSpeed(const MSVehicle* vehicle, double maxSpaceToOvertake) {
2529  // v*v/2*a + v*v/2*d = maxSpaceToOvertake
2530  const double a = vehicle->getCarFollowModel().getMaxAccel();
2531  const double d = vehicle->getCarFollowModel().getMaxDecel();
2532  const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
2533  return v;
2534 }
2535 
2536 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY
#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETY_FACTOR
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP
#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE
#define DEBUG_COND
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:32
std::pair< const MSPerson *, double > PersonDist
Definition: MSPModel.h:39
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SPEED2DIST(x)
Definition: SUMOTime.h:45
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:51
#define TS
Definition: SUMOTime.h:42
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_EMERGENCY
public emergency vehicles
@ RIGHT
The link is a (hard) right direction.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_BLOCKED_BY_RIGHT_LEADER
The vehicle is blocked by right leader.
@ LCA_INSUFFICIENT_SPACE
The vehicle does not have enough space to complete a continuous change before the next turn.
@ LCA_BLOCKED_BY_LEFT_FOLLOWER
The vehicle is blocked by left follower.
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_INSUFFICIENT_SPEED
Vehicle is too slow to complete a continuous lane change (in case that maxSpeedLatStanding==0)
@ LCA_OVERLAPPING
The vehicle is blocked being overlapping.
@ LCA_LEFT
Wants go to the left.
@ LCA_BLOCKED_BY_RIGHT_FOLLOWER
The vehicle is blocked by right follower.
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_LEFT_LEADER
bool gDebugFlag5
Definition: StdDefs.cpp:39
const double SUMO_const_laneWidth
Definition: StdDefs.h:48
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A class responsible for exchanging messages between cars involved in lane-change interaction.
Interface for lane-change models.
double getLaneChangeCompletion() const
Get the current lane change completion ratio.
double getForwardPos() const
get vehicle position relative to the forward direction lane
void setFollowerGaps(CLeaderDist follower, double secGap)
virtual void setOwnState(const int state)
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change.
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
virtual bool saveBlockerLength(double, double)
reserve space at the end of the lane to avoid dead locks
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
virtual double getOppositeSafetyFactor() const
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
void setLeaderGaps(CLeaderDist, double secGap)
void setOrigLeaderGaps(CLeaderDist, double secGap)
int getNormalizedLaneIndex()
brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
virtual int checkChangeBeforeCommitting(const MSVehicle *veh, int state) const
Informs the vehicle that it is about to be moved on an adjacent lane. The method can be used to re-ev...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
void clearNeighbors()
Clear info on neighboring vehicle from previous step.
void saveNeighbors(const int dir, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &leaders)
Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direct...
MSStop & getNextStop()
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
bool isStopped() const
Returns whether the vehicle is at a stop.
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.cpp:166
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition: MSCFModel.h:256
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition: MSCFModel.h:380
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:264
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition: MSCFModel.h:311
A road/street connecting two junctions.
Definition: MSEdge.h:77
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition: MSEdge.cpp:1276
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition: MSEdge.cpp:883
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
int getNumLanes() const
Definition: MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
static double gLateralResolution
Definition: MSGlobals.h:97
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition: MSGlobals.h:169
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition: MSGlobals.h:160
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:94
virtual ~MSLaneChanger()
Destructor.
bool applyTraCICommands(MSVehicle *vehicle)
Execute TraCI LC-commands.
bool continueChange(MSVehicle *vehicle, ChangerIt &from)
continue a lane change maneuver and return whether the vehicle has completely moved onto the new lane...
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
bool checkOppositeStop(MSVehicle *vehicle, const MSLane *oncomingLane, const MSLane *opposite, std::pair< MSVehicle *, double > leader)
decide whether to change (back or forth) for an opposite stop
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, MSVehicle *lastStopped)
MSLaneChanger()
Default constructor.
static bool hasOppositeStop(MSVehicle *vehicle)
whether vehicle has an opposite-direction stop within relevant range
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
virtual void initChanger()
Initialize the changer before looping over all vehicles.
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one.
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
virtual bool change()
static const MSLane * getLaneAfter(const MSLane *lane, const std::vector< MSLane * > &conts, bool allowMinor, bool &contsEnd)
return the next lane in conts beyond lane or nullptr
std::pair< MSVehicle *const, double > getOncomingOppositeVehicle(const MSVehicle *vehicle, std::pair< MSVehicle *, double > overtaken, double searchDist)
std::pair< MSVehicle *const, double > getOncomingVehicle(const MSLane *opposite, std::pair< MSVehicle *, double > neighOncoming, double searchDist, double &vMax, const MSVehicle *overtaken=nullptr, MSLane::MinorLinkMode mLinkMode=MSLane::MinorLinkMode::FOLLOW_NEVER)
bool startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
const bool myAllowsChanging
double computeSafeOppositeLength(MSVehicle *vehicle, double oppositeLength, const MSLane *source, double usableDist, std::pair< MSVehicle *, double > oncoming, double vMax, double oncomingSpeed, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > neighFollow, double surplusGap, const MSLane *opposite, bool canOvertake)
determine for how long the vehicle can drive safely on the opposite side
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
MSVehicle * veh(ConstChangerIt ce) const
static bool foundHilltop(MSVehicle *vehicle, bool foundHill, double searchDist, const std::vector< MSLane * > &bestLanes, int view, double pos, double lastMax, double hilltopThreshold)
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
static double computeSurplusGap(const MSVehicle *vehicle, const MSLane *opposite, std::pair< MSVehicle *, double > oncoming, double timeToOvertake, double spaceToOvertake, double &oncomingSpeed, bool oncomingOpposite=false)
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
bool yieldToOppositeWaiting(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist, SUMOTime deltaWait=0)
check whether to yield for oncoming vehicles that have waited longer for opposite overtaking
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
void registerUnchanged(MSVehicle *vehicle)
void updateLanes(SUMOTime t)
bool avoidDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > leader)
avoid opposite-diretion deadlock when vehicles are stopped on both sides of the road The method may c...
static std::pair< MSVehicle *, double > getColumnleader(double &maxSpace, MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
return leader vehicle that is to be overtaken
static double getMaxOvertakingSpeed(const MSVehicle *vehicle, double maxSpaceToOvertake)
compute maximum maneuver speed
ChangerIt myCandi
bool resolveDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *const, double > leader, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken)
keep stopping to resolve opposite-diretion deadlock while there is oncoming traffic The method may ca...
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
bool yieldToDeadlockOncoming(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist)
check whether to keep stopping for oncoming vehicles in the deadlock zone
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
int checkChange(int laneOffset, const MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &follower, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb) const
virtual bool checkChangeOpposite(MSVehicle *vehicle, int laneOffset, MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb)
static void computeOvertakingTime(const MSVehicle *vehicle, double vMax, const MSVehicle *leader, double gap, double &timeToOvertake, double &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
static std::vector< MSVehicle::LaneQ > getBestLanesOpposite(MSVehicle *vehicle, const MSLane *stopLane, double oppositeLength)
add LaneQ for opposite lanes
virtual void updateChanger(bool vehHasChanged)
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, MinorLinkMode mLinkMode) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
Definition: MSLane.cpp:4246
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
Definition: MSLane.cpp:4420
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2714
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition: MSLane.cpp:2560
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2609
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:584
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:119
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode=MinorLinkMode::FOLLOW_NEVER) const
Definition: MSLane.cpp:4269
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
bool allowsChangingLeft(SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
Definition: MSLane.h:920
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:2981
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
Definition: MSLane.h:841
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:913
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:566
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition: MSLane.cpp:4297
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition: MSLane.cpp:4413
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:634
void requireCollisionCheck()
require another collision check due to relevant changes in the simulation
Definition: MSLane.h:698
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:4241
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:2527
bool isInternal() const
Definition: MSLane.cpp:2486
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1458
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:752
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
Definition: MSLane.h:961
double interpolateGeometryPosToLanePos(double geometryPos) const
Definition: MSLane.h:558
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:2783
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition: MSLane.cpp:4229
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:627
virtual const PositionVector & getShape(bool) const
Definition: MSLane.h:294
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
bool hasElevation() const
return whether the network contains elevation data
Definition: MSNet.h:784
Definition: MSStop.h:44
const MSLane * lane
The lane to stop at (microsim only)
Definition: MSStop.h:50
bool isOpposite
whether this an opposite-direction stop
Definition: MSStop.h:87
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected (concerns approaching vehicles outside the...
Definition: MSVehicle.h:1513
SUMOTime getLaneTimeLineDuration()
Definition: MSVehicle.cpp:460
double myPosLat
the stored lateral position
Definition: MSVehicle.h:140
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:5744
double computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:1466
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1573
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
Definition: MSVehicle.h:631
SUMOTime getWaitingTime(const bool accumulated=false) const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:673
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:5019
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5720
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Definition: MSVehicle.h:592
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:7217
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:7236
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition: MSVehicle.h:1036
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:6421
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition: MSVehicle.h:517
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1242
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:6230
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition: MSVehicle.h:401
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition: MSVehicle.h:1109
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition: MSVehicle.h:1111
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
Definition: MSVehicle.h:528
std::pair< const MSVehicle *const, double > getFollower(double dist=0) const
Returns the follower of the vehicle looking for a fixed distance.
Definition: MSVehicle.cpp:6492
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7182
bool isBidiOn(const MSLane *lane) const
whether this vehicle is driving against lane
Definition: MSVehicle.cpp:6996
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
Definition: MSVehicle.cpp:6622
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links
Definition: MSVehicle.cpp:6862
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
Definition: MSVehicle.cpp:1215
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
Position myCachedPosition
Definition: MSVehicle.h:1931
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:5738
double myAngle
the angle in radians (
Definition: MSVehicle.h:1923
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignored
Definition: MSVehicle.cpp:7260
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:974
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition: MSVehicle.h:1678
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1861
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
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:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:317
double z() const
Returns the z-position.
Definition: Position.h:65
A list of positions.
#define M_PI
Definition: odrSpiral.cpp:45
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.