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