SUMO - Simulation of Urban MObility
MSLCM_JE2013.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // A lane change model developed by J. Erdmann
10 // based on the model of D. Krajzewicz developed between 2004 and 2011 (MSLCM_DK2004)
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2013-2014 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <iostream>
36 #include "MSEdge.h"
37 #include "MSLane.h"
38 #include "MSNet.h"
39 #include "MSLCM_JE2013.h"
40 
41 #ifdef CHECK_MEMORY_LEAKS
42 #include <foreign/nvwa/debug_new.h>
43 #endif // CHECK_MEMORY_LEAKS
44 
45 //#define DEBUG_VEHICLE_GUI_SELECTION 1
46 #ifdef DEBUG_VEHICLE_GUI_SELECTION
48 #include <guisim/GUIVehicle.h>
49 #include <guisim/GUILane.h>
50 #endif
51 
52 
53 
54 // ===========================================================================
55 // variable definitions
56 // ===========================================================================
57 // 80km/h will be the threshold for dividing between long/short foresight
58 #define LOOK_FORWARD_SPEED_DIVIDER (SUMOReal)14.
59 
60 // VARIANT_1 (lf*2)
61 //#define LOOK_FORWARD_FAR 30.
62 //#define LOOK_FORWARD_NEAR 10.
63 
64 #define LOOK_FORWARD_RIGHT (SUMOReal)10.
65 #define LOOK_FORWARD_LEFT (SUMOReal)20.
66 
67 #define JAM_FACTOR (SUMOReal)1.
68 //#define JAM_FACTOR 2. // VARIANT_8 (makes vehicles more focused but also more "selfish")
69 
70 #define LCA_RIGHT_IMPATIENCE (SUMOReal)-1.
71 #define CUT_IN_LEFT_SPEED_THRESHOLD (SUMOReal)27.
72 
73 #define LOOK_AHEAD_MIN_SPEED (SUMOReal)0.0
74 #define LOOK_AHEAD_SPEED_MEMORY (SUMOReal)0.9
75 #define LOOK_AHEAD_SPEED_DECREMENT 6.
76 
77 #define HELP_DECEL_FACTOR (SUMOReal)1.0
78 
79 #define HELP_OVERTAKE (SUMOReal)(10.0 / 3.6)
80 #define MIN_FALLBEHIND (SUMOReal)(14.0 / 3.6)
81 
82 #define KEEP_RIGHT_HEADWAY (SUMOReal)2.0
83 
84 #define URGENCY (SUMOReal)2.0
85 
86 #define ROUNDABOUT_DIST_BONUS (SUMOReal)100.0
87 
88 #define CHANGE_PROB_THRESHOLD_RIGHT (SUMOReal)2.0
89 #define CHANGE_PROB_THRESHOLD_LEFT (SUMOReal)0.2
90 #define KEEP_RIGHT_TIME (SUMOReal)5.0 // the number of seconds after which a vehicle should move to the right lane
91 #define KEEP_RIGHT_ACCEPTANCE (SUMOReal)2.0 // calibration factor for determining the desire to keep right
92 
93 #define RELGAIN_NORMALIZATION_MIN_SPEED (SUMOReal)10.0
94 
95 #define TURN_LANE_DIST (SUMOReal)200.0 // the distance at which a lane leading elsewhere is considered to be a turn-lane that must be avoided
96 
97 //#define DEBUG_COND (myVehicle.getID() == "pkw22806" || myVehicle.getID() == "pkw22823")
98 //#define DEBUG_COND (myVehicle.getID() == "pkw150478" || myVehicle.getID() == "pkw150494" || myVehicle.getID() == "pkw150289")
99 //#define DEBUG_COND (myVehicle.getID() == "A" || myVehicle.getID() == "B") // fail change to left
100 //#define DEBUG_COND (myVehicle.getID() == "Costa_12_13") // test stops_overtaking
101 #define DEBUG_COND false
102 
103 // debug function
104 std::string
105 tryID(const MSVehicle* v) {
106  return v == 0 ? "NULL" : v->getID();
107 }
108 
109 
110 // ===========================================================================
111 // member method definitions
112 // ===========================================================================
115  mySpeedGainProbability(0),
116  myKeepRightProbability(0),
117  myLeadingBlockerLength(0),
118  myLeftSpace(0),
119  myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED)
120 {}
121 
123  changed();
124 }
125 
126 
127 int
129  int laneOffset,
131  int blocked,
132  const std::pair<MSVehicle*, SUMOReal>& leader,
133  const std::pair<MSVehicle*, SUMOReal>& neighLead,
134  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
135  const MSLane& neighLane,
136  const std::vector<MSVehicle::LaneQ>& preb,
137  MSVehicle** lastBlocked,
138  MSVehicle** firstBlocked) {
140 
141  if (gDebugFlag2) {
142  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
143  << " veh=" << myVehicle.getID()
144  << " lane=" << myVehicle.getLane()->getID()
145  << " pos=" << myVehicle.getPositionOnLane()
146  << " speed=" << myVehicle.getSpeed()
147  << " considerChangeTo=" << (laneOffset == -1 ? "right" : "left")
148  << "\n";
149  }
150 
151  const int result = _wantsChange(laneOffset, msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked);
152  if (gDebugFlag2) {
153  if (result & LCA_WANTS_LANECHANGE) {
154  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
155  << " veh=" << myVehicle.getID()
156  << " wantsChangeTo=" << (laneOffset == -1 ? "right" : "left")
157  << ((result & LCA_URGENT) ? " (urgent)" : "")
158  << ((result & LCA_CHANGE_TO_HELP) ? " (toHelp)" : "")
159  << ((result & LCA_STRATEGIC) ? " (strat)" : "")
160  << ((result & LCA_COOPERATIVE) ? " (coop)" : "")
161  << ((result & LCA_SPEEDGAIN) ? " (speed)" : "")
162  << ((result & LCA_KEEPRIGHT) ? " (keepright)" : "")
163  << ((result & LCA_TRACI) ? " (traci)" : "")
164  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
165  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
166  << "\n";
167  }
168  }
169  gDebugFlag2 = false;
170  return result;
171 }
172 
173 
174 SUMOReal
175 MSLCM_JE2013::patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
177 
178  const SUMOReal newSpeed = _patchSpeed(min, wanted, max, cfModel);
179  if (gDebugFlag1) {
180  const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
181  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
182  << " veh=" << myVehicle.getID()
183  << " lane=" << myVehicle.getLane()->getID()
184  << " pos=" << myVehicle.getPositionOnLane()
185  << " v=" << myVehicle.getSpeed()
186  << " wanted=" << wanted
187  << patched
188  << "\n";
189  }
190  gDebugFlag1 = false;
191  return newSpeed;
192 }
193 
194 
195 SUMOReal
196 MSLCM_JE2013::_patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
197 
198  const SUMOReal time = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
199 
200  int state = myOwnState;
201 
202  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
203  SUMOReal MAGIC_offset = 1.;
204  // if we want to change and have a blocking leader and there is enough room for him in front of us
205  if (myLeadingBlockerLength != 0) {
207  if (gDebugFlag1) {
208  std::cout << time << " veh=" << myVehicle.getID() << " myLeadingBlockerLength=" << myLeadingBlockerLength << " space=" << space << "\n";
209  }
210  if (space > 0) {
211  // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
212  SUMOReal safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space);
213  // if we are approaching this place
214  if (safe < wanted) {
215  // return this speed as the speed to use
216  if (gDebugFlag1) {
217  std::cout << time << " veh=" << myVehicle.getID() << " slowing down for leading blocker" << (safe + NUMERICAL_EPS < min ? " (not enough)" : "") << "\n";
218  }
219  return MAX2(min, safe);
220  }
221  }
222  }
223 
224  SUMOReal nVSafe = wanted;
225  bool gotOne = false;
226  for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
227  SUMOReal v = (*i);
228  if (v >= min && v <= max) {
229  nVSafe = MIN2(v, nVSafe);
230  gotOne = true;
231  if (gDebugFlag1) {
232  std::cout << time << " veh=" << myVehicle.getID() << " got nVSafe=" << nVSafe << "\n";
233  }
234  } else {
235  if (v < min) {
236  if (gDebugFlag1) {
237  std::cout << time << " veh=" << myVehicle.getID() << " ignoring low nVSafe=" << v << " min=" << min << "\n";
238  }
239  } else {
240  if (gDebugFlag1) {
241  std::cout << time << " veh=" << myVehicle.getID() << " ignoring high nVSafe=" << v << " max=" << max << "\n";
242  }
243  }
244  }
245  }
246 
247  if (gotOne && !myDontBrake) {
248  if (gDebugFlag1) {
249  std::cout << time << " veh=" << myVehicle.getID() << " got vSafe\n";
250  }
251  return nVSafe;
252  }
253 
254  // check whether the vehicle is blocked
255  if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) != 0) {
256  if ((state & LCA_STRATEGIC) != 0) {
257  // necessary decelerations are controlled via vSafe. If there are
258  // none it means we should speed up
259  if (gDebugFlag1) {
260  std::cout << time << " veh=" << myVehicle.getID() << " LCA_WANTS_LANECHANGE (strat, no vSafe)\n";
261  }
262  return (max + wanted) / (SUMOReal) 2.0;
263  } else if ((state & LCA_COOPERATIVE) != 0) {
264  // only minor adjustments in speed should be done
265  if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
266  if (gDebugFlag1) {
267  std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_LEADER (coop)\n";
268  }
269  return (min + wanted) / (SUMOReal) 2.0;
270  }
271  if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
272  if (gDebugFlag1) {
273  std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER (coop)\n";
274  }
275  return (max + wanted) / (SUMOReal) 2.0;
276  }
277  //} else { // VARIANT_16
278  // // only accelerations should be performed
279  // if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
280  // if (gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER\n";
281  // return (max + wanted) / (SUMOReal) 2.0;
282  // }
283  }
284  }
285 
286  /*
287  // decelerate if being a blocking follower
288  // (and does not have to change lanes)
289  if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
290  if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
291  if (gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER (standing)\n";
292  return 0;
293  }
294  if (gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER\n";
295 
296  //return min; // VARIANT_3 (brakeStrong)
297  return (min + wanted) / (SUMOReal) 2.0;
298  }
299  if ((state & LCA_AMBACKBLOCKER) != 0) {
300  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
301  if (gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER (standing)\n";
302  //return min; VARIANT_9 (backBlockVSafe)
303  return nVSafe;
304  }
305  }
306  if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
307  if (gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER_STANDING\n";
308  //return min;
309  return nVSafe;
310  }
311  */
312 
313  // accelerate if being a blocking leader or blocking follower not able to brake
314  // (and does not have to change lanes)
315  if ((state & LCA_AMBLOCKINGLEADER) != 0) {
316  if (gDebugFlag1) {
317  std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGLEADER\n";
318  }
319  return (max + wanted) / (SUMOReal) 2.0;
320  }
321 
322  if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
323  if (gDebugFlag1) {
324  std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER_DONTBRAKE\n";
325  }
326  /*
327  // VARIANT_4 (dontbrake)
328  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
329  return wanted;
330  }
331  return (min + wanted) / (SUMOReal) 2.0;
332  */
333  }
334  if (myVehicle.getLane()->getEdge().getLanes().size() == 1) {
335  // remove chaning information if on a road with a single lane
336  changed();
337  }
338  return wanted;
339 }
340 
341 
342 void*
343 MSLCM_JE2013::inform(void* info, MSVehicle* sender) {
344  Info* pinfo = (Info*) info;
345  if (pinfo->first >= 0) {
346  myVSafes.push_back(pinfo->first);
347  }
348  //myOwnState &= 0xffffffff; // reset all bits of MyLCAEnum but only those
349  myOwnState |= pinfo->second;
350  if (gDebugFlag2 || DEBUG_COND) {
351  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
352  << " veh=" << myVehicle.getID()
353  << " informedBy=" << sender->getID()
354  << " info=" << pinfo->second
355  << " vSafe=" << pinfo->first
356  << "\n";
357  }
358  delete pinfo;
359  return (void*) true;
360 }
361 
362 
363 SUMOReal
365  int blocked,
366  int dir,
367  const std::pair<MSVehicle*, SUMOReal>& neighLead,
368  SUMOReal remainingSeconds) {
369  SUMOReal plannedSpeed = MIN2(myVehicle.getSpeed(),
371  for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
372  SUMOReal v = (*i);
374  plannedSpeed = MIN2(plannedSpeed, v);
375  }
376  }
377  if (gDebugFlag2) {
378  std::cout << " informLeader speed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
379  }
380 
381  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
382  assert(neighLead.first != 0);
383  MSVehicle* nv = neighLead.first;
384  if (gDebugFlag2) std::cout << " blocked by leader nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
386  // decide whether we want to overtake the leader or follow it
387  const SUMOReal dv = plannedSpeed - nv->getSpeed();
388  const SUMOReal overtakeDist = (neighLead.second // drive to back of follower
389  + nv->getVehicleType().getLengthWithGap() // drive to front of follower
390  + myVehicle.getVehicleType().getLength() // ego back reaches follower front
391  + nv->getCarFollowModel().getSecureGap( // save gap to follower
393 
394  if (dv < 0
395  // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft)
396  || (dir == LCA_MLEFT && !myVehicle.congested())
397  // not enough space to overtake?
398  || myLeftSpace < overtakeDist
399  // not enough time to overtake?
400  || dv * remainingSeconds < overtakeDist) {
401  // cannot overtake
402  msgPass.informNeighLeader(new Info(-1, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
403  // slow down smoothly to follow leader
404  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
405  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
406  if (targetSpeed < myVehicle.getSpeed()) {
407  // slow down smoothly to follow leader
409  MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds)));
410  const SUMOReal nextSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() - decel);
411  if (gDebugFlag2) {
412  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
413  << " cannot overtake leader nv=" << nv->getID()
414  << " dv=" << dv
415  << " remainingSeconds=" << remainingSeconds
416  << " targetSpeed=" << targetSpeed
417  << " nextSpeed=" << nextSpeed
418  << "\n";
419  }
420  myVSafes.push_back(nextSpeed);
421  return nextSpeed;
422  } else {
423  // leader is fast enough anyway
424  if (gDebugFlag2) {
425  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
426  << " cannot overtake fast leader nv=" << nv->getID()
427  << " dv=" << dv
428  << " remainingSeconds=" << remainingSeconds
429  << " targetSpeed=" << targetSpeed
430  << "\n";
431  }
432  myVSafes.push_back(targetSpeed);
433  return plannedSpeed;
434  }
435  } else {
436  if (gDebugFlag2) {
437  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
438  << " wants to overtake leader nv=" << nv->getID()
439  << " dv=" << dv
440  << " remainingSeconds=" << remainingSeconds
441  << " currentGap=" << neighLead.second
443  << "\n";
444  }
445  // overtaking, leader should not accelerate
446  msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
447  return -1;
448  }
449  } else if (neighLead.first != 0) { // (remainUnblocked)
450  // we are not blocked now. make sure we stay far enough from the leader
451  MSVehicle* nv = neighLead.first;
452  const SUMOReal nextNVSpeed = nv->getSpeed() - HELP_OVERTAKE; // conservative
453  const SUMOReal dv = SPEED2DIST(myVehicle.getSpeed() - nextNVSpeed);
454  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
455  &myVehicle, myVehicle.getSpeed(), neighLead.second - dv, nextNVSpeed, nv->getCarFollowModel().getMaxDecel());
456  myVSafes.push_back(targetSpeed);
457  if (gDebugFlag2) {
458  std::cout << " not blocked by leader nv=" << nv->getID()
459  << " nvSpeed=" << nv->getSpeed()
460  << " gap=" << neighLead.second
461  << " nextGap=" << neighLead.second - dv
463  << " targetSpeed=" << targetSpeed
464  << "\n";
465  }
466  return MIN2(targetSpeed, plannedSpeed);
467  } else {
468  // not overtaking
469  return plannedSpeed;
470  }
471 }
472 
473 
474 void
476  int blocked,
477  int dir,
478  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
479  SUMOReal remainingSeconds,
480  SUMOReal plannedSpeed) {
481  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
482  assert(neighFollow.first != 0);
483  MSVehicle* nv = neighFollow.first;
484  if (gDebugFlag2) std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
486 
487  // are we fast enough to cut in without any help?
488  if (plannedSpeed - nv->getSpeed() >= HELP_OVERTAKE) {
489  const SUMOReal neededGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
490  if ((neededGap - neighFollow.second) / remainingSeconds < (plannedSpeed - nv->getSpeed())) {
491  if (gDebugFlag2) {
492  std::cout << " wants to cut in before nv=" << nv->getID() << " without any help neededGap=" << neededGap << "\n";
493  }
494  // follower might even accelerate but not to much
495  msgPass.informNeighFollower(new Info(plannedSpeed - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
496  return;
497  }
498  }
499  // decide whether we will request help to cut in before the follower or allow to be overtaken
500 
501  // PARAMETERS
502  // assume other vehicle will assume the equivalent of 1 second of
503  // maximum deceleration to help us (will probably be spread over
504  // multiple seconds)
505  // -----------
506  const SUMOReal helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR ;
507 
508  // change in the gap between ego and blocker over 1 second (not STEP!)
509  const SUMOReal neighNewSpeed = MAX2((SUMOReal)0, nv->getSpeed() - ACCEL2SPEED(helpDecel));
510  const SUMOReal neighNewSpeed1s = MAX2((SUMOReal)0, nv->getSpeed() - helpDecel);
511  const SUMOReal dv = plannedSpeed - neighNewSpeed1s;
512  // new gap between follower and self in case the follower does brake for 1s
513  const SUMOReal decelGap = neighFollow.second + dv;
514  const SUMOReal secureGap = nv->getCarFollowModel().getSecureGap(neighNewSpeed1s, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
515  if (gDebugFlag2) {
516  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
517  << " egoV=" << myVehicle.getSpeed()
518  << " egoNV=" << plannedSpeed
519  << " nvNewSpeed=" << neighNewSpeed
520  << " nvNewSpeed1s=" << neighNewSpeed1s
521  << " deltaGap=" << dv
522  << " decelGap=" << decelGap
523  << " secGap=" << secureGap
524  << "\n";
525  }
526  if (decelGap > 0 && decelGap >= secureGap) {
527  // if the blocking neighbor brakes it could actually help
528  // how hard does it actually need to be?
529  const SUMOReal vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
530  nv, nv->getSpeed(), neighFollow.second, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel()));
531  msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
532  if (gDebugFlag2) {
533  std::cout << " wants to cut in before nv=" << nv->getID() << "\n";
534  }
535  } else if (dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS)) {
536  // decelerating once is sufficient to open up a large enough gap in time
537  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
538  if (gDebugFlag2) {
539  std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
540  }
541  } else {
543  if (nv->getSpeed() > myVehicle.getSpeed() &&
545  || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
546  )) {
547  // let the follower slow down to increase the likelyhood that later vehicles will be slow enough to help
548  // follower should still be fast enough to open a gap
549  vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
550  if (gDebugFlag2) {
551  std::cout << " wants right follower to slow down a bit\n";
552  }
553  if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
554  if (gDebugFlag2) {
555  std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
556  }
557  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
558  return;
559  }
560  }
561  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
562  // this follower is supposed to overtake us. slow down smoothly to allow this
563  const SUMOReal overtakeDist = (neighFollow.second // follower reaches ego back
564  + myVehicle.getVehicleType().getLengthWithGap() // follower reaches ego front
565  + nv->getVehicleType().getLength() // follower back at ego front
566  + myVehicle.getCarFollowModel().getSecureGap( // follower has safe dist to ego
567  plannedSpeed, vhelp, nv->getCarFollowModel().getMaxDecel()));
568  // speed difference to create a sufficiently large gap
569  const SUMOReal needDV = overtakeDist / remainingSeconds;
570  // make sure the deceleration is not to strong
571  myVSafes.push_back(MAX2(vhelp - needDV, myVehicle.getSpeed() - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())));
572 
573  if (gDebugFlag2) {
574  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
575  << " veh=" << myVehicle.getID()
576  << " wants to be overtaken by=" << nv->getID()
577  << " overtakeDist=" << overtakeDist
578  << " vneigh=" << nv->getSpeed()
579  << " vhelp=" << vhelp
580  << " needDV=" << needDV
581  << " vsafe=" << myVSafes.back()
582  << "\n";
583  }
584  }
585  }
586 }
587 
588 
589 void
591  myOwnState = 0;
593  myLeftSpace = 0;
594  myVSafes.clear();
595  myDontBrake = false;
596  // truncate to work around numerical instability between different builds
597  mySpeedGainProbability = ceil(mySpeedGainProbability * 100000.0) * 0.00001;
598  myKeepRightProbability = ceil(myKeepRightProbability * 100000.0) * 0.00001;
599 }
600 
601 
602 void
604  myOwnState = 0;
608  if (myVehicle.getBestLaneOffset() == 0) {
609  // if we are not yet on our best lane there might still be unseen blockers
610  // (during patchSpeed)
612  myLeftSpace = 0;
613  }
615  myVSafes.clear();
616  myDontBrake = false;
617 }
618 
619 
620 int
622  int laneOffset,
624  int blocked,
625  const std::pair<MSVehicle*, SUMOReal>& leader,
626  const std::pair<MSVehicle*, SUMOReal>& neighLead,
627  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
628  const MSLane& neighLane,
629  const std::vector<MSVehicle::LaneQ>& preb,
630  MSVehicle** lastBlocked,
631  MSVehicle** firstBlocked) {
632  assert(laneOffset == 1 || laneOffset == -1);
633  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
634  // compute bestLaneOffset
635  MSVehicle::LaneQ curr, neigh, best;
636  int bestLaneOffset = 0;
637  SUMOReal currentDist = 0;
638  SUMOReal neighDist = 0;
639  int currIdx = 0;
640  MSLane* prebLane = myVehicle.getLane();
641  if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
642  // internal edges are not kept inside the bestLanes structure
643  prebLane = prebLane->getLinkCont()[0]->getLane();
644  }
645  for (int p = 0; p < (int) preb.size(); ++p) {
646  if (preb[p].lane == prebLane && p + laneOffset >= 0) {
647  assert(p + laneOffset < (int)preb.size());
648  curr = preb[p];
649  neigh = preb[p + laneOffset];
650  currentDist = curr.length;
651  neighDist = neigh.length;
652  bestLaneOffset = curr.bestLaneOffset;
653  // VARIANT_13 (equalBest)
654  if (bestLaneOffset == 0 && preb[p + laneOffset].bestLaneOffset == 0) {
655  if (gDebugFlag2) {
656  std::cout << STEPS2TIME(currentTime)
657  << " veh=" << myVehicle.getID()
658  << " bestLaneOffsetOld=" << bestLaneOffset
659  << " bestLaneOffsetNew=" << laneOffset
660  << "\n";
661  }
662  bestLaneOffset = laneOffset;
663  }
664  best = preb[p + bestLaneOffset];
665  currIdx = p;
666  break;
667  }
668  }
669  // direction specific constants
670  const bool right = (laneOffset == -1);
671  const int lca = (right ? LCA_RIGHT : LCA_LEFT);
672  const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
673  const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
674  const int myLcaCounter = (right ? LCA_MLEFT : LCA_MRIGHT);
675  const bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
676  // keep information about being a leader/follower
677  int ret = (myOwnState & 0xffff0000);
678  int req = 0; // the request to change or stay
679 
680  // VARIANT_5 (disableAMBACKBLOCKER1)
681  /*
682  if (leader.first != 0
683  && (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0
684  && (leader.first->getLaneChangeModel().getOwnState() & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
685 
686  myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE);
687  if (myVehicle.getSpeed() > SUMO_const_haltingSpeed) {
688  myOwnState |= LCA_AMBACKBLOCKER;
689  } else {
690  ret |= LCA_AMBACKBLOCKER;
691  myDontBrake = true;
692  }
693  }
694  */
695 
696  if (gDebugFlag2) {
697  std::cout << STEPS2TIME(currentTime)
698  << " veh=" << myVehicle.getID()
699  << " firstBlocked=" << tryID(*firstBlocked)
700  << " lastBlocked=" << tryID(*lastBlocked)
701  << " neighLead=" << tryID(neighLead.first)
702  << " neighLeadGap=" << neighLead.second
703  << " neighFollow=" << tryID(neighFollow.first)
704  << " neighFollowGap=" << neighFollow.second
705  << "\n";
706  }
707 
708  ret = slowDownForBlocked(lastBlocked, ret);
709  // VARIANT_14 (furtherBlock)
710  if (lastBlocked != firstBlocked) {
711  ret = slowDownForBlocked(firstBlocked, ret);
712  }
713 
714 
715  // we try to estimate the distance which is necessary to get on a lane
716  // we have to get on in order to keep our route
717  // we assume we need something that depends on our velocity
718  // and compare this with the free space on our wished lane
719  //
720  // if the free space is somehow less than the space we need, we should
721  // definitely try to get to the desired lane
722  //
723  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
724  // lookAheadDistance:
725  // we do not want the lookahead distance to change all the time so we discrectize the speed a bit
726 
727  // VARIANT_18 (laHyst)
730  } else {
733  }
734  //myLookAheadSpeed = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
735 
736  //SUMOReal laDist = laSpeed > LOOK_FORWARD_SPEED_DIVIDER
737  // ? laSpeed * LOOK_FORWARD_FAR
738  // : laSpeed * LOOK_FORWARD_NEAR;
740  laDist += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.;
741  // free space that is available for changing
742  //const SUMOReal neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
743  // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
744  // best.lane->getSpeedLimit());
745  // @note: while this lets vehicles change earlier into the correct direction
746  // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
747 
748  // VARIANT_15 (insideRoundabout)
749  int roundaboutEdgesAhead = 0;
750  for (std::vector<MSLane*>::iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) {
751  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
752  roundaboutEdgesAhead += 1;
753  } else if (roundaboutEdgesAhead > 0) {
754  // only check the next roundabout
755  break;
756  }
757  }
758  int roundaboutEdgesAheadNeigh = 0;
759  for (std::vector<MSLane*>::iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) {
760  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
761  roundaboutEdgesAheadNeigh += 1;
762  } else if (roundaboutEdgesAheadNeigh > 0) {
763  // only check the next roundabout
764  break;
765  }
766  }
767  if (roundaboutEdgesAhead > 1) {
768  currentDist += roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS;
769  neighDist += roundaboutEdgesAheadNeigh * ROUNDABOUT_DIST_BONUS;
770  }
771  if (roundaboutEdgesAhead > 0) {
772  if (gDebugFlag2) {
773  std::cout << " roundaboutEdgesAhead=" << roundaboutEdgesAhead << " roundaboutEdgesAheadNeigh=" << roundaboutEdgesAheadNeigh << "\n";
774  }
775  }
776 
777  const SUMOReal usableDist = (currentDist - myVehicle.getPositionOnLane() - best.occupation * JAM_FACTOR);
778  //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
779  const SUMOReal maxJam = MAX2(preb[currIdx + laneOffset].occupation, preb[currIdx].occupation);
780  const SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
781 
782  if (gDebugFlag2) {
783  std::cout << STEPS2TIME(currentTime)
784  << " veh=" << myVehicle.getID()
785  << " laSpeed=" << myLookAheadSpeed
786  << " laDist=" << laDist
787  << " currentDist=" << currentDist
788  << " usableDist=" << usableDist
789  << " bestLaneOffset=" << bestLaneOffset
790  << " best.length=" << best.length
791  << " maxJam=" << maxJam
792  << " neighLeftPlace=" << neighLeftPlace
793  << "\n";
794  }
795 
796  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
797  && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
799  ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
800  } else {
801  // VARIANT_20 (noOvertakeRight)
802  if (!myAllowOvertakingRight && !right && !myVehicle.congested() && neighLead.first != 0) {
803  // check for slower leader on the left. we should not overtake but
804  // rather move left ourselves (unless congested)
805  MSVehicle* nv = neighLead.first;
806  if (nv->getSpeed() < myVehicle.getSpeed()) {
808  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel()));
809  if (nv->getSpeed() + 5 / 3.6 < myVehicle.getSpeed()) {
811  }
812  if (gDebugFlag2) {
813  std::cout << STEPS2TIME(currentTime)
814  << " avoid overtaking on the right nv=" << nv->getID()
815  << " nvSpeed=" << nv->getSpeed()
816  << " mySpeedGainProbability=" << mySpeedGainProbability
817  << " plannedSpeed=" << myVSafes.back()
818  << "\n";
819  }
820  }
821  }
822 
823  if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
824  // the opposite lane-changing direction should be done than the one examined herein
825  // we'll check whether we assume we could change anyhow and get back in time...
826  //
827  // this rule prevents the vehicle from moving in opposite direction of the best lane
828  // unless the way till the end where the vehicle has to be on the best lane
829  // is long enough
830  if (gDebugFlag2) {
831  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
832  }
833  ret = ret | LCA_STAY | LCA_STRATEGIC;
834  } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
835  // the current lane is the best and a lane-changing would cause a situation
836  // of which we assume we will not be able to return to the lane we have to be on.
837  // this rule prevents the vehicle from leaving the current, best lane when it is
838  // close to this lane's end
839  if (gDebugFlag2) {
840  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
841  }
842  ret = ret | LCA_STAY | LCA_STRATEGIC;
843  } else if (bestLaneOffset == 0
844  && (leader.first == 0 || !leader.first->isStopped())
845  && neigh.bestContinuations.back()->getLinkCont().size() != 0
846  && roundaboutEdgesAhead == 0
847  && neighDist < TURN_LANE_DIST) {
848  // VARIANT_21 (stayOnBest)
849  // we do not want to leave the best lane for a lane which leads elsewhere
850  // unless our leader is stopped or we are approaching a roundabout
851  if (gDebugFlag2) {
852  std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
853  }
854  ret = ret | LCA_STAY | LCA_STRATEGIC;
855  }
856  }
857  // check for overriding TraCI requests
858  if (gDebugFlag2) {
859  std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << ret;
860  }
862  if ((ret & lcaCounter) != 0) {
863  // we are not interested in traci requests for the opposite direction here
864  ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
865  }
866  if (gDebugFlag2) {
867  std::cout << " retAfterInfluence=" << ret << "\n";
868  }
869 
870  if ((ret & LCA_STAY) != 0) {
871  return ret;
872  }
873  if ((ret & LCA_URGENT) != 0) {
874  // prepare urgent lane change maneuver
875  // save the left space
876  myLeftSpace = currentDist - myVehicle.getPositionOnLane();
877  if (changeToBest && abs(bestLaneOffset) > 1) {
878  // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
879  if (gDebugFlag2) {
880  std::cout << " reserving space for unseen blockers\n";
881  }
882  myLeadingBlockerLength = MAX2((SUMOReal)(right ? 20.0 : 40.0), myLeadingBlockerLength);
883  }
884 
885  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
886  // if there is a leader and he wants to change to the opposite direction
887  saveBlockerLength(neighLead.first, lcaCounter);
888  if (*firstBlocked != neighLead.first) {
889  saveBlockerLength(*firstBlocked, lcaCounter);
890  }
891 
892  const SUMOReal remainingSeconds = ((ret & LCA_TRACI) == 0 ?
895  const SUMOReal plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
896  if (plannedSpeed >= 0) {
897  // maybe we need to deal with a blocking follower
898  informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
899  }
900 
901  if (gDebugFlag2) {
902  std::cout << STEPS2TIME(currentTime)
903  << " veh=" << myVehicle.getID()
904  << " myLeftSpace=" << myLeftSpace
905  << " remainingSeconds=" << remainingSeconds
906  << " plannedSpeed=" << plannedSpeed
907  << "\n";
908  }
909  return ret;
910  }
911 
912  // VARIANT_15
913  if (roundaboutEdgesAhead > 1) {
914  // try to use the inner lanes of a roundabout to increase throughput
915  // unless we are approaching the exit
916  if (lca == LCA_LEFT) {
917  req = ret | lca | LCA_COOPERATIVE;
918  } else {
919  req = ret | LCA_STAY | LCA_COOPERATIVE;
920  }
921  if (!cancelRequest(req)) {
922  return ret | req;
923  }
924  }
925 
926  // let's also regard the case where the vehicle is driving on a highway...
927  // in this case, we do not want to get to the dead-end of an on-ramp
928  if (right) {
929  if (bestLaneOffset == 0 && myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle) > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
930  if (gDebugFlag2) {
931  std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
932  }
933  req = ret | LCA_STAY | LCA_STRATEGIC;
934  if (!cancelRequest(req)) {
935  return ret | req;
936  }
937  }
938  }
939  // --------
940 
941  // -------- make place on current lane if blocking follower
942  //if (amBlockingFollowerPlusNB()) {
943  // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
944  // << " neighDist=" << neighDist
945  // << " currentDist=" << currentDist
946  // << "\n";
947  //}
949  //&& ((myOwnState & myLcaCounter) == 0) // VARIANT_6 : counterNoHelp
950  && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
951 
952  // VARIANT_2 (nbWhenChangingToHelp)
953  if (gDebugFlag2) {
954  std::cout << STEPS2TIME(currentTime)
955  << " veh=" << myVehicle.getID()
956  << " wantsChangeToHelp=" << (right ? "right" : "left")
957  << " state=" << myOwnState
958  << (((myOwnState & myLcaCounter) != 0) ? " (counter)" : "")
959  << "\n";
960  }
961  req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
962  if (!cancelRequest(req)) {
963  return ret | req;
964  }
965  }
966 
967  // --------
968 
969 
972  //if ((blocked & LCA_BLOCKED) != 0) {
973  // return ret;
974  //}
976 
977  // -------- higher speed
978  //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
979  // return ret;
980  //}
982  SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
983  if (neighLead.first == 0) {
984  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
985  } else {
986  // @todo: what if leader is below safe gap?!!!
987  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(
988  &myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
989  }
990  if (leader.first == 0) {
991  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
992  } else {
993  // @todo: what if leader is below safe gap?!!!
994  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
995  }
996 
998  thisLaneVSafe = MIN2(thisLaneVSafe, vMax);
999  neighLaneVSafe = MIN2(neighLaneVSafe, vMax);
1000  const SUMOReal relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1002 
1003  if (right) {
1004  // ONLY FOR CHANGING TO THE RIGHT
1005  if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1006  // ok, the current lane is faster than the right one...
1007  if (mySpeedGainProbability < 0) {
1008  mySpeedGainProbability /= 2.0;
1009  }
1010  } else {
1011  // ok, the current lane is not faster than the right one
1012  mySpeedGainProbability -= relativeGain;
1013 
1014  // honor the obligation to keep right (Rechtsfahrgebot)
1015  // XXX consider fast approaching followers on the current lane
1016  //const SUMOReal vMax = myLookAheadSpeed;
1017  const SUMOReal acceptanceTime = KEEP_RIGHT_ACCEPTANCE * vMax * MAX2((SUMOReal)1, myVehicle.getSpeed()) / myVehicle.getLane()->getSpeedLimit();
1018  SUMOReal fullSpeedGap = MAX2((SUMOReal)0, neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1019  SUMOReal fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1020  if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1021  fullSpeedGap = MAX2((SUMOReal)0, MIN2(fullSpeedGap,
1022  neighLead.second - myVehicle.getCarFollowModel().getSecureGap(
1023  vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1024  fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1025  }
1026  const SUMOReal deltaProb = (CHANGE_PROB_THRESHOLD_RIGHT
1027  * STEPS2TIME(DELTA_T)
1028  * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1029  myKeepRightProbability -= deltaProb;
1030 
1031  if (gDebugFlag2) {
1032  std::cout << STEPS2TIME(currentTime)
1033  << " veh=" << myVehicle.getID()
1034  << " vMax=" << vMax
1035  << " neighDist=" << neighDist
1036  << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1037  << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1038  << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(
1039  myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1040  << " acceptanceTime=" << acceptanceTime
1041  << " fullSpeedGap=" << fullSpeedGap
1042  << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1043  << " dProb=" << deltaProb
1044  << "\n";
1045  }
1047  req = ret | lca | LCA_KEEPRIGHT;
1048  if (!cancelRequest(req)) {
1049  return ret | req;
1050  }
1051  }
1052  }
1053 
1054  if (gDebugFlag2) {
1055  std::cout << STEPS2TIME(currentTime)
1056  << " veh=" << myVehicle.getID()
1057  << " speed=" << myVehicle.getSpeed()
1058  << " myKeepRightProbability=" << myKeepRightProbability
1059  << " thisLaneVSafe=" << thisLaneVSafe
1060  << " neighLaneVSafe=" << neighLaneVSafe
1061  << " relativeGain=" << relativeGain
1062  << " blocked=" << blocked
1063  << "\n";
1064  }
1065 
1067  && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1
1068  req = ret | lca | LCA_SPEEDGAIN;
1069  if (!cancelRequest(req)) {
1070  return ret | req;
1071  }
1072  }
1073  } else {
1074  // ONLY FOR CHANGING TO THE LEFT
1075  if (thisLaneVSafe > neighLaneVSafe) {
1076  // this lane is better
1077  if (mySpeedGainProbability > 0) {
1078  mySpeedGainProbability /= 2.0;
1079  }
1080  } else {
1081  // left lane is better
1082  mySpeedGainProbability += relativeGain;
1083  }
1084  // VARIANT_19 (stayRight)
1085  //if (neighFollow.first != 0) {
1086  // MSVehicle* nv = neighFollow.first;
1087  // const SUMOReal secGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1088  // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1089  // // do not change left if it would inconvenience faster followers
1090  // return ret | LCA_STAY | LCA_SPEEDGAIN;
1091  // }
1092  //}
1093  if (mySpeedGainProbability > CHANGE_PROB_THRESHOLD_LEFT && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1
1094  req = ret | lca | LCA_SPEEDGAIN;
1095  if (!cancelRequest(req)) {
1096  return ret | req;
1097  }
1098  }
1099  }
1100  // --------
1101  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1102  && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) {
1103  // change towards the correct lane, speedwise it does not hurt
1104  req = ret | lca | LCA_STRATEGIC;
1105  if (!cancelRequest(req)) {
1106  return ret | req;
1107  }
1108  }
1109  if (gDebugFlag2) {
1110  std::cout << STEPS2TIME(currentTime)
1111  << " veh=" << myVehicle.getID()
1112  << " mySpeedGainProbability=" << mySpeedGainProbability
1113  << " myKeepRightProbability=" << myKeepRightProbability
1114  << " thisLaneVSafe=" << thisLaneVSafe
1115  << " neighLaneVSafe=" << neighLaneVSafe
1116  << "\n";
1117  }
1118  return ret;
1119 }
1120 
1121 
1122 int
1124  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1125  if ((*blocked) != 0) {
1126  SUMOReal gap = (*blocked)->getPositionOnLane() - (*blocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1127  if (gDebugFlag2) {
1128  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1129  << " veh=" << myVehicle.getID()
1130  << " blocked=" << tryID(*blocked)
1131  << " gap=" << gap
1132  << "\n";
1133  }
1134  if (gap > POSITION_EPS) {
1135  //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1136  // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1137 
1139  //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1140  ) {
1141  if ((*blocked)->getSpeed() < SUMO_const_haltingSpeed) {
1142  state |= LCA_AMBACKBLOCKER_STANDING;
1143  } else {
1144  state |= LCA_AMBACKBLOCKER;
1145  }
1148  (SUMOReal)(gap - POSITION_EPS), (*blocked)->getSpeed(),
1149  (*blocked)->getCarFollowModel().getMaxDecel()));
1150  //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1151  }
1152  }
1153  }
1154  return state;
1155 }
1156 
1157 
1158 void
1159 MSLCM_JE2013::saveBlockerLength(MSVehicle* blocker, int lcaCounter) {
1160  if (blocker != 0 && (blocker->getLaneChangeModel().getOwnState() & lcaCounter) != 0) {
1161  // is there enough space in front of us for the blocker?
1164  if (blocker->getVehicleType().getLengthWithGap() <= potential) {
1165  // save at least his length in myLeadingBlockerLength
1167  if (gDebugFlag2) {
1168  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1169  << " veh=" << myVehicle.getID()
1170  << " blocker=" << tryID(blocker)
1171  << " saving myLeadingBlockerLength=" << myLeadingBlockerLength
1172  << "\n";
1173  }
1174  } else {
1175  // we cannot save enough space for the blocker. It needs to save
1176  // space for ego instead
1177  if (gDebugFlag2) {
1178  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1179  << " veh=" << myVehicle.getID()
1180  << " blocker=" << tryID(blocker)
1181  << " cannot save space=" << blocker->getVehicleType().getLengthWithGap()
1182  << "\n";
1183  }
1185  }
1186  }
1187 }
1188 /****************************************************************************/
1189 
void * inform(void *info, MSVehicle *sender)
#define LOOK_AHEAD_MIN_SPEED
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:84
int _wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, SUMOReal > &leader, const std::pair< MSVehicle *, SUMOReal > &neighLead, const std::pair< MSVehicle *, SUMOReal > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
helper function for doing the actual work
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:454
#define CHANGE_PROB_THRESHOLD_LEFT
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
SUMOReal getMaxSpeed() const
Get vehicle's maximum speed [m/s].
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
int slowDownForBlocked(MSVehicle **blocked, int state)
compute useful slowdowns for blocked vehicles
#define KEEP_RIGHT_TIME
#define min(a, b)
Definition: polyfonts.c:66
#define TURN_LANE_DIST
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:538
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
#define URGENCY
bool currentDistAllows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_JE2013.h:164
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:173
The action is done to help someone else.
SUMOReal getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive...
Definition: MSVehicle.h:464
bool congested() const
Definition: MSVehicle.h:396
virtual SUMOReal followSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const =0
Computes the vehicle's safe speed (no dawdling)
SUMOReal myLeadingBlockerLength
Definition: MSLCM_JE2013.h:181
The car-following model abstraction.
Definition: MSCFModel.h:58
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
virtual ~MSLCM_JE2013()
SUMOReal getLength() const
Get vehicle's length [m].
SUMOReal myLeftSpace
Definition: MSLCM_JE2013.h:182
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, SUMOReal > &leader, const std::pair< MSVehicle *, SUMOReal > &neighLead, const std::pair< MSVehicle *, SUMOReal > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
T MAX2(T a, T b)
Definition: StdDefs.h:72
MSLCM_JE2013(MSVehicle &v)
std::vector< SUMOReal > myVSafes
Definition: MSLCM_JE2013.h:188
SUMOReal getSecureGap(const SUMOReal speed, const SUMOReal leaderSpeed, const SUMOReal leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum.
Definition: MSCFModel.h:232
SUMOReal getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:283
#define TS
Definition: SUMOTime.h:52
The action is due to a TraCI request.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:216
SUMOReal length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:458
The action is urgent (to be defined by lc-model)
#define abs(a)
Definition: polyfonts.c:67
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:1750
void informFollower(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, SUMOReal > &neighFollow, SUMOReal remainingSeconds, SUMOReal plannedSpeed)
decide whether we will try cut in before the follower or allow to be overtaken
#define LCA_RIGHT_IMPATIENCE
std::pair< SUMOReal, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
Definition: MSLCM_JE2013.h:169
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:60
Wants go to the left.
#define max(a, b)
Definition: polyfonts.c:65
bool cancelRequest(int state)
whether the influencer cancels the given request
SUMOReal brakeGap(const SUMOReal speed) const
Returns the distance the vehicle needs to halt including driver's reaction time.
Definition: MSCFModel.h:213
#define CUT_IN_LEFT_SPEED_THRESHOLD
SUMOReal mySpeedGainProbability
a value for tracking the probability that a change to the offset with the same sign is beneficial ...
Definition: MSLCM_JE2013.h:175
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
void prepareStep()
#define RELGAIN_NORMALIZATION_MIN_SPEED
#define JAM_FACTOR
#define LOOK_FORWARD_RIGHT
bool amBlockingFollowerPlusNB()
Definition: MSLCM_JE2013.h:158
SUMOReal informLeader(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, SUMOReal > &neighLead, SUMOReal remainingSeconds)
SUMOReal _patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel &cfModel)
void saveBlockerLength(MSVehicle *blocker, int lcaCounter)
save space for vehicles which need to counter-lane-change
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
T MIN2(T a, T b)
Definition: StdDefs.h:66
virtual SUMOReal stopSpeed(const MSVehicle *const veh, const SUMOReal speed, SUMOReal gap2pred) const =0
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling) ...
#define POSITION_EPS
Definition: config.h:186
SUMOReal getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:362
std::string tryID(const MSVehicle *v)
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:454
SUMOReal getMaxDecel() const
Get the vehicle type's maximum deceleration [m/s^2].
Definition: MSCFModel.h:165
SUMOReal changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Definition: MSVehicle.cpp:298
int myOwnState
The current state of the vehicle.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:53
Wants go to the right.
#define HELP_OVERTAKE
virtual void saveBlockerLength(SUMOReal length)
reserve space at the end of the lane to avoid dead locks
#define HELP_DECEL_FACTOR
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
The action is needed to follow the route (navigational lc)
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:215
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:2328
SUMOReal myKeepRightProbability
Definition: MSLCM_JE2013.h:179
#define LOOK_AHEAD_SPEED_MEMORY
SUMOTime myLastLaneChangeOffset
information how long ago the vehicle has performed a lane-change
#define ROUNDABOUT_DIST_BONUS
SUMOReal occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:460
#define CHANGE_PROB_THRESHOLD_RIGHT
std::vector< MSLane * > bestContinuations
Consecutive lane that can be followed without a lane change (contribute to length and occupation) ...
Definition: MSVehicle.h:468
SUMOReal myLookAheadSpeed
Definition: MSLCM_JE2013.h:186
The action is due to the default of keeping right "Rechtsfahrgebot".
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
Definition: MSBaseVehicle.h:95
const SUMOReal SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:54
Needs to stay on the current lane.
SUMOReal getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:291
SUMOReal getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:373
#define MIN_FALLBEHIND
#define KEEP_RIGHT_ACCEPTANCE
bool gDebugFlag2
Definition: StdDefs.cpp:85
#define SUMOReal
Definition: config.h:215
#define LOOK_FORWARD_LEFT
#define NUMERICAL_EPS
Definition: config.h:159
#define DELTA_T
Definition: SUMOTime.h:50
#define DEBUG_COND
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:997
SUMOReal getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:354
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:328
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:2346
The edge is an internal edge.
Definition: MSEdge.h:91
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
const MSCFModel & myCarFollowModel
The vehicle's car following model.
bool currentDistDisallows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_JE2013.h:161
Interface for lane-change models.
int getBestLaneOffset() const
returns the current offset from the best lane
Definition: MSVehicle.cpp:2063
SUMOReal patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel &cfModel)
Called to adapt the speed in order to allow a lane change.
const std::string & getID() const
Returns the name of the vehicle.
The action is due to the wish to be faster (tactical lc)