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.org/sumo
3 // Copyright (C) 2002-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
20 // Performs lane changing of vehicles
21 /****************************************************************************/
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include "MSLaneChanger.h"
29 #include "MSNet.h"
30 #include "MSVehicle.h"
31 #include "MSVehicleType.h"
32 #include "MSVehicleTransfer.h"
33 #include "MSGlobals.h"
34 #include <cassert>
35 #include <iterator>
36 #include <cstdlib>
37 #include <cmath>
41 
42 #define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0
43 #define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR 0.0
44 #define OPPOSITE_OVERTAKING_SAFETY_FACTOR 1.2
45 // XXX maxLookAhead should be higher if all leaders are stopped and lower when they are jammed/queued
46 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0 // just a guess
47 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0 // just a guess
48 // this is used for finding oncoming vehicles while driving in the opposite direction
49 #define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 200.0 // just a guess
50 
51 // ===========================================================================
52 // debug defines
53 // ===========================================================================
54 
55 //#define DEBUG_CONTINUE_CHANGE
56 //#define DEBUG_CHECK_CHANGE
57 //#define DEBUG_SURROUNDING_VEHICLES // debug getRealFollower() and getRealLeader()
58 //#define DEBUG_CHANGE_OPPOSITE
59 //#define DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
60 //#define DEBUG_ACTIONSTEPS
61 //#define DEBUG_STATE
62 //#define DEBUG_CANDIDATE
63 //#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
64 #define DEBUG_COND (vehicle->isSelected())
65 
66 
67 
68 // ===========================================================================
69 // ChangeElem member method definitions
70 // ===========================================================================
72  lead(0),
73  lane(_lane),
74  hoppedVeh(0),
75  lastBlocked(0),
76  firstBlocked(0),
77  ahead(lane),
78  aheadNext(lane, 0, 0) {
79 }
80 
81 void
83  lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
84  dens += vehicle->getVehicleType().getLengthWithGap();
85  hoppedVeh = vehicle;
86 }
87 
88 
89 // ===========================================================================
90 // member method definitions
91 // ===========================================================================
92 MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging) :
93  myAllowsChanging(allowChanging),
94  myChangeToOpposite(lanes->front()->getEdge().canChangeToOpposite()) {
95 
96  // Fill the changer with the lane-data.
97  myChanger.reserve(lanes->size());
98  for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
99  myChanger.push_back(ChangeElem(*lane));
100  myChanger.back().mayChangeRight = lane != lanes->begin();
101  myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
102  // avoid changing on internal sibling lane
103  if ((*lane)->isInternal()) {
104  if (myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
105  myChanger.back().mayChangeRight = false;
106  }
107  if (myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
108  myChanger.back().mayChangeLeft = false;
109  }
110  }
111  }
112 }
113 
114 
116 }
117 
118 
119 void
121  // This is what happens in one timestep. After initialization of the
122  // changer, each vehicle will try to change. After that the changer
123  // needs an update to prevent multiple changes of one vehicle.
124  // Finally, the change-result has to be given back to the lanes.
125  initChanger();
126  try {
127  while (vehInChanger()) {
128  const bool haveChanged = change();
129  updateChanger(haveChanged);
130  }
131  updateLanes(t);
132  } catch (const ProcessError&) {
133  // clean up locks or the gui may hang
134  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
135  ce->lane->releaseVehicles();
136  }
137  throw;
138  }
139 }
140 
141 
142 void
144  // Prepare myChanger with a safe state.
145  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
146  ce->lead = 0;
147  ce->hoppedVeh = 0;
148  ce->lastBlocked = 0;
149  ce->firstBlocked = 0;
150  ce->dens = 0;
151  ce->lane->getVehiclesSecure();
152 
153  //std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
154  }
155 }
156 
157 
158 void
159 MSLaneChanger::updateChanger(bool vehHasChanged) {
160  assert(veh(myCandi) != 0);
161 
162  // "Push" the vehicles to the back, i.e. follower becomes vehicle,
163  // vehicle becomes leader, and leader becomes predecessor of vehicle,
164  // if it exists.
165  if (!vehHasChanged || MSGlobals::gLaneChangeDuration > DELTA_T) {
166  //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " has new lead=" << veh(myCandi)->getID() << "\n";
167  myCandi->lead = veh(myCandi);
168  }
169 
170  MSLane::VehCont& vehicles = myCandi->lane->myVehicles;
171  vehicles.pop_back();
172  //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " vehicles=" << toString(myCandi->lane->myVehicles) << "\n";
173 }
174 
175 
176 void
178 
179  // Update the lane's vehicle-container.
180  // First: it is bad style to change other classes members, but for
181  // this release, other attempts were too time-consuming. In a next
182  // release we will change from this lane-centered design to a vehicle-
183  // centered. This will solve many problems.
184  // Second: this swap would be faster if vehicle-containers would have
185  // been pointers, but then I had to change too much of the MSLane code.
186  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
187  //std::cout << SIMTIME << " updateLanes lane=" << ce->lane->getID() << " myVehicles=" << toString(ce->lane->myVehicles) << " myTmpVehicles=" << toString(ce->lane->myTmpVehicles) << "\n";
188  ce->lane->swapAfterLaneChange(t);
189  ce->lane->releaseVehicles();
190  }
191 }
192 
193 
196  // Find the vehicle in myChanger with the largest position. If there
197  // is no vehicle in myChanger (shouldn't happen) , return myChanger.end().
198  ChangerIt max = myChanger.end();
199 #ifdef DEBUG_CANDIDATE
200  std::cout << SIMTIME << " findCandidate() on edge " << myChanger.begin()->lane->getEdge().getID() << std::endl;
201 #endif
202 
203  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
204  if (veh(ce) == 0) {
205  continue;
206  }
207 #ifdef DEBUG_CANDIDATE
208  std::cout << " lane = " << ce->lane->getID() << "\n";
209  std::cout << " check vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
210 #endif
211  if (max == myChanger.end()) {
212 #ifdef DEBUG_CANDIDATE
213  std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
214 #endif
215  max = ce;
216  continue;
217  }
218  assert(veh(ce) != 0);
219  assert(veh(max) != 0);
220  if (veh(max)->getPositionOnLane() < veh(ce)->getPositionOnLane()) {
221 #ifdef DEBUG_CANDIDATE
222  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";
223 #endif
224  max = ce;
225  }
226  }
227  assert(max != myChanger.end());
228  assert(veh(max) != 0);
229  return max;
230 }
231 
232 
233 bool
234 MSLaneChanger::mayChange(int direction) const {
235  if (direction == 0) {
236  return true;
237  }
238  if (!myAllowsChanging) {
239  return false;
240  }
241  if (direction == -1) {
242  return myCandi->mayChangeRight && (myCandi - 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass());
243  } else if (direction == 1) {
244  return myCandi->mayChangeLeft && (myCandi + 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass());
245  } else {
246  return false;
247  }
248 }
249 
250 
251 bool
253  // Find change-candidate. If it is on an allowed lane, try to change
254  // to the right (there is a rule in Germany that you have to change
255  // to the right, unless you are overtaking). If change to the right
256  // isn't possible, check if there is a possibility to overtake (on the
257  // left.
258  // If candidate isn't on an allowed lane, changing to an allowed has
259  // priority.
260 
261 #ifdef DEBUG_ACTIONSTEPS
262 // std::cout<< "\nCHANGE" << std::endl;
263 #endif
264 
265 
267  MSVehicle* vehicle = veh(myCandi);
268 
269  if (vehicle->getLaneChangeModel().isChangingLanes()) {
270  return continueChange(vehicle, myCandi);
271  }
272  if (!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
273  registerUnchanged(vehicle);
274  return false;
275  }
276 
277 
278  if (vehicle->isRemoteControlled()) {
279  registerUnchanged(vehicle);
280  return false;
281  }
282 
283  if (!vehicle->isActive()) {
284 #ifdef DEBUG_ACTIONSTEPS
285  if DEBUG_COND {
286  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
287  }
288 #endif
289  bool changed = false;
290  const int oldstate = vehicle->getLaneChangeModel().getOwnState();
291  // let TraCI influence the wish to change lanes during non-actionsteps
292  checkTraCICommands(vehicle);
293  if (oldstate != vehicle->getLaneChangeModel().getOwnState()) {
294  changed = applyTraCICommands(vehicle);
295  }
296  if (!changed) {
297  registerUnchanged(vehicle);
298  }
299  return changed;
300  }
301 
302  // Check for changes to the opposite lane if vehicle is active
303  std::pair<MSVehicle* const, double> leader = getRealLeader(myCandi);
304  if (myChanger.size() == 1 || vehicle->getLaneChangeModel().isOpposite() || (!mayChange(-1) && !mayChange(1))) {
305  if (changeOpposite(leader)) {
306  return true;
307  }
308  registerUnchanged(vehicle);
309  return false;
310  }
311 
312  vehicle->updateBestLanes(); // needed?
313  for (int i = 0; i < (int) myChanger.size(); ++i) {
314  vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
315  }
316 
317  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
318  // check whether the vehicle wants and is able to change to right lane
319  int stateRight = 0;
320  if (mayChange(-1)) {
321  stateRight = checkChangeWithinEdge(-1, leader, preb);
322  // change if the vehicle wants to and is allowed to change
323  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_BLOCKED) == 0) {
324  vehicle->getLaneChangeModel().setOwnState(stateRight);
325  startChange(vehicle, myCandi, -1);
326  return true;
327  }
328  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_URGENT) != 0) {
329  (myCandi - 1)->lastBlocked = vehicle;
330  if ((myCandi - 1)->firstBlocked == 0) {
331  (myCandi - 1)->firstBlocked = vehicle;
332  }
333  }
334  }
335 
336  // check whether the vehicle wants and is able to change to left lane
337  int stateLeft = 0;
338  if (mayChange(1)) {
339  stateLeft = checkChangeWithinEdge(1, leader, preb);
340  // change if the vehicle wants to and is allowed to change
341  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_BLOCKED) == 0) {
342  vehicle->getLaneChangeModel().setOwnState(stateLeft);
343  startChange(vehicle, myCandi, 1);
344  return true;
345  }
346  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_URGENT) != 0) {
347  (myCandi + 1)->lastBlocked = vehicle;
348  if ((myCandi + 1)->firstBlocked == 0) {
349  (myCandi + 1)->firstBlocked = vehicle;
350  }
351  }
352  }
353 
354  if ((stateRight & LCA_URGENT) != 0 && (stateLeft & LCA_URGENT) != 0) {
355  // ... wants to go to the left AND to the right
356  // just let them go to the right lane...
357  stateLeft = 0;
358  }
359  vehicle->getLaneChangeModel().setOwnState(stateRight | stateLeft);
360 
361  // only emergency vehicles should change to the opposite side on a
362  // multi-lane road
363  if (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
364  && changeOpposite(leader)) {
365  return true;
366  }
367 
368  registerUnchanged(vehicle);
369  return false;
370 }
371 
372 
373 void
375  myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
376  myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
377  vehicle->getLaneChangeModel().unchanged();
378 }
379 
380 
381 
382 void
384 #ifdef DEBUG_STATE
385  const int oldstate = vehicle->getLaneChangeModel().getOwnState();
386 #endif
388 #ifdef DEBUG_STATE
389  if (DEBUG_COND) {
390  const int newstate = vehicle->getLaneChangeModel().getOwnState();
391  std::cout << SIMTIME
392  << " veh=" << vehicle->getID()
393  << " oldState=" << toString((LaneChangeAction) oldstate)
394  << " newState=" << toString((LaneChangeAction) newstate)
395  << ((newstate & LCA_BLOCKED) != 0 ? " (blocked)" : "")
396  << ((newstate & LCA_OVERLAPPING) != 0 ? " (overlap)" : "")
397  << "\n";
398  }
399 #endif
400 }
401 
402 
403 bool
405  // Execute request if not blocked
406  bool changed = false;
407  const int state = vehicle->getLaneChangeModel().getOwnState();
408  const int dir = (state & LCA_RIGHT) != 0 ? -1 : ((state & LCA_LEFT) != 0 ? 1 : 0);
409  const bool execute = dir != 0 && ((state & LCA_BLOCKED) == 0);
410  if (execute) {
411  ChangerIt to = myCandi + dir;
412  bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(myCandi->lane, to->lane, dir);
413  if (continuous) {
414  changed = continueChange(vehicle, myCandi);
415  } else {
416  // insert vehicle into target lane
417  to->registerHop(vehicle);
418  changed = true;
419  }
420  }
421  return changed;
422 }
423 
424 
425 void
426 MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
427  ChangerIt to = from + direction;
428  // @todo delay entering the target lane until the vehicle intersects it
429  // physically (considering lane width and vehicle width)
430  //if (to->lane->getID() == "beg_1") std::cout << SIMTIME << " startChange to lane=" << to->lane->getID() << " myTmpVehiclesBefore=" << toString(to->lane->myTmpVehicles) << "\n";
431  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
432  if (continuous) {
433  continueChange(vehicle, myCandi);
434  } else {
435  to->registerHop(vehicle);
436  }
437 }
438 
439 bool
442  const int direction = lcm.getLaneChangeDirection();
443  const bool pastMidpoint = lcm.updateCompletion();
444  vehicle->myState.myPosLat += SPEED2DIST(lcm.getSpeedLat());
446  if (pastMidpoint) {
447  ChangerIt to = from + direction;
448  MSLane* source = myCandi->lane;
449  MSLane* target = to->lane;
450  vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
451  lcm.primaryLaneChanged(source, target, direction);
452  to->registerHop(vehicle);
453  } else {
454  from->registerHop(vehicle);
455  }
456  if (!lcm.isChangingLanes()) {
457  vehicle->myState.myPosLat = 0;
458  lcm.endLaneChangeManeuver();
459  }
460  lcm.updateShadowLane();
461  if (lcm.getShadowLane() != 0) {
462  // set as hoppedVeh on the shadow lane so it is found as leader on both lanes
463  ChangerIt shadow = pastMidpoint ? from : from + lcm.getShadowDirection();
464  shadow->hoppedVeh = vehicle;
465  }
466  vehicle->myAngle = vehicle->computeAngle();
467 
468 #ifdef DEBUG_CONTINUE_CHANGE
469  if (DEBUG_COND) {
470  std::cout << SIMTIME
471  << " continueChange veh=" << vehicle->getID()
472  << " from=" << Named::getIDSecure(from->lane)
473  << " dir=" << direction
474  << " pastMidpoint=" << pastMidpoint
475  << " posLat=" << vehicle->getLateralPositionOnLane()
476  //<< " completion=" << lcm.getLaneChangeCompletion()
477  << " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
478  //<< " shadowHopped=" << Named::getIDSecure(shadow->lane)
479  << "\n";
480  }
481 #endif
482  return pastMidpoint;
483 }
484 
485 
486 std::pair<MSVehicle* const, double>
488  assert(veh(myCandi) != 0);
489  MSVehicle* vehicle = veh(myCandi);
490 #ifdef DEBUG_SURROUNDING_VEHICLES
491  if (DEBUG_COND) {
492  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl;
493  }
494 #endif
495  // get the leading vehicle on the lane to change to
496  MSVehicle* neighLead = target->lead;
497 
498 #ifdef DEBUG_SURROUNDING_VEHICLES
499  if (DEBUG_COND) {
500  if (neighLead != 0) {
501  std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl;
502  }
503  }
504 #endif
505 
506  //if (veh(myCandi)->getID() == "disabled") std::cout << SIMTIME
507  // << " target=" << target->lane->getID()
508  // << " neighLead=" << Named::getIDSecure(neighLead)
509  // << " hopped=" << Named::getIDSecure(target->hoppedVeh)
510  // << " (416)\n";
511  // check whether the hopped vehicle became the leader
512  if (target->hoppedVeh != 0) {
513  double hoppedPos = target->hoppedVeh->getPositionOnLane();
514 #ifdef DEBUG_SURROUNDING_VEHICLES
515  if (DEBUG_COND) {
516  std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl;
517  }
518 #endif
519  if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) {
520  neighLead = target->hoppedVeh;
521  //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n";
522  }
523  }
524  if (neighLead == 0) {
525 #ifdef DEBUG_SURROUNDING_VEHICLES
526  if (DEBUG_COND) {
527  std::cout << "Looking for leader on consecutive lanes." << std::endl;
528  }
529 #endif
530  // There's no leader on the target lane. Look for leaders on consecutive lanes.
531  // (there might also be partial leaders due to continuous lane changing)
532  MSLane* targetLane = target->lane;
533  const double egoBack = vehicle->getBackPositionOnLane();
534  double leaderBack = targetLane->getLength();
535  for (MSVehicle* pl : targetLane->myPartialVehicles) {
536  double plBack = pl->getBackPositionOnLane(targetLane);
537  if (plBack < leaderBack &&
538  pl->getPositionOnLane(targetLane) + pl->getVehicleType().getMinGap() >= egoBack) {
539  neighLead = pl;
540  leaderBack = plBack;
541  }
542  }
543  if (neighLead != 0) {
544 #ifdef DEBUG_SURROUNDING_VEHICLES
545  if (DEBUG_COND) {
546  std::cout << " found leader=" << neighLead->getID() << " (partial)\n";
547  }
548 #endif
549  return std::pair<MSVehicle*, double>(neighLead, leaderBack - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap());
550  }
551  double seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane();
552  double speed = veh(myCandi)->getSpeed();
553  double dist = veh(myCandi)->getCarFollowModel().brakeGap(speed) + veh(myCandi)->getVehicleType().getMinGap();
554  // always check for link leaders while on an internal lane
555  if (seen > dist && !myCandi->lane->isInternal()) {
556 #ifdef DEBUG_SURROUNDING_VEHICLES
557  if (DEBUG_COND) {
558  std::cout << " found no leader within dist=" << dist << "\n";
559  }
560 #endif
561  return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(0), -1);
562  }
563  const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane);
564 
565  std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts);
566 #ifdef DEBUG_SURROUNDING_VEHICLES
567  if (DEBUG_COND) {
568  std::cout << " found consecutiveLeader=" << Named::getIDSecure(result.first) << "\n";
569  }
570 #endif
571  return result;
572  } else {
573  MSVehicle* candi = veh(myCandi);
574 #ifdef DEBUG_SURROUNDING_VEHICLES
575  if (DEBUG_COND) {
576  std::cout << " found leader=" << neighLead->getID() << "\n";
577  }
578 #endif
579  return std::pair<MSVehicle* const, double>(neighLead, neighLead->getBackPositionOnLane(target->lane) - candi->getPositionOnLane() - candi->getVehicleType().getMinGap());
580  }
581 }
582 
583 
584 std::pair<MSVehicle* const, double>
586  assert(veh(myCandi) != 0);
587 
588 #ifdef DEBUG_SURROUNDING_VEHICLES
589  MSVehicle* vehicle = veh(myCandi);
590  if (DEBUG_COND) {
591  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl;
592  }
593 #endif
594  MSVehicle* candi = veh(myCandi);
595  const double candiPos = candi->getPositionOnLane();
596  MSVehicle* neighFollow = veh(target);
597 
598 #ifdef DEBUG_SURROUNDING_VEHICLES
599  if (DEBUG_COND) {
600  if (neighFollow != 0) {
601  std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl;
602  } else {
603  std::cout << "veh(target) returns none." << std::endl;
604  }
605  }
606 #endif
607 
608 
609 #ifdef DEBUG_SURROUNDING_VEHICLES
610  if (DEBUG_COND) {
611  if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
612  std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
613  }
614  }
615 #endif
616 
617  // check whether the hopped vehicle became the follower
618  neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
619 
620 
621 #ifdef DEBUG_SURROUNDING_VEHICLES
622  if (DEBUG_COND) {
623  MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
624  if (partialBehind != 0 && partialBehind != neighFollow) {
625  std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(candi)->getID() << "' at position " << partialBehind->getPositionOnLane() << " is closer." << std::endl;
626  }
627  }
628 #endif
629  // or a follower which is partially lapping into the target lane
630  neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
631 
632  if (neighFollow == 0) {
633  CLeaderDist consecutiveFollower = target->lane->getFollowersOnConsecutive(candi, candi->getBackPositionOnLane(), true)[0];
634 #ifdef DEBUG_SURROUNDING_VEHICLES
635  if (DEBUG_COND) {
636  if (consecutiveFollower.first == 0) {
637  std::cout << "no follower found." << std::endl;
638  } else {
639  std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl;
640  }
641  }
642 #endif
643  return std::make_pair(const_cast<MSVehicle*>(consecutiveFollower.first), consecutiveFollower.second);
644  } else {
645 #ifdef DEBUG_SURROUNDING_VEHICLES
646  if (DEBUG_COND) {
647  std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl;
648  }
649 #endif
650  MSVehicle* candi = veh(myCandi);
651  return std::pair<MSVehicle* const, double>(neighFollow,
652  candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
653  }
654 }
655 
656 
657 MSVehicle*
658 MSLaneChanger::getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2) {
659  if (follow1 == 0 || follow1->getPositionOnLane() > maxPos) {
660  return follow2;
661  } else if (follow2 == 0 || follow2->getPositionOnLane() > maxPos) {
662  return follow1;
663  } else {
664  if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
665  return follow1;
666  } else {
667  return follow2;
668  }
669  }
670 }
671 
672 int
674  int laneOffset,
675  const std::pair<MSVehicle* const, double>& leader,
676  const std::vector<MSVehicle::LaneQ>& preb) const {
677 
678  std::pair<MSVehicle* const, double> neighLead = getRealLeader(myCandi + laneOffset);
679  std::pair<MSVehicle*, double> neighFollow = getRealFollower(myCandi + laneOffset);
680  if (neighLead.first != 0 && neighLead.first == neighFollow.first) {
681  // vehicles should not be leader and follower at the same time to avoid
682  // contradictory behavior
683  neighFollow.first = 0;
684  }
685  ChangerIt target = myCandi + laneOffset;
686  return checkChange(laneOffset, target->lane, leader, neighLead, neighFollow, preb);
687 }
688 
689 int
691  int laneOffset,
692  const MSLane* targetLane,
693  const std::pair<MSVehicle* const, double>& leader,
694  const std::pair<MSVehicle* const, double>& neighLead,
695  const std::pair<MSVehicle* const, double>& neighFollow,
696  const std::vector<MSVehicle::LaneQ>& preb) const {
697 
698  MSVehicle* vehicle = veh(myCandi);
699 
700 #ifdef DEBUG_CHECK_CHANGE
701  if (DEBUG_COND) {
702  std::cout
703  << "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'"
704  << std::endl;
705  }
706 #endif
707 
708  int blocked = 0;
709  int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
710  int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
711  // overlap
712  if (neighFollow.first != 0 && neighFollow.second < 0) {
713  blocked |= (blockedByFollower | LCA_OVERLAPPING);
714 
715  // Debug (Leo)
716 #ifdef DEBUG_CHECK_CHANGE
717  if (DEBUG_COND) {
718  std::cout << SIMTIME
719  << " overlapping with follower..."
720  << std::endl;
721  }
722 #endif
723 
724  }
725  if (neighLead.first != 0 && neighLead.second < 0) {
726  blocked |= (blockedByLeader | LCA_OVERLAPPING);
727 
728 #ifdef DEBUG_CHECK_CHANGE
729  if (DEBUG_COND) {
730  std::cout << SIMTIME
731  << " overlapping with leader..."
732  << std::endl;
733  }
734 #endif
735 
736  }
737  double secureFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
738  double secureBackGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
739  double secureOrigFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
740 
741  const double tauRemainder = vehicle->getActionStepLength() == DELTA_T ? 0 : MAX2(vehicle->getCarFollowModel().getHeadwayTime() - TS, 0.);
742  // safe back gap
743  if ((blocked & blockedByFollower) == 0 && neighFollow.first != 0) {
744  // Calculate secure gap conservatively with vNextFollower / vNextLeader as
745  // extrapolated speeds after the driver's expected reaction time (tau).
746  // NOTE: there exists a possible source for collisions if the follower and the leader
747  // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
748 
749  // Expected reaction time (tau) for the follower-vehicle.
750  // (substracted TS since at this point the vehicles' states are already updated)
751  const double vNextFollower = neighFollow.first->getSpeed() + MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
752  const double vNextLeader = vehicle->getSpeed() + MIN2(0., tauRemainder * vehicle->getAcceleration());
753  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
754  secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(vNextFollower,
755  vNextLeader, vehicle->getCarFollowModel().getMaxDecel());
756  if (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
757  blocked |= blockedByFollower;
758 
759  // Debug (Leo)
760 #ifdef DEBUG_CHECK_CHANGE
761  if (DEBUG_COND) {
762  std::cout << SIMTIME
763  << " back gap unsafe: "
764  << "gap = " << neighFollow.second
765  << " vNextFollower=" << vNextFollower
766  << " vNextEgo=" << vNextLeader
767  << ", secureGap = "
768  << neighFollow.first->getCarFollowModel().getSecureGap(vNextFollower,
769  vNextLeader, vehicle->getCarFollowModel().getMaxDecel())
770  << std::endl;
771  }
772 #endif
773 
774  }
775  }
776 
777  // safe front gap
778  if ((blocked & blockedByLeader) == 0 && neighLead.first != 0) {
779  // Calculate secure gap conservatively with vNextFollower / vNextLeader as
780  // extrapolated speeds after the driver's expected reaction time (tau).
781  // NOTE: there exists a possible source for collisions if the follower and the leader
782  // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
783 
784  // Expected reaction time (tau) for the follower-vehicle.
785  // (substracted TS since at this point the vehicles' states are already updated)
786  const double vNextFollower = vehicle->getSpeed() + MAX2(0., tauRemainder * vehicle->getAcceleration());
787  const double vNextLeader = neighLead.first->getSpeed() + MIN2(0., tauRemainder * neighLead.first->getAcceleration());
788  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
789  secureFrontGap = vehicle->getCarFollowModel().getSecureGap(vNextFollower,
790  vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel());
791  if (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
792  blocked |= blockedByLeader;
793 
794  // Debug (Leo)
795 #ifdef DEBUG_CHECK_CHANGE
796  if (DEBUG_COND) {
797  std::cout << SIMTIME
798  << " front gap unsafe: "
799  << "gap = " << neighLead.second
800  << " vNextLeader=" << vNextLeader
801  << " vNextEgo=" << vNextFollower
802  << ", secureGap = "
803  << vehicle->getCarFollowModel().getSecureGap(vNextFollower,
804  vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel())
805  << std::endl;
806  }
807 #endif
808 
809  }
810  }
811  if (blocked == 0 && MSPModel::getModel()->hasPedestrians(targetLane)) {
812  PersonDist leader = MSPModel::getModel()->nextBlocking(targetLane, vehicle->getBackPositionOnLane(),
813  vehicle->getRightSideOnLane(), vehicle->getRightSideOnLane() + vehicle->getVehicleType().getWidth(),
814  ceil(vehicle->getSpeed() / vehicle->getCarFollowModel().getMaxDecel()));
815  if (leader.first != 0) {
816  const double brakeGap = vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed());
817  // returned gap value is relative to backPosition
818  const double gap = leader.second - vehicle->getVehicleType().getLengthWithGap();
819 #ifdef DEBUG_CHECK_CHANGE
820  if (DEBUG_COND) {
821  std::cout << SIMTIME << " pedestrian on road " + leader.first->getID() << " gap=" << gap << " brakeGap=" << brakeGap << "\n";
822  }
823 #endif
824  if (brakeGap > gap) {
825  blocked |= blockedByLeader;
826 #ifdef DEBUG_CHECK_CHANGE
827  if (DEBUG_COND) {
828  std::cout << SIMTIME << " blocked by pedestrian " + leader.first->getID() << "\n";
829  }
830 #endif
831  }
832  }
833  }
834 
835  if (leader.first != 0) {
836  secureOrigFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
837  }
838 
839  MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
840  int state = blocked | vehicle->getLaneChangeModel().wantsChange(
841  laneOffset, msg, blocked, leader, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
842 
843  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != 0) {
844  // do a more careful (but expensive) check to ensure that a
845  // safety-critical leader is not being overlooked
846  // while changing on an intersection, it is not sufficient to abort the
847  // search with a leader on the current lane because all linkLeaders must
848  // be considered as well
849  const double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
850  const double speed = vehicle->getSpeed();
851  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
852  if (seen < dist || myCandi->lane->isInternal()) {
853  std::pair<MSVehicle* const, double> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
854  if (neighLead2.first != 0 && neighLead2.first != neighLead.first) {
855  const double secureGap = vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(),
856  neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
857  const double secureGap2 = secureGap * vehicle->getLaneChangeModel().getSafetyFactor();
858 #ifdef DEBUG_SURROUNDING_VEHICLES
859  if (DEBUG_COND) {
860  std::cout << SIMTIME << " found critical leader=" << neighLead2.first->getID()
861  << " gap=" << neighLead2.second << " secGap=" << secureGap << " secGap2=" << secureGap2 << "\n";
862  }
863 #endif
864  if (neighLead2.second < secureGap2) {
865  state |= blockedByLeader;
866  }
867  }
868  }
869  }
870  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
871  // ensure that merging is safe for any upcoming zipper links after changing
872  if (vehicle->unsafeLinkAhead(targetLane)) {
873  state |= blockedByLeader;
874  }
875  }
876 
877  if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
878  // Ensure that a continuous lane change manoeuvre can be completed before the next turning movement.
879  // Assume lateral position == 0. (If this should change in the future add + laneOffset*vehicle->getLateralPositionOnLane() to distToNeighLane)
880  const double distToNeighLane = 0.5 * (vehicle->getLane()->getWidth() + targetLane->getWidth());
881  // Extrapolate the LC duration if operating with speed dependent lateral speed.
882  const MSAbstractLaneChangeModel& lcm = vehicle->getLaneChangeModel();
883  const double assumedDecel = lcm.getAssumedDecelForLaneChangeDuration();
884  const double estimatedLCDuration = lcm.estimateLCDuration(vehicle->getSpeed(), distToNeighLane, assumedDecel);
885  if (estimatedLCDuration == -1) {
886  // Can't guarantee that LC will succeed if vehicle is braking -> assert(lcm.myMaxSpeedLatStanding==0)
887 #ifdef DEBUG_CHECK_CHANGE
888  if DEBUG_COND {
889  std::cout << SIMTIME << " checkChange() too slow to guarantee completion of continuous lane change."
890  << "\nestimatedLCDuration=" << estimatedLCDuration
891  << "\ndistToNeighLane=" << distToNeighLane
892  << std::endl;
893  }
894 #endif
895  state |= LCA_INSUFFICIENT_SPEED;
896  } else {
897  // Compute covered distance, when braking for the whole lc duration
898  const double decel = vehicle->getCarFollowModel().getMaxDecel() * estimatedLCDuration;
899  const double avgSpeed = 0.5 * (
900  MAX2(0., vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
901  MAX2(0., vehicle->getSpeed() - decel));
902  // Distance required for lane change.
903  const double space2change = avgSpeed * estimatedLCDuration;
904  // Available distance for LC maneuver (distance till next turn)
905  double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
906 #ifdef DEBUG_CHECK_CHANGE
907  if DEBUG_COND {
908  std::cout << SIMTIME << " checkChange() checking continuous lane change..."
909  << "\ndistToNeighLane=" << distToNeighLane
910  << " estimatedLCDuration=" << estimatedLCDuration
911  << " space2change=" << space2change
912  << " avgSpeed=" << avgSpeed
913  << std::endl;
914  }
915 #endif
916 
917  // for finding turns it doesn't matter whether we look along the current lane or the target lane
918  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
919  int view = 1;
920  MSLane* nextLane = vehicle->getLane();
921  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
922  while (!nextLane->isLinkEnd(link) && seen <= space2change) {
923  if ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT
924  // the lanes after an internal junction are on different
925  // edges and do not allow lane-changing
926  || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
927  ) {
928  state |= LCA_INSUFFICIENT_SPACE;
929  break;
930  }
931  if ((*link)->getViaLane() == 0) {
932  view++;
933  }
934  nextLane = (*link)->getViaLaneOrLane();
935  seen += nextLane->getLength();
936  // get the next link used
937  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
938  }
939 #ifdef DEBUG_CHECK_CHANGE
940  if (DEBUG_COND) {
941  std::cout << " available distance=" << seen << std::endl;
942  }
943 #endif
944  if (nextLane->isLinkEnd(link) && seen < space2change) {
945 #ifdef DEBUG_CHECK_CHANGE
946  if (DEBUG_COND) {
947  std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
948  }
949 #endif
950  state |= LCA_INSUFFICIENT_SPACE;
951  }
952 
953  if ((state & LCA_BLOCKED) == 0) {
954  // check for dangerous leaders in case the target lane changes laterally between
955  // now and the lane-changing midpoint
956  const double speed = vehicle->getSpeed();
957  seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
958  nextLane = vehicle->getLane();
959  view = 1;
960  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
961  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
962  while (!nextLane->isLinkEnd(link) && seen <= space2change && seen <= dist) {
963  nextLane = (*link)->getViaLaneOrLane();
964  MSLane* targetLane = nextLane->getParallelLane(laneOffset);
965  if (targetLane == 0) {
966  state |= LCA_INSUFFICIENT_SPACE;
967  break;
968  } else {
969  std::pair<MSVehicle* const, double> neighLead2 = targetLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
970  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
971  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
972  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
973  state |= blockedByLeader;
974  break;
975  }
976  }
977  if ((*link)->getViaLane() == 0) {
978  view++;
979  }
980  seen += nextLane->getLength();
981  // get the next link used
982  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
983  }
984  }
985  }
986  }
987  const int oldstate = state;
988  // let TraCI influence the wish to change lanes and the security to take
989  state = vehicle->influenceChangeDecision(state);
990 #ifdef DEBUG_CHECK_CHANGE
991  if (DEBUG_COND) {
992  std::cout << SIMTIME
993  << " veh=" << vehicle->getID()
994  << " oldState=" << toString((LaneChangeAction)oldstate)
995  << " newState=" << toString((LaneChangeAction)state)
996  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
997  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
998  << "\n";
999  }
1000 #endif
1001  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
1002  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
1003  // this lane change will be executed, save gaps
1004  vehicle->getLaneChangeModel().setFollowerGaps(neighFollow, secureBackGap);
1005  vehicle->getLaneChangeModel().setLeaderGaps(neighLead, secureFrontGap);
1006  vehicle->getLaneChangeModel().setOrigLeaderGaps(leader, secureOrigFrontGap);
1007  }
1008  return state;
1009 }
1010 
1011 
1012 bool
1013 MSLaneChanger::changeOpposite(std::pair<MSVehicle*, double> leader) {
1014  if (!myChangeToOpposite) {
1015  return false;
1016  }
1017  myCandi = findCandidate();
1018  MSVehicle* vehicle = veh(myCandi);
1019  MSLane* source = vehicle->getLane();
1020  if (vehicle->isStopped()) {
1021  // stopped vehicles obviously should not change lanes. Usually this is
1022  // prevent by appropriate bestLane distances
1023  return false;
1024  }
1025  int ret = 0;
1026  ret = vehicle->influenceChangeDecision(ret);
1027  bool oppositeChangeByTraci = false;
1028  // Check whether a lane change to the opposite direction was requested via TraCI
1029  if ((ret & (LCA_TRACI)) != 0) {
1030  oppositeChangeByTraci = true;
1031  }
1032  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1033  if (!isOpposite && leader.first == 0 && !oppositeChangeByTraci) {
1034  // no reason to change unless there is a leader
1035  // or we are changing back to the propper direction
1036  // XXX also check whether the leader is so far away as to be irrelevant
1037  return false;
1038  }
1039  if (!isOpposite && !oppositeChangeByTraci
1040  && vehicle->getVClass() != SVC_EMERGENCY
1041  && leader.first != 0
1042  && leader.first->signalSet(MSNet::getInstance()->lefthand()
1044  // do not try to overtake a vehicle that is about to turn left or wants
1045  // to change left itself
1046 #ifdef DEBUG_CHANGE_OPPOSITE
1047  if (DEBUG_COND) {
1048  std::cout << " not overtaking leader " << leader.first->getID() << " that has blinker set\n";
1049  }
1050 #endif
1051  return false;
1052  }
1053 
1054  MSLane* opposite = source->getOpposite();
1055  //There is no lane for opposite driving
1056  if (opposite == 0 || !opposite->allowsVehicleClass(vehicle->getVClass())) {
1057  return false;
1058  }
1059  // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
1060  int direction = isOpposite ? -1 : 1;
1061  std::pair<MSVehicle*, double> neighLead((MSVehicle*)0, -1);
1062 
1063  // preliminary sanity checks for overtaking space
1064  double timeToOvertake;
1065  double spaceToOvertake;
1066 
1067  // we need to find two vehicles:
1068  // 1) the leader that shall be overtaken (not necessarily the current leader but one of its leaders that has enough space in front)
1069  // 2) the oncoming vehicle (we need to look past vehicles that are currentlyovertaking through the opposite direction themselves)
1070  //
1071  // if the vehicle is driving normally, then the search for 1) starts on the current lane and 2) on the opposite lane
1072  // if the vehicle is driving on the opposite side then 1) is found on the neighboring lane and 2) on the current lane
1073 
1074  std::pair<MSVehicle*, double> overtaken;
1075  std::pair<MSVehicle*, double> oncoming;
1076 
1077 
1078  if (!isOpposite && !oppositeChangeByTraci) {
1079  overtaken = getColumnleader(vehicle, leader);
1080  if (overtaken.first == 0) {
1081  return false;
1082  }
1083 #ifdef DEBUG_CHANGE_OPPOSITE
1084  if (DEBUG_COND) {
1085  std::cout << " compute time/space to overtake for columnLeader=" << overtaken.first->getID() << " egoGap=" << overtaken.second << "\n";
1086  }
1087 #endif
1088  computeOvertakingTime(vehicle, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1089  // check for upcoming stops
1090  if (vehicle->nextStopDist() < spaceToOvertake) {
1091 #ifdef DEBUG_CHANGE_OPPOSITE
1092  if (DEBUG_COND) {
1093  std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
1094  }
1095 #endif
1096  return false;
1097  }
1098  neighLead = opposite->getOppositeLeader(vehicle, timeToOvertake * opposite->getSpeedLimit() * 2 + spaceToOvertake, true);
1099 
1100 #ifdef DEBUG_CHANGE_OPPOSITE
1101  if (DEBUG_COND) {
1102  std::cout << SIMTIME
1103  << " veh=" << vehicle->getID()
1104  << " changeOpposite opposite=" << opposite->getID()
1105  << " lead=" << Named::getIDSecure(leader.first)
1106  << " timeToOvertake=" << timeToOvertake
1107  << " spaceToOvertake=" << spaceToOvertake
1108  << "\n";
1109  }
1110 #endif
1111  // check for dangerous oncoming leader
1112  if (neighLead.first != 0) {
1113  const MSVehicle* oncoming = neighLead.first;
1114  // conservative: assume that the oncoming vehicle accelerates to its maximum speed
1115  const double oncomingSpeed = oncoming->isStopped() ? 0 : oncoming->getLane()->getVehicleMaxSpeed(oncoming);
1116  const double safetyGap = ((oncomingSpeed + vehicle->getLane()->getVehicleMaxSpeed(vehicle))
1117  * vehicle->getCarFollowModel().getHeadwayTime()
1119  const double surplusGap = neighLead.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
1120 #ifdef DEBUG_CHANGE_OPPOSITE
1121  if (DEBUG_COND) {
1122  std::cout << SIMTIME
1123  << " oncoming=" << oncoming->getID()
1124  << " oncomingGap=" << neighLead.second
1125  << " leaderGap=" << leader.second
1126  << " safetyGap=" << safetyGap
1127  << " surplusGap=" << surplusGap
1128  << "\n";
1129  }
1130 #endif
1131  if (surplusGap < 0) {
1132 
1133 #ifdef DEBUG_CHANGE_OPPOSITE
1134  if (DEBUG_COND) {
1135  std::cout << " cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap << ")\n";
1136  }
1137 #endif
1138 
1139 #ifdef DEBUG_CHANGE_OPPOSITE
1140  if (DEBUG_COND) {
1141  if (oncoming->getLaneChangeModel().isOpposite()) {
1142  std::cout << SIMTIME << " ego=" << vehicle->getID() << " does not changeOpposite due to dangerous oncoming " << oncoming->getID() << " (but the leader is also opposite)\n";
1143  }
1144  }
1145 #endif
1146  return false;
1147  }
1148  }
1149 
1150  } else if (!oppositeChangeByTraci) {
1151  timeToOvertake = -1;
1152  // look forward as far as possible
1153  spaceToOvertake = std::numeric_limits<double>::max();
1155  leader = source->getOppositeLeader(vehicle, dist, true);
1156  double gap = leader.second;
1157  while (leader.first != nullptr && leader.first->getLaneChangeModel().isOpposite() && dist > 0) {
1158  // look beyond leaders that are also driving in the opposite direction until finding an oncoming leader or exhausting the look-ahead distance
1159 #ifdef DEBUG_CHANGE_OPPOSITE
1160  if (DEBUG_COND) {
1161  std::cout << SIMTIME << " ego=" << vehicle->getID() << " opposite leader=" << leader.first->getID() << " gap=" << gap << " is driving against the flow\n";
1162  }
1163 #endif
1164  const double gapToLeaderFront = leader.second + leader.first->getVehicleType().getLengthWithGap();
1165  dist -= gapToLeaderFront;
1166  leader = source->getOppositeLeader(leader.first, dist, true);
1167  if (leader.first != 0) {
1168  gap += gapToLeaderFront;
1169  }
1170  }
1171  leader.second = gap;
1172  // -1 will use getMaximumBrakeDist() as look-ahead distance
1173  neighLead = opposite->getOppositeLeader(vehicle, -1, false);
1174  } else {
1175  timeToOvertake = STEPS2TIME(vehicle->getInfluencer().getLaneTimeLineDuration());//todo discuss concept
1176  spaceToOvertake = timeToOvertake * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1177  }
1178  // compute remaining space on the opposite side
1179  // 1. the part that remains on the current lane
1180  double usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane();
1181 
1182  if (usableDist < spaceToOvertake) {
1183  // look forward along the next lanes
1184  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
1185  assert(bestLaneConts.size() >= 1);
1186  std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1187  while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1188 #ifdef DEBUG_CHANGE_OPPOSITE
1189  if (DEBUG_COND) {
1190  std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n";
1191  }
1192 #endif
1193  if ((*it)->getOpposite() == 0 || !(*it)->getOpposite()->allowsVehicleClass(vehicle->getVClass())) {
1194  // opposite lane ends
1195  break;
1196  }
1197  // do not overtake past a minor link or turn
1198  if (*(it - 1) != 0) {
1199  MSLink* link = MSLinkContHelper::getConnectingLink(**(it - 1), **it);
1200  if (link == 0 || link->getState() == LINKSTATE_ZIPPER
1201  || (link->getDirection() != LINKDIR_STRAIGHT && vehicle->getVehicleType().getVehicleClass() != SVC_EMERGENCY)
1202  || (!link->havePriority()
1203  // consider traci-influence
1204  && (!vehicle->hasInfluencer() || vehicle->getInfluencer().getRespectJunctionPriority())
1205  // consider junction model parameters
1206  && ((!link->haveRed() && !link->haveYellow()) || !vehicle->ignoreRed(link, true)))) {
1207 #ifdef DEBUG_CHANGE_OPPOSITE
1208  if (DEBUG_COND) {
1209  std::cout << " stop lookahead at link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID()) << " state=" << (link == 0 ? "?" : toString(link->getState())) << " ignoreRed=" << vehicle->ignoreRed(link, true) << "\n";
1210  }
1211 #endif
1212  break;
1213  }
1214  }
1215  usableDist += (*it)->getLength();
1216  ++it;
1217  }
1218  }
1219  if (!isOpposite && usableDist < spaceToOvertake) {
1220 #ifdef DEBUG_CHANGE_OPPOSITE
1221  if (DEBUG_COND) {
1222  std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n";
1223  }
1224 #endif
1225  return false;
1226  }
1227 #ifdef DEBUG_CHANGE_OPPOSITE
1228  if (DEBUG_COND) {
1229  std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
1230  }
1231 #endif
1232  // compute wish to change
1233  // Does "preb" mean "previousBestLanes" ??? If so *rename*
1234  std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
1235  if (isOpposite) {
1236  // compute the remaining distance that can be drive on the opposite side
1237  // this value will put into LaneQ.length of the leftmost lane
1238  // @note: length counts from the start of the current lane
1239  // @note: see MSLCM_LC2013::_wantsChange @1092 (isOpposite()
1240  MSVehicle::LaneQ& laneQ = preb[preb.size() - 1];
1241  // position on the target lane
1242  const double forwardPos = source->getOppositePos(vehicle->getPositionOnLane());
1243 
1244  // consider usableDist (due to minor links or end of opposite lanes)
1245  laneQ.length = MIN2(laneQ.length, usableDist + forwardPos);
1246  // consider upcoming stops
1247  laneQ.length = MIN2(laneQ.length, vehicle->nextStopDist() + forwardPos);
1248  // consider oncoming leaders
1249  if (leader.first != 0) {
1250  if (!leader.first->getLaneChangeModel().isOpposite()) {
1251  MSVehicle* oncoming = leader.first;
1252  const double oncomingSpeed = oncoming->getAcceleration() > 0 ? oncoming->getLane()->getVehicleMaxSpeed(oncoming) : oncoming->getSpeed();
1253  const double safetyGap = ((oncomingSpeed + vehicle->getLane()->getVehicleMaxSpeed(vehicle))
1254  * vehicle->getCarFollowModel().getHeadwayTime()
1256  laneQ.length = MIN2(laneQ.length, leader.second / 2 + forwardPos - safetyGap);
1257 #ifdef DEBUG_CHANGE_OPPOSITE
1258  if (DEBUG_COND) {
1259  std::cout << SIMTIME << " found oncoming leader=" << oncoming->getID() << " gap=" << leader.second << "\n";
1260  }
1261 #endif
1262  } else {
1263 #ifdef DEBUG_CHANGE_OPPOSITE
1264  if (DEBUG_COND) {
1265  std::cout << SIMTIME << " opposite leader=" << leader.first->getID() << " gap=" << leader.second << " is driving against the flow\n";
1266  }
1267 #endif
1268  }
1269  if (neighLead.first != 0) {
1270  overtaken = getColumnleader(vehicle, neighLead);
1271  if (overtaken.first == 0) {
1272 #ifdef DEBUG_CHANGE_OPPOSITE
1273  if (DEBUG_COND) {
1274  std::cout << SIMTIME << " ego=" << vehicle->getID() << " did not find columnleader to overtake\n";
1275  }
1276 #endif
1277  } else {
1278  const double remainingDist = laneQ.length - forwardPos;
1279  computeOvertakingTime(vehicle, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1280 #ifdef DEBUG_CHANGE_OPPOSITE
1281  if (DEBUG_COND) {
1282  std::cout << SIMTIME << " ego=" << vehicle->getID() << " is overtaking " << overtaken.first->getID()
1283  << " remainingDist=" << remainingDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
1284  }
1285 #endif
1286  if (remainingDist > spaceToOvertake) {
1287  // exaggerate remaining dist so that the vehicle continues
1288  // overtaking (otherwise the lane change model might abort prematurely)
1289  laneQ.length += 1000;
1290  }
1291  }
1292  }
1293  leader.first = 0; // ignore leader after this
1294  }
1295 #ifdef DEBUG_CHANGE_OPPOSITE
1296  if (DEBUG_COND) {
1297  std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << laneQ.length - forwardPos << " forwardPos=" << forwardPos << " laneQ.length=" << laneQ.length << "\n";
1298  }
1299 #endif
1300  }
1301  std::pair<MSVehicle* const, double> neighFollow = opposite->getOppositeFollower(vehicle);
1302  int state = checkChange(direction, opposite, leader, neighLead, neighFollow, preb);
1303  vehicle->getLaneChangeModel().setOwnState(state);
1304 
1305  bool changingAllowed = (state & LCA_BLOCKED) == 0;
1306  // change if the vehicle wants to and is allowed to change
1307  if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed
1308  // do not change to the opposite direction for cooperative reasons
1309  && (isOpposite || (state & LCA_COOPERATIVE) == 0)) {
1310  vehicle->getLaneChangeModel().startLaneChangeManeuver(source, opposite, direction);
1312  vehicle->myState.myPos = source->getOppositePos(vehicle->myState.myPos);
1315  if (!isOpposite) {
1316  vehicle->myState.myBackPos = source->getOppositePos(vehicle->myState.myBackPos);
1317  }
1318 #ifdef DEBUG_CHANGE_OPPOSITE
1319  if (DEBUG_COND) {
1320  std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n";
1321  }
1322 #endif
1323  return true;
1324  }
1325 #ifdef DEBUG_CHANGE_OPPOSITE
1326  if (DEBUG_COND) {
1327  std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << direction
1328  << " opposite=" << Named::getIDSecure(opposite) << " state=" << toString((LaneChangeAction)state) << "\n";
1329  }
1330 #endif
1331  return false;
1332 }
1333 
1334 
1335 void
1336 MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake) {
1337  // Assumptions:
1338  // - leader maintains the current speed
1339  // - vehicle merges with maxSpeed ahead of leader
1340  // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
1341 
1342  // first compute these values for the case where vehicle is accelerating
1343  // without upper bound on speed
1344  const double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1345  const double v = vehicle->getSpeed();
1346  const double u = leader->getAcceleration() > 0 ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
1347  const double a = vehicle->getCarFollowModel().getMaxAccel();
1348  const double d = vehicle->getCarFollowModel().getMaxDecel();
1349  const double g = (
1350  // drive up to the rear of leader
1351  gap + vehicle->getVehicleType().getMinGap()
1352  // drive head-to-head with the leader
1353  + leader->getVehicleType().getLengthWithGap()
1354  // drive past the leader
1355  + vehicle->getVehicleType().getLength()
1356  // allow for safe gap between leader and vehicle
1357  + leader->getCarFollowModel().getSecureGap(u, vMax, d));
1358  const double sign = -1; // XXX recheck
1359  // v*t + t*t*a*0.5 = g + u*t
1360  // solve t
1361  // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
1362  double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
1363 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1364  if (DEBUG_COND) {
1365  std::cout << " computeOvertakingTime v=" << v << " vMax=" << vMax << " u=" << u << " a=" << a << " d=" << d << " gap=" << gap << " g=" << g << " t=" << t
1366  << " distEgo=" << v* t + t* t* a * 0.5 << " distLead=" << g + u* t
1367  << "\n";
1368  }
1369 #endif
1370  assert(t >= 0);
1371 
1372  // allow for a safety time gap
1374  // round to multiples of step length (TS)
1375  t = ceil(t / TS) * TS;
1376 
1378  const double timeToMaxSpeed = (vMax - v) / a;
1379 
1380 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1381  if (DEBUG_COND) {
1382  std::cout << " t=" << t << " tvMax=" << timeToMaxSpeed << "\n";
1383  }
1384 #endif
1385  if (t <= timeToMaxSpeed) {
1386  timeToOvertake = t;
1387  spaceToOvertake = v * t + t * t * a * 0.5;
1388 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1389  if (DEBUG_COND) {
1390  std::cout << " sto=" << spaceToOvertake << "\n";
1391  }
1392 #endif
1393  } else {
1394  // space until max speed is reached
1395  const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
1396  const double m = timeToMaxSpeed;
1397  // s + (t-m) * vMax = g + u*t
1398  // solve t
1399  t = (g - s + m * vMax) / (vMax - u);
1400  if (t < 0) {
1401  // cannot overtake in time
1402 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1403  if (DEBUG_COND) {
1404  std::cout << " t2=" << t << "\n";
1405  }
1406 #endif
1407  timeToOvertake = std::numeric_limits<double>::max();
1408  spaceToOvertake = std::numeric_limits<double>::max();
1409  } else {
1410  // allow for a safety time gap
1412  // round to multiples of step length (TS)
1413  t = ceil(t / TS) * TS;
1414 
1415  timeToOvertake = t;
1416  spaceToOvertake = s + (t - m) * vMax;
1417 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1418  if (DEBUG_COND) {
1419  std::cout << " t2=" << t << " s=" << s << " sto=" << spaceToOvertake << " m=" << m << "\n";
1420  }
1421 #endif
1422  }
1423  }
1425  timeToOvertake *= safetyFactor;
1426  spaceToOvertake *= safetyFactor;
1427 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1428  if (DEBUG_COND) {
1429  if (safetyFactor != 1) {
1430  std::cout << " applying safetyFactor=" << safetyFactor
1431  << " tto=" << timeToOvertake << " sto=" << spaceToOvertake << "\n";
1432  }
1433  }
1434 #endif
1435 
1436 }
1437 
1438 
1439 
1440 std::pair<MSVehicle*, double>
1441 MSLaneChanger::getColumnleader(MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, double maxLookAhead) {
1442  assert(leader.first != 0);
1443  MSLane* source = vehicle->getLane();
1444  // find a leader vehicle with sufficient space ahead for merging back
1445  const double overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
1446  const double mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
1447  std::pair<MSVehicle*, double> columnLeader = leader;
1448  double egoGap = leader.second;
1449  bool foundSpaceAhead = false;
1450  double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
1451  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
1452  if (maxLookAhead == std::numeric_limits<double>::max()) {
1453  maxLookAhead = (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
1456  }
1457 #ifdef DEBUG_CHANGE_OPPOSITE
1458  if (DEBUG_COND) {
1459  std::cout << " getColumnleader vehicle=" << vehicle->getID() << " leader=" << leader.first->getID() << " gap=" << leader.second << " maxLookAhead=" << maxLookAhead << "\n";
1460  }
1461 #endif
1463  while (!foundSpaceAhead) {
1464  const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
1465  columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
1466  + columnLeader.first->getVehicleType().getMinGap()
1467  + vehicle->getVehicleType().getLengthWithGap());
1468 
1469 
1470  // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
1471  const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge());
1472  std::pair<MSVehicle* const, double> leadLead = columnLeader.first->getLane()->getLeader(
1473  columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap,
1474  checkTmpVehicles);
1475 
1476 #ifdef DEBUG_CHANGE_OPPOSITE
1477  if (DEBUG_COND) {
1478  std::cout << " leadLead=" << Named::getIDSecure(leadLead.first) << " gap=" << leadLead.second << "\n";
1479  }
1480 #endif
1481  if (leadLead.first == 0) {
1482  double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
1483  const double requiredSpace = safetyFactor * (requiredSpaceAfterLeader
1484  + vehicle->getCarFollowModel().brakeGap(overtakingSpeed));
1485 #ifdef DEBUG_CHANGE_OPPOSITE
1486  if (DEBUG_COND) {
1487  std::cout << " no direct leader found after columnLeader " << columnLeader.first->getID()
1488  << " availableSpace=" << availableSpace
1489  << " req1=" << requiredSpaceAfterLeader
1490  << " req2=" << requiredSpace / safetyFactor
1491  << " req3=" << requiredSpace
1492  << "\n";
1493  }
1494 #endif
1495  if (availableSpace > requiredSpace) {
1496  foundSpaceAhead = true;
1497  } else {
1498  // maybe the columnleader is stopped before a junction or takes a different turn.
1499  // try to find another columnleader on successive lanes
1500  MSLane* next = getLaneAfter(columnLeader.first->getLane(), conts);
1501 #ifdef DEBUG_CHANGE_OPPOSITE
1502  if (DEBUG_COND) {
1503  std::cout << " look for another leader on lane " << Named::getIDSecure(next) << "\n";
1504  }
1505 #endif
1506  while (next != nullptr) {
1507  seen += next->getLength();
1508  MSVehicle* cand = next->getLastAnyVehicle();
1509  if (cand == nullptr) {
1510  availableSpace += next->getLength();
1511  if (availableSpace > requiredSpace) {
1512  foundSpaceAhead = true;
1513  break;
1514  }
1515  } else {
1516  availableSpace += cand->getBackPositionOnLane();
1517  if (availableSpace > requiredSpace) {
1518  foundSpaceAhead = true;
1519  break;
1520  } else {
1521  return getColumnleader(vehicle, std::make_pair(cand, availableSpace + cand->getPositionOnLane()), maxLookAhead - seen);
1522  }
1523  }
1524  }
1525  if (!foundSpaceAhead) {
1526  return std::make_pair(nullptr, -1);
1527  }
1528  }
1529  } else {
1530  const double requiredSpace = safetyFactor * (requiredSpaceAfterLeader
1531  + vehicle->getCarFollowModel().getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel()));
1532 #ifdef DEBUG_CHANGE_OPPOSITE
1533  if (DEBUG_COND) {
1534  std::cout << " leader's leader " << leadLead.first->getID() << " space=" << leadLead.second
1535  << " req1=" << requiredSpaceAfterLeader
1536  << " req2=" << requiredSpace / safetyFactor
1537  << " req3=" << requiredSpace
1538  << "\n";
1539  }
1540 #endif
1541  if (leadLead.second > requiredSpace) {
1542  foundSpaceAhead = true;
1543  } else {
1544 #ifdef DEBUG_CHANGE_OPPOSITE
1545  if (DEBUG_COND) {
1546  std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n";
1547  }
1548 #endif
1549  seen += MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
1550  if (seen > maxLookAhead) {
1551 #ifdef DEBUG_CHANGE_OPPOSITE
1552  if (DEBUG_COND) {
1553  std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n";
1554  }
1555 #endif
1556  return std::make_pair(nullptr, -1);
1557  }
1558  // see if merging after leadLead is possible
1559  egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
1560  columnLeader = leadLead;
1561 #ifdef DEBUG_CHANGE_OPPOSITE
1562  if (DEBUG_COND) {
1563  std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
1564  }
1565 #endif
1566  }
1567  }
1568  }
1569  columnLeader.second = egoGap;
1570  return columnLeader;
1571 }
1572 
1573 
1574 MSLane*
1575 MSLaneChanger::getLaneAfter(MSLane* lane, const std::vector<MSLane*>& conts) {
1576  for (auto it = conts.begin(); it != conts.end(); ++it) {
1577  if (*it == lane) {
1578  if (it + 1 != conts.end()) {
1579  return *(it + 1);
1580  } else {
1581  return nullptr;
1582  }
1583  }
1584  }
1585  return nullptr;
1586 }
1587 
1588 
1589 /****************************************************************************/
1590 
double myPos
the stored position
Definition: MSVehicle.h:136
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge&#39;e lanes.
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected.
Definition: MSVehicle.h:1422
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
double computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:1075
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:485
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time tau (i...
Definition: MSCFModel.h:313
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignore
Definition: MSVehicle.cpp:5264
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:617
double myAngle
the angle in radians (
Definition: MSVehicle.h:1778
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:79
long long int SUMOTime
Definition: SUMOTime.h:36
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:5240
MSLane * lane
the lane corresponding to this ChangeElem (the current change candidate is on this lane) ...
Definition: MSLaneChanger.h:74
#define SPEED2DIST(x)
Definition: SUMOTime.h:48
The action is done to help someone else.
static std::pair< MSVehicle *, double > getColumnleader(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
virtual bool hasPedestrians(const MSLane *lane)
whether the given lane has pedestrians on it
Definition: MSPModel.h:85
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir) const
Definition: MSLane.cpp:3193
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1712
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:54
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change...
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:561
void setLeaderGaps(CLeaderDist, double secGap)
The vehicle is blocked by left follower.
int checkChange(int laneOffset, const 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) const
bool continueChange(MSVehicle *vehicle, ChangerIt &from)
continue a lane change maneuver and return whether the midpoint was passed in this step (used if gLan...
virtual void initChanger()
Initialize the changer before looping over all vehicles.
int getShadowDirection() const
return the direction in which the current shadow lane lies
virtual bool changeOpposite(std::pair< MSVehicle *, double > leader)
const bool myAllowsChanging
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:399
double myPosLat
the stored lateral position
Definition: MSVehicle.h:142
MSVehicle * veh(ConstChangerIt ce) const
static MSLane * getLaneAfter(MSLane *lane, const std::vector< MSLane *> &conts)
return the next lane in conts beyond lane or nullptr
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
Wants go to the right.
Vehicle is too slow to guarantee success of lane change (used for continuous lane changing in case th...
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:160
T MAX2(T a, T b)
Definition: StdDefs.h:76
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:507
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:62
bool isLinkEnd(MSLinkCont::const_iterator &i) const
Definition: MSLane.cpp:1836
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1397
double getRightSideOnLane() const
Get the vehicle&#39;s lateral position on the lane:
Definition: MSVehicle.cpp:4643
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:4419
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
void startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
start the lane change maneuver (and finish it instantly if gLaneChangeDuration == 0) ...
const std::string & getID() const
Returns the id.
Definition: Named.h:69
#define TS
Definition: SUMOTime.h:45
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:808
VehCont myPartialVehicles
The lane&#39;s partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1186
Wants go to the left.
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:523
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
This is an uncontrolled, zipper-merge link.
The link is a (hard) left direction.
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4028
SUMOTime getLaneTimeLineDuration()
Definition: MSVehicle.cpp:302
#define SIMTIME
Definition: SUMOTime.h:65
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:3528
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one...
Right blinker lights are switched on.
Definition: MSVehicle.h:1173
bool applyTraCICommands(MSVehicle *vehicle)
Execute TraCI LC-commands.
The link is a straight direction.
double getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:210
void setFollowerGaps(CLeaderDist follower, double secGap)
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
A class responsible for exchanging messages between cars involved in lane-change interaction.
double getLCParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
virtual bool change()
The vehicle changes lanes (micro only)
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:887
Left blinker lights are switched on.
Definition: MSVehicle.h:1175
virtual void updateChanger(bool vehHasChanged)
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
Definition: MSLane.h:1190
blocked in all directions
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
The action is urgent (to be defined by lc-model)
virtual double getSecureGap(const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.h:328
static MSPModel * getModel()
Definition: MSPModel.cpp:59
SUMOTime getActionStepLength() const
Returns the vehicle&#39;s action step length in millisecs, i.e. the interval between two action points...
Definition: MSVehicle.h:505
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:4046
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:4380
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, 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...
Position myCachedPosition
Definition: MSVehicle.h:1786
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition: MSLane.cpp:3216
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:499
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.
#define STEPS2TIME(x)
Definition: SUMOTime.h:58
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:951
T MIN2(T a, T b)
Definition: StdDefs.h:70
The link is a (hard) right direction.
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:2120
static void computeOvertakingTime(const MSVehicle *vehicle, const MSVehicle *leader, double gap, double &timeToOvertake, double &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
A structure representing the best lanes for continuing the current route starting at &#39;lane&#39;...
Definition: MSVehicle.h:804
virtual PersonDist nextBlocking(const MSLane *lane, double minPos, double minRight, double maxLeft, double stopTime=0)
returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or 0 ...
Definition: MSPModel.h:91
bool hasInfluencer() const
Definition: MSVehicle.h:1572
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:218
MSLaneChanger()
Default constructor.
MSLane * getOpposite() const
return the opposite direction lane for lane changing or 0
Definition: MSLane.cpp:3153
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:224
void updateLanes(SUMOTime t)
const SUMOVTypeParameter & getParameter() const
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:83
static MSLinkCont::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane *> &conts)
Definition: MSLane.cpp:1903
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:436
void setOrigLeaderGaps(CLeaderDist, double secGap)
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD
std::pair< const MSPerson *, double > PersonDist
Definition: MSPModel.h:38
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:35
SUMOVehicleClass getVClass() const
Returns the vehicle&#39;s access class.
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:5197
virtual double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
virtual void setOwnState(const int state)
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:3162
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
Definition: MSVehicle.h:591
virtual ~MSLaneChanger()
Destructor.
virtual double getHeadwayTime() const
Get the driver&#39;s desired headway [s].
Definition: MSCFModel.h:259
The vehicle is blocked being overlapping.
#define DEBUG_COND
double getAcceleration() const
Returns the vehicle&#39;s acceleration in m/s (this is computed as the last step&#39;s mean acceleration in c...
Definition: MSVehicle.h:496
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1875
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:2309
double getLength() const
Get vehicle&#39;s length [m].
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:749
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
The action is due to a TraCI request.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:3446
#define OPPOSITE_OVERTAKING_SAFETY_FACTOR
void registerUnchanged(MSVehicle *vehicle)
The vehicle does not have enough space to complete a continuous lane and change before the next turni...
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links ...
Definition: MSVehicle.cpp:4824
MSLane * getShadowLane() const
Returns the lane the vehicle&#39;s shadow is on during continuous/sublane lane change.
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1386
MSVehicle * hoppedVeh
last vehicle that changed into this lane
Definition: MSLaneChanger.h:76
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:4040
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:479
The vehicle is blocked by right leader.
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:5221
public emergency vehicles
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:82
const std::string & getID() const
Returns the name of the vehicle.
Representation of a lane in the micro simulation.
Definition: MSLane.h:71
double myBackPos
the stored back position
Definition: MSVehicle.h:147
The vehicle is blocked by right follower.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
void saveLCState(const int dir, const int stateWithoutTraCI, const int state)
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
Interface for lane-change models.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR
ChangerIt myCandi
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:274
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition: MSVehicle.h:1039
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2040
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)