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 
bool debugVehicle() const
whether the current vehicles shall be debugged
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 getMinGap() const
Get the free space in front of vehicles of this class.
void saveBlockerLength(MSVehicle *blocker, int lcaCounter)
save space for vehicles which need to counter-lane-change
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:476
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:582
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
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()
#define min(a, b)
Definition: polyfonts.c:66
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:796
#define MIN_FALLBEHIND
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel) const =0
Computes the vehicle&#39;s follow speed (no dawdling)
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
#define LOOK_FORWARD_RIGHT
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition: MSLane.cpp:2106
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
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
bool congested() const
Definition: MSVehicle.h:624
double myKeepRightProbability
Definition: MSLCM_LC2013.h:236
#define KEEP_RIGHT_ACCEPTANCE
The car-following model abstraction.
Definition: MSCFModel.h:60
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
#define MAX_ONRAMP_LENGTH
double myLookAheadSpeed
Definition: MSLCM_LC2013.h:243
Wants go to the right.
bool isAccelLane() const
return whether this lane is an acceleration lane
Definition: MSLane.h:436
double myStrategicParam
Definition: MSLCM_LC2013.h: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
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:484
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:158
T MAX2(T a, T b)
Definition: StdDefs.h:70
double getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
double _patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel)
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:59
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:375
bool isInternal() const
Definition: MSLane.cpp:1497
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
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:257
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
#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 getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:2713
Needs to stay on the current lane.
double getImpatience() const
Returns this vehicles impatience.
const LaneChangeModel myModel
the type of this model
#define ROUNDABOUT_DIST_BONUS
#define DEBUG_COND
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
A class responsible for exchanging messages between cars involved in lane-change interaction.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
static double overtakeDistance(const MSVehicle *follower, const MSVehicle *leader, const double gap, double followerSpeed=INVALID_SPEED, double leaderSpeed=INVALID_SPEED)
MSLane * lane
The described lane.
Definition: MSVehicle.h:704
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
double roundaboutDistBonus(double roundaboutDistAhead, int roundaboutEdgesAhead) const
Computes the artificial bonus distance for roundabout lanes this additional distance reduces the sens...
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
The action is urgent (to be defined by lc-model)
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key ...
const double myChangeProbThresholdLeft
Definition: MSLCM_LC2013.h:262
double getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
#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
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1115
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
int slowDownForBlocked(MSVehicle **blocked, int state)
compute useful slowdowns for blocked vehicles
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
bool isRoundabout() const
Definition: MSEdge.h:636
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:176
A structure representing the best lanes for continuing the current route starting at &#39;lane&#39;...
Definition: MSVehicle.h:702
int myOwnState
The current state of the vehicle.
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:570
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
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation...
Definition: MSVehicle.h:498
double getLength() const
Get vehicle&#39;s length [m].
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:249
double getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:193
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 occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:710
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
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
static double _2double(const E *const data)
converts a char-type array into the double value described by it
Definition: TplConvert.h:297
#define URGENCY
double myCooperativeParam
Definition: MSLCM_LC2013.h:251
virtual ~MSLCM_LC2013()
#define INVALID_SPEED
Definition: MSCFModel.h:40
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:407
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:462
virtual double stopSpeed(const MSVehicle *const veh, const double speed, double gap) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h: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:152
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)
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Definition: MSVehicle.cpp:406
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1597
#define LOOK_AHEAD_MIN_SPEED
#define LCA_RIGHT_IMPATIENCE
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:488
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:4017
The edge is an internal edge.
Definition: MSEdge.h:97
void * inform(void *info, MSVehicle *sender)
blocker by follower
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
const MSCFModel & myCarFollowModel
The vehicle&#39;s car following model.
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
Interface for lane-change models.
int getBestLaneOffset() const
Definition: MSVehicle.cpp:3305
bool hasLaneChanger() const
Definition: MSEdge.h:648
#define HELP_DECEL_FACTOR
const std::string & getID() const
Returns the name of the vehicle.
#define TURN_LANE_DIST
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:442
#define KEEP_RIGHT_TIME