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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
20 // Interface for lane-change models
21 /****************************************************************************/
22 
23 // ===========================================================================
24 // DEBUG
25 // ===========================================================================
26 //#define DEBUG_TARGET_LANE
27 //#define DEBUG_SHADOWLANE
28 #define DEBUG_COND (myVehicle.isSelected())
29 
30 
31 // ===========================================================================
32 // included modules
33 // ===========================================================================
34 #include <config.h>
35 
38 #include <microsim/MSNet.h>
39 #include <microsim/MSEdge.h>
40 #include <microsim/MSLane.h>
41 #include <microsim/MSGlobals.h>
42 #include "MSLCM_DK2008.h"
43 #include "MSLCM_LC2013.h"
44 #include "MSLCM_SL2015.h"
45 
46 /* -------------------------------------------------------------------------
47  * static members
48  * ----------------------------------------------------------------------- */
53 const double MSAbstractLaneChangeModel::NO_NEIGHBOR(std::numeric_limits<double>::max());
54 
55 /* -------------------------------------------------------------------------
56  * MSAbstractLaneChangeModel-methods
57  * ----------------------------------------------------------------------- */
58 
59 void
61  myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
62  myLCOutput = oc.isSet("lanechange-output");
63  myLCStartedOutput = oc.getBool("lanechange-output.started");
64  myLCEndedOutput = oc.getBool("lanechange-output.ended");
65 }
66 
67 
70  if (MSGlobals::gLateralResolution > 0 && lcm != LCM_SL2015 && lcm != LCM_DEFAULT) {
71  throw ProcessError("Lane change model '" + toString(lcm) + "' is not compatible with sublane simulation");
72  }
73  switch (lcm) {
74  case LCM_DK2008:
75  return new MSLCM_DK2008(v);
76  case LCM_LC2013:
77  return new MSLCM_LC2013(v);
78  case LCM_SL2015:
79  return new MSLCM_SL2015(v);
80  case LCM_DEFAULT:
82  return new MSLCM_LC2013(v);
83  } else {
84  return new MSLCM_SL2015(v);
85  }
86  default:
87  throw ProcessError("Lane change model '" + toString(lcm) + "' not implemented");
88  }
89 }
90 
91 
93  myVehicle(v),
94  myOwnState(0),
95  myPreviousState(0),
97  mySpeedLat(0),
101  myManeuverDist(0.),
102  myAlreadyChanged(false),
103  myShadowLane(nullptr),
104  myTargetLane(nullptr),
105  myCarFollowModel(v.getCarFollowModel()),
106  myModel(model),
109  myLastLeaderGap(0.),
110  myLastFollowerGap(0.),
115  myDontResetLCGaps(false),
116  myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
117  myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
119  myAmOpposite(false) {
120 }
121 
122 
124 }
125 
126 void
129  myOwnState = state;
130  myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
131 }
132 
133 void
134 MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
135  UNUSED_PARAMETER(travelledLatDist);
136 }
137 
138 
139 void
141 #ifdef DEBUG_MANEUVER
142  if DEBUG_COND {
143  std::cout << SIMTIME
144  << " veh=" << myVehicle.getID()
145  << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
146  << std::endl;
147  }
148 #endif
149  myManeuverDist = dist;
150 }
151 
152 
153 double
155  return myManeuverDist;
156 }
157 
158 
159 bool
161  if (neighLeader == nullptr) {
162  return false;
163  }
164  // Congested situation are relevant only on highways (maxSpeed > 70km/h)
165  // and congested on German Highways means that the vehicles have speeds
166  // below 60km/h. Overtaking on the right is allowed then.
167  if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
168 
169  return false;
170  }
171  if (myVehicle.congested() && neighLeader->congested()) {
172  return true;
173  }
174  return false;
175 }
176 
177 
178 
179 bool
180 MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
181  if (leader.first == 0) {
182  return false;
183  }
184  // let's check it on highways only
185  if (leader.first->getSpeed() < (80.0 / 3.6)) {
186  return false;
187  }
188  return leader.second < myCarFollowModel.interactionGap(&myVehicle, leader.first->getSpeed());
189 }
190 
191 
192 bool
194  if (&source->getEdge() != &target->getEdge()) {
196  }
199  myLaneChangeDirection = direction;
200  setManeuverDist(target->getCenterOnEdge() - source->getCenterOnEdge());
203  if (myLCOutput) {
205  }
206  return true;
207  } else {
208  primaryLaneChanged(source, target, direction);
209  return false;
210  }
211 }
212 
213 void
215  myDontResetLCGaps = true;
216 }
217 
218 void
220  myDontResetLCGaps = false;
221 }
222 
223 void
225  initLastLaneChangeOffset(direction);
227  source->leftByLaneChange(&myVehicle);
229  target->enteredByLaneChange(&myVehicle);
230  laneChangeOutput("change", source, target, direction);
231  // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
232  // This is necessary because the lane advance uses the target lane from the corresponding drive item.
234  changed();
235 }
236 
237 void
238 MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction) {
239  if (myLCOutput) {
240  OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
241  of.openTag(tag);
244  of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
245  of.writeAttr(SUMO_ATTR_FROM, source->getID());
246  of.writeAttr(SUMO_ATTR_TO, target->getID());
247  of.writeAttr(SUMO_ATTR_DIR, direction);
250  of.writeAttr("reason", toString((LaneChangeAction)(myOwnState & ~(
255  of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
256  of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
257  of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
258  of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
259  of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
260  of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
262  const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
263  of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
264  }
265  of.closeTag();
268  }
269  }
270 }
271 
272 
273 double
274 MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist) {
276  int stepsToChange = (int)ceil(maneuverDist / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
277  return DIST2SPEED(maneuverDist / stepsToChange);
278  } else {
279  return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
280  }
281 }
282 
283 
284 double
286  throw ProcessError("Method getAssumedDecelForLaneChangeDuration() not implemented by model " + toString(myModel));
287 }
288 
289 
290 bool
292  const bool pastBefore = pastMidpoint();
293  // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
294  double maneuverDist = getManeuverDist();
295  mySpeedLat = computeSpeedLat(0, maneuverDist);
297  return !pastBefore && pastMidpoint();
298 }
299 
300 
301 void
303  UNUSED_PARAMETER(reason);
310  if (myAmOpposite) {
312  }
313 }
314 
315 
316 MSLane*
317 MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
319  // initialize shadow lane
320  const double overlap = myVehicle.getLateralOverlap(posLat);
321 #ifdef DEBUG_SHADOWLANE
322  if (debugVehicle()) {
323  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
324  }
325 #endif
326  if (overlap > NUMERICAL_EPS) {
327  const int shadowDirection = posLat < 0 ? -1 : 1;
328  return lane->getParallelLane(shadowDirection);
329  } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
330  // "reserve" target lane even when there is no overlap yet
332  } else {
333  return nullptr;
334  }
335  } else {
336  return nullptr;
337  }
338 }
339 
340 
341 MSLane*
344 }
345 
346 
347 void
349  if (myShadowLane != nullptr) {
350  if (debugVehicle()) {
351  std::cout << SIMTIME << " cleanupShadowLane\n";
352  }
354  myShadowLane = nullptr;
355  }
356  for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
357  if (debugVehicle()) {
358  std::cout << SIMTIME << " cleanupShadowLane2\n";
359  }
360  (*it)->resetPartialOccupation(&myVehicle);
361  }
362  myShadowFurtherLanes.clear();
364 }
365 
366 void
368  if (myTargetLane != nullptr) {
369  if (debugVehicle()) {
370  std::cout << SIMTIME << " cleanupTargetLane\n";
371  }
373  myTargetLane = nullptr;
374  }
375  for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
376  if (debugVehicle()) {
377  std::cout << SIMTIME << " cleanupTargetLane\n";
378  }
379  if (*it != nullptr) {
380  (*it)->resetManeuverReservation(&myVehicle);
381  }
382  }
383  myFurtherTargetLanes.clear();
384 // myNoPartiallyOccupatedByShadow.clear();
385 }
386 
387 
388 bool
389 MSAbstractLaneChangeModel::cancelRequest(int state, int laneOffset) {
390  // store request before canceling
391  myCanceledStates[laneOffset] |= state;
392  int ret = myVehicle.influenceChangeDecision(state);
393  return ret != state;
394 }
395 
396 
397 void
399  if (dir > 0) {
401  } else if (dir < 0) {
403  }
404 }
405 
406 void
408  if (!haveLateralDynamics()) {
409  // assume each vehicle drives at the center of its lane and act as if it fits
410  return;
411  }
412  if (myShadowLane != nullptr) {
413 #ifdef DEBUG_SHADOWLANE
414  if (debugVehicle()) {
415  std::cout << SIMTIME << " updateShadowLane()\n";
416  }
417 #endif
419  }
421  std::vector<MSLane*> passed;
422  if (myShadowLane != nullptr) {
424  const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
425  const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
426  assert(further.size() == furtherPosLat.size());
427  passed.push_back(myShadowLane);
428  for (int i = 0; i < (int)further.size(); ++i) {
429  MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
430 #ifdef DEBUG_SHADOWLANE
431  if (debugVehicle()) {
432  std::cout << SIMTIME << " further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
433  }
434 #endif
435  if (shadowFurther != nullptr && MSLinkContHelper::getConnectingLink(*shadowFurther, *passed.back()) != nullptr) {
436  passed.push_back(shadowFurther);
437  }
438  }
439  std::reverse(passed.begin(), passed.end());
440  } else {
442  WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
443  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
445  }
446  }
447 #ifdef DEBUG_SHADOWLANE
448  if (debugVehicle()) {
449  std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
450  << " newShadowLane=" << Named::getIDSecure(myShadowLane)
451  << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
452  std::cout << std::endl;
453  }
454 #endif
456 #ifdef DEBUG_SHADOWLANE
457  if (debugVehicle()) std::cout
458  << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
459 #endif
460 }
461 
462 
463 int
465  if (isChangingLanes()) {
466  if (pastMidpoint()) {
467  return -myLaneChangeDirection;
468  } else {
469  return myLaneChangeDirection;
470  }
471  } else if (myShadowLane == nullptr) {
472  return 0;
473  } else {
474  assert(&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge());
476  }
477 }
478 
479 
480 void
482 #ifdef DEBUG_TARGET_LANE
483  MSLane* oldTarget = myTargetLane;
484  std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
485  if (debugVehicle()) {
486  std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
487  << "\n oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
488  << " oldFurtherTargets: " << toString(oldFurtherTargets);
489  }
490 #endif
491  if (myTargetLane != nullptr) {
493  }
494  // Clear old further target lanes
495  for (MSLane* oldTargetLane : myFurtherTargetLanes) {
496  if (oldTargetLane != nullptr) {
497  oldTargetLane->resetManeuverReservation(&myVehicle);
498  }
499  }
500  myFurtherTargetLanes.clear();
501 
502  // Get new target lanes and issue a maneuver reservation.
503  int targetDir;
504  myTargetLane = determineTargetLane(targetDir);
505  if (myTargetLane != nullptr) {
507  // further targets are just the target lanes corresponding to the vehicle's further lanes
508  // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
509  for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
510  MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
511  myFurtherTargetLanes.push_back(furtherTargetLane);
512  if (furtherTargetLane != nullptr) {
513  furtherTargetLane->setManeuverReservation(&myVehicle);
514  }
515  }
516  }
517 #ifdef DEBUG_TARGET_LANE
518  if (debugVehicle()) {
519  std::cout << "\n newTarget (offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
520  << " newFurtherTargets: " << toString(myFurtherTargetLanes)
521  << std::endl;
522  }
523 #endif
524 }
525 
526 
527 MSLane*
529  targetDir = 0;
530  if (myManeuverDist == 0) {
531  return nullptr;
532  }
533  // Current lateral boundaries of the vehicle
534  const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
535  const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
536  const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
537 
538  if (vehRight + myManeuverDist < -halfLaneWidth) {
539  // Vehicle intends to traverse the right lane boundary
540  targetDir = -1;
541  } else if (vehLeft + myManeuverDist > halfLaneWidth) {
542  // Vehicle intends to traverse the left lane boundary
543  targetDir = 1;
544  }
545  if (targetDir == 0) {
546  // Presently, no maneuvering into another lane is begun.
547  return nullptr;
548  }
549  MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
550  if (target == nullptr || target == myShadowLane) {
551  return nullptr;
552  } else {
553  return target;
554  }
555 }
556 
557 
558 
559 double
562  return myLaneChangeDirection * angleOffset;
563 }
564 
565 
566 double
567 MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel) const {
568 
570  if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
572  // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
574  } else {
575  return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
576  }
577  }
578 
579  if (remainingManeuverDist == 0) {
580  return 0;
581  }
582 
583  // Check argument assumptions
584  assert(speed >= 0);
585  assert(remainingManeuverDist >= 0);
586  assert(decel > 0);
587  assert(myVehicle.getVehicleType().getMaxSpeedLat() > 0);
589  assert(myMaxSpeedLatStanding >= 0);
590 
591  // for brevity
592  const double v0 = speed;
593  const double D = remainingManeuverDist;
594  const double b = decel;
595  const double wmin = myMaxSpeedLatStanding;
596  const double f = myMaxSpeedLatFactor;
597  const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
598 
599  /* Here's the approach for the calculation of the required time for the LC:
600  * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
601  * Where v(t)=0 <=> t >= ts:=v0/b
602  * For the lateral speed w(t) this gives:
603  * w(t) = min(wmax, wmin + f*v(t))
604  * The lateral distance covered until t is
605  * d(t) = int_0^t w(s) ds
606  * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
607  * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
608  * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
609  * 3) w(T) = wmin, i.e., v(T)=0
610  */
611  const double vm = (wmax - wmin) / f;
612  double distSoFar = 0.;
613  double timeSoFar = 0.;
614  double v = v0;
615  if (v > vm) {
616  const double wmaxTime = (v0 - vm) / b;
617  const double d1 = wmax * wmaxTime;
618  if (d1 >= D) {
619  return D / wmax;
620  } else {
621  distSoFar += d1;
622  timeSoFar += wmaxTime;
623  v = vm;
624  }
625  }
626  if (v > 0) {
627  /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
628  * Thus, the additional lateral distance covered after time t is:
629  * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
630  * and the additional lateral distance covered until v=0 at t=v/b is:
631  * d2 = (wmin + 0.5*f*v)*t
632  */
633  const double t = v / b; // stop time
634  const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
635  assert(d2 > 0);
636  if (distSoFar + d2 >= D) {
637  // LC is completed during this phase
638  const double x = 0.5 * f * b;
639  const double y = wmin + f * v;
640  /* Solve D - distSoFar = y*t - x*t^2.
641  * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
642  */
643  const double p = 0.5 * y / x;
644  const double q = (D - distSoFar) / x;
645  assert(p * p - q > 0);
646  const double t2 = p + sqrt(p * p - q);
647  return timeSoFar + t2;
648  } else {
649  distSoFar += d2;
650  timeSoFar += t;
651  //v = 0;
652  }
653  }
654  // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
655  if (wmin == 0) {
656  // LC won't be completed if vehicle stands
657  return -1;
658  } else {
659  // complete LC with lateral speed wmin
660  return timeSoFar + (D - distSoFar) / wmin;
661  }
662 }
663 
664 SUMOTime
666  assert(isChangingLanes()); // Only to be called during ongoing lane change
668  if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
671  } else {
673  }
674  }
675  // Using maxSpeedLat(Factor/Standing)
677 }
678 
679 
680 void
682  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
683  myApproachedByShadow.push_back(link);
684 }
685 
686 void
688  for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
689  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
690  (*it)->removeApproaching(&myVehicle);
691  }
692  myApproachedByShadow.clear();
693 }
694 
695 
696 
697 void
700  int oldstate = myVehicle.getLaneChangeModel().getOwnState();
701  if (myOwnState != newstate) {
703  // Calculate and set the lateral maneuver distance corresponding to the change request
704  // to induce a corresponding sublane change.
705  const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
706  // minimum distance to move the vehicle fully onto the lane at offset dir
707  const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
708  if ((newstate & LCA_TRACI) != 0) {
709  if ((newstate & LCA_STAY) != 0) {
710  setManeuverDist(0.);
711  } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
712  || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
713  setManeuverDist(latLaneDist);
714  }
715  }
716  if (myVehicle.hasInfluencer()) {
717  // lane change requests override sublane change requests
719  }
720 
721  }
722  setOwnState(newstate);
723  } else {
724  // Check for sublane change requests
726  const double maneuverDist = myVehicle.getInfluencer().getLatDist();
729  newstate |= LCA_TRACI;
730  if (myOwnState != newstate) {
731  setOwnState(newstate);
732  }
733  if (gDebugFlag2) {
734  std::cout << " traci influenced maneuverDist=" << maneuverDist << "\n";
735  }
736  }
737  }
738  if (DEBUG_COND) {
739  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
740  }
741 }
742 
743 void
746  myAlreadyChanged = true;
747 }
748 
749 void
751  if (follower.first != 0) {
752  myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
753  myLastFollowerSecureGap = secGap;
754  }
755 }
756 
757 void
759  if (leader.first != 0) {
760  myLastLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
761  myLastLeaderSecureGap = secGap;
762  }
763 }
764 
765 void
767  if (leader.first != 0) {
769  myLastOrigLeaderSecureGap = secGap;
770  }
771 }
772 
773 void
775  int rightmost;
776  int leftmost;
777  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
778  for (int i = rightmost; i <= leftmost; ++i) {
779  CLeaderDist vehDist = vehicles[i];
780  if (vehDist.first != 0) {
781  const MSVehicle* leader = &myVehicle;
782  const MSVehicle* follower = vehDist.first;
783  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
784  if (netGap < myLastFollowerGap && netGap >= 0) {
785  myLastFollowerGap = netGap;
786  myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
787  }
788  }
789  }
790 }
791 
792 void
794  int rightmost;
795  int leftmost;
796  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
797  for (int i = rightmost; i <= leftmost; ++i) {
798  CLeaderDist vehDist = vehicles[i];
799  if (vehDist.first != 0) {
800  const MSVehicle* leader = vehDist.first;
801  const MSVehicle* follower = &myVehicle;
802  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
803  if (netGap < myLastLeaderGap && netGap >= 0) {
804  myLastLeaderGap = netGap;
805  myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
806  }
807  }
808  }
809 }
810 
811 void
813  int rightmost;
814  int leftmost;
815  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
816  for (int i = rightmost; i <= leftmost; ++i) {
817  CLeaderDist vehDist = vehicles[i];
818  if (vehDist.first != 0) {
819  const MSVehicle* leader = vehDist.first;
820  const MSVehicle* follower = &myVehicle;
821  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
822  if (netGap < myLastOrigLeaderGap && netGap >= 0) {
823  myLastOrigLeaderGap = netGap;
825  }
826  }
827  }
828 }
bool myDontResetLCGaps
Flag to prevent resetting the memorized values for LC relevant gaps until the LC output is triggered ...
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
static double gLateralResolution
Definition: MSGlobals.h:85
A lane change model developed by J. Erdmann.
Definition: MSLCM_SL2015.h:38
#define DIST2SPEED(x)
Definition: SUMOTime.h:50
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
const SubParams & getLCParams() const
Returns the LC parameter.
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:129
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:640
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:79
long long int SUMOTime
Definition: SUMOTime.h:36
#define SPEED2DIST(x)
Definition: SUMOTime.h:48
std::map< SumoXMLAttr, std::string > SubParams
sub-model parameters
int myPreviousState
lane changing state from the previous simulation step
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change...
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:565
void setLeaderGaps(CLeaderDist, double secGap)
double myLastLeaderGap
the actual minimum longitudinal distances to vehicles on the target lane
int getShadowDirection() const
return the direction in which the current shadow lane lies
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model) ...
double myLaneChangeCompletion
progress of the lane change maneuver 0:started, 1:complete
static bool haveLateralDynamics()
whether any kind of lateral dynamics is active
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:403
Notification
Definition of a vehicle state.
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition: MSLane.cpp:288
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
Wants go to the right.
static bool myLCOutput
whether to record lane-changing
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
Definition: MSVehicle.cpp:5045
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
double myLastOrigLeaderGap
acutal and secure distance to closest leader vehicle on the original when performing lane change ...
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
double getAngleOffset() const
return the angle offset during a continuous change maneuver
#define DEBUG_COND
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:71
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key ...
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2506
MSLane * myShadowLane
A lane that is partially occupied by the front of the vehicle but that is not the primary lane...
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:78
virtual bool predInteraction(const std::pair< MSVehicle *, double > &leader)
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:244
const int VTYPEPARS_MAXSPEED_LAT_SET
Wants go to the left.
MSLane * myTargetLane
The target lane for the vehicle&#39;s current maneuver.
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition: MSLane.cpp:277
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:530
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:33
SUMOTime remainingTime() const
Compute the remaining time until LC completion.
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:4147
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
void memorizeGapsAtLCInit()
Control for resetting the memorized values for LC relevant gaps until the LC output is triggered in t...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4307
#define SIMTIME
Definition: SUMOTime.h:65
Right blinker lights are switched on.
Definition: MSVehicle.h:1177
bool wasSet(int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:83
std::vector< double > myShadowFurtherLanesPosLat
void setFollowerGaps(CLeaderDist follower, double secGap)
Needs to stay on the current lane.
const LaneChangeModel myModel
the type of this model
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
LaneChangeModel
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:4257
The vehicle changes lanes (micro only)
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:891
A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013...
Definition: MSLCM_LC2013.h:48
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:537
Left blinker lights are switched on.
Definition: MSVehicle.h:1179
std::vector< MSLane * > myNoPartiallyOccupatedByShadow
double myManeuverDist
The complete lateral distance the vehicle wants to travel to finish its maneuver Only used by sublane...
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:258
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it&#39;s primary lane ...
Definition: MSVehicle.cpp:5095
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:3630
virtual double getSecureGap(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:328
double getCenterOnEdge() const
Definition: MSLane.h:1035
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2513
std::vector< MSLane * > myShadowFurtherLanes
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:789
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:506
#define STEPS2TIME(x)
Definition: SUMOTime.h:58
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
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:224
int myLaneChangeDirection
direction of the lane change maneuver -1 means right, 1 means left
bool hasInfluencer() const
Definition: MSVehicle.h:1640
bool pastMidpoint() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver ...
double getMinGap() const
Get the free space in front of vehicles of this class.
virtual void changed()=0
static void initGlobalOptions(const OptionsCont &oc)
init global model parameters
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:218
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:4715
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
double myLastLeaderSecureGap
the minimum longitudinal distances to vehicles on the target lane that would be necessary for stringe...
int myOwnState
The current state of the vehicle.
MSLane * determineTargetLane(int &targetDir) const
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
const SUMOVTypeParameter & getParameter() const
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:440
void setOrigLeaderGaps(CLeaderDist, double secGap)
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
const std::vector< double > & getFurtherLanesPosLat() const
Definition: MSVehicle.h:793
double getMaxSpeedLat() const
Get vehicle&#39;s maximum lateral speed [m/s].
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:35
trigger: the time of the step
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:5488
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
virtual void setOwnState(const int state)
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
A storage for options typed value containers)
Definition: OptionsCont.h:92
std::vector< MSLane * > myFurtherTargetLanes
double mySpeedLat
the current lateral speed
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:94
The abstract direction of a link.
A lane change model developed by D. Krajzewicz between 2004 and 2010.
Definition: MSLCM_DK2008.h:40
virtual double computeSpeedLat(double latDist, double &maneuverDist)
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
The action is due to a TraCI request.
bool gDebugFlag2
Definition: StdDefs.cpp:33
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void changedToOpposite()
called when a vehicle changes between lanes in opposite directions
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1238
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1230
double myCommittedSpeed
the speed when committing to a change maneuver
#define NUMERICAL_EPS
Definition: config.h:148
std::vector< MSLink * > myApproachedByShadow
links which are approached by the shadow vehicle
MSLane * getShadowLane() const
Returns the lane the vehicle&#39;s shadow is on during continuous/sublane lane change.
void setManeuverDist(const double dist)
Updates the remaining distance for the current maneuver while it is continued within non-action steps...
virtual void updateSafeLatDist(const double travelledLatDist)
Updates the value of safe lateral distances (in SL2015) during maneuver continuation in non-action st...
int myPreviousState2
lane changing state from step before the previous simulation step
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:483
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:5512
double myLastLateralGapLeft
the minimum lateral gaps to other vehicles that were found when last changing to the left and right ...
double getLatDist() const
Definition: MSVehicle.h:1549
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:82
void laneChangeOutput(const std::string &tag, MSLane *source, MSLane *target, int direction)
called once the vehicle ends a lane change manoeuvre (non-instant)
static MSAbstractLaneChangeModel * build(LaneChangeModel lcm, MSVehicle &vehicle)
Factory method for instantiating new lane changing models.
const std::string & getID() const
Returns the name of the vehicle.
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
bool myAlreadyChanged
whether the vehicle has already moved this step
const MSCFModel & myCarFollowModel
The vehicle&#39;s car following model.
bool myAmOpposite
whether the vehicle is driving in the opposite direction
MSAbstractLaneChangeModel(MSVehicle &v, const LaneChangeModel model)
Constructor.
Interface for lane-change models.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
double getWidth() const
Returns the vehicle&#39;s width.
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2063
virtual bool congested(const MSVehicle *const neighLeader)
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
Definition: MSVehicle.cpp:3007
bool congested() const
Definition: MSVehicle.h:715
virtual ~MSAbstractLaneChangeModel()
Destructor.