SUMO - Simulation of Urban MObility
MSLCM_SL2015.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // A lane change model for heterogeneous traffic (based on sub-lanes)
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2013-2016 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #ifdef _MSC_VER
26 #include <windows_config.h>
27 #else
28 #include <config.h>
29 #endif
30 
31 #include <iostream>
33 #include <microsim/MSEdge.h>
34 #include <microsim/MSLane.h>
35 #include <microsim/MSNet.h>
36 #include <microsim/MSGlobals.h>
37 #include "MSLCM_SL2015.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 
45 // ===========================================================================
46 // variable definitions
47 // ===========================================================================
48 // 80km/h will be the threshold for dividing between long/short foresight
49 #define LOOK_FORWARD_SPEED_DIVIDER (SUMOReal)14.
50 
51 // VARIANT_1 (lf*2)
52 //#define LOOK_FORWARD_FAR 30.
53 //#define LOOK_FORWARD_NEAR 10.
54 
55 #define LOOK_FORWARD_RIGHT (SUMOReal)10.
56 #define LOOK_FORWARD_LEFT (SUMOReal)20.
57 
58 #define JAM_FACTOR (SUMOReal)1.
59 //#define JAM_FACTOR 2. // VARIANT_8 (makes vehicles more focused but also more "selfish")
60 
61 #define LCA_RIGHT_IMPATIENCE (SUMOReal)-1.
62 #define CUT_IN_LEFT_SPEED_THRESHOLD (SUMOReal)27.
63 #define MAX_ONRAMP_LENGTH (SUMOReal)200.
64 
65 #define LOOK_AHEAD_MIN_SPEED (SUMOReal)0.0
66 #define LOOK_AHEAD_SPEED_MEMORY (SUMOReal)0.9
67 #define LOOK_AHEAD_SPEED_DECREMENT 6.
68 
69 #define HELP_DECEL_FACTOR (SUMOReal)1.0
70 
71 #define HELP_OVERTAKE (SUMOReal)(10.0 / 3.6)
72 #define MIN_FALLBEHIND (SUMOReal)(7.0 / 3.6)
73 
74 #define KEEP_RIGHT_HEADWAY (SUMOReal)2.0
75 
76 #define URGENCY (SUMOReal)2.0
77 
78 #define ROUNDABOUT_DIST_BONUS (SUMOReal)100.0
79 
80 #define KEEP_RIGHT_TIME (SUMOReal)5.0 // the number of seconds after which a vehicle should move to the right lane
81 #define KEEP_RIGHT_ACCEPTANCE (SUMOReal)7.0 // calibration factor for determining the desire to keep right
82 
83 #define RELGAIN_NORMALIZATION_MIN_SPEED (SUMOReal)10.0
84 
85 #define TURN_LANE_DIST (SUMOReal)200.0 // the distance at which a lane leading elsewhere is considered to be a turn-lane that must be avoided
86 #define GAIN_PERCEPTION_THRESHOLD (SUMOReal)0.05 // the minimum relative speed gain which affects the behavior
87 
88 #define SPEED_GAIN_MIN_SECONDS 20.0
89 
90 #define ARRIVALPOS_LAT_THRESHOLD 100.0
91 
92 //#define DEBUG_COND (myVehicle.getID() == "moped.18" || myVehicle.getID() == "moped.16")
93 //#define DEBUG_COND (myVehicle.getID() == "A")
94 #define DEBUG_COND (myVehicle.getID() == "disabled")
95 //#define DEBUG_COND (myVehicle.getID() == "pkw150478" || myVehicle.getID() == "pkw150494" || myVehicle.getID() == "pkw150289")
96 //#define DEBUG_COND (myVehicle.getID() == "A" || myVehicle.getID() == "B") // fail change to left
97 //#define DEBUG_COND (myVehicle.getID() == "disabled") // test stops_overtaking
98 //#define DEBUG_COND false
99 
100 
101 // ===========================================================================
102 // member method definitions
103 // ===========================================================================
106  mySpeedGainProbabilityRight(0),
107  mySpeedGainProbabilityLeft(0),
108  myKeepRightProbability(0),
109  myLeadingBlockerLength(0),
110  myLeftSpace(0),
111  myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED),
112  myLastEdge(0),
113  myCanChangeFully(true),
114  myPreviousState(0),
115  myOrigLatDist(0),
116  myStrategicParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_PARAM, 1)),
117  myCooperativeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_PARAM, 1)),
118  mySpeedGainParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_PARAM, 1)),
119  myKeepRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_PARAM, 1)),
120  mySublaneParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SUBLANE_PARAM, 1)),
121  myPushy(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_PUSHY, 0)),
122  myAssertive(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_ASSERTIVE, 0)),
123  myChangeProbThresholdRight(2.0 * myKeepRightParam / MAX2(NUMERICAL_EPS, mySpeedGainParam)),
124  myChangeProbThresholdLeft(0.2 / MAX2(NUMERICAL_EPS, mySpeedGainParam)),
125  mySpeedLossProbThreshold(-0.01 + (1 - mySublaneParam)) {
127  throw ProcessError("laneChangeModel 'MSLCM_SL2015' is only meant to be used when simulating with '--lateral-resoluion' > 0");
128  }
129 }
130 
132  changed();
133 }
134 
135 
136 bool
138  return DEBUG_COND;
139 }
140 
141 
142 int
144  int laneOffset,
145  const MSLeaderDistanceInfo& leaders,
146  const MSLeaderDistanceInfo& followers,
147  const MSLeaderDistanceInfo& blockers,
148  const MSLeaderDistanceInfo& neighLeaders,
149  const MSLeaderDistanceInfo& neighFollowers,
150  const MSLeaderDistanceInfo& neighBlockers,
151  const MSLane& neighLane,
152  const std::vector<MSVehicle::LaneQ>& preb,
153  MSVehicle** lastBlocked,
154  MSVehicle** firstBlocked,
155  SUMOReal& latDist, int& blocked) {
156 
158  const std::string changeType = laneOffset == -1 ? "right" : (laneOffset == 1 ? "left" : "current");
159 
160 
161  if (gDebugFlag2) {
162  std::cout << "\n" << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
163  //<< std::setprecision(10)
164  << " veh=" << myVehicle.getID()
165  << " lane=" << myVehicle.getLane()->getID()
166  << " pos=" << myVehicle.getPositionOnLane()
167  << " posLat=" << myVehicle.getLateralPositionOnLane()
168  << " speed=" << myVehicle.getSpeed()
169  << " considerChangeTo=" << changeType
170  << "\n";
171  }
172 
173  int result = _wantsChangeSublane(laneOffset,
174  leaders, followers, blockers,
175  neighLeaders, neighFollowers, neighBlockers,
176  neighLane, preb,
177  lastBlocked, firstBlocked, latDist, blocked);
178 
179  if ((result & LCA_STAY) != 0) {
180  // checkBlocking was not called yet
181  assert(latDist == 0);
182  myOrigLatDist = 0;
183  myCanChangeFully = true;
184  }
185 
186  result = keepLatGap(result, leaders, followers, blockers,
187  neighLeaders, neighFollowers, neighBlockers,
188  neighLane, laneOffset, latDist, blocked);
189 
190  result |= getLCA(result, latDist);
191 
192  if (gDebugFlag2) {
193  if (result & LCA_WANTS_LANECHANGE) {
194  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
195  << " veh=" << myVehicle.getID()
196  << " latDist=" << latDist
197  << " state=" << toString((LaneChangeAction)result)
198  << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
199  << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
200  << "\n\n";
201  } else {
202  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
203  << " veh=" << myVehicle.getID()
204  << " wantsNoChangeTo=" << changeType
205  << " state=" << toString((LaneChangeAction)result)
206  << "\n\n";
207  }
208  }
209  gDebugFlag2 = false;
210  return result;
211 }
212 
213 
214 SUMOReal
215 MSLCM_SL2015::patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
217 
218  const SUMOReal newSpeed = _patchSpeed(min, wanted, max, cfModel);
219  if (gDebugFlag2) {
220  const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
221  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
222  << " veh=" << myVehicle.getID()
223  << " lane=" << myVehicle.getLane()->getID()
224  << " pos=" << myVehicle.getPositionOnLane()
225  << " v=" << myVehicle.getSpeed()
226  << " wanted=" << wanted
227  << patched
228  << "\n\n";
229  }
230  gDebugFlag2 = false;
231  return newSpeed;
232 }
233 
234 
235 SUMOReal
236 MSLCM_SL2015::_patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
237 
238  const SUMOReal time = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
239 
240  int state = myOwnState;
241 
242  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
243  SUMOReal MAGIC_offset = 1.;
244  // if we want to change and have a blocking leader and there is enough room for him in front of us
245  if (myLeadingBlockerLength != 0) {
247  if (gDebugFlag2) {
248  std::cout << time << " veh=" << myVehicle.getID() << " myLeadingBlockerLength=" << myLeadingBlockerLength << " space=" << space << "\n";
249  }
250  if (space > 0) { // XXX space > -MAGIC_offset
251  // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
252  SUMOReal safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space);
253  // if we are approaching this place
254  if (safe < wanted) {
255  if (gDebugFlag2) {
256  std::cout << time << " veh=" << myVehicle.getID() << " slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ? " (not enough)" : "") << "\n";
257  }
258  return MAX2(min, safe);
259  }
260  }
261  }
262 
263  SUMOReal nVSafe = wanted;
264  bool gotOne = false;
265  for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
266  SUMOReal v = (*i);
267  if (v >= min && v <= max) {
268  nVSafe = MIN2(v, nVSafe);
269  gotOne = true;
270  if (gDebugFlag2) {
271  std::cout << time << " veh=" << myVehicle.getID() << " got nVSafe=" << nVSafe << "\n";
272  }
273  } else {
274  if (v < min) {
275  if (gDebugFlag2) {
276  std::cout << time << " veh=" << myVehicle.getID() << " ignoring low nVSafe=" << v << " min=" << min << "\n";
277  }
278  } else {
279  if (gDebugFlag2) {
280  std::cout << time << " veh=" << myVehicle.getID() << " ignoring high nVSafe=" << v << " max=" << max << "\n";
281  }
282  }
283  }
284  }
285 
286  if (gotOne && !myDontBrake) {
287  if (gDebugFlag2) {
288  std::cout << time << " veh=" << myVehicle.getID() << " got vSafe\n";
289  }
290  return nVSafe;
291  }
292 
293  // check whether the vehicle is blocked
294  if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) != 0) {
295  if ((state & LCA_STRATEGIC) != 0) {
296  // necessary decelerations are controlled via vSafe. If there are
297  // none it means we should speed up
298  if (gDebugFlag2) {
299  std::cout << time << " veh=" << myVehicle.getID() << " LCA_WANTS_LANECHANGE (strat, no vSafe)\n";
300  }
301  return (max + wanted) / (SUMOReal) 2.0;
302  } else if ((state & LCA_COOPERATIVE) != 0) {
303  // only minor adjustments in speed should be done
304  if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
305  if (gDebugFlag2) {
306  std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_LEADER (coop)\n";
307  }
308  return (min + wanted) / (SUMOReal) 2.0;
309  }
310  if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
311  if (gDebugFlag2) {
312  std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER (coop)\n";
313  }
314  return (max + wanted) / (SUMOReal) 2.0;
315  }
316  //} else { // VARIANT_16
317  // // only accelerations should be performed
318  // if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
319  // if (gDebugFlag2) std::cout << time << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER\n";
320  // return (max + wanted) / (SUMOReal) 2.0;
321  // }
322  }
323  }
324 
325  /*
326  // decelerate if being a blocking follower
327  // (and does not have to change lanes)
328  if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
329  if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
330  if (gDebugFlag2) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER (standing)\n";
331  return 0;
332  }
333  if (gDebugFlag2) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER\n";
334 
335  //return min; // VARIANT_3 (brakeStrong)
336  return (min + wanted) / (SUMOReal) 2.0;
337  }
338  if ((state & LCA_AMBACKBLOCKER) != 0) {
339  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
340  if (gDebugFlag2) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER (standing)\n";
341  //return min; VARIANT_9 (backBlockVSafe)
342  return nVSafe;
343  }
344  }
345  if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
346  if (gDebugFlag2) std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER_STANDING\n";
347  //return min;
348  return nVSafe;
349  }
350  */
351 
352  // accelerate if being a blocking leader or blocking follower not able to brake
353  // (and does not have to change lanes)
354  if ((state & LCA_AMBLOCKINGLEADER) != 0) {
355  if (gDebugFlag2) {
356  std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGLEADER\n";
357  }
358  return (max + wanted) / (SUMOReal) 2.0;
359  }
360 
361  if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
362  if (gDebugFlag2) {
363  std::cout << time << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER_DONTBRAKE\n";
364  }
365  /*
366  // VARIANT_4 (dontbrake)
367  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
368  return wanted;
369  }
370  return (min + wanted) / (SUMOReal) 2.0;
371  */
372  }
373  return wanted;
374 }
375 
376 
377 void*
378 MSLCM_SL2015::inform(void* info, MSVehicle* sender) {
379  Info* pinfo = (Info*) info;
380  if (pinfo->first >= 0) {
381  myVSafes.push_back(pinfo->first);
382  }
383  //myOwnState &= 0xffffffff; // reset all bits of MyLCAEnum but only those
384  myOwnState |= pinfo->second;
385  if (gDebugFlag2 || DEBUG_COND) {
386  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
387  << " veh=" << myVehicle.getID()
388  << " informedBy=" << sender->getID()
389  << " info=" << pinfo->second
390  << " vSafe=" << pinfo->first
391  << "\n";
392  }
393  delete pinfo;
394  return (void*) true;
395 }
396 
397 
398 void
399 MSLCM_SL2015::msg(const CLeaderDist& cld, SUMOReal speed, int state) {
400  assert(cld.first != 0);
401  ((MSVehicle*)cld.first)->getLaneChangeModel().inform(new Info(speed, state), &myVehicle);
402 }
403 
404 
405 SUMOReal
407  int dir,
408  const CLeaderDist& neighLead,
409  SUMOReal remainingSeconds) {
410  SUMOReal plannedSpeed = MIN2(myVehicle.getSpeed(),
412  for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
413  SUMOReal v = (*i);
415  plannedSpeed = MIN2(plannedSpeed, v);
416  }
417  }
418  if (gDebugFlag2) {
419  std::cout << " informLeader speed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
420  }
421 
422  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
423  assert(neighLead.first != 0);
424  const MSVehicle* nv = neighLead.first;
425  if (gDebugFlag2) std::cout << " blocked by leader nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
427  // decide whether we want to overtake the leader or follow it
428  const SUMOReal dv = plannedSpeed - nv->getSpeed();
429  const SUMOReal overtakeDist = (neighLead.second // drive to back of follower
430  + nv->getVehicleType().getLengthWithGap() // drive to front of follower
431  + myVehicle.getVehicleType().getLength() // ego back reaches follower front
432  + nv->getCarFollowModel().getSecureGap( // save gap to follower
434 
435  if (dv < 0
436  // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft)
438  // not enough space to overtake? (we will start to brake when approaching a dead end)
440  // not enough time to overtake?
441  || dv * remainingSeconds < overtakeDist) {
442  // cannot overtake
443  msg(neighLead, -1, dir | LCA_AMBLOCKINGLEADER);
444  // slow down smoothly to follow leader
445  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
446  &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
447  if (targetSpeed < myVehicle.getSpeed()) {
448  // slow down smoothly to follow leader
450  MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds)));
451  //const SUMOReal nextSpeed = MAX2((SUMOReal)0, MIN2(plannedSpeed, myVehicle.getSpeed() - decel));
452  const SUMOReal nextSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() - decel);
453  if (gDebugFlag2) {
454  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
455  << " cannot overtake leader nv=" << nv->getID()
456  << " dv=" << dv
457  << " remainingSeconds=" << remainingSeconds
458  << " targetSpeed=" << targetSpeed
459  << " nextSpeed=" << nextSpeed
460  << "\n";
461  }
462  myVSafes.push_back(nextSpeed);
463  return nextSpeed;
464  } else {
465  // leader is fast enough anyway
466  if (gDebugFlag2) {
467  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
468  << " cannot overtake fast leader nv=" << nv->getID()
469  << " dv=" << dv
470  << " remainingSeconds=" << remainingSeconds
471  << " targetSpeed=" << targetSpeed
472  << "\n";
473  }
474  myVSafes.push_back(targetSpeed);
475  return plannedSpeed;
476  }
477  } else {
478  if (gDebugFlag2) {
479  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
480  << " wants to overtake leader nv=" << nv->getID()
481  << " dv=" << dv
482  << " remainingSeconds=" << remainingSeconds
483  << " currentGap=" << neighLead.second
485  << " overtakeDist=" << overtakeDist
486  << "\n";
487  }
488  // overtaking, leader should not accelerate
489  msg(neighLead, nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER);
490  return -1;
491  }
492  } else if (neighLead.first != 0) { // (remainUnblocked)
493  // we are not blocked now. make sure we stay far enough from the leader
494  const MSVehicle* nv = neighLead.first;
495  const SUMOReal nextNVSpeed = nv->getSpeed() - HELP_OVERTAKE; // conservative
496  const SUMOReal dv = SPEED2DIST(myVehicle.getSpeed() - nextNVSpeed);
497  const SUMOReal targetSpeed = myCarFollowModel.followSpeed(
498  &myVehicle, myVehicle.getSpeed(), neighLead.second - dv, nextNVSpeed, nv->getCarFollowModel().getMaxDecel());
499  myVSafes.push_back(targetSpeed);
500  if (gDebugFlag2) {
501  std::cout << " not blocked by leader nv=" << nv->getID()
502  << " nvSpeed=" << nv->getSpeed()
503  << " gap=" << neighLead.second
504  << " nextGap=" << neighLead.second - dv
506  << " targetSpeed=" << targetSpeed
507  << "\n";
508  }
509  return MIN2(targetSpeed, plannedSpeed);
510  } else {
511  // not overtaking
512  return plannedSpeed;
513  }
514 }
515 
516 
517 void
519  int dir,
520  const CLeaderDist& neighFollow,
521  SUMOReal remainingSeconds,
522  SUMOReal plannedSpeed) {
523  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
524  assert(neighFollow.first != 0);
525  const MSVehicle* nv = neighFollow.first;
526  if (gDebugFlag2) std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
528 
529  // are we fast enough to cut in without any help?
530  if (plannedSpeed - nv->getSpeed() >= HELP_OVERTAKE) {
531  const SUMOReal neededGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
532  if ((neededGap - neighFollow.second) / remainingSeconds < (plannedSpeed - nv->getSpeed())) {
533  if (gDebugFlag2) {
534  std::cout << " wants to cut in before nv=" << nv->getID() << " without any help neededGap=" << neededGap << "\n";
535  }
536  // follower might even accelerate but not to much
537  msg(neighFollow, plannedSpeed - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER);
538  return;
539  }
540  }
541  // decide whether we will request help to cut in before the follower or allow to be overtaken
542 
543  // PARAMETERS
544  // assume other vehicle will assume the equivalent of 1 second of
545  // maximum deceleration to help us (will probably be spread over
546  // multiple seconds)
547  // -----------
548  const SUMOReal helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR ;
549 
550  // change in the gap between ego and blocker over 1 second (not STEP!)
551  const SUMOReal neighNewSpeed = MAX2((SUMOReal)0, nv->getSpeed() - ACCEL2SPEED(helpDecel));
552  const SUMOReal neighNewSpeed1s = MAX2((SUMOReal)0, nv->getSpeed() - helpDecel);
553  const SUMOReal dv = plannedSpeed - neighNewSpeed1s;
554  // new gap between follower and self in case the follower does brake for 1s
555  const SUMOReal decelGap = neighFollow.second + dv;
556  const SUMOReal secureGap = nv->getCarFollowModel().getSecureGap(neighNewSpeed1s, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
557  if (gDebugFlag2) {
558  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
559  << " egoV=" << myVehicle.getSpeed()
560  << " egoNV=" << plannedSpeed
561  << " nvNewSpeed=" << neighNewSpeed
562  << " nvNewSpeed1s=" << neighNewSpeed1s
563  << " deltaGap=" << dv
564  << " decelGap=" << decelGap
565  << " secGap=" << secureGap
566  << "\n";
567  }
568  if (decelGap > 0 && decelGap >= secureGap) {
569  // if the blocking neighbor brakes it could actually help
570  // how hard does it actually need to be?
571  // to be safe in the next step the following equation has to hold:
572  // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
573  // we compute an upper bound on vsafe by doing the computation twice
574  const SUMOReal vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
575  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel()));
576  const SUMOReal vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
577  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel()));
578  // the following assertion cannot be guaranteed because the CFModel handles small gaps differently, see MSCFModel::maximumSafeStopSpeed
579  // assert(vsafe <= vsafe1);
580  msg(neighFollow, vsafe, dir | LCA_AMBLOCKINGFOLLOWER);
581  if (gDebugFlag2) {
582  std::cout << " wants to cut in before nv=" << nv->getID()
583  << " vsafe1=" << vsafe1
584  << " vsafe=" << vsafe
585  << " newSecGap=" << nv->getCarFollowModel().getSecureGap(vsafe, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel())
586  << "\n";
587  }
588  } else if (dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS)) {
589  // decelerating once is sufficient to open up a large enough gap in time
590  msg(neighFollow, neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER);
591  if (gDebugFlag2) {
592  std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
593  }
594  } else if (dir == LCA_MRIGHT && !myAllowOvertakingRight && !nv->congested()) {
595  const SUMOReal vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
596  msg(neighFollow, vhelp, dir | LCA_AMBLOCKINGFOLLOWER);
597  if (gDebugFlag2) {
598  std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
599  }
600  } else {
602  if (nv->getSpeed() > myVehicle.getSpeed() &&
604  || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
605  // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
606  || (dir == LCA_MLEFT && myLeftSpace > MAX_ONRAMP_LENGTH)
607  )) {
608  // let the follower slow down to increase the likelyhood that later vehicles will be slow enough to help
609  // follower should still be fast enough to open a gap
610  vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
611  if (gDebugFlag2) {
612  std::cout << " wants right follower to slow down a bit\n";
613  }
614  if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
615  if (gDebugFlag2) {
616  std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
617  }
618  msg(neighFollow, vhelp, dir | LCA_AMBLOCKINGFOLLOWER);
619  return;
620  }
621  }
622  msg(neighFollow, vhelp, dir | LCA_AMBLOCKINGFOLLOWER);
623  // this follower is supposed to overtake us. slow down smoothly to allow this
624  const SUMOReal overtakeDist = (neighFollow.second // follower reaches ego back
625  + myVehicle.getVehicleType().getLengthWithGap() // follower reaches ego front
626  + nv->getVehicleType().getLength() // follower back at ego front
627  + myVehicle.getCarFollowModel().getSecureGap( // follower has safe dist to ego
628  plannedSpeed, vhelp, nv->getCarFollowModel().getMaxDecel()));
629  // speed difference to create a sufficiently large gap
630  const SUMOReal needDV = overtakeDist / remainingSeconds;
631  // make sure the deceleration is not to strong
632  myVSafes.push_back(MAX2(vhelp - needDV, myVehicle.getSpeed() - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())));
633 
634  if (gDebugFlag2) {
635  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
636  << " veh=" << myVehicle.getID()
637  << " wants to be overtaken by=" << nv->getID()
638  << " overtakeDist=" << overtakeDist
639  << " vneigh=" << nv->getSpeed()
640  << " vhelp=" << vhelp
641  << " needDV=" << needDV
642  << " vsafe=" << myVSafes.back()
643  << "\n";
644  }
645  }
646  } else if (neighFollow.first != 0) {
647  // we are not blocked no, make sure it remains that way
648  const MSVehicle* nv = neighFollow.first;
649  const SUMOReal vsafe1 = nv->getCarFollowModel().followSpeed(
650  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
651  const SUMOReal vsafe = nv->getCarFollowModel().followSpeed(
652  nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
653  msg(neighFollow, vsafe, dir | LCA_AMBLOCKINGFOLLOWER);
654  if (gDebugFlag2) {
655  std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
656  }
657  }
658 }
659 
660 SUMOReal
661 MSLCM_SL2015::informLeaders(int blocked, int dir,
662  const std::vector<CLeaderDist>& blockers,
663  SUMOReal remainingSeconds) {
664  SUMOReal plannedSpeed = myVehicle.getSpeed();
665  for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
666  plannedSpeed = MIN2(plannedSpeed, informLeader(blocked, dir, *it, remainingSeconds));
667  }
668  return plannedSpeed;
669 }
670 
671 
672 void
673 MSLCM_SL2015::informFollowers(int blocked, int dir,
674  const std::vector<CLeaderDist>& blockers,
675  SUMOReal remainingSeconds,
676  SUMOReal plannedSpeed) {
677  for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
678  informFollower(blocked, dir, *it, remainingSeconds, plannedSpeed);
679  }
680 }
681 
682 
683 void
685  // keep information about strategic change direction
687  if (myCanChangeFully) {
688  myOrigLatDist = 0;
689  }
691  myLeftSpace = 0;
692  myVSafes.clear();
693  myDontBrake = false;
694  // truncate to work around numerical instability between different builds
695  mySpeedGainProbabilityRight = ceil(mySpeedGainProbabilityRight * 100000.0) * 0.00001;
696  mySpeedGainProbabilityLeft = ceil(mySpeedGainProbabilityLeft * 100000.0) * 0.00001;
697  myKeepRightProbability = ceil(myKeepRightProbability * 100000.0) * 0.00001;
698  // updated myExpectedSublaneSpeeds
699  // XXX only do this when (sub)lane changing is possible
700  std::vector<SUMOReal> newExpectedSpeeds;
701  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myExpectedSublaneSpeeds=" << toString(myExpectedSublaneSpeeds) << "\n";
702  if (myExpectedSublaneSpeeds.size() != myVehicle.getLane()->getEdge().getSubLaneSides().size()) {
703  // initialize
704  const MSEdge* currEdge = &myVehicle.getLane()->getEdge();
705  const std::vector<MSLane*>& lanes = currEdge->getLanes();
706  for (std::vector<MSLane*>::const_iterator it_lane = lanes.begin(); it_lane != lanes.end(); ++it_lane) {
707  const int subLanes = MAX2(1, int(ceil((*it_lane)->getWidth() / MSGlobals::gLateralResolution)));
708  for (int i = 0; i < subLanes; ++i) {
709  newExpectedSpeeds.push_back((*it_lane)->getVehicleMaxSpeed(&myVehicle));
710  }
711  }
712  if (myExpectedSublaneSpeeds.size() > 0) {
713  // copy old values
714  assert(myLastEdge != 0);
715  if (myLastEdge->getSubLaneSides().size() == myExpectedSublaneSpeeds.size()) {
716  const int subLaneShift = computeSublaneShift(myLastEdge, currEdge);
717  if (subLaneShift < std::numeric_limits<int>::max()) {
718  for (int i = 0; i < (int)myExpectedSublaneSpeeds.size(); ++i) {
719  const int newI = i + subLaneShift;
720  if (newI > 0 && newI < (int)newExpectedSpeeds.size()) {
721  newExpectedSpeeds[newI] = myExpectedSublaneSpeeds[i];
722  }
723  }
724  }
725  }
726  }
727  myExpectedSublaneSpeeds = newExpectedSpeeds;
728  myLastEdge = currEdge;
729  }
730  assert(myExpectedSublaneSpeeds.size() == myVehicle.getLane()->getEdge().getSubLaneSides().size());
731 }
732 
733 
734 int
735 MSLCM_SL2015::computeSublaneShift(const MSEdge* prevEdge, const MSEdge* curEdge) {
736  // find the first lane that targets the new edge
737  int prevShift = 0;
738  const std::vector<MSLane*>& lanes = prevEdge->getLanes();
739  for (std::vector<MSLane*>::const_iterator it_lane = lanes.begin(); it_lane != lanes.end(); ++it_lane) {
740  const MSLane* lane = *it_lane;
741  for (MSLinkCont::const_iterator it_link = lane->getLinkCont().begin(); it_link != lane->getLinkCont().end(); ++it_link) {
742  if (&((*it_link)->getLane()->getEdge()) == curEdge) {
743  int curShift = 0;
744  const MSLane* target = (*it_link)->getLane();
745  const std::vector<MSLane*>& lanes2 = curEdge->getLanes();
746  for (std::vector<MSLane*>::const_iterator it_lane2 = lanes2.begin(); it_lane2 != lanes2.end(); ++it_lane2) {
747  const MSLane* lane2 = *it_lane2;
748  if (lane2 == target) {
749  return prevShift + curShift;
750  }
751  MSLeaderInfo ahead(lane2);
752  curShift += ahead.numSublanes();
753  }
754  assert(false);
755  }
756  }
757  MSLeaderInfo ahead(lane);
758  prevShift -= ahead.numSublanes();
759  }
761 }
762 
763 
764 void
766  if (!myCanChangeFully) {
767  // do not reset state yet
768  if (DEBUG_COND) {
769  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " state not reset\n";
770  }
771  return;
772  }
773  myOwnState = 0;
774  // XX do not reset values for unfinished maneuvers
778 
779  if (myVehicle.getBestLaneOffset() == 0) {
780  // if we are not yet on our best lane there might still be unseen blockers
781  // (during patchSpeed)
783  myLeftSpace = 0;
784  }
786  myVSafes.clear();
787  myDontBrake = false;
788  if (DEBUG_COND) {
789  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " changed()\n";
790  }
791 }
792 
793 
794 int
796  int laneOffset,
797  const MSLeaderDistanceInfo& leaders,
798  const MSLeaderDistanceInfo& followers,
799  const MSLeaderDistanceInfo& blockers,
800  const MSLeaderDistanceInfo& neighLeaders,
801  const MSLeaderDistanceInfo& neighFollowers,
802  const MSLeaderDistanceInfo& neighBlockers,
803  const MSLane& neighLane,
804  const std::vector<MSVehicle::LaneQ>& preb,
805  MSVehicle** lastBlocked,
806  MSVehicle** firstBlocked,
807  SUMOReal& latDist, int& blocked) {
808 
809  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
810  // compute bestLaneOffset
811  MSVehicle::LaneQ curr, neigh;
812  int bestLaneOffset = 0;
813  SUMOReal currentDist = 0;
814  SUMOReal neighDist = 0;
815  int currIdx = 0;
816  MSLane* prebLane = myVehicle.getLane();
817  if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
818  // internal edges are not kept inside the bestLanes structure
819  prebLane = prebLane->getLinkCont()[0]->getLane();
820  }
821  for (int p = 0; p < (int) preb.size(); ++p) {
822  if (preb[p].lane == prebLane && p + laneOffset >= 0) {
823  assert(p + laneOffset < (int)preb.size());
824  curr = preb[p];
825  neigh = preb[p + laneOffset];
826  currentDist = curr.length;
827  neighDist = neigh.length;
828  bestLaneOffset = curr.bestLaneOffset;
829  // VARIANT_13 (equalBest)
830  if (bestLaneOffset == 0 && preb[p + laneOffset].bestLaneOffset == 0) {
831  if (gDebugFlag2) {
832  std::cout << STEPS2TIME(currentTime)
833  << " veh=" << myVehicle.getID()
834  << " bestLaneOffsetOld=" << bestLaneOffset
835  << " bestLaneOffsetNew=" << laneOffset
836  << "\n";
837  }
838  bestLaneOffset = laneOffset;
839  }
840  currIdx = p;
841  break;
842  }
843  }
844  // direction specific constants
845  const bool right = (laneOffset == -1);
846  const bool left = (laneOffset == 1);
847  const int myLca = (right ? LCA_MRIGHT : (left ? LCA_MLEFT : 0));
848  const int lcaCounter = (right ? LCA_LEFT : (left ? LCA_RIGHT : LCA_NONE));
849  const int myLcaCounter = (right ? LCA_MLEFT : LCA_MRIGHT);
850  const bool changeToBest = (right && bestLaneOffset < 0) || (left && bestLaneOffset > 0) || (laneOffset == 0 && bestLaneOffset == 0);
851  // keep information about being a leader/follower but remove information
852  // about previous lane change request or urgency
853  int ret = (myOwnState & 0xffff0000);
854 
855  // compute the distance when changing to the neighboring lane
856  // (ensure we do not lap into the line behind neighLane since there might be unseen blockers)
857  const SUMOReal halfCurrentLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
858  const SUMOReal halfVehWidth = 0.5 * myVehicle.getVehicleType().getWidth();
860  SUMOReal leftLimit = halfCurrentLaneWidth - halfVehWidth - latPos;
861  SUMOReal rightLimit = -halfCurrentLaneWidth + halfVehWidth - latPos;
862  SUMOReal latLaneDist = 0; // minimum distance to move the vehicle fully onto the new lane
863  if (laneOffset == -1) {
864  latLaneDist = rightLimit - myVehicle.getVehicleType().getWidth();
865  rightLimit -= neighLane.getWidth();
866  } else if (laneOffset == 1) {
867  latLaneDist = leftLimit + myVehicle.getVehicleType().getWidth();
868  leftLimit += neighLane.getWidth();
869  }
870  // VARIANT_5 (disableAMBACKBLOCKER1)
871  /*
872  if (leader.first != 0
873  && (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0
874  && (leader.first->getLaneChangeModel().getOwnState() & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
875 
876  myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE);
877  if (myVehicle.getSpeed() > SUMO_const_haltingSpeed) {
878  myOwnState |= LCA_AMBACKBLOCKER;
879  } else {
880  ret |= LCA_AMBACKBLOCKER;
881  myDontBrake = true;
882  }
883  }
884  */
885 
886  if (gDebugFlag2) {
887  std::cout << STEPS2TIME(currentTime)
888  << " veh=" << myVehicle.getID()
889  << " myState=" << toString((LaneChangeAction)myOwnState)
890  << " firstBlocked=" << Named::getIDSecure(*firstBlocked)
891  << " lastBlocked=" << Named::getIDSecure(*lastBlocked)
892  << " leaders=" << leaders.toString()
893  << " followers=" << followers.toString()
894  << " blockers=" << blockers.toString()
895  << " neighLeaders=" << neighLeaders.toString()
896  << " neighFollowers=" << neighFollowers.toString()
897  << " neighBlockers=" << neighBlockers.toString()
898  << " changeToBest=" << changeToBest
899  << " latLaneDist=" << latLaneDist
900  << " leftLimit=" << leftLimit
901  << " rightLimit=" << rightLimit
902  << " expectedSpeeds=" << toString(myExpectedSublaneSpeeds)
903  << "\n";
904  }
905 
906  ret = slowDownForBlocked(lastBlocked, ret);
907  // VARIANT_14 (furtherBlock)
908  if (lastBlocked != firstBlocked) {
909  ret = slowDownForBlocked(firstBlocked, ret);
910  }
911 
912 
913  // we try to estimate the distance which is necessary to get on a lane
914  // we have to get on in order to keep our route
915  // we assume we need something that depends on our velocity
916  // and compare this with the free space on our wished lane
917  //
918  // if the free space is somehow less than the space we need, we should
919  // definitely try to get to the desired lane
920  //
921  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
922  // lookAheadDistance:
923  // we do not want the lookahead distance to change all the time so we discrectize the speed a bit
924 
925  // VARIANT_18 (laHyst)
928  } else {
931  }
932  //myLookAheadSpeed = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
933 
934  //SUMOReal laDist = laSpeed > LOOK_FORWARD_SPEED_DIVIDER
935  // ? laSpeed * LOOK_FORWARD_FAR
936  // : laSpeed * LOOK_FORWARD_NEAR;
938  laDist += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.;
939 
940  // react to a stopped leader on the current lane
941  if (bestLaneOffset == 0 && leaders.hasStoppedVehicle()) {
942  // value is doubled for the check since we change back and forth
943  // laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap() + leader.first->getVehicleType().getLengthWithGap());
944  // XXX determine lenght of longest stopped vehicle
946  }
947 
948  // free space that is available for changing
949  //const SUMOReal neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
950  // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
951  // best.lane->getSpeedLimit());
952  // @note: while this lets vehicles change earlier into the correct direction
953  // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
954 
955  // VARIANT_15 (insideRoundabout)
956  int roundaboutEdgesAhead = 0;
957  for (std::vector<MSLane*>::iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) {
958  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
959  roundaboutEdgesAhead += 1;
960  } else if (roundaboutEdgesAhead > 0) {
961  // only check the next roundabout
962  break;
963  }
964  }
965  int roundaboutEdgesAheadNeigh = 0;
966  for (std::vector<MSLane*>::iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) {
967  if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
968  roundaboutEdgesAheadNeigh += 1;
969  } else if (roundaboutEdgesAheadNeigh > 0) {
970  // only check the next roundabout
971  break;
972  }
973  }
974  if (roundaboutEdgesAhead > 1) {
975  currentDist += roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS * myCooperativeParam;
976  neighDist += roundaboutEdgesAheadNeigh * ROUNDABOUT_DIST_BONUS * myCooperativeParam;
977  }
978  if (roundaboutEdgesAhead > 0) {
979  if (gDebugFlag2) {
980  std::cout << " roundaboutEdgesAhead=" << roundaboutEdgesAhead << " roundaboutEdgesAheadNeigh=" << roundaboutEdgesAheadNeigh << "\n";
981  }
982  }
983 
984  if (laneOffset != 0) {
985  ret = checkStrategicChange(ret,
986  laneOffset,
987  preb,
988  leaders,
989  neighLeaders,
990  currIdx,
991  bestLaneOffset,
992  changeToBest,
993  lcaCounter,
994  currentDist,
995  neighDist,
996  laDist,
997  roundaboutEdgesAhead);
998  }
999 
1000  if ((ret & LCA_STAY) != 0) {
1001  return ret;
1002  }
1003  if ((ret & LCA_URGENT) != 0) {
1004  // prepare urgent lane change maneuver
1005  // save the left space
1006  myLeftSpace = currentDist - myVehicle.getPositionOnLane();
1007  if (changeToBest && abs(bestLaneOffset) > 1) {
1008  // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1009  if (gDebugFlag2) {
1010  std::cout << " reserving space for unseen blockers\n";
1011  }
1012  myLeadingBlockerLength = MAX2((SUMOReal)(right ? 20.0 : 40.0), myLeadingBlockerLength);
1013  }
1014 
1015  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1016  // if there is a leader and he wants to change to the opposite direction
1017  const MSVehicle* neighLeadLongest = getLongest(neighLeaders).first;
1018  saveBlockerLength(neighLeadLongest, lcaCounter);
1019  if (*firstBlocked != neighLeadLongest) {
1020  saveBlockerLength(*firstBlocked, lcaCounter);
1021  }
1022  latDist = latLaneDist;
1023  std::vector<CLeaderDist> collectLeadBlockers;
1024  std::vector<CLeaderDist> collectFollowBlockers;
1025 
1026  blocked = checkBlocking(neighLane, latDist, laneOffset,
1027  leaders, followers, blockers,
1028  neighLeaders, neighFollowers, neighBlockers, &collectLeadBlockers, &collectFollowBlockers);
1029 
1030  const SUMOReal remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1033  const SUMOReal plannedSpeed = informLeaders(blocked, myLca, collectLeadBlockers, remainingSeconds);
1034  // coordinate with direct obstructions
1035  if (plannedSpeed >= 0) {
1036  // maybe we need to deal with a blocking follower
1037  informFollowers(blocked, myLca, collectFollowBlockers, remainingSeconds, plannedSpeed);
1038  }
1039 
1040  if (gDebugFlag2) {
1041  std::cout << STEPS2TIME(currentTime)
1042  << " veh=" << myVehicle.getID()
1043  << " myLeftSpace=" << myLeftSpace
1044  << " remainingSeconds=" << remainingSeconds
1045  << " plannedSpeed=" << plannedSpeed
1046  << "\n";
1047  }
1048  return ret;
1049  }
1050 
1051  // VARIANT_15
1052  if (roundaboutEdgesAhead > 1) {
1053  // try to use the inner lanes of a roundabout to increase throughput
1054  // unless we are approaching the exit
1055  if (left) {
1056  ret |= LCA_COOPERATIVE;
1057  } else {
1058  ret |= LCA_STAY | LCA_COOPERATIVE;
1059  }
1060  if (!cancelRequest(ret)) {
1061  if ((ret & LCA_STAY) == 0) {
1062  latDist = latLaneDist;
1063  blocked = checkBlocking(neighLane, latDist, laneOffset,
1064  leaders, followers, blockers,
1065  neighLeaders, neighFollowers, neighBlockers);
1066  }
1067  return ret;
1068  }
1069  }
1070 
1071  // --------
1072 
1073  // -------- make place on current lane if blocking follower
1074  //if (amBlockingFollowerPlusNB()) {
1075  // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1076  // << " neighDist=" << neighDist
1077  // << " currentDist=" << currentDist
1078  // << "\n";
1079  //}
1080  const SUMOReal inconvenience = (latLaneDist < 0
1083  if (laneOffset != 0
1085  && (inconvenience < myCooperativeParam)
1086  //&& ((myOwnState & myLcaCounter) == 0) // VARIANT_6 : counterNoHelp
1087  && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1088 
1089  // VARIANT_2 (nbWhenChangingToHelp)
1090  if (gDebugFlag2) {
1091  std::cout << STEPS2TIME(currentTime)
1092  << " veh=" << myVehicle.getID()
1093  << " wantsChangeToHelp=" << (right ? "right" : "left")
1094  << " state=" << myOwnState
1095  << (((myOwnState & myLcaCounter) != 0) ? " (counter)" : "")
1096  << "\n";
1097  }
1098 
1099  ret |= LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1100  if (!cancelRequest(ret)) {
1101  latDist = latLaneDist;
1102  blocked = checkBlocking(neighLane, latDist, laneOffset,
1103  leaders, followers, blockers,
1104  neighLeaders, neighFollowers, neighBlockers);
1105  return ret;
1106  }
1107  }
1108 
1109  // --------
1110 
1111 
1114  //if ((blocked & LCA_BLOCKED) != 0) {
1115  // return ret;
1116  //}
1118 
1119  // -------- higher speed
1120  //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1121  // return ret;
1122  //}
1123 
1124  // iterate over all possible combinations of sublanes this vehicle might cover and check the potential speed
1125  const MSEdge& edge = myVehicle.getLane()->getEdge();
1126  const std::vector<SUMOReal>& sublaneSides = edge.getSubLaneSides();
1127  assert(sublaneSides.size() == myExpectedSublaneSpeeds.size());
1128  const SUMOReal vehWidth = myVehicle.getVehicleType().getWidth();
1129  const SUMOReal rightVehSide = myVehicle.getRightSideOnEdge();
1130  const SUMOReal leftVehSide = rightVehSide + vehWidth;
1131  // figure out next speed when staying where we are
1132  SUMOReal defaultNextSpeed = std::numeric_limits<SUMOReal>::max();
1134  int leftmostOnEdge = (int)sublaneSides.size() - 1;
1135  while (leftmostOnEdge > 0 && sublaneSides[leftmostOnEdge] > leftVehSide) {
1136  leftmostOnEdge--;
1137  }
1138  int rightmostOnEdge = leftmostOnEdge;
1139  while (rightmostOnEdge > 0 && sublaneSides[rightmostOnEdge] > rightVehSide + NUMERICAL_EPS) {
1140  defaultNextSpeed = MIN2(defaultNextSpeed, myExpectedSublaneSpeeds[rightmostOnEdge]);
1141  if (gDebugFlag2) {
1142  std::cout << " adapted to current sublane=" << rightmostOnEdge << " defaultNextSpeed=" << defaultNextSpeed << "\n";
1143  }
1144  if (gDebugFlag2) {
1145  std::cout << " sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] << " rightVehSide=" << rightVehSide << "\n";
1146  }
1147  rightmostOnEdge--;
1148  }
1149  defaultNextSpeed = MIN2(defaultNextSpeed, myExpectedSublaneSpeeds[rightmostOnEdge]);
1150  if (gDebugFlag2) {
1151  std::cout << " adapted to current sublane=" << rightmostOnEdge << " defaultNextSpeed=" << defaultNextSpeed << "\n";
1152  }
1153  if (gDebugFlag2) {
1154  std::cout << " sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] << " rightVehSide=" << rightVehSide << "\n";
1155  }
1157  SUMOReal maxGainRight = -std::numeric_limits<SUMOReal>::max();
1160 
1161  const int iMin = MIN2(myVehicle.getLane()->getRightmostSublane(), neighLane.getRightmostSublane());
1162  const SUMOReal leftMax = MAX2(
1164  neighLane.getRightSideOnEdge() + neighLane.getWidth());
1165  assert(leftMax <= edge.getWidth());
1166  int sublaneCompact = MAX2(iMin, rightmostOnEdge - 1); // try to compactify to the right by default
1167 
1168  if (gDebugFlag2) std::cout
1169  << " checking sublanes rightmostOnEdge=" << rightmostOnEdge
1170  << " leftmostOnEdge=" << leftmostOnEdge
1171  << " iMin=" << iMin
1172  << " leftMax=" << leftMax
1173  << " sublaneCompact=" << sublaneCompact
1174  << "\n";
1175  for (int i = iMin; i < (int)sublaneSides.size(); ++i) {
1176  if (sublaneSides[i] + vehWidth < leftMax) {
1177  // i is the rightmost sublane and the left side of vehicles still fits on the edge,
1178  // compute min speed of all sublanes covered by the vehicle in this case
1180  //std::cout << " i=" << i << "\n";
1181  int j = i;
1182  while (vMin > 0 && j < (int)sublaneSides.size() && sublaneSides[j] < sublaneSides[i] + vehWidth) {
1183  vMin = MIN2(vMin, myExpectedSublaneSpeeds[j]);
1184  //std::cout << " j=" << j << " vMin=" << vMin << " sublaneSides[j]=" << sublaneSides[j] << " leftVehSide=" << leftVehSide << " rightVehSide=" << rightVehSide << "\n";
1185  ++j;
1186  }
1187  const SUMOReal relativeGain = (vMin - defaultNextSpeed) / MAX2(vMin, RELGAIN_NORMALIZATION_MIN_SPEED);
1188  // @note this is biased for changing to the left since we compare the sublanes in ascending order
1189  if (relativeGain > GAIN_PERCEPTION_THRESHOLD && relativeGain > maxGain) {
1190  maxGain = relativeGain;
1191  sublaneCompact = i;
1192  if (maxGain > 0) {
1193  latDist = sublaneSides[i] - rightVehSide;
1194  if (gDebugFlag2) {
1195  std::cout << " i=" << i << " newLatDist=" << latDist << " relGain=" << relativeGain << "\n";
1196  }
1197  }
1198  }
1199  if (gDebugFlag2) {
1200  std::cout << " i=" << i << " rightmostOnEdge=" << rightmostOnEdge << " vMin=" << vMin << " relGain=" << relativeGain << " sublaneCompact=" << sublaneCompact << "\n";
1201  }
1202  if (i < rightmostOnEdge) {
1203  maxGainRight = MAX2(maxGainRight, relativeGain);
1204  } else if (i > rightmostOnEdge) {
1205  maxGainLeft = MAX2(maxGainLeft, relativeGain);
1206  }
1207  const SUMOReal subAlignDist = sublaneSides[i] - rightVehSide;
1208  if (fabs(subAlignDist) < fabs(latDistNice)) {
1209  latDistNice = subAlignDist;
1210  if (gDebugFlag2) std::cout
1211  << " nicest sublane=" << i
1212  << " side=" << sublaneSides[i]
1213  << " rightSide=" << rightVehSide
1214  << " latDistNice=" << latDistNice
1215  << "\n";
1216  }
1217  }
1218  }
1219  // updated change probabilities
1220  if (maxGainRight != -std::numeric_limits<SUMOReal>::max()) {
1221  mySpeedGainProbabilityRight += TS * maxGainRight;
1222  }
1223  if (maxGainLeft != -std::numeric_limits<SUMOReal>::max()) {
1224  mySpeedGainProbabilityLeft += TS * maxGainLeft;
1225  }
1226  // decay
1227  if (maxGainRight < NUMERICAL_EPS) {
1228  mySpeedGainProbabilityRight *= pow(0.5, TS);
1229  }
1230  if (maxGainLeft < NUMERICAL_EPS) {
1231  mySpeedGainProbabilityLeft *= pow(0.5, TS);
1232  }
1233 
1234 
1235  if (gDebugFlag2) std::cout << SIMTIME
1236  << " veh=" << myVehicle.getID()
1237  << " defaultNextSpeed=" << defaultNextSpeed
1238  << " maxGain=" << maxGain
1239  << " maxGainRight=" << maxGainRight
1240  << " maxGainLeft=" << maxGainLeft
1241  << " latDist=" << latDist
1242  << " latDistNice=" << latDistNice
1243  << " sublaneCompact=" << sublaneCompact
1244  << "\n";
1245 
1246  if (!left) {
1247  // ONLY FOR CHANGING TO THE RIGHT
1248  if (right && maxGain >= 0 && latDist <= 0) {
1249  // honor the obligation to keep right (Rechtsfahrgebot)
1250  // XXX consider fast approaching followers on the current lane
1251  //const SUMOReal vMax = myLookAheadSpeed;
1253  const SUMOReal acceptanceTime = KEEP_RIGHT_ACCEPTANCE * vMax * MAX2((SUMOReal)1, myVehicle.getSpeed()) / myVehicle.getLane()->getSpeedLimit();
1254  SUMOReal fullSpeedGap = MAX2((SUMOReal)0, neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1255  SUMOReal fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1256  CLeaderDist neighLead = getSlowest(neighLeaders);
1257  if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1258  fullSpeedGap = MAX2((SUMOReal)0, MIN2(fullSpeedGap,
1259  neighLead.second - myVehicle.getCarFollowModel().getSecureGap(
1260  vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1261  fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1262  }
1263  const SUMOReal deltaProb = (myChangeProbThresholdRight
1264  * STEPS2TIME(DELTA_T)
1265  * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1266  myKeepRightProbability += TS * deltaProb;
1267 
1268  if (gDebugFlag2) {
1269  std::cout << STEPS2TIME(currentTime)
1270  << " considering keepRight:"
1271  << " vMax=" << vMax
1272  << " neighDist=" << neighDist
1273  << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1274  << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1275  << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(
1276  myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1277  << " acceptanceTime=" << acceptanceTime
1278  << " fullSpeedGap=" << fullSpeedGap
1279  << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1280  << " dProb=" << deltaProb
1281  << " keepRight=" << myKeepRightProbability
1282  << " speedGainL=" << mySpeedGainProbabilityLeft
1283  << "\n";
1284  }
1286  ret |= LCA_KEEPRIGHT;
1287  assert(myVehicle.getLane()->getIndex() > neighLane.getIndex());
1288  if (!cancelRequest(ret)) {
1289  latDist = latLaneDist;
1290  blocked = checkBlocking(neighLane, latDist, laneOffset,
1291  leaders, followers, blockers,
1292  neighLeaders, neighFollowers, neighBlockers);
1293  return ret;
1294  }
1295  }
1296  }
1297 
1298  if (gDebugFlag2) {
1299  std::cout << STEPS2TIME(currentTime)
1300  << " speedGainR=" << mySpeedGainProbabilityRight
1301  << " latDist=" << latDist
1302  << "\n";
1303  }
1304 
1305  if (latDist < 0 && mySpeedGainProbabilityRight >= MAX2(myChangeProbThresholdRight, mySpeedGainProbabilityLeft)
1306  && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) {
1307  ret |= LCA_SPEEDGAIN;
1308  if (!cancelRequest(ret)) {
1309  blocked = checkBlocking(neighLane, latDist, laneOffset,
1310  leaders, followers, blockers,
1311  neighLeaders, neighFollowers, neighBlockers);
1312  return ret;
1313  }
1314  }
1315  }
1316  if (!right) {
1317 
1318  const bool stayInLane = myVehicle.getLateralPositionOnLane() + latDist < 0.5 * myVehicle.getLane()->getWidth();
1319  if (gDebugFlag2) {
1320  std::cout << STEPS2TIME(currentTime)
1321  << " speedGainL=" << mySpeedGainProbabilityLeft
1322  << " latDist=" << latDist
1323  << " stayInLane=" << stayInLane
1324  << "\n";
1325  }
1326 
1328  // if we leave our lane, we should be able to stay in the new
1329  // lane for some time
1330  (stayInLane || neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > SPEED_GAIN_MIN_SECONDS)) {
1331  ret |= LCA_SPEEDGAIN;
1332  if (!cancelRequest(ret)) {
1333  blocked = checkBlocking(neighLane, latDist, laneOffset,
1334  leaders, followers, blockers,
1335  neighLeaders, neighFollowers, neighBlockers);
1336  return ret;
1337  }
1338  }
1339  }
1340 
1341  // factor in preferred lateral alignment (unless we are in the middle of an unfinished non-alignment maneuver)
1342  if (fabs(latDist) <= NUMERICAL_EPS && (myCanChangeFully || (myPreviousState | LCA_SUBLANE) != 0)) {
1343  const SUMOReal halfLaneWidth = myVehicle.getLane()->getWidth() * 0.5;
1344  const SUMOReal halfVehWidth = myVehicle.getVehicleType().getWidth() * 0.5;
1347  && bestLaneOffset == 0
1349  // vehicle is on its final edge, on the correct lane and close to
1350  // its arrival position. Change to the desired lateral position
1352  case ARRIVAL_POSLAT_GIVEN:
1354  break;
1355  case ARRIVAL_POSLAT_RIGHT:
1356  latDist = -halfLaneWidth + halfVehWidth - myVehicle.getLateralPositionOnLane();
1357  break;
1358  case ARRIVAL_POSLAT_CENTER:
1359  latDist = -myVehicle.getLateralPositionOnLane();
1360  break;
1361  case ARRIVAL_POSLAT_LEFT:
1362  latDist = halfLaneWidth - halfVehWidth - myVehicle.getLateralPositionOnLane();
1363  break;
1364  default:
1365  assert(false);
1366  }
1367  if (gDebugFlag2) std::cout << SIMTIME
1368  << " arrivalPosLatProcedure=" << myVehicle.getParameter().arrivalPosLatProcedure
1369  << " arrivalPosLat=" << myVehicle.getParameter().arrivalPosLat << "\n";
1370 
1371  } else {
1373  case LATALIGN_RIGHT:
1374  latDist = -halfLaneWidth + halfVehWidth - myVehicle.getLateralPositionOnLane();
1375  break;
1376  case LATALIGN_LEFT:
1377  latDist = halfLaneWidth - halfVehWidth - myVehicle.getLateralPositionOnLane();
1378  break;
1379  case LATALIGN_CENTER:
1380  latDist = -myVehicle.getLateralPositionOnLane();
1381  break;
1382  case LATALIGN_NICE:
1383  latDist = latDistNice;
1384  break;
1385  case LATALIGN_COMPACT:
1386  latDist = sublaneSides[sublaneCompact] - rightVehSide;
1387  break;
1388  case LATALIGN_ARBITRARY:
1389  break;
1390  }
1391  }
1392  if (gDebugFlag2) std::cout << SIMTIME
1394  << " mySpeedGainR=" << mySpeedGainProbabilityRight
1395  << " mySpeedGainL=" << mySpeedGainProbabilityLeft
1396  << " latDist=" << latDist
1397  << " myCanChangeFully=" << myCanChangeFully
1398  << " prevState=" << toString((LaneChangeAction)myPreviousState)
1399  << "\n";
1401  || (latDist > 0 && mySpeedGainProbabilityLeft < mySpeedLossProbThreshold)) {
1402  // do not risk losing speed
1403  latDist = 0;
1404  }
1405  // XXX first compute preferred adaptation and then override with speed
1406  // (this way adaptation is still done if changing for speedgain is
1407  // blocked)
1408  if (fabs(latDist) >= NUMERICAL_EPS) {
1409  if (gDebugFlag2) std::cout << SIMTIME
1410  << " adapting to preferred alignment=" << toString(myVehicle.getVehicleType().getPreferredLateralAlignment())
1411  << " latDist=" << latDist
1412  << "\n";
1413  ret |= LCA_SUBLANE;
1414  if (!cancelRequest(ret)) {
1415  blocked = checkBlocking(neighLane, latDist, laneOffset,
1416  leaders, followers, blockers,
1417  neighLeaders, neighFollowers, neighBlockers);
1418  return ret;
1419  }
1420  } else {
1421  latDist = 0;
1422  ret |= LCA_SUBLANE | LCA_STAY;
1423  }
1424  }
1425 
1426 
1427  // --------
1428  /*
1429  if (changeToBest && bestLaneOffset == curr.bestLaneOffset && laneOffset != 0
1430  && (right
1431  ? mySpeedGainProbabilityRight > MAX2((SUMOReal)0, mySpeedGainProbabilityLeft)
1432  : mySpeedGainProbabilityLeft > MAX2((SUMOReal)0, mySpeedGainProbabilityRight))) {
1433  // change towards the correct lane, speedwise it does not hurt
1434  ret |= LCA_STRATEGIC;
1435  if (!cancelRequest(ret)) {
1436  latDist = latLaneDist;
1437  blocked = checkBlocking(neighLane, latDist, laneOffset,
1438  leaders, followers, blockers,
1439  neighLeaders, neighFollowers, neighBlockers);
1440  return ret;
1441  }
1442  }
1443  */
1444  if (gDebugFlag2) {
1445  std::cout << STEPS2TIME(currentTime)
1446  << " veh=" << myVehicle.getID()
1447  << " mySpeedGainR=" << mySpeedGainProbabilityRight
1448  << " mySpeedGainL=" << mySpeedGainProbabilityLeft
1449  << " myKeepRight=" << myKeepRightProbability
1450  << "\n";
1451  }
1452  return ret;
1453 }
1454 
1455 
1456 int
1458  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1459  if ((*blocked) != 0) {
1460  SUMOReal gap = (*blocked)->getPositionOnLane() - (*blocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1461  if (gDebugFlag2) {
1462  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1463  << " veh=" << myVehicle.getID()
1464  << " blocked=" << Named::getIDSecure(*blocked)
1465  << " gap=" << gap
1466  << "\n";
1467  }
1468  if (gap > POSITION_EPS) {
1469  //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1470  // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1471 
1473  //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1474  ) {
1475  if ((*blocked)->getSpeed() < SUMO_const_haltingSpeed) {
1476  state |= LCA_AMBACKBLOCKER_STANDING;
1477  } else {
1478  state |= LCA_AMBACKBLOCKER;
1479  }
1482  (SUMOReal)(gap - POSITION_EPS), (*blocked)->getSpeed(),
1483  (*blocked)->getCarFollowModel().getMaxDecel()));
1484  //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1485  }
1486  }
1487  }
1488  return state;
1489 }
1490 
1491 
1492 void
1493 MSLCM_SL2015::saveBlockerLength(const MSVehicle* blocker, int lcaCounter) {
1494  if (gDebugFlag2) {
1495  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1496  << " veh=" << myVehicle.getID()
1497  << " saveBlockerLength blocker=" << Named::getIDSecure(blocker)
1498  << " bState=" << (blocker == 0 ? "None" : toString(blocker->getLaneChangeModel().getOwnState()))
1499  << "\n";
1500  }
1501  if (blocker != 0 && (blocker->getLaneChangeModel().getOwnState() & lcaCounter) != 0) {
1502  // is there enough space in front of us for the blocker?
1505  if (blocker->getVehicleType().getLengthWithGap() <= potential) {
1506  // save at least his length in myLeadingBlockerLength
1508  if (gDebugFlag2) {
1509  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1510  << " veh=" << myVehicle.getID()
1511  << " blocker=" << Named::getIDSecure(blocker)
1512  << " saving myLeadingBlockerLength=" << myLeadingBlockerLength
1513  << "\n";
1514  }
1515  } else {
1516  // we cannot save enough space for the blocker. It needs to save
1517  // space for ego instead
1518  if (gDebugFlag2) {
1519  std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())
1520  << " veh=" << myVehicle.getID()
1521  << " blocker=" << Named::getIDSecure(blocker)
1522  << " cannot save space=" << blocker->getVehicleType().getLengthWithGap()
1523  << " potential=" << potential
1524  << "\n";
1525  }
1526  ((MSVehicle*)blocker)->getLaneChangeModel().saveBlockerLength(myVehicle.getVehicleType().getLengthWithGap());
1527  }
1528  }
1529 }
1530 
1531 
1532 void
1533 MSLCM_SL2015::updateExpectedSublaneSpeeds(const MSLeaderInfo& ahead, int sublaneOffset, int laneIndex) {
1534  const std::vector<MSLane*>& lanes = myVehicle.getLane()->getEdge().getLanes();
1535  const std::vector<MSVehicle::LaneQ>& preb = myVehicle.getBestLanes();
1536  const MSLane* lane = lanes[laneIndex];
1537  const SUMOReal vMax = lane->getVehicleMaxSpeed(&myVehicle);
1538  assert(preb.size() == lanes.size());
1539 
1540  for (int sublane = 0; sublane < (int)ahead.numSublanes(); ++sublane) {
1541  const int edgeSublane = sublane + sublaneOffset;
1543  // lane allowed, find potential leaders and compute safe speeds
1544  // XXX anticipate future braking if leader has a lower speed than myVehicle
1545  const MSVehicle* leader = ahead[sublane];
1546  SUMOReal vSafe;
1547  if (leader == 0) {
1548  vSafe = MIN2(vMax, myCarFollowModel.followSpeed(&myVehicle, vMax, preb[laneIndex].length, 0, 0));
1549  } else {
1551  vSafe = MIN2(vMax, myCarFollowModel.followSpeed(
1552  &myVehicle, vMax, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()));
1553  }
1554  // XXX calibrate weightFactor?
1555  const SUMOReal memoryFactor = 0.5;
1556  myExpectedSublaneSpeeds[edgeSublane] = memoryFactor * myExpectedSublaneSpeeds[edgeSublane] + (1 - memoryFactor) * vSafe;
1557  } else {
1558  // lane forbidden
1559  myExpectedSublaneSpeeds[edgeSublane] = -1;
1560  }
1561  }
1562  // XXX deal with leaders on subsequent lanes based on preb
1563 }
1564 
1565 
1568  int iMax = 0;
1569  SUMOReal maxLength = -1;
1570  for (int i = 0; i < ldi.numSublanes(); ++i) {
1571  if (ldi[i].first != 0) {
1572  const SUMOReal length = ldi[i].first->getVehicleType().getLength();
1573  if (length > maxLength) {
1574  maxLength = length;
1575  iMax = i;
1576  }
1577  }
1578  }
1579  return ldi[iMax];
1580 }
1581 
1582 
1585  int iMax = 0;
1587  for (int i = 0; i < ldi.numSublanes(); ++i) {
1588  if (ldi[i].first != 0) {
1589  const SUMOReal speed = ldi[i].first->getSpeed();
1590  if (speed < minSpeed) {
1591  minSpeed = speed;
1592  iMax = i;
1593  }
1594  }
1595  }
1596  return ldi[iMax];
1597 }
1598 
1599 
1600 int
1601 MSLCM_SL2015::checkBlocking(const MSLane& neighLane, SUMOReal& latDist, int laneOffset,
1602  const MSLeaderDistanceInfo& leaders,
1603  const MSLeaderDistanceInfo& followers,
1604  const MSLeaderDistanceInfo& /*blockers */,
1605  const MSLeaderDistanceInfo& neighLeaders,
1606  const MSLeaderDistanceInfo& neighFollowers,
1607  const MSLeaderDistanceInfo& /* neighBlockers */,
1608  std::vector<CLeaderDist>* collectLeadBlockers,
1609  std::vector<CLeaderDist>* collectFollowBlockers,
1610  bool keepLatGapManeuver) {
1611  // truncate latDist according to maxSpeedLat
1612  if (!keepLatGapManeuver) {
1613  myOrigLatDist = latDist;
1614  }
1616  latDist = MAX2(MIN2(latDist, maxDist), -maxDist);
1617 
1618  // reduce latDist to avoid blockage with overlapping vehicles
1619  const SUMOReal halfWidth = myVehicle.getVehicleType().getWidth() * 0.5;
1620  const SUMOReal center = myVehicle.getCenterOnEdge();
1621  SUMOReal surplusGapRight = MIN2(maxDist, center - halfWidth);
1622  SUMOReal surplusGapLeft = MIN2(maxDist, myVehicle.getLane()->getEdge().getWidth() - center - halfWidth);
1623  updateGaps(leaders, myVehicle.getLane()->getRightSideOnEdge(), center, 0, surplusGapRight, surplusGapLeft);
1624  updateGaps(followers, myVehicle.getLane()->getRightSideOnEdge(), center, 0, surplusGapRight, surplusGapLeft);
1625  if (laneOffset != 0) {
1626  updateGaps(neighLeaders, neighLane.getRightSideOnEdge(), center, 0, surplusGapRight, surplusGapLeft);
1627  updateGaps(neighFollowers, neighLane.getRightSideOnEdge(), center, 0, surplusGapRight, surplusGapLeft);
1628  }
1629  if (gDebugFlag2) {
1630  std::cout << " checkBlocking latDist=" << latDist << " surplusGapRight=" << surplusGapRight << " surplusGapLeft=" << surplusGapLeft << "\n";
1631  }
1632  if (latDist < 0) {
1633  if (surplusGapRight <= 0) {
1635  } else {
1636  latDist = MAX2(latDist, -surplusGapRight);
1637  }
1638  } else {
1639  if (surplusGapLeft <= 0) {
1641  } else {
1642  latDist = MIN2(latDist, surplusGapLeft);
1643  }
1644  }
1645 
1646  myCanChangeFully = (myOrigLatDist == 0 || latDist == myOrigLatDist);
1647  if (gDebugFlag2) {
1648  std::cout << " checkBlocking fully=" << myCanChangeFully << " latDist=" << latDist << " origLatDist=" << myOrigLatDist << "\n";
1649  }
1650  // destination sublanes must be safe
1651  // intermediate sublanes must not be blocked by overlapping vehicles
1652 
1653  // XXX avoid checking the same leader multiple times
1654  // XXX ensure that only changes within the same lane are undertaken if laneOffset = 0
1655 
1656  int blocked = 0;
1657  blocked |= checkBlockingVehicles(&myVehicle, leaders, latDist, myVehicle.getLane()->getRightSideOnEdge(), true, LCA_BLOCKED_BY_LEADER, collectLeadBlockers);
1658  blocked |= checkBlockingVehicles(&myVehicle, followers, latDist, myVehicle.getLane()->getRightSideOnEdge(), false, LCA_BLOCKED_BY_FOLLOWER, collectFollowBlockers);
1659  if (laneOffset != 0) {
1660  blocked |= checkBlockingVehicles(&myVehicle, neighLeaders, latDist, neighLane.getRightSideOnEdge(), true,
1661  (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER), collectLeadBlockers);
1662  blocked |= checkBlockingVehicles(&myVehicle, neighFollowers, latDist, neighLane.getRightSideOnEdge(), false,
1663  (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER), collectFollowBlockers);
1664  }
1665 
1666  if (blocked == 0 && !myCanChangeFully && myPushy == 0 && !keepLatGapManeuver) {
1667  // aggressive drivers immediately start moving towards potential
1668  // blockers and only check that the start of their maneuver (latDist) is safe. In
1669  // contrast, cautious drivers need to check latDist and origLatDist to
1670  // ensure that the maneuver can be finished without encroaching on other vehicles.
1671  blocked |= checkBlockingVehicles(&myVehicle, leaders, myOrigLatDist, myVehicle.getLane()->getRightSideOnEdge(), true, LCA_BLOCKED_BY_LEADER, collectLeadBlockers);
1672  blocked |= checkBlockingVehicles(&myVehicle, followers, myOrigLatDist, myVehicle.getLane()->getRightSideOnEdge(), false, LCA_BLOCKED_BY_FOLLOWER, collectFollowBlockers);
1673  if (laneOffset != 0) {
1674  blocked |= checkBlockingVehicles(&myVehicle, neighLeaders, myOrigLatDist, neighLane.getRightSideOnEdge(), true,
1675  (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER), collectLeadBlockers);
1676  blocked |= checkBlockingVehicles(&myVehicle, neighFollowers, myOrigLatDist, neighLane.getRightSideOnEdge(), false,
1677  (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER), collectFollowBlockers);
1678  }
1679  }
1680  if (collectFollowBlockers != 0 && collectLeadBlockers != 0) {
1681  // prevent vehicles from being classified as leader and follower simultaneously
1682  for (std::vector<CLeaderDist>::const_iterator it2 = collectLeadBlockers->begin(); it2 != collectLeadBlockers->end(); ++it2) {
1683  for (std::vector<CLeaderDist>::iterator it = collectFollowBlockers->begin(); it != collectFollowBlockers->end();) {
1684  if ((*it2).first == (*it).first) {
1685  if (gDebugFlag2) {
1686  std::cout << " removed follower " << (*it).first->getID() << " because it is already a leader\n";
1687  }
1688  it = collectFollowBlockers->erase(it);
1689  } else {
1690  ++it;
1691  }
1692  }
1693  }
1694  }
1695  return blocked;
1696 }
1697 
1698 
1699 int
1701  const MSVehicle* ego, const MSLeaderDistanceInfo& vehicles,
1702  SUMOReal latDist, SUMOReal foeOffset, bool leaders, LaneChangeAction blockType,
1703  std::vector<CLeaderDist>* collectBlockers) const {
1704  // determine borders where safety/no-overlap conditions must hold
1705  const SUMOReal vehWidth = ego->getVehicleType().getWidth();
1706  const SUMOReal rightVehSide = ego->getRightSideOnEdge();
1707  const SUMOReal leftVehSide = rightVehSide + vehWidth;
1708  const SUMOReal rightVehSideDest = rightVehSide + latDist;
1709  const SUMOReal leftVehSideDest = leftVehSide + latDist;
1710  const SUMOReal rightNoOverlap = MIN2(rightVehSideDest, rightVehSide);
1711  const SUMOReal leftNoOverlap = MAX2(leftVehSideDest, leftVehSide);
1712 
1713  int result = 0;
1714  for (int i = 0; i < vehicles.numSublanes(); ++i) {
1715  CLeaderDist vehDist = vehicles[i];
1716  if (vehDist.first != 0) {
1717  // only check the current stripe occuped by foe (transform into edge-coordinates)
1718  const SUMOReal foeRight = i * MSGlobals::gLateralResolution + foeOffset;
1719  const SUMOReal foeLeft = foeRight + MSGlobals::gLateralResolution;
1720  if (gDebugFlag2 && false) {
1721  const MSVehicle* leader = vehDist.first;
1722  const MSVehicle* follower = ego;
1723  if (!leaders) {
1724  std::swap(leader, follower);
1725  }
1726  std::cout << " checkBlocking"
1727  << " leaders=" << leaders
1728  << " foe=" << vehDist.first->getID()
1729  << " gap=" << vehDist.second
1730  << " secGap=" << follower->getCarFollowModel().getSecureGap(follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel())
1731  << " foeRight=" << foeRight
1732  << " foeLeft=" << foeLeft
1733  << " rightNoOverlap=" << rightNoOverlap
1734  << " leftNoOverlap=" << leftNoOverlap
1735  << " rightVehSideDest=" << rightVehSideDest
1736  << " leftVehSideDest=" << leftVehSideDest
1737  << " overlap=" << overlap(rightNoOverlap, leftNoOverlap, foeRight, foeLeft)
1738  << " overlapDest=" << overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)
1739  << "\n";
1740  }
1741  if (overlap(rightNoOverlap, leftNoOverlap, foeRight, foeLeft)) {
1742  if (vehDist.second < 0) {
1743  if (gDebugFlag2) {
1744  std::cout << " overlap\n";
1745  }
1746  result |= (blockType | LCA_OVERLAPPING);
1747  if (collectBlockers == 0) {
1748  return result;
1749  } else {
1750  collectBlockers->push_back(vehDist);
1751  }
1752  } else if (overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)) {
1753  const MSVehicle* leader = vehDist.first;
1754  const MSVehicle* follower = ego;
1755  if (!leaders) {
1756  std::swap(leader, follower);
1757  }
1758  const SUMOReal decelFactor = 1 + ego->getImpatience() * myAssertive;
1759  // see MSCFModel::getSecureGap
1760  // for decelFactor == 1 this is equivalent to
1761  // follower->getCarFollowModel().getSecureGap(follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel())
1762  const SUMOReal followDecel = MIN2(follower->getCarFollowModel().getMaxDecel(), leader->getCarFollowModel().getMaxDecel()) * decelFactor;
1763  const SUMOReal secureGap = MAX2((SUMOReal) 0, MSCFModel::brakeGap(follower->getSpeed(), followDecel, follower->getCarFollowModel().getHeadwayTime())
1764  - MSCFModel::brakeGap(leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), 0));
1765  if (vehDist.second < secureGap) {
1766  if (gDebugFlag2) {
1767  std::cout << " blocked decelFactor=" << decelFactor << "\n";
1768  }
1769  result |= blockType;
1770  if (collectBlockers == 0) {
1771  return result;
1772  } else {
1773  collectBlockers->push_back(vehDist);
1774  }
1775  }
1776  }
1777  }
1778  }
1779  }
1780  return result;
1781 
1782 }
1783 
1784 
1785 bool
1787  assert(right <= left);
1788  assert(right2 <= left2);
1789  return left2 >= right + NUMERICAL_EPS && left >= right2 + NUMERICAL_EPS;
1790 }
1791 
1792 
1795  // ignore dummy decisions (returned if mayChange() failes)
1796  if (sd1.state == 0) {
1797  return sd2;
1798  } else if (sd2.state == 0) {
1799  return sd1;
1800  }
1801  // LCA_SUBLANE is special because LCA_STAY|LCA_SUBLANE may override another LCA_SUBLANE command
1802  const bool want1 = ((sd1.state & LCA_WANTS_LANECHANGE) != 0) || ((sd1.state & LCA_SUBLANE) != 0 && (sd1.state & LCA_STAY) != 0);
1803  const bool want2 = ((sd2.state & LCA_WANTS_LANECHANGE) != 0) || ((sd2.state & LCA_SUBLANE) != 0 && (sd2.state & LCA_STAY) != 0);
1804  const bool can1 = ((sd1.state & LCA_BLOCKED) == 0);
1805  if (DEBUG_COND) std::cout << SIMTIME
1806  << " veh=" << myVehicle.getID()
1807  << " state1=" << toString((LaneChangeAction)sd1.state)
1808  << " want1=" << (sd1.state & LCA_WANTS_LANECHANGE)
1809  << " dist1=" << sd1.latDist
1810  << " dir1=" << sd1.dir
1811  << " state2=" << toString((LaneChangeAction)sd2.state)
1812  << " want2=" << (sd2.state & LCA_WANTS_LANECHANGE)
1813  << " dist2=" << sd2.latDist
1814  << " dir2=" << sd2.dir
1815  << "\n";
1816  if (want1) {
1817  if (want2) {
1818  // decide whether right or left has higher priority (lower value in enum LaneChangeAction)
1819  if ((sd1.state & LCA_CHANGE_REASONS) < (sd2.state & LCA_CHANGE_REASONS)) {
1820  //if (DEBUG_COND) std::cout << " " << (sd1.state & LCA_CHANGE_REASONS) << " < " << (sd2.state & LCA_CHANGE_REASONS) << "\n";
1821  return sd1;
1822  } else if ((sd1.state & LCA_CHANGE_REASONS) > (sd2.state & LCA_CHANGE_REASONS)) {
1823  //if (DEBUG_COND) std::cout << " " << (sd1.state & LCA_CHANGE_REASONS) << " > " << (sd2.state & LCA_CHANGE_REASONS) << "\n";
1824  return sd2;
1825  } else {
1826  // same priority.
1827  if ((sd1.state & LCA_SUBLANE) != 0) {
1828  // special treatment: prefer action with dir != 0
1829  if (sd1.dir == 0) {
1830  return sd2;
1831  } else if (sd2.dir == 0) {
1832  return sd1;
1833  } else {
1834  // prefer further right
1835  return sd1.latDist <= sd2.latDist ? sd1 : sd2;
1836  }
1837  } else {
1838  // see which one is allowed
1839  return can1 ? sd1 : sd2;
1840  }
1841  }
1842  } else {
1843  return sd1;
1844  }
1845  } else {
1846  return sd2;
1847  }
1848 
1849 }
1850 
1851 
1853 MSLCM_SL2015::getLCA(int state, SUMOReal latDist) {
1854  return ((latDist == 0 || (state & LCA_CHANGE_REASONS) == 0)
1855  ? LCA_NONE : (latDist < 0 ? LCA_RIGHT : LCA_LEFT));
1856 }
1857 
1858 
1859 int
1861  int laneOffset,
1862  const std::vector<MSVehicle::LaneQ>& preb,
1863  const MSLeaderDistanceInfo& leaders,
1864  const MSLeaderDistanceInfo& neighLeaders,
1865  int currIdx,
1866  int bestLaneOffset,
1867  bool changeToBest,
1868  int lcaCounter,
1869  SUMOReal currentDist,
1870  SUMOReal neighDist,
1871  SUMOReal laDist,
1872  int roundaboutEdgesAhead
1873  ) {
1874  const bool right = (laneOffset == -1);
1875  const bool left = (laneOffset == 1);
1876  const MSVehicle::LaneQ& curr = preb[currIdx];
1877  const MSVehicle::LaneQ& neigh = preb[currIdx + laneOffset];
1878  const MSVehicle::LaneQ& best = preb[currIdx + bestLaneOffset];
1879 
1880  const SUMOReal usableDist = (currentDist - myVehicle.getPositionOnLane() - best.occupation * JAM_FACTOR);
1881  //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1882  const SUMOReal maxJam = MAX2(preb[currIdx + laneOffset].occupation, preb[currIdx].occupation);
1883  const SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
1884 
1885  if (gDebugFlag2) {
1886  std::cout << SIMTIME
1887  << " veh=" << myVehicle.getID()
1888  << " laSpeed=" << myLookAheadSpeed
1889  << " laDist=" << laDist
1890  << " currentDist=" << currentDist
1891  << " usableDist=" << usableDist
1892  << " bestLaneOffset=" << bestLaneOffset
1893  << " best.length=" << best.length
1894  << " maxJam=" << maxJam
1895  << " neighLeftPlace=" << neighLeftPlace
1896  << "\n";
1897  }
1898 
1899  if (laneOffset != 0 && changeToBest && bestLaneOffset == curr.bestLaneOffset
1900  && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1902  ret |= LCA_STRATEGIC | LCA_URGENT;
1903  } else {
1904  // VARIANT_20 (noOvertakeRight)
1905  if (!myAllowOvertakingRight && left && !myVehicle.congested() && neighLeaders.hasVehicles()) {
1906  // check for slower leader on the left. we should not overtake but
1907  // rather move left ourselves (unless congested)
1908  // XXX only adapt as much as possible to get a lateral gap
1909  CLeaderDist cld = getSlowest(neighLeaders);
1910  const MSVehicle* nv = cld.first;
1911  if (nv->getSpeed() < myVehicle.getSpeed()) {
1912  const SUMOReal vSafe = myCarFollowModel.followSpeed(
1913  &myVehicle, myVehicle.getSpeed(), cld.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1914  myVSafes.push_back(vSafe);
1915  if (vSafe < myVehicle.getSpeed()) {
1917  }
1918  if (gDebugFlag2) {
1919  std::cout << SIMTIME
1920  << " avoid overtaking on the right nv=" << nv->getID()
1921  << " nvSpeed=" << nv->getSpeed()
1922  << " mySpeedGainProbabilityR=" << mySpeedGainProbabilityRight
1923  << " plannedSpeed=" << myVSafes.back()
1924  << "\n";
1925  }
1926  }
1927  }
1928 
1929  if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
1930  // the opposite lane-changing direction should be done than the one examined herein
1931  // we'll check whether we assume we could change anyhow and get back in time...
1932  //
1933  // this rule prevents the vehicle from moving in opposite direction of the best lane
1934  // unless the way till the end where the vehicle has to be on the best lane
1935  // is long enough
1936  if (gDebugFlag2) {
1937  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1938  }
1939  ret |= LCA_STAY | LCA_STRATEGIC;
1940  } else if (laneOffset != 0 && bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1941  // the current lane is the best and a lane-changing would cause a situation
1942  // of which we assume we will not be able to return to the lane we have to be on.
1943  // this rule prevents the vehicle from leaving the current, best lane when it is
1944  // close to this lane's end
1945  if (gDebugFlag2) {
1946  std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1947  }
1948  ret |= LCA_STAY | LCA_STRATEGIC;
1949  } else if (
1950  laneOffset != 0
1951  && bestLaneOffset == 0
1952  && !leaders.hasStoppedVehicle()
1953  && neigh.bestContinuations.back()->getLinkCont().size() != 0
1954  && roundaboutEdgesAhead == 0
1955  && neighDist < TURN_LANE_DIST) {
1956  // VARIANT_21 (stayOnBest)
1957  // we do not want to leave the best lane for a lane which leads elsewhere
1958  // unless our leader is stopped or we are approaching a roundabout
1959  if (gDebugFlag2) {
1960  std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1961  }
1962  ret |= LCA_STAY | LCA_STRATEGIC;
1963  } else if (right
1964  && bestLaneOffset == 0
1965  && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6
1967  ) {
1968  // let's also regard the case where the vehicle is driving on a highway...
1969  // in this case, we do not want to get to the dead-end of an on-ramp
1970  if (gDebugFlag2) {
1971  std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1972  }
1973  ret |= LCA_STAY | LCA_STRATEGIC;
1974  }
1975  }
1976  // check for overriding TraCI requests
1977  if (gDebugFlag2) {
1978  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ret=" << ret;
1979  }
1981  if ((ret & lcaCounter) != 0) {
1982  // we are not interested in traci requests for the opposite direction here
1983  ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1984  }
1985  if (gDebugFlag2) {
1986  std::cout << " reqAfterInfluence=" << ret << " ret=" << ret << "\n";
1987  }
1988  return ret;
1989 }
1990 
1991 
1992 int
1994  const MSLeaderDistanceInfo& leaders,
1995  const MSLeaderDistanceInfo& followers,
1996  const MSLeaderDistanceInfo& blockers,
1997  const MSLeaderDistanceInfo& neighLeaders,
1998  const MSLeaderDistanceInfo& neighFollowers,
1999  const MSLeaderDistanceInfo& neighBlockers,
2000  const MSLane& neighLane,
2001  int laneOffset,
2002  SUMOReal& latDist,
2003  int& blocked) {
2004 
2005  /* @notes
2006  * vehicles may need to compromise between fulfilling lane change objectives
2007  * (LCA_STRATEGIC, LCA_SPEED etc) and maintaining lateral gap. The minimum
2008  * acceptable lateral gap depends on
2009  * - the cultural context (China vs Europe)
2010  * - the driver agressiveness (willingness to encroach on other vehicles to force them to move laterally as well)
2011  * - see @note in checkBlocking
2012  * - the vehicle type (car vs motorcycle)
2013  * - the current speed
2014  * - the speed difference
2015  * - the importance / urgency of the desired maneuver
2016  *
2017  * the object of this method is to evaluate the above circumstances and
2018  * either:
2019  * - allow the current maneuver (state, latDist)
2020  * - to override the current maneuver with a distance-keeping maneuver
2021  *
2022  *
2023  * laneChangeModel/driver parameters
2024  * - bool pushy (willingness to encroach)
2025  * - float minGap at 100km/h (to be interpolated for lower speeds (assume 0 at speed 0)
2026  * - gapFactors (a factor for each of the change reasons
2027  *
2028  * further assumptions
2029  * - the maximum of egoSpeed and deltaSpeed can be used when interpolating minGap
2030  * - distance keeping to the edges of the road can be ignored (for now)
2031  *
2032  * currentMinGap = minGap * min(1.0, max(v, abs(v - vOther)) / 100) * gapFactor[lc_reason]
2033  *
2034  * */
2035 
2037  const SUMOReal gapFactor = (state & LCA_STRATEGIC) != 0 ? 0.0 : 1.0;
2038  const bool stayInLane = laneOffset == 0 || ((state & LCA_STRATEGIC) != 0 && (state & LCA_STAY) != 0);
2039  const SUMOReal oldLatDist = latDist;
2040 
2042  // - compute lateral gap after executing the current maneuver (may be LCA_NONE)
2043  // - decide if override is needed
2044  // - compute alternative maneuver to improve lateralGap
2045  // - update blocking (checkBlocking)
2046 
2047  // compute gaps after maneuver
2048  const SUMOReal halfWidth = myVehicle.getVehicleType().getWidth() * 0.5;
2049  // if the current maneuver is blocked we will stay where we are
2050  const SUMOReal newCenter = myVehicle.getCenterOnEdge() + (blocked == 0 ? latDist : 0);
2051  // surplus gaps after the context-dependend value of currentMinGap has ben subtracted
2052  // if this value goes negative, we should override the current maneuver to better maintain distance
2053  SUMOReal surplusGapRight = newCenter - halfWidth;
2054  SUMOReal surplusGapLeft = myVehicle.getLane()->getEdge().getWidth() - newCenter - halfWidth;
2055 
2056  updateGaps(leaders, myVehicle.getLane()->getRightSideOnEdge(), newCenter, gapFactor, surplusGapRight, surplusGapLeft);
2057  updateGaps(followers, myVehicle.getLane()->getRightSideOnEdge(), newCenter, gapFactor, surplusGapRight, surplusGapLeft);
2058  if (laneOffset != 0) {
2059  updateGaps(neighLeaders, neighLane.getRightSideOnEdge(), newCenter, gapFactor, surplusGapRight, surplusGapLeft);
2060  updateGaps(neighFollowers, neighLane.getRightSideOnEdge(), newCenter, gapFactor, surplusGapRight, surplusGapLeft);
2061  }
2062  if (stayInLane) {
2063  // stay fully within the current lane
2064  const SUMOReal halfLaneWidth = myVehicle.getLane()->getWidth() * 0.5;
2065  surplusGapRight = MIN2(surplusGapRight, halfLaneWidth + myVehicle.getLateralPositionOnLane() - halfWidth);
2066  surplusGapLeft = MIN2(surplusGapLeft, halfLaneWidth - myVehicle.getLateralPositionOnLane() - halfWidth);
2067  }
2068  if (gDebugFlag2) {
2069  std::cout << " keepLatGap laneOffset=" << laneOffset
2070  << " latDist=" << latDist
2071  << " gapFactor=" << gapFactor
2072  << " stayInLane=" << stayInLane
2073  << " surplusGapRight=" << surplusGapRight
2074  << " surplusGapLeft=" << surplusGapLeft
2075  << " state=" << toString((LaneChangeAction)state)
2076  << " blockedBefore=" << toString((LaneChangeAction)blocked);
2077  }
2079  if (surplusGapRight < -NUMERICAL_EPS) {
2080  if (surplusGapLeft > 0) {
2081  // move left to increase gap
2082  latDist = MIN3(latDist - surplusGapRight, latDist + surplusGapLeft, maxDist);
2083  } else {
2084  blocked |= LCA_OVERLAPPING | LCA_BLOCKED_RIGHT;
2085  }
2086  } else if (surplusGapLeft < -NUMERICAL_EPS) {
2087  if (surplusGapRight > 0) {
2088  // move right to increase gap
2089  latDist = MAX3(latDist + surplusGapLeft, latDist - surplusGapRight, -maxDist);
2090  } else {
2091  blocked |= LCA_OVERLAPPING | LCA_BLOCKED_LEFT;
2092  }
2093  }
2094  if (latDist != oldLatDist) {
2095  blocked = checkBlocking(neighLane, latDist, laneOffset, leaders, followers, blockers, neighLeaders, neighFollowers, neighBlockers, 0, 0, true);
2096  }
2097  if (latDist != 0) {
2098  state = (state & ~LCA_STAY);
2099  }
2100  if (gDebugFlag2) {
2101  std::cout << " keepLatGap (checked)"
2102  << " latDist2=" << latDist
2103  << " blockedAfter=" << toString((LaneChangeAction)blocked)
2104  << "\n";
2105  }
2106  return state;
2107 }
2108 
2109 
2110 void
2111 MSLCM_SL2015::updateGaps(const MSLeaderDistanceInfo& others, SUMOReal foeOffset, SUMOReal newCenter, SUMOReal gapFactor, SUMOReal& surplusGapRight, SUMOReal& surplusGapLeft) const {
2112  if (others.hasVehicles()) {
2113  const SUMOReal halfWidth = myVehicle.getVehicleType().getWidth() * 0.5 + NUMERICAL_EPS;
2114  const SUMOReal baseMinGap = myVehicle.getVehicleType().getMinGapLat();
2115  for (int i = 0; i < others.numSublanes(); ++i) {
2116  if (others[i].first != 0 && others[i].second <= 0) {
2118  const MSVehicle* foe = others[i].first;
2119  const SUMOReal foeRight = i * MSGlobals::gLateralResolution + foeOffset;
2120  const SUMOReal foeLeft = foeRight + MSGlobals::gLateralResolution;
2121  const SUMOReal foeCenter = foeRight + 0.5 * MSGlobals::gLateralResolution;
2122  const SUMOReal gap = MIN2(fabs(foeRight - newCenter), fabs(foeLeft - newCenter)) - halfWidth;
2123  const SUMOReal currentMinGap = baseMinGap * MIN2(1.0, MAX2(myVehicle.getSpeed(), (SUMOReal)fabs(myVehicle.getSpeed() - foe->getSpeed())) / (100 / 3.6)) * gapFactor;
2124  if (gDebugFlag2 && false) std::cout << " updateGaps"
2125  << " foe=" << foe->getID()
2126  << " foeRight=" << foeRight
2127  << " foeLeft=" << foeLeft
2128  << " gap=" << others[i].second
2129  << " latgap=" << gap
2130  << " currentMinGap=" << currentMinGap
2131  << " surplusGapRight=" << surplusGapRight
2132  << " surplusGapLeft=" << surplusGapLeft
2133  << "\n";
2134  if (foeCenter < newCenter) {
2135  surplusGapRight = MIN2(surplusGapRight, gap - currentMinGap);
2136  } else {
2137  surplusGapLeft = MIN2(surplusGapLeft, gap - currentMinGap);
2138  }
2139  }
2140  }
2141  }
2142 }
2143 
2144 
2145 /****************************************************************************/
void * inform(void *info, MSVehicle *sender)
SUMOReal getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:496
void informFollower(int blocked, int dir, const CLeaderDist &neighFollow, SUMOReal remainingSeconds, SUMOReal plannedSpeed)
decide whether we will try cut in before the follower or allow to be overtaken
SUMOReal getCenterOnEdge(const MSLane *lane=0) const
Get the vehicle&#39;s lateral position on the edge of the given lane (or its current edge if lane == 0) ...
Definition: MSVehicle.cpp:3367
void informFollowers(int blocked, int dir, const std::vector< CLeaderDist > &blockers, SUMOReal remainingSeconds, SUMOReal plannedSpeed)
call informFollower for multiple followers
SUMOReal myKeepRightProbability
Definition: MSLCM_SL2015.h:280
int keepLatGap(int state, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, int laneOffset, SUMOReal &latDist, int &blocked)
check whether lateral gap requirements are met override the current maneuver if necessary ...
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:127
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:571
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:82
long long int SUMOTime
Definition: SUMOTime.h:43
SUMOReal informLeader(int blocked, int dir, const CLeaderDist &neighLead, SUMOReal remainingSeconds)
The action is due to the default of keeping right "Rechtsfahrgebot".
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
The action is done to help someone else.
#define RELGAIN_NORMALIZATION_MIN_SPEED
SUMOReal myOrigLatDist
the complete lateral distance the vehicle wants to travel to finish its maneuver
Definition: MSLCM_SL2015.h:308
std::vector< SUMOReal > myVSafes
speed adaptation requests by ego and surrounding vehicles
Definition: MSLCM_SL2015.h:290
#define min(a, b)
Definition: polyfonts.c:66
const SUMOReal myAssertive
Definition: MSLCM_SL2015.h:319
#define MIN_FALLBEHIND
virtual std::string toString() const
print a debugging representation
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
#define ROUNDABOUT_DIST_BONUS
void msg(const CLeaderDist &cld, SUMOReal speed, int state)
send a speed recommendation to the given vehicle
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:487
bool myCanChangeFully
whether the current lane changing meneuver can be finished in a single step
Definition: MSLCM_SL2015.h:302
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive...
Definition: MSVehicle.h:681
The vehicle is blocked by left follower.
At the leftmost side of the lane.
LateralAlignment getPreferredLateralAlignment() const
Get vehicle&#39;s preferred lateral alignment.
virtual SUMOReal followSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const =0
Computes the vehicle&#39;s follow speed (no dawdling)
The car-following model abstraction.
Definition: MSCFModel.h:60
bool currentDistAllows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_SL2015.h:186
const SUMOVehicleParameter & getParameter() const
Returns the vehicle&#39;s parameter (including departure definition)
static CLeaderDist getSlowest(const MSLeaderDistanceInfo &ldi)
get the slowest vehicle in the given info
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
int getBestLaneOffset() const
returns the current offset from the best lane
Definition: MSVehicle.cpp:3077
Wants go to the right.
SUMOReal getLength() const
Get vehicle&#39;s length [m].
SUMOReal myLeftSpace
Definition: MSLCM_SL2015.h:283
ArrivalPosLatDefinition arrivalPosLatProcedure
Information how the vehicle shall choose the lateral arrival position.
std::pair< const MSVehicle *, SUMOReal > CLeaderDist
Definition: MSLeaderInfo.h:42
int checkBlockingVehicles(const MSVehicle *ego, const MSLeaderDistanceInfo &vehicles, SUMOReal latDist, SUMOReal foeOffset, bool leaders, LaneChangeAction blockType, std::vector< CLeaderDist > *collectBlockers=0) const
check whether any of the vehicles overlaps with ego
void updateExpectedSublaneSpeeds(const MSLeaderInfo &ahead, int sublaneOffset, int laneIndex)
update expected speeds for each sublane of the current edge
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:192
SUMOReal getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:472
SUMOReal getMaxSpeedLat() const
Get vehicle&#39;s maximum lateral speed [m/s].
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
T MAX2(T a, T b)
Definition: StdDefs.h:75
The position is given.
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:59
const MSRoute & getRoute() const
Returns the current route.
Definition: MSBaseVehicle.h:97
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:96
const std::string & getID() const
Returns the id.
Definition: Named.h:66
#define TS
Definition: SUMOTime.h:52
Wants go to the left.
bool debugVehicle() const
whether the current vehicles shall be debugged
The action is due to the wish to be faster (tactical lc)
SUMOReal length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:673
T MAX3(T a, T b, T c)
Definition: StdDefs.h:89
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 (>=0)
Definition: MSCFModel.h:276
MSLCM_SL2015(MSVehicle &v)
#define abs(a)
Definition: polyfonts.c:67
#define LCA_RIGHT_IMPATIENCE
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:2702
#define SIMTIME
Definition: SUMOTime.h:70
#define LOOK_FORWARD_LEFT
#define MAX_ONRAMP_LENGTH
#define GAIN_PERCEPTION_THRESHOLD
SUMOReal changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Definition: MSVehicle.cpp:396
#define ARRIVALPOS_LAT_THRESHOLD
Needs to stay on the current lane.
No action desired.
void saveBlockerLength(const MSVehicle *blocker, int lcaCounter)
save space for vehicles which need to counter-lane-change
SUMOReal getWidth() const
Returns the edges&#39;s width (sum over all lanes)
Definition: MSEdge.h:569
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
StateAndDist decideDirection(StateAndDist sd1, StateAndDist sd2) const
decide in which direction to move in case both directions are desirable
A road/street connecting two junctions.
Definition: MSEdge.h:80
SUMOReal myLeadingBlockerLength
Definition: MSLCM_SL2015.h:282
SUMOReal getWidth() const
Get the width which vehicles of this class shall have when being drawn.
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:758
void prepareStep()
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:503
#define max(a, b)
Definition: polyfonts.c:65
bool cancelRequest(int state)
whether the influencer cancels the given request
virtual SUMOReal getArrivalPos() const
Returns this vehicle&#39;s desired arrivalPos for its current route (may change on reroute) ...
static bool overlap(SUMOReal right, SUMOReal left, SUMOReal right2, SUMOReal left2)
return whether the given intervals overlap
The action is urgent (to be defined by lc-model)
SUMOReal informLeaders(int blocked, int dir, const std::vector< CLeaderDist > &blockers, SUMOReal remainingSeconds)
At the center of the lane.
virtual SUMOReal getHeadwayTime() const
Get the driver&#39;s reaction time [s].
Definition: MSCFModel.h:220
std::vector< SUMOReal > myExpectedSublaneSpeeds
expected travel speeds on all sublanes on the current edge(!)
Definition: MSLCM_SL2015.h:293
const MSEdge * myLastEdge
expected travel speeds on all sublanes on the current edge(!)
Definition: MSLCM_SL2015.h:296
#define URGENCY
SUMOReal getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:556
int wantsChangeSublane(int laneOffset, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked, SUMOReal &latDist, int &blocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
const SUMOReal myChangeProbThresholdLeft
Definition: MSLCM_SL2015.h:326
int checkBlocking(const MSLane &neighLane, SUMOReal &latDist, int laneOffset, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, std::vector< CLeaderDist > *collectLeadBlockers=0, std::vector< CLeaderDist > *collectFollowBlockers=0, bool keepLatGapManeuver=false)
restrict latDist to permissible speed and determine blocking state depending on that distance ...
At the rightmost side of the lane.
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
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.
std::pair< SUMOReal, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
Definition: MSLCM_SL2015.h:191
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:254
SUMOReal myLookAheadSpeed
Definition: MSLCM_SL2015.h:287
#define KEEP_RIGHT_ACCEPTANCE
SUMOReal getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:374
T MIN2(T a, T b)
Definition: StdDefs.h:69
The action is needed to follow the route (navigational lc)
#define POSITION_EPS
Definition: config.h:187
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:669
int _wantsChangeSublane(int laneOffset, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked, SUMOReal &latDist, int &blocked)
helper function for doing the actual work
SUMOReal _patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel &cfModel)
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:249
int myOwnState
The current state of the vehicle.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
#define LOOK_AHEAD_SPEED_MEMORY
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:458
#define LOOK_AHEAD_MIN_SPEED
static CLeaderDist getLongest(const MSLeaderDistanceInfo &ldi)
get the longest vehicle in the given info
#define LOOK_FORWARD_RIGHT
#define JAM_FACTOR
SUMOReal brakeGap(const SUMOReal speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time, assuming that during...
Definition: MSCFModel.h:263
int getRightmostSublane() const
Definition: MSLane.h:901
bool hasStoppedVehicle() const
whether a stopped vehicle is leader
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
virtual ~MSLCM_SL2015()
int checkStrategicChange(int ret, int laneOffset, const std::vector< MSVehicle::LaneQ > &preb, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &neighLeaders, int currIdx, int bestLaneOffset, bool changeToBest, int lcaCounter, SUMOReal currentDist, SUMOReal neighDist, SUMOReal laDist, int roundaboutEdgesAhead)
compute strategic lane change actions
SUMOReal getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:406
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:3690
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
SUMOReal occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:677
const SUMOReal myCooperativeParam
Definition: MSLCM_SL2015.h:313
int slowDownForBlocked(MSVehicle **blocked, int state)
compute useful slowdowns for blocked vehicles
std::vector< MSLane * > bestContinuations
Consecutive lane that can be followed without a lane change (contribute to length and occupation) ...
Definition: MSVehicle.h:685
SUMOReal mySpeedGainProbabilityRight
a value for tracking the probability that a change to the right is beneficial
Definition: MSLCM_SL2015.h:273
bool hasVehicles() const
Definition: MSLeaderInfo.h:94
static SUMOReal gLateralResolution
Definition: MSGlobals.h:89
virtual SUMOReal stopSpeed(const MSVehicle *const veh, const SUMOReal speed, SUMOReal gap) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...
const SUMOReal SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:57
const SUMOReal myPushy
Definition: MSLCM_SL2015.h:318
No information given; use default.
SUMOReal getRightSideOnEdge(const MSLane *lane=0) const
Get the vehicle&#39;s lateral position on the edge of the given lane (or its current edge if lane == 0) ...
Definition: MSVehicle.cpp:3361
const SUMOReal myStrategicParam
Definition: MSLCM_SL2015.h:312
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:695
#define DEBUG_COND
#define CUT_IN_LEFT_SPEED_THRESHOLD
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
The action is due to a TraCI request.
bool currentDistDisallows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_SL2015.h:183
#define HELP_DECEL_FACTOR
bool gDebugFlag2
Definition: StdDefs.cpp:92
#define SUMOReal
Definition: config.h:213
void updateGaps(const MSLeaderDistanceInfo &others, SUMOReal foeOffset, SUMOReal newCenter, SUMOReal gapFactor, SUMOReal &surplusGapRight, SUMOReal &surplusGapLeft) const
check remaining lateral gaps for the given foe vehicles
T MIN3(T a, T b, T c)
Definition: StdDefs.h:82
#define NUMERICAL_EPS
Definition: config.h:160
int numSublanes() const
Definition: MSLeaderInfo.h:86
SUMOReal arrivalPosLat
(optional) The lateral position the vehicle shall arrive on
bool myDontBrake
flag to prevent speed adaptation by slowing down
Definition: MSLCM_SL2015.h:299
const SUMOReal myKeepRightParam
Definition: MSLCM_SL2015.h:315
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1512
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:2714
const SUMOReal myChangeProbThresholdRight
Definition: MSLCM_SL2015.h:325
The vehicle is blocked by right leader.
SUMOReal getImpatience() const
Returns this vehicles impatience.
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:3714
const SUMOReal mySpeedLossProbThreshold
Definition: MSLCM_SL2015.h:327
The edge is an internal edge.
Definition: MSEdge.h:97
SUMOReal getRightSideOnEdge() const
Definition: MSLane.h:897
static LaneChangeAction getLCA(int state, SUMOReal latDist)
compute lane change action from desired lateral distance
const std::vector< SUMOReal > getSubLaneSides() const
Returns the right side offsets of this edge&#39;s sublanes.
Definition: MSEdge.h:574
const std::string & getID() const
Returns the name of the vehicle.
SUMOReal getMinGapLat() const
Get the minimum lateral gap that vehicles of this type maintain.
#define TURN_LANE_DIST
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
const MSCFModel & myCarFollowModel
The vehicle&#39;s car following model.
SUMOReal getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:2198
int myPreviousState
lane changing state from the previous simulation step
Definition: MSLCM_SL2015.h:305
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:441
The vehicle is blocked by right follower.
int computeSublaneShift(const MSEdge *prevEdge, const MSEdge *curEdge)
compute shift so that prevSublane + shift = newSublane
SUMOReal mySpeedGainProbabilityLeft
a value for tracking the probability that a change to the left is beneficial
Definition: MSLCM_SL2015.h:275
Interface for lane-change models.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
SUMOReal getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
The vehicle is blocked by left leader.
#define SPEED_GAIN_MIN_SECONDS
bool amBlockingFollowerPlusNB()
Definition: MSLCM_SL2015.h:180
#define HELP_OVERTAKE
bool congested() const
Definition: MSVehicle.h:596
#define KEEP_RIGHT_TIME