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 // XXX maxLookAhead should be higher if all leaders are stopped and lower when they are jammed/queued
44 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0 // just a guess
45 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0 // just a guess
46 // this is used for finding oncoming vehicles while driving in the opposite direction
47 #define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 200.0 // just a guess
48 
49 // ===========================================================================
50 // debug defines
51 // ===========================================================================
52 
53 //#define DEBUG_CONTINUE_CHANGE
54 //#define DEBUG_CHECK_CHANGE
55 //#define DEBUG_SURROUNDING_VEHICLES // debug getRealFollower() and getRealLeader()
56 //#define DEBUG_CHANGE_OPPOSITE
57 //#define DEBUG_ACTIONSTEPS
58 //#define DEBUG_STATE
59 //#define DEBUG_CANDIDATE
60 //#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
61 #define DEBUG_COND (vehicle->isSelected())
62 
63 
64 
65 // ===========================================================================
66 // ChangeElem member method definitions
67 // ===========================================================================
69  lead(0),
70  lane(_lane),
71  hoppedVeh(0),
72  lastBlocked(0),
73  firstBlocked(0),
74  ahead(lane),
75  aheadNext(lane, 0, 0) {
76 }
77 
78 void
80  lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
81  dens += vehicle->getVehicleType().getLengthWithGap();
82  hoppedVeh = vehicle;
83 }
84 
85 
86 // ===========================================================================
87 // member method definitions
88 // ===========================================================================
89 MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging) :
90  myAllowsChanging(allowChanging),
91  myChangeToOpposite(lanes->front()->getEdge().canChangeToOpposite()) {
92 
93  // Fill the changer with the lane-data.
94  myChanger.reserve(lanes->size());
95  for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
96  myChanger.push_back(ChangeElem(*lane));
97  myChanger.back().mayChangeRight = lane != lanes->begin();
98  myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
99  // avoid changing on internal sibling lane
100  if ((*lane)->isInternal()) {
101  if (myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
102  myChanger.back().mayChangeRight = false;
103  }
104  if (myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
105  myChanger.back().mayChangeLeft = false;
106  }
107  }
108  }
109 }
110 
111 
113 }
114 
115 
116 void
118  // This is what happens in one timestep. After initialization of the
119  // changer, each vehicle will try to change. After that the changer
120  // needs an update to prevent multiple changes of one vehicle.
121  // Finally, the change-result has to be given back to the lanes.
122  initChanger();
123  try {
124  while (vehInChanger()) {
125  const bool haveChanged = change();
126  updateChanger(haveChanged);
127  }
128  updateLanes(t);
129  } catch (const ProcessError&) {
130  // clean up locks or the gui may hang
131  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
132  ce->lane->releaseVehicles();
133  }
134  throw;
135  }
136 }
137 
138 
139 void
141  // Prepare myChanger with a safe state.
142  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
143  ce->lead = 0;
144  ce->hoppedVeh = 0;
145  ce->lastBlocked = 0;
146  ce->firstBlocked = 0;
147  ce->dens = 0;
148  ce->lane->getVehiclesSecure();
149 
150  //std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
151  }
152 }
153 
154 
155 void
156 MSLaneChanger::updateChanger(bool vehHasChanged) {
157  assert(veh(myCandi) != 0);
158 
159  // "Push" the vehicles to the back, i.e. follower becomes vehicle,
160  // vehicle becomes leader, and leader becomes predecessor of vehicle,
161  // if it exists.
162  if (!vehHasChanged || MSGlobals::gLaneChangeDuration > DELTA_T) {
163  //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " has new lead=" << veh(myCandi)->getID() << "\n";
164  myCandi->lead = veh(myCandi);
165  }
166 
167  MSLane::VehCont& vehicles = myCandi->lane->myVehicles;
168  vehicles.pop_back();
169  //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " vehicles=" << toString(myCandi->lane->myVehicles) << "\n";
170 }
171 
172 
173 void
175 
176  // Update the lane's vehicle-container.
177  // First: it is bad style to change other classes members, but for
178  // this release, other attempts were too time-consuming. In a next
179  // release we will change from this lane-centered design to a vehicle-
180  // centered. This will solve many problems.
181  // Second: this swap would be faster if vehicle-containers would have
182  // been pointers, but then I had to change too much of the MSLane code.
183  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
184  //std::cout << SIMTIME << " updateLanes lane=" << ce->lane->getID() << " myVehicles=" << toString(ce->lane->myVehicles) << " myTmpVehicles=" << toString(ce->lane->myTmpVehicles) << "\n";
185  ce->lane->swapAfterLaneChange(t);
186  ce->lane->releaseVehicles();
187  }
188 }
189 
190 
193  // Find the vehicle in myChanger with the largest position. If there
194  // is no vehicle in myChanger (shouldn't happen) , return myChanger.end().
195  ChangerIt max = myChanger.end();
196 #ifdef DEBUG_CANDIDATE
197  std::cout << SIMTIME << " findCandidate() on edge " << myChanger.begin()->lane->getEdge().getID() << std::endl;
198 #endif
199 
200  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
201  if (veh(ce) == 0) {
202  continue;
203  }
204 #ifdef DEBUG_CANDIDATE
205  std::cout << " lane = " << ce->lane->getID() << "\n";
206  std::cout << " check vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
207 #endif
208  if (max == myChanger.end()) {
209 #ifdef DEBUG_CANDIDATE
210  std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
211 #endif
212  max = ce;
213  continue;
214  }
215  assert(veh(ce) != 0);
216  assert(veh(max) != 0);
217  if (veh(max)->getPositionOnLane() < veh(ce)->getPositionOnLane()) {
218 #ifdef DEBUG_CANDIDATE
219  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";
220 #endif
221  max = ce;
222  }
223  }
224  assert(max != myChanger.end());
225  assert(veh(max) != 0);
226  return max;
227 }
228 
229 
230 bool
231 MSLaneChanger::mayChange(int direction) const {
232  if (direction == 0) {
233  return true;
234  }
235  if (!myAllowsChanging) {
236  return false;
237  }
238  if (direction == -1) {
239  return myCandi->mayChangeRight && (myCandi - 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass());
240  } else if (direction == 1) {
241  return myCandi->mayChangeLeft && (myCandi + 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass());
242  } else {
243  return false;
244  }
245 }
246 
247 
248 bool
250  // Find change-candidate. If it is on an allowed lane, try to change
251  // to the right (there is a rule in Germany that you have to change
252  // to the right, unless you are overtaking). If change to the right
253  // isn't possible, check if there is a possibility to overtake (on the
254  // left.
255  // If candidate isn't on an allowed lane, changing to an allowed has
256  // priority.
257 
258 #ifdef DEBUG_ACTIONSTEPS
259 // std::cout<< "\nCHANGE" << std::endl;
260 #endif
261 
262 
264  MSVehicle* vehicle = veh(myCandi);
265 
266  if (vehicle->getLaneChangeModel().isChangingLanes()) {
267  return continueChange(vehicle, myCandi);
268  }
269  if (!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
270  registerUnchanged(vehicle);
271  return false;
272  }
273 
274 
275  if (vehicle->isRemoteControlled()) {
276  registerUnchanged(vehicle);
277  return false;
278  }
279 
280  if (!vehicle->isActive()) {
281 #ifdef DEBUG_ACTIONSTEPS
282  if DEBUG_COND {
283  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
284  }
285 #endif
286  bool changed = false;
287  const int oldstate = vehicle->getLaneChangeModel().getOwnState();
288  // let TraCI influence the wish to change lanes during non-actionsteps
289  checkTraCICommands(vehicle);
290  if (oldstate != vehicle->getLaneChangeModel().getOwnState()) {
291  changed = applyTraCICommands(vehicle);
292  }
293  if (!changed) {
294  registerUnchanged(vehicle);
295  }
296  return changed;
297  }
298 
299  // Check for changes to the opposite lane if vehicle is active
300  std::pair<MSVehicle* const, double> leader = getRealLeader(myCandi);
301  if (myChanger.size() == 1 || vehicle->getLaneChangeModel().isOpposite()) {
302  if (changeOpposite(leader)) {
303  return true;
304  }
305  registerUnchanged(vehicle);
306  return false;
307  }
308 
309  vehicle->updateBestLanes(); // needed?
310  for (int i = 0; i < (int) myChanger.size(); ++i) {
311  vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
312  }
313 
314  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
315  // check whether the vehicle wants and is able to change to right lane
316  int stateRight = 0;
317  if (mayChange(-1)) {
318  stateRight = checkChangeWithinEdge(-1, leader, preb);
319  // change if the vehicle wants to and is allowed to change
320  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_BLOCKED) == 0) {
321  vehicle->getLaneChangeModel().setOwnState(stateRight);
322  startChange(vehicle, myCandi, -1);
323  return true;
324  }
325  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_URGENT) != 0) {
326  (myCandi - 1)->lastBlocked = vehicle;
327  if ((myCandi - 1)->firstBlocked == 0) {
328  (myCandi - 1)->firstBlocked = vehicle;
329  }
330  }
331  }
332 
333  // check whether the vehicle wants and is able to change to left lane
334  int stateLeft = 0;
335  if (mayChange(1)) {
336  stateLeft = checkChangeWithinEdge(1, leader, preb);
337  // change if the vehicle wants to and is allowed to change
338  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_BLOCKED) == 0) {
339  vehicle->getLaneChangeModel().setOwnState(stateLeft);
340  startChange(vehicle, myCandi, 1);
341  return true;
342  }
343  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_URGENT) != 0) {
344  (myCandi + 1)->lastBlocked = vehicle;
345  if ((myCandi + 1)->firstBlocked == 0) {
346  (myCandi + 1)->firstBlocked = vehicle;
347  }
348  }
349  }
350 
351  if ((stateRight & LCA_URGENT) != 0 && (stateLeft & LCA_URGENT) != 0) {
352  // ... wants to go to the left AND to the right
353  // just let them go to the right lane...
354  stateLeft = 0;
355  }
356  vehicle->getLaneChangeModel().setOwnState(stateRight | stateLeft);
357 
358  // only emergency vehicles should change to the opposite side on a
359  // multi-lane road
360  if (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
361  && changeOpposite(leader)) {
362  return true;
363  }
364 
365  registerUnchanged(vehicle);
366  return false;
367 }
368 
369 
370 void
372  myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
373  myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
374  vehicle->getLaneChangeModel().unchanged();
375 }
376 
377 
378 
379 void
381 #ifdef DEBUG_STATE
382  const int oldstate = vehicle->getLaneChangeModel().getOwnState();
383 #endif
385 #ifdef DEBUG_STATE
386  if (DEBUG_COND) {
387  const int newstate = vehicle->getLaneChangeModel().getOwnState();
388  std::cout << SIMTIME
389  << " veh=" << vehicle->getID()
390  << " oldState=" << toString((LaneChangeAction) oldstate)
391  << " newState=" << toString((LaneChangeAction) newstate)
392  << ((newstate & LCA_BLOCKED) != 0 ? " (blocked)" : "")
393  << ((newstate & LCA_OVERLAPPING) != 0 ? " (overlap)" : "")
394  << "\n";
395  }
396 #endif
397 }
398 
399 
400 bool
402  // Execute request if not blocked
403  bool changed = false;
404  const int state = vehicle->getLaneChangeModel().getOwnState();
405  const int dir = (state & LCA_RIGHT) != 0 ? -1 : ((state & LCA_LEFT) != 0 ? 1 : 0);
406  const bool execute = dir != 0 && ((state & LCA_BLOCKED) == 0);
407  if (execute) {
408  ChangerIt to = myCandi + dir;
409  bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(myCandi->lane, to->lane, dir);
410  if (continuous) {
411  changed = continueChange(vehicle, myCandi);
412  } else {
413  // insert vehicle into target lane
414  to->registerHop(vehicle);
415  changed = true;
416  }
417  }
418  return changed;
419 }
420 
421 
422 void
423 MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
424  ChangerIt to = from + direction;
425  // @todo delay entering the target lane until the vehicle intersects it
426  // physically (considering lane width and vehicle width)
427  //if (to->lane->getID() == "beg_1") std::cout << SIMTIME << " startChange to lane=" << to->lane->getID() << " myTmpVehiclesBefore=" << toString(to->lane->myTmpVehicles) << "\n";
428  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
429  if (continuous) {
430  continueChange(vehicle, myCandi);
431  } else {
432  to->registerHop(vehicle);
433  }
434 }
435 
436 bool
439  const int direction = lcm.getLaneChangeDirection();
440  const bool pastMidpoint = lcm.updateCompletion();
441  vehicle->myState.myPosLat += SPEED2DIST(lcm.getSpeedLat());
443  if (pastMidpoint) {
444  ChangerIt to = from + direction;
445  MSLane* source = myCandi->lane;
446  MSLane* target = to->lane;
447  vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
448  lcm.primaryLaneChanged(source, target, direction);
449  to->registerHop(vehicle);
450  } else {
451  from->registerHop(vehicle);
452  }
453  if (!lcm.isChangingLanes()) {
454  vehicle->myState.myPosLat = 0;
455  lcm.endLaneChangeManeuver();
456  }
457  lcm.updateShadowLane();
458  if (lcm.getShadowLane() != 0) {
459  // set as hoppedVeh on the shadow lane so it is found as leader on both lanes
460  ChangerIt shadow = pastMidpoint ? from : from + lcm.getShadowDirection();
461  shadow->hoppedVeh = vehicle;
462  }
463  vehicle->myAngle = vehicle->computeAngle();
464 
465 #ifdef DEBUG_CONTINUE_CHANGE
466  if (DEBUG_COND) {
467  std::cout << SIMTIME
468  << " continueChange veh=" << vehicle->getID()
469  << " from=" << Named::getIDSecure(from->lane)
470  << " dir=" << direction
471  << " pastMidpoint=" << pastMidpoint
472  << " posLat=" << vehicle->getLateralPositionOnLane()
473  //<< " completion=" << lcm.getLaneChangeCompletion()
474  << " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
475  //<< " shadowHopped=" << Named::getIDSecure(shadow->lane)
476  << "\n";
477  }
478 #endif
479  return pastMidpoint;
480 }
481 
482 
483 std::pair<MSVehicle* const, double>
485  assert(veh(myCandi) != 0);
486  MSVehicle* vehicle = veh(myCandi);
487 #ifdef DEBUG_SURROUNDING_VEHICLES
488  if (DEBUG_COND) {
489  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl;
490  }
491 #endif
492  // get the leading vehicle on the lane to change to
493  MSVehicle* neighLead = target->lead;
494 
495 #ifdef DEBUG_SURROUNDING_VEHICLES
496  if (DEBUG_COND) {
497  if (neighLead != 0) {
498  std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl;
499  }
500  }
501 #endif
502 
503  //if (veh(myCandi)->getID() == "disabled") std::cout << SIMTIME
504  // << " target=" << target->lane->getID()
505  // << " neighLead=" << Named::getIDSecure(neighLead)
506  // << " hopped=" << Named::getIDSecure(target->hoppedVeh)
507  // << " (416)\n";
508  // check whether the hopped vehicle became the leader
509  if (target->hoppedVeh != 0) {
510  double hoppedPos = target->hoppedVeh->getPositionOnLane();
511 #ifdef DEBUG_SURROUNDING_VEHICLES
512  if (DEBUG_COND) {
513  std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl;
514  }
515 #endif
516  if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) {
517  neighLead = target->hoppedVeh;
518  //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n";
519  }
520  }
521  if (neighLead == 0) {
522 #ifdef DEBUG_SURROUNDING_VEHICLES
523  if (DEBUG_COND) {
524  std::cout << "Looking for leader on consecutive lanes." << std::endl;
525  }
526 #endif
527  // There's no leader on the target lane. Look for leaders on consecutive lanes.
528  // (there might also be partial leaders due to continuous lane changing)
529  MSLane* targetLane = target->lane;
530  const double egoBack = vehicle->getBackPositionOnLane();
531  double leaderBack = targetLane->getLength();
532  for (MSVehicle* pl : targetLane->myPartialVehicles) {
533  double plBack = pl->getBackPositionOnLane(targetLane);
534  if (plBack < leaderBack &&
535  pl->getPositionOnLane(targetLane) + pl->getVehicleType().getMinGap() >= egoBack) {
536  neighLead = pl;
537  leaderBack = plBack;
538  }
539  }
540  if (neighLead != 0) {
541 #ifdef DEBUG_SURROUNDING_VEHICLES
542  if (DEBUG_COND) {
543  std::cout << " found leader=" << neighLead->getID() << " (partial)\n";
544  }
545 #endif
546  return std::pair<MSVehicle*, double>(neighLead, leaderBack - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap());
547  }
548  double seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane();
549  double speed = veh(myCandi)->getSpeed();
550  double dist = veh(myCandi)->getCarFollowModel().brakeGap(speed) + veh(myCandi)->getVehicleType().getMinGap();
551  // always check for link leaders while on an internal lane
552  if (seen > dist && !myCandi->lane->isInternal()) {
553 #ifdef DEBUG_SURROUNDING_VEHICLES
554  if (DEBUG_COND) {
555  std::cout << " found no leader within dist=" << dist << "\n";
556  }
557 #endif
558  return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(0), -1);
559  }
560  const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane);
561 
562  std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts);
563 #ifdef DEBUG_SURROUNDING_VEHICLES
564  if (DEBUG_COND) {
565  std::cout << " found consecutiveLeader=" << Named::getIDSecure(result.first) << "\n";
566  }
567 #endif
568  return result;
569  } else {
570  MSVehicle* candi = veh(myCandi);
571 #ifdef DEBUG_SURROUNDING_VEHICLES
572  if (DEBUG_COND) {
573  std::cout << " found leader=" << neighLead->getID() << "\n";
574  }
575 #endif
576  return std::pair<MSVehicle* const, double>(neighLead, neighLead->getBackPositionOnLane(target->lane) - candi->getPositionOnLane() - candi->getVehicleType().getMinGap());
577  }
578 }
579 
580 
581 std::pair<MSVehicle* const, double>
583  assert(veh(myCandi) != 0);
584 
585 #ifdef DEBUG_SURROUNDING_VEHICLES
586  MSVehicle* vehicle = veh(myCandi);
587  if (DEBUG_COND) {
588  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl;
589  }
590 #endif
591  MSVehicle* candi = veh(myCandi);
592  const double candiPos = candi->getPositionOnLane();
593  MSVehicle* neighFollow = veh(target);
594 
595 #ifdef DEBUG_SURROUNDING_VEHICLES
596  if (DEBUG_COND) {
597  if (neighFollow != 0) {
598  std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl;
599  } else {
600  std::cout << "veh(target) returns none." << std::endl;
601  }
602  }
603 #endif
604 
605 
606 #ifdef DEBUG_SURROUNDING_VEHICLES
607  if (DEBUG_COND) {
608  if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
609  std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
610  }
611  }
612 #endif
613 
614  // check whether the hopped vehicle became the follower
615  neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
616 
617 
618 #ifdef DEBUG_SURROUNDING_VEHICLES
619  if (DEBUG_COND) {
620  MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
621  if (partialBehind != 0 && partialBehind != neighFollow) {
622  std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(candi)->getID() << "' at position " << partialBehind->getPositionOnLane() << " is closer." << std::endl;
623  }
624  }
625 #endif
626  // or a follower which is partially lapping into the target lane
627  neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
628 
629  if (neighFollow == 0) {
630  CLeaderDist consecutiveFollower = target->lane->getFollowersOnConsecutive(candi, candi->getBackPositionOnLane(), true)[0];
631 #ifdef DEBUG_SURROUNDING_VEHICLES
632  if (DEBUG_COND) {
633  if (consecutiveFollower.first == 0) {
634  std::cout << "no follower found." << std::endl;
635  } else {
636  std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl;
637  }
638  }
639 #endif
640  return std::make_pair(const_cast<MSVehicle*>(consecutiveFollower.first), consecutiveFollower.second);
641  } else {
642 #ifdef DEBUG_SURROUNDING_VEHICLES
643  if (DEBUG_COND) {
644  std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl;
645  }
646 #endif
647  MSVehicle* candi = veh(myCandi);
648  return std::pair<MSVehicle* const, double>(neighFollow,
649  candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
650  }
651 }
652 
653 
654 MSVehicle*
655 MSLaneChanger::getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2) {
656  if (follow1 == 0 || follow1->getPositionOnLane() > maxPos) {
657  return follow2;
658  } else if (follow2 == 0 || follow2->getPositionOnLane() > maxPos) {
659  return follow1;
660  } else {
661  if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
662  return follow1;
663  } else {
664  return follow2;
665  }
666  }
667 }
668 
669 int
671  int laneOffset,
672  const std::pair<MSVehicle* const, double>& leader,
673  const std::vector<MSVehicle::LaneQ>& preb) const {
674 
675  std::pair<MSVehicle* const, double> neighLead = getRealLeader(myCandi + laneOffset);
676  std::pair<MSVehicle*, double> neighFollow = getRealFollower(myCandi + laneOffset);
677  if (neighLead.first != 0 && neighLead.first == neighFollow.first) {
678  // vehicles should not be leader and follower at the same time to avoid
679  // contradictory behavior
680  neighFollow.first = 0;
681  }
682  ChangerIt target = myCandi + laneOffset;
683  return checkChange(laneOffset, target->lane, leader, neighLead, neighFollow, preb);
684 }
685 
686 int
688  int laneOffset,
689  const MSLane* targetLane,
690  const std::pair<MSVehicle* const, double>& leader,
691  const std::pair<MSVehicle* const, double>& neighLead,
692  const std::pair<MSVehicle* const, double>& neighFollow,
693  const std::vector<MSVehicle::LaneQ>& preb) const {
694 
695  MSVehicle* vehicle = veh(myCandi);
696 
697 #ifdef DEBUG_CHECK_CHANGE
698  if (DEBUG_COND) {
699  std::cout
700  << "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'"
701  << std::endl;
702  }
703 #endif
704 
705  int blocked = 0;
706  int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
707  int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
708  // overlap
709  if (neighFollow.first != 0 && neighFollow.second < 0) {
710  blocked |= (blockedByFollower | LCA_OVERLAPPING);
711 
712  // Debug (Leo)
713 #ifdef DEBUG_CHECK_CHANGE
714  if (DEBUG_COND) {
715  std::cout << SIMTIME
716  << " overlapping with follower..."
717  << std::endl;
718  }
719 #endif
720 
721  }
722  if (neighLead.first != 0 && neighLead.second < 0) {
723  blocked |= (blockedByLeader | LCA_OVERLAPPING);
724 
725 #ifdef DEBUG_CHECK_CHANGE
726  if (DEBUG_COND) {
727  std::cout << SIMTIME
728  << " overlapping with leader..."
729  << std::endl;
730  }
731 #endif
732 
733  }
734  double secureFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
735  double secureBackGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
736  double secureOrigFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
737 
738  // safe back gap
739  if ((blocked & blockedByFollower) == 0 && neighFollow.first != 0) {
740  // Calculate secure gap conservatively with vNextFollower / vNextLeader as
741  // extrapolated speeds after the driver's expected reaction time (tau).
742  // NOTE: there exists a possible source for collisions if the follower and the leader
743  // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
744 
745  // Expected reaction time (tau) for the follower-vehicle.
746  // (substracted TS since at this point the vehicles' states are already updated)
747  // XXX: How does the ego vehicle know the value of tau for the neighboring vehicle?
748  const double followerTauRemainder = MAX2(neighFollow.first->getCarFollowModel().getHeadwayTime() - TS, 0.);
749  const double vNextFollower = neighFollow.first->getSpeed() + MAX2(0., followerTauRemainder * neighFollow.first->getAcceleration());
750  const double vNextLeader = vehicle->getSpeed() + MIN2(0., followerTauRemainder * vehicle->getAcceleration());
751  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
752  secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(vNextFollower,
753  vNextLeader, vehicle->getCarFollowModel().getMaxDecel());
754  if (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
755  blocked |= blockedByFollower;
756 
757  // Debug (Leo)
758 #ifdef DEBUG_CHECK_CHANGE
759  if (DEBUG_COND) {
760  std::cout << SIMTIME
761  << " back gap unsafe: "
762  << "gap = " << neighFollow.second
763  << ", secureGap = "
764  << neighFollow.first->getCarFollowModel().getSecureGap(vNextFollower,
765  vNextLeader, vehicle->getCarFollowModel().getMaxDecel())
766  << std::endl;
767  }
768 #endif
769 
770  }
771  }
772 
773  // safe front gap
774  if ((blocked & blockedByLeader) == 0 && neighLead.first != 0) {
775  // Calculate secure gap conservatively with vNextFollower / vNextLeader as
776  // extrapolated speeds after the driver's expected reaction time (tau).
777  // NOTE: there exists a possible source for collisions if the follower and the leader
778  // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
779 
780  // Expected reaction time (tau) for the follower-vehicle.
781  // (substracted TS since at this point the vehicles' states are already updated)
782  // XXX: How does the ego vehicle know the value of tau for the neighboring vehicle?
783  const double followerTauRemainder = MAX2(vehicle->getCarFollowModel().getHeadwayTime() - TS, 0.);
784  const double vNextFollower = vehicle->getSpeed() + MAX2(0., followerTauRemainder * vehicle->getAcceleration());
785  const double vNextLeader = neighLead.first->getSpeed() + MIN2(0., followerTauRemainder * neighLead.first->getAcceleration());
786  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
787  secureFrontGap = vehicle->getCarFollowModel().getSecureGap(vNextFollower,
788  vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel());
789  if (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
790  blocked |= blockedByLeader;
791 
792  // Debug (Leo)
793 #ifdef DEBUG_CHECK_CHANGE
794  if (DEBUG_COND) {
795  std::cout << SIMTIME
796  << " front gap unsafe: "
797  << "gap = " << neighLead.second
798  << ", secureGap = "
799  << vehicle->getCarFollowModel().getSecureGap(vNextFollower,
800  vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel())
801  << std::endl;
802  }
803 #endif
804 
805  }
806  }
807  if (blocked == 0 && MSPModel::getModel()->hasPedestrians(targetLane)) {
808  PersonDist leader = MSPModel::getModel()->nextBlocking(targetLane, vehicle->getBackPositionOnLane(),
809  vehicle->getRightSideOnLane(), vehicle->getRightSideOnLane() + vehicle->getVehicleType().getWidth(),
810  ceil(vehicle->getSpeed() / vehicle->getCarFollowModel().getMaxDecel()));
811  if (leader.first != 0) {
812  const double brakeGap = vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed());
813  // returned gap value is relative to backPosition
814  const double gap = leader.second - vehicle->getVehicleType().getLengthWithGap();
815 #ifdef DEBUG_CHECK_CHANGE
816  if (DEBUG_COND) {
817  std::cout << SIMTIME << " pedestrian on road " + leader.first->getID() << " gap=" << gap << " brakeGap=" << brakeGap << "\n";
818  }
819 #endif
820  if (brakeGap > gap) {
821  blocked |= blockedByLeader;
822 #ifdef DEBUG_CHECK_CHANGE
823  if (DEBUG_COND) {
824  std::cout << SIMTIME << " blocked by pedestrian " + leader.first->getID() << "\n";
825  }
826 #endif
827  }
828  }
829  }
830 
831  if (leader.first != 0) {
832  secureOrigFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
833  }
834 
835  MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
836  int state = blocked | vehicle->getLaneChangeModel().wantsChange(
837  laneOffset, msg, blocked, leader, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
838 
839  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != 0) {
840  // do a more careful (but expensive) check to ensure that a
841  // safety-critical leader is not being overlooked
842  // while changing on an intersection, it is not sufficient to abort the
843  // search with a leader on the current lane because all linkLeaders must
844  // be considered as well
845  const double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
846  const double speed = vehicle->getSpeed();
847  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
848  if (seen < dist || myCandi->lane->isInternal()) {
849  std::pair<MSVehicle* const, double> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
850  if (neighLead2.first != 0 && neighLead2.first != neighLead.first) {
851  const double secureGap = vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(),
852  neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
853  const double secureGap2 = secureGap * vehicle->getLaneChangeModel().getSafetyFactor();
854 #ifdef DEBUG_SURROUNDING_VEHICLES
855  if (DEBUG_COND) {
856  std::cout << SIMTIME << " found critical leader=" << neighLead2.first->getID()
857  << " gap=" << neighLead2.second << " secGap=" << secureGap << " secGap2=" << secureGap2 << "\n";
858  }
859 #endif
860  if (neighLead2.second < secureGap2) {
861  state |= blockedByLeader;
862  }
863  }
864  }
865  }
866  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
867  // ensure that merging is safe for any upcoming zipper links after changing
868  if (vehicle->unsafeLinkAhead(targetLane)) {
869  state |= blockedByLeader;
870  }
871  }
872 
873  if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
874  // Ensure that a continuous lane change manoeuvre can be completed before the next turning movement.
875  // Assume lateral position == 0. (If this should change in the future add + laneOffset*vehicle->getLateralPositionOnLane() to distToNeighLane)
876  const double distToNeighLane = 0.5 * (vehicle->getLane()->getWidth() + targetLane->getWidth());
877  // Extrapolate the LC duration if operating with speed dependent lateral speed.
878  const MSAbstractLaneChangeModel& lcm = vehicle->getLaneChangeModel();
879  const double assumedDecel = lcm.getAssumedDecelForLaneChangeDuration();
880  const double estimatedLCDuration = lcm.estimateLCDuration(vehicle->getSpeed(), distToNeighLane, assumedDecel);
881  if (estimatedLCDuration == -1) {
882  // Can't guarantee that LC will succeed if vehicle is braking -> assert(lcm.myMaxSpeedLatStanding==0)
883 #ifdef DEBUG_CHECK_CHANGE
884  if DEBUG_COND {
885  std::cout << SIMTIME << " checkChange() too slow to guarantee completion of continuous lane change."
886  << "\nestimatedLCDuration=" << estimatedLCDuration
887  << "\ndistToNeighLane=" << distToNeighLane
888  << std::endl;
889  }
890 #endif
891  state |= LCA_INSUFFICIENT_SPEED;
892  } else {
893  // Compute covered distance, when braking for the whole lc duration
894  const double decel = vehicle->getCarFollowModel().getMaxDecel() * estimatedLCDuration;
895  const double avgSpeed = 0.5 * (
896  MAX2(0., vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
897  MAX2(0., vehicle->getSpeed() - decel));
898  // Distance required for lane change.
899  const double space2change = avgSpeed * estimatedLCDuration;
900  // Available distance for LC maneuver (distance till next turn)
901  double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
902 #ifdef DEBUG_CHECK_CHANGE
903  if DEBUG_COND {
904  std::cout << SIMTIME << " checkChange() checking continuous lane change..."
905  << "\ndistToNeighLane=" << distToNeighLane
906  << " estimatedLCDuration=" << estimatedLCDuration
907  << " space2change=" << space2change
908  << " avgSpeed=" << avgSpeed
909  << std::endl;
910  }
911 #endif
912 
913  // for finding turns it doesn't matter whether we look along the current lane or the target lane
914  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
915  int view = 1;
916  MSLane* nextLane = vehicle->getLane();
917  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
918  while (!nextLane->isLinkEnd(link) && seen <= space2change) {
919  if ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT
920  // the lanes after an internal junction are on different
921  // edges and do not allow lane-changing
922  || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
923  ) {
924  state |= LCA_INSUFFICIENT_SPACE;
925  break;
926  }
927  if ((*link)->getViaLane() == 0) {
928  view++;
929  }
930  nextLane = (*link)->getViaLaneOrLane();
931  seen += nextLane->getLength();
932  // get the next link used
933  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
934  }
935 #ifdef DEBUG_CHECK_CHANGE
936  if (DEBUG_COND) {
937  std::cout << " available distance=" << seen << std::endl;
938  }
939 #endif
940  if (nextLane->isLinkEnd(link) && seen < space2change) {
941 #ifdef DEBUG_CHECK_CHANGE
942  if (DEBUG_COND) {
943  std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
944  }
945 #endif
946  state |= LCA_INSUFFICIENT_SPACE;
947  }
948 
949  if ((state & LCA_BLOCKED) == 0) {
950  // check for dangerous leaders in case the target lane changes laterally between
951  // now and the lane-changing midpoint
952  const double speed = vehicle->getSpeed();
953  seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
954  nextLane = vehicle->getLane();
955  view = 1;
956  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
957  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
958  while (!nextLane->isLinkEnd(link) && seen <= space2change && seen <= dist) {
959  nextLane = (*link)->getViaLaneOrLane();
960  MSLane* targetLane = nextLane->getParallelLane(laneOffset);
961  if (targetLane == 0) {
962  state |= LCA_INSUFFICIENT_SPACE;
963  break;
964  } else {
965  std::pair<MSVehicle* const, double> neighLead2 = targetLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
966  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
967  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
968  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
969  state |= blockedByLeader;
970  break;
971  }
972  }
973  if ((*link)->getViaLane() == 0) {
974  view++;
975  }
976  seen += nextLane->getLength();
977  // get the next link used
978  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
979  }
980  }
981  }
982  }
983  const int oldstate = state;
984  // let TraCI influence the wish to change lanes and the security to take
985  state = vehicle->influenceChangeDecision(state);
986 #ifdef DEBUG_CHECK_CHANGE
987  if (DEBUG_COND) {
988  std::cout << SIMTIME
989  << " veh=" << vehicle->getID()
990  << " oldState=" << toString((LaneChangeAction)oldstate)
991  << " newState=" << toString((LaneChangeAction)state)
992  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
993  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
994  << "\n";
995  }
996 #endif
997  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
998  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
999  // this lane change will be executed, save gaps
1000  vehicle->getLaneChangeModel().setFollowerGaps(neighFollow, secureBackGap);
1001  vehicle->getLaneChangeModel().setLeaderGaps(neighLead, secureFrontGap);
1002  vehicle->getLaneChangeModel().setOrigLeaderGaps(leader, secureOrigFrontGap);
1003  }
1004  return state;
1005 }
1006 
1007 
1008 bool
1009 MSLaneChanger::changeOpposite(std::pair<MSVehicle*, double> leader) {
1010  if (!myChangeToOpposite) {
1011  return false;
1012  }
1013  myCandi = findCandidate();
1014  MSVehicle* vehicle = veh(myCandi);
1015  MSLane* source = vehicle->getLane();
1016  if (vehicle->isStopped()) {
1017  // stopped vehicles obviously should not change lanes. Usually this is
1018  // prevent by appropriate bestLane distances
1019  return false;
1020  }
1021  int ret = 0;
1022  ret = vehicle->influenceChangeDecision(ret);
1023  bool oppositeChangeByTraci = false;
1024  // Check whether a lane change to the opposite direction was requested via TraCI
1025  if ((ret & (LCA_TRACI)) != 0) {
1026  oppositeChangeByTraci = true;
1027  }
1028  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1029  if (!isOpposite && leader.first == 0 && !oppositeChangeByTraci) {
1030  // no reason to change unless there is a leader
1031  // or we are changing back to the propper direction
1032  // XXX also check whether the leader is so far away as to be irrelevant
1033  return false;
1034  }
1035  MSLane* opposite = source->getOpposite();
1036  //There is no lane for opposite driving
1037  if (opposite == 0) {
1038  return false;
1039  }
1040  // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
1041  int direction = isOpposite ? -1 : 1;
1042  std::pair<MSVehicle*, double> neighLead((MSVehicle*)0, -1);
1043 
1044  // preliminary sanity checks for overtaking space
1045  double timeToOvertake;
1046  double spaceToOvertake;
1047  if (!isOpposite && !oppositeChangeByTraci) {
1048  assert(leader.first != 0);
1049  // find a leader vehicle with sufficient space ahead for merging back
1050  const double overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
1051  const double mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
1052  std::pair<MSVehicle*, double> columnLeader = leader;
1053  double egoGap = leader.second;
1054  bool foundSpaceAhead = false;
1055  double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
1056  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
1057  while (!foundSpaceAhead) {
1058  const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
1059  columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
1060  + vehicle->getVehicleType().getLengthWithGap());
1061 
1062 
1063  // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
1064  const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge());
1065  std::pair<MSVehicle* const, double> leadLead = columnLeader.first->getLane()->getLeader(
1066  columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap,
1067  checkTmpVehicles);
1068 
1069 #ifdef DEBUG_CHANGE_OPPOSITE
1070  if (DEBUG_COND) {
1071  std::cout << " leadLead=" << Named::getIDSecure(leadLead.first) << " gap=" << leadLead.second << "\n";
1072  }
1073 #endif
1074  if (leadLead.first == 0) {
1075  foundSpaceAhead = true;
1076  } else {
1077  const double maxLookAhead = (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
1080  const double requiredSpace = (requiredSpaceAfterLeader
1081  + vehicle->getCarFollowModel().getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel()));
1082  if (leadLead.second > requiredSpace) {
1083  foundSpaceAhead = true;
1084  } else {
1085 #ifdef DEBUG_CHANGE_OPPOSITE
1086  if (DEBUG_COND) {
1087  std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n";
1088  }
1089 #endif
1090  seen += MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
1091  if (seen > maxLookAhead) {
1092 #ifdef DEBUG_CHANGE_OPPOSITE
1093  if (DEBUG_COND) {
1094  std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n";
1095  }
1096 #endif
1097  return false;
1098  }
1099  // see if merging after leadLead is possible
1100  egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
1101  columnLeader = leadLead;
1102 #ifdef DEBUG_CHANGE_OPPOSITE
1103  if (DEBUG_COND) {
1104  std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
1105  }
1106 #endif
1107  }
1108  }
1109  }
1110 #ifdef DEBUG_CHANGE_OPPOSITE
1111  if (DEBUG_COND) {
1112  std::cout << " compute time/space to overtake for columnLeader=" << columnLeader.first->getID() << " gap=" << columnLeader.second << "\n";
1113  }
1114 #endif
1115  computeOvertakingTime(vehicle, columnLeader.first, egoGap, timeToOvertake, spaceToOvertake);
1116  // check for upcoming stops
1117  if (vehicle->nextStopDist() < spaceToOvertake) {
1118 #ifdef DEBUG_CHANGE_OPPOSITE
1119  if (DEBUG_COND) {
1120  std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
1121  }
1122 #endif
1123  return false;
1124  }
1125  neighLead = opposite->getOppositeLeader(vehicle, timeToOvertake * opposite->getSpeedLimit() * 2 + spaceToOvertake, true);
1126 
1127 #ifdef DEBUG_CHANGE_OPPOSITE
1128  if (DEBUG_COND) {
1129  std::cout << SIMTIME
1130  << " veh=" << vehicle->getID()
1131  << " changeOpposite opposite=" << opposite->getID()
1132  << " lead=" << Named::getIDSecure(leader.first)
1133  << " timeToOvertake=" << timeToOvertake
1134  << " spaceToOvertake=" << spaceToOvertake
1135  << "\n";
1136  }
1137 #endif
1138  // check for dangerous oncoming leader
1139  if (neighLead.first != 0) {
1140  const MSVehicle* oncoming = neighLead.first;
1141 
1142 #ifdef DEBUG_CHANGE_OPPOSITE
1143  if (DEBUG_COND) {
1144  std::cout << SIMTIME
1145  << " oncoming=" << oncoming->getID()
1146  << " oncomingGap=" << neighLead.second
1147  << " leaderGap=" << leader.second
1148  << "\n";
1149  }
1150 #endif
1151  if (neighLead.second - spaceToOvertake - timeToOvertake * oncoming->getSpeed() < 0) {
1152 
1153 #ifdef DEBUG_CHANGE_OPPOSITE
1154  if (DEBUG_COND) {
1155  std::cout << " cannot changeOpposite due to dangerous oncoming\n";
1156  }
1157 #endif
1158  return false;
1159  }
1160  }
1161  } else if (!oppositeChangeByTraci) {
1162  timeToOvertake = -1;
1163  // look forward as far as possible
1164  spaceToOvertake = std::numeric_limits<double>::max();
1165  leader = source->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true);
1166  // -1 will use getMaximumBrakeDist() as look-ahead distance
1167  neighLead = opposite->getOppositeLeader(vehicle, -1, false);
1168  } else {
1169  timeToOvertake = STEPS2TIME(vehicle->getInfluencer().getLaneTimeLineDuration());//todo discuss concept
1170  spaceToOvertake = timeToOvertake * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1171  }
1172  // compute remaining space on the opposite side
1173  // 1. the part that remains on the current lane
1174  double usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane();
1175 
1176  if (usableDist < spaceToOvertake) {
1177  // look forward along the next lanes
1178  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
1179  assert(bestLaneConts.size() >= 1);
1180  std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1181  while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1182 #ifdef DEBUG_CHANGE_OPPOSITE
1183  if (DEBUG_COND) {
1184  std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n";
1185  }
1186 #endif
1187  if ((*it)->getOpposite() == 0) {
1188  // opposite lane ends
1189  break;
1190  }
1191  // do not overtake past a minor link or turn
1192  if (*(it - 1) != 0) {
1193  MSLink* link = MSLinkContHelper::getConnectingLink(**(it - 1), **it);
1194  if (link == 0 || link->getState() == LINKSTATE_ZIPPER
1195  || (link->getDirection() != LINKDIR_STRAIGHT && vehicle->getVehicleType().getVehicleClass() != SVC_EMERGENCY)
1196  || (!link->havePriority()
1197  // consider traci-influence
1198  && (!vehicle->hasInfluencer() || vehicle->getInfluencer().getRespectJunctionPriority())
1199  // consider junction model parameters
1200  && ((!link->haveRed() && !link->haveYellow()) || !vehicle->ignoreRed(link, true)))) {
1201 #ifdef DEBUG_CHANGE_OPPOSITE
1202  if (DEBUG_COND) {
1203  std::cout << " stop lookahead at link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID()) << " state=" << (link == 0 ? "?" : toString(link->getState())) << " ignoreRed=" << vehicle->ignoreRed(link, true) << "\n";
1204  }
1205 #endif
1206  break;
1207  }
1208  }
1209  usableDist += (*it)->getLength();
1210  ++it;
1211  }
1212  }
1213  if (!isOpposite && usableDist < spaceToOvertake) {
1214 #ifdef DEBUG_CHANGE_OPPOSITE
1215  if (DEBUG_COND) {
1216  std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n";
1217  }
1218 #endif
1219  return false;
1220  }
1221 #ifdef DEBUG_CHANGE_OPPOSITE
1222  if (DEBUG_COND) {
1223  std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
1224  }
1225 #endif
1226  // compute wish to change
1227  // Does "preb" mean "previousBestLanes" ??? If so *rename*
1228  std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
1229  if (isOpposite) {
1230  // compute the remaining distance that can be drive on the opposite side
1231  // this value will put into LaneQ.length of the leftmost lane
1232  // @note: length counts from the start of the current lane
1233  // @note: see MSLCM_LC2013::_wantsChange @1092 (isOpposite()
1234  MSVehicle::LaneQ& laneQ = preb[preb.size() - 1];
1235  // position on the target lane
1236  const double forwardPos = source->getOppositePos(vehicle->getPositionOnLane());
1237 
1238  // consider usableDist (due to minor links or end of opposite lanes)
1239  laneQ.length = MIN2(laneQ.length, usableDist + forwardPos);
1240  // consider upcoming stops
1241  laneQ.length = MIN2(laneQ.length, vehicle->nextStopDist() + forwardPos);
1242  // consider oncoming leaders
1243  if (leader.first != 0) {
1244  laneQ.length = MIN2(laneQ.length, leader.second / 2 + forwardPos);
1245 #ifdef DEBUG_CHANGE_OPPOSITE
1246  if (DEBUG_COND) {
1247  std::cout << SIMTIME << " found oncoming leader=" << leader.first->getID() << " gap=" << leader.second << "\n";
1248  }
1249 #endif
1250  leader.first = 0; // ignore leader after this
1251  }
1252 #ifdef DEBUG_CHANGE_OPPOSITE
1253  if (DEBUG_COND) {
1254  std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << laneQ.length - forwardPos << " forwardPos=" << forwardPos << " laneQ.length=" << laneQ.length << "\n";
1255  }
1256 #endif
1257  }
1258  std::pair<MSVehicle* const, double> neighFollow = opposite->getOppositeFollower(vehicle);
1259  int state = checkChange(direction, opposite, leader, neighLead, neighFollow, preb);
1260 
1261  bool changingAllowed = (state & LCA_BLOCKED) == 0;
1262  // change if the vehicle wants to and is allowed to change
1263  if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed
1264  // do not change to the opposite direction for cooperative reasons
1265  && (isOpposite || (state & LCA_COOPERATIVE) == 0)) {
1266  vehicle->getLaneChangeModel().startLaneChangeManeuver(source, opposite, direction);
1268  vehicle->myState.myPos = source->getOppositePos(vehicle->myState.myPos);
1271  if (!isOpposite) {
1272  vehicle->myState.myBackPos = source->getOppositePos(vehicle->myState.myBackPos);
1273  }
1274 #ifdef DEBUG_CHANGE_OPPOSITE
1275  if (DEBUG_COND) {
1276  std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n";
1277  }
1278 #endif
1279  return true;
1280  }
1281 #ifdef DEBUG_CHANGE_OPPOSITE
1282  if (DEBUG_COND) {
1283  std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << direction
1284  << " opposite=" << Named::getIDSecure(opposite) << " state=" << toString((LaneChangeAction)state) << "\n";
1285  }
1286 #endif
1287  return false;
1288 }
1289 
1290 
1291 void
1292 MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake) {
1293  // Assumptions:
1294  // - leader maintains the current speed
1295  // - vehicle merges with maxSpeed ahead of leader
1296  // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
1297 
1298  // first compute these values for the case where vehicle is accelerating
1299  // without upper bound on speed
1300  const double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1301  const double v = vehicle->getSpeed();
1302  const double u = leader->getSpeed();
1303  const double a = vehicle->getCarFollowModel().getMaxAccel();
1304  const double d = vehicle->getCarFollowModel().getMaxDecel();
1305  const double g = (
1306  // drive up to the rear of leader
1307  gap + vehicle->getVehicleType().getMinGap()
1308  // drive head-to-head with the leader
1309  + leader->getVehicleType().getLengthWithGap()
1310  // drive past the leader
1311  + vehicle->getVehicleType().getLength()
1312  // allow for safe gap between leader and vehicle
1313  + leader->getCarFollowModel().getSecureGap(v, vMax, d));
1314  const double sign = -1; // XXX recheck
1315  // v*t + t*t*a*0.5 = g + u*t
1316  // solve t
1317  // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
1318  double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
1319 
1320  // allow for a safety time gap
1322  // round to multiples of step length (TS)
1323  t = ceil(t / TS) * TS;
1324 
1326  const double timeToMaxSpeed = (vMax - v) / a;
1327 
1328  if (t <= timeToMaxSpeed) {
1329  timeToOvertake = t;
1330  spaceToOvertake = v * t + t * t * a * 0.5;
1331  //if (gDebugFlag1) std::cout << " t below " << timeToMaxSpeed << " vMax=" << vMax << "\n";
1332  } else {
1333  // space until max speed is reached
1334  const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
1335  const double m = timeToMaxSpeed;
1336  // s + (t-m) * vMax = g + u*t
1337  // solve t
1338  t = (g - s + m * vMax) / (vMax - u);
1339 
1340  // allow for a safety time gap
1342  // round to multiples of step length (TS)
1343  t = ceil(t / TS) * TS;
1344 
1345  timeToOvertake = t;
1346  spaceToOvertake = s + (t - m) * vMax;
1347  //if (gDebugFlag1) std::cout << " s=" << s << " m=" << m << " vMax=" << vMax << "\n";
1348  }
1349 }
1350 
1351 /****************************************************************************/
1352 
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:307
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignore
Definition: MSVehicle.cpp:5263
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:5239
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.
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:3181
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
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
T MAX2(T a, T b)
Definition: StdDefs.h:68
#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:1824
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1397
double getRightSideOnLane() const
Get the vehicle&#39;s lateral position on the lane:
Definition: MSVehicle.cpp:4642
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:4418
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:4027
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:3527
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one...
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.
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
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)
static MSPModel * getModel()
Definition: MSPModel.cpp:59
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:4045
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:4379
#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:3204
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:948
T MIN2(T a, T b)
Definition: StdDefs.h:62
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:2108
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:3141
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:224
void updateLanes(SUMOTime t)
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:1891
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
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:5196
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:3150
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:253
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
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:2297
double getLength() const
Get vehicle&#39;s length [m].
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:3445
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:4823
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
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:322
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:4039
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:5220
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.
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:2028
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)