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