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