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