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.org/sumo
3 // Copyright (C) 2001-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
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 <microsim/MSNet.h>
40 #include <microsim/MSEdge.h>
41 #include <microsim/MSLane.h>
42 #include <microsim/MSLink.h>
43 #include <microsim/MSStop.h>
44 #include <microsim/MSDriverState.h>
45 #include <microsim/MSGlobals.h>
47 #include "MSLCM_DK2008.h"
48 #include "MSLCM_LC2013.h"
49 #include "MSLCM_SL2015.h"
50 
51 /* -------------------------------------------------------------------------
52  * static members
53  * ----------------------------------------------------------------------- */
59 const double MSAbstractLaneChangeModel::NO_NEIGHBOR(std::numeric_limits<double>::max());
60 
61 /* -------------------------------------------------------------------------
62  * MSAbstractLaneChangeModel-methods
63  * ----------------------------------------------------------------------- */
64 
65 void
67  myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
68  myLCOutput = oc.isSet("lanechange-output");
69  myLCStartedOutput = oc.getBool("lanechange-output.started");
70  myLCEndedOutput = oc.getBool("lanechange-output.ended");
71  myLCXYOutput = oc.getBool("lanechange-output.xy");
72 }
73 
74 
78  throw ProcessError("Lane change model '" + toString(lcm) + "' is not compatible with sublane simulation");
79  }
80  switch (lcm) {
82  return new MSLCM_DK2008(v);
84  return new MSLCM_LC2013(v);
86  return new MSLCM_SL2015(v);
89  return new MSLCM_LC2013(v);
90  } else {
91  return new MSLCM_SL2015(v);
92  }
93  default:
94  throw ProcessError("Lane change model '" + toString(lcm) + "' not implemented");
95  }
96 }
97 
98 
100  myVehicle(v),
101  myOwnState(0),
102  myPreviousState(0),
103  myPreviousState2(0),
104  myCanceledStateRight(LCA_NONE),
105  myCanceledStateCenter(LCA_NONE),
106  myCanceledStateLeft(LCA_NONE),
107  mySpeedLat(0),
108  myAccelerationLat(0),
109  myCommittedSpeed(0),
110  myLaneChangeCompletion(1.0),
111  myLaneChangeDirection(0),
112  myAlreadyChanged(false),
113  myShadowLane(nullptr),
114  myTargetLane(nullptr),
115  myModel(model),
116  myLastLateralGapLeft(0.),
117  myLastLateralGapRight(0.),
118  myLastLeaderGap(0.),
119  myLastFollowerGap(0.),
120  myLastLeaderSecureGap(0.),
121  myLastFollowerSecureGap(0.),
122  myLastOrigLeaderGap(0.),
123  myLastOrigLeaderSecureGap(0.),
124  myLastLeaderSpeed(0),
125  myLastFollowerSpeed(0),
126  myLastOrigLeaderSpeed(0),
127  myDontResetLCGaps(false),
128  myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
129  myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
130  myMaxDistLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXDISTLATSTANDING,
131  // prevent lateral sliding for cars but permit for two-wheelers due to better maneuverability
132  (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
133  mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
134  myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
135  myLastLaneChangeOffset(0),
136  myAmOpposite(false),
137  myManeuverDist(0.),
138  myPreviousManeuverDist(0.) {
142 }
143 
144 
146 }
147 
148 void
151  myOwnState = state;
152  myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
153 }
154 
155 void
156 MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
157  UNUSED_PARAMETER(travelledLatDist);
158 }
159 
160 
161 void
163 #ifdef DEBUG_MANEUVER
164  if (DEBUG_COND) {
165  std::cout << SIMTIME
166  << " veh=" << myVehicle.getID()
167  << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
168  << std::endl;
169  }
170 #endif
171  myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
172  // store value which may be modified by the model during the next step
174 }
175 
176 
177 double
179  return myManeuverDist;
180 }
181 
182 double
184  return myPreviousManeuverDist;
185 }
186 
187 void
189  if (dir == -1) {
190  myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
191  myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
192  } else if (dir == 1) {
193  myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
194  myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
195  } else {
196  // dir \in {-1,1} !
197  assert(false);
198  }
199 }
200 
201 
202 void
203 MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
204  if (dir == -1) {
205  myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane());
206  myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane());
207  } else if (dir == 1) {
208  myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane());
209  myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane());
210  } else {
211  // dir \in {-1,1} !
212  assert(false);
213  }
214 }
215 
216 
217 void
219  myLeftFollowers = nullptr;
220  myLeftLeaders = nullptr;
221  myRightFollowers = nullptr;
222  myRightLeaders = nullptr;
223 }
224 
225 
226 const std::shared_ptr<MSLeaderDistanceInfo>
228  if (dir == -1) {
229  return myLeftFollowers;
230  } else if (dir == 1) {
231  return myRightFollowers;
232  } else {
233  // dir \in {-1,1} !
234  assert(false);
235  }
236  return nullptr;
237 }
238 
239 const std::shared_ptr<MSLeaderDistanceInfo>
241  if (dir == -1) {
242  return myLeftLeaders;
243  } else if (dir == 1) {
244  return myRightLeaders;
245  } else {
246  // dir \in {-1,1} !
247  assert(false);
248  }
249  return nullptr;
250 }
251 
252 
253 bool
255  if (neighLeader == nullptr) {
256  return false;
257  }
258  // Congested situation are relevant only on highways (maxSpeed > 70km/h)
259  // and congested on German Highways means that the vehicles have speeds
260  // below 60km/h. Overtaking on the right is allowed then.
261  if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
262 
263  return false;
264  }
265  if (myVehicle.congested() && neighLeader->congested()) {
266  return true;
267  }
268  return false;
269 }
270 
271 
272 
273 bool
274 MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
275  if (leader.first == 0) {
276  return false;
277  }
278  // let's check it on highways only
279  if (leader.first->getSpeed() < (80.0 / 3.6)) {
280  return false;
281  }
282  return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
283 }
284 
285 
286 bool
290  myLaneChangeDirection = direction;
291  setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
294  if (myLCOutput) {
296  }
297  return true;
298  } else {
299  primaryLaneChanged(source, target, direction);
300  return false;
301  }
302 }
303 
304 void
306  myDontResetLCGaps = true;
307 }
308 
309 void
311  myDontResetLCGaps = false;
312 }
313 
314 void
316  initLastLaneChangeOffset(direction);
318  source->leftByLaneChange(&myVehicle);
319  laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
320  if (&source->getEdge() != &target->getEdge()) {
322 #ifdef DEBUG_OPPOSITE
323  if (debugVehicle()) {
324  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
325  }
326 #endif
329  } else if (myAmOpposite) {
330 #ifdef DEBUG_OPPOSITE
331  if (debugVehicle()) {
332  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
333  }
334 #endif
335  myAlreadyChanged = true;
337  if (!MSGlobals::gSublane) {
338  // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
339  // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
341  }
342  } else {
344  }
345  target->enteredByLaneChange(&myVehicle);
346  // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
347  // This is necessary because the lane advance uses the target lane from the corresponding drive item.
349  changed();
350 }
351 
352 void
353 MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
354  if (myLCOutput) {
355  OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
356  of.openTag(tag);
359  of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
360  of.writeAttr(SUMO_ATTR_FROM, source->getID());
361  of.writeAttr(SUMO_ATTR_TO, target->getID());
362  of.writeAttr(SUMO_ATTR_DIR, direction);
365  of.writeAttr("reason", toString((LaneChangeAction)(myOwnState & ~(
370  of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
371  of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
372  of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed));
373  of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
374  of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
375  of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed));
376  of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
377  of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
378  of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed));
380  const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
381  of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
382  if (maneuverDist != 0) {
383  of.writeAttr("maneuverDistance", toString(maneuverDist));
384  }
385  }
386  if (myLCXYOutput) {
389  }
390  of.closeTag();
393  }
394  }
395 }
396 
397 
398 double
399 MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
401  int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
402  return DIST2SPEED(maneuverDist / stepsToChange);
403  } else {
404  return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
405  }
406 }
407 
408 
409 double
411  throw ProcessError("Method getAssumedDecelForLaneChangeDuration() not implemented by model " + toString(myModel));
412 }
413 
414 void
417  mySpeedLat = speedLat;
418 }
419 
420 bool
422  const bool pastBefore = pastMidpoint();
423  // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
424  double maneuverDist = getManeuverDist();
425  setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
427  return !pastBefore && pastMidpoint();
428 }
429 
430 
431 void
433  UNUSED_PARAMETER(reason);
442  // opposite driving continues after parking
443  } else {
444  // aborted maneuver
445 #ifdef DEBUG_OPPOSITE
446  if (debugVehicle()) {
447  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
448  }
449 #endif
451  }
452  }
453 }
454 
455 
456 MSLane*
457 MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
459  // initialize shadow lane
460  const double overlap = myVehicle.getLateralOverlap(posLat);
461 #ifdef DEBUG_SHADOWLANE
462  if (debugVehicle()) {
463  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
464  }
465 #endif
466  if (myAmOpposite) {
467  // return the neigh-lane in forward direction
468  return lane->getParallelLane(1);
469  } else if (overlap > NUMERICAL_EPS) {
470  const int shadowDirection = posLat < 0 ? -1 : 1;
471  return lane->getParallelLane(shadowDirection);
472  } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
473  // "reserve" target lane even when there is no overlap yet
475  } else {
476  return nullptr;
477  }
478  } else {
479  return nullptr;
480  }
481 }
482 
483 
484 MSLane*
487 }
488 
489 
490 void
492  if (myShadowLane != nullptr) {
493  if (debugVehicle()) {
494  std::cout << SIMTIME << " cleanupShadowLane\n";
495  }
497  myShadowLane = nullptr;
498  }
499  for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
500  if (debugVehicle()) {
501  std::cout << SIMTIME << " cleanupShadowLane2\n";
502  }
503  (*it)->resetPartialOccupation(&myVehicle);
504  }
505  myShadowFurtherLanes.clear();
507 }
508 
509 void
511  if (myTargetLane != nullptr) {
512  if (debugVehicle()) {
513  std::cout << SIMTIME << " cleanupTargetLane\n";
514  }
516  myTargetLane = nullptr;
517  }
518  for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
519  if (debugVehicle()) {
520  std::cout << SIMTIME << " cleanupTargetLane\n";
521  }
522  if (*it != nullptr) {
523  (*it)->resetManeuverReservation(&myVehicle);
524  }
525  }
526  myFurtherTargetLanes.clear();
527 // myNoPartiallyOccupatedByShadow.clear();
528 }
529 
530 
531 bool
532 MSAbstractLaneChangeModel::cancelRequest(int state, int laneOffset) {
533  // store request before canceling
534  getCanceledState(laneOffset) |= state;
535  int ret = myVehicle.influenceChangeDecision(state);
536  return ret != state;
537 }
538 
539 double
542 }
543 
544 void
546  if (dir > 0) {
548  } else if (dir < 0) {
550  }
551 }
552 
553 void
555  if (!MSGlobals::gSublane) {
556  // assume each vehicle drives at the center of its lane and act as if it fits
557  return;
558  }
559  if (myShadowLane != nullptr) {
560 #ifdef DEBUG_SHADOWLANE
561  if (debugVehicle()) {
562  std::cout << SIMTIME << " updateShadowLane()\n";
563  }
564 #endif
566  }
568  std::vector<MSLane*> passed;
569  if (myShadowLane != nullptr) {
571  const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
572  if (myAmOpposite) {
573  assert(further.size() == 0);
574  } else {
575  const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
576  assert(further.size() == furtherPosLat.size());
577  passed.push_back(myShadowLane);
578  for (int i = 0; i < (int)further.size(); ++i) {
579  MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
580 #ifdef DEBUG_SHADOWLANE
581  if (debugVehicle()) {
582  std::cout << SIMTIME << " further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
583  }
584 #endif
585  if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
586  passed.push_back(shadowFurther);
587  }
588  }
589  std::reverse(passed.begin(), passed.end());
590  }
591  } else {
592  if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
593  WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
594  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
596  }
597  }
598 #ifdef DEBUG_SHADOWLANE
599  if (debugVehicle()) {
600  std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
601  << " newShadowLane=" << Named::getIDSecure(myShadowLane)
602  << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
603  std::cout << std::endl;
604  }
605 #endif
607 #ifdef DEBUG_SHADOWLANE
608  if (debugVehicle()) std::cout
609  << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
610 #endif
611 }
612 
613 
614 int
616  if (isChangingLanes()) {
617  if (pastMidpoint()) {
618  return -myLaneChangeDirection;
619  } else {
620  return myLaneChangeDirection;
621  }
622  } else if (myShadowLane == nullptr) {
623  return 0;
624  } else if (myAmOpposite) {
625  // return neigh-lane in forward direction
626  return 1;
627  } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
629  } else {
630  // overlap with opposite direction lane
631  return 1;
632  }
633 }
634 
635 
636 MSLane*
638 #ifdef DEBUG_TARGET_LANE
639  MSLane* oldTarget = myTargetLane;
640  std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
641  if (debugVehicle()) {
642  std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
643  << "\n oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
644  << " oldFurtherTargets: " << toString(oldFurtherTargets);
645  }
646 #endif
647  if (myTargetLane != nullptr) {
649  }
650  // Clear old further target lanes
651  for (MSLane* oldTargetLane : myFurtherTargetLanes) {
652  if (oldTargetLane != nullptr) {
653  oldTargetLane->resetManeuverReservation(&myVehicle);
654  }
655  }
656  myFurtherTargetLanes.clear();
657 
658  // Get new target lanes and issue a maneuver reservation.
659  int targetDir;
660  myTargetLane = determineTargetLane(targetDir);
661  if (myTargetLane != nullptr) {
663  // further targets are just the target lanes corresponding to the vehicle's further lanes
664  // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
665  for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
666  MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
667  myFurtherTargetLanes.push_back(furtherTargetLane);
668  if (furtherTargetLane != nullptr) {
669  furtherTargetLane->setManeuverReservation(&myVehicle);
670  }
671  }
672  }
673 #ifdef DEBUG_TARGET_LANE
674  if (debugVehicle()) {
675  std::cout << "\n newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
676  << " newFurtherTargets: " << toString(myFurtherTargetLanes)
677  << std::endl;
678  }
679 #endif
680  return myTargetLane;
681 }
682 
683 
684 MSLane*
686  targetDir = 0;
687  if (myManeuverDist == 0) {
688  return nullptr;
689  }
690  // Current lateral boundaries of the vehicle
691  const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
692  const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
693  const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
694 
695  if (vehRight + myManeuverDist < -halfLaneWidth) {
696  // Vehicle intends to traverse the right lane boundary
697  targetDir = -1;
698  } else if (vehLeft + myManeuverDist > halfLaneWidth) {
699  // Vehicle intends to traverse the left lane boundary
700  targetDir = 1;
701  }
702  if (targetDir == 0) {
703  // Presently, no maneuvering into another lane is begun.
704  return nullptr;
705  }
706  MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
707  if (target == nullptr || target == myShadowLane) {
708  return nullptr;
709  } else {
710  return target;
711  }
712 }
713 
714 
715 
716 double
718  const double totalDuration = (myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)
721 
722  const double angleOffset = 60 / totalDuration * (pastMidpoint() ? 1 - myLaneChangeCompletion : myLaneChangeCompletion);
723  return myLaneChangeDirection * angleOffset;
724 }
725 
726 
727 double
728 MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
729 
731  if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
733  // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
735  } else {
736  return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
737  }
738  }
739 
740  if (remainingManeuverDist == 0) {
741  return 0;
742  }
743 
744  // Check argument assumptions
745  assert(speed >= 0);
746  assert(remainingManeuverDist >= 0);
747  assert(decel > 0);
748  assert(myVehicle.getVehicleType().getMaxSpeedLat() > 0);
750  assert(myMaxSpeedLatStanding >= 0);
751 
752  // for brevity
753  const double v0 = speed;
754  const double D = remainingManeuverDist;
755  const double b = decel;
756  const double wmin = myMaxSpeedLatStanding;
757  const double f = myMaxSpeedLatFactor;
758  const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
759 
760  /* Here's the approach for the calculation of the required time for the LC:
761  * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
762  * Where v(t)=0 <=> t >= ts:=v0/b
763  * For the lateral speed w(t) this gives:
764  * w(t) = min(wmax, wmin + f*v(t))
765  * The lateral distance covered until t is
766  * d(t) = int_0^t w(s) ds
767  * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
768  * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
769  * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
770  * 3) w(T) = wmin, i.e., v(T)=0
771  */
772  const double vm = (wmax - wmin) / f;
773  double distSoFar = 0.;
774  double timeSoFar = 0.;
775  double v = v0;
776  if (v > vm) {
777  const double wmaxTime = (v0 - vm) / b;
778  const double d1 = wmax * wmaxTime;
779  if (d1 >= D) {
780  return D / wmax;
781  } else {
782  distSoFar += d1;
783  timeSoFar += wmaxTime;
784  v = vm;
785  }
786  }
787  if (v > 0) {
788  /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
789  * Thus, the additional lateral distance covered after time t is:
790  * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
791  * and the additional lateral distance covered until v=0 at t=v/b is:
792  * d2 = (wmin + 0.5*f*v)*t
793  */
794  const double t = v / b; // stop time
795  const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
796  assert(d2 > 0);
797  if (distSoFar + d2 >= D) {
798  // LC is completed during this phase
799  const double x = 0.5 * f * b;
800  const double y = wmin + f * v;
801  /* Solve D - distSoFar = y*t - x*t^2.
802  * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
803  */
804  const double p = 0.5 * y / x;
805  const double q = (D - distSoFar) / x;
806  assert(p * p - q > 0);
807  const double t2 = p + sqrt(p * p - q);
808  return timeSoFar + t2;
809  } else {
810  distSoFar += d2;
811  timeSoFar += t;
812  //v = 0;
813  }
814  }
815  // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
816  if (wmin == 0) {
817  // LC won't be completed if vehicle stands
818  double maneuverDist = remainingManeuverDist;
819  const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
820  if (vModel > 0) {
821  // unless the model tells us something different
822  return D / vModel;
823  } else {
824  return -1;
825  }
826  } else {
827  // complete LC with lateral speed wmin
828  return timeSoFar + (D - distSoFar) / wmin;
829  }
830 }
831 
832 SUMOTime
834  assert(isChangingLanes()); // Only to be called during ongoing lane change
836  if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
839  } else {
841  }
842  }
843  // Using maxSpeedLat(Factor/Standing)
844  const bool urgent = (myOwnState & LCA_URGENT) != 0;
848 }
849 
850 
851 void
853  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
854  myApproachedByShadow.push_back(link);
855 }
856 
857 void
859  for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
860  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
861  (*it)->removeApproaching(&myVehicle);
862  }
863  myApproachedByShadow.clear();
864 }
865 
866 
867 
868 void
871  int oldstate = myVehicle.getLaneChangeModel().getOwnState();
872  if (myOwnState != newstate) {
874  // Calculate and set the lateral maneuver distance corresponding to the change request
875  // to induce a corresponding sublane change.
876  const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
877  // minimum distance to move the vehicle fully onto the lane at offset dir
878  const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
879  if ((newstate & LCA_TRACI) != 0) {
880  if ((newstate & LCA_STAY) != 0) {
881  setManeuverDist(0.);
882  } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
883  || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
884  setManeuverDist(latLaneDist);
885  }
886  }
887  if (myVehicle.hasInfluencer()) {
888  // lane change requests override sublane change requests
890  }
891 
892  }
893  setOwnState(newstate);
894  } else {
895  // Check for sublane change requests
897  const double maneuverDist = myVehicle.getInfluencer().getLatDist();
900  newstate |= LCA_TRACI;
901  if (myOwnState != newstate) {
902  setOwnState(newstate);
903  }
904  if (gDebugFlag2) {
905  std::cout << " traci influenced maneuverDist=" << maneuverDist << "\n";
906  }
907  }
908  }
909  if (gDebugFlag2) {
910  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
911  }
912 }
913 
914 void
917  myAlreadyChanged = true;
918 }
919 
920 void
922  if (follower.first != 0) {
923  myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
924  myLastFollowerSecureGap = secGap;
925  myLastFollowerSpeed = follower.first->getSpeed();
926  }
927 }
928 
929 void
931  if (leader.first != 0) {
932  myLastLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
933  myLastLeaderSecureGap = secGap;
934  myLastLeaderSpeed = leader.first->getSpeed();
935  }
936 }
937 
938 void
940  if (leader.first != 0) {
942  myLastOrigLeaderSecureGap = secGap;
943  myLastOrigLeaderSpeed = leader.first->getSpeed();
944  }
945 }
946 
947 void
957  if (!myDontResetLCGaps) {
967  }
968  myCommittedSpeed = 0;
969 }
970 
971 void
973  int rightmost;
974  int leftmost;
975  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
976  for (int i = rightmost; i <= leftmost; ++i) {
977  CLeaderDist vehDist = vehicles[i];
978  if (vehDist.first != 0) {
979  const MSVehicle* leader = &myVehicle;
980  const MSVehicle* follower = vehDist.first;
981  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
982  if (netGap < myLastFollowerGap && netGap >= 0) {
983  myLastFollowerGap = netGap;
984  myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
985  myLastFollowerSpeed = follower->getSpeed();
986  }
987  }
988  }
989 }
990 
991 void
993  int rightmost;
994  int leftmost;
995  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
996  for (int i = rightmost; i <= leftmost; ++i) {
997  CLeaderDist vehDist = vehicles[i];
998  if (vehDist.first != 0) {
999  const MSVehicle* leader = vehDist.first;
1000  const MSVehicle* follower = &myVehicle;
1001  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1002  if (netGap < myLastLeaderGap && netGap >= 0) {
1003  myLastLeaderGap = netGap;
1004  myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1005  myLastLeaderSpeed = leader->getSpeed();
1006  }
1007  }
1008  }
1009 }
1010 
1011 void
1013  int rightmost;
1014  int leftmost;
1015  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1016  for (int i = rightmost; i <= leftmost; ++i) {
1017  CLeaderDist vehDist = vehicles[i];
1018  if (vehDist.first != 0) {
1019  const MSVehicle* leader = vehDist.first;
1020  const MSVehicle* follower = &myVehicle;
1021  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1022  if (netGap < myLastOrigLeaderGap && netGap >= 0) {
1023  myLastOrigLeaderGap = netGap;
1024  myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1025  myLastOrigLeaderSpeed = leader->getSpeed();
1026  }
1027  }
1028  }
1029 }
1030 
1031 
1032 bool
1034  const int stateRight = mySavedStateRight.second;
1035  if (
1036  (stateRight & LCA_STRATEGIC) != 0
1037  && (stateRight & LCA_RIGHT) != 0
1038  && (stateRight & LCA_BLOCKED) != 0) {
1039  return true;
1040  }
1041  const int stateLeft = mySavedStateLeft.second;
1042  if (
1043  (stateLeft & LCA_STRATEGIC) != 0
1044  && (stateLeft & LCA_LEFT) != 0
1045  && (stateLeft & LCA_BLOCKED) != 0) {
1046  return true;
1047  }
1048  return false;
1049 }
1050 
1051 double
1054 }
1055 
1056 
1057 int
1059  const int i = myVehicle.getLane()->getIndex();
1060  if (myAmOpposite) {
1062  } else {
1063  return i;
1064  }
1065 }
#define DEBUG_COND
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:32
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define SPEED2DIST(x)
Definition: SUMOTime.h:43
#define SIMTIME
Definition: SUMOTime.h:60
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
#define DIST2SPEED(x)
Definition: SUMOTime.h:45
long long int SUMOTime
Definition: SUMOTime.h:32
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:51
const int VTYPEPARS_MAXSPEED_LAT_SET
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_MOTORCYCLE
vehicle is a motorcycle
@ 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_DIR
The abstract direction of a link.
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_TIME
trigger: the time of the step
bool gDebugFlag2
Definition: StdDefs.cpp:33
const double SUMO_const_laneWidth
Definition: StdDefs.h:48
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:80
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
void saveLCState(const int dir, const int stateWithoutTraCI, const int state)
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
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
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)
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
std::vector< MSLink * > myApproachedByShadow
links which are approached by the shadow vehicle
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
const LaneChangeModel myModel
the type of this model
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...
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
MSAbstractLaneChangeModel(MSVehicle &v, const LaneChangeModel model)
Constructor.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
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
double getAngleOffset() const
return the angle offset during a continuous change maneuver
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)
MSStop & getNextStop()
double getWidth() const
Returns the vehicle's width.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
virtual double getSecureGap(const MSVehicle *const, 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.h:351
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:222
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:239
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:88
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition: MSGlobals.h:148
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:85
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.
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:82
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:2300
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition: MSLane.cpp:330
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2214
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:1102
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:533
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2770
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:277
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:563
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2763
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:3817
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:674
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:296
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition: MSLane.cpp:319
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition: MSLane.cpp:3811
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:556
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:133
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:174
bool isOpposite
whether this an opposite-direction stop
Definition: MSStop.h:89
double getLatDist() const
Definition: MSVehicle.h:1542
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:75
const std::vector< double > & getFurtherLanesPosLat() const
Definition: MSVehicle.h:796
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:5878
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:792
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5051
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:6424
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:5686
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1142
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
Definition: MSVehicle.cpp:6012
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:4965
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1129
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition: MSVehicle.h:1068
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition: MSVehicle.h:1070
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:4824
Influencer & getInfluencer()
Definition: MSVehicle.cpp:6389
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:4277
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:411
bool congested() const
Definition: MSVehicle.cpp:1324
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:462
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:372
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:552
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:917
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
Definition: MSVehicle.cpp:6064
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition: MSVehicle.h:1633
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1121
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
Definition: MSVehicle.cpp:3416
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].
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:90
bool wasSet(int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:79
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:248
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
std::map< SumoXMLAttr, std::string > SubParams
sub-model parameters
const SubParams & getLCParams() const
Returns the LC parameter.