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  blocked = state & LCA_BLOCKED;
1053 #ifdef DEBUG_CHECK_CHANGE
1054  if (DEBUG_COND) {
1055  std::cout << SIMTIME
1056  << " veh=" << vehicle->getID()
1057  << " oldState=" << toString((LaneChangeAction)oldstate)
1058  << " newState=" << toString((LaneChangeAction)state)
1059  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
1060  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
1061  << "\n";
1062  }
1063 #endif
1064 
1065  if (state & LCA_WANTS_LANECHANGE && blocked == 0) {
1066  blocked = vehicle->getLaneChangeModel().checkChangeBeforeCommitting(vehicle, state);
1067  state |= blocked;
1068  }
1069  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
1070  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
1071  // this lane change will be executed, save gaps
1072  vehicle->getLaneChangeModel().setFollowerGaps(neighFollow, secureBackGap);
1073  vehicle->getLaneChangeModel().setLeaderGaps(neighLead, secureFrontGap);
1074  vehicle->getLaneChangeModel().setOrigLeaderGaps(leader, secureOrigFrontGap);
1075  }
1076  if (laneOffset != 0) {
1077  vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollow, neighLead);
1078  }
1079  return state;
1080 }
1081 
1082 bool
1084  if (vehicle->hasStops()) {
1085  const MSStop& stop = vehicle->getNextStop();
1086  if (stop.isOpposite && vehicle->nextStopDist() < OPPOSITE_OVERTAKING_MAX_LOOKAHEAD) {
1087  return true;
1088  }
1089  }
1090  return false;
1091 }
1092 
1093 
1094 bool
1095 MSLaneChanger::checkOppositeStop(MSVehicle* vehicle, const MSLane* oncomingLane, const MSLane* opposite, std::pair<MSVehicle*, double> leader) {
1096  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1097  double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1098  std::pair<MSVehicle*, double> neighLead(nullptr, -1);
1099  std::pair<MSVehicle*, double> oncoming(nullptr, -1);
1100  const std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, vehicle->getNextStop().lane, -1);
1101  const int laneIndex = vehicle->getLaneChangeModel().getNormalizedLaneIndex();
1102  const int bestOffset = preb[laneIndex].bestLaneOffset;
1103  //std::cout << SIMTIME << " veh=" << vehicle->getID() << " laneIndex=" << laneIndex << " bestOffset=" << bestOffset << " target=" << target->getID() << "\n";
1104 
1105  // compute safety constraints (assume vehicle is safe once stop is reached)
1106  const double spaceToStop = vehicle->nextStopDist();
1107  const double timeToStopForward = spaceToStop / MAX2(vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxAccel());
1108  const double timeToStopLateral = (MSGlobals::gLaneChangeDuration > 0
1111  ? bestOffset * SUMO_const_laneWidth / vehicle->getVehicleType().getMaxSpeedLat()
1112  : 0.));
1113  const double timeToStop = MAX2(timeToStopForward, timeToStopLateral);
1114  if (!isOpposite) {
1115  // we keep neighLead distinct from oncoming because it determines blocking on the neigh lane
1116  // but also look for an oncoming leader to compute safety constraint
1117  const double searchDist = timeToStop * oncomingLane->getSpeedLimit() * 2 + spaceToStop;
1118  neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1119  oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax);
1120  } else {
1121  double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
1122  oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1123  oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax);
1124  }
1125  double oncomingSpeed;
1126  const double surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1127  if (!isOpposite && surplusGap < 0) {
1128 #ifdef DEBUG_CHANGE_OPPOSITE
1129  if (DEBUG_COND) {
1130  std::cout << " cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1131  << " timeToStopForward=" << timeToStopForward << " timeToStopLateral=" << timeToStopLateral << " surplusGap=" << surplusGap << "\n";
1132  }
1133 #endif
1134  return false;
1135  }
1136 
1137  if (bestOffset > 0) {
1138  MSLane* const target = preb[laneIndex + 1].lane;
1139  neighLead = target->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_MAX_LOOKAHEAD, true);
1140  std::pair<MSVehicle* const, double> neighFollow = target->getOppositeFollower(vehicle);
1141  return checkChangeOpposite(vehicle, 1, target, leader, neighLead, neighFollow, preb);
1142  } else {
1143  // return prematurely (due to foe?)
1144  //return checkChangeOpposite(vehicle, -1, target, leader, neighLead, neighFollow, preb);
1145  return false;
1146  }
1147 }
1148 
1149 
1150 std::vector<MSVehicle::LaneQ>
1151 MSLaneChanger::getBestLanesOpposite(MSVehicle* vehicle, const MSLane* stopLane, double oppositeLength) {
1152  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1153  const MSEdge* forward = isOpposite ? vehicle->getLane()->getEdge().getOppositeEdge()->getNormalSuccessor() : vehicle->getLane()->getEdge().getNormalSuccessor();
1154  const MSEdge* opposite = forward->getOppositeEdge();
1155  const int numForward = forward->getNumLanes();
1156  const int numOpposite = opposite->getNumLanes();
1157  const std::vector<MSLane*>& oLanes = opposite->getLanes();
1158  std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
1159  for (int i = 0; i < numOpposite; i++) {
1160  preb.push_back(preb.back());
1161  preb.back().lane = oLanes[numOpposite - 1 - i];
1162  preb.back().length = oppositeLength;
1163  if (isOpposite) {
1164  preb.back().bestLaneOffset = -1 - i;
1165  //std::cout << " oi=" << i << " bestOffset =" << preb.back().bestLaneOffset << "\n";
1166  }
1167  }
1168  if (stopLane != nullptr) {
1169  const int stopIndex = numForward + numOpposite - stopLane->getIndex() - 1;
1170  for (int i = 0; i < (int)preb.size(); i++) {
1171  preb[i].bestLaneOffset = stopIndex - i;
1172  preb[i].length = vehicle->getLaneChangeModel().getForwardPos() + vehicle->nextStopDist();
1173  //std::cout << " oi2=" << i << " stopIndex=" << stopIndex << " bestOffset =" << preb[i].bestLaneOffset << " stopDist=" << vehicle->nextStopDist() << " length=" << preb[i].length << "\n";
1174  }
1175  }
1176 #ifdef DEBUG_CHANGE_OPPOSITE
1177  if (DEBUG_COND) {
1178  std::cout << SIMTIME << " getBestLanesOpposite " << vehicle->getID() << " isOpposite=" << isOpposite << "\n";
1179  for (int i = 0; i < (int)preb.size(); i++) {
1180  std::cout << " i=" << i << " lane=" << preb[i].lane->getID() << " bestOffset=" << preb[i].bestLaneOffset << " length=" << preb[i].length << "\n";
1181  }
1182  }
1183 #endif
1184  return preb;
1185 }
1186 
1187 
1188 bool
1189 MSLaneChanger::changeOpposite(MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, MSVehicle* lastStopped) {
1190  // Evaluate lane-changing between opposite direction lanes
1191  if (!myChangeToOpposite) {
1192  return false;
1193  }
1194  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1195  MSLane* source = vehicle->getMutableLane();
1196  MSLane* opposite = isOpposite ? source->getParallelLane(1) : source->getOpposite();
1197 
1198 #ifdef DEBUG_CHANGE_OPPOSITE
1200  if (DEBUG_COND) {
1201  std::cout << SIMTIME << " veh=" << vehicle->getID() << " considerChangeOpposite source=" << source->getID()
1202  << " opposite=" << Named::getIDSecure(opposite) << " lead=" << Named::getIDSecure(leader.first) << " isOpposite=" << isOpposite << "\n";
1203  }
1204 #endif
1205  //There is no lane for opposite driving
1206  if (opposite == nullptr) {
1207  return false;
1208  }
1209  if (vehicle->isStopped()) {
1210  // stopped vehicles obviously should not change lanes. Usually this is
1211  // prevent by appropriate bestLane distances
1212  return false;
1213  }
1214  int ret = 0;
1215  ret = vehicle->influenceChangeDecision(ret);
1216  bool oppositeChangeByTraci = false;
1217  // Check whether a lane change to the opposite direction was requested via TraCI
1218  if ((ret & (LCA_TRACI)) != 0) {
1219  if (isOpposite && (ret & LCA_LEFT) != 0) {
1220  // stay on the opposite side
1221  return false;
1222  }
1223  oppositeChangeByTraci = true;
1224  }
1225  if (!isOpposite && !oppositeChangeByTraci && !source->allowsChangingLeft(vehicle->getVClass())) {
1226  // lane changing explicitly forbidden from this lane
1227 #ifdef DEBUG_CHANGE_OPPOSITE
1228  if (DEBUG_COND) {
1229  std::cout << " not overtaking due to changeLeft restriction\n";
1230  }
1231 #endif
1232  return false;
1233  }
1234 
1235  //lane for opposite driving is not permitted
1236  if (!opposite->allowsVehicleClass(vehicle->getVClass())) {
1237  return false;
1238  }
1239 
1240  const MSLane* oncomingLane = isOpposite ? source : opposite;
1241  //const MSLane* forwardLane = isOpposite ? opposite : source;
1242  // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
1243  int direction = isOpposite ? -1 : 1;
1244  std::pair<MSVehicle*, double> neighLead(nullptr, -1);
1245 
1246  // distance that can safely be driven on the opposite side
1247  double surplusGap = std::numeric_limits<double>::max();
1248 
1249  // we need to find two vehicles:
1250  // 1) the leader that shall be overtaken (not necessarily the current leader but one of its leaders that has enough space in front)
1251  // 2) the oncoming vehicle (we need to look past vehicles that are currently overtaking through the opposite direction themselves)
1252  //
1253  // if the vehicle is driving normally, then the search for 1) starts on the current lane and 2) on the opposite lane
1254  // if the vehicle is driving on the opposite side then 1) is found on the neighboring lane and 2) on the current lane
1255 
1256  std::pair<MSVehicle*, double> overtaken(nullptr, -1);
1257  // oncoming vehicle that is driving in the "correct" direction
1258  std::pair<MSVehicle*, double> oncoming(nullptr, -1);
1259  // oncoming vehicle that is driving against the flow
1260  std::pair<MSVehicle*, double> oncomingOpposite(nullptr, -1);
1261  // the maximum speed while overtaking (may be lowered if slow vehicles are
1262  // currently overtaking ahead of vehicle)
1263  double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1264  double oncomingSpeed = oncomingLane->getSpeedLimit();
1265 
1266  // check for opposite direction stop
1267  if (!oppositeChangeByTraci && hasOppositeStop(vehicle)) {
1268  return checkOppositeStop(vehicle, oncomingLane, opposite, leader);
1269  }
1270 
1271  if (!isOpposite && leader.first == nullptr && !oppositeChangeByTraci) {
1272  // no reason to change unless there is a leader
1273  // or we are changing back to the propper direction
1274  // XXX also check whether the leader is so far away as to be irrelevant
1275  return false;
1276  }
1277  if (!isOpposite && !oppositeChangeByTraci
1278  && vehicle->getVClass() != SVC_EMERGENCY
1279  && leader.first != nullptr) {
1280  if (leader.first->signalSet(MSGlobals::gLefthand
1282  // do not try to overtake a vehicle that is about to turn left or wants
1283  // to change left itself
1284 #ifdef DEBUG_CHANGE_OPPOSITE
1285  if (DEBUG_COND) {
1286  std::cout << " not overtaking leader " << leader.first->getID() << " that has blinker set\n";
1287  }
1288 #endif
1289  if (lastStopped != nullptr && vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT) {
1290  neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1291  const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
1292  resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1293  }
1294  return false;
1295  } else if (leader.second < 0) {
1296  // leaders is either a junction leader (that cannot be overtaken) or something else is wrong
1297 #ifdef DEBUG_CHANGE_OPPOSITE
1298  if (DEBUG_COND) {
1299  std::cout << " not overtaking leader " << leader.first->getID() << " with gap " << leader.second << "\n";
1300  }
1301 #endif
1302  return false;
1303  }
1304  }
1305 
1306  // checks for overtaking space
1307  double timeToOvertake = std::numeric_limits<double>::max();
1308  double spaceToOvertake = std::numeric_limits<double>::max();
1309  double maxSpaceToOvertake = 0;
1310 
1311  if (oppositeChangeByTraci) {
1312  timeToOvertake = STEPS2TIME(vehicle->getInfluencer().getLaneTimeLineDuration());//todo discuss concept
1313  spaceToOvertake = timeToOvertake * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1314  } else {
1315  if (isOpposite) {
1316  // -1 will use getMaximumBrakeDist() as look-ahead distance
1317  neighLead = opposite->getOppositeLeader(vehicle, -1, false);
1318  // make sure that overlapping vehicles on the neighboring lane are found by starting search at the back position
1319  overtaken = opposite->getLeader(vehicle, opposite->getOppositePos(vehicle->getBackPositionOnLane()), vehicle->getBestLanesContinuation(opposite));
1320  overtaken.second -= vehicle->getVehicleType().getLength();
1321  if (overtaken.first == nullptr && neighLead.first != nullptr) {
1322  overtaken = neighLead;
1323  }
1324  if (overtaken.first != nullptr) {
1325  overtaken = getColumnleader(maxSpaceToOvertake, vehicle, overtaken);
1326  }
1327 #ifdef DEBUG_CHANGE_OPPOSITE
1328  if (DEBUG_COND) {
1329  std::cout << " leaderOnSource=" << Named::getIDSecure(oncoming.first) << " gap=" << oncoming.second << "\n";
1330  std::cout << " leaderOnTarget=" << Named::getIDSecure(neighLead.first) << " gap=" << neighLead.second << "\n";
1331  std::cout << " overtaken=" << Named::getIDSecure(overtaken.first) << " gap=" << overtaken.second << "\n";
1332  }
1333 #endif
1334  } else {
1335  overtaken = getColumnleader(maxSpaceToOvertake, vehicle, leader);
1336  }
1337 
1338  if (overtaken.first == 0) {
1339  if (!isOpposite) {
1340  // no reason to change to the opposite side
1341 #ifdef DEBUG_CHANGE_OPPOSITE
1342  if (DEBUG_COND) {
1343  std::cout << " no leader found\n";
1344  }
1345 #endif
1347  neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1348  resolveDeadlock(vehicle, leader, neighLead, std::make_pair(nullptr, leader.second));
1349  }
1350  return false;
1351  }
1352  } else {
1353 #ifdef DEBUG_CHANGE_OPPOSITE
1354  if (DEBUG_COND) {
1355  std::cout << " compute time/space to overtake for columnLeader=" << overtaken.first->getID() << " egoGap=" << overtaken.second << "\n";
1356  }
1357 #endif
1358  // if we have limited space to overtake, we may have to limit our maximum maneuver speed
1359  vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, maxSpaceToOvertake));
1360  // there might be leader vehicles on the opposite side that also drive
1361  // against the flow which are slower than ego (must be factored into
1362  // overtaking time)
1363  computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1364 #ifdef DEBUG_CHANGE_OPPOSITE
1365  if (DEBUG_COND) {
1366  std::cout << SIMTIME
1367  << " veh=" << vehicle->getID()
1368  << " changeOpposite opposite=" << opposite->getID()
1369  << " lead=" << Named::getIDSecure(leader.first)
1370  << " maxSpaceToOvertake=" << maxSpaceToOvertake
1371  << " vMax=" << vMax
1372  << " timeToOvertake=" << timeToOvertake
1373  << " spaceToOvertake=" << spaceToOvertake
1374  << "\n";
1375  }
1376 #endif
1377 
1378  if (!isOpposite && spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
1379 #ifdef DEBUG_CHANGE_OPPOSITE
1380  if (DEBUG_COND) {
1381  std::cout << " cannot changeOpposite (cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
1382  }
1383 #endif
1384  neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1385  bool wait = false;
1387  wait = resolveDeadlock(vehicle, leader, neighLead, overtaken);
1388  }
1389  if (!wait && lastStopped != nullptr) {
1390  const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
1391 #ifdef DEBUG_CHANGE_OPPOSITE
1392  if (DEBUG_COND) {
1393  std::cout << " lastStopped=" << Named::getIDSecure(lastStopped) << " gap=" << lastStoppedGap << "\n";
1394  }
1395 #endif
1396  avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1397  }
1398  return false;
1399  }
1400  }
1401 
1402  // if we have a leader vehicle that is driving in the opposite
1403  // direction, it may slow us down (update vMax)
1404  if (!isOpposite) {
1405  assert(timeToOvertake != std::numeric_limits<double>::max());
1406  assert(spaceToOvertake != std::numeric_limits<double>::max());
1407  // we keep neighLead distinct from oncoming because it determines blocking on the neigh lane
1408  // but also look for an oncoming leader to compute safety constraint
1409  double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 2 + spaceToOvertake;
1410  neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1411  oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1412  oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
1413  } else {
1414  double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
1415  oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1416  oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1417  oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
1418  }
1419  if (oncoming.first != nullptr && (oncoming.first->isStopped()
1420  || oncoming.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT)) {
1421  // finish overtaking within the available space
1422  const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1423  if (oncomingGap > 0) {
1424  vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, oncomingGap));
1425  }
1426 #ifdef DEBUG_CHANGE_OPPOSITE
1427  if (DEBUG_COND) {
1428  std::cout << " oncoming=" << oncoming.first->getID() << " stopped=" << oncoming.first->isStopped()
1429  << " halting=" << oncoming.first->getWaitingSeconds()
1430  << " oncomingGap=" << oncomingGap
1431  << " vMaxGap=" << getMaxOvertakingSpeed(vehicle, oncomingGap)
1432  << " vMax=" << vMax << "\n";
1433  }
1434 #endif
1435  }
1436 
1437  if (overtaken.first != nullptr && vMax != vehicle->getLane()->getVehicleMaxSpeed(vehicle)) {
1438  // recompute overtaking time with slow opposite leader
1439  computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1440 #ifdef DEBUG_CHANGE_OPPOSITE
1441  if (DEBUG_COND) {
1442  std::cout << " recomputed overtaking time with vMax=" << vMax
1443  << " timeToOvertake=" << timeToOvertake
1444  << " spaceToOvertake=" << spaceToOvertake
1445  << "\n";
1446  }
1447 #endif
1448  }
1449  if (!isOpposite) {
1450  if (spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
1451 #ifdef DEBUG_CHANGE_OPPOSITE
1452  if (DEBUG_COND) {
1453  std::cout << " cannot changeOpposite (check2: cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
1454  }
1455 #endif
1456  resolveDeadlock(vehicle, leader, neighLead, overtaken);
1457  return false;
1458  }
1459  // check for upcoming stops
1460  if (vehicle->nextStopDist() < spaceToOvertake) {
1461 #ifdef DEBUG_CHANGE_OPPOSITE
1462  if (DEBUG_COND) {
1463  std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
1464  }
1465 #endif
1466  return false;
1467  }
1468  assert(timeToOvertake != std::numeric_limits<double>::max());
1469  assert(spaceToOvertake != std::numeric_limits<double>::max());
1470  }
1471 
1472  // check for dangerous oncoming leader
1473  surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1474  if (oncomingOpposite.first != nullptr) {
1475  double oncomingSpeed2;
1476  const double conservativeTime = ceil(timeToOvertake / TS) * TS;
1477  const double conservativeSpace = conservativeTime * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1478  const double surplusGap2 = computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2, true);
1479 #ifdef DEBUG_CHANGE_OPPOSITE
1480  if (DEBUG_COND) {
1481  std::cout << " oncomingOpposite=" << oncomingOpposite.first->getID() << " speed=" << oncomingSpeed2 << " gap=" << oncomingOpposite.second << " surplusGap2=" << surplusGap2 << "\n";
1482  }
1483 #endif
1484  surplusGap = MIN2(surplusGap, surplusGap2);
1485  oncomingSpeed = MAX2(oncomingSpeed, oncomingSpeed2);
1486  if (!isOpposite && surplusGap >= 0 && oncoming.first != nullptr && oncoming.first->isStopped()
1487  && oncomingOpposite.second > oncoming.second) {
1488  // even if ego can change back and forth successfully, we have to
1489  // make sure that the oncoming vehicle can also finish its lane
1490  // change in time
1491  const double oSpeed = MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1492  // conservative estimate
1493  const double closingSpeed = (vehicle->getLane()->getVehicleMaxSpeed(vehicle)
1494  + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1495  const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1496  double ooTTO = ooSTO / oSpeed;
1497  // round to multiples of step length (TS)
1498  ooTTO = ceil(ooTTO / TS) * TS;
1499  const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1500 #ifdef DEBUG_CHANGE_OPPOSITE
1501  if (DEBUG_COND) {
1502  std::cout << " oSpeed=" << oSpeed << " ooSTO=" << ooSTO << " ooTTO=" << ooTTO << " surplusGap3=" << surplusGap3 << "\n";
1503  }
1504 #endif
1505  surplusGap = MIN2(surplusGap, surplusGap3);
1506  }
1507  }
1508  if (!isOpposite && surplusGap < 0) {
1509 #ifdef DEBUG_CHANGE_OPPOSITE
1510  if (DEBUG_COND) {
1511  std::cout << " cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap << ")\n";
1512  }
1513 #endif
1514 
1515 #ifdef DEBUG_CHANGE_OPPOSITE
1516  if (DEBUG_COND) {
1517  if (oncoming.first->getLaneChangeModel().isOpposite()) {
1518  std::cout << SIMTIME << " ego=" << vehicle->getID() << " does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() << " (but the leader is also opposite)\n";
1519  }
1520  }
1521 #endif
1522  avoidDeadlock(vehicle, neighLead, overtaken, leader);
1523  return false;
1524  }
1525  }
1526  // compute remaining space on the opposite side
1527  // 1. the part that remains on the current lane
1528  double usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane();
1529 
1530  if (usableDist < spaceToOvertake) {
1531  // look forward along the next lanes
1532  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
1533  assert(bestLaneConts.size() >= 1);
1534  std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1535  while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1536 #ifdef DEBUG_CHANGE_OPPOSITE
1537  if (DEBUG_COND) {
1538  std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n";
1539  }
1540 #endif
1541  if ((*it)->getOpposite() == nullptr || !(*it)->getOpposite()->allowsVehicleClass(vehicle->getVClass())) {
1542  // opposite lane ends
1543  break;
1544  }
1545  // do not overtake past a minor link or turn
1546  const MSLane* const prev = *(it - 1);
1547  if (prev != nullptr) {
1548  const MSLink* link = prev->getLinkTo(*it);
1549  if (link == nullptr || link->getState() == LINKSTATE_ZIPPER
1551  || (!link->havePriority()
1552  // consider traci-influence
1553  && (!vehicle->hasInfluencer() || vehicle->getInfluencer().getRespectJunctionPriority())
1554  // consider junction model parameters
1555  && ((!link->haveRed() && !link->haveYellow()) || !vehicle->ignoreRed(link, true)))) {
1556 #ifdef DEBUG_CHANGE_OPPOSITE
1557  if (DEBUG_COND) {
1558  std::cout << " stop lookahead at link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID()) << " state=" << (link == 0 ? "?" : toString(link->getState())) << " ignoreRed=" << vehicle->ignoreRed(link, true) << "\n";
1559  }
1560 #endif
1561  break;
1562  }
1563  }
1564  usableDist += (*it)->getLength();
1565  ++it;
1566  }
1567  }
1568  if (!isOpposite && usableDist < spaceToOvertake) {
1569 #ifdef DEBUG_CHANGE_OPPOSITE
1570  if (DEBUG_COND) {
1571  std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n";
1572  }
1573 #endif
1574  return false;
1575  }
1576  if (!isOpposite && MSNet::getInstance()->hasElevation() && !overtaken.first->isStopped()) {
1577  // do not overtake before the top of a hill
1578  double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 1.5 * vehicle->getLaneChangeModel().getOppositeSafetyFactor() + spaceToOvertake;
1579  int view = vehicle->getLane()->isInternal() ? 1 : 0;
1580  bool foundHill = vehicle->getSlope() > 0;
1581  if (foundHilltop(vehicle, foundHill, searchDist, vehicle->getBestLanesContinuation(), view, vehicle->getPositionOnLane(), vehicle->getPosition().z(), OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD)) {
1582  return false;
1583  }
1584  }
1585 #ifdef DEBUG_CHANGE_OPPOSITE
1586  if (DEBUG_COND) {
1587  std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
1588  }
1589 #endif
1590  // compute wish to change
1591  std::pair<MSVehicle* const, double> neighFollow = opposite->getOppositeFollower(vehicle);
1592  double oppositeLength = vehicle->getBestLanes().back().length;
1593  if (isOpposite) {
1594  const bool canOvertake = spaceToOvertake <= OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE;
1595  oppositeLength = computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1596  leader.first = nullptr;
1597  if (neighLead.first != nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1598  // ignore oncoming vehicle on the target lane (it might even change back in this step)
1599  neighLead.first = nullptr;
1600  }
1601  } else {
1602  if (leader.first != nullptr && neighLead.first != nullptr && leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT
1603  && vehicle->getVehicleType().getVehicleClass() != SVC_EMERGENCY) {
1604 #ifdef DEBUG_CHANGE_OPPOSITE
1605  if (DEBUG_COND) {
1606  std::cout << " not changing to avoid deadlock\n";
1607  }
1608 #endif
1609  return false;
1610  }
1611  if (neighLead.first != nullptr && neighLead.first->isStopped()) {
1612  // do not start overtaking if the opposite side has been waitin for longer
1613  if (yieldToOppositeWaiting(vehicle, neighLead.first, 10)) {
1614  return false;
1615  }
1616  }
1617  if (oncoming.first != nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1618  // only abort the current column of overtaking vehicles if the opposite side has been waiting long enough
1619  if (yieldToOppositeWaiting(vehicle, oncoming.first, 10, TIME2STEPS(60))) {
1620  return false;
1621  }
1622  }
1623  }
1624  std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, nullptr, oppositeLength);
1625  return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1626 }
1627 
1628 
1629 bool
1631  std::pair<MSVehicle*, double> neighLead,
1632  std::pair<MSVehicle*, double> overtaken,
1633  std::pair<MSVehicle*, double> leader) {
1634  assert(!vehicle->getLaneChangeModel().isOpposite());
1635 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1636  if (DEBUG_COND) {
1637  std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1638  << " neighLead=" << Named::getIDSecure(neighLead.first)
1639  << " overtaken=" << Named::getIDSecure(overtaken.first)
1640  << " leader=" << Named::getIDSecure(leader.first)
1641  << "\n";
1642  }
1643 #endif
1644  if (leader.first == nullptr || neighLead.first == nullptr || overtaken.first == nullptr) {
1645  return false;
1646  } else if (!neighLead.first->isStopped()
1648  // possibly there is an oncoming vehicle before the stoppled leader that
1649  // could drive due to our yielding
1650  auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1651  neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1652  neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1653 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1654  if (DEBUG_COND) {
1655  std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
1656  }
1657 #endif
1658  if (neighLead.first == nullptr) {
1659  return false;
1660  }
1661  }
1662 
1663  const bool yield = (yieldToDeadlockOncoming(vehicle, neighLead.first, overtaken.second)
1664  || leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT);
1665  if (neighLead.first->isStopped()
1666  && (overtaken.first->isStopped()
1667  || leader.first->getLaneChangeModel().isOpposite()
1668  || yield)) {
1669 
1670  // estimate required gap
1671  double requiredGap = MAX2(vehicle->getVehicleType().getLengthWithGap(), neighLead.first->getVehicleType().getLengthWithGap());
1672  requiredGap = MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1673  requiredGap = MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1674  requiredGap += 1;
1675  const double distToStop = neighLead.second - requiredGap;
1676 
1677  // find the next non-stopped vehicle behind neighLead
1678  double neighStoppedBack = vehicle->getVehicleType().getMinGap();
1679  while (neighLead.first != nullptr && neighLead.first->isStopped()) {
1680  const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1681  if (neighStoppedBack + nextGap > overtaken.second) {
1682  break;
1683  }
1684  neighStoppedBack += nextGap;
1685  auto neighLeadFollow = neighLead.first->getFollower();
1686  neighLead.second = neighLeadFollow.second;
1687  neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1688 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1689  if (DEBUG_COND) {
1690  std::cout << " neighLeadFollower=" << Named::getIDSecure(neighLead.first) << "\n";
1691  }
1692 #endif
1693  if (neighStoppedBack > overtaken.second) {
1694  break;
1695  }
1696  }
1697 
1698  const double leaderBGap = leader.first->getBrakeGap();
1699  const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->getBestLanesContinuation(), overtaken.second, true).second;
1700  const double extraGap = MAX2(leaderBGap, leaderFGap);
1701  const double gapWithEgo = leader.second + extraGap - neighStoppedBack - vehicle->getVehicleType().getLengthWithGap();
1702 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1703  if (DEBUG_COND) {
1704  std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1705  << " neighLeadGap=" << neighLead.second
1706  << " leaderGap=" << leader.second
1707  << " bGap=" << leaderBGap
1708  << " fGap=" << leaderFGap
1709  << " eGap=" << extraGap
1710  << " neighStoppedBack=" << neighStoppedBack
1711  << " neighStoppedBackPos=" << vehicle->getPositionOnLane() + neighStoppedBack
1712  << " requiredGap=" << requiredGap
1713  << " gapWithEgo=" << gapWithEgo
1714  << " yield=" << yield
1715  << "\n";
1716  }
1717 #endif
1718  // vehicle must fit behind leader and still leave required gap
1719  if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1720  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
1721  const double currentDist = preb[vehicle->getLane()->getIndex()].length;
1722  const double stopPos = vehicle->getPositionOnLane() + distToStop;
1723 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1724  if (DEBUG_COND) {
1725  std::cout << " currentDist=" << currentDist << " stopPos=" << stopPos << " lGap+eGap=" << leader.second + extraGap << " distToStop=" << distToStop << "\n";
1726  }
1727 #endif
1728  if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1729  const double blockerLength = currentDist - stopPos;
1730  const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
1731 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1732  if (DEBUG_COND) {
1733  std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1734  << " blockerLength=" << blockerLength
1735  << " reserved=" << reserved
1736  << "\n";
1737  }
1738 #endif
1739  return reserved;
1740  }
1741  }
1742  }
1743  return false;
1744 }
1745 
1746 
1747 bool
1748 MSLaneChanger::yieldToDeadlockOncoming(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist) {
1749  if (vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT && stoppedNeigh != nullptr) {
1750  // is there a vehicle waiting behind stoppedNeigh that is encouraged by
1751  // halting ego? Due to edge-ordering it might change-opposite this step
1752  // and not be visible as leader
1753  std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
1754  double followerGap = stoppedNeigh->getVehicleType().getLengthWithGap();
1755  while (follower.first != nullptr && followerGap < dist && follower.first->isStopped()) {
1756  followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1757  follower = follower.first->getFollower(dist);
1758  };
1759  if (follower.first != nullptr) {
1760  followerGap += follower.second;
1761  }
1762 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1763  if (DEBUG_COND) {
1764  std::cout << SIMTIME << " veh=" << vehicle->getID() << " yieldToDeadlockOncoming"
1765  << " dist=" << dist << " follower=" << Named::getIDSecure(follower.first) << " fGap=" << followerGap
1766  << "\n";
1767  }
1768 #endif
1769  return follower.first != nullptr && followerGap < dist && !follower.first->isStopped();
1770  }
1771  return false;
1772 }
1773 
1774 
1775 bool
1776 MSLaneChanger::yieldToOppositeWaiting(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist, SUMOTime deltaWait) {
1777  std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
1778  while (follower.first != nullptr && follower.second < dist && follower.first->isStopped()) {
1779  follower = follower.first->getFollower(dist);
1780  };
1781 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1782  if (DEBUG_COND && follower.first != nullptr) {
1783  std::cout << SIMTIME << " yieldToOppositeWaiting veh=" << vehicle->getID() << " stoppedNeigh=" << stoppedNeigh->getID()
1784  << " oncoming=" << follower.first->getID()
1785  << " wait=" << follower.first->getWaitingSeconds()
1786  << " vehWait=" << vehicle->getWaitingSeconds()
1787  << " deltaWait=" << STEPS2TIME(deltaWait)
1788  << "\n";
1789  }
1790 #endif
1791  if (follower.first != nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->getWaitingTime() + deltaWait) {
1792  return true;
1793  }
1794  return false;
1795 }
1796 
1797 
1798 bool
1800  std::pair<MSVehicle* const, double> leader,
1801  std::pair<MSVehicle*, double> neighLead,
1802  std::pair<MSVehicle*, double> overtaken) {
1803  const double deadLockZone = overtaken.second;
1804 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1805  if (DEBUG_COND) {
1806  std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock waiting=" << vehicle->getWaitingSeconds()
1807  << " leader=" << Named::getIDSecure(leader.first)
1808  << " gap=" << leader.second
1809  << "\n";
1810  }
1811 #endif
1813  && leader.first != nullptr && leader.second > vehicle->getVehicleType().getLengthWithGap()) {
1814  // assume vehicle is halting to avoid deadlock (since there is enough
1815  // space to drive further)
1816  // keep halting as long as there is an oncoming vehicle
1817  std::pair<MSVehicle* const, double> oncomingOpposite = getOncomingOppositeVehicle(vehicle, std::make_pair(nullptr, -1), leader.second);
1818 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1819  if (DEBUG_COND) {
1820  std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
1821  << " leader=" << leader.first->getID()
1822  << " leaderGap=" << leader.second
1823  << " neighLead=" << Named::getIDSecure(neighLead.first)
1824  << " deadLockZone=" << deadLockZone
1825  << "\n";
1826  }
1827 #endif
1828  if (neighLead.first != nullptr && !neighLead.first->isStopped()) {
1829  // possibly there is an oncoming vehicle before the stoppled leader that
1830  // could drive due to our yielding
1831  auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1832  neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1833  neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1834 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1835  if (DEBUG_COND) {
1836  std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
1837  }
1838 #endif
1839  }
1840 
1841  if (oncomingOpposite.first != nullptr ||
1842  (neighLead.first != nullptr && neighLead.first->isStopped()
1843  && yieldToDeadlockOncoming(vehicle, neighLead.first, deadLockZone))) {
1844  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
1845  const double currentDist = preb[vehicle->getLane()->getIndex()].length;
1846  // mirror code in patchSpeed
1847  const double blockerLength = currentDist - vehicle->getPositionOnLane() - 1 - vehicle->getVehicleType().getMinGap() - NUMERICAL_EPS;
1848  const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
1849 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1850  if (DEBUG_COND) {
1851  std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
1852  << " leader=" << leader.first->getID()
1853  << " leaderGap=" << leader.second
1854  << " oncoming=" << Named::getIDSecure(oncomingOpposite.first)
1855  << " currentDist=" << currentDist
1856  << " blockerLength=" << blockerLength
1857  << " reserved=" << reserved
1858  << "\n";
1859  }
1860 #else
1861  UNUSED_PARAMETER(reserved);
1862 #endif
1863  return true;
1864  }
1865  }
1866  return false;
1867 }
1868 
1869 
1870 double
1871 MSLaneChanger::computeSafeOppositeLength(MSVehicle* vehicle, double oppositeLength, const MSLane* source, double usableDist,
1872  std::pair<MSVehicle*, double> oncoming, double vMax, double oncomingSpeed,
1873  std::pair<MSVehicle*, double> neighLead,
1874  std::pair<MSVehicle*, double> overtaken,
1875  std::pair<MSVehicle*, double> neighFollow,
1876  double surplusGap, const MSLane* opposite,
1877  bool canOvertake) {
1878  // compute the remaining distance that can be driven on the opposite side
1879  // this value will put into oppositeLength of the opposite lanes
1880  // @note: length counts from the start of the current lane
1881  // @note: see MSLaneChangeModel::LC2013::_wantsChange @1092 (isOpposite()
1882  // position on the target lane
1883  const double forwardPos = source->getOppositePos(vehicle->getPositionOnLane());
1884 
1885  // consider usableDist (due to minor links or end of opposite lanes)
1886  oppositeLength = MIN2(oppositeLength, usableDist + forwardPos);
1887  // consider upcoming stops
1888  oppositeLength = MIN2(oppositeLength, vehicle->nextStopDist() + forwardPos);
1889 #ifdef DEBUG_CHANGE_OPPOSITE
1890  if (DEBUG_COND) {
1891  std::cout << " laneQLength=" << oppositeLength << " usableDist=" << usableDist << " forwardPos=" << forwardPos << " stopDist=" << vehicle->nextStopDist() << "\n";
1892  }
1893 #endif
1894  // consider oncoming leaders
1895  const MSVehicle* oncomingVeh = oncoming.first;
1896  if (oncomingVeh != 0) {
1897  if (!oncomingVeh->getLaneChangeModel().isOpposite() && oncomingVeh->getLaneChangeModel().getShadowLane() != source) {
1898  double egoSpeedFraction = 0.5;
1899  if (oncomingSpeed > 0) {
1900  egoSpeedFraction = MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1901  }
1902  oppositeLength = MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1903 #ifdef DEBUG_CHANGE_OPPOSITE
1904  if (DEBUG_COND) {
1905  std::cout << SIMTIME << " found oncoming leader=" << oncomingVeh->getID() << " gap=" << oncoming.second
1906  << " egoSpeedFraction=" << egoSpeedFraction << " newDist=" << oppositeLength << "\n";
1907  }
1908 #endif
1909  } else {
1910 #ifdef DEBUG_CHANGE_OPPOSITE
1911  if (DEBUG_COND) {
1912  std::cout << SIMTIME << " opposite leader=" << oncomingVeh->getID() << " gap=" << oncoming.second << " is driving against the flow\n";
1913  }
1914 #endif
1915  }
1916  if (neighLead.first != nullptr) {
1917  if (overtaken.first == nullptr) {
1918 #ifdef DEBUG_CHANGE_OPPOSITE
1919  if (DEBUG_COND) {
1920  std::cout << SIMTIME << " ego=" << vehicle->getID() << " did not find columnleader to overtake\n";
1921  }
1922 #endif
1923  } else if (oncomingVeh != nullptr && oncomingVeh->isStopped()
1924  && neighLead.second > 0
1925  && neighFollow.second > 0
1926  && yieldToOppositeWaiting(vehicle, oncomingVeh, 10, TIME2STEPS(60))) {
1927  // merge back into the forward lane
1928  oppositeLength = forwardPos + neighLead.second;
1929  } else {
1930  if (surplusGap > 0) {
1931  // exaggerate remaining dist so that the vehicle continues
1932  // overtaking (otherwise the lane change model might abort prematurely)
1933  oppositeLength += 1000;
1934  } else {
1935  // return from the opposite side ahead of the unpassable column (unless overlapping)
1936  if (overtaken.second > 0) {
1937  oppositeLength = MIN2(oppositeLength, forwardPos + overtaken.second);
1938  }
1939  // (don't set the distance so low as to imply emergency braking)
1940  oppositeLength = MAX2(oppositeLength, forwardPos + vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed()));
1941  }
1942 #ifdef DEBUG_CHANGE_OPPOSITE
1943  if (DEBUG_COND) {
1944  std::cout << SIMTIME << " ego=" << vehicle->getID() << " is overtaking " << overtaken.first->getID()
1945  << " surplusGap=" << surplusGap
1946  << " final laneQLength=" << oppositeLength
1947  << "\n";
1948  }
1949 #endif
1950  }
1951  }
1952  } else {
1953  if (overtaken.first == nullptr || !canOvertake) {
1954  // there is no reason to stay on the opposite side
1955  std::pair<MSVehicle* const, double> oppFollow = opposite->getOppositeFollower(vehicle);
1956  if (oppFollow.first == nullptr) {
1957  oppositeLength = forwardPos;
1958  } else {
1959  const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1960  oppFollow.first, vehicle, oppFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel());
1961 #ifdef DEBUG_CHANGE_OPPOSITE
1962  if (DEBUG_COND) {
1963  std::cout << SIMTIME << " ego=" << vehicle->getID() << " neighFollow=" << oppFollow.first->getID() << " gap=" << oppFollow.second << " secureGap=" << secureGap << "\n";
1964  }
1965 #endif
1966  if (oppFollow.second > secureGap) {
1967  // back gap is safe for immidiate return
1968  oppositeLength = forwardPos;
1969  }
1970  }
1971  }
1972  }
1973 #ifdef DEBUG_CHANGE_OPPOSITE
1974  if (DEBUG_COND) {
1975  std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << oppositeLength - forwardPos << " forwardPos=" << forwardPos << " oppositeLength=" << oppositeLength << "\n";
1976  }
1977 #endif
1978  return oppositeLength;
1979 }
1980 
1981 
1982 std::pair<MSVehicle* const, double>
1983 MSLaneChanger::getOncomingVehicle(const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
1984  double searchDist, double& vMax, const MSVehicle* overtaken, MSLane::MinorLinkMode mLinkMode) {
1985  double gap = oncoming.second;
1986  while (oncoming.first != nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
1987  searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() + MAX2(0.0, oncoming.second));
1988  // leader is itself overtaking through the opposite side. find real oncoming vehicle
1989  gap += oncoming.first->getVehicleType().getLengthWithGap();
1990  if (oncoming.first != overtaken) {
1991  vMax = MIN2(vMax, oncoming.first->getSpeed());
1992  } // else: might be the case if we are overtaking a vehicle that is stopped on the opposite side
1993 #ifdef DEBUG_CHANGE_OPPOSITE
1994  if (gDebugFlag5) {
1995  std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " isOpposite gap=" << oncoming.second
1996  << " totalGap=" << gap << " searchDist=" << searchDist << " vMax=" << vMax << "\n";
1997  }
1998 #endif
1999  if (searchDist < 0) {
2000  break;
2001  }
2002  // getOppositeLeader resets the search postion by ego length and may thus create cycles
2003  if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2004  opposite = oncoming.first->getLane();
2005  }
2006  oncoming = opposite->getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2007  if (oncoming.first != nullptr) {
2008  gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2009 #ifdef DEBUG_CHANGE_OPPOSITE
2010  if (gDebugFlag5) {
2011  std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " gap=" << oncoming.second << " totalGap=" << gap << "\n";
2012  }
2013 #endif
2014  }
2015  }
2016  oncoming.second = gap;
2017  return oncoming;
2018 }
2019 
2020 
2021 std::pair<MSVehicle* const, double>
2022 MSLaneChanger::getOncomingOppositeVehicle(const MSVehicle* vehicle, std::pair<MSVehicle*, double> overtaken, double searchDist) {
2023  double gap = 0;
2024  const MSVehicle* front = nullptr;
2025  if (overtaken.first != nullptr) {
2026  gap += overtaken.second + overtaken.first->getVehicleType().getLengthWithGap();
2027  front = overtaken.first;
2028  } else {
2029  // only for special situations (i.e. traci-triggered)
2030  front = vehicle;
2031  }
2032  // we only need to look for the next leader: If it's driving in the forward
2033  // direction, it "protects" from oncoming opposite vehicles.
2034  // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
2035  const bool checkTmpVehicles = front->getLane() == vehicle->getLane();
2036  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
2037  while (conts.size() > 0 && conts.front() != front->getLane()) {
2038  conts.erase(conts.begin());
2039  }
2040  std::pair<MSVehicle* const, double> oncoming = front->getLane()->getLeader(front, front->getPositionOnLane(), conts, searchDist, checkTmpVehicles);
2041  if (oncoming.first != nullptr) {
2042  const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2043  const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2044 #ifdef DEBUG_CHANGE_OPPOSITE
2045  if (gDebugFlag5) {
2046  std::cout << SIMTIME
2047  << " front=" << front->getID() << " searchDist=" << searchDist
2048  << " oncomingOpposite=" << oncoming.first->getID()
2049  << " gap=" << oncoming.second
2050  << " isOpposite=" << isOpposite
2051  << " shadowLane=" << Named::getIDSecure(shadowLane)
2052  << "\n";
2053  }
2054 #endif
2055  if (isOpposite && shadowLane != front->getLane()) {
2056  // distance was to back position (but the vehicle is oncoming)
2057  oncoming.second -= oncoming.first->getVehicleType().getLength();
2058  oncoming.second += gap;
2059  return oncoming;
2060  }
2061  }
2062  return std::make_pair(nullptr, -1);
2063 }
2064 
2065 
2066 double
2067 MSLaneChanger::computeSurplusGap(const MSVehicle* vehicle, const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
2068  double timeToOvertake, double spaceToOvertake, double& oncomingSpeed, bool oncomingOpposite) {
2069  double surplusGap = std::numeric_limits<double>::max();
2070  const MSVehicle* oncomingVeh = oncoming.first;
2071  if (oncomingVeh != 0 && (oncomingOpposite
2072  || (!oncomingVeh->getLaneChangeModel().isOpposite()
2073  && oncomingVeh->getLaneChangeModel().getShadowLane() != opposite))) {
2074  // conservative: assume that the oncoming vehicle accelerates to its maximum speed
2075  // unless it has been standing (then assume it is trying to let us pass
2076  // to avoid deadlock)
2077  oncomingSpeed = (oncomingVeh->isStopped() || oncomingVeh->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT
2078  ? 0 : oncomingVeh->getLane()->getVehicleMaxSpeed(oncomingVeh));
2079  const double safetyGap = ((oncomingSpeed + vehicle->getLane()->getVehicleMaxSpeed(vehicle))
2080  * vehicle->getCarFollowModel().getHeadwayTime()
2082  surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2083 #ifdef DEBUG_CHANGE_OPPOSITE
2084  if (DEBUG_COND) {
2085  std::cout << SIMTIME
2086  << " oncoming=" << oncomingVeh->getID()
2087  << " oGap=" << oncoming.second
2088  << " oSpeed=" << oncomingSpeed
2089  << " sto=" << spaceToOvertake
2090  << " tto=" << timeToOvertake
2091  << " safetyGap=" << safetyGap
2092  << " surplusGap=" << surplusGap
2093  << "\n";
2094  }
2095 #endif
2096  }
2097  return surplusGap;
2098 }
2099 
2100 bool
2101 MSLaneChanger::foundHilltop(MSVehicle* vehicle, bool foundHill, double searchDist, const std::vector<MSLane*>& bestLanes, int view, double pos, double lastMax, double hilltopThreshold) {
2102  if (view >= (int)bestLanes.size()) {
2103  return false;
2104  }
2105  MSLane* lane = bestLanes[view];
2106  double laneDist = 0;
2107  const PositionVector& shape = lane->getShape();
2108  double lastZ = lastMax;
2109  for (int i = 1; i < (int)shape.size(); i++) {
2110  const double dist = lane->interpolateGeometryPosToLanePos(shape[i - 1].distanceTo(shape[i]));
2111  laneDist += dist;
2112  if (laneDist > pos) {
2113  const double z = shape[i].z();
2114  if (z > lastMax) {
2115  lastMax = z;
2116  }
2117  if (z > lastZ) {
2118  foundHill = true;
2119  }
2120  lastZ = z;
2121 #ifdef DEBUG_CHANGE_OPPOSITE
2122  if (DEBUG_COND) {
2123  std::cout << SIMTIME << " foundHill=" << foundHill << " searchDist=" << searchDist << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2124  }
2125 #endif
2126  if (foundHill && z < lastMax) {
2127  const double drop = lastMax - z;
2128  //std::cout << SIMTIME << " searchDist=" << searchDist << " hillDrop=" << drop << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2129  if (drop > hilltopThreshold) {
2130 #ifdef DEBUG_CHANGE_OPPOSITE
2131  if (DEBUG_COND) {
2132  std::cout << " cannot changeOpposite before the top of a hill searchDist=" << searchDist << " hillDrop=" << drop
2133  << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2134  }
2135 #endif
2136  return true;
2137  }
2138  }
2139  if (pos == 0) {
2140  searchDist -= dist;
2141  } else {
2142  searchDist -= laneDist - pos;
2143  pos = 0;
2144  }
2145  if (searchDist <= 0) {
2146  return false;
2147  }
2148  }
2149  }
2150  return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2151 }
2152 
2153 
2154 bool
2156  MSVehicle* vehicle,
2157  int laneOffset,
2158  MSLane* targetLane,
2159  const std::pair<MSVehicle* const, double>& leader,
2160  const std::pair<MSVehicle* const, double>& neighLead,
2161  const std::pair<MSVehicle* const, double>& neighFollow,
2162  const std::vector<MSVehicle::LaneQ>& preb) {
2163  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
2164  MSLane* source = vehicle->getMutableLane();
2165  const std::pair<MSVehicle* const, double> follower(nullptr, -1);
2166  int state = checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2167  vehicle->getLaneChangeModel().setOwnState(state);
2168  bool changingAllowed = (state & LCA_BLOCKED) == 0;
2169  // change if the vehicle wants to and is allowed to change
2170  if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed
2171  // do not change to the opposite direction for cooperative reasons
2172  && (isOpposite || (state & LCA_COOPERATIVE) == 0)) {
2173  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(source, targetLane, laneOffset);
2174 #ifdef DEBUG_CHANGE_OPPOSITE
2175  if (DEBUG_COND) {
2176  std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset << " opposite=" << Named::getIDSecure(targetLane)
2177  << " state=" << toString((LaneChangeAction)state) << "\n";
2178  }
2179 #endif
2180  if (continuous) {
2181  continueChange(vehicle, myCandi);
2182  }
2183  return true;
2184  }
2185 #ifdef DEBUG_CHANGE_OPPOSITE
2186  if (DEBUG_COND) {
2187  std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset
2188  << " opposite=" << Named::getIDSecure(targetLane) << " state=" << toString((LaneChangeAction)state) << "\n";
2189  }
2190 #endif
2191  return false;
2192 }
2193 
2194 
2195 void
2196 MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, double vMax, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake) {
2197  // Assumptions:
2198  // - leader maintains the current speed
2199  // - vehicle merges with maxSpeed ahead of leader
2200  // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
2201 
2202  // first compute these values for the case where vehicle is accelerating
2203  // without upper bound on speed
2204  const double v = vehicle->getSpeed();
2205  const double u = leader->getAcceleration() > 0 ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
2206  const double a = vehicle->getCarFollowModel().getMaxAccel();
2207  const double d = vehicle->getCarFollowModel().getMaxDecel();
2208  const double g = MAX2(0.0, (
2209  // drive up to the rear of leader
2210  gap + vehicle->getVehicleType().getMinGap()
2211  // drive head-to-head with the leader
2212  + leader->getVehicleType().getLengthWithGap()
2213  // drive past the leader
2214  + vehicle->getVehicleType().getLength()
2215  // allow for safe gap between leader and vehicle
2216  + leader->getCarFollowModel().getSecureGap(leader, vehicle, u, vMax, d))
2217  // time to move between lanes
2218  + (MSGlobals::gSublane ? vMax * vehicle->getLane()->getWidth() / vehicle->getVehicleType().getMaxSpeedLat() : 0));
2219  const double sign = -1; // XXX recheck
2220  // v*t + t*t*a*0.5 = g + u*t
2221  // solve t
2222  // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
2223  double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2224 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2225  if (DEBUG_COND) {
2226  std::cout << " computeOvertakingTime v=" << v << " vMax=" << vMax << " u=" << u << " a=" << a << " d=" << d << " gap=" << gap << " g=" << g << " t=" << t
2227  << " distEgo=" << v* t + t* t* a * 0.5 << " distLead=" << g + u* t
2228  << "\n";
2229  }
2230 #endif
2231  assert(t >= 0);
2232  if (vMax <= u) {
2233  // do not try to overtake faster leader
2234  timeToOvertake = std::numeric_limits<double>::max();
2235  spaceToOvertake = std::numeric_limits<double>::max();
2236  return;
2237  }
2238 
2239  // allow for a safety time gap
2241  // round to multiples of step length (TS)
2242  if (u > 0) {
2243  t = ceil(t / TS) * TS;
2244  }
2245 
2247  const double timeToMaxSpeed = (vMax - v) / a;
2248 
2249 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2250  if (DEBUG_COND) {
2251  std::cout << " t=" << t << " tvMax=" << timeToMaxSpeed << "\n";
2252  }
2253 #endif
2254  if (t <= timeToMaxSpeed) {
2255  timeToOvertake = t;
2256  spaceToOvertake = v * t + t * t * a * 0.5;
2257 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2258  if (DEBUG_COND) {
2259  std::cout << " sto=" << spaceToOvertake << "\n";
2260  }
2261 #endif
2262  } else {
2263  // space until max speed is reached
2264  const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2265  const double m = timeToMaxSpeed;
2266  // s + (t-m) * vMax = g + u*t
2267  // solve t
2268  t = (g - s + m * vMax) / (vMax - u);
2269  if (t < 0) {
2270  // cannot overtake in time
2271 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2272  if (DEBUG_COND) {
2273  std::cout << " t2=" << t << "\n";
2274  }
2275 #endif
2276  timeToOvertake = std::numeric_limits<double>::max();
2277  spaceToOvertake = std::numeric_limits<double>::max();
2278  return;
2279  } else {
2280  // allow for a safety time gap
2282  // round to multiples of step length (TS)
2283  if (u > 0) {
2284  t = ceil(t / TS) * TS;
2285  }
2286  timeToOvertake = t;
2287  spaceToOvertake = s + (t - m) * vMax;
2288 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2289  if (DEBUG_COND) {
2290  std::cout << " t2=" << t << " s=" << s << " sto=" << spaceToOvertake << " m=" << m << "\n";
2291  }
2292 #endif
2293  }
2294  }
2295  const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
2296  timeToOvertake *= safetyFactor;
2297  if (STEPS2TIME(leader->getStopDuration()) < timeToOvertake) {
2298  spaceToOvertake *= safetyFactor;
2299  }
2300  double frac = fmod(timeToOvertake, TS);
2301  if (frac > 0) {
2302  // round to full sim step
2303  timeToOvertake += TS - frac;
2304  }
2305 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2306  if (DEBUG_COND) {
2307  if (safetyFactor != 1) {
2308  std::cout << " applying safetyFactor=" << safetyFactor
2309  << " leaderStopTime=" << STEPS2TIME(leader->getStopDuration())
2310  << " tto=" << timeToOvertake << " sto=" << spaceToOvertake << "\n";
2311  }
2312  }
2313 #endif
2314 }
2315 
2316 
2317 
2318 std::pair<MSVehicle*, double>
2319 MSLaneChanger::getColumnleader(double& maxSpace, MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, double maxLookAhead) {
2320  assert(leader.first != 0);
2321  const MSLane* source = vehicle->getLane();
2322  // find a leader vehicle with sufficient space ahead for merging back
2323  const double overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
2324  const double mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
2325  std::pair<MSVehicle*, double> columnLeader = leader;
2326  double egoGap = leader.second;
2327  bool foundSpaceAhead = false;
2328  double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2329  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
2330  if (maxLookAhead == std::numeric_limits<double>::max()) {
2331  maxLookAhead = (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
2334  maxLookAhead = MAX2(maxLookAhead, mergeBrakeGap + 10
2335  + vehicle->getVehicleType().getLengthWithGap()
2336  + leader.first->getVehicleType().getLengthWithGap());
2337  }
2338 #ifdef DEBUG_CHANGE_OPPOSITE
2339  if (DEBUG_COND) {
2340  std::cout << " getColumnleader vehicle=" << vehicle->getID() << " leader=" << leader.first->getID() << " gap=" << leader.second << " maxLookAhead=" << maxLookAhead << "\n";
2341  }
2342 #endif
2343  const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
2344  while (!foundSpaceAhead) {
2345  const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2346  columnLeader.first, vehicle,
2347  columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
2348  + columnLeader.first->getVehicleType().getMinGap()
2349  + vehicle->getVehicleType().getLengthWithGap());
2350 
2351 
2352  // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
2353  const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge());
2354  double searchStart = columnLeader.first->getPositionOnLane();
2355  std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2356  columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2357  checkTmpVehicles);
2358  std::set<MSVehicle*> seenLeaders;
2359  while (leadLead.first != nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2360 #ifdef DEBUG_CHANGE_OPPOSITE
2361  if (DEBUG_COND) {
2362  std::cout << " skipping opposite leadLead=" << leadLead.first->getID() << " gap=" << leadLead.second << "\n";
2363  }
2364 #endif
2365  if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2366  leadLead.first = nullptr;
2367  break;
2368  }
2369  seenLeaders.insert(leadLead.first);
2370  // found via shadow lane, skip it
2371  const double searchStart2 = searchStart + MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2372  leadLead = columnLeader.first->getLane()->getLeader(
2373  columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2374  checkTmpVehicles);
2375  leadLead.second += (searchStart2 - searchStart);
2376  }
2377  if (leadLead.first == nullptr) {
2378  double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2379  double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2380  if (!columnLeader.first->isStopped()) {
2381  // if the leader is stopped we can trade space for time
2382  requiredSpace += safetyFactor * mergeBrakeGap;
2383  }
2384 #ifdef DEBUG_CHANGE_OPPOSITE
2385  if (DEBUG_COND) {
2386  std::cout << " no direct leader found after columnLeader " << columnLeader.first->getID()
2387  << " availableSpace=" << availableSpace
2388  << " reqAfterLeader=" << requiredSpaceAfterLeader
2389  << " ovSpeed=" << overtakingSpeed
2390  << " reqBGap=" << mergeBrakeGap
2391  << " reqMin=" << requiredSpace / safetyFactor
2392  << " req=" << requiredSpace
2393  << "\n";
2394  }
2395 #endif
2396  if (availableSpace > requiredSpace) {
2397  foundSpaceAhead = true;
2398  } else {
2399  // maybe the columnleader is stopped before a junction or takes a different turn.
2400  // try to find another columnleader on successive lanes
2401  const bool allowMinor = vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY;
2402  bool contsEnd = false;
2403  const MSLane* next = getLaneAfter(columnLeader.first->getLane(), conts, allowMinor, contsEnd);
2404 #ifdef DEBUG_CHANGE_OPPOSITE
2405  if (DEBUG_COND) {
2406  std::cout << " look for another leader on lane " << Named::getIDSecure(next) << "\n";
2407  }
2408 #endif
2409  while (next != nullptr && seen < maxLookAhead) {
2410  seen += next->getLength();
2411  MSVehicle* cand = next->getLastAnyVehicle();
2412  if (cand == nullptr) {
2413  availableSpace += next->getLength();
2414  if (availableSpace > requiredSpace) {
2415  foundSpaceAhead = true;
2416  break;
2417  }
2418  next = getLaneAfter(next, conts, allowMinor, contsEnd);
2419  } else {
2420  availableSpace += cand->getBackPositionOnLane();
2421  if (availableSpace > requiredSpace) {
2422  foundSpaceAhead = true;
2423  break;
2424  } else {
2425  return getColumnleader(maxSpace, vehicle, std::make_pair(cand, availableSpace + cand->getPositionOnLane()), maxLookAhead - seen);
2426  }
2427  }
2428  }
2429 #ifdef DEBUG_CHANGE_OPPOSITE
2430  if (DEBUG_COND) {
2431  std::cout << " foundSpaceAhead=" << foundSpaceAhead << " availableSpace=" << availableSpace << " next=" << Named::getIDSecure(next) << " contsEnd=" << contsEnd << " conts=" << toString(conts) << "\n";
2432  }
2433 #endif
2434  if (!foundSpaceAhead && contsEnd) {
2435  foundSpaceAhead = true;
2436  availableSpace = requiredSpace;
2437  }
2438  if (!foundSpaceAhead) {
2439  return std::make_pair(nullptr, -1);
2440  }
2441  }
2442  maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2443  } else {
2444  const double sGap = vehicle->getCarFollowModel().getSecureGap(vehicle, leadLead.first,
2445  overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2446  double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2447  if (!columnLeader.first->isStopped()) {
2448  // if the leader is stopped we can trade space for time
2449  requiredSpace += safetyFactor * sGap;
2450  }
2451 #ifdef DEBUG_CHANGE_OPPOSITE
2452  if (DEBUG_COND) {
2453  std::cout << " leader's leader " << leadLead.first->getID() << " space=" << leadLead.second
2454  << " reqAfterLeader=" << requiredSpaceAfterLeader
2455  << " ovSpeed=" << overtakingSpeed
2456  << " reqSGap=" << sGap
2457  << " reqMin=" << requiredSpace / safetyFactor
2458  << " req=" << requiredSpace
2459  << "\n";
2460  }
2461 #endif
2462  if (leadLead.second > requiredSpace) {
2463  foundSpaceAhead = true;
2464  maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2465  } else {
2466 
2467  if (leadLead.second < 0) {
2468  // must be a junction leader or some other dangerous situation
2469 #ifdef DEBUG_CHANGE_OPPOSITE
2470  if (DEBUG_COND) {
2471  std::cout << " leader's leader " << leadLead.first->getID() << " gap=" << leadLead.second << " is junction leader (aborting)\n";
2472  }
2473 #endif
2474  return std::make_pair(nullptr, -1);
2475  }
2476 
2477 #ifdef DEBUG_CHANGE_OPPOSITE
2478  if (DEBUG_COND) {
2479  std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n";
2480  }
2481 #endif
2482  seen += MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2483  if (seen > maxLookAhead) {
2484 #ifdef DEBUG_CHANGE_OPPOSITE
2485  if (DEBUG_COND) {
2486  std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n";
2487  }
2488 #endif
2489  return std::make_pair(nullptr, -1);
2490  }
2491  // see if merging after leadLead is possible
2492  egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2493  columnLeader = leadLead;
2494 #ifdef DEBUG_CHANGE_OPPOSITE
2495  if (DEBUG_COND) {
2496  std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
2497  }
2498 #endif
2499  }
2500  }
2501  }
2502  columnLeader.second = egoGap;
2503  return columnLeader;
2504 }
2505 
2506 
2507 const MSLane*
2508 MSLaneChanger::getLaneAfter(const MSLane* lane, const std::vector<MSLane*>& conts, bool allowMinor, bool& contsEnd) {
2509  for (auto it = conts.begin(); it != conts.end(); ++it) {
2510  if (*it == lane) {
2511  if (it + 1 != conts.end()) {
2512  // abort on minor link
2513  const MSLane* next = *(it + 1);
2514  const MSLink* link = lane->getLinkTo(next);
2515  if (link == nullptr || (!allowMinor && !link->havePriority())) {
2516  return nullptr;
2517  }
2518  return next;
2519  } else {
2520  contsEnd = true;
2521  return nullptr;
2522  }
2523  }
2524  }
2525  return nullptr;
2526 }
2527 
2528 double
2529 MSLaneChanger::getMaxOvertakingSpeed(const MSVehicle* vehicle, double maxSpaceToOvertake) {
2530  // v*v/2*a + v*v/2*d = maxSpaceToOvertake
2531  const double a = vehicle->getCarFollowModel().getMaxAccel();
2532  const double d = vehicle->getCarFollowModel().getMaxDecel();
2533  const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
2534  return v;
2535 }
2536 
2537 /****************************************************************************/
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:41
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:1288
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition: MSEdge.cpp:895
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:268
static double gLateralResolution
Definition: MSGlobals.h:97
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition: MSGlobals.h:171
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition: MSGlobals.h:162
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:4297
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:4471
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:2754
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition: MSLane.cpp:2600
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2649
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:4320
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:924
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:3032
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
Definition: MSLane.h:845
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:917
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:4348
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition: MSLane.cpp:4464
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:702
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:4292
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:2567
bool isInternal() const
Definition: MSLane.cpp:2526
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1462
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
Definition: MSLane.h:965
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:2823
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition: MSLane.cpp:4280
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:184
bool hasElevation() const
return whether the network contains elevation data
Definition: MSNet.h:790
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:1520
SUMOTime getLaneTimeLineDuration()
Definition: MSVehicle.cpp:461
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:5798
double computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:1472
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1579
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:5073
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5774
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:7286
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:7305
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition: MSVehicle.h:1043
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:6481
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:1244
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:6290
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:1116
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition: MSVehicle.h:1118
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:6552
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7251
bool isBidiOn(const MSLane *lane) const
whether this vehicle is driving against lane
Definition: MSVehicle.cpp:7064
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
Definition: MSVehicle.cpp:6682
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links
Definition: MSVehicle.cpp:6922
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:1217
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
Position myCachedPosition
Definition: MSVehicle.h:1938
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:5792
double myAngle
the angle in radians (
Definition: MSVehicle.h:1930
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignored
Definition: MSVehicle.cpp:7329
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:977
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition: MSVehicle.h:1685
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1868
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:322
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.