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