Eclipse SUMO - Simulation of Urban MObility
MSAbstractLaneChangeModel.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-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 /****************************************************************************/
23 // Interface for lane-change models
24 /****************************************************************************/
25 
26 // ===========================================================================
27 // DEBUG
28 // ===========================================================================
29 //#define DEBUG_TARGET_LANE
30 //#define DEBUG_SHADOWLANE
31 //#define DEBUG_OPPOSITE
32 //#define DEBUG_MANEUVER
33 #define DEBUG_COND (myVehicle.isSelected())
34 
35 #include <config.h>
36 
39 #include <utils/geom/GeomHelper.h>
40 #include <microsim/MSNet.h>
41 #include <microsim/MSEdge.h>
42 #include <microsim/MSLane.h>
43 #include <microsim/MSLink.h>
44 #include <microsim/MSStop.h>
45 #include <microsim/MSDriverState.h>
46 #include <microsim/MSGlobals.h>
48 #include "MSLCM_DK2008.h"
49 #include "MSLCM_LC2013.h"
50 #include "MSLCM_LC2013_CC.h"
51 #include "MSLCM_SL2015.h"
53 
54 /* -------------------------------------------------------------------------
55  * static members
56  * ----------------------------------------------------------------------- */
62 const double MSAbstractLaneChangeModel::NO_NEIGHBOR(std::numeric_limits<double>::max());
63 
64 #define LC_ASSUMED_DECEL 1.0 // the minimal constant deceleration assumed to estimate the duration of a continuous lane-change at its initiation.
65 
66 /* -------------------------------------------------------------------------
67  * MSAbstractLaneChangeModel-methods
68  * ----------------------------------------------------------------------- */
69 
70 void
72  myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
73  myLCOutput = oc.isSet("lanechange-output");
74  myLCStartedOutput = oc.getBool("lanechange-output.started");
75  myLCEndedOutput = oc.getBool("lanechange-output.ended");
76  myLCXYOutput = oc.getBool("lanechange-output.xy");
77 }
78 
79 
83  throw ProcessError(TLF("Lane change model '%' is not compatible with sublane simulation", toString(lcm)));
84  }
85  switch (lcm) {
87  return new MSLCM_DK2008(v);
89  return new MSLCM_LC2013(v);
91  return new MSLCM_LC2013_CC(v);
93  return new MSLCM_SL2015(v);
96  return new MSLCM_LC2013(v);
97  } else {
98  return new MSLCM_SL2015(v);
99  }
100  default:
101  throw ProcessError(TLF("Lane change model '%' not implemented", toString(lcm)));
102  }
103 }
104 
105 
107  myVehicle(v),
108  myOwnState(0),
109  myPreviousState(0),
110  myPreviousState2(0),
111  myCanceledStateRight(LCA_NONE),
112  myCanceledStateCenter(LCA_NONE),
113  myCanceledStateLeft(LCA_NONE),
114  mySpeedLat(0),
115  myAccelerationLat(0),
116  myAngleOffset(0),
117  myPreviousAngleOffset(0),
118  myCommittedSpeed(0),
119  myLaneChangeCompletion(1.0),
120  myLaneChangeDirection(0),
121  myAlreadyChanged(false),
122  myShadowLane(nullptr),
123  myTargetLane(nullptr),
124  myModel(model),
125  myLastLateralGapLeft(0.),
126  myLastLateralGapRight(0.),
127  myLastLeaderGap(0.),
128  myLastFollowerGap(0.),
129  myLastLeaderSecureGap(0.),
130  myLastFollowerSecureGap(0.),
131  myLastOrigLeaderGap(0.),
132  myLastOrigLeaderSecureGap(0.),
133  myLastLeaderSpeed(0),
134  myLastFollowerSpeed(0),
135  myLastOrigLeaderSpeed(0),
136  myDontResetLCGaps(false),
137  myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
138  myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
139  myMaxDistLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXDISTLATSTANDING,
140  // prevent lateral sliding for cars but permit for two-wheelers due to better maneuverability
141  (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
142  mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
143  myOvertakeRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_RIGHT, 0)),
144  myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
145  myLastLaneChangeOffset(0),
146  myAmOpposite(false),
147  myManeuverDist(0.),
148  myPreviousManeuverDist(0.) {
152 }
153 
154 
156 }
157 
158 void
161  myOwnState = state;
162  myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
163 }
164 
165 void
166 MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
167  UNUSED_PARAMETER(travelledLatDist);
168 }
169 
170 
171 void
173 #ifdef DEBUG_MANEUVER
174  if (DEBUG_COND) {
175  std::cout << SIMTIME
176  << " veh=" << myVehicle.getID()
177  << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
178  << std::endl;
179  }
180 #endif
181  myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
182  // store value which may be modified by the model during the next step
184 }
185 
186 
187 double
189  return myManeuverDist;
190 }
191 
192 double
194  return myPreviousManeuverDist;
195 }
196 
197 void
199  if (dir == -1) {
200  myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
201  myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
202  } else if (dir == 1) {
203  myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
204  myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
205  } else {
206  // dir \in {-1,1} !
207  assert(false);
208  }
209 }
210 
211 
212 void
213 MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
214  if (dir == -1) {
215  myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
216  myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
217  } else if (dir == 1) {
218  myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
219  myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
220  } else {
221  // dir \in {-1,1} !
222  assert(false);
223  }
224 }
225 
226 
227 void
229  myLeftFollowers = nullptr;
230  myLeftLeaders = nullptr;
231  myRightFollowers = nullptr;
232  myRightLeaders = nullptr;
233 }
234 
235 
236 const std::shared_ptr<MSLeaderDistanceInfo>
238  if (dir == -1) {
239  return myLeftFollowers;
240  } else if (dir == 1) {
241  return myRightFollowers;
242  } else {
243  // dir \in {-1,1} !
244  assert(false);
245  }
246  return nullptr;
247 }
248 
249 const std::shared_ptr<MSLeaderDistanceInfo>
251  if (dir == -1) {
252  return myLeftLeaders;
253  } else if (dir == 1) {
254  return myRightLeaders;
255  } else {
256  // dir \in {-1,1} !
257  assert(false);
258  }
259  return nullptr;
260 }
261 
262 
263 bool
265  if (neighLeader == nullptr) {
266  return false;
267  }
268  // Congested situation are relevant only on highways (maxSpeed > 70km/h)
269  // and congested on German Highways means that the vehicles have speeds
270  // below 60km/h. Overtaking on the right is allowed then.
271  if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
272 
273  return false;
274  }
275  if (myVehicle.congested() && neighLeader->congested()) {
276  return true;
277  }
278  return false;
279 }
280 
281 
282 bool
284  return (!myAllowOvertakingRight
285  && !myVehicle.congested()
288 }
289 
290 bool
291 MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
292  if (leader.first == 0) {
293  return false;
294  }
295  // let's check it on highways only
296  if (leader.first->getSpeed() < (80.0 / 3.6)) {
297  return false;
298  }
299  return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
300 }
301 
302 
303 bool
307  myLaneChangeDirection = direction;
308  setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
311  if (myLCOutput) {
313  }
314  return true;
315  } else {
316  primaryLaneChanged(source, target, direction);
317  return false;
318  }
319 }
320 
321 void
323  myDontResetLCGaps = true;
324 }
325 
326 void
328  myDontResetLCGaps = false;
329 }
330 
331 void
333  initLastLaneChangeOffset(direction);
335  source->leftByLaneChange(&myVehicle);
336  laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
337  if (&source->getEdge() != &target->getEdge()) {
339 #ifdef DEBUG_OPPOSITE
340  if (debugVehicle()) {
341  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
342  }
343 #endif
346  } else if (myAmOpposite) {
347 #ifdef DEBUG_OPPOSITE
348  if (debugVehicle()) {
349  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
350  }
351 #endif
352  myAlreadyChanged = true;
354  if (!MSGlobals::gSublane) {
355  // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
356  // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
358  }
359  } else {
361  target->enteredByLaneChange(&myVehicle);
362  }
363  // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
364  // This is necessary because the lane advance uses the target lane from the corresponding drive item.
366  changed();
367 }
368 
369 void
370 MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
371  if (myLCOutput) {
372  OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
373  of.openTag(tag);
376  of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
377  of.writeAttr(SUMO_ATTR_FROM, source->getID());
378  of.writeAttr(SUMO_ATTR_TO, target->getID());
379  of.writeAttr(SUMO_ATTR_DIR, direction);
382  of.writeAttr("reason", toString((LaneChangeAction)(myOwnState & ~(
387  of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
388  of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
389  of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed));
390  of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
391  of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
392  of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed));
393  of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
394  of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
395  of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed));
397  const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
398  of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
399  if (maneuverDist != 0) {
400  of.writeAttr("maneuverDistance", toString(maneuverDist));
401  }
402  }
403  if (myLCXYOutput) {
406  }
407  of.closeTag();
410  }
411  }
412 }
413 
414 
415 double
416 MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
418  int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
419  return DIST2SPEED(maneuverDist / stepsToChange);
420  } else {
421  return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
422  }
423 }
424 
425 
426 double
429 }
430 
431 void
434  mySpeedLat = speedLat;
435 }
436 
437 
438 void
441  setSpeedLat(0);
442  }
443 }
444 
445 
446 bool
448  const bool pastBefore = pastMidpoint();
449  // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
450  double maneuverDist = getManeuverDist();
451  setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
453  return !pastBefore && pastMidpoint();
454 }
455 
456 
457 void
459  UNUSED_PARAMETER(reason);
468  // opposite driving continues after parking
469  } else {
470  // aborted maneuver
471 #ifdef DEBUG_OPPOSITE
472  if (debugVehicle()) {
473  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
474  }
475 #endif
477  }
478  }
479 }
480 
481 
482 MSLane*
483 MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
485  // initialize shadow lane
486  const double overlap = myVehicle.getLateralOverlap(posLat, lane);
487 #ifdef DEBUG_SHADOWLANE
488  if (debugVehicle()) {
489  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
490  }
491 #endif
492  if (myAmOpposite) {
493  // return the neigh-lane in forward direction
494  return lane->getParallelLane(1);
495  } else if (overlap > NUMERICAL_EPS) {
496  const int shadowDirection = posLat < 0 ? -1 : 1;
497  return lane->getParallelLane(shadowDirection);
498  } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
499  // "reserve" target lane even when there is no overlap yet
501  } else {
502  return nullptr;
503  }
504  } else {
505  return nullptr;
506  }
507 }
508 
509 
510 MSLane*
513 }
514 
515 
516 void
518  if (myShadowLane != nullptr) {
519  if (debugVehicle()) {
520  std::cout << SIMTIME << " cleanupShadowLane\n";
521  }
523  myShadowLane = nullptr;
524  }
525  for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
526  if (debugVehicle()) {
527  std::cout << SIMTIME << " cleanupShadowLane2\n";
528  }
529  (*it)->resetPartialOccupation(&myVehicle);
530  }
531  myShadowFurtherLanes.clear();
533 }
534 
535 void
537  if (myTargetLane != nullptr) {
538  if (debugVehicle()) {
539  std::cout << SIMTIME << " cleanupTargetLane\n";
540  }
542  myTargetLane = nullptr;
543  }
544  for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
545  if (debugVehicle()) {
546  std::cout << SIMTIME << " cleanupTargetLane\n";
547  }
548  if (*it != nullptr) {
549  (*it)->resetManeuverReservation(&myVehicle);
550  }
551  }
552  myFurtherTargetLanes.clear();
553 // myNoPartiallyOccupatedByShadow.clear();
554 }
555 
556 
557 bool
558 MSAbstractLaneChangeModel::cancelRequest(int state, int laneOffset) {
559  // store request before canceling
560  getCanceledState(laneOffset) |= state;
561  int ret = myVehicle.influenceChangeDecision(state);
562  return ret != state;
563 }
564 
565 double
568 }
569 
570 void
572  if (dir > 0) {
574  } else if (dir < 0) {
576  }
577 }
578 
579 void
581  if (!MSGlobals::gSublane) {
582  // assume each vehicle drives at the center of its lane and act as if it fits
583  return;
584  }
585  if (myShadowLane != nullptr) {
586 #ifdef DEBUG_SHADOWLANE
587  if (debugVehicle()) {
588  std::cout << SIMTIME << " updateShadowLane()\n";
589  }
590 #endif
592  }
594  std::vector<MSLane*> passed;
595  if (myShadowLane != nullptr) {
597  const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
598  if (myAmOpposite) {
599  assert(further.size() == 0);
600  } else {
601  const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
602  assert(further.size() == furtherPosLat.size());
603  passed.push_back(myShadowLane);
604  for (int i = 0; i < (int)further.size(); ++i) {
605  MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
606 #ifdef DEBUG_SHADOWLANE
607  if (debugVehicle()) {
608  std::cout << SIMTIME << " further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
609  }
610 #endif
611  if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
612  passed.push_back(shadowFurther);
613  }
614  }
615  std::reverse(passed.begin(), passed.end());
616  }
617  } else {
618  if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
619  WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
620  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
622  }
623  }
624 #ifdef DEBUG_SHADOWLANE
625  if (debugVehicle()) {
626  std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
627  << " newShadowLane=" << Named::getIDSecure(myShadowLane)
628  << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
629  std::cout << std::endl;
630  }
631 #endif
633 #ifdef DEBUG_SHADOWLANE
634  if (debugVehicle()) std::cout
635  << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
636 #endif
637 }
638 
639 
640 int
642  if (isChangingLanes()) {
643  if (pastMidpoint()) {
644  return -myLaneChangeDirection;
645  } else {
646  return myLaneChangeDirection;
647  }
648  } else if (myShadowLane == nullptr) {
649  return 0;
650  } else if (myAmOpposite) {
651  // return neigh-lane in forward direction
652  return 1;
653  } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
655  } else {
656  // overlap with opposite direction lane
657  return 1;
658  }
659 }
660 
661 
662 MSLane*
664 #ifdef DEBUG_TARGET_LANE
665  MSLane* oldTarget = myTargetLane;
666  std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
667  if (debugVehicle()) {
668  std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
669  << "\n oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
670  << " oldFurtherTargets: " << toString(oldFurtherTargets);
671  }
672 #endif
673  if (myTargetLane != nullptr) {
675  }
676  // Clear old further target lanes
677  for (MSLane* oldTargetLane : myFurtherTargetLanes) {
678  if (oldTargetLane != nullptr) {
679  oldTargetLane->resetManeuverReservation(&myVehicle);
680  }
681  }
682  myFurtherTargetLanes.clear();
683 
684  // Get new target lanes and issue a maneuver reservation.
685  int targetDir;
686  myTargetLane = determineTargetLane(targetDir);
687  if (myTargetLane != nullptr) {
689  // further targets are just the target lanes corresponding to the vehicle's further lanes
690  // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
691  for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
692  MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
693  myFurtherTargetLanes.push_back(furtherTargetLane);
694  if (furtherTargetLane != nullptr) {
695  furtherTargetLane->setManeuverReservation(&myVehicle);
696  }
697  }
698  }
699 #ifdef DEBUG_TARGET_LANE
700  if (debugVehicle()) {
701  std::cout << "\n newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
702  << " newFurtherTargets: " << toString(myFurtherTargetLanes)
703  << std::endl;
704  }
705 #endif
706  return myTargetLane;
707 }
708 
709 
710 MSLane*
712  targetDir = 0;
713  if (myManeuverDist == 0) {
714  return nullptr;
715  }
716  // Current lateral boundaries of the vehicle
717  const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
718  const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
719  const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
720 
721  if (vehRight + myManeuverDist < -halfLaneWidth) {
722  // Vehicle intends to traverse the right lane boundary
723  targetDir = -1;
724  } else if (vehLeft + myManeuverDist > halfLaneWidth) {
725  // Vehicle intends to traverse the left lane boundary
726  targetDir = 1;
727  }
728  if (targetDir == 0) {
729  // Presently, no maneuvering into another lane is begun.
730  return nullptr;
731  }
732  MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
733  if (target == nullptr || target == myShadowLane) {
734  return nullptr;
735  } else {
736  return target;
737  }
738 }
739 
740 
741 
742 double
744  double result = 0.;
745  if (!(fabs(mySpeedLat) < NUMERICAL_EPS && fabs(myPreviousAngleOffset * 180 / M_PI) < NUMERICAL_EPS)) {
747  result = atan2(mySpeedLat, myVehicle.getSpeed());
748  } else {
750  }
751  }
752 
753  myAngleOffset = result;
754  return result;
755 }
756 
757 
758 double
759 MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
760 
762  if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
764  // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
766  } else {
767  return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
768  }
769  }
770 
771  if (remainingManeuverDist == 0) {
772  return 0;
773  }
774 
775  // Check argument assumptions
776  assert(speed >= 0);
777  assert(remainingManeuverDist >= 0);
778  assert(decel > 0);
779  assert(myVehicle.getVehicleType().getMaxSpeedLat() > 0);
781  assert(myMaxSpeedLatStanding >= 0);
782 
783  // for brevity
784  const double v0 = speed;
785  const double D = remainingManeuverDist;
786  const double b = decel;
787  const double wmin = myMaxSpeedLatStanding;
788  const double f = myMaxSpeedLatFactor;
789  const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
790 
791  /* Here's the approach for the calculation of the required time for the LC:
792  * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
793  * Where v(t)=0 <=> t >= ts:=v0/b
794  * For the lateral speed w(t) this gives:
795  * w(t) = min(wmax, wmin + f*v(t))
796  * The lateral distance covered until t is
797  * d(t) = int_0^t w(s) ds
798  * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
799  * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
800  * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
801  * 3) w(T) = wmin, i.e., v(T)=0
802  */
803  const double vm = (wmax - wmin) / f;
804  double distSoFar = 0.;
805  double timeSoFar = 0.;
806  double v = v0;
807  if (v > vm) {
808  const double wmaxTime = (v0 - vm) / b;
809  const double d1 = wmax * wmaxTime;
810  if (d1 >= D) {
811  return D / wmax;
812  } else {
813  distSoFar += d1;
814  timeSoFar += wmaxTime;
815  v = vm;
816  }
817  }
818  if (v > 0) {
819  /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
820  * Thus, the additional lateral distance covered after time t is:
821  * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
822  * and the additional lateral distance covered until v=0 at t=v/b is:
823  * d2 = (wmin + 0.5*f*v)*t
824  */
825  const double t = v / b; // stop time
826  const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
827  assert(d2 > 0);
828  if (distSoFar + d2 >= D) {
829  // LC is completed during this phase
830  const double x = 0.5 * f * b;
831  const double y = wmin + f * v;
832  /* Solve D - distSoFar = y*t - x*t^2.
833  * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
834  */
835  const double p = 0.5 * y / x;
836  const double q = (D - distSoFar) / x;
837  assert(p * p - q > 0);
838  const double t2 = p + sqrt(p * p - q);
839  return timeSoFar + t2;
840  } else {
841  distSoFar += d2;
842  timeSoFar += t;
843  //v = 0;
844  }
845  }
846  // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
847  if (wmin == 0) {
848  // LC won't be completed if vehicle stands
849  double maneuverDist = remainingManeuverDist;
850  const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
851  if (vModel > 0) {
852  // unless the model tells us something different
853  return D / vModel;
854  } else {
855  return -1;
856  }
857  } else {
858  // complete LC with lateral speed wmin
859  return timeSoFar + (D - distSoFar) / wmin;
860  }
861 }
862 
863 SUMOTime
865  assert(isChangingLanes()); // Only to be called during ongoing lane change
867  if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
870  } else {
872  }
873  }
874  // Using maxSpeedLat(Factor/Standing)
875  const bool urgent = (myOwnState & LCA_URGENT) != 0;
879 }
880 
881 
882 void
884  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
885  myApproachedByShadow.push_back(link);
886 }
887 
888 void
890  for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
891  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
892  (*it)->removeApproaching(&myVehicle);
893  }
894  myApproachedByShadow.clear();
895 }
896 
897 
898 
899 void
902  int oldstate = myVehicle.getLaneChangeModel().getOwnState();
903  if (myOwnState != newstate) {
905  // Calculate and set the lateral maneuver distance corresponding to the change request
906  // to induce a corresponding sublane change.
907  const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
908  // minimum distance to move the vehicle fully onto the lane at offset dir
909  const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
910  if ((newstate & LCA_TRACI) != 0) {
911  if ((newstate & LCA_STAY) != 0) {
912  setManeuverDist(0.);
913  } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
914  || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
915  setManeuverDist(latLaneDist);
916  }
917  }
918  if (myVehicle.hasInfluencer()) {
919  // lane change requests override sublane change requests
921  }
922 
923  }
924  setOwnState(newstate);
925  } else {
926  // Check for sublane change requests
928  const double maneuverDist = myVehicle.getInfluencer().getLatDist();
931  newstate |= LCA_TRACI;
932  if (myOwnState != newstate) {
933  setOwnState(newstate);
934  }
935  if (gDebugFlag2) {
936  std::cout << " traci influenced maneuverDist=" << maneuverDist << "\n";
937  }
938  }
939  }
940  if (gDebugFlag2) {
941  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
942  }
943 }
944 
945 void
948  myAlreadyChanged = true;
949 }
950 
951 void
953  if (follower.first != 0) {
954  myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
955  myLastFollowerSecureGap = secGap;
956  myLastFollowerSpeed = follower.first->getSpeed();
957  }
958 }
959 
960 void
962  if (leader.first != 0) {
963  myLastLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
964  myLastLeaderSecureGap = secGap;
965  myLastLeaderSpeed = leader.first->getSpeed();
966  }
967 }
968 
969 void
971  if (leader.first != 0) {
973  myLastOrigLeaderSecureGap = secGap;
974  myLastOrigLeaderSpeed = leader.first->getSpeed();
975  }
976 }
977 
978 void
988  if (!myDontResetLCGaps) {
998  }
999  myCommittedSpeed = 0;
1000 }
1001 
1002 void
1004  int rightmost;
1005  int leftmost;
1006  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1007  for (int i = rightmost; i <= leftmost; ++i) {
1008  CLeaderDist vehDist = vehicles[i];
1009  if (vehDist.first != 0) {
1010  const MSVehicle* leader = &myVehicle;
1011  const MSVehicle* follower = vehDist.first;
1012  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1013  if (netGap < myLastFollowerGap && netGap >= 0) {
1014  myLastFollowerGap = netGap;
1015  myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1016  myLastFollowerSpeed = follower->getSpeed();
1017  }
1018  }
1019  }
1020 }
1021 
1022 void
1024  int rightmost;
1025  int leftmost;
1026  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1027  for (int i = rightmost; i <= leftmost; ++i) {
1028  CLeaderDist vehDist = vehicles[i];
1029  if (vehDist.first != 0) {
1030  const MSVehicle* leader = vehDist.first;
1031  const MSVehicle* follower = &myVehicle;
1032  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1033  if (netGap < myLastLeaderGap && netGap >= 0) {
1034  myLastLeaderGap = netGap;
1035  myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1036  myLastLeaderSpeed = leader->getSpeed();
1037  }
1038  }
1039  }
1040 }
1041 
1042 void
1044  int rightmost;
1045  int leftmost;
1046  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1047  for (int i = rightmost; i <= leftmost; ++i) {
1048  CLeaderDist vehDist = vehicles[i];
1049  if (vehDist.first != 0) {
1050  const MSVehicle* leader = vehDist.first;
1051  const MSVehicle* follower = &myVehicle;
1052  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1053  if (netGap < myLastOrigLeaderGap && netGap >= 0) {
1054  myLastOrigLeaderGap = netGap;
1055  myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1056  myLastOrigLeaderSpeed = leader->getSpeed();
1057  }
1058  }
1059  }
1060 }
1061 
1062 
1063 bool
1065  const int stateRight = mySavedStateRight.second;
1066  if (
1067  (stateRight & LCA_STRATEGIC) != 0
1068  && (stateRight & LCA_RIGHT) != 0
1069  && (stateRight & LCA_BLOCKED) != 0) {
1070  return true;
1071  }
1072  const int stateLeft = mySavedStateLeft.second;
1073  if (
1074  (stateLeft & LCA_STRATEGIC) != 0
1075  && (stateLeft & LCA_LEFT) != 0
1076  && (stateLeft & LCA_BLOCKED) != 0) {
1077  return true;
1078  }
1079  return false;
1080 }
1081 
1082 double
1085 }
1086 
1087 
1088 int
1090  const int i = myVehicle.getLane()->getIndex();
1091  if (myAmOpposite) {
1093  } else {
1094  return i;
1095  }
1096 }
1097 
1098 void
1099 MSAbstractLaneChangeModel::addLCSpeedAdvice(const double vSafe, bool ownAdvice) {
1100  const double accel = SPEED2ACCEL(vSafe - myVehicle.getSpeed());
1101  myLCAccelerationAdvices.push_back({accel, ownAdvice});
1102 }
1103 
1104 
1105 void
1107  std::vector<std::string> lcState;
1109  lcState.push_back(toString(mySpeedLat));
1110  lcState.push_back(toString(myLaneChangeCompletion));
1111  lcState.push_back(toString(myLaneChangeDirection));
1112  }
1113  if (lcState.size() > 0) {
1114  out.writeAttr(SUMO_ATTR_LCSTATE, lcState);
1115  }
1116 }
1117 
1118 void
1120  if (attrs.hasAttribute(SUMO_ATTR_LCSTATE)) {
1121  std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE));
1122  bis >> mySpeedLat;
1123  bis >> myLaneChangeCompletion;
1124  bis >> myLaneChangeDirection;
1125  }
1126 }
long long int SUMOTime
Definition: GUI.h:35
#define LC_ASSUMED_DECEL
#define DEBUG_COND
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:32
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TLF(string,...)
Definition: MsgHandler.h:317
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SPEED2DIST(x)
Definition: SUMOTime.h:45
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
#define DIST2SPEED(x)
Definition: SUMOTime.h:47
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:53
const long long int VTYPEPARS_MAXSPEED_LAT_SET
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_MOTORCYCLE
vehicle is a motorcycle
@ SVC_EMERGENCY
public emergency vehicles
@ SVC_MOPED
vehicle is a moped
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_UNKNOWN
The action has not been determined.
@ 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_AMBACKBLOCKER
@ LCA_AMBLOCKINGLEADER
@ LCA_LEFT
Wants go to the left.
@ LCA_MRIGHT
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_AMBACKBLOCKER_STANDING
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_RIGHT
Wants go to the right.
@ LCA_MLEFT
@ LCA_AMBLOCKINGFOLLOWER
LaneChangeModel
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_Y
@ SUMO_ATTR_X
@ SUMO_ATTR_LCA_MAXDISTLATSTANDING
@ SUMO_ATTR_LCA_MAXSPEEDLATFACTOR
@ SUMO_ATTR_LCA_MAXSPEEDLATSTANDING
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_LCA_SIGMA
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_LCSTATE
The state of the lanechange model.
@ SUMO_ATTR_LCA_OVERTAKE_RIGHT
@ SUMO_ATTR_DIR
The abstract direction of a link.
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_TIME
trigger: the time of the step
bool gDebugFlag2
Definition: StdDefs.cpp:36
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
Interface for lane-change models.
double getForwardPos() const
get vehicle position relative to the forward direction lane
double myAccelerationLat
the current lateral acceleration
void setFollowerGaps(CLeaderDist follower, double secGap)
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
std::vector< MSLane * > myFurtherTargetLanes
bool myAlreadyChanged
whether the vehicle has already moved this step
bool myAmOpposite
whether the vehicle is driving in the opposite direction
std::shared_ptr< MSLeaderDistanceInfo > myRightFollowers
std::shared_ptr< MSLeaderDistanceInfo > myRightLeaders
virtual void setOwnState(const int state)
bool pastMidpoint() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver
double myPreviousAngleOffset
the angle offset of the previous time step resulting from lane change and sigma
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change.
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...
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
std::shared_ptr< MSLeaderDistanceInfo > myLeftLeaders
int myPreviousState
lane changing state from the previous simulation step
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model)
int myOwnState
The current state of the vehicle.
double myLastOrigLeaderGap
acutal and secure distance to closest leader vehicle on the original when performing lane change
virtual bool predInteraction(const std::pair< MSVehicle *, double > &leader)
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)
bool myDontResetLCGaps
Flag to prevent resetting the memorized values for LC relevant gaps until the LC output is triggered ...
int myPreviousState2
lane changing state from step before the previous simulation step
const std::shared_ptr< MSLeaderDistanceInfo > getFollowers(const int dir)
Returns the neighboring, lc-relevant followers for the last step in the requested direction.
double myCommittedSpeed
the speed when committing to a change maneuver
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
std::pair< int, int > mySavedStateLeft
std::shared_ptr< MSLeaderDistanceInfo > myLeftFollowers
Cached info on lc-relevant neighboring vehicles.
static bool myLCOutput
whether to record lane-changing
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
virtual void saveState(OutputDevice &out) const
Save the state of the laneChangeModel.
std::pair< int, int > mySavedStateRight
double myLastLeaderSecureGap
the minimum longitudinal distances to vehicles on the target lane that would be necessary for stringe...
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
std::vector< MSLink * > myApproachedByShadow
links which are approached by the shadow vehicle
void addLCSpeedAdvice(const double vSafe, bool ownAdvice=true)
Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration ...
void setLeaderGaps(CLeaderDist, double secGap)
const std::shared_ptr< MSLeaderDistanceInfo > getLeaders(const int dir)
Returns the neighboring, lc-relevant leaders for the last step in the requested direction.
std::vector< MSLane * > myNoPartiallyOccupatedByShadow
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
double myLastLeaderGap
the actual minimum longitudinal distances to vehicles on the target lane
SUMOTime remainingTime() const
Compute the remaining time until LC completion.
void setOrigLeaderGaps(CLeaderDist, double secGap)
void setManeuverDist(const double dist)
Updates the remaining distance for the current maneuver while it is continued within non-action steps...
std::vector< std::pair< double, bool > > myLCAccelerationAdvices
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
int getNormalizedLaneIndex()
brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
static MSAbstractLaneChangeModel * build(LaneChangeModel lcm, MSVehicle &vehicle)
Factory method for instantiating new lane changing models.
void changedToOpposite()
called when a vehicle changes between lanes in opposite directions
void setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
MSLane * myTargetLane
The target lane for the vehicle's current maneuver.
MSLane * determineTargetLane(int &targetDir) const
double myPreviousManeuverDist
Maneuver distance from the previous simulation step.
double getMaxSpeedLat2() const
return the max of maxSpeedLat and lcMaxSpeedLatStanding
std::vector< double > myShadowFurtherLanesPosLat
MSLane * myShadowLane
A lane that is partially occupied by the front of the vehicle but that is not the primary lane.
double mySpeedLat
the current lateral speed
virtual void updateSafeLatDist(const double travelledLatDist)
Updates the value of safe lateral distances (in SL2015) during maneuver continuation in non-action st...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
double myManeuverDist
The complete lateral distance the vehicle wants to travel to finish its maneuver Only used by sublane...
int myLaneChangeDirection
direction of the lane change maneuver -1 means right, 1 means left
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
int getShadowDirection() const
return the direction in which the current shadow lane lies
double myLastLeaderSpeed
speeds of surrounding vehicles at the time of lane change
virtual void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the laneChangeModel from the given attributes.
MSAbstractLaneChangeModel(MSVehicle &v, const LaneChangeModel model)
Constructor.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
double calcAngleOffset()
return the angle offset during a continuous change maneuver
double myAngleOffset
the current angle offset resulting from lane change and sigma
double myLastLateralGapLeft
the minimum lateral gaps to other vehicles that were found when last changing to the left and right
virtual ~MSAbstractLaneChangeModel()
Destructor.
static void initGlobalOptions(const OptionsCont &oc)
init global model parameters
void memorizeGapsAtLCInit()
Control for resetting the memorized values for LC relevant gaps until the LC output is triggered in t...
double myLaneChangeCompletion
progress of the lane change maneuver 0:started, 1:complete
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
virtual void changed()=0
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
std::vector< MSLane * > myShadowFurtherLanes
virtual bool congested(const MSVehicle *const neighLeader)
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...
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getLength() const
Returns the vehicle's length.
MSStop & getNextStop()
double getWidth() const
Returns the vehicle's width.
SumoRNG * getRNG() const
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
virtual double interactionGap(const MSVehicle *const veh, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
Definition: MSCFModel.cpp:277
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.cpp:166
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:264
A device which collects info on the vehicle trip (mainly on departure and arrival)
int getNumLanes() const
Definition: MSEdge.h:172
static double gLateralResolution
Definition: MSGlobals.h:97
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition: MSGlobals.h:160
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:94
A lane change model developed by D. Krajzewicz between 2004 and 2010.
Definition: MSLCM_DK2008.h:37
A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013,...
A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013.
Definition: MSLCM_LC2013.h:45
A lane change model developed by J. Erdmann.
Definition: MSLCM_SL2015.h:35
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2714
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition: MSLane.cpp:411
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2609
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:1316
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:584
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:3208
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:358
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:634
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:3201
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:4241
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:752
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:377
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition: MSLane.cpp:400
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition: MSLane.cpp:4235
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
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
Notification
Definition of a vehicle state.
@ NOTIFICATION_LANE_CHANGE
The vehicle changes lanes (micro only)
@ NOTIFICATION_PARKING
The vehicle starts or ends parking.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
bool isOpposite
whether this an opposite-direction stop
Definition: MSStop.h:87
double getLatDist() const
Definition: MSVehicle.h:1587
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
const std::vector< double > & getFurtherLanesPosLat() const
Definition: MSVehicle.h:847
void setTentativeLaneAndPosition(MSLane *lane, double pos, double posLat=0)
set tentative lane and position during insertion to ensure that all cfmodels work (some of them requi...
Definition: MSVehicle.cpp:6613
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:843
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5720
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:7217
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:6429
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition: MSVehicle.h:517
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1242
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
Definition: MSVehicle.cpp:6788
void leaveLane(const MSMoveReminder::Notification reason, const MSLane *approachedLane=0)
Update of members if vehicle leaves a new lane in the lane change step or at arrival.
Definition: MSVehicle.cpp:5626
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1170
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition: MSVehicle.h:1109
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition: MSVehicle.h:1111
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:5421
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7182
double updateFurtherLanes(std::vector< MSLane * > &furtherLanes, std::vector< double > &furtherLanesPosLat, const std::vector< MSLane * > &passedLanes)
update a vector of further lanes and return the new backPos
Definition: MSVehicle.cpp:4829
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
bool congested() const
Definition: MSVehicle.cpp:1460
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
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
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:974
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
Definition: MSVehicle.cpp:6844
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition: MSVehicle.h:1678
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1162
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
Definition: MSVehicle.cpp:3903
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMinGap() const
Get the free space in front of vehicles of this class.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:80
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
const SUMOVTypeParameter & getParameter() const
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
double x() const
Returns the x-position.
Definition: Position.h:55
double y() const
Returns the y-position.
Definition: Position.h:60
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
std::map< SumoXMLAttr, std::string > SubParams
sub-model parameters
const SubParams & getLCParams() const
Returns the LC parameter.
Definition: json.hpp:4471
#define M_PI
Definition: odrSpiral.cpp:45