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