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