SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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_SURROUNDING_VEHICLES // debug getRealFollower() and getRealLeader()
61 //#define DEBUG_CHANGE_OPPOSITE
62 //#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
63 #define DEBUG_COND false
64 
65 
66 
67 // ===========================================================================
68 // ChangeElem member method definitions
69 // ===========================================================================
71  lead(0),
72  lane(_lane),
73  hoppedVeh(0),
74  lastBlocked(0),
75  firstBlocked(0),
76  ahead(lane) {
77 }
78 
79 // ===========================================================================
80 // member method definitions
81 // ===========================================================================
82 MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging) :
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  // needs 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 myChanger.end().
179  // XXX: To my impression this returns the vehicle with the *largest* position?! (Leo)
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  if (!changeOpposite(leader)) {
312  registerUnchanged(vehicle);
313  return false;
314  } else {
315  return true;
316  }
317 }
318 
319 
320 void
322  myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
323  myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
324  vehicle->getLaneChangeModel().unchanged();
325 }
326 
327 
328 void
329 MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
330  ChangerIt to = from + direction;
331  // @todo delay entering the target lane until the vehicle intersects it
332  // physically (considering lane width and vehicle width)
333  //if (to->lane->getID() == "beg_1") std::cout << SIMTIME << " startChange to lane=" << to->lane->getID() << " myTmpVehiclesBefore=" << toString(to->lane->myTmpVehicles) << "\n";
334  const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
335  if (continuous) {
336  continueChange(vehicle, myCandi);
337  } else {
338  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
339  to->dens += vehicle->getVehicleType().getLengthWithGap();
340  to->hoppedVeh = vehicle;
341  }
342 }
343 
344 
345 bool
348  const int direction = lcm.getLaneChangeDirection();
349  const bool pastMidpoint = lcm.updateCompletion();
350  vehicle->myState.myPosLat += lcm.getLateralSpeed();
352  if (pastMidpoint) {
353  ChangerIt to = from + direction;
354  MSLane* source = myCandi->lane;
355  MSLane* target = to->lane;
356  vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
357  lcm.primaryLaneChanged(source, target, direction);
358  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
359  to->dens += vehicle->getVehicleType().getLengthWithGap();
360  to->hoppedVeh = vehicle;
361  } else {
362  from->lane->myTmpVehicles.insert(from->lane->myTmpVehicles.begin(), vehicle);
363  from->dens += vehicle->getVehicleType().getLengthWithGap();
364  from->hoppedVeh = vehicle;
365  }
366  if (!lcm.isChangingLanes()) {
367  vehicle->myState.myPosLat = 0;
368  lcm.endLaneChangeManeuver();
369  }
370  lcm.updateShadowLane();
371  if (lcm.getShadowLane() != 0) {
372  // set as hoppedVeh on the shadow lane so it is found as leader on both lanes
373  ChangerIt shadow = pastMidpoint ? from : from + lcm.getShadowDirection();
374  shadow->hoppedVeh = vehicle;
375  }
376  vehicle->myAngle = vehicle->computeAngle();
377 
378 #ifdef DEBUG_CONTINUE_CHANGE
379  if (DEBUG_COND) {
380  std::cout << SIMTIME
381  << " continueChange veh=" << vehicle->getID()
382  << " from=" << Named::getIDSecure(from->lane)
383  << " dir=" << direction
384  << " pastMidpoint=" << pastMidpoint
385  << " posLat=" << vehicle->getLateralPositionOnLane()
386  //<< " completion=" << lcm.getLaneChangeCompletion()
387  << " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
388  << " shadowHopped=" << Named::getIDSecure(shadow->lane)
389  << "\n";
390  }
391 #endif
392  return pastMidpoint;
393 }
394 
395 
396 std::pair<MSVehicle* const, SUMOReal>
398  assert(veh(myCandi) != 0);
399 
400 #ifdef DEBUG_SURROUNDING_VEHICLES
401  MSVehicle* vehicle = veh(myCandi);
402  if (DEBUG_COND) {
403  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl;
404  }
405 #endif
406  // get the leading vehicle on the lane to change to
407  MSVehicle* neighLead = target->lead;
408 
409 #ifdef DEBUG_SURROUNDING_VEHICLES
410  if (DEBUG_COND) {
411  if (neighLead != 0) {
412  std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl;
413  }
414  }
415 #endif
416 
417  //if (veh(myCandi)->getID() == "disabled") std::cout << SIMTIME
418  // << " target=" << target->lane->getID()
419  // << " neighLead=" << Named::getIDSecure(neighLead)
420  // << " hopped=" << Named::getIDSecure(target->hoppedVeh)
421  // << " (416)\n";
422  // check whether the hopped vehicle became the leader
423  if (target->hoppedVeh != 0) {
424  SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane();
425 #ifdef DEBUG_SURROUNDING_VEHICLES
426  if (DEBUG_COND) {
427  std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl;
428  }
429 #endif
430  if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) {
431  neighLead = target->hoppedVeh;
432  //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n";
433  }
434  }
435  if (neighLead == 0) {
436 #ifdef DEBUG_SURROUNDING_VEHICLES
437  if (DEBUG_COND) {
438  std::cout << "Looking for leader on consecutive lanes." << std::endl;
439  }
440 #endif
441  // There's no leader on the target lane. Look for leaders on consecutive lanes.
442  MSLane* targetLane = target->lane;
443  if (targetLane->myPartialVehicles.size() > 0) {
444  assert(targetLane->myPartialVehicles.size() > 0);
445  std::vector<MSVehicle*>::const_iterator i = targetLane->myPartialVehicles.begin();
446  MSVehicle* leader = *i;
447  SUMOReal leaderPos = leader->getBackPositionOnLane(targetLane);
448  while (++i != targetLane->myPartialVehicles.end()) {
449  if ((*i)->getBackPositionOnLane(targetLane) < leader->getBackPositionOnLane(targetLane)) {
450  leader = *i;
451  leaderPos = leader->getBackPositionOnLane(targetLane);
452  }
453  }
454  return std::pair<MSVehicle*, SUMOReal>(leader, leaderPos - veh(myCandi)->getPositionOnLane() - veh(myCandi)->getVehicleType().getMinGap());
455  }
456  SUMOReal seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane();
457  SUMOReal speed = veh(myCandi)->getSpeed();
459  if (seen > dist) {
460  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
461  }
462  const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane);
463  return target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts);
464  } else {
465  MSVehicle* candi = veh(myCandi);
466  return std::pair<MSVehicle* const, SUMOReal>(neighLead, neighLead->getBackPositionOnLane(target->lane) - candi->getPositionOnLane() - candi->getVehicleType().getMinGap());
467  }
468 }
469 
470 
471 std::pair<MSVehicle* const, SUMOReal>
473  assert(veh(myCandi) != 0);
474 
475 #ifdef DEBUG_SURROUNDING_VEHICLES
476  MSVehicle* vehicle = veh(myCandi);
477  if (DEBUG_COND) {
478  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl;
479  }
480 #endif
481  MSVehicle* candi = veh(myCandi);
482  const SUMOReal candiPos = candi->getPositionOnLane();
483  MSVehicle* neighFollow = veh(target);
484 
485 #ifdef DEBUG_SURROUNDING_VEHICLES
486  if (DEBUG_COND) {
487  if (neighFollow != 0) {
488  std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl;
489  } else {
490  std::cout << "veh(target) returns none." << std::endl;
491  }
492  }
493 #endif
494 
495 
496 #ifdef DEBUG_SURROUNDING_VEHICLES
497  if (DEBUG_COND) {
498  if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
499  std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
500  }
501  }
502 #endif
503 
504  // check whether the hopped vehicle became the follower
505  neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
506 
507 
508 #ifdef DEBUG_SURROUNDING_VEHICLES
509  if (DEBUG_COND) {
510  MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
511  if (partialBehind != 0 && partialBehind != neighFollow) {
512  std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(candi)->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
513  }
514  }
515 #endif
516  // or a follower which is partially lapping into the target lane
517  neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
518 
519  if (neighFollow == 0) {
520  std::pair<MSVehicle* const, SUMOReal> consecutiveFollower = target->lane->getFollowerOnConsecutive(
521  candi->getPositionOnLane() - candi->getVehicleType().getLength(),
522  candi->getSpeed(), candi->getCarFollowModel().getMaxDecel());
523 #ifdef DEBUG_SURROUNDING_VEHICLES
524  if (DEBUG_COND) {
525  if (consecutiveFollower.first == 0) {
526  std::cout << "no follower found." << std::endl;
527  } else {
528  std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl;
529  }
530  }
531 #endif
532  return consecutiveFollower;
533  } else {
534 #ifdef DEBUG_SURROUNDING_VEHICLES
535  if (DEBUG_COND) {
536  std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl;
537  }
538 #endif
539  MSVehicle* candi = veh(myCandi);
540  return std::pair<MSVehicle* const, SUMOReal>(neighFollow,
541  candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
542  }
543 }
544 
545 
546 MSVehicle*
548  if (follow1 == 0 || follow1->getPositionOnLane() > maxPos) {
549  return follow2;
550  } else if (follow2 == 0 || follow2->getPositionOnLane() > maxPos) {
551  return follow1;
552  } else {
553  if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
554  return follow1;
555  } else {
556  return follow2;
557  }
558  }
559 }
560 
561 int
563  int laneOffset,
564  const std::pair<MSVehicle* const, SUMOReal>& leader,
565  const std::vector<MSVehicle::LaneQ>& preb) const {
566 
567  std::pair<MSVehicle* const, SUMOReal> neighLead = getRealLeader(myCandi + laneOffset);
568  std::pair<MSVehicle*, SUMOReal> neighFollow = getRealFollower(myCandi + laneOffset);
569  if (neighLead.first != 0 && neighLead.first == neighFollow.first) {
570  // vehicles should not be leader and follower at the same time to avoid
571  // contradictory behavior
572  neighFollow.first = 0;
573  }
574  ChangerIt target = myCandi + laneOffset;
575  return checkChange(laneOffset, target->lane, leader, neighLead, neighFollow, preb);
576 }
577 
578 int
580  int laneOffset,
581  const MSLane* targetLane,
582  const std::pair<MSVehicle* const, SUMOReal>& leader,
583  const std::pair<MSVehicle* const, SUMOReal>& neighLead,
584  const std::pair<MSVehicle* const, SUMOReal>& neighFollow,
585  const std::vector<MSVehicle::LaneQ>& preb) const {
586 
587  MSVehicle* vehicle = veh(myCandi);
588 
589  // Debug (Leo)
590 #ifdef DEBUG_CHECK_CHANGE
591  if (DEBUG_COND) {
592  std::cout
593  << "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'"
594  << std::endl;
595  }
596 #endif
597 
598 
599  int blocked = 0;
600  int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
601  int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
602  // overlap
603  if (neighFollow.first != 0 && neighFollow.second < 0) {
604  blocked |= (blockedByFollower | LCA_OVERLAPPING);
605 
606  // Debug (Leo)
607 #ifdef DEBUG_CHECK_CHANGE
608  if (DEBUG_COND) {
609  std::cout << SIMTIME
610  << " overlapping with follower..."
611  << std::endl;
612  }
613 #endif
614 
615  }
616  if (neighLead.first != 0 && neighLead.second < 0) {
617  blocked |= (blockedByLeader | LCA_OVERLAPPING);
618 
619  // Debug (Leo)
620 #ifdef DEBUG_CHECK_CHANGE
621  if (DEBUG_COND) {
622  std::cout << SIMTIME
623  << " overlapping with leader..."
624  << std::endl;
625  }
626 #endif
627 
628  }
629 
630  // safe back gap
631  if ((blocked & blockedByFollower) == 0 && neighFollow.first != 0) {
632  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
633  if (neighFollow.second < neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel())) {
634  blocked |= blockedByFollower;
635 
636  // Debug (Leo)
637 #ifdef DEBUG_CHECK_CHANGE
638  if (DEBUG_COND) {
639  std::cout << SIMTIME
640  << " back gap unsafe: "
641  << "gap = " << neighFollow.second
642  << ", secureGap = "
643  << neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first->getSpeed(),
644  vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel())
645  << std::endl;
646  }
647 #endif
648 
649  }
650  }
651 
652  // safe front gap
653  if ((blocked & blockedByLeader) == 0 && neighLead.first != 0) {
654  // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
655  if (neighLead.second < vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())) {
656  blocked |= blockedByLeader;
657 
658  // Debug (Leo)
659 #ifdef DEBUG_CHECK_CHANGE
660  if (DEBUG_COND) {
661  std::cout << SIMTIME
662  << " front gap unsafe: "
663  << "gap = " << neighLead.second
664  << ", secureGap = "
665  << vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(),
666  neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())
667  << std::endl;
668  }
669 #endif
670 
671  }
672  }
673 
674 
675  MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
676  int state = blocked | vehicle->getLaneChangeModel().wantsChange(
677  laneOffset, msg, blocked, leader, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
678 
679  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != 0) {
680  // do are more carefull (but expensive) check to ensure that a
681  // safety-critical leader is not being overloocked
682  const SUMOReal seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
683  const SUMOReal speed = vehicle->getSpeed();
684  const SUMOReal dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
685  if (seen < dist) {
686  std::pair<MSVehicle* const, SUMOReal> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
687  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
688  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
689  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
690  state |= blockedByLeader;
691  }
692  }
693  }
694  if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
695  // ensure that merging is safe for any upcoming zipper links after changing
696  if (vehicle->unsafeLinkAhead(targetLane)) {
697  state |= blockedByLeader;
698  }
699  }
700 
701  if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
702  // ensure that a continuous lane change manoeuvre can be completed
703  // before the next turning movement
704  SUMOReal seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
706  const SUMOReal avgSpeed = 0.5 * (
707  MAX2((SUMOReal)0, vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
708  MAX2((SUMOReal)0, vehicle->getSpeed() - decel));
709  const SUMOReal space2change = avgSpeed * STEPS2TIME(MSGlobals::gLaneChangeDuration);
710  // for finding turns it doesn't matter whether we look along the current lane or the target lane
711  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
712  int view = 1;
713  MSLane* nextLane = vehicle->getLane();
714  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
715  while (!nextLane->isLinkEnd(link) && seen <= space2change) {
716  if ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT
717  // the lanes after an internal junction are on different
718  // edges and do not allow lane-changing
719  || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
720  ) {
721  state |= LCA_INSUFFICIENT_SPACE;
722  break;
723  }
724 #ifdef HAVE_INTERNAL_LANES
725  if ((*link)->getViaLane() == 0) {
726  view++;
727  }
728 #else
729  view++;
730 #endif
731  nextLane = (*link)->getViaLaneOrLane();
732  seen += nextLane->getLength();
733  // get the next link used
734  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
735  }
736  if (nextLane->isLinkEnd(link) && seen < space2change) {
737 #ifdef DEBUG_CHECK_CHANGE
738  if (DEBUG_COND) {
739  std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
740  }
741 #endif
742  state |= LCA_INSUFFICIENT_SPACE;
743  }
744 
745  if ((state & LCA_BLOCKED) == 0) {
746  // check for dangerous leaders in case the target lane changes laterally between
747  // now and the lane-changing midpoint
748  const SUMOReal speed = vehicle->getSpeed();
749  seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
750  nextLane = vehicle->getLane();
751  view = 1;
752  const SUMOReal dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
753  MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
754  while (!nextLane->isLinkEnd(link) && seen <= space2change && seen <= dist) {
755  nextLane = (*link)->getViaLaneOrLane();
756  MSLane* targetLane = nextLane->getParallelLane(laneOffset);
757  if (targetLane == 0) {
758  state |= LCA_INSUFFICIENT_SPACE;
759  break;
760  } else {
761  std::pair<MSVehicle* const, SUMOReal> neighLead2 = targetLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
762  if (neighLead2.first != 0 && neighLead2.first != neighLead.first
763  && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(
764  vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
765  state |= blockedByLeader;
766  break;
767  }
768  }
769 #ifdef HAVE_INTERNAL_LANES
770  if ((*link)->getViaLane() == 0) {
771  view++;
772  }
773 #else
774  view++;
775 #endif
776  seen += nextLane->getLength();
777  // get the next link used
778  link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
779  }
780  }
781  }
782 #ifndef NO_TRACI
783 #ifdef DEBUG_CHECK_CHANGE
784  const int oldstate = state;
785 #endif
786  // let TraCI influence the wish to change lanes and the security to take
787  state = vehicle->influenceChangeDecision(state);
788 #endif
789 #ifdef DEBUG_CHECK_CHANGE
790  if (DEBUG_COND) {
791  std::cout << SIMTIME
792  << " veh=" << vehicle->getID()
793  << " oldState=" << toString((LaneChangeAction)oldstate)
794  << " newState=" << toString((LaneChangeAction)state)
795  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
796  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
797  << "\n";
798  }
799 #endif
800  return state;
801 }
802 
803 
804 bool
805 MSLaneChanger::changeOpposite(std::pair<MSVehicle*, SUMOReal> leader) {
806  if (!myChangeToOpposite) {
807  return false;
808  }
810  MSVehicle* vehicle = veh(myCandi);
811  MSLane* source = vehicle->getLane();
812  if (vehicle->isStopped()) {
813  // stopped vehicles obviously should not change lanes. Usually this is
814  // prevent by appropriate bestLane distances
815  return false;
816  }
817  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
818  if (!isOpposite && leader.first == 0) {
819  // no reason to change unless there is a leader
820  // or we are changing back to the propper direction
821  // XXX also check whether the leader is so far away as to be irrelevant
822  return false;
823  }
824  if (!source->getEdge().canChangeToOpposite()) {
825  return false;
826  }
827  MSLane* opposite = source->getOpposite();
828  if (opposite == 0) {
829  return false;
830  }
831 
832  // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
833  int direction = vehicle->getLaneChangeModel().isOpposite() ? -1 : 1;
834  std::pair<MSVehicle*, SUMOReal> neighLead((MSVehicle*)0, -1);
835 
836  // preliminary sanity checks for overtaking space
837  if (!isOpposite) {
838  assert(leader.first != 0);
839  // find a leader vehicle with sufficient space ahead for merging back
840  const SUMOReal overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
841  const SUMOReal mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
842  const SUMOReal maxLookAhead = 150; // just a guess
843  std::pair<MSVehicle*, SUMOReal> columnLeader = leader;
844  SUMOReal egoGap = leader.second;
845  bool foundSpaceAhead = false;
846  SUMOReal seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
847  std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
848  while (!foundSpaceAhead) {
849  const SUMOReal requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
850  columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
851  + vehicle->getVehicleType().getLengthWithGap());
852 
853 
854  std::pair<MSVehicle* const, SUMOReal> leadLead = columnLeader.first->getLane()->getLeader(
855  columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap, true);
856 
857 #ifdef DEBUG_CHANGE_OPPOSITE
858  if (DEBUG_COND) {
859  std::cout << " leadLead=" << Named::getIDSecure(leadLead.first) << " gap=" << leadLead.second << "\n";
860  }
861 #endif
862  if (leadLead.first == 0) {
863  foundSpaceAhead = true;
864  } else {
865  const SUMOReal requiredSpace = (requiredSpaceAfterLeader
866  + vehicle->getCarFollowModel().getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel()));
867  if (leadLead.second > requiredSpace) {
868  foundSpaceAhead = true;
869  } else {
870 #ifdef DEBUG_CHANGE_OPPOSITE
871  if (DEBUG_COND) {
872  std::cout << " not enough space after columnLeader=" << leadLead.first->getID() << " gap=" << leadLead.second << " required=" << requiredSpace << "\n";
873  }
874 #endif
875  seen += leadLead.second + leadLead.first->getVehicleType().getLengthWithGap();
876  if (seen > maxLookAhead) {
877 #ifdef DEBUG_CHANGE_OPPOSITE
878  if (DEBUG_COND) {
879  std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << leadLead.first->getID() << ")\n";
880  }
881 #endif
882  return false;
883  }
884  // see if merging after leadLead is possible
885  egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
886  columnLeader = leadLead;
887 #ifdef DEBUG_CHANGE_OPPOSITE
888  if (DEBUG_COND) {
889  std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
890  }
891 #endif
892  }
893  }
894  }
895 #ifdef DEBUG_CHANGE_OPPOSITE
896  if (DEBUG_COND) {
897  std::cout << " compute time/space to overtake for columnLeader=" << columnLeader.first->getID() << " gap=" << columnLeader.second << "\n";
898  }
899 #endif
900  SUMOReal timeToOvertake;
901  SUMOReal spaceToOvertake;
902  computeOvertakingTime(vehicle, columnLeader.first, egoGap, timeToOvertake, spaceToOvertake);
903  // check for upcoming stops
904  if (vehicle->nextStopDist() < spaceToOvertake) {
905 #ifdef DEBUG_CHANGE_OPPOSITE
906  if (DEBUG_COND) {
907  std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
908  }
909 #endif
910  return false;
911  }
912  neighLead = opposite->getOppositeLeader(vehicle, timeToOvertake * opposite->getSpeedLimit() * 2 + spaceToOvertake);
913 
914 #ifdef DEBUG_CHANGE_OPPOSITE
915  if (DEBUG_COND) {
916  std::cout << SIMTIME
917  << " veh=" << vehicle->getID()
918  << " changeOpposite opposite=" << opposite->getID()
919  << " lead=" << Named::getIDSecure(leader.first)
920  << " oncoming=" << Named::getIDSecure(neighLead.first)
921  << " timeToOvertake=" << timeToOvertake
922  << " spaceToOvertake=" << spaceToOvertake
923  << "\n";
924  }
925 #endif
926 
927  // check for dangerous oncoming leader
928  if (!vehicle->getLaneChangeModel().isOpposite() && neighLead.first != 0) {
929  const MSVehicle* oncoming = neighLead.first;
931 
932 #ifdef DEBUG_CHANGE_OPPOSITE
933  if (DEBUG_COND) {
934  std::cout << SIMTIME
935  << " timeToOvertake=" << timeToOvertake
936  << " spaceToOvertake=" << spaceToOvertake
937  << " oncomingGap=" << neighLead.second
938  << " leaderGap=" << leader.second
939  << "\n";
940  }
941 #endif
942  if (neighLead.second - spaceToOvertake - timeToOvertake * oncoming->getSpeed() < 0) {
943 
944 #ifdef DEBUG_CHANGE_OPPOSITE
945  if (DEBUG_COND) {
946  std::cout << " cannot changeOpposite due to dangerous oncoming\n";
947  }
948 #endif
949  return false;
950  }
951  }
952  // check for sufficient space on the opposite side
953  seen = source->getLength() - vehicle->getPositionOnLane();
954  if (!vehicle->getLaneChangeModel().isOpposite() && seen < spaceToOvertake) {
955  const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
956  assert(bestLaneConts.size() >= 1);
957  std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
958  while (seen < spaceToOvertake && it != bestLaneConts.end()) {
959  if ((*it)->getOpposite() == 0) {
960  break;
961  }
962  // do not overtake past a minor link
963  if (*(it - 1) != 0) {
964  MSLink* link = MSLinkContHelper::getConnectingLink(**(it - 1), **it);
965  if (link == 0 || !link->havePriority() || link->getState() == LINKSTATE_ZIPPER) {
966  break;
967  }
968  }
969  seen += (*it)->getLength();
970  }
971  if (seen < spaceToOvertake) {
972 #ifdef DEBUG_CHANGE_OPPOSITE
973  if (DEBUG_COND) {
974  std::cout << " cannot changeOpposite due to insufficient space (seen=" << seen << " spaceToOvertake=" << spaceToOvertake << ")\n";
975  }
976 #endif
977  return false;
978  }
979 #ifdef DEBUG_CHANGE_OPPOSITE
980  if (DEBUG_COND) {
981  std::cout << " seen=" << seen << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
982  }
983 #endif
984  }
985  } else {
987  leader = source->getOppositeLeader(vehicle, 200);
988  neighLead = opposite->getOppositeLeader(vehicle, -1);
989  }
990 
991  // compute wish to change
992  std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
993  if (isOpposite && leader.first != 0) {
994  MSVehicle::LaneQ& laneQ = preb[preb.size() - 1];
996  laneQ.length -= MIN2(laneQ.length, opposite->getOppositePos(vehicle->getPositionOnLane()) + leader.second / 2);
997  leader.first = 0; // ignore leader
998  }
999  std::pair<MSVehicle* const, SUMOReal> neighFollow = opposite->getOppositeFollower(vehicle);
1000  int state = checkChange(direction, opposite, leader, neighLead, neighFollow, preb);
1001 
1002  bool changingAllowed = (state & LCA_BLOCKED) == 0;
1003  // change if the vehicle wants to and is allowed to change
1004  if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed) {
1005  vehicle->getLaneChangeModel().startLaneChangeManeuver(source, opposite, direction);
1007  vehicle->myState.myPos = source->getOppositePos(vehicle->myState.myPos);
1008  vehicle->myState.myBackPos = source->getOppositePos(vehicle->myState.myBackPos);
1011 #ifdef DEBUG_CHANGE_OPPOSITE
1012  if (DEBUG_COND) {
1013  std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n";
1014  }
1015 #endif
1016  return true;
1017  }
1018 #ifdef DEBUG_CHANGE_OPPOSITE
1019  if (DEBUG_COND) {
1020  std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n";
1021  }
1022 #endif
1023  return false;
1024 }
1025 
1026 
1027 void
1028 MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, const MSVehicle* leader, SUMOReal gap, SUMOReal& timeToOvertake, SUMOReal& spaceToOvertake) {
1029  // Assumption: leader maintains the current speed
1030  // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
1031 
1032  // first compute these values for the case where vehicle is accelerating
1033  // without upper bound on speed
1034  const SUMOReal v = vehicle->getSpeed();
1035  const SUMOReal u = leader->getSpeed();
1036  const SUMOReal a = vehicle->getCarFollowModel().getMaxAccel();
1037  const SUMOReal g = gap + vehicle->getVehicleType().getMinGap() + leader->getVehicleType().getLengthWithGap();
1038  const SUMOReal sign = -1; // XXX recheck
1039  // v*t + t*t*a*0.5 = g + u*t
1040  // solve t
1041  // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
1042  SUMOReal t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
1043 
1045  const SUMOReal vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1046  const SUMOReal timeToMaxSpeed = (vMax - v) / a;
1047 
1048  if (t <= timeToMaxSpeed) {
1049  timeToOvertake = t;
1050  spaceToOvertake = v * t + t * t * a * 0.5;
1051  //if (gDebugFlag1) std::cout << " t below " << timeToMaxSpeed << " vMax=" << vMax << "\n";
1052  } else {
1053  // space until max speed is reached
1054  const SUMOReal s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
1055  const SUMOReal m = timeToMaxSpeed;
1056  // s + (t-m) * vMax = g + u*t
1057  // solve t
1058  t = (g - s + m * vMax) / (vMax - u);
1059  timeToOvertake = t;
1060  spaceToOvertake = s + (t - m) * vMax;
1061  //if (gDebugFlag1) std::cout << " s=" << s << " m=" << m << " vMax=" << vMax << "\n";
1062  }
1063 }
1064 
1065 /****************************************************************************/
1066 
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:3734
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:571
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:82
bool isLinkEnd(MSLinkCont::const_iterator &i) const
Definition: MSLane.cpp:1394
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:1461
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:758
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1437
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:2561
SUMOReal getLengthWithGap() const
Get vehicle'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:2500
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:3461
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's length.
Definition: MSLane.h:480
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'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's width.
Definition: MSLane.h:496
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 (>=0)
Definition: MSCFModel.h:276
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's position along the lane.
Definition: MSVehicle.h:374
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:1885
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1060
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:673
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:2702
#define SIMTIME
Definition: SUMOTime.h:70
std::string gDebugSelectedVehicle
Definition: StdDefs.cpp:95
SUMOReal getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:406
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) XXX: What if a vehicle changes lanes and passes a junction sim...
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's reaction time, assuming that during...
Definition: MSCFModel.h:263
SUMOReal computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:823
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's current lane and their successors...
Definition: MSVehicle.cpp:3048
SUMOReal getLateralSpeed() const
return the lateral speed of the current lane change maneuver
SUMOReal myAngle
the angle in radians (
Definition: MSVehicle.h:1483
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:2720
Position myCachedPosition
Definition: MSVehicle.h:1488
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:1561
virtual bool changeOpposite(std::pair< MSVehicle *, SUMOReal > leader)
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1003
#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's maximum allowed speed.
Definition: MSLane.h:472
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:669
SUMOReal getMaxDecel() const
Get the vehicle type's maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
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:2714
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:857
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:806
SUMOReal getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition: MSCFModel.h:193
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's lane-change behavior.
std::pair< MSVehicle *const, SUMOReal > getOppositeLeader(const MSVehicle *ego, SUMOReal dist) const
Definition: MSLane.cpp:2540
virtual ~MSLaneChanger()
Destructor.
#define DEBUG_COND
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
SUMOReal getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:441
SUMOReal myPos
the stored position
Definition: MSVehicle.h:139
SUMOReal getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition: MSVehicle.cpp:2198
SUMOReal nextStopDist() const
return the distance to the next stop or SUMORealMax if there is none.
Definition: MSVehicle.h:849
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:2509
void registerUnchanged(MSVehicle *vehicle)
SUMOReal myPosLat
the stored lateral position
Definition: MSVehicle.h:145
#define SUMOReal
Definition: config.h:214
void adaptBestLanesOccupation(int laneIndex, SUMOReal density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:3087
SUMOReal myBackPos
the stored back position
Definition: MSVehicle.h:150
SUMOReal getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:458
The vehicle is blocked by right leader.
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:487
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:3714
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:86
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:1735
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)