Eclipse SUMO - Simulation of Urban MObility
MSLCM_LC2013.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 /****************************************************************************/
24 // A lane change model developed by J. Erdmann
25 // based on the model of D. Krajzewicz developed between 2004 and 2011 (MSLCM_DK2004)
26 /****************************************************************************/
27 #include <config.h>
28 
29 #include <iostream>
34 #include <microsim/MSEdge.h>
35 #include <microsim/MSLane.h>
36 #include <microsim/MSLink.h>
37 #include <microsim/MSDriverState.h>
38 #include <microsim/MSNet.h>
39 #include <microsim/MSStop.h>
40 #include "MSLCHelper.h"
41 #include "MSLCM_LC2013.h"
42 
43 
44 // ===========================================================================
45 // variable definitions
46 // ===========================================================================
47 #define MAGIC_OFFSET 1.
48 #define LOOK_FORWARD 10.
49 
50 #define JAM_FACTOR 1.
51 
52 #define LCA_RIGHT_IMPATIENCE -1.
53 #define CUT_IN_LEFT_SPEED_THRESHOLD 27.
54 
55 #define LOOK_AHEAD_MIN_SPEED 0.0
56 #define LOOK_AHEAD_SPEED_MEMORY 0.9
57 
58 #define HELP_DECEL_FACTOR 1.0
59 
60 #define HELP_OVERTAKE (10.0 / 3.6)
61 #define MIN_FALLBEHIND (7.0 / 3.6)
62 
63 #define RELGAIN_NORMALIZATION_MIN_SPEED 10.0
64 #define URGENCY 2.0
65 #define OPPOSITE_URGENCY 5.0
66 
67 #define KEEP_RIGHT_TIME 5.0 // the number of seconds after which a vehicle should move to the right lane
68 
69 #define KEEP_RIGHT_HEADWAY 2.0
70 #define MAX_ONRAMP_LENGTH 200.
71 #define TURN_LANE_DIST 200.0 // the distance at which a lane leading elsewhere is considered to be a turn-lane that must be avoided
72 
73 #define LC_RESOLUTION_SPEED_LAT 0.5 // the lateral speed (in m/s) for a standing vehicle which was unable to finish a continuous LC in time (in case mySpeedLatStanding==0), see #3771
74 
75 #define REACT_TO_STOPPED_DISTANCE 100
76 
77 // ===========================================================================
78 // debug defines
79 // ===========================================================================
80 //#define DEBUG_CONSTRUCTOR
81 //#define DEBUG_PATCH_SPEED
82 //#define DEBUG_INFORMED
83 //#define DEBUG_INFORMER
84 //#define DEBUG_WANTS_CHANGE
85 //#define DEBUG_SLOW_DOWN
86 //#define DEBUG_COOPERATE
87 //#define DEBUG_SAVE_BLOCKER_LENGTH
88 
89 //#define DEBUG_COND (myVehicle.getID() == "disabled")
90 #define DEBUG_COND (myVehicle.isSelected())
91 //#define DEBUG_COND (false)
92 
93 // ===========================================================================
94 // member method definitions
95 // ===========================================================================
98  mySpeedGainProbability(0),
99  myKeepRightProbability(0),
100  myLeadingBlockerLength(0),
101  myLeftSpace(0),
102  myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED),
103  myStrategicParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_PARAM, 1)),
104  myCooperativeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_PARAM, 1)),
105  mySpeedGainParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_PARAM, 1)),
106  myKeepRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_PARAM, 1)),
107  myOppositeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OPPOSITE_PARAM, 1)),
108  myLookaheadLeft(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_LOOKAHEADLEFT, 2.0)),
109  mySpeedGainRight(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAINRIGHT, 0.1)),
110  myAssertive(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_ASSERTIVE, 1)),
111  mySpeedGainLookahead(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD, 0)),
112  myRoundaboutBonus(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT, myCooperativeParam)),
113  myCooperativeSpeed(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_SPEED, myCooperativeParam)),
114  myKeepRightAcceptanceTime(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME, -1)),
115  myOvertakeDeltaSpeedFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR, 0)),
116  myExperimentalParam1(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_EXPERIMENTAL1, 0)) {
118 #ifdef DEBUG_CONSTRUCTOR
119  if (DEBUG_COND) {
120  std::cout << SIMTIME
121  << " create lcModel veh=" << myVehicle.getID()
122  << " lcStrategic=" << myStrategicParam
123  << " lcCooperative=" << myCooperativeParam
124  << " lcSpeedGain=" << mySpeedGainParam
125  << " lcKeepRight=" << myKeepRightParam
126  << "\n";
127  }
128 #endif
129 }
130 
132  changed();
133 }
134 
135 
136 void
138  if (mySpeedGainParam <= 0) {
139  myChangeProbThresholdRight = std::numeric_limits<double>::max();
140  myChangeProbThresholdLeft = std::numeric_limits<double>::max();
141  } else {
144  }
145 }
146 
147 
148 bool
150  return DEBUG_COND;
151 }
152 
153 
154 int
156  int laneOffset,
158  int blocked,
159  const std::pair<MSVehicle*, double>& leader,
160  const std::pair<MSVehicle*, double>& follower,
161  const std::pair<MSVehicle*, double>& neighLead,
162  const std::pair<MSVehicle*, double>& neighFollow,
163  const MSLane& neighLane,
164  const std::vector<MSVehicle::LaneQ>& preb,
165  MSVehicle** lastBlocked,
166  MSVehicle** firstBlocked) {
167 
168 #ifdef DEBUG_WANTS_CHANGE
169  if (DEBUG_COND) {
170  std::cout << "\nWANTS_CHANGE\n" << SIMTIME
171  << std::setprecision(gPrecision)
172  << " veh=" << myVehicle.getID()
173  << " lane=" << myVehicle.getLane()->getID()
174  << " pos=" << myVehicle.getPositionOnLane()
175  << " posLat=" << myVehicle.getLateralPositionOnLane()
176  << " speed=" << myVehicle.getSpeed()
177  << " considerChangeTo=" << (laneOffset == -1 ? "right" : "left")
178  << "\n";
179  }
180 #endif
181 
182  const int result = _wantsChange(laneOffset, msgPass, blocked, leader, follower, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked);
183 
184 #ifdef DEBUG_WANTS_CHANGE
185  if (DEBUG_COND) {
186  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " result=" << toString((LaneChangeAction)result) << " blocked=" << toString((LaneChangeAction)blocked) << "\n\n\n";
187  }
188 #endif
189 
190  return result;
191 }
192 
193 
194 double
195 MSLCM_LC2013::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
196 
197 #ifdef DEBUG_PATCH_SPEED
198  if (DEBUG_COND) {
199  std::cout << "\nPATCH_SPEED\n"
200  << SIMTIME
201  << " veh=" << myVehicle.getID()
202  << " lane=" << myVehicle.getLane()->getID()
203  << " pos=" << myVehicle.getPositionOnLane()
204  << " v=" << myVehicle.getSpeed()
205  << " min=" << min
206  << " wanted=" << wanted
207  << " max=" << max
208  << "\n";
209  }
210 #endif
211 
212  // negative min speed may be passed when using ballistic updated
213  const double newSpeed = _patchSpeed(MAX2(min, 0.0), wanted, max, cfModel);
214 
215 #ifdef DEBUG_PATCH_SPEED
216  if (DEBUG_COND) {
217  const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
218  std::cout << patched
219  << "\n";
220  }
221 #endif
222 
223  return newSpeed;
224 }
225 
226 
227 double
228 MSLCM_LC2013::_patchSpeed(double min, const double wanted, double max, const MSCFModel& cfModel) {
229  int state = myOwnState;
230 #ifdef DEBUG_PATCH_SPEED
231  if (DEBUG_COND) {
232  std::cout
233  << "\n" << SIMTIME << std::setprecision(gPrecision)
234  << " patchSpeed state=" << toString((LaneChangeAction)state) << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
235  << "\n speed=" << myVehicle.getSpeed() << " min=" << min << " wanted=" << wanted
236  << "\n myLeadingBlockerLength=" << myLeadingBlockerLength
237  << "\n";
238  }
239 #endif
240 
241  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
242  double nVSafe = wanted;
243  bool gotOne = false;
244  // if we want to change and have a blocking leader and there is enough room for him in front of us
245  if (myLeadingBlockerLength != 0) {
247 #ifdef DEBUG_PATCH_SPEED
248  if (DEBUG_COND) {
249  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " myLeadingBlockerLength=" << myLeadingBlockerLength << " space=" << space << "\n";
250  }
251 #endif
252  if (space > 0) { // XXX space > -MAGIC_OFFSET
253  // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
254  const double vMinEmergency = myVehicle.getCarFollowModel().minNextSpeedEmergency(myVehicle.getSpeed(), &myVehicle);
255  double safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space, MSCFModel::CalcReason::LANE_CHANGE);
256  max = MIN2(max, MAX2(safe, vMinEmergency));
257  // if we are approaching this place
258  if (safe < wanted) {
259  // return this speed as the speed to use
260  if (safe < min) {
261  if (safe >= vMinEmergency) {
262  // permit harder braking if needed and helpful
263  min = MAX2(vMinEmergency, safe);
264  }
265  }
266 #ifdef DEBUG_PATCH_SPEED
267  if (DEBUG_COND) {
268  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ? " (not enough)" : "") << "\n";
269  }
270 #endif
271  nVSafe = MAX2(min, safe);
272  gotOne = true;
273  }
274  }
275  }
276 
277  const double coopWeight = MAX2(0.0, MIN2(1.0, myCooperativeSpeed));
278  for (auto i : myLCAccelerationAdvices) {
279  double a = i.first;
280  double v = myVehicle.getSpeed() + ACCEL2SPEED(a);
281 
282  if (v >= min && v <= max && (MSGlobals::gSemiImplicitEulerUpdate
283  // ballistic update: (negative speeds may appear, e.g. min<0, v<0), BUT:
284  // XXX: LaneChanging returns -1 to indicate no restrictions, which leads to probs here (Leo), refs. #2577
285  // As a quick fix, we just dismiss cases where v=-1
286  // VERY rarely (whenever a requested help-acceleration is really indicated by v=-1)
287  // this can lead to failing lane-change attempts, though)
288  || v != -1)) {
289  if (i.second) {
290  // own advice, no scaling needed
291  nVSafe = MIN2(v, nVSafe);
292  } else {
293  nVSafe = MIN2(v * coopWeight + (1 - coopWeight) * wanted, nVSafe);
294  }
295  gotOne = true;
296 #ifdef DEBUG_PATCH_SPEED
297  if (DEBUG_COND) {
298  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got nVSafe=" << nVSafe << "\n";
299  }
300 #endif
301  } else {
302  if (v < min) {
303 #ifdef DEBUG_PATCH_SPEED
304  if (DEBUG_COND) {
305  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring low nVSafe=" << v << " min=" << min << "\n";
306  }
307 #endif
308  } else {
309 #ifdef DEBUG_PATCH_SPEED
310  if (DEBUG_COND) {
311  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring high nVSafe=" << v << " max=" << max << "\n";
312  }
313 #endif
314  }
315  }
316  }
317  // myDontBrake is used in counter-lane-change situations with relief connection
318  if (gotOne && !myDontBrake) {
319 #ifdef DEBUG_PATCH_SPEED
320  if (DEBUG_COND) {
321  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got vSafe\n";
322  }
323 #endif
324  return nVSafe;
325  }
326 
327  // check whether the vehicle is blocked
328  if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) != 0) {
329  if ((state & LCA_STRATEGIC) != 0) {
330  // necessary decelerations are controlled via vSafe. If there are
331  // none it means we should speed up
332 #ifdef DEBUG_PATCH_SPEED
333  if (DEBUG_COND) {
334  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_WANTS_LANECHANGE (strat, no vSafe)\n";
335  }
336 #endif
337  return (max + wanted) / 2.0;
338  } else if ((state & LCA_COOPERATIVE) != 0) {
339  // only minor adjustments in speed should be done
340  if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
341 #ifdef DEBUG_PATCH_SPEED
342  if (DEBUG_COND) {
343  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_LEADER (coop)\n";
344  }
345 #endif
346  if (wanted >= 0.) {
347  return (MAX2(0., min) + wanted) / 2.0;
348  } else {
349  return wanted;
350  }
351  }
352  if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
353 #ifdef DEBUG_PATCH_SPEED
354  if (DEBUG_COND) {
355  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER (coop)\n";
356  }
357 #endif
358  return (max + wanted) / 2.0;
359  }
360  //} else { // VARIANT_16
361  // // only accelerations should be performed
362  // if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
363  // if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER\n";
364  // return (max + wanted) / 2.0;
365  // }
366  }
367  }
368 
369  /*
370  // decelerate if being a blocking follower
371  // (and does not have to change lanes)
372  if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
373  if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
374  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER (standing)\n";
375  return 0;
376  }
377  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER\n";
378 
379  //return min; // VARIANT_3 (brakeStrong)
380  return (min + wanted) / 2.0;
381  }
382  if ((state & LCA_AMBACKBLOCKER) != 0) {
383  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
384  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER (standing)\n";
385  //return min; VARIANT_9 (backBlockVSafe)
386  return nVSafe;
387  }
388  }
389  if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
390  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER_STANDING\n";
391  //return min;
392  return nVSafe;
393  }
394  */
395 
396  // accelerate if being a blocking leader or blocking follower not able to brake
397  // (and does not have to change lanes)
398  if ((state & LCA_AMBLOCKINGLEADER) != 0) {
399 #ifdef DEBUG_PATCH_SPEED
400  if (DEBUG_COND) {
401  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGLEADER\n";
402  }
403 #endif
404  return (max + wanted) / 2.0;
405  }
406 
407  if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
408 #ifdef DEBUG_PATCH_SPEED
409  if (DEBUG_COND) {
410  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER_DONTBRAKE\n";
411  }
412 #endif
413  /*
414  // VARIANT_4 (dontbrake)
415  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
416  return wanted;
417  }
418  return (min + wanted) / 2.0;
419  */
420  }
421  if (!myVehicle.getLane()->getEdge().hasLaneChanger()) {
422  // remove chaning information if on a road with a single lane
423  changed();
424  }
425  return wanted;
426 }
427 
428 
429 void*
430 MSLCM_LC2013::inform(void* info, MSVehicle* sender) {
431  UNUSED_PARAMETER(sender);
432  Info* pinfo = (Info*)info;
433  assert(pinfo->first >= 0 || !MSGlobals::gSemiImplicitEulerUpdate);
434  addLCSpeedAdvice(pinfo->first, false);
435  myOwnState |= pinfo->second;
436 #ifdef DEBUG_INFORMED
437  if (DEBUG_COND) {
438  std::cout << SIMTIME
439  << " veh=" << myVehicle.getID()
440  << " informedBy=" << sender->getID()
441  << " info=" << pinfo->second
442  << " vSafe=" << pinfo->first
443  << "\n";
444  }
445 #endif
446  delete pinfo;
447  return (void*) true;
448 }
449 
450 double
451 MSLCM_LC2013::overtakeDistance(const MSVehicle* follower, const MSVehicle* leader, const double gap, double followerSpeed, double leaderSpeed) {
452  followerSpeed = followerSpeed == INVALID_SPEED ? follower->getSpeed() : followerSpeed;
453  leaderSpeed = leaderSpeed == INVALID_SPEED ? leader->getSpeed() : leaderSpeed;
454  double overtakeDist = (gap // drive to back of leader
455  + leader->getVehicleType().getLengthWithGap() // drive to front of leader
456  + follower->getVehicleType().getLength() // follower back reaches leader front
457  + leader->getCarFollowModel().getSecureGap( // save gap to leader
458  leader, follower, leaderSpeed, followerSpeed, follower->getCarFollowModel().getMaxDecel()));
459  return MAX2(overtakeDist, 0.);
460 }
461 
462 
463 double
465  int blocked,
466  int dir,
467  const std::pair<MSVehicle*, double>& neighLead,
468  double remainingSeconds) {
469  double plannedSpeed = myVehicle.getSpeed();
470  if (!isOpposite()) {
471  plannedSpeed = MIN2(plannedSpeed,
473  }
474  for (auto i : myLCAccelerationAdvices) {
475  const double a = i.first;
476  if (a >= -myVehicle.getCarFollowModel().getMaxDecel()) {
477  plannedSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() + ACCEL2SPEED(a));
478  }
479  }
480 #ifdef DEBUG_INFORMER
481  if (DEBUG_COND) {
482  std::cout << "\nINFORM_LEADER"
483  << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
484  }
485 #endif
486 
487  const MSVehicle* const nv = neighLead.first;
488  if (nv == nullptr) {
489  // not overtaking
490  return plannedSpeed;
491  }
492  const double neighNextSpeed = nv->getSpeed() - ACCEL2SPEED(MAX2(1.0, -nv->getAcceleration()));
493  double neighNextGap;
495  neighNextGap = neighLead.second + SPEED2DIST(neighNextSpeed - plannedSpeed);
496  } else {
497  neighNextGap = neighLead.second + SPEED2DIST((nv->getSpeed() + neighNextSpeed) / 2) - SPEED2DIST((myVehicle.getSpeed() + plannedSpeed) / 2);
498  }
499  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
501  //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingLeader=" << nv->getID() << "\n";
502  return plannedSpeed;
503  }
504 #ifdef DEBUG_INFORMER
505  if (DEBUG_COND) {
506  std::cout << " blocked by leader nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
508  }
509 #endif
510  // decide whether we want to overtake the leader or follow it
511  double overtakeTime;
512  const double overtakeDist = overtakeDistance(&myVehicle, nv, neighLead.second);
513  const double dv = plannedSpeed - nv->getSpeed();
514 
516  overtakeTime = overtakeDist / dv;
517  } else {
518  // -> set overtakeTime to something indicating impossibility of overtaking
519  overtakeTime = remainingSeconds + 1;
520  }
521 
522 #ifdef DEBUG_INFORMER
523  if (DEBUG_COND) {
524  std::cout << SIMTIME << " informLeader() of " << myVehicle.getID()
525  << "\nnv = " << nv->getID()
526  << "\nplannedSpeed = " << plannedSpeed
527  << "\nleaderSpeed = " << nv->getSpeed()
528  << "\nmyLeftSpace = " << myLeftSpace
529  << "\nremainingSeconds = " << remainingSeconds
530  << "\novertakeDist = " << overtakeDist
531  << "\novertakeTime = " << overtakeTime
532  << std::endl;
533  }
534 #endif
535 
537  // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft)
539  // not enough space to overtake?
541  // using brakeGap() without headway seems adequate in a situation where the obstacle (the lane end) is not moving [XXX implemented in branch ticket860, can be used in general if desired, refs. #2575] (Leo).
543  // not enough time to overtake? (skipped for a stopped leader [currently only for ballistic update XXX: check if appropriate for euler, too, refs. #2575] to ensure that it can be overtaken if only enough space is exists) (Leo)
544  || (remainingSeconds < overtakeTime && (MSGlobals::gSemiImplicitEulerUpdate || !nv->isStopped())))
545  // opposite driving and must overtake
546  && (!neighLead.first->isStopped() || (isOpposite() && neighLead.second >= 0))) {
547  // cannot overtake
548  msgPass.informNeighLeader(new Info(std::numeric_limits<double>::max(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
549  // slow down smoothly to follow leader
550  // account for minor decelerations by the leader (dawdling)
551  const double targetSpeed = MAX2(
553  getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()));
554  if (targetSpeed < myVehicle.getSpeed()) {
555  // slow down smoothly to follow leader
556  const double decel = remainingSeconds == 0. ? myVehicle.getCarFollowModel().getMaxDecel() :
558  MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds));
559  const double nextSpeed = MIN2(plannedSpeed, MAX2(0.0, myVehicle.getSpeed() - ACCEL2SPEED(decel)));
560 #ifdef DEBUG_INFORMER
561  if (DEBUG_COND) {
562  std::cout << SIMTIME
563  << " cannot overtake leader nv=" << nv->getID()
564  << " dv=" << dv
565  << " myLookAheadSpeed=" << myLookAheadSpeed
566  << " myLeftSpace=" << myLeftSpace
567  << " overtakeDist=" << overtakeDist
568  << " overtakeTime=" << overtakeTime
569  << " remainingSeconds=" << remainingSeconds
570  << " currentGap=" << neighLead.second
571  << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed(), getCarFollowModel().getMaxDecel(), 0.)
572  << " neighNextSpeed=" << neighNextSpeed
573  << " neighNextGap=" << neighNextGap
574  << " targetSpeed=" << targetSpeed
575  << " nextSpeed=" << nextSpeed
576  << "\n";
577  }
578 #endif
579  addLCSpeedAdvice(nextSpeed);
580  return nextSpeed;
581  } else {
582  // leader is fast enough anyway
583 #ifdef DEBUG_INFORMER
584  if (DEBUG_COND) {
585  std::cout << SIMTIME
586  << " cannot overtake fast leader nv=" << nv->getID()
587  << " dv=" << dv
588  << " myLookAheadSpeed=" << myLookAheadSpeed
589  << " myLeftSpace=" << myLeftSpace
590  << " overtakeDist=" << overtakeDist
591  << " myLeadingBlockerLength=" << myLeadingBlockerLength
592  << " overtakeTime=" << overtakeTime
593  << " remainingSeconds=" << remainingSeconds
594  << " currentGap=" << neighLead.second
595  << " neighNextSpeed=" << neighNextSpeed
596  << " neighNextGap=" << neighNextGap
597  << " targetSpeed=" << targetSpeed
598  << "\n";
599  }
600 #endif
601  addLCSpeedAdvice(targetSpeed);
602  return plannedSpeed;
603  }
604  } else {
605  // overtaking, leader should not accelerate
606 #ifdef DEBUG_INFORMER
607  if (DEBUG_COND) {
608  std::cout << SIMTIME
609  << " wants to overtake leader nv=" << nv->getID()
610  << " dv=" << dv
611  << " overtakeDist=" << overtakeDist
612  << " remainingSeconds=" << remainingSeconds
613  << " overtakeTime=" << overtakeTime
614  << " currentGap=" << neighLead.second
616  << "\n";
617  }
618 #endif
619  msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
620  return -1; // XXX: using -1 is ambiguous for the ballistic update! Currently this is being catched in patchSpeed() (Leo), consider returning INVALID_SPEED, refs. #2577
621  }
622  } else { // (remainUnblocked)
623  // we are not blocked now. make sure we stay far enough from the leader
624  const double targetSpeed = MAX2(
626  getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()));
627  addLCSpeedAdvice(targetSpeed);
628 #ifdef DEBUG_INFORMER
629  if (DEBUG_COND) {
630  std::cout << " not blocked by leader nv=" << nv->getID()
631  << " nvSpeed=" << nv->getSpeed()
632  << " gap=" << neighLead.second
633  << " neighNextSpeed=" << neighNextSpeed
634  << " neighNextGap=" << neighNextGap
636  << " targetSpeed=" << targetSpeed
637  << "\n";
638  }
639 #endif
640  return MIN2(targetSpeed, plannedSpeed);
641  }
642 }
643 
644 void
646  int blocked,
647  int dir,
648  const std::pair<MSVehicle*, double>& neighFollow,
649  double remainingSeconds,
650  double plannedSpeed) {
651 
652  MSVehicle* nv = neighFollow.first;
653  const double plannedAccel = SPEED2ACCEL(MAX2(MIN2(getCarFollowModel().getMaxAccel(), plannedSpeed - myVehicle.getSpeed()), -getCarFollowModel().getMaxDecel()));
654 
655 #ifdef DEBUG_INFORMER
656  if (DEBUG_COND) {
657  std::cout << "\nINFORM_FOLLOWER"
658  << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
659  }
660 
661 #endif
662  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0 && nv != nullptr) {
664  //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingFollower=" << nv->getID() << "\n";
665  return;
666  }
667 #ifdef DEBUG_INFORMER
668  if (DEBUG_COND) {
669  std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
670  << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel()) << " planned=" << plannedSpeed << "\n";
671  }
672 #endif
673 
674  // are we fast enough to cut in without any help?
675  if (MAX2(plannedSpeed, 0.) - nv->getSpeed() >= HELP_OVERTAKE) {
676  const double neededGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
677  if ((neededGap - neighFollow.second) / remainingSeconds < (MAX2(plannedSpeed, 0.) - nv->getSpeed())) {
678 #ifdef DEBUG_INFORMER
679  if (DEBUG_COND) {
680  std::cout << " wants to cut in before nv=" << nv->getID() << " without any help." << "\nneededGap = " << neededGap << "\n";
681  }
682 #endif
683  // follower might even accelerate but not to much
684  // XXX: I don't understand this. The needed gap was determined for nv->getSpeed(), not for (plannedSpeed - HELP_OVERTAKE)?! (Leo), refs. #2578
685  msgPass.informNeighFollower(new Info(MAX2(plannedSpeed, 0.) - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
686  return;
687  }
688  }
689 
690  // decide whether we will request help to cut in before the follower or allow to be overtaken
691 
692  // PARAMETERS
693  // assume other vehicle will assume the equivalent of 1 second of
694  // maximum deceleration to help us (will probably be spread over
695  // multiple seconds)
696  // -----------
697  const double helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR;
698 
699  // follower's new speed in next step
700  double neighNewSpeed;
701  // follower's new speed after 1s.
702  double neighNewSpeed1s;
703  // velocity difference, gap after follower-deceleration
704  double dv, decelGap;
705 
707  // euler
708  neighNewSpeed = MAX2(0., nv->getSpeed() - ACCEL2SPEED(helpDecel));
709  neighNewSpeed1s = MAX2(0., nv->getSpeed() - helpDecel); // TODO: consider introduction of a configurable anticipationTime here (see far below in the !blocked part). Refs. #2578
710  // change in the gap between ego and blocker over 1 second (not STEP!)
711  // XXX: though here it is calculated as if it were one step!? (Leo) Refs. #2578
712  dv = plannedSpeed - neighNewSpeed1s; // XXX: what is this quantity (if TS!=1)?
713  // new gap between follower and self in case the follower does brake for 1s
714  // XXX: if the step-length is not 1s., this is not the gap after 1s. deceleration!
715  // And this formula overestimates the real gap. Isn't that problematic? (Leo)
716  // Below, it seems that decelGap > secureGap is taken to indicate the possibility
717  // to cut in within the next time-step. However, this is not the case, if TS<1s.,
718  // since decelGap is (not exactly, though!) the gap after 1s. Refs. #2578
719  decelGap = neighFollow.second + dv;
720  } else {
721  // ballistic
722  // negative newSpeed-extrapolation possible, if stop lies within the next time-step
723  // XXX: this code should work for the euler case as well, since gapExtrapolation() takes
724  // care of this, but for TS!=1 we will have different behavior (see previous remark) Refs. #2578
725  neighNewSpeed = nv->getSpeed() - ACCEL2SPEED(helpDecel);
726  neighNewSpeed1s = nv->getSpeed() - helpDecel;
727 
728  dv = myVehicle.getSpeed() - nv->getSpeed(); // current velocity difference
729  decelGap = getCarFollowModel().gapExtrapolation(1., neighFollow.second, myVehicle.getSpeed(),
730  nv->getSpeed(), plannedAccel, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
731  }
732 
733  const double secureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, MAX2(neighNewSpeed1s, 0.),
734  MAX2(plannedSpeed, 0.), myVehicle.getCarFollowModel().getMaxDecel());
735 
736  const double onRampThreshold = myVehicle.getLane()->getSpeedLimit() * 0.8 * myExperimentalParam1 * (1 - myVehicle.getImpatience());
737 
738 #ifdef DEBUG_INFORMER
739  if (DEBUG_COND) {
740  std::cout << SIMTIME
741  << " speed=" << myVehicle.getSpeed()
742  << " plannedSpeed=" << plannedSpeed
743  << " threshold=" << onRampThreshold
744  << " neighNewSpeed=" << neighNewSpeed
745  << " neighNewSpeed1s=" << neighNewSpeed1s
746  << " dv=" << dv
747  << " gap=" << neighFollow.second
748  << " decelGap=" << decelGap
749  << " secureGap=" << secureGap
750  << "\n";
751  }
752 #endif
753  // prevent vehicles on an on ramp stopping the main flow
754  if (dir == LCA_MLEFT
756  && neighNewSpeed1s < onRampThreshold) {
757  return;
758  }
759 
760  if (decelGap > 0 && decelGap >= secureGap) {
761  // XXX: This does not assure that the leader can cut in in the next step if TS < 1 (see above)
762  // this seems to be supposed in the following (euler code)...?! (Leo) Refs. #2578
763 
764  // if the blocking follower brakes it could help
765  // how hard does it actually need to be?
766  // to be safe in the next step the following equation has to hold for the follower's vsafe:
767  // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
768  double vsafe, vsafe1;
769 
771  // euler
772  // we compute an upper bound on vsafe by doing the computation twice
773  vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
774  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, getCarFollowModel().getMaxDecel()));
775  vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
776  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, getCarFollowModel().getMaxDecel()));
777  //assert(vsafe <= vsafe1); assertion does not hold for models with randomness in followSpeed (W99)
778  } else {
779  // ballistic
780 
781  // XXX: This block should actually do as well for euler update (TODO: test!), refs #2575
782  // we compute an upper bound on vsafe
783  // next step's gap without help deceleration (nv's speed assumed constant)
784  double nextGap = getCarFollowModel().gapExtrapolation(TS,
785  neighFollow.second, myVehicle.getSpeed(),
786  nv->getSpeed(), plannedAccel, 0,
788 #ifdef DEBUG_INFORMER
789  if (DEBUG_COND) {
790  std::cout << "nextGap=" << nextGap << " (without help decel) \n";
791  }
792 #endif
793 
794  // NOTE: the second argument of MIN2() can get larger than nv->getSpeed()
795  vsafe1 = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
797  nv->getSpeed(), nextGap,
798  MAX2(0., plannedSpeed),
799  getCarFollowModel().getMaxDecel())));
800 
801 
802  // next step's gap with possibly less than maximal help deceleration (in case vsafe1 > neighNewSpeed)
803  double decel2 = SPEED2ACCEL(nv->getSpeed() - vsafe1);
805  neighFollow.second, myVehicle.getSpeed(),
806  nv->getSpeed(), plannedAccel, -decel2,
808 
809  // vsafe = MAX(neighNewSpeed, safe speed assuming next_gap)
810  // Thus, the gap resulting from vsafe is larger or equal to next_gap
811  // in contrast to the euler case, where nv's follow speed doesn't depend on the actual speed,
812  // we need to assure, that nv doesn't accelerate
813  vsafe = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
815  nv->getSpeed(), nextGap,
816  MAX2(0., plannedSpeed),
817  getCarFollowModel().getMaxDecel())));
818 
819  assert(vsafe >= vsafe1 - NUMERICAL_EPS);
820 
821 #ifdef DEBUG_INFORMER
822  if (DEBUG_COND) {
823  std::cout << "nextGap=" << nextGap
824  << " (with vsafe1 and help decel) \nvsafe1=" << vsafe1
825  << " vsafe=" << vsafe
826  << "\n";
827  }
828 #endif
829 
830  // For subsecond simulation, this might not lead to secure gaps for a long time,
831  // we seek to establish a secure gap as soon as possible
832  double nextSecureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe, plannedSpeed, getCarFollowModel().getMaxDecel());
833 
834  if (nextGap < nextSecureGap) {
835  // establish a secureGap as soon as possible
836  vsafe = neighNewSpeed;
837  }
838 
839 #ifdef DEBUG_INFORMER
840  if (DEBUG_COND) {
841  std::cout << "nextGap=" << nextGap
842  << " minNextSecureGap=" << nextSecureGap
843  << " vsafe=" << vsafe << "\n";
844  }
845 #endif
846 
847  }
848  msgPass.informNeighFollower(
849  new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
850 
851 #ifdef DEBUG_INFORMER
852  if (DEBUG_COND) {
853  std::cout << " wants to cut in before nv=" << nv->getID()
854  << " vsafe1=" << vsafe1 << " vsafe=" << vsafe
855  << " newSecGap="
856  << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe,
857  plannedSpeed,
859  << "\n";
860  }
861 #endif
862  } else if ((MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS))
863  || (!MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * (remainingSeconds - 1) > secureGap - decelGap + POSITION_EPS)
864  ) {
865 
866  // XXX: Alternative formulation (encapsulating differences of euler and ballistic) TODO: test, refs. #2575
867  // double eventualGap = getCarFollowModel().gapExtrapolation(remainingSeconds - 1., decelGap, plannedSpeed, neighNewSpeed1s);
868  // } else if (eventualGap > secureGap + POSITION_EPS) {
869 
870 
871  // NOTE: This case corresponds to the situation, where some time is left to perform the lc
872  // For the ballistic case this is interpreted as follows:
873  // If the follower breaks with helpDecel for one second, this vehicle maintains the plannedSpeed,
874  // and both continue with their speeds for remainingSeconds seconds the gap will suffice for a laneChange
875  // For the euler case we had the following comment:
876  // 'decelerating once is sufficient to open up a large enough gap in time', but:
877  // XXX: 1) Decelerating *once* does not necessarily lead to the gap decelGap! (if TS<1s.) (Leo)
878  // 2) Probably, the if() for euler should test for dv * (remainingSeconds-1) > ..., too ?!, refs. #2578
879  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
880 #ifdef DEBUG_INFORMER
881  if (DEBUG_COND) {
882  std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
883  }
884 #endif
885  } else if (dir == LCA_MRIGHT && !myAllowOvertakingRight && !nv->congested()) {
886  // XXX: check if this requires a special treatment for the ballistic update, refs. #2575
887  const double vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
888  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
889 #ifdef DEBUG_INFORMER
890  if (DEBUG_COND) {
891  std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
892  }
893 #endif
894  } else {
895  double vhelp = MAX2(nv->getSpeed(), myVehicle.getSpeed() + HELP_OVERTAKE);
896  //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE &&
897  // nv->getSpeed() > myVehicle.getSpeed()) {
898  if (nv->getSpeed() > myVehicle.getSpeed() &&
899  ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) // NOTE: it might be considered to use myVehicle.getAccumulatedWaitingSeconds() > LCA_RIGHT_IMPATIENCE instead (Leo). Refs. #2578
900  || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
901  // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
903  )) {
904  // let the follower slow down to increase the likelihood that later vehicles will be slow enough to help
905  // follower should still be fast enough to open a gap
906  // XXX: The probability for that success would be larger if the slow down of the appropriate following vehicle
907  // would take place without the immediate follower slowing down. We might consider to model reactions of
908  // vehicles that are not immediate followers. (Leo) -> see ticket #2532
909  vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
910 #ifdef DEBUG_INFORMER
911  if (DEBUG_COND) {
912  // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! (Leo)
913  // Further, vhelp might be larger than nv->getSpeed(), so the request issued below is not to slow down!? (see below) Refs. #2578
914  std::cout << " wants right follower to slow down a bit\n";
915  }
916 #endif
918  // euler
919  if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
920 
921 #ifdef DEBUG_INFORMER
922  if (DEBUG_COND) {
923  // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! Refs. #2578
924  std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
925  }
926 #endif
927  // XXX: I don't understand. This vhelp might be larger than nv->getSpeed() but the above condition seems to rely
928  // on the reasoning that if nv breaks with helpDecel for remaining Seconds, nv will be so slow, that this
929  // vehicle will be able to cut in. But nv might have overtaken this vehicle already (or am I missing sth?). (Leo)
930  // Ad: To my impression, the intention behind allowing larger speeds for the blocking follower is to prevent a
931  // situation, where an overlapping follower keeps blocking the ego vehicle. Refs. #2578
932  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
933  return;
934  }
935  } else {
936 
937  // ballistic (this block is a bit different to the logic in the euler part, but in general suited to work on euler as well.. must be tested <- TODO, refs. #2575)
938  // estimate gap after remainingSeconds.
939  // Assumptions:
940  // (A1) leader continues with currentSpeed. (XXX: That might be wrong: Think of accelerating on an on-ramp or of a congested region ahead!)
941  // (A2) follower breaks with helpDecel.
942  const double gapAfterRemainingSecs = getCarFollowModel().gapExtrapolation(
943  remainingSeconds, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(), 0, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
944  const double secureGapAfterRemainingSecs = nv->getCarFollowModel().getSecureGap(nv, &myVehicle,
945  MAX2(nv->getSpeed() - remainingSeconds * helpDecel, 0.), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
946  if (gapAfterRemainingSecs >= secureGapAfterRemainingSecs) { // XXX: here it would be wise to check whether there is enough space for eventual braking if the maneuver doesn't succeed
947 #ifdef DEBUG_INFORMER
948  if (DEBUG_COND) {
949  std::cout << " wants to cut in before follower nv=" << nv->getID() << " (eventually)\n";
950  }
951 #endif
952  // NOTE: ballistic uses neighNewSpeed instead of vhelp, see my note above. (Leo)
953  // TODO: recheck if this might cause suboptimal behaviour in some LC-situations. Refs. #2578
954  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
955  return;
956  }
957  }
958 
959 
960  }
961 
962 #ifdef DEBUG_INFORMER
963  if (DEBUG_COND) {
964  std::cout << SIMTIME
965  << " veh=" << myVehicle.getID()
966  << " informs follower " << nv->getID()
967  << " vhelp=" << vhelp
968  << "\n";
969  }
970 #endif
971 
972  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
973  // This follower is supposed to overtake us. Slow down smoothly to allow this.
974  const double overtakeDist = overtakeDistance(nv, &myVehicle, neighFollow.second, vhelp, plannedSpeed);
975  // speed difference to create a sufficiently large gap
976  const double needDV = overtakeDist / remainingSeconds;
977  // make sure the deceleration is not to strong (XXX: should be assured in finalizeSpeed -> TODO: remove the MAX2 if agreed) -> prob with possibly non-existing maximal deceleration for som CF Models(?) Refs. #2578
979 
980 #ifdef DEBUG_INFORMER
981  if (DEBUG_COND) {
982  std::cout << SIMTIME
983  << " veh=" << myVehicle.getID()
984  << " wants to be overtaken by=" << nv->getID()
985  << " overtakeDist=" << overtakeDist
986  << " vneigh=" << nv->getSpeed()
987  << " vhelp=" << vhelp
988  << " needDV=" << needDV
989  << " vsafe=" << myLCAccelerationAdvices.back().first
990  << "\n";
991  }
992 #endif
993  }
994  } else if (neighFollow.first != nullptr && (blocked & LCA_BLOCKED_BY_LEADER)) {
995  // we are not blocked by the follower now, make sure it remains that way
996  const double vsafe = MSLCHelper::getSpeedPreservingSecureGap(myVehicle, *neighFollow.first, neighFollow.second, plannedSpeed);
997  msgPass.informNeighFollower(new Info(vsafe, dir), &myVehicle);
998 
999 #ifdef DEBUG_INFORMER
1000  if (DEBUG_COND) {
1001  std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
1002  }
1003 #endif
1004  }
1005 }
1006 
1007 
1008 void
1011  // keep information about strategic change direction
1012  if (!isChangingLanes()) {
1014  }
1016  myLeftSpace = 0;
1017  myLCAccelerationAdvices.clear();
1018  myDontBrake = false;
1019  // truncate to work around numerical instability between different builds
1020  mySpeedGainProbability = ceil(mySpeedGainProbability * 100000.0) * 0.00001;
1021  myKeepRightProbability = ceil(myKeepRightProbability * 100000.0) * 0.00001;
1022  if (mySigma > 0 && !isChangingLanes()) {
1023  // disturb lateral position directly
1024  const double maxDist = SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat());
1025  const double oldPosLat = myVehicle.getLateralPositionOnLane();
1026  const double overlap = myVehicle.getLateralOverlap();
1027  double scaledDelta;
1028  if (overlap > 0) {
1029  // return to within lane boundary
1030  scaledDelta = MIN2(overlap, maxDist);
1031  if (myVehicle.getLateralPositionOnLane() > 0) {
1032  scaledDelta *= -1;
1033  }
1034  } else {
1035  // random drift
1036  double deltaPosLat = OUProcess::step(oldPosLat,
1038  MAX2(NUMERICAL_EPS, (1 - mySigma) * 100), mySigma) - oldPosLat;
1039  deltaPosLat = MAX2(MIN2(deltaPosLat, maxDist), -maxDist);
1040  scaledDelta = deltaPosLat * myVehicle.getSpeed() / myVehicle.getLane()->getSpeedLimit();
1041  }
1042  myVehicle.setLateralPositionOnLane(oldPosLat + scaledDelta);
1043  setSpeedLat(DIST2SPEED(scaledDelta));
1044  } else {
1045  resetSpeedLat();
1046  }
1047 }
1048 
1049 
1050 double
1051 MSLCM_LC2013::getExtraReservation(int bestLaneOffset) const {
1052  if (bestLaneOffset < -1) {
1053  return 20;
1054  } else if (bestLaneOffset > 1) {
1055  return 40;
1056  }
1057  return 0;
1058 }
1059 
1060 void
1062  myOwnState = 0;
1065  if (myVehicle.getBestLaneOffset() == 0) {
1066  // if we are not yet on our best lane there might still be unseen blockers
1067  // (during patchSpeed)
1069  myLeftSpace = 0;
1070  }
1072  myLCAccelerationAdvices.clear();
1073  myDontBrake = false;
1074 }
1075 
1076 
1077 void
1079  myOwnState = 0;
1083  myLeftSpace = 0;
1085  myLCAccelerationAdvices.clear();
1086  myDontBrake = false;
1087 }
1088 
1089 
1090 int
1092  int laneOffset,
1094  int blocked,
1095  const std::pair<MSVehicle*, double>& leader,
1096  const std::pair<MSVehicle*, double>& follower,
1097  const std::pair<MSVehicle*, double>& neighLead,
1098  const std::pair<MSVehicle*, double>& neighFollow,
1099  const MSLane& neighLane,
1100  const std::vector<MSVehicle::LaneQ>& preb,
1101  MSVehicle** lastBlocked,
1102  MSVehicle** firstBlocked) {
1103  assert(laneOffset == 1 || laneOffset == -1);
1104  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
1105  // compute bestLaneOffset
1106  MSVehicle::LaneQ curr, neigh, best;
1107  int bestLaneOffset = 0;
1108  // What do these "dists" mean? Please comment. (Leo) Ad: I now think the following:
1109  // currentDist is the distance that the vehicle can go on its route without having to
1110  // change lanes from the current lane. neighDist as currentDist for the considered target lane (i.e., neigh)
1111  // If this is true I suggest to put this into the docu of wantsChange()
1112  double currentDist = 0;
1113  double neighDist = 0;
1114  int currIdx = 0;
1115  const bool checkOpposite = &neighLane.getEdge() != &myVehicle.getLane()->getEdge();
1116  const MSLane* prebLane = myVehicle.getLane();
1117  if (prebLane->getEdge().isInternal()) {
1118  // internal edges are not kept inside the bestLanes structure
1119  if (isOpposite()) {
1120  prebLane = prebLane->getNormalPredecessorLane();
1121  } else {
1122  prebLane = prebLane->getLinkCont()[0]->getLane();
1123  }
1124  }
1125  // special case: vehicle considers changing to the opposite direction edge
1126  const int prebOffset = laneOffset;
1127  for (int p = 0; p < (int) preb.size(); ++p) {
1128  //if (DEBUG_COND) {
1129  // std::cout << " p=" << p << " prebLane=" << prebLane->getID() << " preb.p=" << preb[p].lane->getID() << "\n";
1130  //}
1131  if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1132  assert(p + prebOffset < (int)preb.size());
1133  curr = preb[p];
1134  neigh = preb[p + prebOffset];
1135  currentDist = curr.length;
1136  neighDist = neigh.length;
1137  bestLaneOffset = curr.bestLaneOffset;
1138  if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1139 #ifdef DEBUG_WANTS_CHANGE
1140  if (DEBUG_COND) {
1141  std::cout << STEPS2TIME(currentTime)
1142  << " veh=" << myVehicle.getID()
1143  << " bestLaneOffsetOld=" << bestLaneOffset
1144  << " bestLaneOffsetNew=" << laneOffset
1145  << "\n";
1146  }
1147 #endif
1148  bestLaneOffset = prebOffset;
1149  }
1150  best = preb[p + bestLaneOffset];
1151  currIdx = p;
1152  break;
1153  }
1154  }
1155  assert(curr.lane != nullptr);
1156  assert(neigh.lane != nullptr);
1157  assert(best.lane != nullptr);
1158  // direction specific constants
1159  const bool right = (laneOffset == -1);
1160  const double posOnLane = getForwardPos();
1161  double driveToNextStop = -std::numeric_limits<double>::max();
1162  if (myVehicle.nextStopDist() < std::numeric_limits<double>::max()
1164  // vehicle can always drive up to stop distance
1165  // @note this information is dynamic and thus not available in updateBestLanes()
1166  // @note: nextStopDist was compute before the vehicle moved
1167  driveToNextStop = myVehicle.nextStopDist();
1168  const double stopPos = posOnLane + myVehicle.nextStopDist() - myVehicle.getLastStepDist();
1169 #ifdef DEBUG_WANTS_CHANGE
1170  if (DEBUG_COND) {
1171  std::cout << SIMTIME << std::setprecision(gPrecision) << " veh=" << myVehicle.getID()
1172  << " stopDist=" << myVehicle.nextStopDist()
1173  << " lastDist=" << myVehicle.getLastStepDist()
1174  << " stopPos=" << stopPos
1175  << " currentDist=" << currentDist
1176  << " neighDist=" << neighDist
1177  << "\n";
1178  }
1179 #endif
1180  currentDist = MAX2(currentDist, stopPos);
1181  neighDist = MAX2(neighDist, stopPos);
1182  }
1183  const int lca = (right ? LCA_RIGHT : LCA_LEFT);
1184  const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
1185  const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
1186  bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1187  // keep information about being a leader/follower
1188  int ret = (myOwnState & 0xffff0000);
1189  int req = 0; // the request to change or stay
1190 
1191  ret = slowDownForBlocked(lastBlocked, ret);
1192  if (lastBlocked != firstBlocked) {
1193  ret = slowDownForBlocked(firstBlocked, ret);
1194  }
1195 
1196 #ifdef DEBUG_WANTS_CHANGE
1197  if (DEBUG_COND) {
1198  std::cout << SIMTIME
1199  << " veh=" << myVehicle.getID()
1200  << " _wantsChange state=" << myOwnState
1201  << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
1202  << " firstBlocked=" << Named::getIDSecure(*firstBlocked)
1203  << " lastBlocked=" << Named::getIDSecure(*lastBlocked)
1204  << " leader=" << Named::getIDSecure(leader.first)
1205  << " leaderGap=" << leader.second
1206  << " follower=" << Named::getIDSecure(follower.first)
1207  << " followerGap=" << follower.second
1208  << " neighLead=" << Named::getIDSecure(neighLead.first)
1209  << " neighLeadGap=" << neighLead.second
1210  << " neighFollow=" << Named::getIDSecure(neighFollow.first)
1211  << " neighFollowGap=" << neighFollow.second
1212  << "\n";
1213  }
1214 #endif
1215 
1216  // we try to estimate the distance which is necessary to get on a lane
1217  // we have to get on in order to keep our route
1218  // we assume we need something that depends on our velocity
1219  // and compare this with the free space on our wished lane
1220  //
1221  // if the free space is somehow(<-?) less than the space we need, we should
1222  // definitely try to get to the desired lane
1223  //
1224  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
1225 
1226 
1227  // we do not want the lookahead distance to change all the time so we let it decay slowly
1228  // (in contrast, growth is applied instantaneously)
1231  } else {
1232  // memory decay factor for this action step
1233  const double memoryFactor = 1. - (1. - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getActionStepLengthSecs();
1234  assert(memoryFactor > 0.);
1236  (memoryFactor * myLookAheadSpeed + (1 - memoryFactor) * myVehicle.getSpeed()));
1237  }
1238  double laDist = myLookAheadSpeed * LOOK_FORWARD * myStrategicParam * (right ? 1 : myLookaheadLeft);
1239  laDist += myVehicle.getVehicleType().getLengthWithGap() * 2.;
1240  const bool hasStoppedLeader = leader.first != 0 && leader.first->isStopped() && leader.second < (currentDist - posOnLane);
1241  const bool hasBidiLeader = myVehicle.getLane()->getBidiLane() != nullptr && MSLCHelper::isBidiLeader(leader.first, curr.bestContinuations);
1242  const bool hasBidiNeighLeader = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiLeader(neighLead.first, neigh.bestContinuations);
1243 
1244  if (bestLaneOffset == 0 && hasBidiLeader) {
1245  // getting out of the way is enough to clear the blockage
1246  laDist = 0;
1247  } else if (bestLaneOffset == 0 && hasStoppedLeader) {
1248  // react to a stopped leader on the current lane
1249  // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1250  // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1251  laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1252  + leader.first->getVehicleType().getLengthWithGap()
1253  + leader.second);
1254  } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && (neighLead.first->isStopped() || hasBidiNeighLeader) && neighLead.second < (currentDist - posOnLane)) {
1255  // react to a stopped leader on the target lane (if it is the bestLane)
1256  if (isOpposite()) {
1257  // always allow changing back
1259  + neighLead.first->getVehicleType().getLengthWithGap()
1260  + neighLead.second);
1261  } else if (!hasStoppedLeader &&
1262  ((neighLead.second + myVehicle.getVehicleType().getLengthWithGap() + neighLead.first->getVehicleType().getLengthWithGap()) < (currentDist - posOnLane)
1263  || hasBidiNeighLeader)) {
1264  // do not change to the target lane until passing the stopped vehicle
1265  // (unless the vehicle blocks our intended stopping position, then we have to wait anyway)
1266  changeToBest = false;
1267  }
1268  }
1269  if (myStrategicParam < 0) {
1270  laDist = -1e3; // never perform strategic change
1271  }
1272 
1273  // free space that is available for changing
1274  //const double neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
1275  // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
1276  // best.lane->getSpeedLimit());
1277  // @note: while this lets vehicles change earlier into the correct direction
1278  // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
1279 
1280 
1281 
1282  // Next we assign to roundabout edges a larger distance than to normal edges
1283  // in order to decrease sense of lc urgency and induce higher usage of inner roundabout lanes.
1284  const double roundaboutBonus = MSLCHelper::getRoundaboutDistBonus(myVehicle, myRoundaboutBonus, curr, neigh, best);
1285  currentDist += roundaboutBonus;
1286  neighDist += roundaboutBonus;
1287 
1288  const double usableDist = MAX2(currentDist - posOnLane - best.occupation * JAM_FACTOR, driveToNextStop);
1289  //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1290  const double maxJam = MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1291  const double vMax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
1292  const double neighVMax = neighLane.getVehicleMaxSpeed(&myVehicle);
1293  // upper bound which will be restricted successively
1294  double thisLaneVSafe = vMax;
1295  const bool checkOverTakeRight = avoidOvertakeRight();
1296 
1297  double neighLeftPlace = MAX2(0.0, neighDist - posOnLane - maxJam);
1298  if (neighLead.first != 0 && neighLead.first->isStopped()) {
1299  neighLeftPlace = MIN2(neighLeftPlace, neighLead.second);
1300  }
1301 
1302 #ifdef DEBUG_WANTS_CHANGE
1303  if (DEBUG_COND) {
1304  std::cout << STEPS2TIME(currentTime)
1305  << " veh=" << myVehicle.getID()
1306  << " laSpeed=" << myLookAheadSpeed
1307  << " laDist=" << laDist
1308  << " currentDist=" << currentDist
1309  << " usableDist=" << usableDist
1310  << " bestLaneOffset=" << bestLaneOffset
1311  << " best.occupation=" << best.occupation
1312  << " best.length=" << best.length
1313  << "\n roundaboutBonus=" << roundaboutBonus
1314  << " maxJam=" << maxJam
1315  << " neighDist=" << neighDist
1316  << " neighLeftPlace=" << neighLeftPlace
1317  << (hasBidiLeader ? " bidiLeader" : "")
1318  << (hasBidiNeighLeader ? " bidiNeighLeader" : "")
1319  << "\n";
1320  }
1321 #endif
1322 
1323  bool changeLeftToAvoidOvertakeRight = false;
1324  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1325  && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1327  ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1328  } else {
1329  // VARIANT_20 (noOvertakeRight)
1330  if (neighLead.first != 0 && checkOverTakeRight && !right) {
1331  // check for slower leader on the left. we should not overtake but
1332  // rather move left ourselves (unless congested)
1333  MSVehicle* nv = neighLead.first;
1334  const double deltaV = MAX2(vMax - neighLane.getVehicleMaxSpeed(nv),
1335  myVehicle.getSpeed() - nv->getSpeed());
1336  if (deltaV > 0) {
1337  const double vMaxDecel = getCarFollowModel().getSpeedAfterMaxDecel(myVehicle.getSpeed());
1338  const double vSafeFollow = getCarFollowModel().followSpeed(
1339  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1340  const double vStayBehind = nv->getSpeed() - HELP_OVERTAKE;
1341  double vSafe;
1342  if (vSafeFollow >= vMaxDecel) {
1343  vSafe = vSafeFollow;
1344  } else {
1345  vSafe = MAX2(vMaxDecel, vStayBehind);
1346  }
1348  vSafe = MAX2(vSafe, nv->getSpeed());
1349  }
1350  thisLaneVSafe = MIN2(thisLaneVSafe, vSafe);
1351  addLCSpeedAdvice(vSafe);
1352  // only generate impulse for overtaking left shortly before braking would be necessary
1353  const double deltaGapFuture = deltaV * 8;
1354  const double vSafeFuture = getCarFollowModel().followSpeed(
1355  &myVehicle, myVehicle.getSpeed(), neighLead.second - deltaGapFuture, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1356  if (vSafeFuture < vSafe) {
1357  const double relativeGain = deltaV / MAX2(vMax,
1360  changeLeftToAvoidOvertakeRight = true;
1361  }
1362 #ifdef DEBUG_WANTS_CHANGE
1363  if (DEBUG_COND) {
1364  std::cout << STEPS2TIME(currentTime)
1365  << " avoid overtaking on the right nv=" << nv->getID()
1366  << " deltaV=" << deltaV
1367  << " nvSpeed=" << nv->getSpeed()
1368  << " mySpeedGainProbability=" << mySpeedGainProbability
1369  << " planned acceleration =" << myLCAccelerationAdvices.back().first
1370  << "\n";
1371  }
1372 #endif
1373  }
1374  }
1375  const bool currFreeUntilNeighEnd = leader.first == nullptr || neighDist - posOnLane <= leader.second;
1376  const double overtakeDist = (leader.first == 0 || hasBidiLeader ? -1 :
1377  leader.second + myVehicle.getVehicleType().getLength() + leader.first->getVehicleType().getLengthWithGap());
1378  if (leader.first != 0 && (leader.first->isStopped() || hasBidiLeader) && leader.second < REACT_TO_STOPPED_DISTANCE
1379  // current destination leaves enough space to overtake the leader
1380  && MIN2(neighDist, currentDist) - posOnLane > overtakeDist
1381  // maybe do not overtake on the right at high speed
1382  && (!checkOverTakeRight || !right)
1383  && myStrategicParam >= 0
1384  && (neighLead.first == 0 || !neighLead.first->isStopped()
1385  // neighboring stopped vehicle leaves enough space to overtake leader
1386  || neighLead.second > overtakeDist)) {
1387  // avoid becoming stuck behind a stopped leader
1388  currentDist = myVehicle.getPositionOnLane() + leader.second;
1389 #ifdef DEBUG_WANTS_CHANGE
1390  if (DEBUG_COND) {
1391  std::cout << " veh=" << myVehicle.getID() << " overtake stopped leader=" << leader.first->getID()
1392  << " overtakeDist=" << overtakeDist
1393  << " remaining=" << MIN2(neighDist, currentDist) - posOnLane
1394  << "\n";
1395  }
1396 #endif
1397  ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1398  } else if (!changeToBest && currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist) && !hasBidiLeader) {
1399  // the opposite lane-changing direction should be done than the one examined herein
1400  // we'll check whether we assume we could change anyhow and get back in time...
1401  //
1402  // this rule prevents the vehicle from moving in opposite direction of the best lane
1403  // unless the way till the end where the vehicle has to be on the best lane
1404  // is long enough
1405 #ifdef DEBUG_WANTS_CHANGE
1406  if (DEBUG_COND) {
1407  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1408  }
1409 #endif
1410  ret = ret | LCA_STAY | LCA_STRATEGIC;
1411  } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1412  // the current lane is the best and a lane-changing would cause a situation
1413  // of which we assume we will not be able to return to the lane we have to be on.
1414  // this rule prevents the vehicle from leaving the current, best lane when it is
1415  // close to this lane's end
1416 #ifdef DEBUG_WANTS_CHANGE
1417  if (DEBUG_COND) {
1418  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1419  }
1420 #endif
1421  ret = ret | LCA_STAY | LCA_STRATEGIC;
1422  } else if (bestLaneOffset == 0
1423  && (leader.first == 0 || !leader.first->isStopped())
1424  && !hasBidiLeader
1425  && neigh.bestContinuations.back()->getLinkCont().size() != 0
1426  && roundaboutBonus == 0
1427  && !checkOpposite
1428  && ((myStrategicParam >= 0 && neighDist < TURN_LANE_DIST)
1429  // lane changing cannot possibly help
1430  || (myStrategicParam < 0 && currFreeUntilNeighEnd))
1431  ) {
1432  // VARIANT_21 (stayOnBest)
1433  // we do not want to leave the best lane for a lane which leads elsewhere
1434  // unless our leader is stopped or we are approaching a roundabout
1435 #ifdef DEBUG_WANTS_CHANGE
1436  if (DEBUG_COND) {
1437  std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1438  }
1439 #endif
1440  ret = ret | LCA_STAY | LCA_STRATEGIC;
1441  }
1442  }
1443  // check for overriding TraCI requests
1444 #ifdef DEBUG_WANTS_CHANGE
1445  if (DEBUG_COND) {
1446  std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << toString((LaneChangeAction)ret);
1447  }
1448 #endif
1449  // store state before canceling
1450  getCanceledState(laneOffset) |= ret;
1452  if ((ret & lcaCounter) != 0) {
1453  // we are not interested in traci requests for the opposite direction here
1454  ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1455  }
1456 #ifdef DEBUG_WANTS_CHANGE
1457  if (DEBUG_COND) {
1458  std::cout << " retAfterInfluence=" << toString((LaneChangeAction)ret) << "\n";
1459  }
1460 #endif
1461 
1462  if ((ret & LCA_STAY) != 0) {
1463  // remove TraCI flags because it should not be included in "state-without-traci"
1464  ret = getCanceledState(laneOffset);
1465  return ret;
1466  }
1467  if ((ret & LCA_URGENT) != 0) {
1468  // prepare urgent lane change maneuver
1469  // save the left space
1470  myLeftSpace = currentDist - posOnLane;
1471  if (changeToBest && abs(bestLaneOffset) > 1) {
1472  // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1473  myLeadingBlockerLength = MAX2((right ? 20.0 : 40.0), myLeadingBlockerLength);
1474 #ifdef DEBUG_WANTS_CHANGE
1475  if (DEBUG_COND) {
1476  std::cout << " reserving space for unseen blockers myLeadingBlockerLength=" << myLeadingBlockerLength << "\n";
1477  }
1478 #endif
1479  }
1480 
1481  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1482  // if there is a leader and he wants to change to the opposite direction
1483  const bool canContinue = curr.bestContinuations.size() > 1;
1484  bool canReserve = MSLCHelper::updateBlockerLength(myVehicle, neighLead.first, lcaCounter, myLeftSpace - MAGIC_OFFSET, canContinue, myLeadingBlockerLength);
1485  if (*firstBlocked != neighLead.first) {
1486  canReserve &= MSLCHelper::updateBlockerLength(myVehicle, *firstBlocked, lcaCounter, myLeftSpace - MAGIC_OFFSET, canContinue, myLeadingBlockerLength);
1487  }
1488 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
1489  if (DEBUG_COND) {
1490  std::cout << SIMTIME << " canReserve=" << canReserve << " canContinue=" << canContinue << "\n";
1491  }
1492 #endif
1493  if (!canReserve && !isOpposite()) {
1494  // we have a low-priority relief connection
1495  // std::cout << SIMTIME << " veh=" << myVehicle.getID() << " cannotReserve for blockers\n";
1496  myDontBrake = canContinue;
1497  }
1498 
1499  const int remainingLanes = MAX2(1, abs(bestLaneOffset));
1500  const double urgency = isOpposite() ? OPPOSITE_URGENCY : URGENCY;
1501  const double remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1502  //MAX2(STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1503  MAX2(STEPS2TIME(TS), myLeftSpace / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1505  if (!hasBidiNeighLeader) {
1506  const double plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1507  // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1508  // while informLeader returns -1 in that case. Refs. #2577
1509  if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1510  // maybe we need to deal with a blocking follower
1511  const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, neighFollow.first);
1512  if (!hasBidiNeighFollower) {
1513  informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1514  }
1515  }
1516 #ifdef DEBUG_WANTS_CHANGE
1517  if (DEBUG_COND) {
1518  std::cout << STEPS2TIME(currentTime)
1519  << " veh=" << myVehicle.getID()
1520  << " myLeftSpace=" << myLeftSpace
1521  << " remainingSeconds=" << remainingSeconds
1522  << " plannedSpeed=" << plannedSpeed
1523  << "\n";
1524  }
1525 #endif
1526  } else {
1527 #ifdef DEBUG_WANTS_CHANGE
1528  if (DEBUG_COND) {
1529  std::cout << STEPS2TIME(currentTime)
1530  << " veh=" << myVehicle.getID()
1531  << " myLeftSpace=" << myLeftSpace
1532  << " remainingSeconds=" << remainingSeconds
1533  << " hasBidiNeighLeader\n";
1534  }
1535 #endif
1536  }
1537 
1538 
1539  // remove TraCI flags because it should not be included in "state-without-traci"
1540  ret = getCanceledState(laneOffset);
1541  return ret;
1542  }
1543 
1544  // we wish to anticipate future speeds. This is difficult when the leading
1545  // vehicles are still accelerating so we resort to comparing speeds for the near future (1s) in this case
1546  const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1547  || (leader.first != 0 && leader.first->getAcceleration() > 0);
1548  double neighLaneVSafe = MIN2(neighVMax, anticipateFollowSpeed(neighLead, neighDist, neighVMax, acceleratingLeader));
1549  thisLaneVSafe = MIN2(thisLaneVSafe, anticipateFollowSpeed(leader, currentDist, vMax, acceleratingLeader));
1550  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " thisLaneVSafe=" << thisLaneVSafe << " neighLaneVSafe=" << neighLaneVSafe << "\n";
1551 
1552 
1553  // a high inconvenience prevents cooperative changes and the following things are inconvenient:
1554  // - a desire to change in the opposite direction for speedGain
1555  // - low anticipated speed on the neighboring lane
1556  // - high occupancy on the neighboring lane while in a roundabout
1557 
1558  double inconvenience = laneOffset < 0
1561 
1562  const double relSpeedDiff = thisLaneVSafe == 0 ? 0 : (thisLaneVSafe - neighLaneVSafe) / MAX2(thisLaneVSafe, neighLaneVSafe);
1563  inconvenience = MAX2(relSpeedDiff, inconvenience);
1564  inconvenience = MIN2(1.0, inconvenience);
1565 
1566  const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1567  const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1568 #ifdef DEBUG_WANTS_CHANGE
1569  if (DEBUG_COND) {
1570  std::cout << STEPS2TIME(currentTime)
1571  << " veh=" << myVehicle.getID()
1572  << " speedGainProb=" << mySpeedGainProbability
1573  << " neighSpeedFactor=" << (thisLaneVSafe / neighLaneVSafe - 1)
1574  << " inconvenience=" << inconvenience
1575  << " speedInconv=" << speedGainInconvenient
1576  << " occInconv=" << neighOccupancyInconvenient
1577  << "\n";
1578  }
1579 #endif
1580 
1581  // VARIANT_15
1582  if (roundaboutBonus > 0) {
1583 
1584 #ifdef DEBUG_WANTS_CHANGE
1585  if (DEBUG_COND) {
1586  std::cout << STEPS2TIME(currentTime)
1587  << " veh=" << myVehicle.getID()
1588  << " roundaboutBonus=" << roundaboutBonus
1589  << " myLeftSpace=" << myLeftSpace
1590  << "\n";
1591  }
1592 #endif
1593  // try to use the inner lanes of a roundabout to increase throughput
1594  // unless we are approaching the exit
1595  if (lca == LCA_LEFT) {
1596  // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1597  // TODO: test this for euler update! Refs. #2575
1598  if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1599 // if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1600  req = ret | lca | LCA_COOPERATIVE;
1601  }
1602  } else {
1603  // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1604  if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1605 // if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1606  req = ret | LCA_STAY | LCA_COOPERATIVE;
1607  }
1608  }
1609  if (!cancelRequest(req, laneOffset)) {
1610  return ret | req;
1611  }
1612  }
1613 
1614  // let's also regard the case where the vehicle is driving on a highway...
1615  // in this case, we do not want to get to the dead-end of an on-ramp
1616  if (right) {
1617  if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1618 #ifdef DEBUG_WANTS_CHANGE
1619  if (DEBUG_COND) {
1620  std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1621  }
1622 #endif
1623  req = ret | LCA_STAY | LCA_STRATEGIC;
1624  if (!cancelRequest(req, laneOffset)) {
1625  return ret | req;
1626  }
1627  }
1628  }
1629  // --------
1630 
1631  // -------- make place on current lane if blocking follower
1632  //if (amBlockingFollowerPlusNB()) {
1633  // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1634  // << " neighDist=" << neighDist
1635  // << " currentDist=" << currentDist
1636  // << "\n";
1637  //}
1638 
1640  && (!speedGainInconvenient)
1641  && ((myOwnState & myLca) != 0) // VARIANT_6 : counterNoHelp
1642  && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1643 
1644  // VARIANT_2 (nbWhenChangingToHelp)
1645 #ifdef DEBUG_COOPERATE
1646  if (DEBUG_COND) {
1647  std::cout << STEPS2TIME(currentTime)
1648  << " veh=" << myVehicle.getID()
1649  << " wantsChangeToHelp=" << (right ? "right" : "left")
1650  << " state=" << myOwnState
1651  << (((myOwnState & myLca) == 0) ? " (counter)" : "")
1652  << "\n";
1653  }
1654 #endif
1655  req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1656  if (!cancelRequest(req, laneOffset)) {
1657  return ret | req;
1658  }
1659  }
1660 
1661  // --------
1662 
1663 
1666  //if ((blocked & LCA_BLOCKED) != 0) {
1667  // return ret;
1668  //}
1670 
1671  // -------- higher speed
1672  //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1673  // return ret;
1674  //}
1675 
1676  if (neighLane.getEdge().getPersons().size() > 0) {
1677  // react to pedestrians
1678  adaptSpeedToPedestrians(myVehicle.getLane(), thisLaneVSafe);
1679  adaptSpeedToPedestrians(&neighLane, neighLaneVSafe);
1680  }
1681 
1682  const double relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1684 
1685 #ifdef DEBUG_WANTS_CHANGE
1686  if (DEBUG_COND) {
1687  std::cout << STEPS2TIME(currentTime)
1688  << " veh=" << myVehicle.getID()
1689  << " currentDist=" << currentDist
1690  << " neighDist=" << neighDist
1691  << " thisVSafe=" << thisLaneVSafe
1692  << " neighVSafe=" << neighLaneVSafe
1693  << " relGain=" << toString(relativeGain, 8)
1694  << "\n";
1695  }
1696 #endif
1697 
1698  if (right) {
1699  // ONLY FOR CHANGING TO THE RIGHT
1700  if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1701  // ok, the current lane is faster than the right one...
1702  if (mySpeedGainProbability < 0) {
1704  //myKeepRightProbability /= 2.0;
1705  }
1706  } else {
1707  // ok, the current lane is not (much) faster than the right one
1708  // @todo recheck the 5 km/h discount on thisLaneVSafe, refs. #2068
1709 
1710  // do not promote changing to the left just because changing to the right is bad
1711  // XXX: The following code may promote it, though!? (recheck!)
1712  // (Think of small negative mySpeedGainProbability and larger negative relativeGain)
1713  // One might think of replacing '||' by '&&' to exclude that possibility...
1714  // Still, for negative relativeGain, we might want to decrease the inclination for
1715  // changing to the left. Another solution could be the seperation of mySpeedGainProbability into
1716  // two variables (one for left and one for right). Refs #2578
1717  if (mySpeedGainProbability < 0 || relativeGain > 0) {
1719  }
1720 
1721  // honor the obligation to keep right (Rechtsfahrgebot)
1722  const double roadSpeedFactor = vMax / myVehicle.getLane()->getSpeedLimit(); // differse from speedFactor if vMax < speedLimit
1723  double acceptanceTime;
1724  if (myKeepRightAcceptanceTime == -1) {
1725  // legacy behavior: scale acceptance time with current speed and
1726  // use old hard-coded constant
1727  acceptanceTime = 7 * roadSpeedFactor * MAX2(1.0, myVehicle.getSpeed());
1728  } else {
1729  acceptanceTime = myKeepRightAcceptanceTime * roadSpeedFactor;
1730  if (follower.first != nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1731  // reduce acceptanceTime if the follower vehicle is faster or wants to drive faster
1732  if (follower.first->getSpeed() >= myVehicle.getSpeed()) {
1733  acceptanceTime *= MAX2(1.0, myVehicle.getSpeed()) / MAX2(1.0, follower.first->getSpeed());
1734  const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1735  if (fRSF > roadSpeedFactor) {
1736  acceptanceTime /= fRSF;
1737  }
1738  }
1739  }
1740  }
1741  double fullSpeedGap = MAX2(0., neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1742  double fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1743  if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1744  fullSpeedGap = MAX2(0., MIN2(fullSpeedGap,
1745  neighLead.second - myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1746  vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1747  fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1748  }
1749  // stay on the current lane if we cannot overtake a slow leader on the right
1750  if (checkOverTakeRight && leader.first != 0
1751  && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1752  fullSpeedGap = MIN2(fullSpeedGap, leader.second);
1753  fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1754  const double relGain = (vMax - leader.first->getLane()->getVehicleMaxSpeed(leader.first)) / MAX2(vMax,
1756  // tiebraker to avoid buridans paradox see #1312
1758  }
1759 
1760  const double deltaProb = (myChangeProbThresholdRight * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1762 
1763  //std::cout << STEPS2TIME(currentTime)
1764  // << " veh=" << myVehicle.getID()
1765  // << " acceptanceTime=" << acceptanceTime
1766  // << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1767  // << " dProb=" << deltaProb
1768  // << " myKeepRightProbability=" << myKeepRightProbability
1769  // << "\n";
1770 
1771 #ifdef DEBUG_WANTS_CHANGE
1772  if (DEBUG_COND) {
1773  std::cout << STEPS2TIME(currentTime)
1774  << " veh=" << myVehicle.getID()
1775  << " vMax=" << vMax
1776  << " neighDist=" << neighDist
1777  << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1778  << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1779  << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1780  myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1781  << " acceptanceTime=" << acceptanceTime
1782  << " fullSpeedGap=" << fullSpeedGap
1783  << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1784  << " dProb=" << deltaProb
1785  << " myKeepRightProbability=" << myKeepRightProbability
1786  << "\n";
1787  }
1788 #endif
1790  req = ret | lca | LCA_KEEPRIGHT;
1791  if (!cancelRequest(req, laneOffset)) {
1792  return ret | req;
1793  }
1794  }
1795  }
1796 
1797 #ifdef DEBUG_WANTS_CHANGE
1798  if (DEBUG_COND) {
1799  std::cout << STEPS2TIME(currentTime)
1800  << " veh=" << myVehicle.getID()
1801  << " speed=" << myVehicle.getSpeed()
1802  << " mySpeedGainProbability=" << mySpeedGainProbability
1803  << " thisLaneVSafe=" << thisLaneVSafe
1804  << " neighLaneVSafe=" << neighLaneVSafe
1805  << " relativeGain=" << relativeGain
1806  << " blocked=" << blocked
1807  << "\n";
1808  }
1809 #endif
1810 
1812  && neighDist / MAX2(.1, myVehicle.getSpeed()) > 20.) { //./MAX2( .1, myVehicle.getSpeed())) { // -.1
1813  req = ret | lca | LCA_SPEEDGAIN;
1814  if (!cancelRequest(req, laneOffset)) {
1815  return ret | req;
1816  }
1817  }
1818  } else {
1819  // ONLY FOR CHANGING TO THE LEFT
1820  if (thisLaneVSafe > neighLaneVSafe) {
1821  // this lane is better
1822  if (mySpeedGainProbability > 0) {
1824  }
1825  } else if (thisLaneVSafe == neighLaneVSafe) {
1826  if (mySpeedGainProbability > 0) {
1828  }
1829  } else {
1830  // left lane is better
1832  }
1833  // VARIANT_19 (stayRight)
1834  //if (neighFollow.first != 0) {
1835  // MSVehicle* nv = neighFollow.first;
1836  // const double secGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1837  // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1838  // // do not change left if it would inconvenience faster followers
1839  // return ret | LCA_STAY | LCA_SPEEDGAIN;
1840  // }
1841  //}
1842 
1843 #ifdef DEBUG_WANTS_CHANGE
1844  if (DEBUG_COND) {
1845  std::cout << STEPS2TIME(currentTime)
1846  << " veh=" << myVehicle.getID()
1847  << " speed=" << myVehicle.getSpeed()
1848  << " mySpeedGainProbability=" << mySpeedGainProbability
1849  << " thisLaneVSafe=" << thisLaneVSafe
1850  << " neighLaneVSafe=" << neighLaneVSafe
1851  << " relativeGain=" << relativeGain
1852  << " blocked=" << blocked
1853  << "\n";
1854  }
1855 #endif
1856 
1858  && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1859  && neighDist / MAX2(.1, myVehicle.getSpeed()) > 20.) { // .1
1860  req = ret | lca | LCA_SPEEDGAIN;
1861  if (!cancelRequest(req, laneOffset)) {
1862  return ret | req;
1863  }
1864  }
1865  }
1866  // --------
1867  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1868  && myStrategicParam >= 0
1869  && relativeGain >= 0
1870  && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) {
1871  // change towards the correct lane, speedwise it does not hurt
1872  req = ret | lca | LCA_STRATEGIC;
1873  if (!cancelRequest(req, laneOffset)) {
1874  return ret | req;
1875  }
1876  }
1877 #ifdef DEBUG_WANTS_CHANGE
1878  if (DEBUG_COND) {
1879  std::cout << STEPS2TIME(currentTime)
1880  << " veh=" << myVehicle.getID()
1881  << " mySpeedGainProbability=" << mySpeedGainProbability
1882  << " myKeepRightProbability=" << myKeepRightProbability
1883  << " thisLaneVSafe=" << thisLaneVSafe
1884  << " neighLaneVSafe=" << neighLaneVSafe
1885  << "\n";
1886  }
1887 #endif
1888 
1889  return ret;
1890 }
1891 
1892 
1893 double
1894 MSLCM_LC2013::anticipateFollowSpeed(const std::pair<MSVehicle*, double>& leaderDist, double dist, double vMax, bool acceleratingLeader) {
1895  const MSVehicle* leader = leaderDist.first;
1896  const double gap = leaderDist.second;
1897  double futureSpeed;
1898  if (acceleratingLeader) {
1899  // XXX see #6562
1900  const double maxSpeed1s = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1902  if (leader == nullptr) {
1903  if (hasBlueLight()) {
1904  // can continue from any lane if necessary
1905  futureSpeed = vMax;
1906  } else {
1907  futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, dist, 0, 0);
1908  }
1909  } else {
1910  futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1911  }
1912  } else {
1913  // onInsertion = true because the vehicle has already moved
1914  if (leader == nullptr) {
1915  if (hasBlueLight()) {
1916  // can continue from any lane if necessary
1917  futureSpeed = vMax;
1918  } else {
1919  futureSpeed = getCarFollowModel().maximumSafeStopSpeed(dist, getCarFollowModel().getMaxDecel(), myVehicle.getSpeed(), true);
1920  }
1921  } else {
1922  futureSpeed = getCarFollowModel().maximumSafeFollowSpeed(gap, myVehicle.getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), true);
1923  }
1924  }
1925  futureSpeed = MIN2(vMax, futureSpeed);
1926  if (leader != nullptr && gap > 0 && mySpeedGainLookahead > 0) {
1927  const double futureLeaderSpeed = acceleratingLeader ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
1928  const double deltaV = vMax - futureLeaderSpeed;
1929  if (deltaV > 0 && gap > 0) {
1930  const double secGap = getCarFollowModel().getSecureGap(&myVehicle, leader, futureSpeed, leader->getSpeed(), getCarFollowModel().getMaxDecel());
1931  const double fullSpeedGap = gap - secGap;
1932  if (fullSpeedGap / deltaV < mySpeedGainLookahead) {
1933  // anticipate future braking by computing the average
1934  // speed over the next few seconds
1935  const double gapClosingTime = MAX2(0.0, fullSpeedGap / deltaV);
1936  const double foreCastTime = mySpeedGainLookahead * 2;
1937  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " leader=" << leader->getID() << " gap=" << gap << " deltaV=" << deltaV << " futureSpeed=" << futureSpeed << " futureLeaderSpeed=" << futureLeaderSpeed;
1938  futureSpeed = MIN2(futureSpeed, (gapClosingTime * futureSpeed + (foreCastTime - gapClosingTime) * futureLeaderSpeed) / foreCastTime);
1939  //if (DEBUG_COND) std::cout << " newFutureSpeed=" << futureSpeed << "\n";
1940  }
1941  }
1942  }
1943  return futureSpeed;
1944 }
1945 
1946 
1947 int
1949  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1950  if ((*blocked) != nullptr) {
1951  double gap = (*blocked)->getPositionOnLane() - (*blocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1952 #ifdef DEBUG_SLOW_DOWN
1953  if (DEBUG_COND) {
1954  std::cout << SIMTIME
1955  << " veh=" << myVehicle.getID()
1956  << " blocked=" << Named::getIDSecure(*blocked)
1957  << " gap=" << gap
1958  << "\n";
1959  }
1960 #endif
1961  if (gap > POSITION_EPS) {
1962  //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1963  // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1964 
1966  //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1967  ) {
1968  if ((*blocked)->getSpeed() < SUMO_const_haltingSpeed) {
1969  state |= LCA_AMBACKBLOCKER_STANDING;
1970  } else {
1971  state |= LCA_AMBACKBLOCKER;
1972  }
1973  addLCSpeedAdvice(getCarFollowModel().followSpeed(
1975  gap - POSITION_EPS, (*blocked)->getSpeed(),
1976  (*blocked)->getCarFollowModel().getMaxDecel()), false);
1977 
1978  //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1979 #ifdef DEBUG_SLOW_DOWN
1980  if (DEBUG_COND) {
1981  std::cout << SIMTIME
1982  << " veh=" << myVehicle.getID()
1983  << " slowing down for"
1984  << " blocked=" << Named::getIDSecure(*blocked)
1985  << " helpSpeed=" << myLCAccelerationAdvices.back().first
1986  << "\n";
1987  }
1988 #endif
1989  } /* else {
1990  // experimental else-branch...
1991  state |= LCA_AMBACKBLOCKER;
1992  myVSafes.push_back(getCarFollowModel().followSpeed(
1993  &myVehicle, myVehicle.getSpeed(),
1994  (gap - POSITION_EPS), (*blocked)->getSpeed(),
1995  (*blocked)->getCarFollowModel().getMaxDecel()));
1996  }*/
1997  }
1998  }
1999  return state;
2000 }
2001 
2002 
2003 void
2005  if (lane->hasPedestrians()) {
2006 #ifdef DEBUG_WANTS_CHANGE
2007  if (DEBUG_COND) {
2008  std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << "\n";
2009  }
2010 #endif
2014  if (leader.first != 0) {
2015  const double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), leader.second - myVehicle.getVehicleType().getMinGap());
2016  v = MIN2(v, stopSpeed);
2017 #ifdef DEBUG_WANTS_CHANGE
2018  if (DEBUG_COND) {
2019  std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2020  }
2021 #endif
2022  }
2023  }
2024 }
2025 
2026 
2027 double
2028 MSLCM_LC2013::computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const {
2029  double result = MSAbstractLaneChangeModel::computeSpeedLat(latDist, maneuverDist, urgent);
2030 #ifdef DEBUG_WANTS_CHANGE
2031  if (DEBUG_COND) {
2032  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " latDist=" << latDist << " maneuverDist=" << maneuverDist << " result=" << result << "\n";
2033  }
2034 #endif
2035  if (myLeftSpace > POSITION_EPS) {
2036  double speedBound = myMaxSpeedLatStanding + myMaxSpeedLatFactor * myVehicle.getSpeed();
2037  if (isChangingLanes()) {
2038  speedBound = MAX2(LC_RESOLUTION_SPEED_LAT, speedBound);
2039  }
2040  result = MAX2(-speedBound, MIN2(speedBound, result));
2041  }
2042  return result;
2043 }
2044 
2045 
2046 double
2048  return 1 / myAssertive;
2049 }
2050 
2051 double
2053  return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 / myOppositeParam;
2054 }
2055 
2056 bool
2057 MSLCM_LC2013::saveBlockerLength(double length, double foeLeftSpace) {
2058  const bool canReserve = MSLCHelper::canSaveBlockerLength(myVehicle, length, myLeftSpace);
2059  if (!isOpposite() && (canReserve || myLeftSpace > foeLeftSpace)) {
2061 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
2062  if (DEBUG_COND) {
2063  std::cout << SIMTIME << " saveBlockerLength veh=" << myVehicle.getID() << " canReserve=" << canReserve << " myLeftSpace=" << myLeftSpace << " foeLeftSpace=" << foeLeftSpace << "\n";
2064  }
2065 #endif
2066  if (myLeftSpace == 0 && foeLeftSpace < 0) {
2067  // called from opposite overtaking, myLeftSpace must be initialized
2069  }
2070  return true;
2071  } else {
2072  return false;
2073  }
2074 }
2075 
2076 std::string
2077 MSLCM_LC2013::getParameter(const std::string& key) const {
2079  return toString(myStrategicParam);
2080  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2081  return toString(myCooperativeParam);
2082  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2083  return toString(mySpeedGainParam);
2084  } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2085  return toString(myKeepRightParam);
2086  } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2087  return toString(myOppositeParam);
2088  } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2089  return toString(myLookaheadLeft);
2090  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2091  return toString(mySpeedGainRight);
2092  } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2093  return toString(myAssertive);
2094  } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2096  } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2097  return toString(mySigma);
2102  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2104  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT)) {
2105  return toString(myRoundaboutBonus);
2106  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2107  return toString(myCooperativeSpeed);
2108  } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2110  } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2111  return toString(myMaxSpeedLatFactor);
2112  } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2114  // access to internal state for debugging in sumo-gui (not documented since it may change at any time)
2115  } else if (key == "speedGainProbabilityRight") {
2117  } else if (key == "speedGainProbabilityLeft") {
2119  } else if (key == "keepRightProbability") {
2121  } else if (key == "lookAheadSpeed") {
2122  return toString(myLookAheadSpeed);
2123  // motivation relative to threshold
2124  } else if (key == "speedGainRP") {
2126  } else if (key == "speedGainLP") {
2128  } else if (key == "keepRightP") {
2130  }
2131  throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2132 }
2133 
2134 
2135 void
2136 MSLCM_LC2013::setParameter(const std::string& key, const std::string& value) {
2137  double doubleValue;
2138  try {
2139  doubleValue = StringUtils::toDouble(value);
2140  } catch (NumberFormatException&) {
2141  throw InvalidArgument("Setting parameter '" + key + "' requires a number for laneChangeModel of type '" + toString(myModel) + "'");
2142  }
2144  myStrategicParam = doubleValue;
2145  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2146  myCooperativeParam = doubleValue;
2147  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2148  mySpeedGainParam = doubleValue;
2149  } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2150  myKeepRightParam = doubleValue;
2151  } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2152  myOppositeParam = doubleValue;
2153  } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2154  myLookaheadLeft = doubleValue;
2155  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2156  mySpeedGainRight = doubleValue;
2157  } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2158  myAssertive = doubleValue;
2159  } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2160  myOvertakeRightParam = doubleValue;
2161  } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2162  mySigma = doubleValue;
2164  myKeepRightAcceptanceTime = doubleValue;
2166  myOvertakeDeltaSpeedFactor = doubleValue;
2167  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2168  mySpeedGainLookahead = doubleValue;
2169  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT)) {
2170  myRoundaboutBonus = doubleValue;
2171  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2172  myCooperativeSpeed = doubleValue;
2173  } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2174  myMaxSpeedLatStanding = doubleValue;
2175  } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2176  myMaxSpeedLatFactor = doubleValue;
2177  } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2178  myMaxDistLatStanding = doubleValue;
2179  // access to internal state
2180  } else if (key == "speedGainProbabilityRight") {
2181  mySpeedGainProbability = -doubleValue;
2182  } else if (key == "speedGainProbabilityLeft") {
2183  mySpeedGainProbability = doubleValue;
2184  } else if (key == "keepRightProbability") {
2185  myKeepRightProbability = -doubleValue;
2186  } else if (key == "lookAheadSpeed") {
2187  myLookAheadSpeed = doubleValue;
2188  } else {
2189  throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2190  }
2192 }
2193 
2194 
2195 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define INVALID_SPEED
Definition: MSCFModel.h:31
#define MAGIC_OFFSET
#define HELP_DECEL_FACTOR
#define LOOK_AHEAD_MIN_SPEED
#define LCA_RIGHT_IMPATIENCE
#define LOOK_FORWARD
#define HELP_OVERTAKE
#define REACT_TO_STOPPED_DISTANCE
#define KEEP_RIGHT_TIME
#define RELGAIN_NORMALIZATION_MIN_SPEED
#define CUT_IN_LEFT_SPEED_THRESHOLD
#define MAX_ONRAMP_LENGTH
#define OPPOSITE_URGENCY
#define MIN_FALLBEHIND
#define URGENCY
#define LOOK_AHEAD_SPEED_MEMORY
#define JAM_FACTOR
#define DEBUG_COND
#define TURN_LANE_DIST
#define LC_RESOLUTION_SPEED_LAT
std::pair< const MSPerson *, double > PersonDist
Definition: MSPModel.h:39
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SPEED2DIST(x)
Definition: SUMOTime.h:45
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:51
#define TS
Definition: SUMOTime.h:42
#define SIMTIME
Definition: SUMOTime.h:62
#define DIST2SPEED(x)
Definition: SUMOTime.h:47
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:53
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_KEEPRIGHT
The action is due to the default of keeping right "Rechtsfahrgebot".
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_BLOCKED_BY_LEADER
blocked by leader
@ LCA_AMBACKBLOCKER
@ LCA_AMBLOCKINGLEADER
@ LCA_AMBLOCKINGFOLLOWER_DONTBRAKE
@ LCA_COOPERATIVE
The action is done to help someone else.
@ 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_SPEEDGAIN
The action is due to the wish to be faster (tactical lc)
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_MLEFT
@ LCA_BLOCKED_BY_FOLLOWER
blocker by follower
@ LCA_AMBLOCKINGFOLLOWER
LaneChangeModel
@ SUMO_ATTR_LCA_COOPERATIVE_SPEED
@ SUMO_ATTR_LCA_ASSERTIVE
@ SUMO_ATTR_LCA_LOOKAHEADLEFT
@ SUMO_ATTR_LCA_SPEEDGAIN_PARAM
@ SUMO_ATTR_LCA_MAXDISTLATSTANDING
@ SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT
@ SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD
@ SUMO_ATTR_LCA_MAXSPEEDLATFACTOR
@ SUMO_ATTR_LCA_MAXSPEEDLATSTANDING
@ SUMO_ATTR_LCA_KEEPRIGHT_PARAM
@ SUMO_ATTR_LCA_COOPERATIVE_PARAM
@ SUMO_ATTR_LCA_OPPOSITE_PARAM
@ SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR
@ SUMO_ATTR_LCA_SIGMA
@ SUMO_ATTR_LCA_OVERTAKE_RIGHT
@ SUMO_ATTR_LCA_STRATEGIC_PARAM
@ SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME
@ SUMO_ATTR_LCA_EXPERIMENTAL1
@ SUMO_ATTR_LCA_SPEEDGAINRIGHT
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:26
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:58
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A class responsible for exchanging messages between cars involved in lane-change interaction.
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
Interface for lane-change models.
double getForwardPos() const
get vehicle position relative to the forward direction lane
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
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...
int myOwnState
The current state of the vehicle.
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
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 ...
const LaneChangeModel myModel
the type of this model
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
std::vector< std::pair< double, bool > > myLCAccelerationAdvices
void setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
double getImpatience() const
Returns this vehicles impatience.
MSStop & getNextStop()
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
The car-following model abstraction.
Definition: MSCFModel.h:55
static double gapExtrapolation(const double duration, const double currentGap, double v1, double v2, double a1=0, double a2=0, const double maxV1=std::numeric_limits< double >::max(), const double maxV2=std::numeric_limits< double >::max())
return the resulting gap if, starting with gap currentGap, two vehicles continue with constant accele...
Definition: MSCFModel.cpp:564
virtual double minNextSpeedEmergency(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed after emergency braking, given the current speed (depends on the numerical ...
Definition: MSCFModel.cpp:309
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
Definition: MSCFModel.cpp:298
double maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion=false) const
Returns the maximum safe velocity for following the given leader.
Definition: MSCFModel.cpp:922
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 getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition: MSCFModel.h:256
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition: MSCFModel.h:380
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1, bool relaxEmergency=true) const
Returns the maximum next velocity for stopping within gap.
Definition: MSCFModel.cpp:774
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:264
virtual double getSpeedAfterMaxDecel(double v) const
Returns the velocity after maximum deceleration.
Definition: MSCFModel.h:403
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const =0
Computes the vehicle's follow speed (no dawdling)
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition: MSCFModel.h:168
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition: MSEdge.h:201
bool hasLaneChanger() const
Definition: MSEdge.h:715
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:53
static bool isBidiFollower(const MSVehicle *ego, const MSVehicle *follower)
Definition: MSLCHelper.cpp:352
static bool canSaveBlockerLength(const MSVehicle &veh, double requested, double leftSpace)
Definition: MSLCHelper.cpp:290
static double getSpeedPreservingSecureGap(const MSVehicle &leader, const MSVehicle &follower, double currentGap, double leaderPlannedSpeed)
Definition: MSLCHelper.cpp:311
static double getRoundaboutDistBonus(const MSVehicle &veh, double bonusParam, const MSVehicle::LaneQ &curr, const MSVehicle::LaneQ &neigh, const MSVehicle::LaneQ &best)
Definition: MSLCHelper.cpp:43
static bool isBidiLeader(const MSVehicle *leader, const std::vector< MSLane * > &cont)
Definition: MSLCHelper.cpp:334
static bool updateBlockerLength(const MSVehicle &veh, MSVehicle *blocker, int lcaCounter, double leftSpace, bool reliefConnection, double &leadingBlockerLength)
Definition: MSLCHelper.cpp:225
static bool divergentRoute(const MSVehicle &v1, const MSVehicle &v2)
return whether the vehicles are on the same junction but on divergent paths
Definition: MSLCHelper.cpp:302
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
Definition: MSLCM_LC2013.h:192
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked) override
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
void informFollower(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighFollow, double remainingSeconds, double plannedSpeed)
decide whether we will try cut in before the follower or allow to be overtaken
double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const override
decides the next lateral speed (for continuous lane changing)
double myOvertakeDeltaSpeedFactor
Definition: MSLCM_LC2013.h:243
double myLookAheadSpeed
Definition: MSLCM_LC2013.h:213
double getExtraReservation(int bestLaneOffset) const override
reserve extra space for unseen blockers when more tnan one lane change is required
bool debugVehicle() const override
whether the current vehicles shall be debugged
double myStrategicParam
Definition: MSLCM_LC2013.h:219
double myRoundaboutBonus
Definition: MSLCM_LC2013.h:235
double mySpeedGainLookahead
Definition: MSLCM_LC2013.h:233
const double myExperimentalParam1
Definition: MSLCM_LC2013.h:246
double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel) override
Called to adapt the speed in order to allow a lane change. It uses information on LC-related desired ...
void initDerivedParameters()
init cached parameters derived directly from model parameters
double myCooperativeParam
Definition: MSLCM_LC2013.h:220
MSLCM_LC2013(MSVehicle &v)
double myChangeProbThresholdRight
Definition: MSLCM_LC2013.h:253
double anticipateFollowSpeed(const std::pair< MSVehicle *, double > &leaderDist, double dist, double vMax, bool acceleratingLeader)
anticipate future follow speed for the given leader
std::string getParameter(const std::string &key) const override
try to retrieve the given parameter from this device. Throw exception for unsupported key
void setParameter(const std::string &key, const std::string &value) override
try to set the given parameter for this laneChangeModel. Throw exception for unsupported key
double myCooperativeSpeed
Definition: MSLCM_LC2013.h:237
double informLeader(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighLead, double remainingSeconds)
double _patchSpeed(double min, const double wanted, double max, const MSCFModel &cfModel)
double mySpeedGainParam
Definition: MSLCM_LC2013.h:221
double myLookaheadLeft
Definition: MSLCM_LC2013.h:226
double myLeadingBlockerLength
Definition: MSLCM_LC2013.h:208
std::pair< double, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
Definition: MSLCM_LC2013.h:199
void prepareStep() override
double getSafetyFactor() const override
return factor for modifying the safety constraints of the car-following model
int slowDownForBlocked(MSVehicle **blocked, int state)
compute useful slowdowns for blocked vehicles
double myLeftSpace
Definition: MSLCM_LC2013.h:209
double myOppositeParam
Definition: MSLCM_LC2013.h:223
bool amBlockingFollowerPlusNB()
Definition: MSLCM_LC2013.h:186
double myKeepRightProbability
Definition: MSLCM_LC2013.h:206
double myKeepRightParam
Definition: MSLCM_LC2013.h:222
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
Definition: MSLCM_LC2013.h:189
void adaptSpeedToPedestrians(const MSLane *lane, double &v)
react to pedestrians on the given lane
virtual ~MSLCM_LC2013()
double getOppositeSafetyFactor() const override
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
void resetState() override
double mySpeedGainRight
Definition: MSLCM_LC2013.h:228
double myKeepRightAcceptanceTime
Definition: MSLCM_LC2013.h:240
double myAssertive
Definition: MSLCM_LC2013.h:231
bool saveBlockerLength(double length, double foeLeftSpace) override
reserve space at the end of the lane to avoid dead locks
void changed() override
double mySpeedGainProbability
a value for tracking the probability that a change to the offset with the same sign is beneficial
Definition: MSLCM_LC2013.h:202
double myChangeProbThresholdLeft
Definition: MSLCM_LC2013.h:254
void * inform(void *info, MSVehicle *sender) override
int _wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
helper function for doing the actual work
static double overtakeDistance(const MSVehicle *follower, const MSVehicle *leader, const double gap, double followerSpeed=INVALID_SPEED, double leaderSpeed=INVALID_SPEED)
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:712
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
Definition: MSLane.cpp:4420
bool isAccelLane() const
return whether this lane is an acceleration lane
Definition: MSLane.h:535
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:584
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:566
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition: MSLane.cpp:4413
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:634
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition: MSLane.cpp:3245
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:752
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition: MSLane.cpp:4494
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition: MSLane.cpp:3090
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
const MSLane * lane
The lane to stop at (microsim only)
Definition: MSStop.h:50
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Definition: MSVehicle.cpp:771
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition: MSVehicle.h:536
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:7218
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation,...
Definition: MSVehicle.cpp:1376
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition: MSVehicle.h:1036
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
int getBestLaneOffset() const
Definition: MSVehicle.cpp:6402
double getLastStepDist() const
Get the distance the vehicle covered in the previous timestep.
Definition: MSVehicle.h:384
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7183
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
Definition: MSVehicle.cpp:6623
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
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:5738
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:6845
void setLateralPositionOnLane(double posLat)
Definition: MSVehicle.h:420
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
void step(double dt)
evolve for a time step of length dt.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
A structure representing the best lanes for continuing the current route starting at 'lane'.
Definition: MSVehicle.h:865
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:869
std::vector< MSLane * > bestContinuations
Definition: MSVehicle.h:885
MSLane * lane
The described lane.
Definition: MSVehicle.h:867
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition: MSVehicle.h:877
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:873