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-2016 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  // cannot overtake
509  // slow down smoothly to follow leader
510  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
511  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
512  if (targetSpeed < myVehicle.getSpeed()) {
513  // slow down smoothly to follow leader
514  const SUMOReal decel = remainingSeconds == 0. ? myVehicle.getCarFollowModel().getMaxDecel() :
516  MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds));
517  const SUMOReal nextSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() - ACCEL2SPEED(decel));
518 #ifdef DEBUG_INFORMER
519  if (DEBUG_COND) {
520  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
521  << " cannot overtake leader nv=" << nv->getID()
522  << " dv=" << dv
523  << " myLookAheadSpeed=" << myLookAheadSpeed
524  << " myLeftSpace=" << myLeftSpace
525  << " overtakeDist=" << overtakeDist
526  << " overtakeTime=" << overtakeTime
527  << " remainingSeconds=" << remainingSeconds
528  << " currentGap=" << neighLead.second
531  << " targetSpeed=" << targetSpeed
532  << " nextSpeed=" << nextSpeed
533  << "\n";
534  }
535 #endif
536  myVSafes.push_back(nextSpeed);
537  return nextSpeed;
538  } else {
539  // leader is fast enough anyway
540 #ifdef DEBUG_INFORMER
541  if (DEBUG_COND) {
542  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
543  << " cannot overtake fast leader nv=" << nv->getID()
544  << " dv=" << dv
545  << " myLookAheadSpeed=" << myLookAheadSpeed
546  << " myLeftSpace=" << myLeftSpace
547  << " overtakeDist=" << overtakeDist
548  << " myLeadingBlockerLength=" << myLeadingBlockerLength
549  << " overtakeTime=" << overtakeTime
550  << " remainingSeconds=" << remainingSeconds
551  << " currentGap=" << neighLead.second
552  << " targetSpeed=" << targetSpeed
553  << "\n";
554  }
555 #endif
556  myVSafes.push_back(targetSpeed);
557  return plannedSpeed;
558  }
559  } else {
560  // overtaking, leader should not accelerate
561 #ifdef DEBUG_INFORMER
562  if (DEBUG_COND) {
563  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
564  << " wants to overtake leader nv=" << nv->getID()
565  << " dv=" << dv
566  << " overtakeDist=" << overtakeDist
567  << " remainingSeconds=" << remainingSeconds
568  << " overtakeTime=" << overtakeTime
569  << " currentGap=" << neighLead.second
571  << "\n";
572  }
573 #endif
574  msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
575  return -1; // XXX: using -1 is ambiguous for the ballistic update! Currently this is being catched in patchSpeed() (Leo), consider returning INVALID_SPEED, refs. #2577
576  }
577  } else if (neighLead.first != 0) { // (remainUnblocked)
578  // we are not blocked now. make sure we stay far enough from the leader
579  MSVehicle* nv = neighLead.first;
580  const SUMOReal nextNVSpeed = nv->getSpeed() - HELP_OVERTAKE; // conservative
581  const SUMOReal dv = SPEED2DIST(myVehicle.getSpeed() - nextNVSpeed);
582  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
583  &myVehicle, myVehicle.getSpeed(), neighLead.second - dv, nextNVSpeed, nv->getCarFollowModel().getMaxDecel());
584  myVSafes.push_back(targetSpeed);
585 #ifdef DEBUG_INFORMER
586  if (DEBUG_COND) {
587  std::cout << " not blocked by leader nv=" << nv->getID()
588  << " nvSpeed=" << nv->getSpeed()
589  << " gap=" << neighLead.second
590  << " nextGap=" << neighLead.second - dv
592  << " targetSpeed=" << targetSpeed
593  << "\n";
594  }
595 #endif
596  return MIN2(targetSpeed, plannedSpeed);
597  } else {
598  // not overtaking
599  return plannedSpeed;
600  }
601 }
602 
603 void
605  int blocked,
606  int dir,
607  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
608  SUMOReal remainingSeconds,
609  SUMOReal plannedSpeed) {
610 
611  MSVehicle* nv = neighFollow.first;
613 
614 #ifdef DEBUG_INFORMER
615  if (DEBUG_COND) {
616  std::cout << "\nINFORM_FOLLOWER"
617  << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
618  }
619 
620 #endif
621  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
622  assert(nv != 0);
623 #ifdef DEBUG_INFORMER
624  if (DEBUG_COND) {
625  std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
626  << nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel()) << " planned=" << plannedSpeed << "\n";
627  }
628 #endif
629 
630  // are we fast enough to cut in without any help?
631  if (MAX2(plannedSpeed, (SUMOReal)0.) - nv->getSpeed() >= HELP_OVERTAKE) {
632  const SUMOReal neededGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
633  if ((neededGap - neighFollow.second) / remainingSeconds < (MAX2(plannedSpeed, (SUMOReal)0.) - nv->getSpeed())) {
634 #ifdef DEBUG_INFORMER
635  if (DEBUG_COND) {
636  std::cout << " wants to cut in before nv=" << nv->getID() << " without any help." << "\nneededGap = " << neededGap << "\n";
637  }
638 #endif
639  // follower might even accelerate but not to much
640  // XXX: I don't understand this. The needed gap was determined for nv->getSpeed(), not for (plannedSpeed - HELP_OVERTAKE)?! (Leo), refs. #2578
641  msgPass.informNeighFollower(new Info(MAX2(plannedSpeed, (SUMOReal)0.) - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
642  return;
643  }
644  }
645 
646  // decide whether we will request help to cut in before the follower or allow to be overtaken
647 
648  // PARAMETERS
649  // assume other vehicle will assume the equivalent of 1 second of
650  // maximum deceleration to help us (will probably be spread over
651  // multiple seconds)
652  // -----------
653  const SUMOReal helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR;
654 
655  // follower's new speed in next step
656  SUMOReal neighNewSpeed;
657  // follower's new speed after 1s.
658  SUMOReal neighNewSpeed1s;
659  // velocity difference, gap after follower-deceleration
660  SUMOReal dv, decelGap;
661 
663  // euler
664  neighNewSpeed = MAX2((SUMOReal)0, nv->getSpeed() - ACCEL2SPEED(helpDecel));
665  neighNewSpeed1s = MAX2((SUMOReal)0, nv->getSpeed() - helpDecel); // TODO: consider introduction of a configurable anticipationTime here (see far below in the !blocked part). Refs. #2578
666  // change in the gap between ego and blocker over 1 second (not STEP!)
667  // XXX: though here it is calculated as if it were one step!? (Leo) Refs. #2578
668  dv = plannedSpeed - neighNewSpeed1s; // XXX: what is this quantity (if TS!=1)?
669  // new gap between follower and self in case the follower does brake for 1s
670  // XXX: if the step-length is not 1s., this is not the gap after 1s. deceleration!
671  // And this formula overestimates the real gap. Isn't that problematic? (Leo)
672  // Below, it seems that decelGap > secureGap is taken to indicate the possibility
673  // to cut in within the next time-step. However, this is not the case, if TS<1s.,
674  // since decelGap is (not exactly, though!) the gap after 1s. Refs. #2578
675  decelGap = neighFollow.second + dv;
676  } else {
677  // ballistic
678  // negative newSpeed-extrapolation possible, if stop lies within the next time-step
679  // XXX: this code should work for the euler case as well, since gapExtrapolation() takes
680  // care of this, but for TS!=1 we will have different behavior (see previous remark) Refs. #2578
681  neighNewSpeed = nv->getSpeed() - ACCEL2SPEED(helpDecel);
682  neighNewSpeed1s = nv->getSpeed() - helpDecel;
683 
684  dv = myVehicle.getSpeed() - nv->getSpeed(); // current velocity difference
685  decelGap = myCarFollowModel.gapExtrapolation(1., neighFollow.second, myVehicle.getSpeed(),
686  nv->getSpeed(), plannedAccel, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
687  }
688 
689  const SUMOReal secureGap = nv->getCarFollowModel().getSecureGap(MAX2(neighNewSpeed1s, (SUMOReal)0.),
690  MAX2(plannedSpeed, (SUMOReal)0.), myVehicle.getCarFollowModel().getMaxDecel());
691 
692 #ifdef DEBUG_INFORMER
693  if (DEBUG_COND) {
694  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
695  << " speed=" << myVehicle.getSpeed()
696  << " plannedSpeed=" << plannedSpeed
697  << " neighNewSpeed=" << neighNewSpeed
698  << " neighNewSpeed1s=" << neighNewSpeed1s
699  << " dv=" << dv
700  << " gap=" << neighFollow.second
701  << " decelGap=" << decelGap
702  << " secureGap=" << secureGap
703  << "\n";
704  }
705 #endif
706 
707  if (decelGap > 0 && decelGap >= secureGap) {
708  // XXX: This does not assure that the leader can cut in in the next step if TS < 1 (see above)
709  // this seems to be supposed in the following (euler code)...?! (Leo) Refs. #2578
710 
711  // if the blocking follower brakes it could help
712  // how hard does it actually need to be?
713  // to be safe in the next step the following equation has to hold for the follower's vsafe:
714  // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
715  SUMOReal vsafe, vsafe1;
716 
718  // euler
719  // we compute an upper bound on vsafe by doing the computation twice
720  vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
721  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, myCarFollowModel.getMaxDecel()));
722  vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
723  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, myCarFollowModel.getMaxDecel()));
724  assert(vsafe <= vsafe1);
725  } else {
726  // ballistic
727 
728  // XXX: This block should actually do as well for euler update (TODO: test!), refs #2575
729  // we compute an upper bound on vsafe
730  // next step's gap without help deceleration (nv's speed assumed constant)
732  neighFollow.second, myVehicle.getSpeed(),
733  nv->getSpeed(), plannedAccel, 0,
735 #ifdef DEBUG_INFORMER
736  if (DEBUG_COND) {
737  std::cout << "nextGap=" << nextGap << " (without help decel) \n";
738  }
739 #endif
740 
741  // NOTE: the second argument of MIN2() can get larger than nv->getSpeed()
742  vsafe1 = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
744  nv->getSpeed(), nextGap,
745  MAX2((SUMOReal)0., plannedSpeed),
747 
748 
749  // next step's gap with possibly less than maximal help deceleration (in case vsafe1 > neighNewSpeed)
750  SUMOReal decel2 = SPEED2ACCEL(nv->getSpeed() - vsafe1);
752  neighFollow.second, myVehicle.getSpeed(),
753  nv->getSpeed(), plannedAccel, -decel2,
755 
756  // vsafe = MAX(neighNewSpeed, safe speed assuming next_gap)
757  // Thus, the gap resulting from vsafe is larger or equal to next_gap
758  // in contrast to the euler case, where nv's follow speed doesn't depend on the actual speed,
759  // we need to assure, that nv doesn't accelerate
760  vsafe = MIN2(nv->getSpeed(),
761  MAX2(neighNewSpeed,
763  nv->getSpeed(), nextGap,
764  MAX2((SUMOReal)0., plannedSpeed),
766 
767  assert(vsafe >= vsafe1);
768 
769 #ifdef DEBUG_INFORMER
770  if (DEBUG_COND) {
771  std::cout << "nextGap=" << nextGap
772  << " (with vsafe1 and help decel) \nvsafe1=" << vsafe1
773  << " vsafe=" << vsafe
774  << "\n";
775  }
776 #endif
777 
778  // For subsecond simulation, this might not lead to secure gaps for a long time,
779  // we seek to establish a secure gap as soon as possible
780  SUMOReal nextSecureGap = nv->getCarFollowModel().getSecureGap(vsafe, plannedSpeed, myCarFollowModel.getMaxDecel());
781 
782  if (nextGap < nextSecureGap) {
783  // establish a secureGap as soon as possible
784  vsafe = neighNewSpeed;
785  }
786 
787 #ifdef DEBUG_INFORMER
788  if (DEBUG_COND) {
789  std::cout << "nextGap=" << nextGap
790  << " minNextSecureGap=" << nextSecureGap
791  << " vsafe=" << vsafe << "\n";
792  }
793 #endif
794 
795  }
796  msgPass.informNeighFollower(
797  new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
798 
799 #ifdef DEBUG_INFORMER
800  if (DEBUG_COND) {
801  std::cout << " wants to cut in before nv=" << nv->getID()
802  << " vsafe1=" << vsafe1 << " vsafe=" << vsafe
803  << " newSecGap="
804  << nv->getCarFollowModel().getSecureGap(vsafe,
805  plannedSpeed,
807  << "\n";
808  }
809 #endif
810  } else if ((MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS))
811  || (!MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * (remainingSeconds - 1) > secureGap - decelGap + POSITION_EPS)
812  ) {
813 
814  // XXX: Alternative formulation (encapsulating differences of euler and ballistic) TODO: test, refs. #2575
815  // SUMOReal eventualGap = myCarFollowModel.gapExtrapolation(remainingSeconds - 1., decelGap, plannedSpeed, neighNewSpeed1s);
816  // } else if (eventualGap > secureGap + POSITION_EPS) {
817 
818 
819  // NOTE: This case corresponds to the situation, where some time is left to perform the lc
820  // For the ballistic case this is interpreted as follows:
821  // If the follower breaks with helpDecel for one second, this vehicle maintains the plannedSpeed,
822  // and both continue with their speeds for remainingSeconds seconds the gap will suffice for a laneChange
823  // For the euler case we had the following comment:
824  // 'decelerating once is sufficient to open up a large enough gap in time', but:
825  // XXX: 1) Decelerating *once* does not necessarily lead to the gap decelGap! (if TS<1s.) (Leo)
826  // 2) Probably, the if() for euler should test for dv * (remainingSeconds-1) > ..., too ?!, refs. #2578
827  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
828 #ifdef DEBUG_INFORMER
829  if (DEBUG_COND) {
830  std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
831  }
832 #endif
833  } else if (dir == LCA_MRIGHT && !myAllowOvertakingRight && !nv->congested()) {
834  // XXX: check if this requires a special treatment for the ballistic update, refs. #2575
835  const SUMOReal vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
836  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
837 #ifdef DEBUG_INFORMER
838  if (DEBUG_COND) {
839  std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
840  }
841 #endif
842  } else {
844  //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE &&
845  // nv->getSpeed() > myVehicle.getSpeed()) {
846  if (nv->getSpeed() > myVehicle.getSpeed() &&
847  ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) // NOTE: it might be considered to use myVehicle.getAccumulatedWaitingSeconds() > LCA_RIGHT_IMPATIENCE instead (Leo). Refs. #2578
848  || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
849  // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
850  || (dir == LCA_MLEFT && myLeftSpace > MAX_ONRAMP_LENGTH)
851  )) {
852  // let the follower slow down to increase the likelihood that later vehicles will be slow enough to help
853  // follower should still be fast enough to open a gap
854  // XXX: The probability for that success would be larger if the slow down of the appropriate following vehicle
855  // would take place without the immediate follower slowing down. We might consider to model reactions of
856  // vehicles that are not immediate followers. (Leo) -> see ticket #2532
857  vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
858 #ifdef DEBUG_INFORMER
859  if (DEBUG_COND) {
860  // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! (Leo)
861  // Further, vhelp might be larger than nv->getSpeed(), so the request issued below is not to slow down!? (see below) Refs. #2578
862  std::cout << " wants right follower to slow down a bit\n";
863  }
864 #endif
866  // euler
867  if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
868 
869 #ifdef DEBUG_INFORMER
870  if (DEBUG_COND) {
871  // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! Refs. #2578
872  std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
873  }
874 #endif
875  // XXX: I don't understand. This vhelp might be larger than nv->getSpeed() but the above condition seems to rely
876  // on the reasoning that if nv breaks with helpDecel for remaining Seconds, nv will be so slow, that this
877  // vehicle will be able to cut in. But nv might have overtaken this vehicle already (or am I missing sth?). (Leo)
878  // Ad: To my impression, the intention behind allowing larger speeds for the blocking follower is to prevent a
879  // situation, where an overlapping follower keeps blocking the ego vehicle. Refs. #2578
880  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
881  return;
882  }
883  } else {
884 
885  // 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)
886  // estimate gap after remainingSeconds.
887  // Assumptions:
888  // (A1) leader continues with currentSpeed. (XXX: That might be wrong: Think of accelerating on an on-ramp or of a congested region ahead!)
889  // (A2) follower breaks with helpDecel.
890  const SUMOReal gapAfterRemainingSecs = myCarFollowModel.gapExtrapolation(
891  remainingSeconds, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(), 0, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
892  const SUMOReal secureGapAfterRemainingSecs = nv->getCarFollowModel().getSecureGap(
893  MAX2(nv->getSpeed() - remainingSeconds * helpDecel, (SUMOReal)0.), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
894  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
895 #ifdef DEBUG_INFORMER
896  if (DEBUG_COND) {
897  std::cout << " wants to cut in before follower nv=" << nv->getID() << " (eventually)\n";
898  }
899 #endif
900  // NOTE: ballistic uses neighNewSpeed instead of vhelp, see my note above. (Leo)
901  // TODO: recheck if this might cause suboptimal behaviour in some LC-situations. Refs. #2578
902  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
903  return;
904  }
905  }
906 
907 
908  }
909 
910 #ifdef DEBUG_INFORMER
911  if (DEBUG_COND) {
912  std::cout << SIMTIME
913  << " veh=" << myVehicle.getID()
914  << " informs follower " << nv->getID()
915  << " vhelp=" << vhelp
916  << "\n";
917  }
918 #endif
919 
920  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
921  // This follower is supposed to overtake us. Slow down smoothly to allow this.
922  const SUMOReal overtakeDist = overtakeDistance(nv, &myVehicle, neighFollow.second, vhelp, plannedSpeed);
923  // speed difference to create a sufficiently large gap
924  const SUMOReal needDV = overtakeDist / remainingSeconds;
925  // 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
926  myVSafes.push_back(MAX2(vhelp - needDV, myVehicle.getSpeed() - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())));
927 
928 #ifdef DEBUG_INFORMER
929  if (DEBUG_COND) {
930  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
931  << " veh=" << myVehicle.getID()
932  << " wants to be overtaken by=" << nv->getID()
933  << " overtakeDist=" << overtakeDist
934  << " vneigh=" << nv->getSpeed()
935  << " vhelp=" << vhelp
936  << " needDV=" << needDV
937  << " vsafe=" << myVSafes.back()
938  << "\n";
939  }
940 #endif
941  }
942  } else if (neighFollow.first != 0) {
943  // XXX: Shouldn't the condition be extended by '&& (blocked & LCA_BLOCKED_BY_LEADER) != 0'? Refs. #2578
944  // Otherwise we don't need to inform the follower but simply cut in
945 
946  // we are not blocked by the follower now, make sure it remains that way
947  // XXX: Does the below code for the euler case really assure that? Refs. #2578
948  SUMOReal vsafe, vsafe1;
950  // euler
951  MSVehicle* nv = neighFollow.first;
952  vsafe1 = nv->getCarFollowModel().followSpeed(
953  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
954  vsafe = nv->getCarFollowModel().followSpeed(
955  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
956  // NOTE: since vsafe1 > nv->getSpeed() is possible, we don't have vsafe1 < vsafe < nv->getSpeed here (similar pattern above works differently)
957 
958  } else {
959  // ballistic
960  // XXX This should actually do for euler and ballistic cases (TODO: test!) Refs. #2575
961 
962  SUMOReal anticipationTime = 1.;
963  SUMOReal anticipatedSpeed = MIN2(myVehicle.getSpeed() + plannedAccel * anticipationTime, myVehicle.getMaxSpeedOnLane());
964  SUMOReal anticipatedGap = myCarFollowModel.gapExtrapolation(anticipationTime, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(),
965  plannedAccel, 0, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
966  SUMOReal secureGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), anticipatedSpeed, myCarFollowModel.getMaxDecel());
967 
968  // propose follower speed corresponding to first estimation of gap
969  SUMOReal vsafe = nv->getCarFollowModel().followSpeed(
970  nv, nv->getSpeed(), anticipatedGap, plannedSpeed, myCarFollowModel.getMaxDecel());
971  SUMOReal helpAccel = SPEED2ACCEL(vsafe - nv->getSpeed()) / anticipationTime;
972 
973  if (anticipatedGap > secureGap) {
974  // follower may accelerate, implying vhelp >= vsafe >= nv->getSpeed()
975  // calculate gap for the assumed acceleration
976  anticipatedGap = myCarFollowModel.gapExtrapolation(anticipationTime, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(),
977  plannedAccel, helpAccel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
978  SUMOReal anticipatedHelpSpeed = MIN2(nv->getSpeed() + anticipationTime * helpAccel, nv->getMaxSpeedOnLane());
979  secureGap = nv->getCarFollowModel().getSecureGap(anticipatedHelpSpeed, anticipatedSpeed, myCarFollowModel.getMaxDecel());
980  if (anticipatedGap < secureGap) {
981  // don't accelerate
982  vsafe = nv->getSpeed();
983  }
984  } else {
985  // follower is too fast, implying that vhelp <= vsafe <= nv->getSpeed()
986  // we use the above vhelp
987  }
988  }
989  msgPass.informNeighFollower(new Info(vsafe, dir), &myVehicle);
990 
991 #ifdef DEBUG_INFORMER
992  if (DEBUG_COND) {
993  std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
994  }
995 #endif
996  }
997 }
998 
999 
1000 void
1002  // keep information about strategic change direction
1005  myLeftSpace = 0;
1006  myVSafes.clear();
1007  myDontBrake = false;
1008  // truncate to work around numerical instability between different builds
1009  mySpeedGainProbability = ceil(mySpeedGainProbability * 100000.0) * 0.00001;
1010  myKeepRightProbability = ceil(myKeepRightProbability * 100000.0) * 0.00001;
1011 }
1012 
1013 
1014 void
1016  myOwnState = 0;
1019  if (myVehicle.getBestLaneOffset() == 0) {
1020  // if we are not yet on our best lane there might still be unseen blockers
1021  // (during patchSpeed)
1023  myLeftSpace = 0;
1024  }
1026  myVSafes.clear();
1027  myDontBrake = false;
1028 }
1029 
1030 
1031 int
1033  int laneOffset,
1035  int blocked,
1036  const std::pair<MSVehicle*, SUMOReal>& leader,
1037  const std::pair<MSVehicle*, SUMOReal>& neighLead,
1038  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
1039  const MSLane& neighLane,
1040  const std::vector<MSVehicle::LaneQ>& preb, // XXX: What does "preb" stand for? Please comment. (Leo) Refs. #2578, #2604
1041  MSVehicle** lastBlocked,
1042  MSVehicle** firstBlocked) {
1043  assert(laneOffset == 1 || laneOffset == -1);
1044  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
1045  // compute bestLaneOffset
1046  MSVehicle::LaneQ curr, neigh, best;
1047  int bestLaneOffset = 0;
1048  // What do these "dists" mean? Please comment. (Leo) Ad: I now think the following:
1049  // currentDist is the distance that the vehicle can go on its route without having to
1050  // change lanes from the current lane. neighDist as currentDist for the considered target lane (i.e., neigh)
1051  // If this is true I suggest to put this into the docu of wantsChange()
1052  SUMOReal currentDist = 0;
1053  SUMOReal neighDist = 0;
1054  int currIdx = 0;
1055  MSLane* prebLane = myVehicle.getLane();
1056  if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
1057  // internal edges are not kept inside the bestLanes structure
1058  prebLane = prebLane->getLinkCont()[0]->getLane();
1059  }
1060  // XXX: What does the following code do? Please comment. (Leo) Refs. #2578
1061  const bool checkOpposite = &neighLane.getEdge() != &myVehicle.getLane()->getEdge();
1062  const int prebOffset = (checkOpposite ? 0 : laneOffset);
1063  for (int p = 0; p < (int) preb.size(); ++p) {
1064  if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1065  assert(p + prebOffset < (int)preb.size());
1066  curr = preb[p];
1067  neigh = preb[p + prebOffset];
1068  currentDist = curr.length;
1069  neighDist = neigh.length;
1070  bestLaneOffset = curr.bestLaneOffset;
1071  if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0) {
1072 #ifdef DEBUG_WANTS_CHANGE
1073  if (DEBUG_COND) {
1074  std::cout << STEPS2TIME(currentTime)
1075  << " veh=" << myVehicle.getID()
1076  << " bestLaneOffsetOld=" << bestLaneOffset
1077  << " bestLaneOffsetNew=" << laneOffset
1078  << "\n";
1079  }
1080 #endif
1081  bestLaneOffset = prebOffset;
1082  }
1083  best = preb[p + bestLaneOffset];
1084  currIdx = p;
1085  break;
1086  }
1087  }
1088  // direction specific constants
1089  const bool right = (laneOffset == -1);
1090  if (isOpposite() && right) {
1091  neigh = preb[preb.size() - 1];
1092  curr = neigh;
1093  best = neigh;
1094  bestLaneOffset = -1;
1095  curr.bestLaneOffset = -1;
1096  neighDist = neigh.length;
1097  currentDist = curr.length;
1098  }
1100  const int lca = (right ? LCA_RIGHT : LCA_LEFT);
1101  const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
1102  const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
1103  const bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1104  // keep information about being a leader/follower
1105  int ret = (myOwnState & 0xffff0000);
1106  int req = 0; // the request to change or stay
1107 
1108  ret = slowDownForBlocked(lastBlocked, ret);
1109  if (lastBlocked != firstBlocked) {
1110  ret = slowDownForBlocked(firstBlocked, ret);
1111  }
1112 
1113 #ifdef DEBUG_WANTS_CHANGE
1114  if (DEBUG_COND) {
1115  std::cout << SIMTIME
1116  << " veh=" << myVehicle.getID()
1117  << " _wantsChange state=" << myOwnState
1118  << " myVSafes=" << toString(myVSafes)
1119  << " firstBlocked=" << Named::getIDSecure(*firstBlocked)
1120  << " lastBlocked=" << Named::getIDSecure(*lastBlocked)
1121  << " leader=" << Named::getIDSecure(leader.first)
1122  << " leaderGap=" << leader.second
1123  << " neighLead=" << Named::getIDSecure(neighLead.first)
1124  << " neighLeadGap=" << neighLead.second
1125  << " neighFollow=" << Named::getIDSecure(neighFollow.first)
1126  << " neighFollowGap=" << neighFollow.second
1127  << "\n";
1128  }
1129 #endif
1130 
1131  // we try to estimate the distance which is necessary to get on a lane
1132  // we have to get on in order to keep our route
1133  // we assume we need something that depends on our velocity
1134  // and compare this with the free space on our wished lane
1135  //
1136  // if the free space is somehow(<-?) less than the space we need, we should
1137  // definitely try to get to the desired lane
1138  //
1139  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
1140 
1141 
1142  // we do not want the lookahead distance to change all the time so we let it decay slowly
1143  // (in contrast, growth is applied instantaneously)
1146  } else {
1147  // memory decay factor for this time step
1148  const SUMOReal memoryFactor = 1. - (1. - LOOK_AHEAD_SPEED_MEMORY) * TS;
1149  assert(memoryFactor > 0.);
1151  (memoryFactor * myLookAheadSpeed + (1 - memoryFactor) * myVehicle.getSpeed()));
1152  }
1154  laDist += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.;
1155 
1156 
1157  if (bestLaneOffset == 0 && leader.first != 0 && leader.first->isStopped()) {
1158  // react to a stopped leader on the current lane
1159  // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1160  // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1161  laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1162  + leader.first->getVehicleType().getLengthWithGap());
1163  } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && neighLead.first->isStopped()) {
1164  // react to a stopped leader on the target lane (if it is the bestLane)
1166  + neighLead.first->getVehicleType().getLengthWithGap();
1167  }
1168 
1169  // free space that is available for changing
1170  //const SUMOReal neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
1171  // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
1172  // best.lane->getSpeedLimit());
1173  // @note: while this lets vehicles change earlier into the correct direction
1174  // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
1175 
1176 
1177 
1178  // Next we assign to roundabout edges a larger distance than to normal edges
1179  // in order to decrease sense of lc urgency and induce higher usage of inner roundabout lanes.
1180  // 1) get information about the next upcoming roundabout
1181  SUMOReal roundaboutDistanceAhead;
1182  SUMOReal roundaboutDistanceAheadNeigh;
1183  int roundaboutEdgesAhead;
1184  int roundaboutEdgesAheadNeigh;
1185  getRoundaboutAheadInfo(this, curr, neigh, roundaboutDistanceAhead, roundaboutDistanceAheadNeigh, roundaboutEdgesAhead, roundaboutEdgesAheadNeigh);
1186  // 2) add a distance bonus for roundabout edges
1187  currentDist += roundaboutDistBonus(roundaboutDistanceAhead, roundaboutEdgesAhead);
1188  neighDist += roundaboutDistBonus(roundaboutDistanceAheadNeigh, roundaboutEdgesAheadNeigh);
1189 
1190 #ifdef DEBUG_WANTS_CHANGE
1191  if (DEBUG_COND) {
1192  if (roundaboutEdgesAhead > 0) {
1193  std::cout << " roundaboutEdgesAhead=" << roundaboutEdgesAhead << " roundaboutEdgesAheadNeigh=" << roundaboutEdgesAheadNeigh << "\n";
1194 // std::cout << " roundaboutDistanceAhead=" << roundaboutDistanceAhead << " roundaboutDistanceAheadNeigh=" << roundaboutDistanceAheadNeigh << "\n";
1195  }
1196  }
1197 #endif
1198 
1199  const SUMOReal usableDist = (currentDist - posOnLane - best.occupation * JAM_FACTOR);
1200  //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1201  const SUMOReal maxJam = MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1202  const SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - posOnLane - maxJam);
1203 
1204 #ifdef DEBUG_WANTS_CHANGE
1205  if (DEBUG_COND) {
1206  std::cout << STEPS2TIME(currentTime)
1207  << " veh=" << myVehicle.getID()
1208  << " laSpeed=" << myLookAheadSpeed
1209  << " laDist=" << laDist
1210  << " currentDist=" << currentDist
1211  << " usableDist=" << usableDist
1212  << " bestLaneOffset=" << bestLaneOffset
1213  << " best.occupation=" << best.occupation
1214  << " best.length=" << best.length
1215  << " maxJam=" << maxJam
1216  << " neighLeftPlace=" << neighLeftPlace
1217  << "\n";
1218  }
1219 #endif
1220 
1221  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1222  && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1224  ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1225  } else {
1226  // VARIANT_20 (noOvertakeRight)
1227  if (!myAllowOvertakingRight && !right && !myVehicle.congested() && neighLead.first != 0) {
1228  // check for slower leader on the left. we should not overtake but
1229  // rather move left ourselves (unless congested)
1230  MSVehicle* nv = neighLead.first;
1231  if (nv->getSpeed() < myVehicle.getSpeed()) {
1232  const SUMOReal vSafe = myCarFollowModel.followSpeed(
1233  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1234  myVSafes.push_back(vSafe);
1235  if (vSafe < myVehicle.getSpeed()) {
1237  }
1238 #ifdef DEBUG_WANTS_CHANGE
1239  if (DEBUG_COND) {
1240  std::cout << STEPS2TIME(currentTime)
1241  << " avoid overtaking on the right nv=" << nv->getID()
1242  << " nvSpeed=" << nv->getSpeed()
1243  << " mySpeedGainProbability=" << mySpeedGainProbability
1244  << " plannedSpeed=" << myVSafes.back()
1245  << "\n";
1246  }
1247 #endif
1248  }
1249  }
1250 
1251  if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
1252  // the opposite lane-changing direction should be done than the one examined herein
1253  // we'll check whether we assume we could change anyhow and get back in time...
1254  //
1255  // this rule prevents the vehicle from moving in opposite direction of the best lane
1256  // unless the way till the end where the vehicle has to be on the best lane
1257  // is long enough
1258 #ifdef DEBUG_WANTS_CHANGE
1259  if (DEBUG_COND) {
1260  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1261  }
1262 #endif
1263  ret = ret | LCA_STAY | LCA_STRATEGIC;
1264  } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1265  // the current lane is the best and a lane-changing would cause a situation
1266  // of which we assume we will not be able to return to the lane we have to be on.
1267  // this rule prevents the vehicle from leaving the current, best lane when it is
1268  // close to this lane's end
1269 #ifdef DEBUG_WANTS_CHANGE
1270  if (DEBUG_COND) {
1271  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1272  }
1273 #endif
1274  ret = ret | LCA_STAY | LCA_STRATEGIC;
1275  } else if (bestLaneOffset == 0
1276  && (leader.first == 0 || !leader.first->isStopped())
1277  && neigh.bestContinuations.back()->getLinkCont().size() != 0
1278  && roundaboutEdgesAhead == 0
1279  && neighDist < TURN_LANE_DIST) {
1280  // VARIANT_21 (stayOnBest)
1281  // we do not want to leave the best lane for a lane which leads elsewhere
1282  // unless our leader is stopped or we are approaching a roundabout
1283 #ifdef DEBUG_WANTS_CHANGE
1284  if (DEBUG_COND) {
1285  std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1286  }
1287 #endif
1288  ret = ret | LCA_STAY | LCA_STRATEGIC;
1289  }
1290  }
1291  // check for overriding TraCI requests
1292 #ifdef DEBUG_WANTS_CHANGE
1293  if (DEBUG_COND) {
1294  std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << ret;
1295  }
1296 #endif
1298  if ((ret & lcaCounter) != 0) {
1299  // we are not interested in traci requests for the opposite direction here
1300  ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1301  }
1302 #ifdef DEBUG_WANTS_CHANGE
1303  if (DEBUG_COND) {
1304  std::cout << " retAfterInfluence=" << ret << "\n";
1305  }
1306 #endif
1307 
1308  if ((ret & LCA_STAY) != 0) {
1309  return ret;
1310  }
1311  if ((ret & LCA_URGENT) != 0) {
1312  // prepare urgent lane change maneuver
1313  // save the left space
1314  myLeftSpace = currentDist - posOnLane;
1315  if (changeToBest && abs(bestLaneOffset) > 1) {
1316  // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1317 #ifdef DEBUG_WANTS_CHANGE
1318  if (DEBUG_COND) {
1319  std::cout << " reserving space for unseen blockers\n";
1320  }
1321 #endif
1322  myLeadingBlockerLength = MAX2((SUMOReal)(right ? 20.0 : 40.0), myLeadingBlockerLength);
1323  }
1324 
1325  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1326  // if there is a leader and he wants to change to the opposite direction
1327  saveBlockerLength(neighLead.first, lcaCounter);
1328  if (*firstBlocked != neighLead.first) {
1329  saveBlockerLength(*firstBlocked, lcaCounter);
1330  }
1331 
1332  const SUMOReal remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1333  // MAX2((SUMOReal)STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / abs(bestLaneOffset) / URGENCY) :
1336  const SUMOReal plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1337  // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1338  // while informLeader returns -1 in that case. Refs. #2577
1339  if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1340  // maybe we need to deal with a blocking follower
1341  informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1342  }
1343 
1344 #ifdef DEBUG_WANTS_CHANGE
1345  if (DEBUG_COND) {
1346  std::cout << STEPS2TIME(currentTime)
1347  << " veh=" << myVehicle.getID()
1348  << " myLeftSpace=" << myLeftSpace
1349  << " remainingSeconds=" << remainingSeconds
1350  << " plannedSpeed=" << plannedSpeed
1351  << "\n";
1352  }
1353 #endif
1354 
1355  return ret;
1356  }
1357  // a high inconvenience prevents cooperative changes.
1358  const SUMOReal inconvenience = MIN2((SUMOReal)1.0, (laneOffset < 0
1361  const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1362  const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1363 
1364  // VARIANT_15
1365  if (roundaboutEdgesAhead > 1) {
1366 
1367 #ifdef DEBUG_WANTS_CHANGE
1368  if (DEBUG_COND) {
1369  std::cout << STEPS2TIME(currentTime)
1370  << " veh=" << myVehicle.getID()
1371  << " roundaboutEdgesAhead=" << roundaboutEdgesAhead
1372  << " myLeftSpace=" << myLeftSpace
1373  << "\n";
1374  }
1375 #endif
1376  // try to use the inner lanes of a roundabout to increase throughput
1377  // unless we are approaching the exit
1378  if (lca == LCA_LEFT) {
1379  // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1380  // TODO: test this for euler update! Refs. #2575
1381  if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1382 // if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1383  req = ret | lca | LCA_COOPERATIVE;
1384  }
1385  } else {
1386  // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1387  if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1388 // if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1389  req = ret | LCA_STAY | LCA_COOPERATIVE;
1390  }
1391  }
1392  if (!cancelRequest(req)) {
1393  return ret | req;
1394  }
1395  }
1396 
1397  // let's also regard the case where the vehicle is driving on a highway...
1398  // in this case, we do not want to get to the dead-end of an on-ramp
1399  if (right) {
1400  if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1401 #ifdef DEBUG_WANTS_CHANGE
1402  if (DEBUG_COND) {
1403  std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1404  }
1405 #endif
1406  req = ret | LCA_STAY | LCA_STRATEGIC;
1407  if (!cancelRequest(req)) {
1408  return ret | req;
1409  }
1410  }
1411  }
1412  // --------
1413 
1414  // -------- make place on current lane if blocking follower
1415  //if (amBlockingFollowerPlusNB()) {
1416  // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1417  // << " neighDist=" << neighDist
1418  // << " currentDist=" << currentDist
1419  // << "\n";
1420  //}
1421 
1423  && (!speedGainInconvenient)
1424  //&& ((myOwnState & lcaCounter) == 0) // VARIANT_6 : counterNoHelp
1425  && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1426 
1427  // VARIANT_2 (nbWhenChangingToHelp)
1428 #ifdef DEBUG_WANTS_CHANGE
1429  if (DEBUG_COND) {
1430  std::cout << STEPS2TIME(currentTime)
1431  << " veh=" << myVehicle.getID()
1432  << " wantsChangeToHelp=" << (right ? "right" : "left")
1433  << " state=" << myOwnState
1434  // << (((myOwnState & lcaCounter) != 0) ? " (counter)" : "")
1435  << "\n";
1436  }
1437 #endif
1438  req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1439  if (!cancelRequest(req)) {
1440  return ret | req;
1441  }
1442  }
1443 
1444  // --------
1445 
1446 
1449  //if ((blocked & LCA_BLOCKED) != 0) {
1450  // return ret;
1451  //}
1453 
1454  // -------- higher speed
1455  //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1456  // return ret;
1457  //}
1458 
1459  SUMOReal thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
1460  SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
1461 
1462  /* First attempt to fix #2126
1463  * should rather be considering anticipated speeds further in the future, maybe combined with maximal speed as tried here
1464  if (neighLead.first == 0) {
1465  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.maximumSafeStopSpeed(neighDist, myVehicle.getSpeed(),true));
1466  } else {
1467  // @todo: what if leader is below safe gap?!!!
1468  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.maximumSafeFollowSpeed(neighLead.second, myVehicle.getSpeed(),
1469  neighLead.first->getSpeed(),neighLead.first->getCarFollowModel().getMaxDecel(),true));
1470  }
1471  if (leader.first == 0) {
1472  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.maximumSafeStopSpeed(currentDist, myVehicle.getSpeed(),true));
1473  } else {
1474  // @todo: what if leader is below safe gap?!!!
1475  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.maximumSafeFollowSpeed(leader.second, myVehicle.getSpeed(),
1476  leader.first->getSpeed(),leader.first->getCarFollowModel().getMaxDecel(),true));
1477  }
1478  */
1479 
1480  const SUMOReal correctedSpeed = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1482  if (neighLead.first == 0) {
1483  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, correctedSpeed, neighDist, 0, 0));
1484  } else {
1485  // @todo: what if leader is below safe gap?!!!
1486  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(
1487  &myVehicle, correctedSpeed, neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
1488  }
1489  if (leader.first == 0) {
1490  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, correctedSpeed, currentDist, 0, 0));
1491  } else {
1492  // @todo: what if leader is below safe gap?!!!
1493  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(
1494  &myVehicle, correctedSpeed, leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
1495  }
1496 
1498  thisLaneVSafe = MIN2(thisLaneVSafe, vMax);
1499  neighLaneVSafe = MIN2(neighLaneVSafe, vMax);
1500  const SUMOReal relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1502 
1503 // // maybe this (acceleration-difference) would be a good quantity to take into account for lc-considerations..., refs. #2126
1504 // const SUMOReal accelDifference = ACCEL2SPEED(neighLaneVSafe - thisLaneVSafe);
1505 
1506 
1507 #ifdef DEBUG_WANTS_CHANGE
1508  if (DEBUG_COND) {
1509  std::cout << STEPS2TIME(currentTime)
1510  << " veh=" << myVehicle.getID()
1511  << " currentDist=" << currentDist
1512  << " neighDist=" << neighDist
1513 // << "\n thisLaneVSafe=" << toString(thisLaneVSafe,24)
1514 // << "\nneighLaneVSafe=" << toString(neighLaneVSafe,24)
1515 // << "\nrelativeGain=" << toString(relativeGain,24)
1516  << "\n";
1517  }
1518 #endif
1519 
1520  if (right) {
1521  // ONLY FOR CHANGING TO THE RIGHT
1522  if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1523  // ok, the current lane is faster than the right one...
1524  if (mySpeedGainProbability < 0) {
1525  mySpeedGainProbability *= pow(0.5, TS);
1526  //myKeepRightProbability /= 2.0;
1527  }
1528  } else {
1529  // ok, the current lane is not (much) faster than the right one
1530  // @todo recheck the 5 km/h discount on thisLaneVSafe, refs. #2068
1531 
1532  // do not promote changing to the left just because changing to the right is bad
1533  // XXX: The following code may promote it, though!? (recheck!)
1534  // (Think of small negative mySpeedGainProbability and larger negative relativeGain)
1535  // One might think of replacing '||' by '&&' to exclude that possibility...
1536  // Still, for negative relativeGain, we might want to decrease the inclination for
1537  // changing to the left. Another solution could be the seperation of mySpeedGainProbability into
1538  // two variables (one for left and one for right). Refs #2578
1539  if (mySpeedGainProbability < 0 || relativeGain > 0) {
1540  mySpeedGainProbability -= TS * relativeGain;
1541  }
1542 
1543  // honor the obligation to keep right (Rechtsfahrgebot)
1544  // XXX consider fast approaching followers on the current lane. Refs #2578
1545  //const SUMOReal vMax = myLookAheadSpeed;
1546  const SUMOReal acceptanceTime = KEEP_RIGHT_ACCEPTANCE * vMax * MAX2((SUMOReal)1, myVehicle.getSpeed()) / myVehicle.getLane()->getSpeedLimit();
1547  SUMOReal fullSpeedGap = MAX2((SUMOReal)0, neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1548  SUMOReal fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1549  if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1550  fullSpeedGap = MAX2((SUMOReal)0, MIN2(fullSpeedGap,
1551  neighLead.second - myVehicle.getCarFollowModel().getSecureGap(
1552  vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1553  fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1554  }
1555  const SUMOReal deltaProb = (myChangeProbThresholdRight
1556  * STEPS2TIME(DELTA_T)
1557  * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1558  myKeepRightProbability -= TS * deltaProb;
1559 
1560 #ifdef DEBUG_WANTS_CHANGE
1561  if (DEBUG_COND) {
1562  std::cout << STEPS2TIME(currentTime)
1563  << " veh=" << myVehicle.getID()
1564  << " vMax=" << vMax
1565  << " neighDist=" << neighDist
1566  << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1567  << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1568  << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(
1569  myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1570  << " acceptanceTime=" << acceptanceTime
1571  << " fullSpeedGap=" << fullSpeedGap
1572  << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1573  << " dProb=" << deltaProb
1574  << " myKeepRightProbability=" << myKeepRightProbability
1575  << "\n";
1576  }
1577 #endif
1579  req = ret | lca | LCA_KEEPRIGHT;
1580  if (!cancelRequest(req)) {
1581  return ret | req;
1582  }
1583  }
1584  }
1585 
1586 #ifdef DEBUG_WANTS_CHANGE
1587  if (DEBUG_COND) {
1588  std::cout << STEPS2TIME(currentTime)
1589  << " veh=" << myVehicle.getID()
1590  << " speed=" << myVehicle.getSpeed()
1591  << " mySpeedGainProbability=" << mySpeedGainProbability
1592  << " thisLaneVSafe=" << thisLaneVSafe
1593  << " neighLaneVSafe=" << neighLaneVSafe
1594  << " relativeGain=" << relativeGain
1595  << " blocked=" << blocked
1596  << "\n";
1597  }
1598 #endif
1599 
1601  && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1
1602  req = ret | lca | LCA_SPEEDGAIN;
1603  if (!cancelRequest(req)) {
1604  return ret | req;
1605  }
1606  }
1607  } else {
1608  // ONLY FOR CHANGING TO THE LEFT
1609  if (thisLaneVSafe > neighLaneVSafe) {
1610  // this lane is better
1611  if (mySpeedGainProbability > 0) {
1612  mySpeedGainProbability *= pow(0.5, TS);
1613  }
1614  } else {
1615  // left lane is better
1616  mySpeedGainProbability += TS * relativeGain;
1617  }
1618  // VARIANT_19 (stayRight)
1619  //if (neighFollow.first != 0) {
1620  // MSVehicle* nv = neighFollow.first;
1621  // const SUMOReal secGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1622  // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1623  // // do not change left if it would inconvenience faster followers
1624  // return ret | LCA_STAY | LCA_SPEEDGAIN;
1625  // }
1626  //}
1627 
1628 #ifdef DEBUG_WANTS_CHANGE
1629  if (DEBUG_COND) {
1630  std::cout << STEPS2TIME(currentTime)
1631  << " veh=" << myVehicle.getID()
1632  << " speed=" << myVehicle.getSpeed()
1633  << " mySpeedGainProbability=" << mySpeedGainProbability
1634  << " thisLaneVSafe=" << thisLaneVSafe
1635  << " neighLaneVSafe=" << neighLaneVSafe
1636  << " relativeGain=" << relativeGain
1637  << " blocked=" << blocked
1638  << "\n";
1639  }
1640 #endif
1641 
1642  if (mySpeedGainProbability > myChangeProbThresholdLeft && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1
1643  req = ret | lca | LCA_SPEEDGAIN;
1644  if (!cancelRequest(req)) {
1645  return ret | req;
1646  }
1647  }
1648  }
1649  // --------
1650  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1651  && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) {
1652  // change towards the correct lane, speedwise it does not hurt
1653  req = ret | lca | LCA_STRATEGIC;
1654  if (!cancelRequest(req)) {
1655  return ret | req;
1656  }
1657  }
1658 #ifdef DEBUG_WANTS_CHANGE
1659  if (DEBUG_COND) {
1660  std::cout << STEPS2TIME(currentTime)
1661  << " veh=" << myVehicle.getID()
1662  << " mySpeedGainProbability=" << mySpeedGainProbability
1663  << " myKeepRightProbability=" << myKeepRightProbability
1664  << " thisLaneVSafe=" << thisLaneVSafe
1665  << " neighLaneVSafe=" << neighLaneVSafe
1666  << "\n";
1667  }
1668 #endif
1669 
1670  return ret;
1671 }
1672 
1673 
1674 void
1676  SUMOReal& roundaboutDistanceAhead, SUMOReal& roundaboutDistanceAheadNeigh, int& roundaboutEdgesAhead, int& roundaboutEdgesAheadNeigh) {
1677 
1678  const MSVehicle& veh = lcm->myVehicle;
1679 
1680  // In what follows, we check whether a roundabout is ahead (or the vehicle is on a roundabout)
1681  // We calculate the lengths of the continuations described by curr and neigh,
1682  // which are part of the roundabout. Currently only takes effect for ballistic update, refs #1807, #2576 (Leo)
1683  SUMOReal pos = lcm->isOpposite() ? veh.getLane()->getLength() - veh.getPositionOnLane() : veh.getPositionOnLane();
1684  roundaboutDistanceAhead = distanceAlongNextRoundabout(pos, veh.getLane(), curr.bestContinuations);
1685 
1686  // For the distance on the neigh.lane, we need to do a little hack since we may not
1687  // have access to the right initial lane (neigh.lane is only the first non-null lane of neigh.bestContinuations).
1688  roundaboutDistanceAheadNeigh = 0;
1689  SUMOReal neighPosition = pos;
1690 #ifdef HAVE_INTERNAL_LANES
1692  // take care of the distance on internal lanes
1693  neighPosition = 0.;
1694  if (veh.getLane()->getEdge().isRoundabout()) {
1695  // vehicle is on internal roundabout lane -> neigh.lane is not a parallel internal lane, but the next non-internal lane
1696  // add remaining length on current, internal lane to roundabout distance on neigh continuation
1697  roundaboutDistanceAheadNeigh = veh.getLane()->getLength() - veh.getPositionOnLane();
1698  MSLane* nextLane = 0;
1699  for (std::vector<MSLane*>::const_iterator i = curr.bestContinuations.begin(); i != curr.bestContinuations.end(); i++) {
1700  if (*i != 0 && *i != veh.getLane()) {
1701  nextLane = *i;
1702  break;
1703  }
1704  }
1705  assert(nextLane != 0);
1706  // add all lengths remaining internal lanes of current continuations until nextLane
1707  const MSLink* link = MSLinkContHelper::getConnectingLink(*veh.getLane(), *nextLane);
1708  roundaboutDistanceAheadNeigh += link->getInternalLengthsAfter();
1709  }
1710  }
1711 #endif
1712  // add roundabout distance from neigh.lane on
1713  roundaboutDistanceAheadNeigh += distanceAlongNextRoundabout(neighPosition, neigh.lane, neigh.bestContinuations);
1714 
1715 #ifdef DEBUG_WANTS_CHANGE
1716  if (DEBUG_COND) {
1717  std::cout << "roundaboutDistanceAhead = " << roundaboutDistanceAhead
1718  << " roundaboutDistanceAheadNeigh = " << roundaboutDistanceAheadNeigh
1719  << "\n";
1720  }
1721 #endif
1722 
1723  // count the number of roundabout edges ahead to determine whether
1724  // special LC behavior is required (promoting the use of the inner lane, mainly)
1725  roundaboutEdgesAhead = 0;
1726  for (std::vector<MSLane*>::const_iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) {
1727  const MSLane* lane = *it;
1728  if (lane != 0 && lane->getEdge().isRoundabout()) {
1729  roundaboutEdgesAhead += 1;
1730  } else if (roundaboutEdgesAhead > 0) {
1731  // only check the next roundabout
1732  break;
1733  }
1734  }
1735  roundaboutEdgesAheadNeigh = 0;
1736  for (std::vector<MSLane*>::const_iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) {
1737  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
1738  roundaboutEdgesAheadNeigh += 1;
1739  } else if (roundaboutEdgesAheadNeigh > 0) {
1740  // only check the next roundabout
1741  break;
1742  }
1743  }
1744  return;
1745 }
1746 
1747 
1748 SUMOReal
1749 MSLCM_LC2013::roundaboutDistBonus(SUMOReal roundaboutDistAhead, int roundaboutEdgesAhead) const {
1750  // NOTE: Currently there are two variants, one taking into account only the number
1751  // of upcoming non-internal roundabout edges and adding ROUNDABOUT_DIST_BONUS per upcoming edge except the first.
1752  // Another variant uses the actual distance and multiplies it by a factor ROUNDABOUT_DIST_FACTOR.
1753  // Currently, the update rule decides which variant to take (because the second was experimentally implemented
1754  // in the ballistic branch (ticket860)). Both variants may be combined in future. Refs. #2576
1756  if (roundaboutEdgesAhead > 1) {
1757  // Here we add a bonus length for each upcoming roundabout edge to the distance.
1758  // XXX: That becomes problematic, if the vehicle enters the last round about edge,
1759  // realizes suddenly that the change is very urgent and finds itself with very
1760  // few space to complete the urgent strategic change frequently leading to
1761  // a hang up on the inner lane.
1762  return roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS * myCooperativeParam;
1763  } else {
1764  return 0.;
1765  }
1766  } else {
1767  // This weighs the roundabout edges' distance with a larger factor
1768  if (roundaboutDistAhead > ROUNDABOUT_DIST_TRESH) {
1769  return (roundaboutDistAhead - ROUNDABOUT_DIST_TRESH) * (ROUNDABOUT_DIST_FACTOR - 1.);
1770  } else {
1771  return 0.;
1772  }
1773  }
1774 }
1775 
1776 
1777 SUMOReal
1778 MSLCM_LC2013::distanceAlongNextRoundabout(SUMOReal position, const MSLane* initialLane, const std::vector<MSLane*>& continuationLanes) {
1779  for (std::vector<MSLane*>::const_iterator i = continuationLanes.begin(); i != continuationLanes.end(); i++) {
1780  assert((*i) == 0 || (*i)->getEdge().getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL);
1781  }
1782 
1783  // We start with the current edge.
1784  bool encounteredRoundabout = false;
1785  SUMOReal roundaboutDistanceAhead = 0.;
1786 
1787  // set an iterator to the first non-zero entry of continuationLanes
1788  std::vector<MSLane*>::const_iterator j = continuationLanes.begin();
1789  while (j != continuationLanes.end() && *j == 0) {
1790  ++j;
1791  }
1792 
1793  // differentiate possible situations
1794  if (j == continuationLanes.end()) {
1795  // continuations end here
1796  assert(initialLane == 0);
1797  return 0.;
1798  } else if (initialLane == 0) {
1799  // NOTE: this may occur when calling distanceAlongNextRoundabout() with neigh.lane in _wantsChange().
1800  // In that case, the possible internal lengths have been taken into account in _wantsChange().
1801  // Thus we set initialLane to the first non-zero lane in continuationLanes
1802  initialLane = *j;
1803  } else if (!initialLane->isInternal() && initialLane != *j) {
1804  // this may occur during opposite direction driving where the initial Lane
1805  // is the reverse lane of *j. This should not happen on a roundabout! Therefore we can skip initialLane.
1806  assert(!initialLane->getEdge().isRoundabout());
1807  initialLane = *j;
1808  } else if (initialLane->getEdge().isRoundabout()) {
1809  // initial lane is on roundabout
1810  assert(position >= 0. && position <= initialLane->getLength());
1811  if (!initialLane->isInternal()) {
1812  assert(initialLane == *j);
1813  roundaboutDistanceAhead += initialLane->getLength() - position;
1814  if (j + 1 == continuationLanes.end() || *(j + 1) == 0 || !(*(j + 1))->getEdge().isRoundabout()) {
1815  // following connection is not part of the roundabout
1816  } else {
1817  // add internal lengths
1818  const MSLane* nextLane = *(j + 1);
1819  const MSLink* link = MSLinkContHelper::getConnectingLink(*initialLane, *nextLane);
1820  assert(link != 0);
1821  roundaboutDistanceAhead += link->getInternalLengthsAfter();
1822  }
1823  j++;
1824  } else {
1825  // initialLane is an internal roundabout lane -> add length to roundaboutDistanceAhead
1826  roundaboutDistanceAhead += initialLane->getLength() - position;
1827  assert(initialLane->getLinkCont().size() == 1);
1828  roundaboutDistanceAhead += initialLane->getLinkCont()[0]->getInternalLengthsAfter();
1829  }
1830  }
1831 
1832  // treat lanes beyond the initial one
1833  for (std::vector<MSLane*>::const_iterator it = j; it != continuationLanes.end(); ++it) {
1834  const MSLane* lane = *it;
1835  assert(lane != 0); // possible leading NULL lanes in continuationLanes were treated above
1836  if (lane->getEdge().isRoundabout()) {
1837  encounteredRoundabout = true;
1838  // add roundabout lane length
1839  roundaboutDistanceAhead += lane->getLength();
1840 
1841  // since bestContinuations contains no internal edges
1842  // add consecutive connection lengths if it is part of the route and the
1843  // consecutive edge is on the roundabout as well
1844  if (it + 1 != continuationLanes.end() && *(it + 1) != 0 && (*(it + 1))->getEdge().isRoundabout()) {
1845  // find corresponding link for the current lane
1846  const MSLink* link = MSLinkContHelper::getConnectingLink(*lane, **(it + 1));
1847  assert(link != 0);
1848  SUMOReal linkLength = link->getInternalLengthsAfter();
1849  roundaboutDistanceAhead += linkLength;
1850  }
1851  } else if (encounteredRoundabout) {
1852  // only check the next roundabout
1853  break;
1854  }
1855  }
1856  return roundaboutDistanceAhead;
1857 }
1858 
1859 
1860 
1861 int
1863  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1864  if ((*blocked) != 0) {
1865  SUMOReal gap = (*blocked)->getPositionOnLane() - (*blocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1866 #ifdef DEBUG_SLOW_DOWN
1867  if (DEBUG_COND) {
1868  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1869  << " veh=" << myVehicle.getID()
1870  << " blocked=" << Named::getIDSecure(*blocked)
1871  << " gap=" << gap
1872  << "\n";
1873  }
1874 #endif
1875  if (gap > POSITION_EPS) {
1876  //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1877  // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1878 
1880  //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1881  ) {
1882  if ((*blocked)->getSpeed() < SUMO_const_haltingSpeed) {
1883  state |= LCA_AMBACKBLOCKER_STANDING;
1884  } else {
1885  state |= LCA_AMBACKBLOCKER;
1886  }
1889  (SUMOReal)(gap - POSITION_EPS), (*blocked)->getSpeed(),
1890  (*blocked)->getCarFollowModel().getMaxDecel()));
1891 
1892  //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1893 #ifdef DEBUG_SLOW_DOWN
1894  if (DEBUG_COND) {
1895  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1896  << " veh=" << myVehicle.getID()
1897  << " slowing down for"
1898  << " blocked=" << Named::getIDSecure(*blocked)
1899  << " helpSpeed=" << myVSafes.back()
1900  << "\n";
1901  }
1902 #endif
1903  } /* else {
1904  // experimental else-branch...
1905  state |= LCA_AMBACKBLOCKER;
1906  myVSafes.push_back(myCarFollowModel.followSpeed(
1907  &myVehicle, myVehicle.getSpeed(),
1908  (SUMOReal)(gap - POSITION_EPS), (*blocked)->getSpeed(),
1909  (*blocked)->getCarFollowModel().getMaxDecel()));
1910  }*/
1911  }
1912  }
1913  return state;
1914 }
1915 
1916 
1917 void
1918 MSLCM_LC2013::saveBlockerLength(MSVehicle* blocker, int lcaCounter) {
1919 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
1920  if (DEBUG_COND) {
1921  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1922  << " veh=" << myVehicle.getID()
1923  << " saveBlockerLength blocker=" << Named::getIDSecure(blocker)
1924  << " bState=" << (blocker == 0 ? "None" : toString(blocker->getLaneChangeModel().getOwnState()))
1925  << "\n";
1926  }
1927 #endif
1928  if (blocker != 0 && (blocker->getLaneChangeModel().getOwnState() & lcaCounter) != 0) {
1929  // is there enough space in front of us for the blocker?
1932  if (blocker->getVehicleType().getLengthWithGap() <= potential) {
1933  // save at least his length in myLeadingBlockerLength
1935 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
1936  if (DEBUG_COND) {
1937  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1938  << " veh=" << myVehicle.getID()
1939  << " blocker=" << Named::getIDSecure(blocker)
1940  << " saving myLeadingBlockerLength=" << myLeadingBlockerLength
1941  << "\n";
1942  }
1943 #endif
1944  } else {
1945  // we cannot save enough space for the blocker. It needs to save
1946  // space for ego instead
1947 #ifdef DEBUG_SAVE_BLOCKER_LENGTH
1948  if (DEBUG_COND) {
1949  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1950  << " veh=" << myVehicle.getID()
1951  << " blocker=" << Named::getIDSecure(blocker)
1952  << " cannot save space=" << blocker->getVehicleType().getLengthWithGap()
1953  << " potential=" << potential
1954  << "\n";
1955  }
1956 #endif
1958  }
1959  }
1960 }
1961 /****************************************************************************/
1962 
SUMOReal getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:480
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:82
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
#define MIN_FALLBEHIND
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
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:487
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive...
Definition: MSVehicle.h:681
const SUMOReal myChangeProbThresholdRight
Definition: MSLCM_LC2013.h:254
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)
#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
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
int getBestLaneOffset() const
returns the current offset from the best lane
Definition: MSVehicle.cpp:3077
Wants go to the right.
SUMOReal getLength() const
Get vehicle&#39;s length [m].
bool isRoundabout() const
Definition: MSEdge.h:638
SUMOReal getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:472
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:75
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
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
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...
const std::string & getID() const
Returns the id.
Definition: Named.h:66
std::vector< SUMOReal > myVSafes
Definition: MSLCM_LC2013.h:240
#define TS
Definition: SUMOTime.h:52
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:673
const SUMOReal myCooperativeParam
Definition: MSLCM_LC2013.h:246
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:63
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
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
#define abs(a)
Definition: polyfonts.c:67
bool hasLaneChanger() const
Definition: MSEdge.h:650
#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:2702
#define SIMTIME
Definition: SUMOTime.h:70
SUMOReal changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Definition: MSVehicle.cpp:396
Needs to stay on the current lane.
const SUMOReal myStrategicParam
Definition: MSLCM_LC2013.h:245
#define ROUNDABOUT_DIST_BONUS
#define DEBUG_COND
bool isInternal() const
Definition: MSLane.cpp:1410
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
bool debugVehicle() const
whether the current vehicles shall be debugged
A class responsible for exchanging messages between cars involved in lane-change interaction.
bool currentDistDisallows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_LC2013.h:213
MSLane * lane
The described lane.
Definition: MSVehicle.h:671
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:758
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 roundaboutDistBonus(SUMOReal roundaboutDistAhead, int roundaboutEdgesAhead) const
Computes the artificial bonus distance for roundabout lanes this additional distance reduces the sens...
The action is urgent (to be defined by lc-model)
SUMOReal myLeadingBlockerLength
Definition: MSLCM_LC2013.h:233
SUMOReal getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:556
#define CUT_IN_LEFT_SPEED_THRESHOLD
SUMOReal myLookAheadSpeed
Definition: MSLCM_LC2013.h:238
#define LOOK_AHEAD_SPEED_MEMORY
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
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:254
SUMOReal getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:374
T MIN2(T a, T b)
Definition: StdDefs.h:69
#define RELGAIN_NORMALIZATION_MIN_SPEED
The action is needed to follow the route (navigational lc)
#define POSITION_EPS
Definition: config.h:187
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:669
SUMOReal getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:193
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:249
int myOwnState
The current state of the vehicle.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
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
SUMOReal informLeader(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, SUMOReal > &neighLead, SUMOReal remainingSeconds)
SUMOReal getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition: MSLane.cpp:2041
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
virtual void saveBlockerLength(SUMOReal length)
reserve space at the end of the lane to avoid dead locks
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.
SUMOReal getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:406
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:3690
#define JAM_FACTOR
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.
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
SUMOReal occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:677
std::vector< MSLane * > bestContinuations
Consecutive lane that can be followed without a lane change (contribute to length and occupation) ...
Definition: MSVehicle.h:685
SUMOReal getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
#define URGENCY
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) ...
const SUMOReal SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:57
virtual ~MSLCM_LC2013()
#define INVALID_SPEED
Definition: MSCFModel.h:40
#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
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
The action is due to a TraCI request.
SUMOReal myLeftSpace
Definition: MSLCM_LC2013.h:234
#define SUMOReal
Definition: config.h:213
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:63
#define NUMERICAL_EPS
Definition: config.h:160
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
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1003
SUMOReal _patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel &cfModel)
#define LOOK_AHEAD_MIN_SPEED
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1512
#define LCA_RIGHT_IMPATIENCE
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:3714
The edge is an internal edge.
Definition: MSEdge.h:97
void * inform(void *info, MSVehicle *sender)
const std::string & getID() const
Returns the name of the vehicle.
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
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:441
SUMOReal getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation...
Definition: MSVehicle.h:497
Interface for lane-change models.
SUMOReal getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
#define HELP_DECEL_FACTOR
#define TURN_LANE_DIST
#define KEEP_RIGHT_TIME
bool congested() const
Definition: MSVehicle.h:596