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