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-2016 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 #ifdef CHECK_MEMORY_LEAKS
49 #include <foreign/nvwa/debug_new.h>
50 #endif // CHECK_MEMORY_LEAKS
51 
52 
53 // ===========================================================================
54 // debug defines
55 // ===========================================================================
56 //#define DEBUG_VEHICLE_GUI_SELECTION
57 
58 //#define DEBUG_CONTINUE_CHANGE
59 //#define DEBUG_CHECK_CHANGE
60 //#define DEBUG_CHANGE_OPPOSITE
61 //#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
62 #define DEBUG_COND false
63 
64 
65 
66 // ===========================================================================
67 // ChangeElem member method definitions
68 // ===========================================================================
70  lead(0),
71  lane(_lane),
72  hoppedVeh(0),
73  lastBlocked(0),
74  firstBlocked(0),
75  ahead(lane) {
76 }
77 
78 // ===========================================================================
79 // member method definitions
80 // ===========================================================================
81 MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging, bool allowSwap) :
82  myAllowsSwap(allowSwap),
83  myAllowsChanging(allowChanging),
84  myChangeToOpposite(lanes->front()->getEdge().canChangeToOpposite()) {
85 
86  // Fill the changer with the lane-data.
87  myChanger.reserve(lanes->size());
88  for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
89  myChanger.push_back(ChangeElem(*lane));
90  }
91 }
92 
93 
95 }
96 
97 
98 void
100  // This is what happens in one timestep. After initialization of the
101  // changer, each vehicle will try to change. After that the changer
102  // nedds an update to prevent multiple changes of one vehicle.
103  // Finally, the change-result has to be given back to the lanes.
104  initChanger();
105  try {
106  while (vehInChanger()) {
107  const bool haveChanged = change();
108  updateChanger(haveChanged);
109  }
110  updateLanes(t);
111  } catch (const ProcessError&) {
112  // clean up locks or the gui may hang
113  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
114  ce->lane->releaseVehicles();
115  }
116  throw;
117  }
118 }
119 
120 
121 void
123  // Prepare myChanger with a safe state.
124  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
125  ce->lead = 0;
126  ce->hoppedVeh = 0;
127  ce->lastBlocked = 0;
128  ce->firstBlocked = 0;
129  ce->dens = 0;
130  ce->ahead.clear();
131  ce->lane->getVehiclesSecure();
132 
133  //std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
134 
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 smallest position. If there
178  // is no vehicle in myChanger (shouldn't happen) , return
179  // 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, SUMOReal> leader = getRealLeader(myCandi);
246  if (myChanger.size() == 1) {
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 state1 = 0;
266  if (mayChange(-1)) {
267  state1 = checkChangeWithinEdge(-1, leader, preb);
268  bool changingAllowed1 = (state1 & LCA_BLOCKED) == 0;
269  // change if the vehicle wants to and is allowed to change
270  if ((state1 & LCA_RIGHT) != 0 && changingAllowed1) {
271  vehicle->getLaneChangeModel().setOwnState(state1);
272  startChange(vehicle, myCandi, -1);
273  return true;
274  }
275  if ((state1 & LCA_RIGHT) != 0 && (state1 & LCA_URGENT) != 0) {
276  (myCandi - 1)->lastBlocked = vehicle;
277  if ((myCandi - 1)->firstBlocked == 0) {
278  (myCandi - 1)->firstBlocked = vehicle;
279  }
280  }
281  }
282 
283 
284 
285  // check whether the vehicle wants and is able to change to left lane
286  int state2 = 0;
287  if (mayChange(1)) {
288  state2 = checkChangeWithinEdge(1, leader, preb);
289  bool changingAllowed2 = (state2 & LCA_BLOCKED) == 0;
290  // change if the vehicle wants to and is allowed to change
291  if ((state2 & LCA_LEFT) != 0 && changingAllowed2) {
292  vehicle->getLaneChangeModel().setOwnState(state2);
293  startChange(vehicle, myCandi, 1);
294  return true;
295  }
296  if ((state2 & LCA_LEFT) != 0 && (state2 & LCA_URGENT) != 0) {
297  (myCandi + 1)->lastBlocked = vehicle;
298  if ((myCandi + 1)->firstBlocked == 0) {
299  (myCandi + 1)->firstBlocked = vehicle;
300  }
301  }
302  }
303 
304  if ((state1 & (LCA_URGENT)) != 0 && (state2 & (LCA_URGENT)) != 0) {
305  // ... wants to go to the left AND to the right
306  // just let them go to the right lane...
307  state2 = 0;
308  }
309  vehicle->getLaneChangeModel().setOwnState(state2 | state1);
310 
311  // check whether the vehicles should be swapped
312  if (myAllowsSwap && ((state1 & (LCA_URGENT)) != 0 || (state2 & (LCA_URGENT)) != 0)) {
313  // get the direction ...
314  ChangerIt target;
315  int direction = 0;
316  if ((state1 & (LCA_URGENT)) != 0) {
317  // ... wants to go right
318  target = myCandi - 1;
319  direction = -1;
320  }
321  if ((state2 & (LCA_URGENT)) != 0) {
322  // ... wants to go left
323  target = myCandi + 1;
324  direction = 1;
325  }
326  MSVehicle* prohibitor = target->lead;
327  if (target->hoppedVeh != 0) {
328  SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane();
329  if (prohibitor == 0 || (hoppedPos > vehicle->getPositionOnLane() && prohibitor->getPositionOnLane() > hoppedPos)) {
330  prohibitor = 0;// !!! vehicles should not jump over more than one lanetarget->hoppedVeh;
331  }
332  }
333  if (prohibitor != 0
334  &&
335  ((prohibitor->getLaneChangeModel().getOwnState() & (LCA_URGENT/*|LCA_SPEEDGAIN*/)) != 0
336  &&
337  (prohibitor->getLaneChangeModel().getOwnState() & (LCA_LEFT | LCA_RIGHT))
338  !=
339  (vehicle->getLaneChangeModel().getOwnState() & (LCA_LEFT | LCA_RIGHT))
340  )
341  ) {
342 
343  // check for position and speed
344  if (prohibitor->getVehicleType().getLengthWithGap() == vehicle->getVehicleType().getLengthWithGap()) {
345  // ok, may be swapped
346  // remove vehicle to swap with
347  MSLane::VehCont::iterator i = find(target->lane->myTmpVehicles.begin(), target->lane->myTmpVehicles.end(), prohibitor);
348  if (i != target->lane->myTmpVehicles.end()) {
349  assert(*i == prohibitor);
350  target->lane->myTmpVehicles.erase(i);
351  startChange(vehicle, myCandi, direction);
352  startChange(prohibitor, target, -direction);
353  std::swap(vehicle->myState, prohibitor->myState);
354  myCandi->lead = prohibitor;
355  target->lead = vehicle;
356  return true;
357  }
358  }
359  }
360  }
361  if (!changeOpposite(leader)) {
362  registerUnchanged(vehicle);
363  return false;
364  } else {
365  return true;
366  }
367 }
368 
369 
370 void
372  myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
373  myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
374  vehicle->getLaneChangeModel().unchanged();
375 }
376 
377 
378 void
379 MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
380  ChangerIt to = from + direction;
381  // @todo delay entering the target lane until the vehicle intersects it
382  // physically (considering lane width and vehicle width)
383  //if (to->lane->getID() == "beg_1") std::cout << SIMTIME << " startChange to lane=" << to->lane->getID() << " myTmpVehiclesBefore=" << toString(to->lane->myTmpVehicles) << "\n";
384  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
385  if (continuous) {
386  continueChange(vehicle, myCandi);
387  } else {
388  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
389  to->dens += vehicle->getVehicleType().getLengthWithGap();
390  to->hoppedVeh = vehicle;
391  }
392 }
393 
394 
395 bool
398  const int direction = lcm.getLaneChangeDirection();
399  const bool pastMidpoint = lcm.updateCompletion();
400  vehicle->myState.myPosLat += lcm.getLateralSpeed();
402  ChangerIt shadow;
403  if (pastMidpoint) {
404  ChangerIt to = from + direction;
405  MSLane* source = myCandi->lane;
406  MSLane* target = to->lane;
407  vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
408  lcm.primaryLaneChanged(source, target, direction);
409  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
410  to->dens += vehicle->getVehicleType().getLengthWithGap();
411  to->hoppedVeh = vehicle;
412  shadow = from;
413  } else {
414  from->lane->myTmpVehicles.insert(from->lane->myTmpVehicles.begin(), vehicle);
415  from->dens += vehicle->getVehicleType().getLengthWithGap();
416  from->hoppedVeh = vehicle;
417  shadow = from + lcm.getShadowDirection();
418  }
419  if (!lcm.isChangingLanes()) {
420  vehicle->myState.myPosLat = 0;
421  lcm.endLaneChangeManeuver();
422  }
423  lcm.updateShadowLane();
424  if (lcm.getShadowLane() != 0) {
425  // set as hoppedVeh on the shadow lane so it is found as leader on both lanes
426  shadow->hoppedVeh = vehicle;
427  }
428  vehicle->myAngle = vehicle->computeAngle();
429 
430 #ifdef DEBUG_CONTINUE_CHANGE
431  if (DEBUG_COND) {
432  std::cout << SIMTIME
433  << " continueChange veh=" << vehicle->getID()
434  << " from=" << Named::getIDSecure(from->lane)
435  << " dir=" << direction
436  << " pastMidpoint=" << pastMidpoint
437  << " posLat=" << vehicle->getLateralPositionOnLane()
438  //<< " completion=" << lcm.getLaneChangeCompletion()
439  << " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
440  << " shadowHopped=" << Named::getIDSecure(shadow->lane)
441  << "\n";
442  }
443 #endif
444  return pastMidpoint;
445 }
446 
447 
448 std::pair<MSVehicle* const, SUMOReal>
450  // get the leading vehicle on the lane to change to
451  MSVehicle* neighLead = target->lead;
452  //if (veh(myCandi)->getID() == "disabled") std::cout << SIMTIME
453  // << " target=" << target->lane->getID()
454  // << " neighLead=" << Named::getIDSecure(neighLead)
455  // << " hopped=" << Named::getIDSecure(target->hoppedVeh)
456  // << " (416)\n";
457  // check whether the hopped vehicle became the leader
458  if (target->hoppedVeh != 0) {
459  SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane();
460  if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) {
461  neighLead = target->hoppedVeh;
462  //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n";
463  }
464  }
465  if (neighLead == 0) {
466  MSLane* targetLane = target->lane;
467  if (targetLane->myPartialVehicles.size() > 0) {
468  assert(targetLane->myPartialVehicles.size() == 1);
469  MSVehicle* leader = targetLane->myPartialVehicles.front();
470  return std::pair<MSVehicle*, SUMOReal>(leader, leader->getBackPositionOnLane(targetLane) - veh(myCandi)->getPositionOnLane() - veh(myCandi)->getVehicleType().getMinGap());
471  }
472  SUMOReal seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane();
473  SUMOReal speed = veh(myCandi)->getSpeed();
475  if (seen > dist) {
476  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
477  }
478  const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane);
479  //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " calling getLeaderOnConsecutive (443)\n";
480  return target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts);
481  } else {
482  MSVehicle* candi = veh(myCandi);
483  return std::pair<MSVehicle* const, SUMOReal>(neighLead, neighLead->getBackPositionOnLane(target->lane) - candi->getPositionOnLane() - candi->getVehicleType().getMinGap());
484  }
485 }
486 
487 
488 std::pair<MSVehicle* const, SUMOReal>
490  MSVehicle* candi = veh(myCandi);
491  const SUMOReal candiPos = candi->getPositionOnLane();
492  MSVehicle* neighFollow = veh(target);
493  // check whether the hopped vehicle became the follower
494  neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
495  neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
496  if (neighFollow == 0) {
497  return target->lane->getFollowerOnConsecutive(
498  candi->getPositionOnLane() - candi->getVehicleType().getLength(),
499  candi->getSpeed(), candi->getCarFollowModel().getMaxDecel());
500  } else {
501  MSVehicle* candi = veh(myCandi);
502  return std::pair<MSVehicle* const, SUMOReal>(neighFollow,
503  candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
504  }
505 }
506 
507 
508 MSVehicle*
510  if (follow1 == 0 || follow1->getPositionOnLane() > maxPos) {
511  return follow2;
512  } else if (follow2 == 0 || follow2->getPositionOnLane() > maxPos) {
513  return follow1;
514  } else {
515  if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
516  return follow1;
517  } else {
518  return follow2;
519  }
520  }
521 }
522 
523 int
525  int laneOffset,
526  const std::pair<MSVehicle* const, SUMOReal>& leader,
527  const std::vector<MSVehicle::LaneQ>& preb) const {
528 
529  std::pair<MSVehicle* const, SUMOReal> neighLead = getRealLeader(myCandi + laneOffset);
530  std::pair<MSVehicle*, SUMOReal> neighFollow = getRealFollower(myCandi + laneOffset);
531  if (neighLead.first != 0 && neighLead.first == neighFollow.first) {
532  // vehicles should not be leader and follower at the same time to avoid
533  // contradictory behavior
534  neighFollow.first = 0;
535  }
536  ChangerIt target = myCandi + laneOffset;
537  return checkChange(laneOffset, target->lane, leader, neighLead, neighFollow, preb);
538 }
539 
540 int
542  int laneOffset,
543  const MSLane* targetLane,
544  const std::pair<MSVehicle* const, SUMOReal>& leader,
545  const std::pair<MSVehicle* const, SUMOReal>& neighLead,
546  const std::pair<MSVehicle* const, SUMOReal>& neighFollow,
547  const std::vector<MSVehicle::LaneQ>& preb) const {
548 
549  MSVehicle* vehicle = veh(myCandi);
550  int blocked = 0;
551  int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
552  int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
553  // overlap
554  if (neighFollow.first != 0 && neighFollow.second < 0) {
555  blocked |= (blockedByFollower | LCA_OVERLAPPING);
556  }
557  if (neighLead.first != 0 && neighLead.second < 0) {
558  blocked |= (blockedByLeader | LCA_OVERLAPPING);
559  }
560  // safe back gap
561  if ((blocked & blockedByFollower) == 0 && neighFollow.first != 0) {
562  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
563  if (neighFollow.second < neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel())) {
564  blocked |= blockedByFollower;
565  }
566  }
567 
568  // safe front gap
569  if ((blocked & blockedByLeader) == 0 && neighLead.first != 0) {
570  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
571  if (neighLead.second < vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())) {
572  blocked |= blockedByLeader;
573  }
574  }
575 
576  MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
577  int state = blocked | vehicle->getLaneChangeModel().wantsChange(
578  laneOffset, msg, blocked, leader, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
579 
580  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != 0) {
581  // do are more carefull (but expensive) check to ensure that a
582  // safety-critical leader is not being overloocked
583  const SUMOReal seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
584  const SUMOReal speed = vehicle->getSpeed();
585  const SUMOReal dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
586  if (seen < dist) {
587  std::pair<MSVehicle* const, SUMOReal> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
588  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
589  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
590  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
591  state |= blockedByLeader;
592  }
593  }
594  }
595  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
596  // ensure that merging is safe for any upcoming zipper links after changing
597  if (vehicle->unsafeLinkAhead(targetLane)) {
598  state |= blockedByLeader;
599  }
600  }
601 
602  if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
603  // ensure that a continuous lane change manoeuvre can be completed
604  // before the next turning movement
605  SUMOReal seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
607  const SUMOReal avgSpeed = 0.5 * (
608  MAX2((SUMOReal)0, vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
609  MAX2((SUMOReal)0, vehicle->getSpeed() - decel));
610  const SUMOReal space2change = avgSpeed * STEPS2TIME(MSGlobals::gLaneChangeDuration);
611  // for finding turns it doesn't matter whether we look along the current lane or the target lane
612  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
613  int view = 1;
614  MSLane* nextLane = vehicle->getLane();
615  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
616  while (!nextLane->isLinkEnd(link) && seen <= space2change) {
617  if ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT
618  // the lanes after an internal junction are on different
619  // edges and do not allow lane-changing
620  || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
621  ) {
622  state |= LCA_INSUFFICIENT_SPACE;
623  break;
624  }
625 #ifdef HAVE_INTERNAL_LANES
626  if ((*link)->getViaLane() == 0) {
627  view++;
628  }
629 #else
630  view++;
631 #endif
632  nextLane = (*link)->getViaLaneOrLane();
633  seen += nextLane->getLength();
634  // get the next link used
635  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
636  }
637  if (nextLane->isLinkEnd(link) && seen < space2change) {
638 #ifdef DEBUG_CHECK_CHANGE
639  if (DEBUG_COND) {
640  std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
641  }
642 #endif
643  state |= LCA_INSUFFICIENT_SPACE;
644  }
645 
646  if ((state & LCA_BLOCKED) == 0) {
647  // check for dangerous leaders in case the target lane changes laterally between
648  // now and the lane-changing midpoint
649  const SUMOReal speed = vehicle->getSpeed();
650  seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
651  nextLane = vehicle->getLane();
652  view = 1;
653  const SUMOReal dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
654  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
655  while (!nextLane->isLinkEnd(link) && seen <= space2change && seen <= dist) {
656  nextLane = (*link)->getViaLaneOrLane();
657  MSLane* targetLane = nextLane->getParallelLane(laneOffset);
658  if (targetLane == 0) {
659  state |= LCA_INSUFFICIENT_SPACE;
660  break;
661  } else {
662  std::pair<MSVehicle* const, SUMOReal> neighLead2 = targetLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
663  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
664  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
665  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
666  state |= blockedByLeader;
667  break;
668  }
669  }
670 #ifdef HAVE_INTERNAL_LANES
671  if ((*link)->getViaLane() == 0) {
672  view++;
673  }
674 #else
675  view++;
676 #endif
677  seen += nextLane->getLength();
678  // get the next link used
679  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
680  }
681  }
682  }
683 #ifndef NO_TRACI
684 #ifdef DEBUG_CHECK_CHANGE
685  const int oldstate = state;
686 #endif
687  // let TraCI influence the wish to change lanes and the security to take
688  state = vehicle->influenceChangeDecision(state);
689 #endif
690 #ifdef DEBUG_CHECK_CHANGE
691  if (DEBUG_COND) {
692  std::cout << SIMTIME
693  << " veh=" << vehicle->getID()
694  << " oldState=" << toString((LaneChangeAction)oldstate)
695  << " newState=" << toString((LaneChangeAction)state)
696  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
697  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
698  << "\n";
699  }
700 #endif
701  return state;
702 }
703 
704 
705 bool
706 MSLaneChanger::changeOpposite(std::pair<MSVehicle*, SUMOReal> leader) {
707  if (!myChangeToOpposite) {
708  return false;
709  }
711  MSVehicle* vehicle = veh(myCandi);
712  MSLane* source = vehicle->getLane();
713  if (vehicle->isStopped()) {
714  // stopped vehicles obviously should not change lanes. Usually this is
715  // prevent by appropriate bestLane distances
716  return false;
717  }
718  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
719  if (!isOpposite && leader.first == 0) {
720  // no reason to change unless there is a leader
721  // or we are changing back to the propper direction
722  // XXX also check whether the leader is so far away as to be irrelevant
723  return false;
724  }
725  if (!source->getEdge().canChangeToOpposite()) {
726  return false;
727  }
728  MSLane* opposite = source->getOpposite();
729  if (opposite == 0) {
730  return false;
731  }
732 
733  // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
734  int direction = vehicle->getLaneChangeModel().isOpposite() ? -1 : 1;
735  std::pair<MSVehicle*, SUMOReal> neighLead((MSVehicle*)0, -1);
736 
737  // preliminary sanity checks for overtaking space
738  if (!isOpposite) {
739  assert(leader.first != 0);
740  // find a leader vehicle with sufficient space ahead for merging back
741  const SUMOReal overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
742  const SUMOReal mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
743  const SUMOReal maxLookAhead = 150; // just a guess
744  std::pair<MSVehicle*, SUMOReal> columnLeader = leader;
745  SUMOReal egoGap = leader.second;
746  bool foundSpaceAhead = false;
747  SUMOReal seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
748  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
749  while (!foundSpaceAhead) {
750  const SUMOReal requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
751  columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
752  + vehicle->getVehicleType().getLengthWithGap());
753 
754 
755  std::pair<MSVehicle* const, SUMOReal> leadLead = columnLeader.first->getLane()->getLeader(
756  columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap, true);
757 
758 #ifdef DEBUG_CHANGE_OPPOSITE
759  if (DEBUG_COND) {
760  std::cout << " leadLead=" << Named::getIDSecure(leadLead.first) << " gap=" << leadLead.second << "\n";
761  }
762 #endif
763  if (leadLead.first == 0) {
764  foundSpaceAhead = true;
765  } else {
766  const SUMOReal requiredSpace = (requiredSpaceAfterLeader
767  + vehicle->getCarFollowModel().getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel()));
768  if (leadLead.second > requiredSpace) {
769  foundSpaceAhead = true;
770  } else {
771 #ifdef DEBUG_CHANGE_OPPOSITE
772  if (DEBUG_COND) {
773  std::cout << " not enough space after columnLeader=" << leadLead.first->getID() << " gap=" << leadLead.second << " required=" << requiredSpace << "\n";
774  }
775 #endif
776  seen += leadLead.second + leadLead.first->getVehicleType().getLengthWithGap();
777  if (seen > maxLookAhead) {
778 #ifdef DEBUG_CHANGE_OPPOSITE
779  if (DEBUG_COND) {
780  std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << leadLead.first->getID() << ")\n";
781  }
782 #endif
783  return false;
784  }
785  // see if merging after leadLead is possible
786  egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
787  columnLeader = leadLead;
788 #ifdef DEBUG_CHANGE_OPPOSITE
789  if (DEBUG_COND) {
790  std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
791  }
792 #endif
793  }
794  }
795  }
796 #ifdef DEBUG_CHANGE_OPPOSITE
797  if (DEBUG_COND) {
798  std::cout << " compute time/space to overtake for columnLeader=" << columnLeader.first->getID() << " gap=" << columnLeader.second << "\n";
799  }
800 #endif
801  SUMOReal timeToOvertake;
802  SUMOReal spaceToOvertake;
803  computeOvertakingTime(vehicle, columnLeader.first, egoGap, timeToOvertake, spaceToOvertake);
804  // check for upcoming stops
805  if (vehicle->nextStopDist() < spaceToOvertake) {
806 #ifdef DEBUG_CHANGE_OPPOSITE
807  if (DEBUG_COND) {
808  std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
809  }
810 #endif
811  return false;
812  }
813  neighLead = opposite->getOppositeLeader(vehicle, timeToOvertake * opposite->getSpeedLimit() * 2 + spaceToOvertake);
814 
815 #ifdef DEBUG_CHANGE_OPPOSITE
816  if (DEBUG_COND) {
817  std::cout << SIMTIME
818  << " veh=" << vehicle->getID()
819  << " changeOpposite opposite=" << opposite->getID()
820  << " lead=" << Named::getIDSecure(leader.first)
821  << " oncoming=" << Named::getIDSecure(neighLead.first)
822  << " timeToOvertake=" << timeToOvertake
823  << " spaceToOvertake=" << spaceToOvertake
824  << "\n";
825  }
826 #endif
827 
828  // check for dangerous oncoming leader
829  if (!vehicle->getLaneChangeModel().isOpposite() && neighLead.first != 0) {
830  const MSVehicle* oncoming = neighLead.first;
832 
833 #ifdef DEBUG_CHANGE_OPPOSITE
834  if (DEBUG_COND) {
835  std::cout << SIMTIME
836  << " timeToOvertake=" << timeToOvertake
837  << " spaceToOvertake=" << spaceToOvertake
838  << " oncomingGap=" << neighLead.second
839  << " leaderGap=" << leader.second
840  << "\n";
841  }
842 #endif
843  if (neighLead.second - spaceToOvertake - timeToOvertake * oncoming->getSpeed() < 0) {
844 
845 #ifdef DEBUG_CHANGE_OPPOSITE
846  if (DEBUG_COND) {
847  std::cout << " cannot changeOpposite due to dangerous oncoming\n";
848  }
849 #endif
850  return false;
851  }
852  }
853  // check for sufficient space on the opposite side
854  seen = source->getLength() - vehicle->getPositionOnLane();
855  if (!vehicle->getLaneChangeModel().isOpposite() && seen < spaceToOvertake) {
856  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
857  assert(bestLaneConts.size() >= 1);
858  std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
859  while (seen < spaceToOvertake && it != bestLaneConts.end()) {
860  if ((*it)->getOpposite() == 0) {
861  break;
862  }
863  // do not overtake past a minor link
864  if (*(it - 1) != 0) {
865  MSLink* link = MSLinkContHelper::getConnectingLink(**(it - 1), **it);
866  if (link == 0 || !link->havePriority() || link->getState() == LINKSTATE_ZIPPER) {
867  break;
868  }
869  }
870  seen += (*it)->getLength();
871  }
872  if (seen < spaceToOvertake) {
873 #ifdef DEBUG_CHANGE_OPPOSITE
874  if (DEBUG_COND) {
875  std::cout << " cannot changeOpposite due to insufficient space (seen=" << seen << " spaceToOvertake=" << spaceToOvertake << ")\n";
876  }
877 #endif
878  return false;
879  }
880 #ifdef DEBUG_CHANGE_OPPOSITE
881  if (DEBUG_COND) {
882  std::cout << " seen=" << seen << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
883  }
884 #endif
885  }
886  } else {
888  leader = source->getOppositeLeader(vehicle, 200);
889  neighLead = opposite->getOppositeLeader(vehicle, -1);
890  }
891 
892  // compute wish to change
893  std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
894  if (isOpposite && leader.first != 0) {
895  MSVehicle::LaneQ& laneQ = preb[preb.size() - 1];
897  laneQ.length -= MIN2(laneQ.length, opposite->getOppositePos(vehicle->getPositionOnLane()) + leader.second / 2);
898  leader.first = 0; // ignore leader
899  }
900  std::pair<MSVehicle* const, SUMOReal> neighFollow = opposite->getOppositeFollower(vehicle);
901  int state = checkChange(direction, opposite, leader, neighLead, neighFollow, preb);
902 
903  bool changingAllowed = (state & LCA_BLOCKED) == 0;
904  // change if the vehicle wants to and is allowed to change
905  if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed) {
906  vehicle->getLaneChangeModel().startLaneChangeManeuver(source, opposite, direction);
908  vehicle->myState.myPos = source->getOppositePos(vehicle->myState.myPos);
909  vehicle->myState.myBackPos = source->getOppositePos(vehicle->myState.myBackPos);
912 #ifdef DEBUG_CHANGE_OPPOSITE
913  if (DEBUG_COND) {
914  std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n";
915  }
916 #endif
917  return true;
918  }
919 #ifdef DEBUG_CHANGE_OPPOSITE
920  if (DEBUG_COND) {
921  std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n";
922  }
923 #endif
924  return false;
925 }
926 
927 
928 void
929 MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, const MSVehicle* leader, SUMOReal gap, SUMOReal& timeToOvertake, SUMOReal& spaceToOvertake) {
930  // Assumption: leader maintains the current speed
931  // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
932 
933  // first compute these values for the case where vehicle is accelerating
934  // without upper bound on speed
935  const SUMOReal v = vehicle->getSpeed();
936  const SUMOReal u = leader->getSpeed();
937  const SUMOReal a = vehicle->getCarFollowModel().getMaxAccel();
938  const SUMOReal g = gap + vehicle->getVehicleType().getMinGap() + leader->getVehicleType().getLengthWithGap();
939  const SUMOReal sign = -1; // XXX recheck
940  // v*t + t*t*a*0.5 = g + u*t
941  // solve t
942  // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
943  SUMOReal t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
944 
946  const SUMOReal vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
947  const SUMOReal timeToMaxSpeed = (vMax - v) / a;
948 
949  if (t <= timeToMaxSpeed) {
950  timeToOvertake = t;
951  spaceToOvertake = v * t + t * t * a * 0.5;
952  //if (gDebugFlag1) std::cout << " t below " << timeToMaxSpeed << " vMax=" << vMax << "\n";
953  } else {
954  // space until max speed is reached
955  const SUMOReal s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
956  const SUMOReal m = timeToMaxSpeed;
957  // s + (t-m) * vMax = g + u*t
958  // solve t
959  t = (g - s + m * vMax) / (vMax - u);
960  timeToOvertake = t;
961  spaceToOvertake = s + (t - m) * vMax;
962  //if (gDebugFlag1) std::cout << " s=" << s << " m=" << m << " vMax=" << vMax << "\n";
963  }
964 }
965 
966 /****************************************************************************/
967 
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:3492
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:567
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:81
bool isLinkEnd(MSLinkCont::const_iterator &i) const
Definition: MSLane.cpp:1334
long long int SUMOTime
Definition: SUMOTime.h:43
static MSLinkCont::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition: MSLane.cpp:1396
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:700
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1379
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, SUMOReal > getRealLeader(const ChangerIt &target) const
std::pair< MSVehicle *const, SUMOReal > getOppositeFollower(const MSVehicle *ego) const
Definition: MSLane.cpp:2490
SUMOReal getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
The vehicle is blocked by left follower.
MSLane * getOpposite() const
return the opposite direction lane for lane changing or 0
Definition: MSLane.cpp:2429
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links ...
Definition: MSVehicle.cpp:3219
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.
SUMOReal getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:475
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, SUMOReal > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
int getShadowDirection() const
return the direction in which the current shadow lane lies
Wants go to the right.
SUMOReal getLength() const
Get vehicle&#39;s length [m].
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, SUMOReal > &leader, const std::pair< MSVehicle *, SUMOReal > &neighLead, const std::pair< MSVehicle *, SUMOReal > &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...
SUMOReal getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:491
T MAX2(T a, T b)
Definition: StdDefs.h:75
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
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
SUMOReal getSecureGap(const SUMOReal speed, const SUMOReal leaderSpeed, const SUMOReal leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum.
Definition: MSCFModel.h:272
void startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
start the lane change maneuver (and finish it instantly if gLaneChangeDuration == 0) ...
SUMOReal getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:350
std::pair< MSVehicle *const, SUMOReal > getCriticalLeader(SUMOReal dist, SUMOReal seen, SUMOReal speed, const MSVehicle &veh) const
Returns the most dangerous leader and the distance to him.
Definition: MSLane.cpp:1814
VehCont myPartialVehicles
The lane&#39;s partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1046
Wants go to the left.
SUMOReal length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:618
static void computeOvertakingTime(const MSVehicle *vehicle, const MSVehicle *leader, SUMOReal gap, SUMOReal &timeToOvertake, SUMOReal &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
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.
static MSVehicle * getCloserFollower(const SUMOReal maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:2462
#define SIMTIME
Definition: SUMOTime.h:70
std::string gDebugSelectedVehicle
Definition: StdDefs.cpp:95
SUMOReal getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:375
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)
std::pair< MSVehicle *const, SUMOReal > getRealFollower(const ChangerIt &target) const
#define max(a, b)
Definition: polyfonts.c:65
SUMOReal brakeGap(const SUMOReal speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time.
Definition: MSCFModel.h:234
SUMOReal computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:808
virtual void updateChanger(bool vehHasChanged)
The action is urgent (to be defined by lc-model)
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the subpart of best lanes that describes the vehicle&#39;s current lane and their successors...
Definition: MSVehicle.cpp:2808
SUMOReal getLateralSpeed() const
return the lateral speed of the current lane change maneuver
SUMOReal myAngle
the angle (
Definition: MSVehicle.h:1425
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:2480
Position myCachedPosition
Definition: MSVehicle.h:1430
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:1494
virtual bool changeOpposite(std::pair< MSVehicle *, SUMOReal > leader)
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:988
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
T MIN2(T a, T b)
Definition: StdDefs.h:69
The link is a (hard) right direction.
virtual void setOwnState(int state)
SUMOReal getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:467
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:614
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:186
MSLane * getShadowLane() const
Returns the lane the vehicles shadow is on during continuous/sublane lane change. ...
MSLaneChanger()
Default constructor.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
int checkChange(int laneOffset, const MSLane *targetLane, const std::pair< MSVehicle *const, SUMOReal > &leader, const std::pair< MSVehicle *const, SUMOReal > &neighLead, const std::pair< MSVehicle *const, SUMOReal > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb) const
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:254
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:2474
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:91
bool canChangeToOpposite()
whether this edge allows changing to the opposite direction edge
Definition: MSEdge.cpp:850
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void forceVehicleInsertion(MSVehicle *veh, SUMOReal pos, MSMoveReminder::Notification notification, SUMOReal posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:743
SUMOReal getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:178
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
#define sign(a)
Definition: polyfonts.c:68
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
bool myAllowsSwap
Whether blocking vehicles may be swapped.
std::pair< MSVehicle *const, SUMOReal > getOppositeLeader(const MSVehicle *ego, SUMOReal dist) const
Definition: MSLane.cpp:2469
virtual ~MSLaneChanger()
Destructor.
#define DEBUG_COND
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
Definition: MSBaseVehicle.h:97
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:410
SUMOReal myPos
the stored position
Definition: MSVehicle.h:133
SUMOReal getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:1962
SUMOReal nextStopDist() const
return the distance to the next stop or SUMORealMax if there is none.
Definition: MSVehicle.h:791
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
SUMOReal getOppositePos(SUMOReal pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:2438
void registerUnchanged(MSVehicle *vehicle)
SUMOReal myPosLat
the stored lateral position
Definition: MSVehicle.h:139
#define SUMOReal
Definition: config.h:213
void adaptBestLanesOccupation(int laneIndex, SUMOReal density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:2846
SUMOReal myBackPos
the stored back position
Definition: MSVehicle.h:144
SUMOReal getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:453
The vehicle is blocked by right leader.
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:447
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:3472
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one...
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:81
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
The vehicle is blocked by right follower.
Interface for lane-change models.
std::pair< MSVehicle *const, SUMOReal > getLeader(const MSVehicle *veh, const SUMOReal vehPos, const std::vector< MSLane * > &bestLaneConts, SUMOReal dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
Definition: MSLane.cpp:1664
ChangerIt myCandi
static const Position INVALID
Definition: Position.h:261
The vehicle is blocked by left leader.
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
const std::string & getID() const
Returns the name of the vehicle.
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)