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.dev/sumo
3 // Copyright (C) 2002-2024 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  ce->outsideBounds.clear();
79 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
80 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles=" << toString(ce->lane->myPartialVehicles) << "\n";
81 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles beyond=" << toString(ce->ahead.toString()) << "\n";
82  }
83 }
84 
85 
86 
87 void
89  MSLaneChanger::updateChanger(vehHasChanged);
90  if (!vehHasChanged) {
91  MSVehicle* lead = myCandi->lead;
92  //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(lead) << " lsol=" << lead->getLeftSideOnLane() << " rsol=" << lead->getRightSideOnLane() << "\n";
93  if (lead->getLeftSideOnLane() < 0 || lead->getRightSideOnLane() > myCandi->lane->getWidth()) {
94  myCandi->outsideBounds.push_back(lead);
95  } else {
96  myCandi->ahead.addLeader(lead, false, 0);
97  }
98  MSLane* shadowLane = lead->getLaneChangeModel().getShadowLane();
99  if (shadowLane != nullptr && &shadowLane->getEdge() == &lead->getLane()->getEdge()) {
100  assert(shadowLane->getIndex() < (int)myChanger.size());
101  const double latOffset = lead->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
102  //std::cout << SIMTIME << " updateChanger shadowLane=" << shadowLane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
103  (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(lead, false, latOffset);
104  }
105  }
106  //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(myCandi->lead) << " ahead=" << myCandi->ahead.toString() << " vehHasChanged=" << vehHasChanged << "\n";
107  //for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
108  // std::cout << " lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
109  //}
110 }
111 
112 
113 bool
115  // variant of change() for the sublane case
117  MSVehicle* vehicle = veh(myCandi);
118  vehicle->getLaneChangeModel().clearNeighbors();
119 #ifdef DEBUG_ACTIONSTEPS
120  if (DEBUG_COND) {
121  std::cout << "\n" << SIMTIME << " CHANGE veh=" << vehicle->getID() << " lane=" << vehicle->getLane()->getID() << "\n";
122  }
123 #endif
124  assert(vehicle->getLane() == (*myCandi).lane);
125  assert(!vehicle->getLaneChangeModel().isChangingLanes());
126  if ( vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
127  registerUnchanged(vehicle);
128  if (vehicle->isStoppedOnLane()) {
129  myCandi->lastStopped = vehicle;
130  }
131  return false;
132  }
133  if (!vehicle->isActive()) {
134 #ifdef DEBUG_ACTIONSTEPS
135  if (DEBUG_COND) {
136  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
137  }
138 #endif
139 
140  bool changed;
141  // let TraCI influence the wish to change lanes during non-actionsteps
142  checkTraCICommands(vehicle);
143 
144  // Resume change
145  changed = continueChangeSublane(vehicle, myCandi);
146 #ifdef DEBUG_ACTIONSTEPS
147  if (DEBUG_COND) {
148  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' lcm->maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
149  << " lcm->speedLat=" << vehicle->getLaneChangeModel().getSpeedLat() << std::endl;
150  }
151 #endif
152  if (!changed) {
153  registerUnchanged(vehicle);
154  }
155  return changed;
156  }
157 
158 #ifdef DEBUG_ACTIONSTEPS
159  if (DEBUG_COND) {
160  std::cout << "\n" << SIMTIME << " veh '" << vehicle->getID() << "' plans lanechange maneuver." << std::endl;
161  }
162 #endif
163  vehicle->updateBestLanes(); // needed?
164  const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
165  if (!isOpposite) {
166  for (int i = 0; i < (int) myChanger.size(); ++i) {
167  vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
168  }
169  }
170  // update leaders beyond the current edge for all lanes
171  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
172  ce->aheadNext = getLeaders(ce, vehicle);
173  }
174  // update expected speeds
175  int sublaneIndex = 0;
176  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
177  vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ce->aheadNext, sublaneIndex, ce->lane->getIndex());
178  for (int offset : ce->siblings) {
179  // treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
180  ChangerIt ceSib = ce + offset;
181  vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ceSib->aheadNext, sublaneIndex, ceSib->lane->getIndex());
182  }
183  sublaneIndex += ce->ahead.numSublanes();
184  }
185 
186  // Check for changes to the opposite lane if vehicle is active
187 #ifdef DEBUG_ACTIONSTEPS
188  if (DEBUG_COND) {
189  std::cout << " myChangeToOpposite=" << myChangeToOpposite << " isOpposite=" << isOpposite << " mayChangeRight=" << mayChange(-1) << " mayChangeLeft=" << mayChange(1) << "\n";
190  }
191 #endif
192 
193  const bool stopOpposite = hasOppositeStop(vehicle);
194  const int traciState = vehicle->influenceChangeDecision(0);
195  const bool traciRequestOpposite = !mayChange(1) && (traciState & LCA_LEFT) != 0;
196 
197  if (myChangeToOpposite && (
198  // cannot overtake since there is only one usable lane (or emergency)
199  ((!mayChange(-1) && !mayChange(1)) || vehicle->getVClass() == SVC_EMERGENCY)
200  || traciRequestOpposite
201  || stopOpposite
202  // can alway come back from the opposite side
203  || isOpposite)) {
204  const MSLeaderDistanceInfo& leaders = myCandi->aheadNext;
205  if (leaders.hasVehicles() || isOpposite || stopOpposite || traciRequestOpposite) {
206  std::pair<MSVehicle*, double> leader = findClosestLeader(leaders, vehicle);
207  myCheckedChangeOpposite = false;
208  if ((leader.first != nullptr || isOpposite || stopOpposite || traciRequestOpposite)
209  && changeOpposite(vehicle, leader, myCandi->lastStopped)) {
210  return true;
211  } else if (myCheckedChangeOpposite) {
212  registerUnchanged(vehicle);
213  return false;
214  }
215  // try sublane change within current lane otherwise
216  }
217  }
218 
220  | (mayChange(1) ? LCA_LEFT : LCA_NONE));
221 
222  StateAndDist right = checkChangeHelper(vehicle, -1, alternatives);
223  StateAndDist left = checkChangeHelper(vehicle, 1, alternatives);
224  StateAndDist current = checkChangeHelper(vehicle, 0, alternatives);
225 
226  StateAndDist decision = vehicle->getLaneChangeModel().decideDirection(current,
227  vehicle->getLaneChangeModel().decideDirection(right, left));
228 #ifdef DEBUG_DECISION
229  if (vehicle->getLaneChangeModel().debugVehicle()) {
230  std::cout << "\n" << SIMTIME << " decision=" << toString((LaneChangeAction)decision.state) << " dir=" << decision.dir << " latDist=" << decision.latDist << " maneuverDist=" << decision.maneuverDist << "\n";
231  }
232 #endif
233  vehicle->getLaneChangeModel().setOwnState(decision.state);
234  if ((decision.state & LCA_WANTS_LANECHANGE) != 0 && (decision.state & LCA_BLOCKED) == 0) {
235  // change if the vehicle wants to and is allowed to change
236 #ifdef DEBUG_MANEUVER
237  if (DEBUG_COND) {
238  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' performing sublane change..." << std::endl;
239  }
240 #endif
241  const bool changed = startChangeSublane(vehicle, myCandi, decision.latDist, decision.maneuverDist);
242  if (!changed) {
243  registerUnchanged(vehicle);
244  }
245  return changed;
246  }
247  // @note this assumes vehicles can instantly abort any maneuvre in case of emergency
248  abortLCManeuver(vehicle);
249  registerUnchanged(vehicle);
250 
251  if ((right.state & (LCA_URGENT)) != 0 && (left.state & (LCA_URGENT)) != 0) {
252  // ... wants to go to the left AND to the right
253  // just let them go to the right lane...
254  left.state = 0;
255  }
256  return false;
257 }
258 
259 
260 void
262 #ifdef DEBUG_MANEUVER
263  if (DEBUG_COND) {
264  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' aborts LC-continuation."
265  << std::endl;
266  }
267 #endif
268  const int priorReason = vehicle->getLaneChangeModel().getPrevState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
269  const int reason = vehicle->getLaneChangeModel().getOwnState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
270  if (priorReason != 0 && priorReason != reason && vehicle->getLaneChangeModel().getPreviousManeuverDist() != 0) {
271  // original from cannot be reconstructed
272  const int priorDirection = vehicle->getLaneChangeModel().getPreviousManeuverDist() > 0 ? 1 : -1;
273 #ifdef DEBUG_MANEUVER
274  if (DEBUG_COND) {
275  std::cout << SIMTIME << " abortLCManeuver priorReason=" << toString((LaneChangeAction)priorReason)
276  << " reason=" << toString((LaneChangeAction)reason) << " veh=" << vehicle->getID() << "\n";
277  }
278 #endif
279  outputLCEnded(vehicle, myCandi, myCandi, priorDirection);
280  }
281  const double updatedSpeedLat = vehicle->getLaneChangeModel().getSpeedLat() != 0;
282  vehicle->getLaneChangeModel().setSpeedLat(0);
283  vehicle->getLaneChangeModel().setManeuverDist(0.);
285  if (updatedSpeedLat) {
286  // update angle after having reset lateral speed
287  vehicle->setAngle(vehicle->computeAngle());
288  }
289 }
290 
291 
293 MSLaneChangerSublane::checkChangeHelper(MSVehicle* vehicle, int laneOffset, LaneChangeAction alternatives) {
294  StateAndDist result = StateAndDist(0, 0, 0, 0);
295  if (mayChange(laneOffset)) {
296  if (laneOffset != 0 && vehicle->getLaneChangeModel().isOpposite()) {
297  return result;
298  }
299  const std::vector<MSVehicle::LaneQ>& preb = (vehicle->getLaneChangeModel().isOpposite()
300  ? getBestLanesOpposite(vehicle, nullptr, 1000)
301  : vehicle->getBestLanes());
302  result.state = checkChangeSublane(laneOffset, alternatives, preb, result.latDist, result.maneuverDist);
303  result.dir = laneOffset;
304  if ((result.state & LCA_WANTS_LANECHANGE) != 0 && (result.state & LCA_URGENT) != 0 && (result.state & LCA_BLOCKED) != 0) {
305  (myCandi + laneOffset)->lastBlocked = vehicle;
306  if ((myCandi + laneOffset)->firstBlocked == nullptr) {
307  (myCandi + laneOffset)->firstBlocked = vehicle;
308  }
309  }
310  }
311  return result;
312 }
313 
314 
316 // (used to continue sublane changing in non-action steps).
317 bool
319  // lateral distance to complete maneuver
320  double remLatDist = vehicle->getLaneChangeModel().getManeuverDist();
321  if (remLatDist == 0) {
322  return false;
323  }
324  const bool urgent = (vehicle->getLaneChangeModel().getOwnState() & LCA_URGENT) != 0;
325  const double nextLatDist = SPEED2DIST(vehicle->getLaneChangeModel().computeSpeedLat(remLatDist, remLatDist, urgent));
326 #ifdef DEBUG_MANEUVER
327  if (DEBUG_COND) {
328  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' continueChangeSublane()"
329  << " remLatDist=" << remLatDist << " nextLatDist=" << nextLatDist
330  << std::endl;
331  }
332 #endif
333 
334  const bool changed = startChangeSublane(vehicle, from, nextLatDist, remLatDist);
335  return changed;
336 }
337 
338 
339 bool
340 MSLaneChangerSublane::startChangeSublane(MSVehicle* vehicle, ChangerIt& from, double latDist, double maneuverDist) {
341  if (vehicle->isRemoteControlled()) {
342  return false;
343  }
344  MSLane* source = from->lane;
345  // Prevent continuation of LC beyond lane borders if change is not allowed
346  double distToRightLaneBorder = vehicle->getLane()->getWidth() * 0.5 + vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5;
347  double distToLeftLaneBorder = vehicle->getLane()->getWidth() * 0.5 - vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5;
348  if (vehicle->getLaneChangeModel().isOpposite()) {
349  std::swap(distToRightLaneBorder, distToLeftLaneBorder);
350  }
351  // determine direction of LC
352  int direction = 0;
353  if (latDist > 0 && latDist > distToLeftLaneBorder) {
354  direction = 1;
355  } else if (latDist < 0 && -latDist > distToRightLaneBorder) {
356  direction = -1;
357  }
358  const int changerDirection = vehicle->getLaneChangeModel().isOpposite() ? -direction : direction;
359  ChangerIt to = from;
360 #ifdef DEBUG_MANEUVER
361  if (DEBUG_COND) {
362  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' latDist=" << latDist << " maneuverDist=" << maneuverDist
363  << " distRight=" << distToRightLaneBorder << " distLeft=" << distToLeftLaneBorder
364  << " dir=" << direction << " cDir=" << changerDirection << " mayChange=" << mayChange(changerDirection) << "\n";
365  }
366 #endif
367  if (mayChange(changerDirection)) {
368  to = from + changerDirection;
369  } else if (changerDirection == 1 && source->getOpposite() != nullptr) {
370  // change to the opposite direction lane
371  to = (source->getOpposite()->getEdge().myLaneChanger->getChanger().end() - 1);
372  } else {
373  // This may occur during maneuver continuation in non-actionsteps.
374  // TODO: Understand better why and test later if additional sublane actionstep debugging resolves this
375  // (XXX: perhaps one should try to extrapolate check for this case before to avoid maneuver initialization
376  // similar as for continuous LC in MSLaneChanger::checkChange())
377  //assert(false);
378  abortLCManeuver(vehicle);
379  return false;
380  }
381 
382  // The following does:
383  // 1) update vehicles lateral position according to latDist and target lane
384  // 2) distinguish several cases
385  // a) vehicle moves completely within the same lane
386  // b) vehicle intersects another lane
387  // - vehicle must be moved to the lane where its midpoint is (either old or new)
388  // - shadow vehicle must be created/moved to the other lane if the vehicle intersects it
389  // 3) updated dens of all lanes that hold the vehicle or its shadow
390 
391  vehicle->myState.myPosLat += latDist * (vehicle->getLaneChangeModel().isOpposite() ? -1 : 1);
392  for (int i = 0; i < (int)vehicle->myFurtherLanesPosLat.size(); i++) {
393  vehicle->myFurtherLanesPosLat[i] += latDist * (vehicle->getLaneChangeModel().isOpposite() ? -1 : 1);
394  }
396  vehicle->getLaneChangeModel().setSpeedLat(DIST2SPEED(latDist));
397 #ifdef DEBUG_MANEUVER
398  if (DEBUG_COND) {
399  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' with maneuverDist=" << maneuverDist
400  << " and committedSpeed=" << vehicle->getLaneChangeModel().getCommittedSpeed()
401  << " increments lateral position by latDist=" << latDist << std::endl;
402  }
403 #endif
404 #ifdef DEBUG_SURROUNDING
405  if (DEBUG_COND) {
406  std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "'\n to->ahead=" << to->ahead.toString()
407  << "'\n to->aheadNext=" << to->aheadNext.toString()
408  << std::endl;
409  }
410 #endif
411  const bool completedPriorManeuver = fabs(vehicle->getLaneChangeModel().getPreviousManeuverDist()) < NUMERICAL_EPS;
412  const bool completedManeuver = fabs(maneuverDist - latDist) < NUMERICAL_EPS;
413  vehicle->getLaneChangeModel().updateSafeLatDist(latDist);
414 
415  // current maneuver is aborted when direction or reason changes
416  const int priorReason = vehicle->getLaneChangeModel().getPrevState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
417  const int reason = vehicle->getLaneChangeModel().getOwnState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
418 #ifdef DEBUG_MANEUVER
419  if (DEBUG_COND) {
420  std::cout << SIMTIME << " vehicle '" << vehicle->getID()
421  << "' completedPriorManeuver=" << completedPriorManeuver
422  << " completedManeuver=" << completedManeuver
423  << " priorReason=" << toString((LaneChangeAction)priorReason)
424  << " reason=" << toString((LaneChangeAction)reason)
425  << " priorManeuverDist=" << vehicle->getLaneChangeModel().getPreviousManeuverDist()
426  << " maneuverDist=" << maneuverDist
427  << " latDist=" << latDist
428  << std::endl;
429  }
430 #endif
431  if (!completedManeuver && !completedPriorManeuver && priorReason != 0 &&
432  (vehicle->getLaneChangeModel().getPreviousManeuverDist() * latDist < 0
433  || priorReason != reason)) {
434  const int priorDirection = vehicle->getLaneChangeModel().getPreviousManeuverDist() > 0 ? 1 : -1;
435  // original from cannot be reconstructed
436 #ifdef DEBUG_MANEUVER
437  if (DEBUG_COND) {
438  std::cout << SIMTIME << " startChangeSublane abort priorReason=" << toString((LaneChangeAction)priorReason)
439  << " reason=" << toString((LaneChangeAction)reason) << " veh=" << vehicle->getID() << "\n";
440  }
441 #endif
442  outputLCEnded(vehicle, from, from, priorDirection);
443  }
444 
445  outputLCStarted(vehicle, from, to, direction, maneuverDist);
446  vehicle->getLaneChangeModel().setManeuverDist(maneuverDist - latDist);
447  const bool changedToNewLane = checkChangeToNewLane(vehicle, direction, from, to);
448 
449  MSLane* oldShadowLane = vehicle->getLaneChangeModel().getShadowLane();
451  MSLane* shadowLane = vehicle->getLaneChangeModel().getShadowLane();
452  if (shadowLane != nullptr && shadowLane != oldShadowLane
453  && &shadowLane->getEdge() == &source->getEdge()) {
454  assert(oldShadowLane == 0 || vehicle->getLaneChangeModel().isOpposite() || to != from);
455  const double latOffset = vehicle->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
456  (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(vehicle, false, latOffset);
457  }
458  if (completedManeuver) {
459  outputLCEnded(vehicle, from, to, direction);
460  }
461 
462  // Update maneuver reservations on target lanes
463  MSLane* targetLane = vehicle->getLaneChangeModel().updateTargetLane();
464  if (!changedToNewLane && targetLane != nullptr
465  && vehicle->getActionStepLength() > DELTA_T
466  && &targetLane->getEdge() == &source->getEdge()
467  ) {
468  const int dir = (vehicle->getLaneChangeModel().getManeuverDist() > 0 ? 1 : -1);
469  ChangerIt target = from + dir;
470  const double actionStepDist = dir * vehicle->getVehicleType().getMaxSpeedLat() * vehicle->getActionStepLengthSecs();
471  const double latOffset = vehicle->getLatOffset(targetLane) + actionStepDist;
472  target->ahead.addLeader(vehicle, false, latOffset);
473  //std::cout << SIMTIME << " veh=" << vehicle->getID() << " target=" << targetLane->getID()
474  // << " actionStepDist=" << actionStepDist << " latOffset=" << latOffset
475  // << " targetAhead=" << target->ahead.toString() << "\n";
476  }
477 
478  // compute new angle of the vehicle from the x- and y-distances travelled within last time step
479  // (should happen last because primaryLaneChanged() also triggers angle computation)
480  // this part of the angle comes from the orientation of our current lane
481  double laneAngle = vehicle->computeAngle();
482  if (vehicle->getLaneChangeModel().isOpposite()) {
483  // reverse lane angle
484  laneAngle += M_PI;
485  }
486 #ifdef DEBUG_MANEUVER
487  if (DEBUG_COND) {
488  std::cout << SIMTIME << " startChangeSublane"
489  << " oldLane=" << from->lane->getID()
490  << " newLane=" << to->lane->getID()
491  << " shadowLane=" << (shadowLane != nullptr ? shadowLane->getID() : "NULL")
492  << " targetLane=" << (targetLane != nullptr ? targetLane->getID() : "NULL")
493  << " maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
494  << " latDist=" << latDist
495  << " oldShadowLane=" << Named::getIDSecure(oldShadowLane)
496  << " newShadowLane=" << Named::getIDSecure(vehicle->getLaneChangeModel().getShadowLane())
497  << " laneA=" << RAD2DEG(laneAngle)
498  << " oldA=" << RAD2DEG(vehicle->getAngle())
499  << " oppposite=" << vehicle->getLaneChangeModel().isOpposite()
500  << " changedToNewLane=" << changedToNewLane
501  << "\n";
502  }
503 #endif
504  vehicle->setAngle(laneAngle, completedManeuver);
505 
506  // check if a traci maneuver must continue
507  // getOwnState is reset to 0 when changing lanes so we use the stored reason
508  if ((reason & LCA_TRACI) != 0) {
509 #ifdef DEBUG_MANEUVER
510  if (DEBUG_COND) {
511  std::cout << SIMTIME << " continue TraCI-maneuver remainingLatDist=" << vehicle->getLaneChangeModel().getManeuverDist() << "\n";
512  }
513 #endif
515  }
516  from->lane->requireCollisionCheck();
517  to->lane->requireCollisionCheck();
518  return changedToNewLane;
519 }
520 
521 bool
523  const int oppositeSign = vehicle->getLaneChangeModel().isOpposite() ? -1 : 1;
524  const bool opposite = (&from->lane->getEdge() != &to->lane->getEdge());
525  const bool changedToNewLane = (to->lane != from->lane
526  && fabs(vehicle->getLateralPositionOnLane()) > 0.5 * vehicle->getLane()->getWidth()
527  && (mayChange(direction * oppositeSign) || opposite));
528  if (changedToNewLane) {
529  vehicle->myState.myPosLat -= direction * 0.5 * (from->lane->getWidth() + to->lane->getWidth()) * oppositeSign;
530  if (!opposite) {
531  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
532  to->dens += vehicle->getVehicleType().getLengthWithGap();
533  }
535  if (!vehicle->isActive()) {
536  // update leaders beyond the current edge for all lanes
537  // @note to->aheadNext and from->aheadNext are only needed for output in non-action steps.
538  to->aheadNext = getLeaders(to, vehicle);
539  from->aheadNext = getLeaders(from, vehicle);
540  }
541  vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
542  vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
543  vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
544  }
545  vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
546  if (!opposite) {
547  to->ahead.addLeader(vehicle, false, 0);
548  }
549  } else {
550  from->ahead.addLeader(vehicle, false, 0);
551  }
552  return changedToNewLane;
553 }
554 
555 void
556 MSLaneChangerSublane::outputLCStarted(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction, double maneuverDist) {
558  // non-sublane change started
559  && ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)
560  && ((vehicle->getLaneChangeModel().getOwnState() & LCA_STAY) == 0)
561  // no changing for the same reason in previous step (either not wanted or blocked)
564  || ((vehicle->getLaneChangeModel().getPrevState() & LCA_STAY) != 0)
565  || ((vehicle->getLaneChangeModel().getPrevState() & LCA_BLOCKED) != 0))
566  ) {
567 #ifdef DEBUG_STATE
568  if (DEBUG_COND) {
569  std::cout << SIMTIME << " veh=" << vehicle->getID() << " laneChangeStarted state=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getOwnState())
570  << " prevState=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getPrevState())
572  << " filtered=" << toString((LaneChangeAction)(vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)))
573  << "\n";
574  }
575 #endif
576  vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
577  vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
578  vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
579  vehicle->getLaneChangeModel().laneChangeOutput("changeStarted", from->lane, to->lane, direction, maneuverDist);
580  }
581 }
582 
583 void
584 MSLaneChangerSublane::outputLCEnded(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction) {
586  // non-sublane change ended
587  && ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)) {
588  vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
589  vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
590  vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
591  vehicle->getLaneChangeModel().laneChangeOutput("changeEnded", from->lane, to->lane, direction);
592  }
593 }
594 
595 
597 MSLaneChangerSublane::getLeaders(const ChangerIt& target, const MSVehicle* vehicle) const {
598  // get the leading vehicle on the lane to change to
599 #ifdef DEBUG_SURROUNDING
600  if (DEBUG_COND) {
601  std::cout << SIMTIME << " getLeaders lane=" << target->lane->getID() << " ego=" << vehicle->getID() << " ahead=" << target->ahead.toString() << "\n";
602  }
603 #endif
604  MSLeaderDistanceInfo result(target->lane->getWidth(), nullptr, 0);
605  int sublaneShift = 0;
606  if (target->lane == vehicle->getLane()) {
608  sublaneShift = int(-vehicle->getLeftSideOnLane() / MSGlobals::gLateralResolution);
609  } else if (vehicle->getRightSideOnLane() > target->lane->getWidth() + MSGlobals::gLateralResolution) {
610  sublaneShift = -int((vehicle->getRightSideOnLane() - target->lane->getWidth()) / MSGlobals::gLateralResolution);
611  }
612  result.setSublaneOffset(sublaneShift);
613  }
614  for (int i = 0; i < target->ahead.numSublanes(); ++i) {
615  const MSVehicle* veh = target->ahead[i];
616  if (veh != nullptr) {
617  const double gap = veh->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
618 #ifdef DEBUG_SURROUNDING
619  if (DEBUG_COND) {
620  std::cout << " ahead lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane() << " gap=" << gap << " sublaneShift=" << sublaneShift << "\n";
621  }
622 #endif
623  if (i + sublaneShift >= 0 && i + sublaneShift < result.numSublanes()) {
624  result.addLeader(veh, gap, 0, i + sublaneShift);
625  }
626  }
627  }
628  if (sublaneShift != 0) {
629  for (MSVehicle* cand : target->outsideBounds) {
630  const double gap = cand->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
631  result.addLeader(cand, gap);
632  }
633  }
634 #ifdef DEBUG_SURROUNDING
635  if (DEBUG_COND) {
636  std::cout << " outsideBounds=" << toString(target->outsideBounds) << " result=" << result.toString() << "\n";
637  }
638 #endif
639  target->lane->addLeaders(vehicle, vehicle->getPositionOnLane(), result);
640  return result;
641 }
642 
643 
644 int
646  int laneOffset,
647  LaneChangeAction alternatives,
648  const std::vector<MSVehicle::LaneQ>& preb,
649  double& latDist,
650  double& maneuverDist) const {
651 
652  ChangerIt target = myCandi + laneOffset;
653  MSVehicle* vehicle = veh(myCandi);
654  const MSLane& neighLane = *(target->lane);
655  int blocked = 0;
656 
657  MSLeaderDistanceInfo neighLeaders = target->aheadNext;
658  MSLeaderDistanceInfo neighFollowers = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
659  MSLeaderDistanceInfo neighBlockers(neighLane.getWidth(), vehicle, vehicle->getLane()->getRightSideOnEdge() - neighLane.getRightSideOnEdge());
660  MSLeaderDistanceInfo leaders = myCandi->aheadNext;
661  addOutsideLeaders(vehicle, leaders);
662  MSLeaderDistanceInfo followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
663  MSLeaderDistanceInfo blockers(vehicle->getLane()->getWidth(), vehicle, 0);
664 
665  // consider sibling lanes of the origin and target lane
666  for (int offset : myCandi->siblings) {
667  // treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
668  ChangerIt ceSib = myCandi + offset;
669  MSLeaderDistanceInfo sibFollowers = ceSib->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
670  if (sibFollowers.hasVehicles()) {
671  followers.addLeaders(sibFollowers);
672  }
673  if (ceSib->aheadNext.hasVehicles()) {
674  leaders.addLeaders(ceSib->aheadNext);
675  }
676 #ifdef DEBUG_SURROUNDING
677  if (DEBUG_COND) {
678  std::cout << SIMTIME << " ego=" << vehicle->getID() << " ahead=" << myCandi->aheadNext.toString() << " sib=" << ceSib->lane->getID() << " sibAhead=" << ceSib->aheadNext.toString() << " leaders=" << leaders.toString() << "\n";
679  }
680 #endif
681  }
682  for (int offset : target->siblings) {
683  // treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
684  ChangerIt ceSib = target + offset;
685  MSLeaderDistanceInfo sibFollowers = ceSib->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
686  if (sibFollowers.hasVehicles()) {
687  neighFollowers.addLeaders(sibFollowers);
688  }
689  if (ceSib->aheadNext.hasVehicles()) {
690  neighLeaders.addLeaders(ceSib->aheadNext);
691  }
692 #ifdef DEBUG_SURROUNDING
693  if (DEBUG_COND) {
694  std::cout << SIMTIME << " ego=" << vehicle->getID() << " neighAhead=" << target->aheadNext.toString() << " sib=" << ceSib->lane->getID() << " sibAhead=" << ceSib->aheadNext.toString() << " neighLeaders=" << neighLeaders.toString() << "\n";
695  }
696 #endif
697  }
698 
699  // break leader symmetry
700  if (laneOffset == -1 && neighLeaders.hasVehicles()) {
701  neighLeaders.moveSamePosTo(vehicle, neighFollowers);
702  }
703 
704 #ifdef DEBUG_SURROUNDING
705  if (DEBUG_COND) std::cout << SIMTIME
706  << " checkChangeSublane: veh=" << vehicle->getID()
707  << " laneOffset=" << laneOffset
708  << "\n leaders=" << leaders.toString()
709  << "\n neighLeaders=" << neighLeaders.toString()
710  << "\n followers=" << followers.toString()
711  << "\n neighFollowers=" << neighFollowers.toString()
712  << "\n";
713 #endif
714 
715 
716  const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
717  laneOffset, alternatives,
718  leaders, followers, blockers,
719  neighLeaders, neighFollowers, neighBlockers,
720  neighLane, preb,
721  &(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, maneuverDist, blocked);
722  int state = blocked | wish;
723 
724  // XXX
725  // do are more careful (but expensive) check to ensure that a
726  // safety-critical leader is not being overlooked
727 
728  // XXX
729  // ensure that a continuous lane change manoeuvre can be completed
730  // before the next turning movement
731 
732  // let TraCI influence the wish to change lanes and the security to take
733  const int oldstate = state;
734  state = vehicle->influenceChangeDecision(state);
735 #ifdef DEBUG_STATE
736  if (DEBUG_COND && state != oldstate) {
737  std::cout << SIMTIME << " veh=" << vehicle->getID() << " stateAfterTraCI=" << toString((LaneChangeAction)state) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
738  }
739 #endif
740  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
741  if (laneOffset != 0) {
742  vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollowers, neighLeaders);
743  }
744  return state;
745 }
746 
747 
748 bool
750  MSVehicle* vehicle,
751  int laneOffset,
752  MSLane* targetLane,
753  const std::pair<MSVehicle* const, double>& leader,
754  const std::pair<MSVehicle* const, double>& neighLead,
755  const std::pair<MSVehicle* const, double>& neighFollow,
756  const std::vector<MSVehicle::LaneQ>& preb) {
758 
759  UNUSED_PARAMETER(leader);
760  UNUSED_PARAMETER(neighLead);
761  UNUSED_PARAMETER(neighFollow);
762 
763  const MSLane& neighLane = *targetLane;
764  MSLane* curLane = myCandi->lane;
765 
766  MSLeaderDistanceInfo neighLeaders(targetLane->getWidth(), nullptr, 0);
767  MSLeaderDistanceInfo neighFollowers(targetLane->getWidth(), nullptr, 0);
768  MSLeaderDistanceInfo neighBlockers(targetLane->getWidth(), nullptr, 0);
769  MSLeaderDistanceInfo leaders(curLane->getWidth(), nullptr, 0);
770  MSLeaderDistanceInfo followers(curLane->getWidth(), nullptr, 0);
771  MSLeaderDistanceInfo blockers(curLane->getWidth(), nullptr, 0);
772 
773  const double backPosOnTarget = vehicle->getLane()->getOppositePos(vehicle->getBackPositionOnLane());
774  if (vehicle->getLaneChangeModel().isOpposite()) {
775  leaders = curLane->getFollowersOnConsecutive(vehicle, vehicle->getPositionOnLane(), true, -1, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
776  leaders.fixOppositeGaps(false);
777  curLane->addLeaders(vehicle, vehicle->getBackPositionOnLane(), followers);
778  followers.fixOppositeGaps(true);
779  neighFollowers = targetLane->getFollowersOnConsecutive(vehicle, backPosOnTarget, true);
780  neighFollowers.fixOppositeGaps(false);
781  // artificially increase the position to ensure that ego is not added as a leader
782  const double posOnTarget = backPosOnTarget + vehicle->getVehicleType().getLength() + POSITION_EPS;
783  targetLane->addLeaders(vehicle, posOnTarget, neighLeaders);
784  neighLeaders.patchGaps(2 * POSITION_EPS);
785  int sublaneIndex = 0;
786  for (int i = 0; i < targetLane->getIndex(); i++) {
787  sublaneIndex += MSLeaderInfo(targetLane->getEdge().getLanes()[i]->getWidth()).numSublanes();
788  }
789  vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(neighLeaders, sublaneIndex, targetLane->getIndex());
790  } else {
791  leaders = myCandi->aheadNext;
792  followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
793  const double posOnTarget = backPosOnTarget - vehicle->getVehicleType().getLength();
794  targetLane->addLeaders(vehicle, backPosOnTarget, neighFollowers, true);
795  neighFollowers.fixOppositeGaps(true);
796  neighLeaders = targetLane->getFollowersOnConsecutive(vehicle, posOnTarget, true);
797  neighLeaders.fixOppositeGaps(false);
798  }
799 
800 
801 #ifdef DEBUG_CHANGE_OPPOSITE
802  if (DEBUG_COND) std::cout << SIMTIME
803  << " checkChangeOppositeSublane: veh=" << vehicle->getID()
804  << " isOpposite=" << vehicle->getLaneChangeModel().isOpposite()
805  << " laneOffset=" << laneOffset
806  << "\n leaders=" << leaders.toString()
807  << "\n neighLeaders=" << neighLeaders.toString()
808  << "\n followers=" << followers.toString()
809  << "\n neighFollowers=" << neighFollowers.toString()
810  << "\n";
811 #endif
812 
814  | (mayChange(1) ? LCA_LEFT : LCA_NONE));
815 
816  int blocked = 0;
817  double latDist = 0;
818  double maneuverDist = 0;
819  const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
820  laneOffset, alternatives,
821  leaders, followers, blockers,
822  neighLeaders, neighFollowers, neighBlockers,
823  neighLane, preb,
824  &(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, maneuverDist, blocked);
825  int state = blocked | wish;
826 
827  const int oldstate = state;
828  state = vehicle->influenceChangeDecision(state);
829 #ifdef DEBUG_CHANGE_OPPOSITE
830  if (DEBUG_COND && state != oldstate) {
831  std::cout << SIMTIME << " veh=" << vehicle->getID() << " stateAfterTraCI=" << toString((LaneChangeAction)state) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
832  }
833 #endif
834  vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
835  if (laneOffset != 0) {
836  vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollowers, neighLeaders);
837  }
838 
839  if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) == 0) {
840  // change if the vehicle wants to and is allowed to change
841 #ifdef DEBUG_CHANGE_OPPOSITE
842  if (DEBUG_COND) {
843  std::cout << SIMTIME << " veh '" << vehicle->getID() << "' performing sublane change latDist=" << latDist << " maneuverDist=" << maneuverDist << "\n";
844  }
845 #endif
846  vehicle->getLaneChangeModel().setOwnState(state);
847  return startChangeSublane(vehicle, myCandi, latDist, maneuverDist);
848  } else {
849  vehicle->getLaneChangeModel().setSpeedLat(0);
850  return false;
851  }
852 }
853 
854 std::pair<MSVehicle*, double>
856  const double egoWidth = vehicle->getVehicleType().getWidth() + vehicle->getVehicleType().getMinGapLat();
857  std::pair<MSVehicle*, double> leader(nullptr, std::numeric_limits<double>::max());
858  for (int i = 0; i < leaders.numSublanes(); ++i) {
859  CLeaderDist cand = leaders[i];
860  if (cand.first != nullptr) {
861  const double rightSide = cand.first->getRightSideOnLane();
862  if (cand.second < leader.second
863  && rightSide < egoWidth
864  && vehicle->getLane()->getWidth() - rightSide - cand.first->getVehicleType().getWidth() < egoWidth) {
865  leader.first = const_cast<MSVehicle*>(cand.first);
866  leader.second = cand.second;
867  }
868  }
869  }
870  return leader;
871 }
872 
873 
874 void
876  if (vehicle->getLaneChangeModel().getShadowLane() == nullptr) {
877  const MSLane* lane = vehicle->getLane();
878  const double rightOL = vehicle->getRightSideOnLane(lane);
879  const double leftOL = vehicle->getLeftSideOnLane(lane);
880  const bool outsideLeft = rightOL > lane->getWidth();
881 #ifdef DEBUG_SURROUNDING
882  if (DEBUG_COND) {
883  std::cout << SIMTIME << " addOutsideLeaders veh=" << vehicle->getID() << " lane=" << lane->getID() << " rightOL=" << rightOL << " leftOL=" << leftOL << "\n";
884  }
885 #endif
886  if (leftOL < 0 || outsideLeft) {
887  int sublaneOffset = 0;
888  if (outsideLeft) {
889  sublaneOffset = MIN2(0, -(int)ceil((leftOL - lane->getWidth()) / MSGlobals::gLateralResolution) + 1);
890  } else {
891  sublaneOffset = MAX2(0, (int)ceil(-rightOL / MSGlobals::gLateralResolution) - 1);
892  }
893  if (sublaneOffset != 0) {
894  leaders.setSublaneOffset(sublaneOffset);
895 #ifdef DEBUG_SURROUNDING
896  if (DEBUG_COND) {
897  std::cout << " sublaneOffset=" << sublaneOffset << " outsideLeft=" << outsideLeft << "\n";
898  }
899 #endif
900  for (const MSVehicle* cand : lane->myTmpVehicles) {
901 #ifdef DEBUG_SURROUNDING
902  if (DEBUG_COND) {
903  std::cout << " cand=" << cand->getID() << " cLOE=" << cand->getLeftSideOnEdge() << " cROE=" << cand->getRightSideOnEdge() << "\n";
904  }
905 #endif
906  if (cand->getPositionOnLane() > vehicle->getPositionOnLane()
907  && ((!outsideLeft && cand->getLeftSideOnEdge() < 0)
908  || (outsideLeft && cand->getLeftSideOnEdge() > lane->getEdge().getWidth()))) {
909  const double gap = cand->getPositionOnLane() - vehicle->getPositionOnLane() - cand->getLength() - vehicle->getVehicleType().getMinGap();
910  leaders.addLeader(cand, gap);
911 #ifdef DEBUG_SURROUNDING
912  if (DEBUG_COND) {
913  std::cout << " outsideLeader=" << cand->getID() << " ahead=" << leaders.toString() << "\n";
914  }
915 #endif
916  }
917  }
918  }
919  }
920  }
921 }
922 
923 /****************************************************************************/
#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:38
#define SPEED2DIST(x)
Definition: SUMOTime.h:45
#define SIMTIME
Definition: SUMOTime.h:62
#define DIST2SPEED(x)
Definition: SUMOTime.h:47
@ 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
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
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
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
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 getLength() const
Returns the vehicle's length.
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:891
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
double getWidth() const
Returns the edges's width (sum over all lanes)
Definition: MSEdge.h:641
static double gLateralResolution
Definition: MSGlobals.h:97
Performs lane changing of vehicles.
Definition: MSLaneChanger.h:45
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, MSVehicle *lastStopped)
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
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
void addOutsideLeaders(const MSVehicle *vehicle, MSLeaderDistanceInfo &leaders) const
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:84
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
Definition: MSLane.h:1466
void addLeaders(const MSVehicle *vehicle, double vehPos, MSLeaderDistanceInfo &result, bool oppositeDirection=false)
get leaders for ego on the given lane
Definition: MSLane.cpp:4045
double getRightSideOnEdge() const
Definition: MSLane.h:1186
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:634
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:4292
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition: MSLane.cpp:4280
MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle *ego, double backOffset, bool allSublanes, double searchDist=-1, MinorLinkMode mLinkMode=FOLLOW_ALWAYS) const
return the sublane followers with the largest missing rear gap among all predecessor lanes (within di...
Definition: MSLane.cpp:3706
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:627
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:144
virtual void addLeaders(MSLeaderDistanceInfo &other)
updatd empty sublanes with vehicles and gaps from other
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
void patchGaps(double amount)
add given value to all gaps
virtual int addLeader(const MSVehicle *veh, double gap, double latOffset=0, int sublane=-1)
void moveSamePosTo(const MSVehicle *ego, MSLeaderDistanceInfo &other)
void setSublaneOffset(int offset)
set number of sublanes by which to shift positions
int numSublanes() const
Definition: MSLeaderInfo.h:86
bool hasVehicles() const
Definition: MSLeaderInfo.h:94
void setSublaneChange(double latDist)
Sets a new sublane-change request.
Definition: MSVehicle.cpp:434
double myPosLat
the stored lateral position
Definition: MSVehicle.h:140
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
double getRightSideOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
Definition: MSVehicle.cpp:6706
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:5798
double computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:1472
double getLeftSideOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
Definition: MSVehicle.cpp:6712
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1579
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
Definition: MSVehicle.h:631
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5774
double getLeftSideOnLane() const
Get the lateral position of the vehicles left side on the lane:
Definition: MSVehicle.cpp:6688
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition: MSVehicle.h:536
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:7286
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:7305
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:6481
void setAngle(double angle, bool straightenFurther=false)
Set a custom vehicle angle in rad, optionally updates furtherLanePosLat.
Definition: MSVehicle.cpp:1425
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition: MSVehicle.h:401
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:6768
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
Definition: MSVehicle.h:528
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7251
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
Definition: MSVehicle.cpp:6682
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
Position myCachedPosition
Definition: MSVehicle.h:1938
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:5792
std::vector< double > myFurtherLanesPosLat
lateral positions on further lanes
Definition: MSVehicle.h:1916
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
double getAngle() const
Returns the vehicle's direction in radians.
Definition: MSVehicle.h:734
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1868
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:322
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:21884
#define M_PI
Definition: odrSpiral.cpp:45