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-2013 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)80.0
85 
86 //#define DEBUG_COND (myVehicle.getID() == "pkw22806" || myVehicle.getID() == "pkw22823")
87 //#define DEBUG_COND (myVehicle.getID() == "emitter_SST92-150 FG 1 DE 3_26966400" || myVehicle.getID() == "emitter_SST92-150 FG 1 DE 1_26932941" || myVehicle.getID() == "emitter_SST92-175 FG 1 DE 129_27105000")
88 //#define DEBUG_COND (myVehicle.getID() == "Costa_200_153" || myVehicle.getID() == "Costa_12_154") // fail change to left
89 //#define DEBUG_COND (myVehicle.getID() == "150_2_36000000") // test stops_overtaking
90 #define DEBUG_COND false
91 
92 // debug function
93 std::string
94 tryID(const MSVehicle* v) {
95  return v == 0 ? "NULL" : v->getID();
96 }
97 
98 
99 // ===========================================================================
100 // member method definitions
101 // ===========================================================================
104  mySpeedGainProbability(0),
105  myKeepRightProbability(0),
106  myLeadingBlockerLength(0),
107  myLeftSpace(0),
108  myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED)
109 {}
110 
112  changed();
113 }
114 
115 
116 int
118  int laneOffset,
120  int blocked,
121  const std::pair<MSVehicle*, SUMOReal>& leader,
122  const std::pair<MSVehicle*, SUMOReal>& neighLead,
123  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
124  const MSLane& neighLane,
125  const std::vector<MSVehicle::LaneQ>& preb,
126  MSVehicle** lastBlocked,
127  MSVehicle** firstBlocked) {
129 
131  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
132  << " veh=" << myVehicle.getID()
133  << " lane=" << myVehicle.getLane()->getID()
134  << " pos=" << myVehicle.getPositionOnLane()
135  << " speed=" << myVehicle.getSpeed()
136  << " considerChangeTo=" << (laneOffset == -1 ? "right" : "left")
137  << "\n";
138  }
139 
140  const int result = _wantsChange(laneOffset, msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked);
142  if (result & LCA_WANTS_LANECHANGE) {
143  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
144  << " veh=" << myVehicle.getID()
145  << " wantsChangeTo=" << (laneOffset == -1 ? "right" : "left")
146  << ((result & LCA_URGENT) ? " (urgent)" : "")
147  << ((result & LCA_CHANGE_TO_HELP) ? " (toHelp)" : "")
148  << ((result & LCA_STRATEGIC) ? " (strat)" : "")
149  << ((result & LCA_COOPERATIVE) ? " (coop)" : "")
150  << ((result & LCA_SPEEDGAIN) ? " (speed)" : "")
151  << ((result & LCA_KEEPRIGHT) ? " (keepright)" : "")
152  << ((result & LCA_TRACI) ? " (traci)" : "")
153  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
154  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
155  << "\n";
156  }
157  }
158  MSGlobals::gDebugFlag2 = false;
159  return result;
160 }
161 
162 
163 SUMOReal
164 MSLCM_JE2013::patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
166 
167  const SUMOReal newSpeed = _patchSpeed(min, wanted, max, cfModel);
169  const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
170  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
171  << " veh=" << myVehicle.getID()
172  << " lane=" << myVehicle.getLane()->getID()
173  << " pos=" << myVehicle.getPositionOnLane()
174  << " v=" << myVehicle.getSpeed()
175  << " wanted=" << wanted
176  << patched
177  << "\n";
178  }
179  MSGlobals::gDebugFlag1 = false;
180  return newSpeed;
181 }
182 
183 
184 SUMOReal
185 MSLCM_JE2013::_patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
186 
187  const SUMOReal time = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
188 
189  int state = myOwnState;
190 
191  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
192  SUMOReal MAGIC_offset = 1.;
193  // if we want to change and have a blocking leader and there is enough room for him in front of us
194  if (myLeadingBlockerLength != 0) {
197  std::cout << time << " veh=" << myVehicle.getID() << " myLeadingBlockerLength=" << myLeadingBlockerLength << " space=" << space << "\n";
198  }
199  if (space > 0) {
200  // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
201  SUMOReal safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space);
202  // if we are approaching this place
203  if (safe < wanted) {
204  // return this speed as the speed to use
206  std::cout << time << " veh=" << myVehicle.getID() << " slowing down for leading blocker" << (safe < min ? " (not enough)" : "") << "\n";
207  }
208  return MAX2(min, safe);
209  }
210  }
211  }
212 
213  SUMOReal nVSafe = wanted;
214  bool gotOne = false;
215  for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
216  SUMOReal v = (*i);
217  if (v >= min && v <= max) {
218  nVSafe = MIN2(v, nVSafe);
219  gotOne = true;
221  std::cout << time << " veh=" << myVehicle.getID() << " got nVSafe=" << nVSafe << "\n";
222  }
223  } else {
224  if (v < min) {
226  std::cout << time << " veh=" << myVehicle.getID() << " ignoring low nVSafe=" << v << " min=" << min << "\n";
227  }
228  } else {
230  std::cout << time << " veh=" << myVehicle.getID() << " ignoring high nVSafe=" << v << " max=" << max << "\n";
231  }
232  }
233  }
234  }
235 
236  if (gotOne && !myDontBrake) {
238  std::cout << time << " veh=" << myVehicle.getID() << " got vSafe\n";
239  }
240  return nVSafe;
241  }
242 
243  // check whether the vehicle is blocked
244  if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) != 0) {
245  if ((state & LCA_STRATEGIC) != 0) {
246  // necessary decelerations are controlled via vSafe. If there are
247  // none it means we should speed up
249  std::cout << time << " veh=" << myVehicle.getID() << " LCA_WANTS_LANECHANGE (strat, no vSafe)\n";
250  }
251  return (max + wanted) / (SUMOReal) 2.0;
252  } else if ((state & LCA_COOPERATIVE) != 0) {
253  // only minor adjustments in speed should be done
254  if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
256  std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_LEADER (coop)\n";
257  }
258  return (min + wanted) / (SUMOReal) 2.0;
259  }
260  if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
262  std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER (coop)\n";
263  }
264  return (max + wanted) / (SUMOReal) 2.0;
265  }
266  //} else { // VARIANT_16
267  // // only accelerations should be performed
268  // if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
269  // if (MSGlobals::gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER\n";
270  // return (max + wanted) / (SUMOReal) 2.0;
271  // }
272  }
273  }
274 
275  /*
276  // decelerate if being a blocking follower
277  // (and does not have to change lanes)
278  if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
279  if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
280  if (MSGlobals::gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER (standing)\n";
281  return 0;
282  }
283  if (MSGlobals::gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER\n";
284 
285  //return min; // VARIANT_3 (brakeStrong)
286  return (min + wanted) / (SUMOReal) 2.0;
287  }
288  if ((state & LCA_AMBACKBLOCKER) != 0) {
289  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
290  if (MSGlobals::gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER (standing)\n";
291  //return min; VARIANT_9 (backBlockVSafe)
292  return nVSafe;
293  }
294  }
295  if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
296  if (MSGlobals::gDebugFlag1) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER_STANDING\n";
297  //return min;
298  return nVSafe;
299  }
300  */
301 
302  // accelerate if being a blocking leader or blocking follower not able to brake
303  // (and does not have to change lanes)
304  if ((state & LCA_AMBLOCKINGLEADER) != 0) {
306  std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGLEADER\n";
307  }
308  return (max + wanted) / (SUMOReal) 2.0;
309  }
310 
311  if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
313  std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER_DONTBRAKE\n";
314  }
315  /*
316  // VARIANT_4 (dontbrake)
317  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
318  return wanted;
319  }
320  return (min + wanted) / (SUMOReal) 2.0;
321  */
322  }
323  if (myVehicle.getLane()->getEdge().getLanes().size() == 1) {
324  // remove chaning information if on a road with a single lane
325  changed();
326  }
327  return wanted;
328 }
329 
330 
331 void*
332 MSLCM_JE2013::inform(void* info, MSVehicle* sender) {
333  Info* pinfo = (Info*) info;
334  if (pinfo->first >= 0) {
335  myVSafes.push_back(pinfo->first);
336  }
337  //myOwnState &= 0xffffffff; // reset all bits of MyLCAEnum but only those
338  myOwnState |= pinfo->second;
340  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
341  << " veh=" << myVehicle.getID()
342  << " informedBy=" << sender->getID()
343  << " info=" << pinfo->second
344  << " vSafe=" << pinfo->first
345  << "\n";
346  }
347  delete pinfo;
348  return (void*) true;
349 }
350 
351 
352 SUMOReal
354  int blocked,
355  int dir,
356  const std::pair<MSVehicle*, SUMOReal>& neighLead,
357  SUMOReal remainingSeconds) {
358  SUMOReal plannedSpeed = MIN2(myVehicle.getSpeed(),
360  for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
361  SUMOReal v = (*i);
363  plannedSpeed = MIN2(plannedSpeed, v);
364  }
365  }
367  std::cout << " informLeader speed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
368  }
369 
370  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
371  assert(neighLead.first != 0);
372  MSVehicle* nv = neighLead.first;
373  if (MSGlobals::gDebugFlag2) std::cout << " blocked by leader nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
375  // decide whether we want to overtake the leader or follow it
376  const SUMOReal dv = plannedSpeed - nv->getSpeed();
377  const SUMOReal overtakeDist = (neighLead.second // drive to back of follower
378  + nv->getVehicleType().getLengthWithGap() // drive to front of follower
379  + myVehicle.getVehicleType().getLength() // ego back reaches follower front
380  + nv->getCarFollowModel().getSecureGap( // save gap to follower
382 
383  if (dv < 0
384  // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft)
385  || (dir == LCA_MLEFT && !myVehicle.congested())
386  // not enough space to overtake?
387  || myLeftSpace < overtakeDist
388  // not enough time to overtake?
389  || dv * remainingSeconds < overtakeDist) {
390  // cannot overtake
391  msgPass.informNeighLeader(new Info(-1, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
392  // slow down smoothly to follow leader
393  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
394  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
395  if (targetSpeed < myVehicle.getSpeed()) {
396  // slow down smoothly to follow leader
398  MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds)));
399  const SUMOReal nextSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() - decel);
401  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
402  << " cannot overtake leader nv=" << nv->getID()
403  << " dv=" << dv
404  << " remainingSeconds=" << remainingSeconds
405  << " targetSpeed=" << targetSpeed
406  << " nextSpeed=" << nextSpeed
407  << "\n";
408  }
409  myVSafes.push_back(nextSpeed);
410  return nextSpeed;
411  } else {
412  // leader is fast enough anyway
414  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
415  << " cannot overtake fast leader nv=" << nv->getID()
416  << " dv=" << dv
417  << " remainingSeconds=" << remainingSeconds
418  << " targetSpeed=" << targetSpeed
419  << "\n";
420  }
421  myVSafes.push_back(targetSpeed);
422  return plannedSpeed;
423  }
424  } else {
426  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
427  << " wants to overtake leader nv=" << nv->getID()
428  << " dv=" << dv
429  << " remainingSeconds=" << remainingSeconds
430  << " currentGap=" << neighLead.second
432  << "\n";
433  }
434  // overtaking, leader should not accelerate
435  msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
436  return -1;
437  }
438  } else if (neighLead.first != 0) { // (remainUnblocked)
439  // we are not blocked now. make sure we stay far enough from the leader
440  MSVehicle* nv = neighLead.first;
441  const SUMOReal nextNVSpeed = nv->getSpeed() - HELP_OVERTAKE; // conservative
442  const SUMOReal dv = SPEED2DIST(myVehicle.getSpeed() - nextNVSpeed);
443  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
444  &myVehicle, myVehicle.getSpeed(), neighLead.second - dv, nextNVSpeed, nv->getCarFollowModel().getMaxDecel());
445  myVSafes.push_back(targetSpeed);
447  std::cout << " not blocked by leader nv=" << nv->getID()
448  << " nvSpeed=" << nv->getSpeed()
449  << " gap=" << neighLead.second
450  << " nextGap=" << neighLead.second - dv
452  << " targetSpeed=" << targetSpeed
453  << "\n";
454  }
455  return MIN2(targetSpeed, plannedSpeed);
456  } else {
457  // not overtaking
458  return plannedSpeed;
459  }
460 }
461 
462 
463 void
465  int blocked,
466  int dir,
467  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
468  SUMOReal remainingSeconds,
469  SUMOReal plannedSpeed) {
470  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
471  assert(neighFollow.first != 0);
472  MSVehicle* nv = neighFollow.first;
473  if (MSGlobals::gDebugFlag2) std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
475 
476  // are we fast enough to cut in without any help?
477  if (plannedSpeed - nv->getSpeed() >= HELP_OVERTAKE) {
478  const SUMOReal neededGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
479  if ((neededGap - neighFollow.second) / remainingSeconds < (plannedSpeed - nv->getSpeed())) {
481  std::cout << " wants to cut in before nv=" << nv->getID() << " without any help neededGap=" << neededGap << "\n";
482  }
483  // follower might even accelerate but not to much
484  msgPass.informNeighFollower(new Info(plannedSpeed - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
485  return;
486  }
487  }
488  // decide whether we will request help to cut in before the follower or allow to be overtaken
489 
490  // PARAMETERS
491  // assume other vehicle will assume the equivalent of 1 second of
492  // maximum deceleration to help us (will probably be spread over
493  // multiple seconds)
494  // -----------
495  const SUMOReal helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR ;
496 
497  // change in the gap between ego and blocker over 1 second (not STEP!)
498  const SUMOReal neighNewSpeed = MAX2((SUMOReal)0, nv->getSpeed() - ACCEL2SPEED(helpDecel));
499  const SUMOReal neighNewSpeed1s = MAX2((SUMOReal)0, nv->getSpeed() - helpDecel);
500  const SUMOReal dv = plannedSpeed - neighNewSpeed1s;
501  // new gap between follower and self in case the follower does brake for 1s
502  const SUMOReal decelGap = neighFollow.second + dv;
503  const SUMOReal secureGap = nv->getCarFollowModel().getSecureGap(neighNewSpeed1s, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
505  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
506  << " egoV=" << myVehicle.getSpeed()
507  << " egoNV=" << plannedSpeed
508  << " nvNewSpeed=" << neighNewSpeed
509  << " nvNewSpeed1s=" << neighNewSpeed1s
510  << " deltaGap=" << dv
511  << " decelGap=" << decelGap
512  << " secGap=" << secureGap
513  << "\n";
514  }
515  if (decelGap > 0 && decelGap >= secureGap) {
516  // if the blocking neighbor brakes it could actually help
517  // how hard does it actually need to be?
518  const SUMOReal vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
519  nv, nv->getSpeed(), neighFollow.second, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel()));
520  msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
522  std::cout << " wants to cut in before nv=" << nv->getID() << "\n";
523  }
524  } else if (dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS)) {
525  // decelerating once is sufficient to open up a large enough gap in time
526  msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
528  std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
529  }
530  } else {
532  if (nv->getSpeed() > myVehicle.getSpeed() &&
534  || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
535  )) {
536  // let the follower slow down to increase the likelyhood that later vehicles will be slow enough to help
537  // follower should still be fast enough to open a gap
538  vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
540  std::cout << " wants right follower to slow down a bit\n";
541  }
542  if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
544  std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
545  }
546  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
547  return;
548  }
549  }
550  msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
551  // this follower is supposed to overtake us. slow down smoothly to allow this
552  const SUMOReal overtakeDist = (neighFollow.second // follower reaches ego back
553  + myVehicle.getVehicleType().getLengthWithGap() // follower reaches ego front
554  + nv->getVehicleType().getLength() // follower back at ego front
555  + myVehicle.getCarFollowModel().getSecureGap( // follower has safe dist to ego
556  plannedSpeed, vhelp, nv->getCarFollowModel().getMaxDecel()));
557  // speed difference to create a sufficiently large gap
558  const SUMOReal needDV = overtakeDist / remainingSeconds;
559  // make sure the deceleration is not to strong
560  myVSafes.push_back(MAX2(vhelp - needDV, myVehicle.getSpeed() - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())));
561 
563  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
564  << " veh=" << myVehicle.getID()
565  << " wants to be overtaken by=" << nv->getID()
566  << " overtakeDist=" << overtakeDist
567  << " vneigh=" << nv->getSpeed()
568  << " vhelp=" << vhelp
569  << " vsafe=" << myVSafes.back()
570  << "\n";
571  }
572  }
573  }
574 }
575 
576 
577 void
579  myOwnState = 0;
581  myLeftSpace = 0;
582  myVSafes.clear();
583  myDontBrake = false;
584  // truncate to work around numerical instability between different builds
585  mySpeedGainProbability = ceil(mySpeedGainProbability * 100000.0) * 0.00001;
586  myKeepRightProbability = ceil(myKeepRightProbability * 100000.0) * 0.00001;
587 }
588 
589 
590 void
592  myOwnState = 0;
596  if (myVehicle.getBestLaneOffset() == 0) {
597  // if we are not yet on our best lane there might still be unseen blockers
598  // (during patchSpeed)
600  myLeftSpace = 0;
601  }
603  myVSafes.clear();
604  myDontBrake = false;
605 }
606 
607 
608 int
610  int laneOffset,
612  int blocked,
613  const std::pair<MSVehicle*, SUMOReal>& leader,
614  const std::pair<MSVehicle*, SUMOReal>& neighLead,
615  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
616  const MSLane& neighLane,
617  const std::vector<MSVehicle::LaneQ>& preb,
618  MSVehicle** lastBlocked,
619  MSVehicle** firstBlocked) {
620  assert(laneOffset == 1 || laneOffset == -1);
621  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
622  // compute bestLaneOffset
623  MSVehicle::LaneQ curr, neigh, best;
624  int bestLaneOffset = 0;
625  SUMOReal currentDist = 0;
626  SUMOReal neighDist = 0;
627  int currIdx = 0;
628  MSLane* prebLane = myVehicle.getLane();
629  if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
630  // internal edges are not kept inside the bestLanes structure
631  prebLane = prebLane->getLinkCont()[0]->getLane();
632  }
633  for (int p = 0; p < (int) preb.size(); ++p) {
634  if (preb[p].lane == prebLane && p + laneOffset >= 0) {
635  assert(p + laneOffset < (int)preb.size());
636  curr = preb[p];
637  neigh = preb[p + laneOffset];
638  currentDist = curr.length;
639  neighDist = neigh.length;
640  bestLaneOffset = curr.bestLaneOffset;
641  // VARIANT_13 (equalBest)
642  if (bestLaneOffset == 0 && preb[p + laneOffset].bestLaneOffset == 0) {
644  std::cout << STEPS2TIME(currentTime)
645  << " veh=" << myVehicle.getID()
646  << " bestLaneOffsetOld=" << bestLaneOffset
647  << " bestLaneOffsetNew=" << laneOffset
648  << "\n";
649  }
650  bestLaneOffset = laneOffset;
651  }
652  best = preb[p + bestLaneOffset];
653  currIdx = p;
654  break;
655  }
656  }
657  // direction specific constants
658  const bool right = (laneOffset == -1);
659  const int lca = (right ? LCA_RIGHT : LCA_LEFT);
660  const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
661  const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
662  const int myLcaCounter = (right ? LCA_MLEFT : LCA_MRIGHT);
663  const bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
664  // keep information about being a leader/follower
665  int ret = (myOwnState & 0xffff0000);
666 
667  // VARIANT_5 (disableAMBACKBLOCKER1)
668  /*
669  if (leader.first != 0
670  && (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0
671  && (leader.first->getLaneChangeModel().getOwnState() & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
672 
673  myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE);
674  if (myVehicle.getSpeed() > SUMO_const_haltingSpeed) {
675  myOwnState |= LCA_AMBACKBLOCKER;
676  } else {
677  ret |= LCA_AMBACKBLOCKER;
678  myDontBrake = true;
679  }
680  }
681  */
682 
684  std::cout << STEPS2TIME(currentTime)
685  << " veh=" << myVehicle.getID()
686  << " firstBlocked=" << tryID(*firstBlocked)
687  << " lastBlocked=" << tryID(*lastBlocked)
688  << " neighLead=" << tryID(neighLead.first)
689  << " neighLeadGap=" << neighLead.second
690  << " neighFollow=" << tryID(neighFollow.first)
691  << " neighFollowGap=" << neighFollow.second
692  << "\n";
693  }
694 
695  ret = slowDownForBlocked(lastBlocked, ret);
696  // VARIANT_14 (furtherBlock)
697  if (lastBlocked != firstBlocked) {
698  ret = slowDownForBlocked(firstBlocked, ret);
699  }
700 
701 
702  // we try to estimate the distance which is necessary to get on a lane
703  // we have to get on in order to keep our route
704  // we assume we need something that depends on our velocity
705  // and compare this with the free space on our wished lane
706  //
707  // if the free space is somehow less than the space we need, we should
708  // definitely try to get to the desired lane
709  //
710  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
711  // lookAheadDistance:
712  // we do not want the lookahead distance to change all the time so we discrectize the speed a bit
713 
714  // VARIANT_18 (laHyst)
717  } else {
720  }
721  //myLookAheadSpeed = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
722 
723  //SUMOReal laDist = laSpeed > LOOK_FORWARD_SPEED_DIVIDER
724  // ? laSpeed * LOOK_FORWARD_FAR
725  // : laSpeed * LOOK_FORWARD_NEAR;
727  laDist += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.;
728  // free space that is available for changing
729  //const SUMOReal neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
730  // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
731  // best.lane->getSpeedLimit());
732  // @note: while this lets vehicles change earlier into the correct direction
733  // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
734 
735  // VARIANT_15 (insideRoundabout)
736  int roundaboutEdgesAhead = 0;
737  for (std::vector<MSLane*>::iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) {
738  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
739  roundaboutEdgesAhead += 1;
740  } else if (roundaboutEdgesAhead > 0) {
741  // only check the next roundabout
742  break;
743  }
744  }
745  int roundaboutEdgesAheadNeigh = 0;
746  for (std::vector<MSLane*>::iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) {
747  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
748  roundaboutEdgesAheadNeigh += 1;
749  } else if (roundaboutEdgesAheadNeigh > 0) {
750  // only check the next roundabout
751  break;
752  }
753  }
754  if (roundaboutEdgesAhead > 1) {
755  currentDist += roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS;
756  neighDist += roundaboutEdgesAheadNeigh * ROUNDABOUT_DIST_BONUS;
757  }
758  if (roundaboutEdgesAhead > 0) {
760  std::cout << " roundaboutEdgesAhead=" << roundaboutEdgesAhead << " roundaboutEdgesAheadNeigh=" << roundaboutEdgesAheadNeigh << "\n";
761  }
762  }
763 
764  const SUMOReal usableDist = (currentDist - myVehicle.getPositionOnLane() - best.occupation * JAM_FACTOR);
765  //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
766  const SUMOReal maxJam = MAX2(preb[currIdx + laneOffset].occupation, preb[currIdx].occupation);
767  const SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
768 
770  std::cout << STEPS2TIME(currentTime)
771  << " veh=" << myVehicle.getID()
772  << " laSpeed=" << myLookAheadSpeed
773  << " laDist=" << laDist
774  << " currentDist=" << currentDist
775  << " usableDist=" << usableDist
776  << " bestLaneOffset=" << bestLaneOffset
777  << " best.length=" << best.length
778  << "\n";
779  }
780 
781  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
782  && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
784  ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
785  } else {
786  // VARIANT_20 (noOvertakeRight)
787  if (!right && !myVehicle.congested() && neighLead.first != 0) {
788  // check for slower leader on the left. we should not overtake but
789  // rather move left ourselves (unless congested)
790  MSVehicle* nv = neighLead.first;
791  if (nv->getSpeed() < myVehicle.getSpeed()) {
792  mySpeedGainProbability += 0.3;
794  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel()));
796  std::cout << STEPS2TIME(currentTime)
797  << " avoid overtaking on the right nv=" << nv->getID()
798  << " nvSpeed=" << nv->getSpeed()
799  << " mySpeedGainProbability=" << mySpeedGainProbability
800  << " plannedSpeed=" << myVSafes.back()
801  << "\n";
802  }
803  }
804  }
805 
806  if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
807  // the opposite lane-changing direction should be done than the one examined herein
808  // we'll check whether we assume we could change anyhow and get back in time...
809  //
810  // this rule prevents the vehicle from moving in opposite direction of the best lane
811  // unless the way till the end where the vehicle has to be on the best lane
812  // is long enough
814  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
815  }
816  ret = ret | LCA_STAY | LCA_STRATEGIC;
817  } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
818  // the current lane is the best and a lane-changing would cause a situation
819  // of which we assume we will not be able to return to the lane we have to be on.
820  // this rule prevents the vehicle from leaving the current, best lane when it is
821  // close to this lane's end
823  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
824  }
825  ret = ret | LCA_STAY | LCA_STRATEGIC;
826  }
827  }
828  // check for overriding TraCI requests
830  std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << ret;
831  }
833  if ((ret & lcaCounter) != 0) {
834  // we are not interested in traci requests for the opposite direction here
835  ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
836  }
838  std::cout << " retAfterInfluence=" << ret << "\n";
839  }
840 
841  if ((ret & LCA_STAY) != 0) {
842  return ret;
843  }
844  if ((ret & LCA_URGENT) != 0) {
845  // prepare urgent lane change maneuver
846  // save the left space
847  myLeftSpace = currentDist - myVehicle.getPositionOnLane();
848  if (changeToBest && abs(bestLaneOffset) > 1) {
849  // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
851  std::cout << " reserving space for unseen blockers\n";
852  }
853  myLeadingBlockerLength = MAX2((SUMOReal)(right ? 20.0 : 40.0), myLeadingBlockerLength);
854  }
855 
856  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
857  // if there is a leader and he wants to change to the opposite direction
858  saveBlockerLength(neighLead.first, lcaCounter);
859  if (*firstBlocked != neighLead.first) {
860  saveBlockerLength(*firstBlocked, lcaCounter);
861  }
862 
863  const SUMOReal remainingSeconds = ((ret & LCA_TRACI) == 0 ?
864  MAX2((SUMOReal)STEPS2TIME(TS), myLeftSpace / myLookAheadSpeed / abs(bestLaneOffset) / URGENCY) :
866  const SUMOReal plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
867  if (plannedSpeed >= 0) {
868  // maybe we need to deal with a blocking follower
869  informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
870  }
871 
873  std::cout << STEPS2TIME(currentTime)
874  << " veh=" << myVehicle.getID()
875  << " myLeftSpace=" << myLeftSpace
876  << " remainingSeconds=" << remainingSeconds
877  << " plannedSpeed=" << plannedSpeed
878  << "\n";
879  }
880  return ret;
881  }
882 
883  // VARIANT_15
884  if (roundaboutEdgesAhead > 1) {
885  // try to use the inner lanes of a roundabout to increase throughput
886  // unless we are approaching the exit
887  if (lca == LCA_LEFT) {
888  return ret | lca | LCA_COOPERATIVE;
889  } else {
890  return ret | LCA_STAY | LCA_COOPERATIVE;
891  }
892  }
893 
894  // let's also regard the case where the vehicle is driving on a highway...
895  // in this case, we do not want to get to the dead-end of an on-ramp
896  if (right) {
897  if (bestLaneOffset == 0 && myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle) > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
899  std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
900  }
901  return ret | LCA_STAY | LCA_STRATEGIC;
902  }
903  }
904  // --------
905 
906  // -------- make place on current lane if blocking follower
907  //if (amBlockingFollowerPlusNB()) {
908  // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
909  // << " neighDist=" << neighDist
910  // << " currentDist=" << currentDist
911  // << "\n";
912  //}
914  //&& ((myOwnState & myLcaCounter) == 0) // VARIANT_6 : counterNoHelp
915  && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
916 
917  // VARIANT_2 (nbWhenChangingToHelp)
919  std::cout << STEPS2TIME(currentTime)
920  << " veh=" << myVehicle.getID()
921  << " wantsChangeToHelp=" << (right ? "right" : "left")
922  << " state=" << myOwnState
923  << (((myOwnState & myLcaCounter) != 0) ? " (counter)" : "")
924  << "\n";
925  }
926  return ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
927  }
928 
929  // --------
930 
931 
934  //if ((blocked & LCA_BLOCKED) != 0) {
935  // return ret;
936  //}
938 
939  // -------- higher speed
940  //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
941  // return ret;
942  //}
944  SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
945  if (neighLead.first == 0) {
946  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
947  } else {
948  // @todo: what if leader is below safe gap?!!!
949  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(
950  &myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
951  }
952  if (leader.first == 0) {
953  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
954  } else {
955  // @todo: what if leader is below safe gap?!!!
956  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
957  }
958 
959  thisLaneVSafe = MIN3(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle));
960  neighLaneVSafe = MIN3(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), neighLane.getVehicleMaxSpeed(&myVehicle));
961 
962  if (right) {
963  // ONLY FOR CHANGING TO THE RIGHT
964  if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) {
965  // ok, the current lane is faster than the right one...
966  if (mySpeedGainProbability < 0) {
967  mySpeedGainProbability /= 2.0;
968  myKeepRightProbability /= 2.0;
969  }
970  } else {
971  // ok, the right lane is faster than the current
972  mySpeedGainProbability -= (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)));
973  }
974 
975  // let's recheck the "Rechtsfahrgebot"
976  //keepRight(neighLead.first);
977  keepRight(neighFollow.first);
979  std::cout << STEPS2TIME(currentTime)
980  << " veh=" << myVehicle.getID()
981  << " mySpeedGainProbability=" << mySpeedGainProbability
982  << " myKeepRightProbability=" << myKeepRightProbability
983  << " thisLaneVSafe=" << thisLaneVSafe
984  << " neighLaneVSafe=" << neighLaneVSafe
985  << "\n";
986  }
987 
988  if (mySpeedGainProbability < -2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1
990  return ret | lca | LCA_KEEPRIGHT;
991  } else {
992  return ret | lca | LCA_SPEEDGAIN;
993  }
994  }
995  } else {
996  // ONLY FOR CHANGING TO THE LEFT
997  if (thisLaneVSafe > neighLaneVSafe) {
998  // this lane is better
999  if (mySpeedGainProbability > 0) {
1000  mySpeedGainProbability /= 2.0;
1001  }
1002  } else {
1003  // left lane is better
1004  mySpeedGainProbability += (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle))); // !!! Fahrzeuggeschw.!
1005  }
1006  // VARIANT_19 (stayRight)
1007  //if (neighFollow.first != 0) {
1008  // MSVehicle* nv = neighFollow.first;
1009  // const SUMOReal secGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1010  // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1011  // // do not change left if it would inconvenience faster followers
1012  // return ret | LCA_STAY | LCA_SPEEDGAIN;
1013  // }
1014  //}
1015  if (mySpeedGainProbability > .2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1
1016  return ret | lca | LCA_SPEEDGAIN;
1017  }
1018  }
1019  // --------
1020  if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1021  && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) {
1022  // change towards the correct lane, speedwise it does not hurt
1023  return ret | lca | LCA_STRATEGIC;
1024  }
1025  if (MSGlobals::gDebugFlag2) {
1026  std::cout << STEPS2TIME(currentTime)
1027  << " veh=" << myVehicle.getID()
1028  << " mySpeedGainProbability=" << mySpeedGainProbability
1029  << " myKeepRightProbability=" << myKeepRightProbability
1030  << " thisLaneVSafe=" << thisLaneVSafe
1031  << " neighLaneVSafe=" << neighLaneVSafe
1032  << "\n";
1033  }
1034  return ret;
1035 }
1036 
1037 
1038 void
1040  if (neigh != 0 && neigh->getSpeed() > myVehicle.getSpeed()) {
1041  const SUMOReal dProb = (neigh->getSpeed() - myVehicle.getSpeed()) / neigh->getSpeed();
1042  myKeepRightProbability -= dProb;
1043  mySpeedGainProbability -= dProb;
1044  }
1045 }
1046 
1047 
1048 int
1050  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1051  if ((*blocked) != 0) {
1052  SUMOReal gap = (*blocked)->getPositionOnLane() - (*blocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1053  if (MSGlobals::gDebugFlag2) {
1054  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1055  << " veh=" << myVehicle.getID()
1056  << " blocked=" << tryID(*blocked)
1057  << " gap=" << gap
1058  << "\n";
1059  }
1060  if (gap > POSITION_EPS) {
1061  //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1062  // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1063 
1065  //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1066  ) {
1067  if ((*blocked)->getSpeed() < SUMO_const_haltingSpeed) {
1068  state |= LCA_AMBACKBLOCKER_STANDING;
1069  } else {
1070  state |= LCA_AMBACKBLOCKER;
1071  }
1074  (SUMOReal)(gap - POSITION_EPS), (*blocked)->getSpeed(),
1075  (*blocked)->getCarFollowModel().getMaxDecel()));
1076  //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1077  }
1078  }
1079  }
1080  return state;
1081 }
1082 
1083 
1084 void
1085 MSLCM_JE2013::saveBlockerLength(MSVehicle* blocker, int lcaCounter) {
1086  if (blocker != 0 && (blocker->getLaneChangeModel().getOwnState() & lcaCounter) != 0) {
1087  // is there enough space in front of us for the blocker?
1090  if (blocker->getVehicleType().getLengthWithGap() <= potential) {
1091  // save at least his length in myLeadingBlockerLength
1093  if (MSGlobals::gDebugFlag2) {
1094  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1095  << " veh=" << myVehicle.getID()
1096  << " blocker=" << tryID(blocker)
1097  << " saving myLeadingBlockerLength=" << myLeadingBlockerLength
1098  << "\n";
1099  }
1100  } else {
1101  // we cannot save enough space for the blocker. It needs to save
1102  // space for ego instead
1103  if (MSGlobals::gDebugFlag2) {
1104  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1105  << " veh=" << myVehicle.getID()
1106  << " blocker=" << tryID(blocker)
1107  << " cannot save space=" << blocker->getVehicleType().getLengthWithGap()
1108  << "\n";
1109  }
1111  }
1112  }
1113 }
1114 /****************************************************************************/
1115 
void * inform(void *info, MSVehicle *sender)
#define LOOK_AHEAD_MIN_SPEED
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&#39;s edge.
Definition: MSLane.h:447
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
SUMOReal getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
static bool gDebugFlag1
global utility flags for debugging
Definition: MSGlobals.h:103
int slowDownForBlocked(MSVehicle **blocked, int state)
compute useful slowdowns for blocked vehicles
#define min(a, b)
Definition: polyfonts.c:62
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:510
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
#define URGENCY
bool currentDistAllows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_JE2013.h:165
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:168
The action is done to help someone else.
SUMOReal getLengthWithGap() const
Get vehicle&#39;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:443
bool congested() const
Definition: MSVehicle.h:375
virtual SUMOReal followSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const =0
Computes the vehicle&#39;s safe speed (no dawdling)
SUMOReal myLeadingBlockerLength
Definition: MSLCM_JE2013.h:180
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&#39;s length [m].
SUMOReal myLeftSpace
Definition: MSLCM_JE2013.h:181
void keepRight(MSVehicle *neigh)
updated myKeepRightProbability and mySpeedGainProbability if the right neighbours are faster ...
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:150
T MAX2(T a, T b)
Definition: StdDefs.h:63
MSLCM_JE2013(MSVehicle &v)
std::vector< SUMOReal > myVSafes
Definition: MSLCM_JE2013.h:187
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&#39;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 (in s)
Definition: MSNet.cpp:502
SUMOReal length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:437
The action is urgent (to be defined by lc-model)
#define abs(a)
Definition: polyfonts.c:63
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:1661
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:170
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&#39;s reaction time.
Definition: MSCFModel.h:213
#define CUT_IN_LEFT_SPEED_THRESHOLD
static bool gDebugFlag2
Definition: MSGlobals.h:104
SUMOReal mySpeedGainProbability
a value for tracking the probability that a change to the offset with the same sign is beneficial ...
Definition: MSLCM_JE2013.h:176
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:159
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:57
virtual SUMOReal stopSpeed(const MSVehicle *const veh, const SUMOReal speed, SUMOReal gap2pred) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...
#define POSITION_EPS
Definition: config.h:186
std::string tryID(const MSVehicle *v)
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:433
SUMOReal getMaxDecel() const
Get the vehicle type&#39;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:292
int myOwnState
The current state of the vehicle.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:51
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:2187
SUMOReal myKeepRightProbability
a value for tracking the probability of following the/&quot;Rechtsfahrgebot&quot; (never a positive value) ...
Definition: MSLCM_JE2013.h:178
#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:439
std::vector< MSLane * > bestContinuations
Consecutive lane that can be followed without a lane change (contribute to length and occupation) ...
Definition: MSVehicle.h:447
SUMOReal myLookAheadSpeed
Definition: MSLCM_JE2013.h:185
The action is due to the default of keeping right &quot;Rechtsfahrgebot&quot;.
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;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:49
Needs to stay on the current lane.
SUMOReal getSpeed() const
Returns the vehicle&#39;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:352
#define MIN_FALLBEHIND
#define SUMOReal
Definition: config.h:215
T MIN3(T a, T b, T c)
Definition: StdDefs.h:70
#define LOOK_FORWARD_LEFT
#define DEBUG_COND
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:981
SUMOReal getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:349
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:322
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:2205
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&#39;s car following model.
bool currentDistDisallows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_JE2013.h:162
Interface for lane-change models.
int getBestLaneOffset() const
returns the current offset from the best lane
Definition: MSVehicle.cpp:1974
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)