SUMO - Simulation of Urban MObility
MSLaneChanger.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 // Performs lane changing of vehicles
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
15 // Copyright (C) 2002-2017 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include "MSLaneChanger.h"
36 #include "MSNet.h"
37 #include "MSVehicle.h"
38 #include "MSVehicleType.h"
39 #include "MSVehicleTransfer.h"
40 #include "MSGlobals.h"
41 #include <cassert>
42 #include <iterator>
43 #include <cstdlib>
44 #include <cmath>
47 
48 #define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0
49 // XXX maxLookAhead should be higher if all leaders are stopped and lower when they are jammed/queued
50 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0 // just a guess
51 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0 // just a guess
52 // this is used for finding oncoming vehicles while driving in the opposite direction
53 #define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 200.0 // just a guess
54 
55 // ===========================================================================
56 // debug defines
57 // ===========================================================================
58 //#define DEBUG_VEHICLE_GUI_SELECTION
59 
60 //#define DEBUG_CONTINUE_CHANGE
61 //#define DEBUG_CHECK_CHANGE
62 //#define DEBUG_SURROUNDING_VEHICLES // debug getRealFollower() and getRealLeader()
63 //#define DEBUG_CHANGE_OPPOSITE
64 //#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
65 #define DEBUG_COND false
66 
67 
68 
69 // ===========================================================================
70 // ChangeElem member method definitions
71 // ===========================================================================
73  lead(0),
74  lane(_lane),
75  hoppedVeh(0),
76  lastBlocked(0),
77  firstBlocked(0),
78  ahead(lane) {
79 }
80 
81 // ===========================================================================
82 // member method definitions
83 // ===========================================================================
84 MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging) :
85  myAllowsChanging(allowChanging),
86  myChangeToOpposite(lanes->front()->getEdge().canChangeToOpposite()) {
87 
88  // Fill the changer with the lane-data.
89  myChanger.reserve(lanes->size());
90  for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
91  myChanger.push_back(ChangeElem(*lane));
92  }
93 }
94 
95 
97 }
98 
99 
100 void
102  // This is what happens in one timestep. After initialization of the
103  // changer, each vehicle will try to change. After that the changer
104  // needs an update to prevent multiple changes of one vehicle.
105  // Finally, the change-result has to be given back to the lanes.
106  initChanger();
107  try {
108  while (vehInChanger()) {
109  const bool haveChanged = change();
110  updateChanger(haveChanged);
111  }
112  updateLanes(t);
113  } catch (const ProcessError&) {
114  // clean up locks or the gui may hang
115  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
116  ce->lane->releaseVehicles();
117  }
118  throw;
119  }
120 }
121 
122 
123 void
125  // Prepare myChanger with a safe state.
126  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
127  ce->lead = 0;
128  ce->hoppedVeh = 0;
129  ce->lastBlocked = 0;
130  ce->firstBlocked = 0;
131  ce->dens = 0;
132  ce->lane->getVehiclesSecure();
133 
134  //std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
135  }
136 }
137 
138 
139 void
140 MSLaneChanger::updateChanger(bool vehHasChanged) {
141  assert(veh(myCandi) != 0);
142 
143  // "Push" the vehicles to the back, i.e. follower becomes vehicle,
144  // vehicle becomes leader, and leader becomes predecessor of vehicle,
145  // if it exists.
146  if (!vehHasChanged || MSGlobals::gLaneChangeDuration > DELTA_T) {
147  //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " has new lead=" << veh(myCandi)->getID() << "\n";
148  myCandi->lead = veh(myCandi);
149  }
150 
151  MSLane::VehCont& vehicles = myCandi->lane->myVehicles;
152  vehicles.pop_back();
153  //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " vehicles=" << toString(myCandi->lane->myVehicles) << "\n";
154 }
155 
156 
157 void
159 
160  // Update the lane's vehicle-container.
161  // First: it is bad style to change other classes members, but for
162  // this release, other attempts were too time-consuming. In a next
163  // release we will change from this lane-centered design to a vehicle-
164  // centered. This will solve many problems.
165  // Second: this swap would be faster if vehicle-containers would have
166  // been pointers, but then I had to change too much of the MSLane code.
167  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
168  //std::cout << SIMTIME << " updateLanes lane=" << ce->lane->getID() << " myVehicles=" << toString(ce->lane->myVehicles) << " myTmpVehicles=" << toString(ce->lane->myTmpVehicles) << "\n";
169  ce->lane->swapAfterLaneChange(t);
170  ce->lane->releaseVehicles();
171  }
172 }
173 
174 
177  // Find the vehicle in myChanger with the largest position. If there
178  // is no vehicle in myChanger (shouldn't happen) , return myChanger.end().
179  ChangerIt max = myChanger.end();
180  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
181  if (veh(ce) == 0) {
182  continue;
183  }
184  if (max == myChanger.end()) {
185  //std::cout << SIMTIME << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
186  max = ce;
187  continue;
188  }
189  assert(veh(ce) != 0);
190  assert(veh(max) != 0);
191  if (veh(max)->getPositionOnLane() < veh(ce)->getPositionOnLane()) {
192  //std::cout << SIMTIME << " 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";
193  max = ce;
194  }
195  }
196  assert(max != myChanger.end());
197  assert(veh(max) != 0);
198  return max;
199 }
200 
201 
202 bool
203 MSLaneChanger::mayChange(int direction) const {
204  if (direction == 0) {
205  return true;
206  }
207  if (!myAllowsChanging) {
208  return false;
209  }
210  if (direction == -1) {
211  return (myCandi != myChanger.begin() && (myCandi - 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass()));
212  } else if (direction == 1) {
213  return (myCandi + 1) != myChanger.end() && (myCandi + 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass());
214  } else {
215  return false;
216  }
217 }
218 
219 
220 bool
222  // Find change-candidate. If it is on an allowed lane, try to change
223  // to the right (there is a rule in Germany that you have to change
224  // to the right, unless you are overtaking). If change to the right
225  // isn't possible, check if there is a possibility to overtake (on the
226  // left.
227  // If candidate isn't on an allowed lane, changing to an allowed has
228  // priority.
230  MSVehicle* vehicle = veh(myCandi);
231 
232 #ifdef DEBUG_VEHICLE_GUI_SELECTION
233  if (gDebugSelectedVehicle == vehicle->getID()) {
234  int bla = 0;
235  }
236 #endif
237  if (vehicle->getLaneChangeModel().isChangingLanes()) {
238  return continueChange(vehicle, myCandi);
239  }
240  if (!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
241  registerUnchanged(vehicle);
242  return false;
243  }
244  std::pair<MSVehicle* const, double> leader = getRealLeader(myCandi);
245  if (myChanger.size() == 1 || vehicle->getLaneChangeModel().isOpposite()) {
246  if (changeOpposite(leader)) {
247  return true;
248  }
249  registerUnchanged(vehicle);
250  return false;
251  }
252 
253 #ifndef NO_TRACI
254  if (vehicle->isRemoteControlled()) {
255  registerUnchanged(vehicle);
256  return false;
257  }
258 #endif
259  vehicle->updateBestLanes(); // needed?
260  for (int i = 0; i < (int) myChanger.size(); ++i) {
261  vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
262  }
263  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
264  // check whether the vehicle wants and is able to change to right lane
265  int stateRight = 0;
266  if (mayChange(-1)) {
267  stateRight = checkChangeWithinEdge(-1, leader, preb);
268  // change if the vehicle wants to and is allowed to change
269  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_BLOCKED) == 0) {
270  vehicle->getLaneChangeModel().setOwnState(stateRight);
271  startChange(vehicle, myCandi, -1);
272  return true;
273  }
274  if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_URGENT) != 0) {
275  (myCandi - 1)->lastBlocked = vehicle;
276  if ((myCandi - 1)->firstBlocked == 0) {
277  (myCandi - 1)->firstBlocked = vehicle;
278  }
279  }
280  }
281 
282  // check whether the vehicle wants and is able to change to left lane
283  int stateLeft = 0;
284  if (mayChange(1)) {
285  stateLeft = checkChangeWithinEdge(1, leader, preb);
286  // change if the vehicle wants to and is allowed to change
287  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_BLOCKED) == 0) {
288  vehicle->getLaneChangeModel().setOwnState(stateLeft);
289  startChange(vehicle, myCandi, 1);
290  return true;
291  }
292  if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_URGENT) != 0) {
293  (myCandi + 1)->lastBlocked = vehicle;
294  if ((myCandi + 1)->firstBlocked == 0) {
295  (myCandi + 1)->firstBlocked = vehicle;
296  }
297  }
298  }
299 
300  if ((stateRight & LCA_URGENT) != 0 && (stateLeft & LCA_URGENT) != 0) {
301  // ... wants to go to the left AND to the right
302  // just let them go to the right lane...
303  stateLeft = 0;
304  }
305  vehicle->getLaneChangeModel().setOwnState(stateRight | stateLeft);
306 
307  // only emergency vehicles should change to the opposite side on a
308  // multi-lane road
309  if (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
310  && changeOpposite(leader)) {
311  return true;
312  }
313  registerUnchanged(vehicle);
314  return false;
315 }
316 
317 
318 void
320  myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
321  myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
322  vehicle->getLaneChangeModel().unchanged();
323 }
324 
325 
326 void
327 MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
328  ChangerIt to = from + direction;
329  // @todo delay entering the target lane until the vehicle intersects it
330  // physically (considering lane width and vehicle width)
331  //if (to->lane->getID() == "beg_1") std::cout << SIMTIME << " startChange to lane=" << to->lane->getID() << " myTmpVehiclesBefore=" << toString(to->lane->myTmpVehicles) << "\n";
332  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
333  if (continuous) {
334  continueChange(vehicle, myCandi);
335  } else {
336  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
337  to->dens += vehicle->getVehicleType().getLengthWithGap();
338  to->hoppedVeh = vehicle;
339  }
340 }
341 
342 
343 bool
346  const int direction = lcm.getLaneChangeDirection();
347  const bool pastMidpoint = lcm.updateCompletion();
348  vehicle->myState.myPosLat += lcm.getSpeedLat();
350  if (pastMidpoint) {
351  ChangerIt to = from + direction;
352  MSLane* source = myCandi->lane;
353  MSLane* target = to->lane;
354  vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
355  lcm.primaryLaneChanged(source, target, direction);
356  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
357  to->dens += vehicle->getVehicleType().getLengthWithGap();
358  to->hoppedVeh = vehicle;
359  } else {
360  from->lane->myTmpVehicles.insert(from->lane->myTmpVehicles.begin(), vehicle);
361  from->dens += vehicle->getVehicleType().getLengthWithGap();
362  from->hoppedVeh = vehicle;
363  }
364  if (!lcm.isChangingLanes()) {
365  vehicle->myState.myPosLat = 0;
366  lcm.endLaneChangeManeuver();
367  }
368  lcm.updateShadowLane();
369  if (lcm.getShadowLane() != 0) {
370  // set as hoppedVeh on the shadow lane so it is found as leader on both lanes
371  ChangerIt shadow = pastMidpoint ? from : from + lcm.getShadowDirection();
372  shadow->hoppedVeh = vehicle;
373  }
374  vehicle->myAngle = vehicle->computeAngle();
375 
376 #ifdef DEBUG_CONTINUE_CHANGE
377  if (DEBUG_COND) {
378  std::cout << SIMTIME
379  << " continueChange veh=" << vehicle->getID()
380  << " from=" << Named::getIDSecure(from->lane)
381  << " dir=" << direction
382  << " pastMidpoint=" << pastMidpoint
383  << " posLat=" << vehicle->getLateralPositionOnLane()
384  //<< " completion=" << lcm.getLaneChangeCompletion()
385  << " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
386  << " shadowHopped=" << Named::getIDSecure(shadow->lane)
387  << "\n";
388  }
389 #endif
390  return pastMidpoint;
391 }
392 
393 
394 std::pair<MSVehicle* const, double>
396  assert(veh(myCandi) != 0);
397 
398 #ifdef DEBUG_SURROUNDING_VEHICLES
399  MSVehicle* vehicle = veh(myCandi);
400  if (DEBUG_COND) {
401  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl;
402  }
403 #endif
404  // get the leading vehicle on the lane to change to
405  MSVehicle* neighLead = target->lead;
406 
407 #ifdef DEBUG_SURROUNDING_VEHICLES
408  if (DEBUG_COND) {
409  if (neighLead != 0) {
410  std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl;
411  }
412  }
413 #endif
414 
415  //if (veh(myCandi)->getID() == "disabled") std::cout << SIMTIME
416  // << " target=" << target->lane->getID()
417  // << " neighLead=" << Named::getIDSecure(neighLead)
418  // << " hopped=" << Named::getIDSecure(target->hoppedVeh)
419  // << " (416)\n";
420  // check whether the hopped vehicle became the leader
421  if (target->hoppedVeh != 0) {
422  double hoppedPos = target->hoppedVeh->getPositionOnLane();
423 #ifdef DEBUG_SURROUNDING_VEHICLES
424  if (DEBUG_COND) {
425  std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl;
426  }
427 #endif
428  if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) {
429  neighLead = target->hoppedVeh;
430  //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n";
431  }
432  }
433  if (neighLead == 0) {
434 #ifdef DEBUG_SURROUNDING_VEHICLES
435  if (DEBUG_COND) {
436  std::cout << "Looking for leader on consecutive lanes." << std::endl;
437  }
438 #endif
439  // There's no leader on the target lane. Look for leaders on consecutive lanes.
440  MSLane* targetLane = target->lane;
441  if (targetLane->myPartialVehicles.size() > 0) {
442  assert(targetLane->myPartialVehicles.size() > 0);
443  std::vector<MSVehicle*>::const_iterator i = targetLane->myPartialVehicles.begin();
444  MSVehicle* leader = *i;
445  double leaderPos = leader->getBackPositionOnLane(targetLane);
446  while (++i != targetLane->myPartialVehicles.end()) {
447  if ((*i)->getBackPositionOnLane(targetLane) < leader->getBackPositionOnLane(targetLane)) {
448  leader = *i;
449  leaderPos = leader->getBackPositionOnLane(targetLane);
450  }
451  }
452  return std::pair<MSVehicle*, double>(leader, leaderPos - veh(myCandi)->getPositionOnLane() - veh(myCandi)->getVehicleType().getMinGap());
453  }
454  double seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane();
455  double speed = veh(myCandi)->getSpeed();
456  double dist = veh(myCandi)->getCarFollowModel().brakeGap(speed) + veh(myCandi)->getVehicleType().getMinGap();
457  if (seen > dist) {
458  return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(0), -1);
459  }
460  const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane);
461  return target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts);
462  } else {
463  MSVehicle* candi = veh(myCandi);
464  return std::pair<MSVehicle* const, double>(neighLead, neighLead->getBackPositionOnLane(target->lane) - candi->getPositionOnLane() - candi->getVehicleType().getMinGap());
465  }
466 }
467 
468 
469 std::pair<MSVehicle* const, double>
471  assert(veh(myCandi) != 0);
472 
473 #ifdef DEBUG_SURROUNDING_VEHICLES
474  MSVehicle* vehicle = veh(myCandi);
475  if (DEBUG_COND) {
476  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl;
477  }
478 #endif
479  MSVehicle* candi = veh(myCandi);
480  const double candiPos = candi->getPositionOnLane();
481  MSVehicle* neighFollow = veh(target);
482 
483 #ifdef DEBUG_SURROUNDING_VEHICLES
484  if (DEBUG_COND) {
485  if (neighFollow != 0) {
486  std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl;
487  } else {
488  std::cout << "veh(target) returns none." << std::endl;
489  }
490  }
491 #endif
492 
493 
494 #ifdef DEBUG_SURROUNDING_VEHICLES
495  if (DEBUG_COND) {
496  if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
497  std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
498  }
499  }
500 #endif
501 
502  // check whether the hopped vehicle became the follower
503  neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
504 
505 
506 #ifdef DEBUG_SURROUNDING_VEHICLES
507  if (DEBUG_COND) {
508  MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
509  if (partialBehind != 0 && partialBehind != neighFollow) {
510  std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(candi)->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
511  }
512  }
513 #endif
514  // or a follower which is partially lapping into the target lane
515  neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
516 
517  if (neighFollow == 0) {
518  CLeaderDist consecutiveFollower = target->lane->getFollowersOnConsecutive(candi, candi->getBackPositionOnLane(), true)[0];
519 #ifdef DEBUG_SURROUNDING_VEHICLES
520  if (DEBUG_COND) {
521  if (consecutiveFollower.first == 0) {
522  std::cout << "no follower found." << std::endl;
523  } else {
524  std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl;
525  }
526  }
527 #endif
528  return std::make_pair(const_cast<MSVehicle*>(consecutiveFollower.first), consecutiveFollower.second);
529  } else {
530 #ifdef DEBUG_SURROUNDING_VEHICLES
531  if (DEBUG_COND) {
532  std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl;
533  }
534 #endif
535  MSVehicle* candi = veh(myCandi);
536  return std::pair<MSVehicle* const, double>(neighFollow,
537  candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
538  }
539 }
540 
541 
542 MSVehicle*
543 MSLaneChanger::getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2) {
544  if (follow1 == 0 || follow1->getPositionOnLane() > maxPos) {
545  return follow2;
546  } else if (follow2 == 0 || follow2->getPositionOnLane() > maxPos) {
547  return follow1;
548  } else {
549  if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
550  return follow1;
551  } else {
552  return follow2;
553  }
554  }
555 }
556 
557 int
559  int laneOffset,
560  const std::pair<MSVehicle* const, double>& leader,
561  const std::vector<MSVehicle::LaneQ>& preb) const {
562 
563  std::pair<MSVehicle* const, double> neighLead = getRealLeader(myCandi + laneOffset);
564  std::pair<MSVehicle*, double> neighFollow = getRealFollower(myCandi + laneOffset);
565  if (neighLead.first != 0 && neighLead.first == neighFollow.first) {
566  // vehicles should not be leader and follower at the same time to avoid
567  // contradictory behavior
568  neighFollow.first = 0;
569  }
570  ChangerIt target = myCandi + laneOffset;
571  return checkChange(laneOffset, target->lane, leader, neighLead, neighFollow, preb);
572 }
573 
574 int
576  int laneOffset,
577  const MSLane* targetLane,
578  const std::pair<MSVehicle* const, double>& leader,
579  const std::pair<MSVehicle* const, double>& neighLead,
580  const std::pair<MSVehicle* const, double>& neighFollow,
581  const std::vector<MSVehicle::LaneQ>& preb) const {
582 
583  MSVehicle* vehicle = veh(myCandi);
584 
585  // Debug (Leo)
586 #ifdef DEBUG_CHECK_CHANGE
587  if (DEBUG_COND) {
588  std::cout
589  << "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'"
590  << std::endl;
591  }
592 #endif
593 
594 
595  int blocked = 0;
596  int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
597  int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
598  // overlap
599  if (neighFollow.first != 0 && neighFollow.second < 0) {
600  blocked |= (blockedByFollower | LCA_OVERLAPPING);
601 
602  // Debug (Leo)
603 #ifdef DEBUG_CHECK_CHANGE
604  if (DEBUG_COND) {
605  std::cout << SIMTIME
606  << " overlapping with follower..."
607  << std::endl;
608  }
609 #endif
610 
611  }
612  if (neighLead.first != 0 && neighLead.second < 0) {
613  blocked |= (blockedByLeader | LCA_OVERLAPPING);
614 
615  // Debug (Leo)
616 #ifdef DEBUG_CHECK_CHANGE
617  if (DEBUG_COND) {
618  std::cout << SIMTIME
619  << " overlapping with leader..."
620  << std::endl;
621  }
622 #endif
623 
624  }
625 
626  double secureFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
627  double secureBackGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
628  // safe back gap
629  if ((blocked & blockedByFollower) == 0 && neighFollow.first != 0) {
630  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
631  secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel());
632  if (neighFollow.second < secureBackGap) {
633  blocked |= blockedByFollower;
634 
635  // Debug (Leo)
636 #ifdef DEBUG_CHECK_CHANGE
637  if (DEBUG_COND) {
638  std::cout << SIMTIME
639  << " back gap unsafe: "
640  << "gap = " << neighFollow.second
641  << ", secureGap = "
642  << neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first->getSpeed(),
643  vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel())
644  << std::endl;
645  }
646 #endif
647 
648  }
649  }
650 
651  // safe front gap
652  if ((blocked & blockedByLeader) == 0 && neighLead.first != 0) {
653  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
654  secureFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel());
655  if (neighLead.second < secureFrontGap) {
656  blocked |= blockedByLeader;
657 
658  // Debug (Leo)
659 #ifdef DEBUG_CHECK_CHANGE
660  if (DEBUG_COND) {
661  std::cout << SIMTIME
662  << " front gap unsafe: "
663  << "gap = " << neighLead.second
664  << ", secureGap = "
665  << vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(),
666  neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())
667  << std::endl;
668  }
669 #endif
670 
671  }
672  }
673 
674 
675  MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
676  int state = blocked | vehicle->getLaneChangeModel().wantsChange(
677  laneOffset, msg, blocked, leader, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
678 
679  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != 0) {
680  // do are more carefull (but expensive) check to ensure that a
681  // safety-critical leader is not being overloocked
682  const double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
683  const double speed = vehicle->getSpeed();
684  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
685  if (seen < dist) {
686  std::pair<MSVehicle* const, double> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
687  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
688  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
689  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
690  state |= blockedByLeader;
691  }
692  }
693  }
694  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
695  // ensure that merging is safe for any upcoming zipper links after changing
696  if (vehicle->unsafeLinkAhead(targetLane)) {
697  state |= blockedByLeader;
698  }
699  }
700 
701  if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
702  // ensure that a continuous lane change manoeuvre can be completed
703  // before the next turning movement
704  double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
705  const double decel = vehicle->getCarFollowModel().getMaxDecel() * STEPS2TIME(MSGlobals::gLaneChangeDuration);
706  const double avgSpeed = 0.5 * (
707  MAX2(0., vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
708  MAX2(0., vehicle->getSpeed() - decel));
709  const double space2change = avgSpeed * STEPS2TIME(MSGlobals::gLaneChangeDuration);
710  // for finding turns it doesn't matter whether we look along the current lane or the target lane
711  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
712  int view = 1;
713  MSLane* nextLane = vehicle->getLane();
714  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
715  while (!nextLane->isLinkEnd(link) && seen <= space2change) {
716  if ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT
717  // the lanes after an internal junction are on different
718  // edges and do not allow lane-changing
719  || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
720  ) {
721  state |= LCA_INSUFFICIENT_SPACE;
722  break;
723  }
724  if ((*link)->getViaLane() == 0) {
725  view++;
726  }
727  nextLane = (*link)->getViaLaneOrLane();
728  seen += nextLane->getLength();
729  // get the next link used
730  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
731  }
732  if (nextLane->isLinkEnd(link) && seen < space2change) {
733 #ifdef DEBUG_CHECK_CHANGE
734  if (DEBUG_COND) {
735  std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
736  }
737 #endif
738  state |= LCA_INSUFFICIENT_SPACE;
739  }
740 
741  if ((state & LCA_BLOCKED) == 0) {
742  // check for dangerous leaders in case the target lane changes laterally between
743  // now and the lane-changing midpoint
744  const double speed = vehicle->getSpeed();
745  seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
746  nextLane = vehicle->getLane();
747  view = 1;
748  const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
749  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
750  while (!nextLane->isLinkEnd(link) && seen <= space2change && seen <= dist) {
751  nextLane = (*link)->getViaLaneOrLane();
752  MSLane* targetLane = nextLane->getParallelLane(laneOffset);
753  if (targetLane == 0) {
754  state |= LCA_INSUFFICIENT_SPACE;
755  break;
756  } else {
757  std::pair<MSVehicle* const, double> neighLead2 = targetLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
758  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
759  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
760  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
761  state |= blockedByLeader;
762  break;
763  }
764  }
765  if ((*link)->getViaLane() == 0) {
766  view++;
767  }
768  seen += nextLane->getLength();
769  // get the next link used
770  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
771  }
772  }
773  }
774  const int oldstate = state;
775 #ifndef NO_TRACI
776  // let TraCI influence the wish to change lanes and the security to take
777  state = vehicle->influenceChangeDecision(state);
778 #endif
779 #ifdef DEBUG_CHECK_CHANGE
780  if (DEBUG_COND) {
781  std::cout << SIMTIME
782  << " veh=" << vehicle->getID()
783  << " oldState=" << toString((LaneChangeAction)oldstate)
784  << " newState=" << toString((LaneChangeAction)state)
785  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
786  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
787  << "\n";
788  }
789 #endif
790  vehicle->getLaneChangeModel().saveState(laneOffset, oldstate, state);
791  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
792  // this lane change will be executed, save gaps
793  vehicle->getLaneChangeModel().setFollowerGaps(neighFollow, secureBackGap);
794  vehicle->getLaneChangeModel().setLeaderGaps(neighLead, secureFrontGap);
795  }
796  return state;
797 }
798 
799 
800 bool
801 MSLaneChanger::changeOpposite(std::pair<MSVehicle*, double> leader) {
802  if (!myChangeToOpposite) {
803  return false;
804  }
806  MSVehicle* vehicle = veh(myCandi);
807  MSLane* source = vehicle->getLane();
808  if (vehicle->isStopped()) {
809  // stopped vehicles obviously should not change lanes. Usually this is
810  // prevent by appropriate bestLane distances
811  return false;
812  }
813  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
814  if (!isOpposite && leader.first == 0) {
815  // no reason to change unless there is a leader
816  // or we are changing back to the propper direction
817  // XXX also check whether the leader is so far away as to be irrelevant
818  return false;
819  }
820  MSLane* opposite = source->getOpposite();
821  if (opposite == 0) {
822  return false;
823  }
824 
825  // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
826  int direction = isOpposite ? -1 : 1;
827  std::pair<MSVehicle*, double> neighLead((MSVehicle*)0, -1);
828 
829  // preliminary sanity checks for overtaking space
830  double timeToOvertake;
831  double spaceToOvertake;
832  if (!isOpposite) {
833  assert(leader.first != 0);
834  // find a leader vehicle with sufficient space ahead for merging back
835  const double overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
836  const double mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
837  std::pair<MSVehicle*, double> columnLeader = leader;
838  double egoGap = leader.second;
839  bool foundSpaceAhead = false;
840  double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
841  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
842  while (!foundSpaceAhead) {
843  const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
844  columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
845  + vehicle->getVehicleType().getLengthWithGap());
846 
847 
848  // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
849  const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge());
850  std::pair<MSVehicle* const, double> leadLead = columnLeader.first->getLane()->getLeader(
851  columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap,
852  checkTmpVehicles);
853 
854 #ifdef DEBUG_CHANGE_OPPOSITE
855  if (DEBUG_COND) {
856  std::cout << " leadLead=" << Named::getIDSecure(leadLead.first) << " gap=" << leadLead.second << "\n";
857  }
858 #endif
859  if (leadLead.first == 0) {
860  foundSpaceAhead = true;
861  } else {
862  const double maxLookAhead = (vehicle->getVehicleType().getVehicleClass() == SVC_EMERGENCY
865  const double requiredSpace = (requiredSpaceAfterLeader
866  + vehicle->getCarFollowModel().getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel()));
867  if (leadLead.second > requiredSpace) {
868  foundSpaceAhead = true;
869  } else {
870 #ifdef DEBUG_CHANGE_OPPOSITE
871  if (DEBUG_COND) {
872  std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n";
873  }
874 #endif
875  seen += MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
876  if (seen > maxLookAhead) {
877 #ifdef DEBUG_CHANGE_OPPOSITE
878  if (DEBUG_COND) {
879  std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n";
880  }
881 #endif
882  return false;
883  }
884  // see if merging after leadLead is possible
885  egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
886  columnLeader = leadLead;
887 #ifdef DEBUG_CHANGE_OPPOSITE
888  if (DEBUG_COND) {
889  std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
890  }
891 #endif
892  }
893  }
894  }
895 #ifdef DEBUG_CHANGE_OPPOSITE
896  if (DEBUG_COND) {
897  std::cout << " compute time/space to overtake for columnLeader=" << columnLeader.first->getID() << " gap=" << columnLeader.second << "\n";
898  }
899 #endif
900  computeOvertakingTime(vehicle, columnLeader.first, egoGap, timeToOvertake, spaceToOvertake);
901  // check for upcoming stops
902  if (vehicle->nextStopDist() < spaceToOvertake) {
903 #ifdef DEBUG_CHANGE_OPPOSITE
904  if (DEBUG_COND) {
905  std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
906  }
907 #endif
908  return false;
909  }
910  neighLead = opposite->getOppositeLeader(vehicle, timeToOvertake * opposite->getSpeedLimit() * 2 + spaceToOvertake, true);
911 
912 #ifdef DEBUG_CHANGE_OPPOSITE
913  if (DEBUG_COND) {
914  std::cout << SIMTIME
915  << " veh=" << vehicle->getID()
916  << " changeOpposite opposite=" << opposite->getID()
917  << " lead=" << Named::getIDSecure(leader.first)
918  << " timeToOvertake=" << timeToOvertake
919  << " spaceToOvertake=" << spaceToOvertake
920  << "\n";
921  }
922 #endif
923 
924  // check for dangerous oncoming leader
925  if (neighLead.first != 0) {
926  const MSVehicle* oncoming = neighLead.first;
927 
928 #ifdef DEBUG_CHANGE_OPPOSITE
929  if (DEBUG_COND) {
930  std::cout << SIMTIME
931  << " oncoming=" << oncoming->getID()
932  << " oncomingGap=" << neighLead.second
933  << " leaderGap=" << leader.second
934  << "\n";
935  }
936 #endif
937  if (neighLead.second - spaceToOvertake - timeToOvertake * oncoming->getSpeed() < 0) {
938 
939 #ifdef DEBUG_CHANGE_OPPOSITE
940  if (DEBUG_COND) {
941  std::cout << " cannot changeOpposite due to dangerous oncoming\n";
942  }
943 #endif
944  return false;
945  }
946  }
947  } else {
948  timeToOvertake = -1;
949  // look forward as far as possible
950  spaceToOvertake = std::numeric_limits<double>::max();
951  leader = source->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true);
952  // -1 will use getMaximumBrakeDist() as look-ahead distance
953  neighLead = opposite->getOppositeLeader(vehicle, -1, false);
954  }
955 
956  // compute remaining space on the opposite side
957  // 1. the part that remains on the current lane
958  double usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane();
959  if (usableDist < spaceToOvertake) {
960  // look forward along the next lanes
961  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
962  assert(bestLaneConts.size() >= 1);
963  std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
964  while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
965 #ifdef DEBUG_CHANGE_OPPOSITE
966  if (DEBUG_COND) {
967  std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n";
968  }
969 #endif
970  if ((*it)->getOpposite() == 0) {
971  // opposite lane ends
972  break;
973  }
974  // do not overtake past a minor link or turn
975  if (*(it - 1) != 0) {
976  MSLink* link = MSLinkContHelper::getConnectingLink(**(it - 1), **it);
977  if (link == 0 || link->getState() == LINKSTATE_ZIPPER
979  || (!link->havePriority()
980  // consider traci-influence
981  && (!vehicle->hasInfluencer() || vehicle->getInfluencer().getRespectJunctionPriority())
982  // consider junction model parameters
983  && ((!link->haveRed() && !link->haveYellow()) || !vehicle->ignoreRed(link, true)))) {
984 #ifdef DEBUG_CHANGE_OPPOSITE
985  if (DEBUG_COND) {
986  std::cout << " stop lookahead at link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID()) << " state=" << (link == 0 ? "?" : toString(link->getState())) << " ignoreRed=" << vehicle->ignoreRed(link, true) << "\n";
987  }
988 #endif
989  break;
990  }
991  }
992  usableDist += (*it)->getLength();
993  ++it;
994  }
995  }
996  if (!isOpposite && usableDist < spaceToOvertake) {
997 #ifdef DEBUG_CHANGE_OPPOSITE
998  if (DEBUG_COND) {
999  std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n";
1000  }
1001 #endif
1002  return false;
1003  }
1004 #ifdef DEBUG_CHANGE_OPPOSITE
1005  if (DEBUG_COND) {
1006  std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
1007  }
1008 #endif
1009 
1010  // compute wish to change
1011  std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
1012  if (isOpposite) {
1013  // compute the remaining distance that can be drive on the opposite side
1014  // this value will put into LaneQ.length of the leftmost lane
1015  // @note: length counts from the start of the current lane
1016  // @note: see MSLCM_LC2013::_wantsChange @1092 (isOpposite()
1017  MSVehicle::LaneQ& laneQ = preb[preb.size() - 1];
1018  // position on the target lane
1019  const double forwardPos = source->getOppositePos(vehicle->getPositionOnLane());
1020 
1021  // consider usableDist (due to minor links or end of opposite lanes)
1022  laneQ.length = MIN2(laneQ.length, usableDist + forwardPos);
1023  // consider upcoming stops
1024  laneQ.length = MIN2(laneQ.length, vehicle->nextStopDist() + forwardPos);
1025  // consider oncoming leaders
1026  if (leader.first != 0) {
1027  laneQ.length = MIN2(laneQ.length, leader.second / 2 + forwardPos);
1028 #ifdef DEBUG_CHANGE_OPPOSITE
1029  if (DEBUG_COND) {
1030  std::cout << SIMTIME << " found oncoming leader=" << leader.first->getID() << " gap=" << leader.second << "\n";
1031  }
1032 #endif
1033  leader.first = 0; // ignore leader after this
1034  }
1035 #ifdef DEBUG_CHANGE_OPPOSITE
1036  if (DEBUG_COND) {
1037  std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << laneQ.length - forwardPos << " forwardPos=" << forwardPos << " laneQ.length=" << laneQ.length << "\n";
1038  }
1039 #endif
1040  }
1041  std::pair<MSVehicle* const, double> neighFollow = opposite->getOppositeFollower(vehicle);
1042  int state = checkChange(direction, opposite, leader, neighLead, neighFollow, preb);
1043 
1044  bool changingAllowed = (state & LCA_BLOCKED) == 0;
1045  // change if the vehicle wants to and is allowed to change
1046  if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed
1047  // do not change to the opposite direction for cooperative reasons
1048  && (isOpposite || (state & LCA_COOPERATIVE) == 0)) {
1049  vehicle->getLaneChangeModel().startLaneChangeManeuver(source, opposite, direction);
1051  vehicle->myState.myPos = source->getOppositePos(vehicle->myState.myPos);
1054  if (!isOpposite) {
1055  vehicle->myState.myBackPos = source->getOppositePos(vehicle->myState.myBackPos);
1056  }
1057 #ifdef DEBUG_CHANGE_OPPOSITE
1058  if (DEBUG_COND) {
1059  std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n";
1060  }
1061 #endif
1062  return true;
1063  }
1064 #ifdef DEBUG_CHANGE_OPPOSITE
1065  if (DEBUG_COND) {
1066  std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << direction
1067  << " opposite=" << Named::getIDSecure(opposite) << " state=" << toString((LaneChangeAction)state) << "\n";
1068  }
1069 #endif
1070  return false;
1071 }
1072 
1073 
1074 void
1075 MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake) {
1076  // Assumptions:
1077  // - leader maintains the current speed
1078  // - vehicle merges with maxSpeed ahead of leader
1079  // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
1080 
1081  // first compute these values for the case where vehicle is accelerating
1082  // without upper bound on speed
1083  const double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1084  const double v = vehicle->getSpeed();
1085  const double u = leader->getSpeed();
1086  const double a = vehicle->getCarFollowModel().getMaxAccel();
1087  const double d = vehicle->getCarFollowModel().getMaxDecel();
1088  const double g = (
1089  // drive up to the rear of leader
1090  gap + vehicle->getVehicleType().getMinGap()
1091  // drive head-to-head with the leader
1092  + leader->getVehicleType().getLengthWithGap()
1093  // drive past the leader
1094  + vehicle->getVehicleType().getLength()
1095  // allow for safe gap between leader and vehicle
1096  + leader->getCarFollowModel().getSecureGap(v, vMax, d));
1097  const double sign = -1; // XXX recheck
1098  // v*t + t*t*a*0.5 = g + u*t
1099  // solve t
1100  // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
1101  double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
1102 
1103  // allow for a safety time gap
1105  // round to multiples of step length (TS)
1106  t = ceil(t / TS) * TS;
1107 
1109  const double timeToMaxSpeed = (vMax - v) / a;
1110 
1111  if (t <= timeToMaxSpeed) {
1112  timeToOvertake = t;
1113  spaceToOvertake = v * t + t * t * a * 0.5;
1114  //if (gDebugFlag1) std::cout << " t below " << timeToMaxSpeed << " vMax=" << vMax << "\n";
1115  } else {
1116  // space until max speed is reached
1117  const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
1118  const double m = timeToMaxSpeed;
1119  // s + (t-m) * vMax = g + u*t
1120  // solve t
1121  t = (g - s + m * vMax) / (vMax - u);
1122 
1123  // allow for a safety time gap
1125  // round to multiples of step length (TS)
1126  t = ceil(t / TS) * TS;
1127 
1128  timeToOvertake = t;
1129  spaceToOvertake = s + (t - m) * vMax;
1130  //if (gDebugFlag1) std::cout << " s=" << s << " m=" << m << " vMax=" << vMax << "\n";
1131  }
1132 }
1133 
1134 /****************************************************************************/
1135 
double myPos
the stored position
Definition: MSVehicle.h:140
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge&#39;e lanes.
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:4267
double getMinGap() const
Get the free space in front of vehicles of this class.
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:476
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:582
double myAngle
the angle in radians (
Definition: MSVehicle.h:1591
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:500
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
bool isLinkEnd(MSLinkCont::const_iterator &i) const
Definition: MSLane.cpp:1663
static MSLinkCont::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition: MSLane.cpp:1730
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
The action is done to help someone else.
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:1947
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:796
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1535
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir) const
Definition: MSLane.cpp:2957
bool hasInfluencer() const
Definition: MSVehicle.h:1451
void setLeaderGaps(CLeaderDist, double secGap)
The vehicle is blocked by left follower.
MSLane * getOpposite() const
return the opposite direction lane for lane changing or 0
Definition: MSLane.cpp:2917
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1245
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links ...
Definition: MSVehicle.cpp:3929
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.
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:305
virtual bool changeOpposite(std::pair< MSVehicle *, double > leader)
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
const bool myAllowsChanging
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
double myPosLat
the stored lateral position
Definition: MSVehicle.h:146
int getShadowDirection() const
return the direction in which the current shadow lane lies
Wants go to the right.
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
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:2098
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:484
T MAX2(T a, T b)
Definition: StdDefs.h:74
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
MSVehicle * veh(ConstChangerIt ce) const
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:59
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:375
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:3541
void startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
start the lane change maneuver (and finish it instantly if gLaneChangeDuration == 0) ...
#define TS
Definition: SUMOTime.h:52
double computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:935
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:717
VehCont myPartialVehicles
The lane&#39;s partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1139
Wants go to the left.
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.
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:3144
#define SIMTIME
Definition: SUMOTime.h:70
std::string gDebugSelectedVehicle
Definition: StdDefs.cpp:37
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:2926
void saveState(const int dir, const int stateWithoutTraCI, const int state)
The link is a straight direction.
void setFollowerGaps(CLeaderDist follower, double secGap)
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
A class responsible for exchanging messages between cars involved in lane-change interaction.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
virtual bool change()
The vehicle changes lanes (micro only)
#define max(a, b)
Definition: polyfonts.c:65
virtual void updateChanger(bool vehHasChanged)
blocked in all directions
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
The action is urgent (to be defined by lc-model)
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:212
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:3502
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:3162
#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:1599
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:1867
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1240
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected.
Definition: MSVehicle.h:1311
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:911
T MIN2(T a, T b)
Definition: StdDefs.h:68
The link is a (hard) right direction.
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:713
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:2617
MSLane * getShadowLane() const
Returns the lane the vehicles shadow is on during continuous/sublane lane change. ...
MSLaneChanger()
Default constructor.
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:230
void updateLanes(SUMOTime t)
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:3156
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition: MSVehicle.h:924
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:91
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD
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
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP
double getLength() const
Get vehicle&#39;s length [m].
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:42
double getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:204
#define sign(a)
Definition: polyfonts.c:68
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:4223
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
virtual void setOwnState(const int state)
virtual ~MSLaneChanger()
Destructor.
The vehicle is blocked being overlapping.
#define DEBUG_COND
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition: MSLane.cpp:2980
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:407
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:462
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
void registerUnchanged(MSVehicle *vehicle)
The vehicle does not have enough space to complete a continuous lane and change before the next turni...
long long int SUMOTime
Definition: TraCIDefs.h:52
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
The vehicle is blocked by right leader.
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:499
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:4247
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one...
public emergency vehicles
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:89
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
double myBackPos
the stored back position
Definition: MSVehicle.h:151
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
The vehicle is blocked by right follower.
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:290
Interface for lane-change models.
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
ChangerIt myCandi
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:278
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
const std::string & getID() const
Returns the name of the vehicle.
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:443
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignore
Definition: MSVehicle.cpp:4346