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 
65 #define KEEP_RIGHT_TIME (double)5.0 // the number of seconds after which a vehicle should move to the right lane
66 #define KEEP_RIGHT_ACCEPTANCE (double)7.0 // calibration factor for determining the desire to keep right
67 #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)
68 
69 #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
70 #define ROUNDABOUT_DIST_TRESH (double)10.0 // roundabout distances below ROUNDABOUT_DIST_TRESH are not multiplied by ROUNDABOUT_DIST_FACTOR
71 
72 #define KEEP_RIGHT_HEADWAY (double)2.0
73 #define MAX_ONRAMP_LENGTH (double)200.
74 #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
75 
76 #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
77 #define LC_ASSUMED_DECEL (double)1.0 // the minimal constant deceleration assumed to estimate the duration of a continuous lane-change at its initiation.
78 
79 #define REACT_TO_STOPPED_DISTANCE 100
80 
81 // ===========================================================================
82 // debug defines
83 // ===========================================================================
84 //#define DEBUG_PATCH_SPEED
85 //#define DEBUG_INFORMED
86 //#define DEBUG_INFORMER
87 //#define DEBUG_CONSTRUCTOR
88 //#define DEBUG_WANTS_CHANGE
89 //#define DEBUG_SLOW_DOWN
90 //#define DEBUG_COOPERATE
91 //#define DEBUG_SAVE_BLOCKER_LENGTH
92 
93 //#define DEBUG_COND (myVehicle.getID() == "disabled")
94 #define DEBUG_COND (myVehicle.isSelected())
95 //#define DEBUG_COND (false)
96 
97 // ===========================================================================
98 // member method definitions
99 // ===========================================================================
102  mySpeedGainProbability(0),
103  myKeepRightProbability(0),
104  myLeadingBlockerLength(0),
105  myLeftSpace(0),
106  myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED),
107  myStrategicParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_PARAM, 1)),
108  myCooperativeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_PARAM, 1)),
109  mySpeedGainParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_PARAM, 1)),
110  myKeepRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_PARAM, 1)),
111  myLookaheadLeft(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_LOOKAHEADLEFT, 2.0)),
112  mySpeedGainRight(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAINRIGHT, 0.1)),
113  myAssertive(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_ASSERTIVE, 1)),
114  myExperimentalParam1(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_EXPERIMENTAL1, 0)) {
116 #ifdef DEBUG_CONSTRUCTOR
117  if (DEBUG_COND) {
118  std::cout << SIMTIME
119  << " create lcModel veh=" << myVehicle.getID()
120  << " lcStrategic=" << myStrategicParam
121  << " lcCooperative=" << myCooperativeParam
122  << " lcSpeedGain=" << mySpeedGainParam
123  << " lcKeepRight=" << myKeepRightParam
124  << "\n";
125  }
126 #endif
127 }
128 
130  changed();
131 }
132 
133 
134 void
138 }
139 
140 
141 bool
143  return DEBUG_COND;
144 }
145 
146 
147 int
149  int laneOffset,
151  int blocked,
152  const std::pair<MSVehicle*, double>& leader,
153  const std::pair<MSVehicle*, double>& neighLead,
154  const std::pair<MSVehicle*, double>& neighFollow,
155  const MSLane& neighLane,
156  const std::vector<MSVehicle::LaneQ>& preb,
157  MSVehicle** lastBlocked,
158  MSVehicle** firstBlocked) {
159 
160 #ifdef DEBUG_WANTS_CHANGE
161  if (DEBUG_COND) {
162  std::cout << "\nWANTS_CHANGE\n" << SIMTIME
163  << std::setprecision(gPrecision)
164  << " veh=" << myVehicle.getID()
165  << " lane=" << myVehicle.getLane()->getID()
166  << " pos=" << myVehicle.getPositionOnLane()
167  << " posLat=" << myVehicle.getLateralPositionOnLane()
168  << " speed=" << myVehicle.getSpeed()
169  << " considerChangeTo=" << (laneOffset == -1 ? "right" : "left")
170  << "\n";
171  }
172 #endif
173 
174  const int result = _wantsChange(laneOffset, msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked);
175 
176 #ifdef DEBUG_WANTS_CHANGE
177  if (DEBUG_COND) {
178  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " result=" << toString((LaneChangeAction)result) << " blocked=" << toString((LaneChangeAction)blocked) << "\n\n\n";
179  }
180 #endif
181 
182  return result;
183 }
184 
185 
186 double
187 MSLCM_LC2013::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
188 
189 #ifdef DEBUG_PATCH_SPEED
190  if (DEBUG_COND) {
191  std::cout << "\nPATCH_SPEED\n"
192  << SIMTIME
193  << " veh=" << myVehicle.getID()
194  << " lane=" << myVehicle.getLane()->getID()
195  << " pos=" << myVehicle.getPositionOnLane()
196  << " v=" << myVehicle.getSpeed()
197  << " min=" << min
198  << " wanted=" << wanted
199  << " max=" << max
200  << "\n";
201  }
202 #endif
203 
204  // negative min speed may be passed when using ballistic updated
205  const double newSpeed = _patchSpeed(MAX2(min, 0.0), wanted, max, cfModel);
206 
207 #ifdef DEBUG_PATCH_SPEED
208  if (DEBUG_COND) {
209  const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
210  std::cout << patched
211  << "\n";
212  }
213 #endif
214 
215  return newSpeed;
216 }
217 
218 
219 double
220 MSLCM_LC2013::_patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
221  int state = myOwnState;
222 #ifdef DEBUG_PATCH_SPEED
223  if (DEBUG_COND) {
224  std::cout
225  << "\n" << SIMTIME << std::setprecision(gPrecision)
226  << " patchSpeed state=" << state << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
227  << " \nspeed=" << myVehicle.getSpeed()
228  << " min=" << min
229  << " wanted=" << wanted << std::endl;
230  }
231 #endif
232 
233  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
234  double MAGIC_offset = 1.;
235  // if we want to change and have a blocking leader and there is enough room for him in front of us
236  if (myLeadingBlockerLength != 0) {
237  double space = myLeftSpace - myLeadingBlockerLength - MAGIC_offset - myVehicle.getVehicleType().getMinGap();
238 #ifdef DEBUG_PATCH_SPEED
239  if (DEBUG_COND) {
240  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeadingBlockerLength=" << myLeadingBlockerLength << " space=" << space << "\n";
241  }
242 #endif
243  if (space > 0) { // XXX space > -MAGIC_offset
244  // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
245  double safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space);
246  // if we are approaching this place
247  if (safe < wanted) {
248  // return this speed as the speed to use
249 #ifdef DEBUG_PATCH_SPEED
250  if (DEBUG_COND) {
251  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ? " (not enough)" : "") << "\n";
252  }
253 #endif
254  return MAX2(min, safe);
255  }
256  }
257  }
258 
259  double nVSafe = wanted;
260  bool gotOne = false;
261  for (std::vector<double>::const_iterator i = myLCAccelerationAdvices.begin(); i != myLCAccelerationAdvices.end(); ++i) {
262  double a = (*i);
263  double v = myVehicle.getSpeed() + ACCEL2SPEED(a);
264 
265  if (v >= min && v <= max && (MSGlobals::gSemiImplicitEulerUpdate
266  // ballistic update: (negative speeds may appear, e.g. min<0, v<0), BUT:
267  // XXX: LaneChanging returns -1 to indicate no restrictions, which leads to probs here (Leo), refs. #2577
268  // As a quick fix, we just dismiss cases where v=-1
269  // VERY rarely (whenever a requested help-acceleration is really indicated by v=-1)
270  // this can lead to failing lane-change attempts, though)
271  || v != -1)) {
272  nVSafe = MIN2(v * myCooperativeParam + (1 - myCooperativeParam) * wanted, nVSafe);
273  gotOne = true;
274 #ifdef DEBUG_PATCH_SPEED
275  if (DEBUG_COND) {
276  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got nVSafe=" << nVSafe << "\n";
277  }
278 #endif
279  } else {
280  if (v < min) {
281 #ifdef DEBUG_PATCH_SPEED
282  if (DEBUG_COND) {
283  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring low nVSafe=" << v << " min=" << min << "\n";
284  }
285 #endif
286  } else {
287 #ifdef DEBUG_PATCH_SPEED
288  if (DEBUG_COND) {
289  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring high nVSafe=" << v << " max=" << max << "\n";
290  }
291 #endif
292  }
293  }
294  }
295 
296  if (gotOne && !myDontBrake) { // XXX: myDontBrake is initialized as false and seems not to be changed anywhere... What's its purpose???
297 #ifdef DEBUG_PATCH_SPEED
298  if (DEBUG_COND) {
299  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got vSafe\n";
300  }
301 #endif
302  return nVSafe;
303  }
304 
305  // check whether the vehicle is blocked
306  if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) != 0) {
307  if ((state & LCA_STRATEGIC) != 0) {
308  // necessary decelerations are controlled via vSafe. If there are
309  // none it means we should speed up
310 #ifdef DEBUG_PATCH_SPEED
311  if (DEBUG_COND) {
312  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_WANTS_LANECHANGE (strat, no vSafe)\n";
313  }
314 #endif
315  return (max + wanted) / (double) 2.0;
316  } else if ((state & LCA_COOPERATIVE) != 0) {
317  // only minor adjustments in speed should be done
318  if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
319 #ifdef DEBUG_PATCH_SPEED
320  if (DEBUG_COND) {
321  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_LEADER (coop)\n";
322  }
323 #endif
324  if (wanted >= 0.) {
325  return (MAX2(0., min) + wanted) / (double) 2.0;
326  } else {
327  return wanted;
328  }
329  }
330  if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
331 #ifdef DEBUG_PATCH_SPEED
332  if (DEBUG_COND) {
333  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER (coop)\n";
334  }
335 #endif
336  return (max + wanted) / (double) 2.0;
337  }
338  //} else { // VARIANT_16
339  // // only accelerations should be performed
340  // if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
341  // if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER\n";
342  // return (max + wanted) / (double) 2.0;
343  // }
344  }
345  }
346 
347  /*
348  // decelerate if being a blocking follower
349  // (and does not have to change lanes)
350  if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
351  if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
352  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER (standing)\n";
353  return 0;
354  }
355  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER\n";
356 
357  //return min; // VARIANT_3 (brakeStrong)
358  return (min + wanted) / (double) 2.0;
359  }
360  if ((state & LCA_AMBACKBLOCKER) != 0) {
361  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
362  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER (standing)\n";
363  //return min; VARIANT_9 (backBlockVSafe)
364  return nVSafe;
365  }
366  }
367  if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
368  if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER_STANDING\n";
369  //return min;
370  return nVSafe;
371  }
372  */
373 
374  // accelerate if being a blocking leader or blocking follower not able to brake
375  // (and does not have to change lanes)
376  if ((state & LCA_AMBLOCKINGLEADER) != 0) {
377 #ifdef DEBUG_PATCH_SPEED
378  if (DEBUG_COND) {
379  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGLEADER\n";
380  }
381 #endif
382  return (max + wanted) / (double) 2.0;
383  }
384 
385  if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
386 #ifdef DEBUG_PATCH_SPEED
387  if (DEBUG_COND) {
388  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER_DONTBRAKE\n";
389  }
390 #endif
391  /*
392  // VARIANT_4 (dontbrake)
393  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
394  return wanted;
395  }
396  return (min + wanted) / (double) 2.0;
397  */
398  }
399  if (!myVehicle.getLane()->getEdge().hasLaneChanger()) {
400  // remove chaning information if on a road with a single lane
401  changed();
402  }
403  return wanted;
404 }
405 
406 
407 void*
408 MSLCM_LC2013::inform(void* info, MSVehicle* sender) {
409  UNUSED_PARAMETER(sender);
410  Info* pinfo = (Info*)info;
411  assert(pinfo->first >= 0 || !MSGlobals::gSemiImplicitEulerUpdate);
412  addLCSpeedAdvice(pinfo->first);
413  myOwnState |= pinfo->second;
414 #ifdef DEBUG_INFORMED
415  if (DEBUG_COND) {
416  std::cout << SIMTIME
417  << " veh=" << myVehicle.getID()
418  << " informedBy=" << sender->getID()
419  << " info=" << pinfo->second
420  << " vSafe=" << pinfo->first
421  << "\n";
422  }
423 #endif
424  delete pinfo;
425  return (void*) true;
426 }
427 
428 double
429 MSLCM_LC2013::overtakeDistance(const MSVehicle* follower, const MSVehicle* leader, const double gap, double followerSpeed, double leaderSpeed) {
430  followerSpeed = followerSpeed == INVALID_SPEED ? follower->getSpeed() : followerSpeed;
431  leaderSpeed = leaderSpeed == INVALID_SPEED ? leader->getSpeed() : leaderSpeed;
432  double overtakeDist = (gap // drive to back of leader
433  + leader->getVehicleType().getLengthWithGap() // drive to front of leader
434  + follower->getVehicleType().getLength() // follower back reaches leader front
435  + leader->getCarFollowModel().getSecureGap( // save gap to leader
436  leaderSpeed, followerSpeed, follower->getCarFollowModel().getMaxDecel()));
437  return MAX2(overtakeDist, 0.);
438 }
439 
440 
441 double
443  int blocked,
444  int dir,
445  const std::pair<MSVehicle*, double>& neighLead,
446  double remainingSeconds) {
447  double plannedSpeed = MIN2(myVehicle.getSpeed(),
449  for (std::vector<double>::const_iterator i = myLCAccelerationAdvices.begin(); i != myLCAccelerationAdvices.end(); ++i) {
450  const double a = *i;
451  if (a >= -myVehicle.getCarFollowModel().getMaxDecel()) {
452  plannedSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() + ACCEL2SPEED(a));
453  }
454  }
455 #ifdef DEBUG_INFORMER
456  if (DEBUG_COND) {
457  std::cout << "\nINFORM_LEADER"
458  << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
459  }
460 #endif
461 
462  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0 && neighLead.first != 0) {
463  MSVehicle* nv = neighLead.first;
464 #ifdef DEBUG_INFORMER
465  if (DEBUG_COND) {
466  std::cout << " blocked by leader nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
468  }
469 #endif
470  // decide whether we want to overtake the leader or follow it
471  double overtakeTime;
472  const double overtakeDist = overtakeDistance(&myVehicle, nv, neighLead.second);
473  const double dv = plannedSpeed - nv->getSpeed();
474 
475  if (dv > 0) {
476  overtakeTime = overtakeDist / dv;
477  } else {
478  // -> set overtakeTime to something indicating impossibility of overtaking
479  overtakeTime = remainingSeconds + 1;
480  }
481 
482 #ifdef DEBUG_INFORMER
483  if (DEBUG_COND) {
484  std::cout << SIMTIME << " informLeader() of " << myVehicle.getID()
485  << "\nnv = " << nv->getID()
486  << "\nplannedSpeed = " << plannedSpeed
487  << "\nleaderSpeed = " << nv->getSpeed()
488  << "\nmyLeftSpace = " << myLeftSpace
489  << "\nremainingSeconds = " << remainingSeconds
490  << "\novertakeDist = " << overtakeDist
491  << "\novertakeTime = " << overtakeTime
492  << std::endl;
493  }
494 #endif
495 
496  if ((dv < 0
497  // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft)
499  // not enough space to overtake?
501  // 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).
503  // 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)
504  || (remainingSeconds < overtakeTime && (MSGlobals::gSemiImplicitEulerUpdate || !nv->isStopped())))
505  // opposite driving and must overtake
506  && !(isOpposite() && neighLead.second < 0 && neighLead.first->isStopped())) {
507  // cannot overtake
508  msgPass.informNeighLeader(new Info(std::numeric_limits<double>::max(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
509  // slow down smoothly to follow leader
510  const double targetSpeed = myCarFollowModel.followSpeed(
511  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
512  if (targetSpeed < myVehicle.getSpeed()) {
513  // slow down smoothly to follow leader
514  const double decel = remainingSeconds == 0. ? myVehicle.getCarFollowModel().getMaxDecel() :
516  MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds));
517  const double nextSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() - ACCEL2SPEED(decel));
518 #ifdef DEBUG_INFORMER
519  if (DEBUG_COND) {
520  std::cout << SIMTIME
521  << " cannot overtake leader nv=" << nv->getID()
522  << " dv=" << dv
523  << " myLookAheadSpeed=" << myLookAheadSpeed
524  << " myLeftSpace=" << myLeftSpace
525  << " overtakeDist=" << overtakeDist
526  << " overtakeTime=" << overtakeTime
527  << " remainingSeconds=" << remainingSeconds
528  << " currentGap=" << neighLead.second
531  << " targetSpeed=" << targetSpeed
532  << " nextSpeed=" << nextSpeed
533  << "\n";
534  }
535 #endif
536  addLCSpeedAdvice(nextSpeed);
537  return nextSpeed;
538  } else {
539  // leader is fast enough anyway
540 #ifdef DEBUG_INFORMER
541  if (DEBUG_COND) {
542  std::cout << SIMTIME
543  << " cannot overtake fast leader nv=" << nv->getID()
544  << " dv=" << dv
545  << " myLookAheadSpeed=" << myLookAheadSpeed
546  << " myLeftSpace=" << myLeftSpace
547  << " overtakeDist=" << overtakeDist
548  << " myLeadingBlockerLength=" << myLeadingBlockerLength
549  << " overtakeTime=" << overtakeTime
550  << " remainingSeconds=" << remainingSeconds
551  << " currentGap=" << neighLead.second
552  << " targetSpeed=" << targetSpeed
553  << "\n";
554  }
555 #endif
556  addLCSpeedAdvice(targetSpeed);
557  return plannedSpeed;
558  }
559  } else {
560  // overtaking, leader should not accelerate
561 #ifdef DEBUG_INFORMER
562  if (DEBUG_COND) {
563  std::cout << SIMTIME
564  << " wants to overtake leader nv=" << nv->getID()
565  << " dv=" << dv
566  << " overtakeDist=" << overtakeDist
567  << " remainingSeconds=" << remainingSeconds
568  << " overtakeTime=" << overtakeTime
569  << " currentGap=" << neighLead.second
571  << "\n";
572  }
573 #endif
574  msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
575  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
576  }
577  } else if (neighLead.first != 0) { // (remainUnblocked)
578  // we are not blocked now. make sure we stay far enough from the leader
579  MSVehicle* nv = neighLead.first;
580  double dv, nextNVSpeed;
582  // XXX: the decrement (HELP_OVERTAKE) should be scaled with timestep length, I think.
583  // It seems to function as an estimate nv's speed in the next simstep!? (so HELP_OVERTAKE should be an acceleration value.)
584  nextNVSpeed = nv->getSpeed() - HELP_OVERTAKE; // conservative
585  dv = SPEED2DIST(myVehicle.getSpeed() - nextNVSpeed);
586  } else {
587  // Estimate neigh's speed after actionstep length
588  // @note The possible breaking can be underestimated by the formula, so this is a potential
589  // source of collisions if actionsteplength>simsteplength.
590  const double nvMaxDecel = HELP_OVERTAKE;
591  nextNVSpeed = nv->getSpeed() - nvMaxDecel * myVehicle.getActionStepLengthSecs(); // conservative
592  // Estimated gap reduction until next action step if own speed stays constant
593  dv = SPEED2DIST(myVehicle.getSpeed() - nextNVSpeed);
594  }
595  const double targetSpeed = myCarFollowModel.followSpeed(
596  &myVehicle, myVehicle.getSpeed(), neighLead.second - dv, nextNVSpeed, 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  << " nextGap=" << neighLead.second - dv
605  << " targetSpeed=" << targetSpeed
606  << "\n";
607  }
608 #endif
609  return MIN2(targetSpeed, plannedSpeed);
610  } else {
611  // not overtaking
612  return plannedSpeed;
613  }
614 }
615 
616 void
618  int blocked,
619  int dir,
620  const std::pair<MSVehicle*, double>& neighFollow,
621  double remainingSeconds,
622  double plannedSpeed) {
623 
624  MSVehicle* nv = neighFollow.first;
625  const double plannedAccel = SPEED2ACCEL(MAX2(MIN2(myCarFollowModel.getMaxAccel(), plannedSpeed - myVehicle.getSpeed()), -myCarFollowModel.getMaxDecel()));
626 
627 #ifdef DEBUG_INFORMER
628  if (DEBUG_COND) {
629  std::cout << "\nINFORM_FOLLOWER"
630  << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
631  }
632 
633 #endif
634  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0 && nv != 0) {
635 #ifdef DEBUG_INFORMER
636  if (DEBUG_COND) {
637  std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
638  << nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel()) << " planned=" << plannedSpeed << "\n";
639  }
640 #endif
641 
642  // are we fast enough to cut in without any help?
643  if (MAX2(plannedSpeed, 0.) - nv->getSpeed() >= HELP_OVERTAKE) {
644  const double neededGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
645  if ((neededGap - neighFollow.second) / remainingSeconds < (MAX2(plannedSpeed, 0.) - nv->getSpeed())) {
646 #ifdef DEBUG_INFORMER
647  if (DEBUG_COND) {
648  std::cout << " wants to cut in before nv=" << nv->getID() << " without any help." << "\nneededGap = " << neededGap << "\n";
649  }
650 #endif
651  // follower might even accelerate but not to much
652  // XXX: I don't understand this. The needed gap was determined for nv->getSpeed(), not for (plannedSpeed - HELP_OVERTAKE)?! (Leo), refs. #2578
653  msgPass.informNeighFollower(new Info(MAX2(plannedSpeed, 0.) - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
654  return;
655  }
656  }
657 
658  // decide whether we will request help to cut in before the follower or allow to be overtaken
659 
660  // PARAMETERS
661  // assume other vehicle will assume the equivalent of 1 second of
662  // maximum deceleration to help us (will probably be spread over
663  // multiple seconds)
664  // -----------
665  const double helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR;
666 
667  // follower's new speed in next step
668  double neighNewSpeed;
669  // follower's new speed after 1s.
670  double neighNewSpeed1s;
671  // velocity difference, gap after follower-deceleration
672  double dv, decelGap;
673 
675  // euler
676  neighNewSpeed = MAX2(0., nv->getSpeed() - ACCEL2SPEED(helpDecel));
677  neighNewSpeed1s = MAX2(0., nv->getSpeed() - helpDecel); // TODO: consider introduction of a configurable anticipationTime here (see far below in the !blocked part). Refs. #2578
678  // change in the gap between ego and blocker over 1 second (not STEP!)
679  // XXX: though here it is calculated as if it were one step!? (Leo) Refs. #2578
680  dv = plannedSpeed - neighNewSpeed1s; // XXX: what is this quantity (if TS!=1)?
681  // new gap between follower and self in case the follower does brake for 1s
682  // XXX: if the step-length is not 1s., this is not the gap after 1s. deceleration!
683  // And this formula overestimates the real gap. Isn't that problematic? (Leo)
684  // Below, it seems that decelGap > secureGap is taken to indicate the possibility
685  // to cut in within the next time-step. However, this is not the case, if TS<1s.,
686  // since decelGap is (not exactly, though!) the gap after 1s. Refs. #2578
687  decelGap = neighFollow.second + dv;
688  } else {
689  // ballistic
690  // negative newSpeed-extrapolation possible, if stop lies within the next time-step
691  // XXX: this code should work for the euler case as well, since gapExtrapolation() takes
692  // care of this, but for TS!=1 we will have different behavior (see previous remark) Refs. #2578
693  neighNewSpeed = nv->getSpeed() - ACCEL2SPEED(helpDecel);
694  neighNewSpeed1s = nv->getSpeed() - helpDecel;
695 
696  dv = myVehicle.getSpeed() - nv->getSpeed(); // current velocity difference
697  decelGap = myCarFollowModel.gapExtrapolation(1., neighFollow.second, myVehicle.getSpeed(),
698  nv->getSpeed(), plannedAccel, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
699  }
700 
701  const double secureGap = nv->getCarFollowModel().getSecureGap(MAX2(neighNewSpeed1s, 0.),
702  MAX2(plannedSpeed, 0.), myVehicle.getCarFollowModel().getMaxDecel());
703 
704  const double onRampThreshold = myVehicle.getLane()->getSpeedLimit() * 0.8 * myExperimentalParam1 * (1 - myVehicle.getImpatience());
705 
706 #ifdef DEBUG_INFORMER
707  if (DEBUG_COND) {
708  std::cout << SIMTIME
709  << " speed=" << myVehicle.getSpeed()
710  << " plannedSpeed=" << plannedSpeed
711  << " threshold=" << onRampThreshold
712  << " neighNewSpeed=" << neighNewSpeed
713  << " neighNewSpeed1s=" << neighNewSpeed1s
714  << " dv=" << dv
715  << " gap=" << neighFollow.second
716  << " decelGap=" << decelGap
717  << " secureGap=" << secureGap
718  << "\n";
719  }
720 #endif
721  // prevent vehicles on an on ramp stopping the main flow
722  if (dir == LCA_MLEFT
724  && neighNewSpeed1s < onRampThreshold) {
725  return;
726  }
727 
728  if (decelGap > 0 && decelGap >= secureGap) {
729  // XXX: This does not assure that the leader can cut in in the next step if TS < 1 (see above)
730  // this seems to be supposed in the following (euler code)...?! (Leo) Refs. #2578
731 
732  // if the blocking follower brakes it could help
733  // how hard does it actually need to be?
734  // to be safe in the next step the following equation has to hold for the follower's vsafe:
735  // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
736  double vsafe, vsafe1;
737 
739  // euler
740  // we compute an upper bound on vsafe by doing the computation twice
741  vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
742  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, myCarFollowModel.getMaxDecel()));
743  vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
744  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, myCarFollowModel.getMaxDecel()));
745  assert(vsafe <= vsafe1);
746  } else {
747  // ballistic
748 
749  // XXX: This block should actually do as well for euler update (TODO: test!), refs #2575
750  // we compute an upper bound on vsafe
751  // next step's gap without help deceleration (nv's speed assumed constant)
752  double nextGap = myCarFollowModel.gapExtrapolation(TS,
753  neighFollow.second, myVehicle.getSpeed(),
754  nv->getSpeed(), plannedAccel, 0,
756 #ifdef DEBUG_INFORMER
757  if (DEBUG_COND) {
758  std::cout << "nextGap=" << nextGap << " (without help decel) \n";
759  }
760 #endif
761 
762  // NOTE: the second argument of MIN2() can get larger than nv->getSpeed()
763  vsafe1 = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
765  nv->getSpeed(), nextGap,
766  MAX2(0., plannedSpeed),
768 
769 
770  // next step's gap with possibly less than maximal help deceleration (in case vsafe1 > neighNewSpeed)
771  double decel2 = SPEED2ACCEL(nv->getSpeed() - vsafe1);
773  neighFollow.second, myVehicle.getSpeed(),
774  nv->getSpeed(), plannedAccel, -decel2,
776 
777  // vsafe = MAX(neighNewSpeed, safe speed assuming next_gap)
778  // Thus, the gap resulting from vsafe is larger or equal to next_gap
779  // in contrast to the euler case, where nv's follow speed doesn't depend on the actual speed,
780  // we need to assure, that nv doesn't accelerate
781  vsafe = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
783  nv->getSpeed(), nextGap,
784  MAX2(0., plannedSpeed),
786 
787  assert(vsafe >= vsafe1 - NUMERICAL_EPS);
788 
789 #ifdef DEBUG_INFORMER
790  if (DEBUG_COND) {
791  std::cout << "nextGap=" << nextGap
792  << " (with vsafe1 and help decel) \nvsafe1=" << vsafe1
793  << " vsafe=" << vsafe
794  << "\n";
795  }
796 #endif
797 
798  // For subsecond simulation, this might not lead to secure gaps for a long time,
799  // we seek to establish a secure gap as soon as possible
800  double nextSecureGap = nv->getCarFollowModel().getSecureGap(vsafe, plannedSpeed, myCarFollowModel.getMaxDecel());
801 
802  if (nextGap < nextSecureGap) {
803  // establish a secureGap as soon as possible
804  vsafe = neighNewSpeed;
805  }
806 
807 #ifdef DEBUG_INFORMER
808  if (DEBUG_COND) {
809  std::cout << "nextGap=" << nextGap
810  << " minNextSecureGap=" << nextSecureGap
811  << " vsafe=" << vsafe << "\n";
812  }
813 #endif
814 
815  }
816  msgPass.informNeighFollower(
817  new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
818 
819 #ifdef DEBUG_INFORMER
820  if (DEBUG_COND) {
821  std::cout << " wants to cut in before nv=" << nv->getID()
822  << " vsafe1=" << vsafe1 << " vsafe=" << vsafe
823  << " newSecGap="
824  << nv->getCarFollowModel().getSecureGap(vsafe,
825  plannedSpeed,
827  << "\n";
828  }
829 #endif
830  } else if ((MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS))
831  || (!MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * (remainingSeconds - 1) > secureGap - decelGap + POSITION_EPS)
832  ) {
833 
834  // XXX: Alternative formulation (encapsulating differences of euler and ballistic) TODO: test, refs. #2575
835  // double eventualGap = myCarFollowModel.gapExtrapolation(remainingSeconds - 1., decelGap, plannedSpeed, neighNewSpeed1s);
836  // } else if (eventualGap > secureGap + POSITION_EPS) {
837 
838 
839  // NOTE: This case corresponds to the situation, where some time is left to perform the lc
840  // For the ballistic case this is interpreted as follows:
841  // If the follower breaks with helpDecel for one second, this vehicle maintains the plannedSpeed,
842  // and both continue with their speeds for remainingSeconds seconds the gap will suffice for a laneChange
843  // For the euler case we had the following comment:
844  // 'decelerating once is sufficient to open up a large enough gap in time', but:
845  // XXX: 1) Decelerating *once* does not necessarily lead to the gap decelGap! (if TS<1s.) (Leo)
846  // 2) Probably, the if() for euler should test for dv * (remainingSeconds-1) > ..., too ?!, refs. #2578
847  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
848 #ifdef DEBUG_INFORMER
849  if (DEBUG_COND) {
850  std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
851  }
852 #endif
853  } else if (dir == LCA_MRIGHT && !myAllowOvertakingRight && !nv->congested()) {
854  // XXX: check if this requires a special treatment for the ballistic update, refs. #2575
855  const double vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
856  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
857 #ifdef DEBUG_INFORMER
858  if (DEBUG_COND) {
859  std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
860  }
861 #endif
862  } else {
863  double vhelp = MAX2(nv->getSpeed(), myVehicle.getSpeed() + HELP_OVERTAKE);
864  //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE &&
865  // nv->getSpeed() > myVehicle.getSpeed()) {
866  if (nv->getSpeed() > myVehicle.getSpeed() &&
867  ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) // NOTE: it might be considered to use myVehicle.getAccumulatedWaitingSeconds() > LCA_RIGHT_IMPATIENCE instead (Leo). Refs. #2578
868  || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
869  // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
871  )) {
872  // let the follower slow down to increase the likelihood that later vehicles will be slow enough to help
873  // follower should still be fast enough to open a gap
874  // XXX: The probability for that success would be larger if the slow down of the appropriate following vehicle
875  // would take place without the immediate follower slowing down. We might consider to model reactions of
876  // vehicles that are not immediate followers. (Leo) -> see ticket #2532
877  vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
878 #ifdef DEBUG_INFORMER
879  if (DEBUG_COND) {
880  // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! (Leo)
881  // Further, vhelp might be larger than nv->getSpeed(), so the request issued below is not to slow down!? (see below) Refs. #2578
882  std::cout << " wants right follower to slow down a bit\n";
883  }
884 #endif
886  // euler
887  if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
888 
889 #ifdef DEBUG_INFORMER
890  if (DEBUG_COND) {
891  // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! Refs. #2578
892  std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
893  }
894 #endif
895  // XXX: I don't understand. This vhelp might be larger than nv->getSpeed() but the above condition seems to rely
896  // on the reasoning that if nv breaks with helpDecel for remaining Seconds, nv will be so slow, that this
897  // vehicle will be able to cut in. But nv might have overtaken this vehicle already (or am I missing sth?). (Leo)
898  // Ad: To my impression, the intention behind allowing larger speeds for the blocking follower is to prevent a
899  // situation, where an overlapping follower keeps blocking the ego vehicle. Refs. #2578
900  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
901  return;
902  }
903  } else {
904 
905  // 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)
906  // estimate gap after remainingSeconds.
907  // Assumptions:
908  // (A1) leader continues with currentSpeed. (XXX: That might be wrong: Think of accelerating on an on-ramp or of a congested region ahead!)
909  // (A2) follower breaks with helpDecel.
910  const double gapAfterRemainingSecs = myCarFollowModel.gapExtrapolation(
911  remainingSeconds, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(), 0, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
912  const double secureGapAfterRemainingSecs = nv->getCarFollowModel().getSecureGap(
913  MAX2(nv->getSpeed() - remainingSeconds * helpDecel, 0.), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
914  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
915 #ifdef DEBUG_INFORMER
916  if (DEBUG_COND) {
917  std::cout << " wants to cut in before follower nv=" << nv->getID() << " (eventually)\n";
918  }
919 #endif
920  // NOTE: ballistic uses neighNewSpeed instead of vhelp, see my note above. (Leo)
921  // TODO: recheck if this might cause suboptimal behaviour in some LC-situations. Refs. #2578
922  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
923  return;
924  }
925  }
926 
927 
928  }
929 
930 #ifdef DEBUG_INFORMER
931  if (DEBUG_COND) {
932  std::cout << SIMTIME
933  << " veh=" << myVehicle.getID()
934  << " informs follower " << nv->getID()
935  << " vhelp=" << vhelp
936  << "\n";
937  }
938 #endif
939 
940  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
941  // This follower is supposed to overtake us. Slow down smoothly to allow this.
942  const double overtakeDist = overtakeDistance(nv, &myVehicle, neighFollow.second, vhelp, plannedSpeed);
943  // speed difference to create a sufficiently large gap
944  const double needDV = overtakeDist / remainingSeconds;
945  // 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
947 
948 #ifdef DEBUG_INFORMER
949  if (DEBUG_COND) {
950  std::cout << SIMTIME
951  << " veh=" << myVehicle.getID()
952  << " wants to be overtaken by=" << nv->getID()
953  << " overtakeDist=" << overtakeDist
954  << " vneigh=" << nv->getSpeed()
955  << " vhelp=" << vhelp
956  << " needDV=" << needDV
957  << " vsafe=" << myLCAccelerationAdvices.back()
958  << "\n";
959  }
960 #endif
961  }
962  } else if (neighFollow.first != 0 && (blocked & LCA_BLOCKED_BY_LEADER)) {
963  // we are not blocked by the follower now, make sure it remains that way
964  // XXX: Does the below code for the euler case really assure that? Refs. #2578
965  double vsafe, vsafe1;
967  // euler
968  MSVehicle* nv = neighFollow.first;
969  vsafe1 = nv->getCarFollowModel().followSpeed(
970  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
971  vsafe = nv->getCarFollowModel().followSpeed(
972  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
973  // NOTE: since vsafe1 > nv->getSpeed() is possible, we don't have vsafe1 < vsafe < nv->getSpeed here (similar pattern above works differently)
974 
975  } else {
976  // ballistic
977  // XXX This should actually do for euler and ballistic cases (TODO: test!) Refs. #2575
978 
979  double anticipationTime = 1.;
980  double anticipatedSpeed = MIN2(myVehicle.getSpeed() + plannedAccel * anticipationTime, myVehicle.getMaxSpeedOnLane());
981  double anticipatedGap = myCarFollowModel.gapExtrapolation(anticipationTime, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(),
982  plannedAccel, 0, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
983  double secureGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), anticipatedSpeed, myCarFollowModel.getMaxDecel());
984 
985  // propose follower speed corresponding to first estimation of gap
986  double vsafe = nv->getCarFollowModel().followSpeed(
987  nv, nv->getSpeed(), anticipatedGap, plannedSpeed, myCarFollowModel.getMaxDecel());
988  double helpAccel = SPEED2ACCEL(vsafe - nv->getSpeed()) / anticipationTime;
989 
990  if (anticipatedGap > secureGap) {
991  // follower may accelerate, implying vhelp >= vsafe >= nv->getSpeed()
992  // calculate gap for the assumed acceleration
993  anticipatedGap = myCarFollowModel.gapExtrapolation(anticipationTime, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(),
994  plannedAccel, helpAccel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
995  double anticipatedHelpSpeed = MIN2(nv->getSpeed() + anticipationTime * helpAccel, nv->getMaxSpeedOnLane());
996  secureGap = nv->getCarFollowModel().getSecureGap(anticipatedHelpSpeed, anticipatedSpeed, myCarFollowModel.getMaxDecel());
997  if (anticipatedGap < secureGap) {
998  // don't accelerate
999  vsafe = nv->getSpeed();
1000  }
1001  } else {
1002  // follower is too fast, implying that vhelp <= vsafe <= nv->getSpeed()
1003  // we use the above vhelp
1004  }
1005  }
1006  msgPass.informNeighFollower(new Info(vsafe, dir), &myVehicle);
1007 
1008 #ifdef DEBUG_INFORMER
1009  if (DEBUG_COND) {
1010  std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
1011  }
1012 #endif
1013  }
1014 }
1015 
1016 
1017 void
1020  // keep information about strategic change direction
1023  myLeftSpace = 0;
1024  myLCAccelerationAdvices.clear();
1025  myDontBrake = false;
1026  // truncate to work around numerical instability between different builds
1027  mySpeedGainProbability = ceil(mySpeedGainProbability * 100000.0) * 0.00001;
1028  myKeepRightProbability = ceil(myKeepRightProbability * 100000.0) * 0.00001;
1029 }
1030 
1031 
1032 void
1034  myOwnState = 0;
1037  if (myVehicle.getBestLaneOffset() == 0) {
1038  // if we are not yet on our best lane there might still be unseen blockers
1039  // (during patchSpeed)
1041  myLeftSpace = 0;
1042  }
1044  myLCAccelerationAdvices.clear();
1045  myDontBrake = false;
1046 }
1047 
1048 
1049 int
1051  int laneOffset,
1053  int blocked,
1054  const std::pair<MSVehicle*, double>& leader,
1055  const std::pair<MSVehicle*, double>& neighLead,
1056  const std::pair<MSVehicle*, double>& neighFollow,
1057  const MSLane& neighLane,
1058  const std::vector<MSVehicle::LaneQ>& preb,
1059  MSVehicle** lastBlocked,
1060  MSVehicle** firstBlocked) {
1061  assert(laneOffset == 1 || laneOffset == -1);
1062  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
1063  // compute bestLaneOffset
1064  MSVehicle::LaneQ curr, neigh, best;
1065  int bestLaneOffset = 0;
1066  // What do these "dists" mean? Please comment. (Leo) Ad: I now think the following:
1067  // currentDist is the distance that the vehicle can go on its route without having to
1068  // change lanes from the current lane. neighDist as currentDist for the considered target lane (i.e., neigh)
1069  // If this is true I suggest to put this into the docu of wantsChange()
1070  double currentDist = 0;
1071  double neighDist = 0;
1072  int currIdx = 0;
1073  MSLane* prebLane = myVehicle.getLane();
1074  if (prebLane->getEdge().isInternal()) {
1075  // internal edges are not kept inside the bestLanes structure
1076  prebLane = prebLane->getLinkCont()[0]->getLane();
1077  }
1078  // XXX: What does the following code do? Please comment. (Leo) Refs. #2578
1079  const bool checkOpposite = &neighLane.getEdge() != &myVehicle.getLane()->getEdge();
1080  const int prebOffset = (checkOpposite ? 0 : laneOffset);
1081  for (int p = 0; p < (int) preb.size(); ++p) {
1082  if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1083  assert(p + prebOffset < (int)preb.size());
1084  curr = preb[p];
1085  neigh = preb[p + prebOffset];
1086  currentDist = curr.length;
1087  neighDist = neigh.length;
1088  bestLaneOffset = curr.bestLaneOffset;
1089  if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0) {
1090 #ifdef DEBUG_WANTS_CHANGE
1091  if (DEBUG_COND) {
1092  std::cout << STEPS2TIME(currentTime)
1093  << " veh=" << myVehicle.getID()
1094  << " bestLaneOffsetOld=" << bestLaneOffset
1095  << " bestLaneOffsetNew=" << laneOffset
1096  << "\n";
1097  }
1098 #endif
1099  bestLaneOffset = prebOffset;
1100  }
1101  best = preb[p + bestLaneOffset];
1102  currIdx = p;
1103  break;
1104  }
1105  }
1106  // direction specific constants
1107  const bool right = (laneOffset == -1);
1108  if (isOpposite() && right) {
1109  neigh = preb[preb.size() - 1];
1110  curr = neigh;
1111  best = neigh;
1112  bestLaneOffset = -1;
1113  curr.bestLaneOffset = -1;
1114  neighDist = neigh.length;
1115  currentDist = curr.length;
1116  }
1118  const int lca = (right ? LCA_RIGHT : LCA_LEFT);
1119  const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
1120  const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
1121  const bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1122  // keep information about being a leader/follower
1123  int ret = (myOwnState & 0xffff0000);
1124  int req = 0; // the request to change or stay
1125 
1126  ret = slowDownForBlocked(lastBlocked, ret);
1127  if (lastBlocked != firstBlocked) {
1128  ret = slowDownForBlocked(firstBlocked, ret);
1129  }
1130 
1131 #ifdef DEBUG_WANTS_CHANGE
1132  if (DEBUG_COND) {
1133  std::cout << SIMTIME
1134  << " veh=" << myVehicle.getID()
1135  << " _wantsChange state=" << myOwnState
1136  << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
1137  << " firstBlocked=" << Named::getIDSecure(*firstBlocked)
1138  << " lastBlocked=" << Named::getIDSecure(*lastBlocked)
1139  << " leader=" << Named::getIDSecure(leader.first)
1140  << " leaderGap=" << leader.second
1141  << " neighLead=" << Named::getIDSecure(neighLead.first)
1142  << " neighLeadGap=" << neighLead.second
1143  << " neighFollow=" << Named::getIDSecure(neighFollow.first)
1144  << " neighFollowGap=" << neighFollow.second
1145  << "\n";
1146  }
1147 #endif
1148 
1149  // we try to estimate the distance which is necessary to get on a lane
1150  // we have to get on in order to keep our route
1151  // we assume we need something that depends on our velocity
1152  // and compare this with the free space on our wished lane
1153  //
1154  // if the free space is somehow(<-?) less than the space we need, we should
1155  // definitely try to get to the desired lane
1156  //
1157  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
1158 
1159 
1160  // we do not want the lookahead distance to change all the time so we let it decay slowly
1161  // (in contrast, growth is applied instantaneously)
1164  } else {
1165  // memory decay factor for this action step
1166  const double memoryFactor = 1. - (1. - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getActionStepLengthSecs();
1167  assert(memoryFactor > 0.);
1169  (memoryFactor * myLookAheadSpeed + (1 - memoryFactor) * myVehicle.getSpeed()));
1170  }
1171  double laDist = myLookAheadSpeed * LOOK_FORWARD * myStrategicParam * (right ? 1 : myLookaheadLeft);
1172  laDist += myVehicle.getVehicleType().getLengthWithGap() * (double) 2.;
1173 
1174 
1175  if (bestLaneOffset == 0 && leader.first != 0 && leader.first->isStopped()) {
1176  // react to a stopped leader on the current lane
1177  // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1178  // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1179  laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1180  + leader.first->getVehicleType().getLengthWithGap());
1181  } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && neighLead.first->isStopped()) {
1182  // react to a stopped leader on the target lane (if it is the bestLane)
1184  + neighLead.first->getVehicleType().getLengthWithGap();
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 double remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1392  // MAX2((double)STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / abs(bestLaneOffset) / URGENCY) :
1393  MAX2((double)STEPS2TIME(TS), myLeftSpace / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / abs(bestLaneOffset) / URGENCY) :
1395  const double plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1396  // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1397  // while informLeader returns -1 in that case. Refs. #2577
1398  if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1399  // maybe we need to deal with a blocking follower
1400  informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1401  }
1402 
1403 #ifdef DEBUG_WANTS_CHANGE
1404  if (DEBUG_COND) {
1405  std::cout << STEPS2TIME(currentTime)
1406  << " veh=" << myVehicle.getID()
1407  << " myLeftSpace=" << myLeftSpace
1408  << " remainingSeconds=" << remainingSeconds
1409  << " plannedSpeed=" << plannedSpeed
1410  << "\n";
1411  }
1412 #endif
1413 
1414  return ret;
1415  }
1416  // a high inconvenience prevents cooperative changes.
1417  const double inconvenience = MIN2((double)1.0, (laneOffset < 0
1420  const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1421  const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1422 
1423  // VARIANT_15
1424  if (roundaboutEdgesAhead > 1) {
1425 
1426 #ifdef DEBUG_WANTS_CHANGE
1427  if (DEBUG_COND) {
1428  std::cout << STEPS2TIME(currentTime)
1429  << " veh=" << myVehicle.getID()
1430  << " roundaboutEdgesAhead=" << roundaboutEdgesAhead
1431  << " myLeftSpace=" << myLeftSpace
1432  << "\n";
1433  }
1434 #endif
1435  // try to use the inner lanes of a roundabout to increase throughput
1436  // unless we are approaching the exit
1437  if (lca == LCA_LEFT) {
1438  // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1439  // TODO: test this for euler update! Refs. #2575
1440  if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1441 // if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1442  req = ret | lca | LCA_COOPERATIVE;
1443  }
1444  } else {
1445  // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1446  if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1447 // if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1448  req = ret | LCA_STAY | LCA_COOPERATIVE;
1449  }
1450  }
1451  if (!cancelRequest(req, laneOffset)) {
1452  return ret | req;
1453  }
1454  }
1455 
1456  // let's also regard the case where the vehicle is driving on a highway...
1457  // in this case, we do not want to get to the dead-end of an on-ramp
1458  if (right) {
1459  if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1460 #ifdef DEBUG_WANTS_CHANGE
1461  if (DEBUG_COND) {
1462  std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1463  }
1464 #endif
1465  req = ret | LCA_STAY | LCA_STRATEGIC;
1466  if (!cancelRequest(req, laneOffset)) {
1467  return ret | req;
1468  }
1469  }
1470  }
1471  // --------
1472 
1473  // -------- make place on current lane if blocking follower
1474  //if (amBlockingFollowerPlusNB()) {
1475  // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1476  // << " neighDist=" << neighDist
1477  // << " currentDist=" << currentDist
1478  // << "\n";
1479  //}
1480 
1482  && (!speedGainInconvenient)
1483  //&& ((myOwnState & myLca) != 0) // VARIANT_6 : counterNoHelp
1484  && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1485 
1486  // VARIANT_2 (nbWhenChangingToHelp)
1487 #ifdef DEBUG_COOPERATE
1488  if (DEBUG_COND) {
1489  std::cout << STEPS2TIME(currentTime)
1490  << " veh=" << myVehicle.getID()
1491  << " wantsChangeToHelp=" << (right ? "right" : "left")
1492  << " state=" << myOwnState
1493  << (((myOwnState & myLca) == 0) ? " (counter)" : "")
1494  << "\n";
1495  }
1496 #endif
1497  req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1498  if (!cancelRequest(req, laneOffset)) {
1499  return ret | req;
1500  }
1501  }
1502 
1503  // --------
1504 
1505 
1508  //if ((blocked & LCA_BLOCKED) != 0) {
1509  // return ret;
1510  //}
1512 
1513  // -------- higher speed
1514  //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1515  // return ret;
1516  //}
1517 
1518  double neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
1519 
1520  // we wish to anticipate future speeds. This is difficult when the leading
1521  // vehicles are still accelerating so we resort to comparing next speeds in this case
1522  const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1523  || (leader.first != 0 && leader.first->getAcceleration() > 0);
1524 
1525  if (acceleratingLeader) {
1526  // followSpeed allows acceleration for 1 step, to always compare speeds
1527  // after 1 second of acceleration we have call the function with a correct speed value
1528  // TODO: This should be explained better. Refs #2
1529  const double correctedSpeed = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1531 
1532  if (neighLead.first == 0) {
1533  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, correctedSpeed, neighDist, 0, 0));
1534  } else {
1535  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(
1536  &myVehicle, correctedSpeed, neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
1537  }
1538  if (leader.first == 0) {
1539  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, correctedSpeed, currentDist, 0, 0));
1540  } else {
1541  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(
1542  &myVehicle, correctedSpeed, leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
1543  }
1544  } else {
1545  if (neighLead.first == 0) {
1546  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.maximumSafeStopSpeed(neighDist, myVehicle.getSpeed(), true));
1547  } else {
1548  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.maximumSafeFollowSpeed(neighLead.second, myVehicle.getSpeed(),
1549  neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel(), true));
1550  }
1551  if (leader.first == 0) {
1552  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.maximumSafeStopSpeed(currentDist, myVehicle.getSpeed(), true));
1553  } else {
1554  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.maximumSafeFollowSpeed(leader.second, myVehicle.getSpeed(),
1555  leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel(), true));
1556  }
1557  }
1558 
1559  if (neighLane.getEdge().getPersons().size() > 0) {
1560  // react to pedestrians
1561  adaptSpeedToPedestrians(myVehicle.getLane(), thisLaneVSafe);
1562  adaptSpeedToPedestrians(&neighLane, neighLaneVSafe);
1563  }
1564 
1565  const double relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1567 
1568 #ifdef DEBUG_WANTS_CHANGE
1569  if (DEBUG_COND) {
1570  std::cout << STEPS2TIME(currentTime)
1571  << " veh=" << myVehicle.getID()
1572  << " currentDist=" << currentDist
1573  << " neighDist=" << neighDist
1574  << " thisVSafe=" << thisLaneVSafe
1575  << " neighVSafe=" << neighLaneVSafe
1576  << " relGain=" << toString(relativeGain, 8)
1577  << "\n";
1578  }
1579 #endif
1580 
1581  if (right) {
1582  // ONLY FOR CHANGING TO THE RIGHT
1583  if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1584  // ok, the current lane is faster than the right one...
1585  if (mySpeedGainProbability < 0) {
1587  //myKeepRightProbability /= 2.0;
1588  }
1589  } else {
1590  // ok, the current lane is not (much) faster than the right one
1591  // @todo recheck the 5 km/h discount on thisLaneVSafe, refs. #2068
1592 
1593  // do not promote changing to the left just because changing to the right is bad
1594  // XXX: The following code may promote it, though!? (recheck!)
1595  // (Think of small negative mySpeedGainProbability and larger negative relativeGain)
1596  // One might think of replacing '||' by '&&' to exclude that possibility...
1597  // Still, for negative relativeGain, we might want to decrease the inclination for
1598  // changing to the left. Another solution could be the seperation of mySpeedGainProbability into
1599  // two variables (one for left and one for right). Refs #2578
1600  if (mySpeedGainProbability < 0 || relativeGain > 0) {
1602  }
1603 
1604  // honor the obligation to keep right (Rechtsfahrgebot)
1605  // XXX consider fast approaching followers on the current lane. Refs #2578
1606  //const double vMax = myLookAheadSpeed;
1607  const double acceptanceTime = KEEP_RIGHT_ACCEPTANCE * vMax * MAX2((double)1, myVehicle.getSpeed()) / myVehicle.getLane()->getSpeedLimit();
1608  double fullSpeedGap = MAX2(0., neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1609  double fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1610  if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1611  fullSpeedGap = MAX2(0., MIN2(fullSpeedGap,
1612  neighLead.second - myVehicle.getCarFollowModel().getSecureGap(
1613  vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1614  fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1615  }
1616  // stay on the current lane if we cannot overtake a slow leader on the right
1617  if (checkOverTakeRight && leader.first != 0
1618  && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1619  fullSpeedGap = MIN2(fullSpeedGap, leader.second);
1620  fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1621  const double relativeGain = (vMax - leader.first->getLane()->getVehicleMaxSpeed(leader.first)) / MAX2(vMax,
1623  // tiebraker to avoid buridans paradox see #1312
1625  }
1626 
1627  const double deltaProb = (myChangeProbThresholdRight * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1629 
1630 #ifdef DEBUG_WANTS_CHANGE
1631  if (DEBUG_COND) {
1632  std::cout << STEPS2TIME(currentTime)
1633  << " veh=" << myVehicle.getID()
1634  << " vMax=" << vMax
1635  << " neighDist=" << neighDist
1636  << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1637  << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1638  << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(
1639  myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1640  << " acceptanceTime=" << acceptanceTime
1641  << " fullSpeedGap=" << fullSpeedGap
1642  << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1643  << " dProb=" << deltaProb
1644  << " myKeepRightProbability=" << myKeepRightProbability
1645  << "\n";
1646  }
1647 #endif
1649  req = ret | lca | LCA_KEEPRIGHT;
1650  if (!cancelRequest(req, laneOffset)) {
1651  return ret | req;
1652  }
1653  }
1654  }
1655 
1656 #ifdef DEBUG_WANTS_CHANGE
1657  if (DEBUG_COND) {
1658  std::cout << STEPS2TIME(currentTime)
1659  << " veh=" << myVehicle.getID()
1660  << " speed=" << myVehicle.getSpeed()
1661  << " mySpeedGainProbability=" << mySpeedGainProbability
1662  << " thisLaneVSafe=" << thisLaneVSafe
1663  << " neighLaneVSafe=" << neighLaneVSafe
1664  << " relativeGain=" << relativeGain
1665  << " blocked=" << blocked
1666  << "\n";
1667  }
1668 #endif
1669 
1671  && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((double) .1, myVehicle.getSpeed())) { // -.1
1672  req = ret | lca | LCA_SPEEDGAIN;
1673  if (!cancelRequest(req, laneOffset)) {
1674  return ret | req;
1675  }
1676  }
1677  } else {
1678  // ONLY FOR CHANGING TO THE LEFT
1679  if (thisLaneVSafe > neighLaneVSafe) {
1680  // this lane is better
1681  if (mySpeedGainProbability > 0) {
1683  }
1684  } else if (thisLaneVSafe == neighLaneVSafe) {
1685  if (mySpeedGainProbability > 0) {
1687  }
1688  } else {
1689  // left lane is better
1691  }
1692  // VARIANT_19 (stayRight)
1693  //if (neighFollow.first != 0) {
1694  // MSVehicle* nv = neighFollow.first;
1695  // const double secGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1696  // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1697  // // do not change left if it would inconvenience faster followers
1698  // return ret | LCA_STAY | LCA_SPEEDGAIN;
1699  // }
1700  //}
1701 
1702 #ifdef DEBUG_WANTS_CHANGE
1703  if (DEBUG_COND) {
1704  std::cout << STEPS2TIME(currentTime)
1705  << " veh=" << myVehicle.getID()
1706  << " speed=" << myVehicle.getSpeed()
1707  << " mySpeedGainProbability=" << mySpeedGainProbability
1708  << " thisLaneVSafe=" << thisLaneVSafe
1709  << " neighLaneVSafe=" << neighLaneVSafe
1710  << " relativeGain=" << relativeGain
1711  << " blocked=" << blocked
1712  << "\n";
1713  }
1714 #endif
1715 
1717  && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1718  && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { // .1
1719  req = ret | lca | LCA_SPEEDGAIN;
1720  if (!cancelRequest(req, laneOffset)) {
1721  return ret | req;
1722  }
1723  }
1724  }
1725  // --------
1726  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1727  && relativeGain >= 0
1728  && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) {
1729  // change towards the correct lane, speedwise it does not hurt
1730  req = ret | lca | LCA_STRATEGIC;
1731  if (!cancelRequest(req, laneOffset)) {
1732  return ret | req;
1733  }
1734  }
1735 #ifdef DEBUG_WANTS_CHANGE
1736  if (DEBUG_COND) {
1737  std::cout << STEPS2TIME(currentTime)
1738  << " veh=" << myVehicle.getID()
1739  << " mySpeedGainProbability=" << mySpeedGainProbability
1740  << " myKeepRightProbability=" << myKeepRightProbability
1741  << " thisLaneVSafe=" << thisLaneVSafe
1742  << " neighLaneVSafe=" << neighLaneVSafe
1743  << "\n";
1744  }
1745 #endif
1746 
1747  return ret;
1748 }
1749 
1750 
1751 void
1753  double& roundaboutDistanceAhead, double& roundaboutDistanceAheadNeigh, int& roundaboutEdgesAhead, int& roundaboutEdgesAheadNeigh) {
1754 
1755  const MSVehicle& veh = lcm->myVehicle;
1756 
1757  // In what follows, we check whether a roundabout is ahead (or the vehicle is on a roundabout)
1758  // We calculate the lengths of the continuations described by curr and neigh,
1759  // which are part of the roundabout. Currently only takes effect for ballistic update, refs #1807, #2576 (Leo)
1760  double pos = lcm->isOpposite() ? veh.getLane()->getLength() - veh.getPositionOnLane() : veh.getPositionOnLane();
1761  roundaboutDistanceAhead = distanceAlongNextRoundabout(pos, veh.getLane(), curr.bestContinuations);
1762 
1763  // For the distance on the neigh.lane, we need to do a little hack since we may not
1764  // have access to the right initial lane (neigh.lane is only the first non-null lane of neigh.bestContinuations).
1765  roundaboutDistanceAheadNeigh = 0;
1766  double neighPosition = pos;
1767  if (veh.getLane()->getEdge().isInternal()) {
1768  // take care of the distance on internal lanes
1769  neighPosition = 0.;
1770  if (veh.getLane()->getEdge().isRoundabout()) {
1771  // vehicle is on internal roundabout lane -> neigh.lane is not a parallel internal lane, but the next non-internal lane
1772  // add remaining length on current, internal lane to roundabout distance on neigh continuation
1773  roundaboutDistanceAheadNeigh = veh.getLane()->getLength() - veh.getPositionOnLane();
1774  MSLane* nextLane = 0;
1775  for (std::vector<MSLane*>::const_iterator i = curr.bestContinuations.begin(); i != curr.bestContinuations.end(); i++) {
1776  if (*i != 0 && *i != veh.getLane()) {
1777  nextLane = *i;
1778  break;
1779  }
1780  }
1781  assert(nextLane != 0);
1782  // add all lengths remaining internal lanes of current continuations until nextLane
1783  const MSLink* link = MSLinkContHelper::getConnectingLink(*veh.getLane(), *nextLane);
1784  roundaboutDistanceAheadNeigh += link->getInternalLengthsAfter();
1785  }
1786  }
1787  // add roundabout distance from neigh.lane on
1788  roundaboutDistanceAheadNeigh += distanceAlongNextRoundabout(neighPosition, neigh.lane, neigh.bestContinuations);
1789 
1790 #ifdef DEBUG_WANTS_CHANGE
1791  if (lcm->debugVehicle()) {
1792  std::cout << "roundaboutDistanceAhead = " << roundaboutDistanceAhead
1793  << " roundaboutDistanceAheadNeigh = " << roundaboutDistanceAheadNeigh
1794  << "\n";
1795  }
1796 #endif
1797 
1798  // count the number of roundabout edges ahead to determine whether
1799  // special LC behavior is required (promoting the use of the inner lane, mainly)
1800  roundaboutEdgesAhead = 0;
1801  for (std::vector<MSLane*>::const_iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) {
1802  const MSLane* lane = *it;
1803  if (lane != 0 && lane->getEdge().isRoundabout()) {
1804  roundaboutEdgesAhead += 1;
1805  } else if (roundaboutEdgesAhead > 0) {
1806  // only check the next roundabout
1807  break;
1808  }
1809  }
1810  roundaboutEdgesAheadNeigh = 0;
1811  for (std::vector<MSLane*>::const_iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) {
1812  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
1813  roundaboutEdgesAheadNeigh += 1;
1814  } else if (roundaboutEdgesAheadNeigh > 0) {
1815  // only check the next roundabout
1816  break;
1817  }
1818  }
1819  return;
1820 }
1821 
1822 
1823 double
1824 MSLCM_LC2013::roundaboutDistBonus(double roundaboutDistAhead, int roundaboutEdgesAhead) const {
1825  // NOTE: Currently there are two variants, one taking into account only the number
1826  // of upcoming non-internal roundabout edges and adding ROUNDABOUT_DIST_BONUS per upcoming edge except the first.
1827  // Another variant uses the actual distance and multiplies it by a factor ROUNDABOUT_DIST_FACTOR.
1828  // Currently, the update rule decides which variant to take (because the second was experimentally implemented
1829  // in the ballistic branch (ticket860)). Both variants may be combined in future. Refs. #2576
1831  if (roundaboutEdgesAhead > 1) {
1832  // Here we add a bonus length for each upcoming roundabout edge to the distance.
1833  // XXX: That becomes problematic, if the vehicle enters the last round about edge,
1834  // realizes suddenly that the change is very urgent and finds itself with very
1835  // few space to complete the urgent strategic change frequently leading to
1836  // a hang up on the inner lane.
1837  return roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS * myCooperativeParam;
1838  } else {
1839  return 0.;
1840  }
1841  } else {
1842  // This weighs the roundabout edges' distance with a larger factor
1843  if (roundaboutDistAhead > ROUNDABOUT_DIST_TRESH) {
1844  return (roundaboutDistAhead - ROUNDABOUT_DIST_TRESH) * (ROUNDABOUT_DIST_FACTOR - 1.);
1845  } else {
1846  return 0.;
1847  }
1848  }
1849 }
1850 
1851 
1852 double
1853 MSLCM_LC2013::distanceAlongNextRoundabout(double position, const MSLane* initialLane, const std::vector<MSLane*>& continuationLanes) {
1854  for (std::vector<MSLane*>::const_iterator i = continuationLanes.begin(); i != continuationLanes.end(); i++) {
1855  assert((*i) == 0 || !(*i)->getEdge().isInternal());
1856  }
1857 
1858  // We start with the current edge.
1859  bool encounteredRoundabout = false;
1860  double roundaboutDistanceAhead = 0.;
1861 
1862  // set an iterator to the first non-zero entry of continuationLanes
1863  std::vector<MSLane*>::const_iterator j = continuationLanes.begin();
1864  while (j != continuationLanes.end() && *j == 0) {
1865  ++j;
1866  }
1867 
1868  // differentiate possible situations
1869  if (j == continuationLanes.end()) {
1870  // continuations end here
1871  assert(initialLane == 0);
1872  return 0.;
1873  } else if (initialLane == 0) {
1874  // NOTE: this may occur when calling distanceAlongNextRoundabout() with neigh.lane in _wantsChange().
1875  // In that case, the possible internal lengths have been taken into account in _wantsChange().
1876  // Thus we set initialLane to the first non-zero lane in continuationLanes
1877  initialLane = *j;
1878  } else if (!initialLane->isInternal() && initialLane != *j) {
1879  // this may occur during opposite direction driving where the initial Lane
1880  // is the reverse lane of *j. This should not happen on a roundabout! Therefore we can skip initialLane.
1881  assert(!initialLane->getEdge().isRoundabout());
1882  initialLane = *j;
1883  } else if (initialLane->getEdge().isRoundabout()) {
1884  // initial lane is on roundabout
1885  assert(position >= 0. && position <= initialLane->getLength());
1886  if (!initialLane->isInternal()) {
1887  assert(initialLane == *j);
1888  roundaboutDistanceAhead += initialLane->getLength() - position;
1889  if (j + 1 == continuationLanes.end() || *(j + 1) == 0 || !(*(j + 1))->getEdge().isRoundabout()) {
1890  // following connection is not part of the roundabout
1891  } else {
1892  // add internal lengths
1893  const MSLane* nextLane = *(j + 1);
1894  const MSLink* link = MSLinkContHelper::getConnectingLink(*initialLane, *nextLane);
1895  assert(link != 0);
1896  roundaboutDistanceAhead += link->getInternalLengthsAfter();
1897  }
1898  j++;
1899  } else {
1900  // initialLane is an internal roundabout lane -> add length to roundaboutDistanceAhead
1901  roundaboutDistanceAhead += initialLane->getLength() - position;
1902  assert(initialLane->getLinkCont().size() == 1);
1903  roundaboutDistanceAhead += initialLane->getLinkCont()[0]->getInternalLengthsAfter();
1904  }
1905  }
1906 
1907  // treat lanes beyond the initial one
1908  for (std::vector<MSLane*>::const_iterator it = j; it != continuationLanes.end(); ++it) {
1909  const MSLane* lane = *it;
1910  assert(lane != 0); // possible leading NULL lanes in continuationLanes were treated above
1911  if (lane->getEdge().isRoundabout()) {
1912  encounteredRoundabout = true;
1913  // add roundabout lane length
1914  roundaboutDistanceAhead += lane->getLength();
1915 
1916  // since bestContinuations contains no internal edges
1917  // add consecutive connection lengths if it is part of the route and the
1918  // consecutive edge is on the roundabout as well
1919  if (it + 1 != continuationLanes.end() && *(it + 1) != 0 && (*(it + 1))->getEdge().isRoundabout()) {
1920  // find corresponding link for the current lane
1921  const MSLink* link = MSLinkContHelper::getConnectingLink(*lane, **(it + 1));
1922  assert(link != 0);
1923  double linkLength = link->getInternalLengthsAfter();
1924  roundaboutDistanceAhead += linkLength;
1925  }
1926  } else if (encounteredRoundabout) {
1927  // only check the next roundabout
1928  break;
1929  }
1930  }
1931  return roundaboutDistanceAhead;
1932 }
1933 
1934 
1935 
1936 int
1938  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1939  if ((*blocked) != 0) {
1940  double gap = (*blocked)->getPositionOnLane() - (*blocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1941 #ifdef DEBUG_SLOW_DOWN
1942  if (DEBUG_COND) {
1943  std::cout << SIMTIME
1944  << " veh=" << myVehicle.getID()
1945  << " blocked=" << Named::getIDSecure(*blocked)
1946  << " gap=" << gap
1947  << "\n";
1948  }
1949 #endif
1950  if (gap > POSITION_EPS) {
1951  //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1952  // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1953 
1955  //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1956  ) {
1957  if ((*blocked)->getSpeed() < SUMO_const_haltingSpeed) {
1958  state |= LCA_AMBACKBLOCKER_STANDING;
1959  } else {
1960  state |= LCA_AMBACKBLOCKER;
1961  }
1964  (double)(gap - POSITION_EPS), (*blocked)->getSpeed(),
1965  (*blocked)->getCarFollowModel().getMaxDecel()));
1966 
1967  //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1968 #ifdef DEBUG_SLOW_DOWN
1969  if (DEBUG_COND) {
1970  std::cout << SIMTIME
1971  << " veh=" << myVehicle.getID()
1972  << " slowing down for"
1973  << " blocked=" << Named::getIDSecure(*blocked)
1974  << " helpSpeed=" << myLCAccelerationAdvices.back()
1975  << "\n";
1976  }
1977 #endif
1978  } /* else {
1979  // experimental else-branch...
1980  state |= LCA_AMBACKBLOCKER;
1981  myVSafes.push_back(myCarFollowModel.followSpeed(
1982  &myVehicle, myVehicle.getSpeed(),
1983  (double)(gap - POSITION_EPS), (*blocked)->getSpeed(),
1984  (*blocked)->getCarFollowModel().getMaxDecel()));
1985  }*/
1986  }
1987  }
1988  return state;
1989 }
1990 
1991 
1992 void
1993 MSLCM_LC2013::saveBlockerLength(MSVehicle* blocker, int lcaCounter) {
1994 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
1995  if (DEBUG_COND) {
1996  std::cout << SIMTIME
1997  << " veh=" << myVehicle.getID()
1998  << " saveBlockerLength blocker=" << Named::getIDSecure(blocker)
1999  << " bState=" << (blocker == 0 ? "None" : toString(blocker->getLaneChangeModel().getOwnState()))
2000  << "\n";
2001  }
2002 #endif
2003  if (blocker != 0 && (blocker->getLaneChangeModel().getOwnState() & lcaCounter) != 0) {
2004  // is there enough space in front of us for the blocker?
2005  const double potential = myLeftSpace - myVehicle.getCarFollowModel().brakeGap(
2007  if (blocker->getVehicleType().getLengthWithGap() <= potential) {
2008  // save at least his length in myLeadingBlockerLength
2010 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
2011  if (DEBUG_COND) {
2012  std::cout << SIMTIME
2013  << " veh=" << myVehicle.getID()
2014  << " blocker=" << Named::getIDSecure(blocker)
2015  << " saving myLeadingBlockerLength=" << myLeadingBlockerLength
2016  << "\n";
2017  }
2018 #endif
2019  } else {
2020  // we cannot save enough space for the blocker. It needs to save
2021  // space for ego instead
2022 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
2023  if (DEBUG_COND) {
2024  std::cout << SIMTIME
2025  << " veh=" << myVehicle.getID()
2026  << " blocker=" << Named::getIDSecure(blocker)
2027  << " cannot save space=" << blocker->getVehicleType().getLengthWithGap()
2028  << " potential=" << potential
2029  << "\n";
2030  }
2031 #endif
2033  }
2034  }
2035 }
2036 
2037 
2038 void
2040  if (MSPModel::getModel()->hasPedestrians(lane)) {
2041 #ifdef DEBUG_WANTS_CHANGE
2042  if (DEBUG_COND) {
2043  std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << "\n";
2044  }
2045 #endif
2049  if (leader.first != 0) {
2050  const double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), leader.second - myVehicle.getVehicleType().getMinGap());
2051  v = MIN2(v, stopSpeed);
2052 #ifdef DEBUG_WANTS_CHANGE
2053  if (DEBUG_COND) {
2054  std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2055  }
2056 #endif
2057  }
2058  }
2059 }
2060 
2061 
2062 void MSLCM_LC2013::addLCSpeedAdvice(const double vSafe) {
2063  const double accel = SPEED2ACCEL(vSafe - myVehicle.getSpeed());
2064  myLCAccelerationAdvices.push_back(accel);
2065 }
2066 
2067 
2068 double
2069 MSLCM_LC2013::computeSpeedLat(double latDist, double& maneuverDist) {
2070  double speedBound = myMaxSpeedLatStanding + myMaxSpeedLatFactor * myVehicle.getSpeed();
2071  if (isChangingLanes()) {
2072  // Don't stay caught in the middle of a lane change while vehicle is standing, workaround for #3771
2073  speedBound = MAX2(LC_RESOLUTION_SPEED_LAT, speedBound);
2074  }
2075  return MAX2(-speedBound, MIN2(speedBound,
2076  MSAbstractLaneChangeModel::computeSpeedLat(latDist, maneuverDist)));
2077 }
2078 
2079 double
2082 }
2083 
2084 double
2086  return 1 / myAssertive;
2087 }
2088 
2089 std::string
2090 MSLCM_LC2013::getParameter(const std::string& key) const {
2092  return toString(myStrategicParam);
2093  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2094  return toString(myCooperativeParam);
2095  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2096  return toString(mySpeedGainParam);
2097  } else if (key == toString(LCA_KEEPRIGHT)) {
2098  return toString(myKeepRightParam);
2099  } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2100  return toString(myLookaheadLeft);
2101  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2102  return toString(mySpeedGainRight);
2103  } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2104  return toString(myAssertive);
2105  }
2106  throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2107 }
2108 
2109 
2110 void
2111 MSLCM_LC2013::setParameter(const std::string& key, const std::string& value) {
2112  double doubleValue;
2113  try {
2114  doubleValue = TplConvert::_2double(value.c_str());
2115  } catch (NumberFormatException&) {
2116  throw InvalidArgument("Setting parameter '" + key + "' requires a number for laneChangeModel of type '" + toString(myModel) + "'");
2117  }
2119  myStrategicParam = doubleValue;
2120  } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2121  myCooperativeParam = doubleValue;
2122  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2123  mySpeedGainParam = doubleValue;
2124  } else if (key == toString(LCA_KEEPRIGHT)) {
2125  myKeepRightParam = doubleValue;
2126  } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2127  myLookaheadLeft = doubleValue;
2128  } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2129  mySpeedGainRight = doubleValue;
2130  } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2131  myAssertive = doubleValue;
2132  } else {
2133  throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2134  }
2136 }
2137 
2138 /****************************************************************************/
2139 
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:2497
#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:852
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:307
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
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:4408
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:68
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:4642
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:626
#define ROUNDABOUT_DIST_FACTOR
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4027
#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:1840
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)
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:62
#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:335
#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:703
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:497
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:5196
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:3150
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:52
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
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:322
#define LOOK_AHEAD_MIN_SPEED
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1940
#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:5220
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 KEEP_RIGHT_TIME
bool congested() const
Definition: MSVehicle.h:711