Eclipse SUMO - Simulation of Urban MObility
MSLaneChangerSublane.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2002-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
19 // Performs sub-lane changing of vehicles
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include "MSLaneChangerSublane.h"
24 #include "MSNet.h"
25 #include "MSVehicle.h"
26 #include "MSVehicleType.h"
27 #include "MSVehicleTransfer.h"
28 #include "MSGlobals.h"
29 #include <cassert>
30 #include <iterator>
31 #include <cstdlib>
32 #include <cmath>
35 #include <utils/geom/GeomHelper.h>
36 
37 
38 // ===========================================================================
39 // DEBUG constants
40 // ===========================================================================
41 #define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
42 //#define DEBUG_COND (vehicle->getID() == "disabled")
43 //#define DEBUG_COND true
44 //#define DEBUG_DECISION
45 //#define DEBUG_ACTIONSTEPS
46 //#define DEBUG_STATE
47 //#define DEBUG_MANEUVER
48 //#define DEBUG_SURROUNDING
49 //#define DEBUG_CHANGE_OPPOSITE
50 
51 // ===========================================================================
52 // member method definitions
53 // ===========================================================================
54 MSLaneChangerSublane::MSLaneChangerSublane(const std::vector<MSLane*>* lanes, bool allowChanging) :
55  MSLaneChanger(lanes, allowChanging) {
56  // initialize siblings
57  if (myChanger.front().lane->isInternal()) {
58  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
59  for (ChangerIt ce2 = myChanger.begin(); ce2 != myChanger.end(); ++ce2) {
60  if (ce != ce2 && ce->lane->getIncomingLanes().front().lane == ce2->lane->getIncomingLanes().front().lane) {
61  //std::cout << "addSibling lane=" << ce->lane->getID() << " offset=" << ce2->lane->getIndex() - ce->lane->getIndex() << "\n";
62  ce->siblings.push_back(ce2->lane->getIndex() - ce->lane->getIndex());
63  }
64  }
65  }
66  }
67 }
68 
69 
71 
72 void
75  // Prepare myChanger with a safe state.
76  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
77  ce->ahead = ce->lane->getPartialBeyond();
78 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
79 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles=" << toString(ce->lane->myPartialVehicles) << "\n";
80 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles beyond=" << toString(ce->ahead.toString()) << "\n";
81  }
82 }
83 
84 
85 
86 void
88  MSLaneChanger::updateChanger(vehHasChanged);
89  if (!vehHasChanged) {
90  MSVehicle* lead = myCandi->lead;
91  //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
92  myCandi->ahead.addLeader(lead, false, 0);
93  MSLane* shadowLane = lead->getLaneChangeModel().getShadowLane();
94  if (shadowLane != nullptr && &shadowLane->getEdge() == &lead->getLane()->getEdge()) {
95  assert(shadowLane->getIndex() < (int)myChanger.size());
96  const double latOffset = lead->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
97  //std::cout << SIMTIME << " updateChanger shadowLane=" << shadowLane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
98  (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(lead, false, latOffset);
99  }
100  }
101  //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(myCandi->lead) << " ahead=" << myCandi->ahead.toString() << " vehHasChanged=" << vehHasChanged << "\n";
102  //for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
103  // std::cout << " lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
104  //}
105 }
106 
107 
108 bool
110  // variant of change() for the sublane case
112  MSVehicle* vehicle = veh(myCandi);
113  vehicle->getLaneChangeModel().clearNeighbors();
114 #ifdef DEBUG_ACTIONSTEPS
115  if (DEBUG_COND) {
116  std::cout << "\n" << SIMTIME << " CHANGE veh=" << vehicle->getID() << " lane=" << vehicle->getLane()->getID() << "\n";
117  }
118 #endif
119  assert(vehicle->getLane() == (*myCandi).lane);
120  assert(!vehicle->getLaneChangeModel().isChangingLanes());
121  if ( vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
122  registerUnchanged(vehicle);
123  return false;
124  }
125  if (!vehicle->isActive()) {
126 #ifdef DEBUG_ACTIONSTEPS
127  if (DEBUG_COND) {
128  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
129  }
130 #endif
131 
132  bool changed;
133  // let TraCI influence the wish to change lanes during non-actionsteps
134  checkTraCICommands(vehicle);
135 
136  // Resume change
137  changed = continueChangeSublane(vehicle, myCandi);
138 #ifdef DEBUG_ACTIONSTEPS
139  if (DEBUG_COND) {
140  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' lcm->maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
141  << " lcm->speedLat=" << vehicle->getLaneChangeModel().getSpeedLat() << std::endl;
142  }
143 #endif
144  if (!changed) {
145  registerUnchanged(vehicle);
146  }
147  return changed;
148  }
149 
150 #ifdef DEBUG_ACTIONSTEPS
151  if (DEBUG_COND) {
152  std::cout << "\n" << SIMTIME << " veh '" << vehicle->getID() << "' plans lanechange maneuver." << std::endl;
153  }
154 #endif
155  vehicle->updateBestLanes(); // needed?
156  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
157  if (!isOpposite) {
158  for (int i = 0; i < (int) myChanger.size(); ++i) {
159  vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
160  }
161  }
162  // update leaders beyond the current edge for all lanes
163  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
164  ce->aheadNext = getLeaders(ce, vehicle);
165  }
166  // update expected speeds
167  int sublaneIndex = 0;
168  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
169  vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ce->aheadNext, sublaneIndex, ce->lane->getIndex());
170  for (int offset : ce->siblings) {
171  // treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
172  ChangerIt ceSib = ce + offset;
173  vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ceSib->aheadNext, sublaneIndex, ceSib->lane->getIndex());
174  }
175  sublaneIndex += ce->ahead.numSublanes();
176  }
177 
178  // Check for changes to the opposite lane if vehicle is active
179 #ifdef DEBUG_ACTIONSTEPS
180  if (DEBUG_COND) {
181  std::cout << " myChangeToOpposite=" << myChangeToOpposite << " isOpposite=" << isOpposite << " mayChangeRight=" << mayChange(-1) << " mayChangeLeft=" << mayChange(1) << "\n";
182  }
183 #endif
184 
185  const bool stopOpposite = hasOppositeStop(vehicle);
186  const int traciState = vehicle->influenceChangeDecision(0);
187  const bool traciRequestOpposite = !mayChange(1) && (traciState & LCA_LEFT) != 0;
188 
189  if (myChangeToOpposite && (
190  // cannot overtake since there is only one usable lane (or emergency)
191  ((!mayChange(-1) && !mayChange(1)) || vehicle->getVClass() == SVC_EMERGENCY)
192  || traciRequestOpposite
193  || stopOpposite
194  // can alway come back from the opposite side
195  || isOpposite)) {
196  const MSLeaderDistanceInfo& leaders = myCandi->aheadNext;
197  if (leaders.hasVehicles() || isOpposite || stopOpposite || traciRequestOpposite) {
198  std::pair<MSVehicle*, double> leader = findClosestLeader(leaders, vehicle);
199  myCheckedChangeOpposite = false;
200  if ((leader.first != nullptr || isOpposite || stopOpposite || traciRequestOpposite)
201  && changeOpposite(vehicle, leader)) {
202  return true;
203  } else if (myCheckedChangeOpposite) {
204  registerUnchanged(vehicle);
205  return false;
206  }
207  // try sublane change within current lane otherwise
208  }
209  }
210 
212  | (mayChange(1) ? LCA_LEFT : LCA_NONE));
213 
214  StateAndDist right = checkChangeHelper(vehicle, -1, alternatives);
215  StateAndDist left = checkChangeHelper(vehicle, 1, alternatives);
216  StateAndDist current = checkChangeHelper(vehicle, 0, alternatives);
217 
218  StateAndDist decision = vehicle->getLaneChangeModel().decideDirection(current,
219  vehicle->getLaneChangeModel().decideDirection(right, left));
220 #ifdef DEBUG_DECISION
221  if (vehicle->getLaneChangeModel().debugVehicle()) {
222  std::cout << "\n" << SIMTIME << " decision=" << toString((LaneChangeAction)decision.state) << " dir=" << decision.dir << " latDist=" << decision.latDist << " maneuverDist=" << decision.maneuverDist << "\n";
223  }
224 #endif
225  vehicle->getLaneChangeModel().setOwnState(decision.state);
226  if ((decision.state & LCA_WANTS_LANECHANGE) != 0 && (decision.state & LCA_BLOCKED) == 0) {
227  // change if the vehicle wants to and is allowed to change
228 #ifdef DEBUG_MANEUVER
229  if (DEBUG_COND) {
230  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' performing sublane change..." << std::endl;
231  }
232 #endif
233  const bool changed = startChangeSublane(vehicle, myCandi, decision.latDist, decision.maneuverDist);
234  if (!changed) {
235  registerUnchanged(vehicle);
236  }
237  return changed;
238  }
239  // @note this assumes vehicles can instantly abort any maneuvre in case of emergency
240  abortLCManeuver(vehicle);
241  registerUnchanged(vehicle);
242 
243  if ((right.state & (LCA_URGENT)) != 0 && (left.state & (LCA_URGENT)) != 0) {
244  // ... wants to go to the left AND to the right
245  // just let them go to the right lane...
246  left.state = 0;
247  }
248  return false;
249 }
250 
251 
252 void
254 #ifdef DEBUG_MANEUVER
255  if (DEBUG_COND) {
256  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' aborts LC-continuation."
257  << std::endl;
258  }
259 #endif
260  const int priorReason = vehicle->getLaneChangeModel().getPrevState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
261  const int reason = vehicle->getLaneChangeModel().getOwnState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
262  if (priorReason != 0 && priorReason != reason && vehicle->getLaneChangeModel().getPreviousManeuverDist() != 0) {
263  // original from cannot be reconstructed
264  const int priorDirection = vehicle->getLaneChangeModel().getPreviousManeuverDist() > 0 ? 1 : -1;
265 #ifdef DEBUG_MANEUVER
266  if (DEBUG_COND) {
267  std::cout << SIMTIME << " abortLCManeuver priorReason=" << toString((LaneChangeAction)priorReason)
268  << " reason=" << toString((LaneChangeAction)reason) << " veh=" << vehicle->getID() << "\n";
269  }
270 #endif
271  outputLCEnded(vehicle, myCandi, myCandi, priorDirection);
272  }
273  vehicle->getLaneChangeModel().setSpeedLat(0);
274  vehicle->getLaneChangeModel().setManeuverDist(0.);
276 }
277 
278 
280 MSLaneChangerSublane::checkChangeHelper(MSVehicle* vehicle, int laneOffset, LaneChangeAction alternatives) {
281  StateAndDist result = StateAndDist(0, 0, 0, 0);
282  if (mayChange(laneOffset)) {
283  if (laneOffset != 0 && vehicle->getLaneChangeModel().isOpposite()) {
284  return result;
285  }
286  const std::vector<MSVehicle::LaneQ>& preb = (vehicle->getLaneChangeModel().isOpposite()
287  ? getBestLanesOpposite(vehicle, nullptr, 1000)
288  : vehicle->getBestLanes());
289  result.state = checkChangeSublane(laneOffset, alternatives, preb, result.latDist, result.maneuverDist);
290  result.dir = laneOffset;
291  if ((result.state & LCA_WANTS_LANECHANGE) != 0 && (result.state & LCA_URGENT) != 0 && (result.state & LCA_BLOCKED) != 0) {
292  (myCandi + laneOffset)->lastBlocked = vehicle;
293  if ((myCandi + laneOffset)->firstBlocked == nullptr) {
294  (myCandi + laneOffset)->firstBlocked = vehicle;
295  }
296  }
297  }
298  return result;
299 }
300 
301 
303 // (used to continue sublane changing in non-action steps).
304 bool
306  // lateral distance to complete maneuver
307  double remLatDist = vehicle->getLaneChangeModel().getManeuverDist();
308  if (remLatDist == 0) {
309  return false;
310  }
311  const bool urgent = (vehicle->getLaneChangeModel().getOwnState() & LCA_URGENT) != 0;
312  const double nextLatDist = SPEED2DIST(vehicle->getLaneChangeModel().computeSpeedLat(remLatDist, remLatDist, urgent));
313 #ifdef DEBUG_MANEUVER
314  if (DEBUG_COND) {
315  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' continueChangeSublane()"
316  << " remLatDist=" << remLatDist << " nextLatDist=" << nextLatDist
317  << std::endl;
318  }
319 #endif
320 
321  const bool changed = startChangeSublane(vehicle, from, nextLatDist, remLatDist);
322  return changed;
323 }
324 
325 
326 bool
327 MSLaneChangerSublane::startChangeSublane(MSVehicle* vehicle, ChangerIt& from, double latDist, double maneuverDist) {
328  if (vehicle->isRemoteControlled()) {
329  return false;
330  }
331  MSLane* source = from->lane;
332  // Prevent continuation of LC beyond lane borders if change is not allowed
333  double distToRightLaneBorder = vehicle->getLane()->getWidth() * 0.5 + vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5;
334  double distToLeftLaneBorder = vehicle->getLane()->getWidth() * 0.5 - vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5;
335  if (vehicle->getLaneChangeModel().isOpposite()) {
336  std::swap(distToRightLaneBorder, distToLeftLaneBorder);
337  }
338  // determine direction of LC
339  int direction = 0;
340  if (latDist > 0 && latDist > distToLeftLaneBorder) {
341  direction = 1;
342  } else if (latDist < 0 && -latDist > distToRightLaneBorder) {
343  direction = -1;
344  }
345  const int changerDirection = vehicle->getLaneChangeModel().isOpposite() ? -direction : direction;
346  ChangerIt to = from;
347 #ifdef DEBUG_MANEUVER
348  if (DEBUG_COND) {
349  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' latDist=" << latDist << " maneuverDist=" << maneuverDist
350  << " distRight=" << distToRightLaneBorder << " distLeft=" << distToLeftLaneBorder
351  << " dir=" << direction << " cDir=" << changerDirection << " mayChange=" << mayChange(changerDirection) << "\n";
352  }
353 #endif
354  if (mayChange(changerDirection)) {
355  to = from + changerDirection;
356  } else if (changerDirection == 1 && source->getOpposite() != nullptr) {
357  // change to the opposite direction lane
358  to = (source->getOpposite()->getEdge().myLaneChanger->getChanger().end() - 1);
359  } else {
360  // This may occur during maneuver continuation in non-actionsteps.
361  // TODO: Understand better why and test later if additional sublane actionstep debugging resolves this
362  // (XXX: perhaps one should try to extrapolate check for this case before to avoid maneuver initialization
363  // similar as for continuous LC in MSLaneChanger::checkChange())
364  //assert(false);
365  abortLCManeuver(vehicle);
366  return false;
367  }
368 
369  // The following does:
370  // 1) update vehicles lateral position according to latDist and target lane
371  // 2) distinguish several cases
372  // a) vehicle moves completely within the same lane
373  // b) vehicle intersects another lane
374  // - vehicle must be moved to the lane where it's midpoint is (either old or new)
375  // - shadow vehicle must be created/moved to the other lane if the vehicle intersects it
376  // 3) updated dens of all lanes that hold the vehicle or its shadow
377 
378  vehicle->myState.myPosLat += latDist * (vehicle->getLaneChangeModel().isOpposite() ? -1 : 1);
380  vehicle->getLaneChangeModel().setSpeedLat(DIST2SPEED(latDist));
381 #ifdef DEBUG_MANEUVER
382  if (DEBUG_COND) {
383  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' with maneuverDist=" << maneuverDist
384  << " and committedSpeed=" << vehicle->getLaneChangeModel().getCommittedSpeed()
385  << " increments lateral position by latDist=" << latDist << std::endl;
386  }
387 #endif
388 #ifdef DEBUG_SURROUNDING
389  if (DEBUG_COND) {
390  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "'\n to->ahead=" << to->ahead.toString()
391  << "'\n to->aheadNext=" << to->aheadNext.toString()
392  << std::endl;
393  }
394 #endif
395  const bool completedPriorManeuver = fabs(vehicle->getLaneChangeModel().getPreviousManeuverDist()) < NUMERICAL_EPS;
396  const bool completedManeuver = fabs(maneuverDist - latDist) < NUMERICAL_EPS;
397  vehicle->getLaneChangeModel().updateSafeLatDist(latDist);
398 
399  // current maneuver is aborted when direction or reason changes
400  const int priorReason = vehicle->getLaneChangeModel().getPrevState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
401  const int reason = vehicle->getLaneChangeModel().getOwnState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
402 #ifdef DEBUG_MANEUVER
403  if (DEBUG_COND) {
404  std::cout << SIMTIME << " vehicle '" << vehicle->getID()
405  << "' completedPriorManeuver=" << completedPriorManeuver
406  << " completedManeuver=" << completedManeuver
407  << " priorReason=" << toString((LaneChangeAction)priorReason)
408  << " reason=" << toString((LaneChangeAction)reason)
409  << " priorManeuverDist=" << vehicle->getLaneChangeModel().getPreviousManeuverDist()
410  << " maneuverDist=" << maneuverDist
411  << " latDist=" << latDist
412  << std::endl;
413  }
414 #endif
415  if (!completedManeuver && !completedPriorManeuver && priorReason != 0 &&
416  (vehicle->getLaneChangeModel().getPreviousManeuverDist() * latDist < 0
417  || priorReason != reason)) {
418  const int priorDirection = vehicle->getLaneChangeModel().getPreviousManeuverDist() > 0 ? 1 : -1;
419  // original from cannot be reconstructed
420 #ifdef DEBUG_MANEUVER
421  if (DEBUG_COND) {
422  std::cout << SIMTIME << " startChangeSublane abort priorReason=" << toString((LaneChangeAction)priorReason)
423  << " reason=" << toString((LaneChangeAction)reason) << " veh=" << vehicle->getID() << "\n";
424  }
425 #endif
426  outputLCEnded(vehicle, from, from, priorDirection);
427  }
428 
429  outputLCStarted(vehicle, from, to, direction, maneuverDist);
430  vehicle->getLaneChangeModel().setManeuverDist(maneuverDist - latDist);
431  const bool changedToNewLane = checkChangeToNewLane(vehicle, direction, from, to);
432 
433  MSLane* oldShadowLane = vehicle->getLaneChangeModel().getShadowLane();
435  MSLane* shadowLane = vehicle->getLaneChangeModel().getShadowLane();
436  if (shadowLane != nullptr && shadowLane != oldShadowLane
437  && &shadowLane->getEdge() == &source->getEdge()) {
438  assert(oldShadowLane == 0 || vehicle->getLaneChangeModel().isOpposite() || to != from);
439  const double latOffset = vehicle->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
440  (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(vehicle, false, latOffset);
441  }
442  if (completedManeuver) {
443  outputLCEnded(vehicle, from, to, direction);
444  }
445 
446  // Update maneuver reservations on target lanes
447  MSLane* targetLane = vehicle->getLaneChangeModel().updateTargetLane();
448  if (!changedToNewLane && targetLane != nullptr
449  && vehicle->getActionStepLength() > DELTA_T
450  && &targetLane->getEdge() == &source->getEdge()
451  ) {
452  const int dir = (vehicle->getLaneChangeModel().getManeuverDist() > 0 ? 1 : -1);
453  ChangerIt target = from + dir;
454  const double actionStepDist = dir * vehicle->getVehicleType().getMaxSpeedLat() * vehicle->getActionStepLengthSecs();
455  const double latOffset = vehicle->getLatOffset(targetLane) + actionStepDist;
456  target->ahead.addLeader(vehicle, false, latOffset);
457  //std::cout << SIMTIME << " veh=" << vehicle->getID() << " target=" << targetLane->getID()
458  // << " actionStepDist=" << actionStepDist << " latOffset=" << latOffset
459  // << " targetAhead=" << target->ahead.toString() << "\n";
460  }
461 
462  // compute new angle of the vehicle from the x- and y-distances travelled within last time step
463  // (should happen last because primaryLaneChanged() also triggers angle computation)
464  // this part of the angle comes from the orientation of our current lane
465  double laneAngle = vehicle->getLane()->getShape().rotationAtOffset(vehicle->getLane()->interpolateLanePosToGeometryPos(vehicle->getPositionOnLane())) ;
466  if (vehicle->getLane()->getShape().length2D() == 0) {
467  if (vehicle->getFurtherLanes().size() == 0) {
468  laneAngle = vehicle->getAngle();
469  } else {
470  laneAngle = vehicle->getFurtherLanes().front()->getShape().rotationAtOffset(-NUMERICAL_EPS);
471  }
472  }
473  // this part of the angle comes from the vehicle's lateral movement
474  double changeAngle = 0;
475  // avoid flicker
476  if (fabs(latDist) > NUMERICAL_EPS) {
477  // angle is between vehicle front and vehicle back (and depending on travelled distance)
478  changeAngle = atan2(DIST2SPEED(latDist), vehicle->getVehicleType().getLength() + vehicle->getSpeed());
479  if (MSGlobals::gLefthand) {
480  changeAngle *= -1;
481  }
482  }
483  if (vehicle->getLaneChangeModel().isOpposite()) {
484  // reverse lane angle
485  laneAngle += M_PI;
486  }
487 #ifdef DEBUG_MANEUVER
488  if (DEBUG_COND) {
489  std::cout << SIMTIME << " startChangeSublane"
490  << " oldLane=" << from->lane->getID()
491  << " newLane=" << to->lane->getID()
492  << " shadowLane=" << (shadowLane != nullptr ? shadowLane->getID() : "NULL")
493  << " targetLane=" << (targetLane != nullptr ? targetLane->getID() : "NULL")
494  << " maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
495  << " latDist=" << latDist
496  << " oldShadowLane=" << Named::getIDSecure(oldShadowLane)
497  << " newShadowLane=" << Named::getIDSecure(vehicle->getLaneChangeModel().getShadowLane())
498  << " laneA=" << RAD2DEG(laneAngle)
499  << " changeA=" << RAD2DEG(changeAngle)
500  << " oldA=" << RAD2DEG(vehicle->getAngle())
501  << " newA=" << RAD2DEG(laneAngle + changeAngle)
502  << " oppposite=" << vehicle->getLaneChangeModel().isOpposite()
503  << " changedToNewLane=" << changedToNewLane
504  << "\n";
505  }
506 #endif
507  vehicle->setAngle(laneAngle + changeAngle, completedManeuver);
508 
509  // check if a traci maneuver must continue
510  // getOwnState is reset to 0 when changing lanes so we use the stored reason
511  if ((reason & LCA_TRACI) != 0) {
512 #ifdef DEBUG_MANEUVER
513  if (DEBUG_COND) {
514  std::cout << SIMTIME << " continue TraCI-maneuver remainingLatDist=" << vehicle->getLaneChangeModel().getManeuverDist() << "\n";
515  }
516 #endif
518  }
519  from->lane->requireCollisionCheck();
520  to->lane->requireCollisionCheck();
521  return changedToNewLane;
522 }
523 
524 bool
526  const int oppositeSign = vehicle->getLaneChangeModel().isOpposite() ? -1 : 1;
527  const bool opposite = (&from->lane->getEdge() != &to->lane->getEdge());
528  const bool changedToNewLane = (to->lane != from->lane
529  && fabs(vehicle->getLateralPositionOnLane()) > 0.5 * vehicle->getLane()->getWidth()
530  && (mayChange(direction * oppositeSign) || opposite));
531  if (changedToNewLane) {
532  vehicle->myState.myPosLat -= direction * 0.5 * (from->lane->getWidth() + to->lane->getWidth()) * oppositeSign;
533  if (!opposite) {
534  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
535  to->dens += vehicle->getVehicleType().getLengthWithGap();
536  }
538  if (!vehicle->isActive()) {
539  // update leaders beyond the current edge for all lanes
540  // @note to->aheadNext and from->aheadNext are only needed for output in non-action steps.
541  to->aheadNext = getLeaders(to, vehicle);
542  from->aheadNext = getLeaders(from, vehicle);
543  }
544  vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
545  vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
546  vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
547  }
548  vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
549  if (!opposite) {
550  to->ahead.addLeader(vehicle, false, 0);
551  }
552  } else {
553  from->ahead.addLeader(vehicle, false, 0);
554  }
555  return changedToNewLane;
556 }
557 
558 void
559 MSLaneChangerSublane::outputLCStarted(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction, double maneuverDist) {
561  // non-sublane change started
562  && ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)
563  && ((vehicle->getLaneChangeModel().getOwnState() & LCA_STAY) == 0)
564  // no changing for the same reason in previous step (either not wanted or blocked)
567  || ((vehicle->getLaneChangeModel().getPrevState() & LCA_STAY) != 0)
568  || ((vehicle->getLaneChangeModel().getPrevState() & LCA_BLOCKED) != 0))
569  ) {
570 #ifdef DEBUG_STATE
571  if (DEBUG_COND) {
572  std::cout << SIMTIME << " veh=" << vehicle->getID() << " laneChangeStarted state=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getOwnState())
573  << " prevState=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getPrevState())
575  << " filtered=" << toString((LaneChangeAction)(vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)))
576  << "\n";
577  }
578 #endif
579  vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
580  vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
581  vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
582  vehicle->getLaneChangeModel().laneChangeOutput("changeStarted", from->lane, to->lane, direction, maneuverDist);
583  }
584 }
585 
586 void
587 MSLaneChangerSublane::outputLCEnded(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction) {
589  // non-sublane change ended
590  && ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)) {
591  vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
592  vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
593  vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
594  vehicle->getLaneChangeModel().laneChangeOutput("changeEnded", from->lane, to->lane, direction);
595  }
596 }
597 
598 
600 MSLaneChangerSublane::getLeaders(const ChangerIt& target, const MSVehicle* vehicle) const {
601  // get the leading vehicle on the lane to change to
602 #ifdef DEBUG_SURROUNDING
603  if (DEBUG_COND) {
604  std::cout << SIMTIME << " getLeaders lane=" << target->lane->getID() << " ego=" << vehicle->getID() << " ahead=" << target->ahead.toString() << "\n";
605  }
606 #endif
607  MSLeaderDistanceInfo result(target->lane, nullptr, 0);
608  for (int i = 0; i < target->ahead.numSublanes(); ++i) {
609  const MSVehicle* veh = target->ahead[i];
610  if (veh != nullptr) {
611  const double gap = veh->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
612 #ifdef DEBUG_SURROUNDING
613  if (DEBUG_COND) {
614  std::cout << " ahead lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane() << " gap=" << gap << "\n";
615  }
616 #endif
617  result.addLeader(veh, gap, 0, i);
618  }
619  }
620  target->lane->addLeaders(vehicle, vehicle->getPositionOnLane(), result);
621  return result;
622 }
623 
624 
625 int
627  int laneOffset,
628  LaneChangeAction alternatives,
629  const std::vector<MSVehicle::LaneQ>& preb,
630  double& latDist,
631  double& maneuverDist) const {
632 
633  ChangerIt target = myCandi + laneOffset;
634  MSVehicle* vehicle = veh(myCandi);
635  const MSLane& neighLane = *(target->lane);
636  int blocked = 0;
637 
638  MSLeaderDistanceInfo neighLeaders = target->aheadNext;
639  MSLeaderDistanceInfo neighFollowers = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
640  MSLeaderDistanceInfo neighBlockers(&neighLane, vehicle, vehicle->getLane()->getRightSideOnEdge() - neighLane.getRightSideOnEdge());
641  MSLeaderDistanceInfo leaders = myCandi->aheadNext;
642  MSLeaderDistanceInfo followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
643  MSLeaderDistanceInfo blockers(vehicle->getLane(), vehicle, 0);
644 
645 #ifdef DEBUG_SURROUNDING
646  if (DEBUG_COND) std::cout << SIMTIME
647  << " checkChangeSublane: veh=" << vehicle->getID()
648  << " laneOffset=" << laneOffset
649  << "\n leaders=" << leaders.toString()
650  << "\n neighLeaders=" << neighLeaders.toString()
651  << "\n followers=" << followers.toString()
652  << "\n neighFollowers=" << neighFollowers.toString()
653  << "\n";
654 #endif
655 
656 
657  const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
658  laneOffset, alternatives,
659  leaders, followers, blockers,
660  neighLeaders, neighFollowers, neighBlockers,
661  neighLane, preb,
662  &(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, maneuverDist, blocked);
663  int state = blocked | wish;
664 
665  // XXX
666  // do are more careful (but expensive) check to ensure that a
667  // safety-critical leader is not being overlooked
668 
669  // XXX
670  // ensure that a continuous lane change manoeuvre can be completed
671  // before the next turning movement
672 
673  // let TraCI influence the wish to change lanes and the security to take
674  const int oldstate = state;
675  state = vehicle->influenceChangeDecision(state);
676 #ifdef DEBUG_STATE
677  if (DEBUG_COND && state != oldstate) {
678  std::cout << SIMTIME << " veh=" << vehicle->getID() << " stateAfterTraCI=" << toString((LaneChangeAction)state) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
679  }
680 #endif
681  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
682  if (laneOffset != 0) {
683  vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollowers, neighLeaders);
684  }
685  return state;
686 }
687 
688 
689 bool
691  MSVehicle* vehicle,
692  int laneOffset,
693  MSLane* targetLane,
694  const std::pair<MSVehicle* const, double>& leader,
695  const std::pair<MSVehicle* const, double>& neighLead,
696  const std::pair<MSVehicle* const, double>& neighFollow,
697  const std::vector<MSVehicle::LaneQ>& preb) {
699 
700  UNUSED_PARAMETER(leader);
701  UNUSED_PARAMETER(neighLead);
702  UNUSED_PARAMETER(neighFollow);
703 
704  const MSLane& neighLane = *targetLane;
705  MSLane* curLane = myCandi->lane;
706 
707  MSLeaderDistanceInfo neighLeaders(targetLane, nullptr, 0);
708  MSLeaderDistanceInfo neighFollowers(targetLane, nullptr, 0);
709  MSLeaderDistanceInfo neighBlockers(targetLane, nullptr, 0);
710  MSLeaderDistanceInfo leaders(curLane, nullptr, 0);
711  MSLeaderDistanceInfo followers(curLane, nullptr, 0);
712  MSLeaderDistanceInfo blockers(curLane, nullptr, 0);
713 
714  const double backPosOnTarget = vehicle->getLane()->getOppositePos(vehicle->getBackPositionOnLane());
715  if (vehicle->getLaneChangeModel().isOpposite()) {
716  leaders = curLane->getFollowersOnConsecutive(vehicle, vehicle->getPositionOnLane(), true);
717  leaders.fixOppositeGaps(false);
718  curLane->addLeaders(vehicle, vehicle->getBackPositionOnLane(), followers);
719  followers.fixOppositeGaps(true);
720  const double posOnTarget = backPosOnTarget + vehicle->getVehicleType().getLength() + POSITION_EPS;
721  neighFollowers = targetLane->getFollowersOnConsecutive(vehicle, backPosOnTarget, true);
722  targetLane->addLeaders(vehicle, posOnTarget, neighLeaders);
723  int sublaneIndex = 0;
724  for (int i = 0; i < targetLane->getIndex(); i++) {
725  sublaneIndex += MSLeaderInfo(targetLane->getEdge().getLanes()[i]).numSublanes();
726  }
727  vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(neighLeaders, sublaneIndex, targetLane->getIndex());
728  } else {
729  leaders = myCandi->aheadNext;
730  followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
731  const double posOnTarget = backPosOnTarget - vehicle->getVehicleType().getLength();
732  targetLane->addLeaders(vehicle, backPosOnTarget, neighFollowers, true);
733  neighFollowers.fixOppositeGaps(true);
734  neighLeaders = targetLane->getFollowersOnConsecutive(vehicle, posOnTarget, true);
735  neighLeaders.fixOppositeGaps(false);
736  }
737 
738 
739 #ifdef DEBUG_CHANGE_OPPOSITE
740  if (DEBUG_COND) std::cout << SIMTIME
741  << " checkChangeOppositeSublane: veh=" << vehicle->getID()
742  << " isOpposite=" << vehicle->getLaneChangeModel().isOpposite()
743  << " laneOffset=" << laneOffset
744  << "\n leaders=" << leaders.toString()
745  << "\n neighLeaders=" << neighLeaders.toString()
746  << "\n followers=" << followers.toString()
747  << "\n neighFollowers=" << neighFollowers.toString()
748  << "\n";
749 #endif
750 
752  | (mayChange(1) ? LCA_LEFT : LCA_NONE));
753 
754  int blocked = 0;
755  double latDist = 0;
756  double maneuverDist = 0;
757  const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
758  laneOffset, alternatives,
759  leaders, followers, blockers,
760  neighLeaders, neighFollowers, neighBlockers,
761  neighLane, preb,
762  &(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, maneuverDist, blocked);
763  int state = blocked | wish;
764 
765  const int oldstate = state;
766  state = vehicle->influenceChangeDecision(state);
767 #ifdef DEBUG_CHANGE_OPPOSITE
768  if (DEBUG_COND && state != oldstate) {
769  std::cout << SIMTIME << " veh=" << vehicle->getID() << " stateAfterTraCI=" << toString((LaneChangeAction)state) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
770  }
771 #endif
772  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
773  if (laneOffset != 0) {
774  vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollowers, neighLeaders);
775  }
776 
777  if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) == 0) {
778  // change if the vehicle wants to and is allowed to change
779 #ifdef DEBUG_CHANGE_OPPOSITE
780  if (DEBUG_COND) {
781  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' performing sublane change latDist=" << latDist << " maneuverDist=" << maneuverDist << "\n";
782  }
783 #endif
784  vehicle->getLaneChangeModel().setOwnState(state);
785  return startChangeSublane(vehicle, myCandi, latDist, maneuverDist);
786  } else {
787  vehicle->getLaneChangeModel().setSpeedLat(0);
788  return false;
789  }
790 }
791 
792 std::pair<MSVehicle*, double>
794  const double egoWidth = vehicle->getVehicleType().getWidth() + vehicle->getVehicleType().getMinGapLat();
795  std::pair<MSVehicle*, double> leader(nullptr, std::numeric_limits<double>::max());
796  for (int i = 0; i < leaders.numSublanes(); ++i) {
797  CLeaderDist cand = leaders[i];
798  if (cand.first != nullptr) {
799  const double rightSide = cand.first->getRightSideOnLane();
800  if (cand.second < leader.second
801  && rightSide < egoWidth
802  && vehicle->getLane()->getWidth() - rightSide - cand.first->getVehicleType().getWidth() < egoWidth) {
803  leader.first = const_cast<MSVehicle*>(cand.first);
804  leader.second = cand.second;
805  }
806  }
807  }
808  return leader;
809 }
810 
811 /****************************************************************************/
#define RAD2DEG(x)
Definition: GeomHelper.h:36
#define DEBUG_COND
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:32
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
#define SPEED2DIST(x)
Definition: SUMOTime.h:43
#define SIMTIME
Definition: SUMOTime.h:60
#define DIST2SPEED(x)
Definition: SUMOTime.h:45
@ SVC_EMERGENCY
public emergency vehicles
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_BLOCKED
blocked in all directions
@ LCA_NONE
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_SUBLANE
used by the sublane model
@ LCA_LEFT
Wants go to the left.
@ LCA_CHANGE_REASONS
reasons of lane change
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void saveLCState(const int dir, const int stateWithoutTraCI, const int state)
void setFollowerGaps(CLeaderDist follower, double secGap)
virtual void setOwnState(const int state)
virtual double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
static bool outputLCEnded()
whether start of maneuvers shall be recorede
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model)
void laneChangeOutput(const std::string &tag, MSLane *source, MSLane *target, int direction, double maneuverDist=0)
called once the vehicle ends a lane change manoeuvre (non-instant)
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
static bool haveLCOutput()
whether lanechange-output is active
virtual void updateExpectedSublaneSpeeds(const MSLeaderDistanceInfo &ahead, int sublaneOffset, int laneIndex)
update expected speeds for each sublane of the current edge
void setLeaderGaps(CLeaderDist, double secGap)
void setOrigLeaderGaps(CLeaderDist, double secGap)
virtual int wantsChangeSublane(int laneOffset, LaneChangeAction alternatives, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked, double &latDist, double &targetDistLat, int &blocked)
void setManeuverDist(const double dist)
Updates the remaining distance for the current maneuver while it is continued within non-action steps...
void setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
virtual void updateSafeLatDist(const double travelledLatDist)
Updates the value of safe lateral distances (in SL2015) during maneuver continuation in non-action st...
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
virtual StateAndDist decideDirection(StateAndDist sd1, StateAndDist sd2) const
decide in which direction to move in case both directions are desirable
static bool outputLCStarted()
whether start of maneuvers shall be recorede
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
void clearNeighbors()
Clear info on neighboring vehicle from previous step.
void saveNeighbors(const int dir, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &leaders)
Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direct...
double getWidth() const
Returns the vehicle's width.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
MSLaneChanger * myLaneChanger
This member will do the lane-change.
Definition: MSEdge.h:861
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition: MSGlobals.h:157
Performs lane changing of vehicles.
Definition: MSLaneChanger.h:45
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
static bool hasOppositeStop(MSVehicle *vehicle)
whether vehicle has an opposite-direction stop within relevant range
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
virtual void initChanger()
Initialize the changer before looping over all vehicles.
Changer & getChanger()
return changer (only to be used by MSLaneChangerSublane from another instance)
MSVehicle * veh(ConstChangerIt ce) const
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
void registerUnchanged(MSVehicle *vehicle)
ChangerIt myCandi
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader)
static std::vector< MSVehicle::LaneQ > getBestLanesOpposite(MSVehicle *vehicle, const MSLane *stopLane, double oppositeLength)
add LaneQ for opposite lanes
virtual void updateChanger(bool vehHasChanged)
bool startChangeSublane(MSVehicle *vehicle, ChangerIt &from, double latDist, double maneuverDist)
change by the specified amount and return whether a new lane was entered
bool checkChangeToNewLane(MSVehicle *vehicle, const int direction, ChangerIt from, ChangerIt to)
check whether the given vehicle has entered the new lane 'to->lane' during a sublane LC-step
void outputLCStarted(MSVehicle *vehicle, ChangerIt &from, ChangerIt &to, int direction, double maneuverDist)
optional output for start of lane-change maneuvre
MSLeaderDistanceInfo getLeaders(const ChangerIt &target, const MSVehicle *ego) const
get leaders for ego on the given lane
StateAndDist checkChangeHelper(MSVehicle *vehicle, int laneOffset, LaneChangeAction alternatives)
helper function that calls checkChangeSublane and sets blocker information
static std::pair< MSVehicle *, double > findClosestLeader(const MSLeaderDistanceInfo &leaders, const MSVehicle *vehicle)
find the closest leader that prevents ego vehicle from passing on the current lane
bool myCheckedChangeOpposite
whether checkChangeOpposite was called for the current vehicle
virtual void initChanger()
Initialize the changer before looping over all vehicles.
bool checkChangeOpposite(MSVehicle *vehicle, int laneOffset, MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb)
virtual void updateChanger(bool vehHasChanged)
void abortLCManeuver(MSVehicle *vehicle)
immediately stop lane-changing and register vehicle as unchanged
MSLaneChangerSublane()
Default constructor.
void outputLCEnded(MSVehicle *vehicle, ChangerIt &from, ChangerIt &to, int direction)
optional output for end of lane-change maneuvre
MSAbstractLaneChangeModel::StateAndDist StateAndDist
int checkChangeSublane(int laneOffset, LaneChangeAction alternatives, const std::vector< MSVehicle::LaneQ > &preb, double &latDist, double &maneuverDist) const
check whether sub-lane changing in the given direction is desirable and possible
bool continueChangeSublane(MSVehicle *vehicle, ChangerIt &from)
Continue a sublane-lane change maneuver and return whether the midpoint was passed in this step.
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
void addLeaders(const MSVehicle *vehicle, double vehPos, MSLeaderDistanceInfo &result, bool oppositeDirection=false)
get leaders for ego on the given lane
Definition: MSLane.cpp:3571
double getRightSideOnEdge() const
Definition: MSLane.h:1094
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:563
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:3817
MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle *ego, double backOffset, bool allSublanes, double searchDist=-1, bool ignoreMinorLinks=false) const
return the sublane followers with the largest missing rear gap among all predecessor lanes (within di...
Definition: MSLane.cpp:3275
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:674
const PositionVector & getShape() const
Returns this lane's shape.
Definition: MSLane.h:478
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition: MSLane.cpp:3802
double interpolateLanePosToGeometryPos(double lanePos) const
Definition: MSLane.h:499
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:556
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:133
virtual std::string toString() const
print a debugging representation
void fixOppositeGaps(bool isFollower)
subtract vehicle length from all gaps if the leader vehicle is driving in the opposite direction
virtual int addLeader(const MSVehicle *veh, double gap, double latOffset=0, int sublane=-1)
int numSublanes() const
Definition: MSLeaderInfo.h:85
bool hasVehicles() const
Definition: MSLeaderInfo.h:93
void setSublaneChange(double latDist)
Sets a new sublane-change request.
Definition: MSVehicle.cpp:427
double myPosLat
the stored lateral position
Definition: MSVehicle.h:138
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:75
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:5069
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:792
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1477
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
Definition: MSVehicle.h:597
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5051
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition: MSVehicle.h:504
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:6424
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:6443
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:5678
void setAngle(double angle, bool straightenFurther=false)
Set a custom vehicle angle in rad, optionally updates furtherLanePosLat.
Definition: MSVehicle.cpp:1284
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition: MSVehicle.h:396
double getLatOffset(const MSLane *lane) const
Get the offset that that must be added to interpret myState.myPosLat for the given lane.
Definition: MSVehicle.cpp:5941
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
Definition: MSVehicle.h:496
Influencer & getInfluencer()
Definition: MSVehicle.cpp:6389
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:411
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:462
Position myCachedPosition
Definition: MSVehicle.h:1882
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:5063
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:372
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:552
double getAngle() const
Returns the vehicle's direction in radians.
Definition: MSVehicle.h:683
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1809
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getMinGapLat() const
Get the minimum lateral gap that vehicles of this type maintain.
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
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:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:293
double length2D() const
Returns the length.
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
#define M_PI
Definition: odrSpiral.cpp:40