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