SUMO - Simulation of Urban MObility
MSLCM_DK2008.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // A lane change model developed by D. Krajzewicz between 2004 and 2010
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
14 // Copyright (C) 2005-2017 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include <iostream>
37 #include <microsim/MSEdge.h>
38 #include <microsim/MSLane.h>
39 #include <microsim/MSNet.h>
40 #include "MSLCM_DK2008.h"
41 
42 //#define DEBUG_VEHICLE_GUI_SELECTION 1
43 
44 // ===========================================================================
45 // variable definitions
46 // ===========================================================================
47 // 80km/h will be the threshold for dividing between long/short foresight
48 #define LOOK_FORWARD_SPEED_DIVIDER 14.
49 
50 #define LOOK_FORWARD_FAR 15.
51 #define LOOK_FORWARD_NEAR 5.
52 
53 
54 
55 #define JAM_FACTOR 2.
56 #define JAM_FACTOR2 1.
57 
58 
59 // ===========================================================================
60 // member method definitions
61 // ===========================================================================
64  myChangeProbability(0),
65  myLeadingBlockerLength(0), myLeftSpace(0) {}
66 
68  changed();
69 }
70 
71 int
73  int laneOffset,
74  MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
75  const std::pair<MSVehicle*, double>& leader,
76  const std::pair<MSVehicle*, double>& neighLead,
77  const std::pair<MSVehicle*, double>& neighFollow,
78  const MSLane& neighLane,
79  const std::vector<MSVehicle::LaneQ>& preb,
80  MSVehicle** lastBlocked,
81  MSVehicle** firstBlocked) {
82  UNUSED_PARAMETER(firstBlocked);
83  return (laneOffset == -1 ?
84  wantsChangeToRight(msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked)
85  : wantsChangeToLeft(msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked));
86 
87 }
88 
89 
90 int
92  int blocked,
93  const std::pair<MSVehicle*, double>& leader,
94  const std::pair<MSVehicle*, double>& neighLead,
95  const std::pair<MSVehicle*, double>& neighFollow,
96  const MSLane& neighLane,
97  const std::vector<MSVehicle::LaneQ>& preb,
98  MSVehicle** lastBlocked,
99  MSVehicle** firstBlocked) {
100  UNUSED_PARAMETER(firstBlocked);
101 #ifdef DEBUG_VEHICLE_GUI_SELECTION
103  int bla = 0;
104  }
105 #endif
106  MSVehicle::LaneQ curr, best;
107  int bestLaneOffset = 0;
108  double currentDist = 0;
109  double neighDist = 0;
110  double neighExtDist = 0;
111  double currExtDist = 0;
112  int currIdx = 0;
113  MSLane* prebLane = myVehicle.getLane();
114  if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
115  // internal edges are not kept inside the bestLanes structure
116  prebLane = prebLane->getLinkCont()[0]->getLane();
117  }
118  for (int p = 0; p < (int) preb.size(); ++p) {
119  if (preb[p].lane == prebLane && p > 0) {
120  curr = preb[p];
121  bestLaneOffset = curr.bestLaneOffset;
122  currentDist = curr.length;
123  currExtDist = curr.lane->getLength();
124  neighDist = preb[p - 1].length;
125  neighExtDist = preb[p - 1].lane->getLength();
126  best = preb[p + bestLaneOffset];
127  currIdx = p;
128  break;
129  }
130  }
131 
132  // keep information about being a leader/follower
133  int ret = (myOwnState & 0xffff0000);
134 
135  if (leader.first != 0
136  &&
138  &&
139  (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
140 
144  } else {
145  ret |= LCA_AMBACKBLOCKER;
146  myDontBrake = true;
147  }
148  }
149 
150  // process information about the last blocked vehicle
151  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
152  if ((*lastBlocked) != 0) {
153  double gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
154  if (gap > 0.1) {
156  if ((*lastBlocked)->getSpeed() < SUMO_const_haltingSpeed) {
158  } else {
159  ret |= LCA_AMBACKBLOCKER;
160  }
161  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (double)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
162  (*lastBlocked) = 0;
163  }
164  return ret;
165  }
166  }
167 
168  // we try to estimate the distance which is necessary to get on a lane
169  // we have to get on in order to keep our route
170  // we assume we need something that depends on our velocity
171  // and compare this with the free space on our wished lane
172  //
173  // if the free space is somehow less than the space we need, we should
174  // definitely try to get to the desired lane
175  //
176  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
178  ? myVehicle.getSpeed() * (double) LOOK_FORWARD_FAR
179  : myVehicle.getSpeed() * (double) LOOK_FORWARD_NEAR;
180  rv += myVehicle.getVehicleType().getLengthWithGap() * (double) 2.;
181 
182  double tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (double) JAM_FACTOR2;
183 
184  // assert(best.length > curr.length);
185  // XXX if (curr.length != best.length) && ...
186  if (fabs(best.length - curr.length) > MIN2((double) .1, best.lane->getLength()) && bestLaneOffset < 0 && currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, rv)) {
187  informBlocker(msgPass, blocked, LCA_MRIGHT, neighLead, neighFollow);
188  if (neighLead.second > 0 && neighLead.second > leader.second) {
189  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (double) 0.5);
190  }
191 
192  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, right
193  // if there is a leader and he wants to change to left (we want to change to right)
194  if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_LEFT) != 0) {
195  // save at least his length in myLeadingBlockerLength
196  myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
197  // save the left space
198  myLeftSpace = currentDist - myVehicle.getPositionOnLane();
199  }
200  //
201 
202  return ret | LCA_RIGHT | LCA_STRATEGIC | LCA_URGENT;
203  }
204 
205 
206  // the opposite lane-changing direction should be done than the one examined herein
207  // we'll check whether we assume we could change anyhow and get back in time...
208  //
209  // this rule prevents the vehicle from moving in opposite direction of the best lane
210  // unless the way till the end where the vehicle has to be on the best lane
211  // is long enough
212  double maxJam = MAX2(preb[currIdx - 1].occupation, preb[currIdx].occupation);
213  double neighLeftPlace = MAX2((double) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
214  if (bestLaneOffset >= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset + 2, rv))) {
215  // ...we will not change the lane if not
216  return ret | LCA_STAY | LCA_STRATEGIC;
217  }
218 
219 
220  // if the current lane is the best and a lane-changing would cause a situation
221  // of which we assume we will not be able to return to the lane we have to be on...
222  //
223  // this rule prevents the vehicle from leaving the current, best lane when it is
224  // close to this lane's end
225  if (currExtDist > neighExtDist && (neighLeftPlace * 2. < rv/*||currE[currIdx+1].length<currentDist*/)) {
226  return ret | LCA_STAY | LCA_STRATEGIC;
227  }
228 
229  // let's also regard the case where the vehicle is driving on a highway...
230  // in this case, we do not want to get to the dead-end of an on-ramp
231  //
232  // THIS RULE APPLIES ONLY TO CHANGING TO THE RIGHT LANE
233  if (bestLaneOffset == 0 && preb[currIdx - 1].bestLaneOffset != 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6) {
234  return ret | LCA_STAY | LCA_STRATEGIC;
235  }
236  // --------
237 
238  // -------- make place on current lane if blocking follower
240  &&
241  (currentDistAllows(neighDist, bestLaneOffset, rv) || neighDist >= currentDist)) {
242 
243  return ret | LCA_RIGHT | LCA_COOPERATIVE | LCA_URGENT;
244  }
245  // --------
246 
247 
248  // -------- security checks for krauss
249  // (vsafe fails when gap<0)
250  if ((blocked & LCA_BLOCKED) != 0) {
251  return ret;
252  }
253  // --------
254 
255  // -------- higher speed
256  if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader)) {
257  return ret;
258  }
259  double thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
260  double neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
261  if (neighLead.first == 0) {
262  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
263  } else {
264  // @todo: what if leader is below safe gap?!!!
265  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
266  }
267  if (leader.first == 0) {
268  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
269  } else {
270  // @todo: what if leader is below safe gap?!!!
271  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
272  }
273 
274  thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
275  neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
276  if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) {
277  // ok, the current lane is faster than the right one...
278  if (myChangeProbability < 0) {
279  myChangeProbability *= pow(0.5, TS);
280  }
281  } else {
282  // ok, the right lane is faster than the current
283  myChangeProbability -= TS * ((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)));
284  }
285 
286  // let's recheck the "Rechtsfahrgebot"
288  vmax -= (double)(5. / 2.6);
289  if (neighLaneVSafe >= vmax) {
290  myChangeProbability -= TS * ((neighLaneVSafe - vmax) / (vmax));
291  }
292 
293  if (myChangeProbability < -2 && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((double) .1, myVehicle.getSpeed())) { // -.1
294  return ret | LCA_RIGHT | LCA_SPEEDGAIN;
295  }
296  // --------
297 
298  return ret;
299 }
300 
301 
302 int
304  int blocked,
305  const std::pair<MSVehicle*, double>& leader,
306  const std::pair<MSVehicle*, double>& neighLead,
307  const std::pair<MSVehicle*, double>& neighFollow,
308  const MSLane& neighLane,
309  const std::vector<MSVehicle::LaneQ>& preb,
310  MSVehicle** lastBlocked,
311  MSVehicle** firstBlocked) {
312  UNUSED_PARAMETER(firstBlocked);
313 #ifdef DEBUG_VEHICLE_GUI_SELECTION
315  int bla = 0;
316  }
317 #endif
318  MSVehicle::LaneQ curr, best;
319  int bestLaneOffset = 0;
320  double currentDist = 0;
321  double neighDist = 0;
322  double neighExtDist = 0;
323  double currExtDist = 0;
324  int currIdx = 0;
325  MSLane* prebLane = myVehicle.getLane();
326  if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
327  // internal edges are not kept inside the bestLanes structure
328  prebLane = prebLane->getLinkCont()[0]->getLane();
329  }
330  for (int p = 0; p < (int) preb.size(); ++p) {
331  if (preb[p].lane == prebLane) {
332  curr = preb[p];
333  bestLaneOffset = curr.bestLaneOffset;
334  currentDist = curr.length;
335  currExtDist = curr.lane->getLength();
336  neighDist = preb[p + 1].length;
337  neighExtDist = preb[p + 1].lane->getLength();
338  best = preb[p + bestLaneOffset];
339  currIdx = p;
340  break;
341  }
342  }
343  // keep information about being a leader/follower
344  int ret = (myOwnState & 0xffff0000);
345 
346  // ?!!!
347  if (leader.first != 0
348  &&
350  &&
351  (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
352 
356  } else {
357  ret |= LCA_AMBACKBLOCKER;
358  myDontBrake = true;
359  }
360  }
361 
362  // process information about the last blocked vehicle
363  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
364  if ((*lastBlocked) != 0) {
365  double gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
366  if (gap > 0.1) {
368  if ((*lastBlocked)->getSpeed() < SUMO_const_haltingSpeed) {
370  } else {
371  ret |= LCA_AMBACKBLOCKER;
372  }
373  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (double)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
374  (*lastBlocked) = 0;
375  }
376  return ret;
377  }
378  }
379 
380  // we try to estimate the distance which is necessary to get on a lane
381  // we have to get on in order to keep our route
382  // we assume we need something that depends on our velocity
383  // and compare this with the free space on our wished lane
384  //
385  // if the free space is somehow less than the space we need, we should
386  // definitely try to get to the desired lane
387  //
388  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
390  ? myVehicle.getSpeed() * (double) LOOK_FORWARD_FAR
391  : myVehicle.getSpeed() * (double) LOOK_FORWARD_NEAR;
392  lv += myVehicle.getVehicleType().getLengthWithGap() * (double) 2.;
393 
394 
395  double tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (double) JAM_FACTOR2;
396  if (fabs(best.length - curr.length) > MIN2((double) .1, best.lane->getLength()) && bestLaneOffset > 0
397  &&
398  currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, lv)) {
399  informBlocker(msgPass, blocked, LCA_MLEFT, neighLead, neighFollow);
400  if (neighLead.second > 0 && neighLead.second > leader.second) {
401  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (double) 0.5);
402  }
403 
404  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, left
405  // if there is a leader and he wants to change to right (we want to change to left)
406  if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_RIGHT) != 0) {
407  // save at least his length in myLeadingBlockerLength
408  myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
409  // save the left space
410  myLeftSpace = currentDist - myVehicle.getPositionOnLane();
411  }
412  //
413 
414  return ret | LCA_LEFT | LCA_STRATEGIC | LCA_URGENT;
415  }
416 
417  // the opposite lane-changing direction should be rather done, not
418  // the one examined herein
419  // we'll check whether we assume we could change anyhow and get back in time...
420  //
421  // this rule prevents the vehicle from moving in opposite direction of the best lane
422  // unless the way till the end where the vehicle has to be on the best lane
423  // is long enough
424  double maxJam = MAX2(preb[currIdx + 1].occupation, preb[currIdx].occupation);
425  double neighLeftPlace = MAX2((double) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
426  if (bestLaneOffset <= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset - 2, lv))) {
427  // ...we will not change the lane if not
428  return ret | LCA_STAY | LCA_STRATEGIC;
429  }
430 
431 
432  // if the current lane is the best and a lane-changing would cause a situation
433  // of which we assume we will not be able to return to the lane we have to be on...
434  //
435  // this rule prevents the vehicle from leaving the current, best lane when it is
436  // close to this lane's end
437  if (currExtDist > neighExtDist && (neighLeftPlace * 2. < lv/*||currE[currIdx+1].length<currentDist*/)) {
438  // ... let's not change the lane
439  return ret | LCA_STAY | LCA_STRATEGIC;
440  }
441 
442  /*
443  // let's also regard the case where the vehicle is driving on a highway...
444  // in this case, we do not want to get to the dead-end of an on-ramp
445  if(bestLaneOffset==0&&myVehicle.getLane().getMaxSpeed()>80./3.6) {
446  return ret;
447  }
448  */
449 
450 
451  /*
452  // if the current lane is the
453  if(bestLaneOffset==0&&(neighDist==0||curr.seenVehicles2*JAM_FACTOR>=neighExtDist-curr.length)) {
454  return ret;
455  }
456  */
457  // --------
458 
459  // -------- make place on current lane if blocking follower
461  &&
462  (currentDistAllows(neighDist, bestLaneOffset, lv) || neighDist >= currentDist)) {
463 
464  return ret | LCA_LEFT | LCA_COOPERATIVE | LCA_URGENT;
465  }
466  // --------
467 
468  // -------- security checks for krauss
469  // (vsafe fails when gap<0)
470  if ((blocked & LCA_BLOCKED) != 0) {
471  return ret;
472  }
473 
474  // -------- higher speed
475  if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader)) {
476  return ret;
477  }
478  double neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
479  double thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
480  if (neighLead.first == 0) {
481  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); // !!! warum nicht die Folgesgeschw.?
482  } else {
483  // @todo: what if leader is below safe gap?!!!
484  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
485  }
486  if (leader.first == 0) {
487  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
488  } else {
489  // @todo: what if leader is below safe gap?!!!
490  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
491  }
492  thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
493  neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
494  if (thisLaneVSafe > neighLaneVSafe) {
495  // this lane is better
496  if (myChangeProbability > 0) {
497  myChangeProbability *= pow(0.5, TS);
498  }
499  } else {
500  // right lane is better
501  myChangeProbability += TS * ((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle))); // !!! Fahrzeuggeschw.!
502  }
503  if (myChangeProbability > .2 && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { // .1
504  return ret | LCA_LEFT | LCA_SPEEDGAIN | LCA_URGENT;
505  }
506  // --------
507 
508  return ret;
509 }
510 
511 
512 double
513 MSLCM_DK2008::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
514 #ifdef DEBUG_VEHICLE_GUI_SELECTION
516  int bla = 0;
517  }
518 #endif
519  int state = myOwnState;
520 
521  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
522  double MAGIC_offset = 1.;
523  // if we want to change and have a blocking leader and there is enough room for him in front of us
524  if (myLeadingBlockerLength != 0) {
525  double space = myLeftSpace - myLeadingBlockerLength - MAGIC_offset - myVehicle.getVehicleType().getMinGap();
526  if (space > 0) {
527  // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
528  double safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space);
529  // if we are approaching this place
530  if (safe < wanted) {
531  // return this speed as the speed to use
532  return MAX2(min, safe);
533  }
534  }
535  }
536 
537  // just to make sure to be notified about lane chaning end
539  // remove chaning information if on a road with a single lane
540  changed();
541  return wanted;
542  }
543 
544  double nVSafe = wanted;
545  bool gotOne = false;
546  for (std::vector<double>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
547  double v = (*i);
548  if (v >= min && v <= max) {
549  nVSafe = MIN2(v, nVSafe);
550  gotOne = true;
551  }
552  }
553 
554  // check whether the vehicle is blocked
555  if ((state & LCA_WANTS_LANECHANGE) != 0) {
556  if (gotOne && !myDontBrake) {
557  return nVSafe;
558  }
559  // check whether the vehicle maybe has to be swapped with one of
560  // the blocking vehicles
561  if ((state & LCA_BLOCKED) != 0) {
562  if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
563  // if interacting with leader and not too slow
564  return (min + wanted) / (double) 2.0;
565  }
566  if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
567  return (max + wanted) / (double) 2.0;
568  }
569  return (min + wanted) / (double) 2.0;
570  }
571  }
572 
573 
574  // decelerate if being a blocking follower
575  // (and does not have to change lanes)
576  if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
577  if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
578  return 0;
579  }
580  return (min + wanted) / (double) 2.0;
581  }
582  if ((state & LCA_AMBACKBLOCKER) != 0) {
583  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
584  return min;
585  }
586  }
587  if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
588  return min;
589  }
590  // accelerate if being a blocking leader or blocking follower not able to brake
591  // (and does not have to change lanes)
592  if ((state & LCA_AMBLOCKINGLEADER) != 0) {
593  return (max + wanted) / (double) 2.0;
594  }
595  if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
596  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
597  return wanted;
598  }
599  return (min + wanted) / (double) 2.0;
600  }
601  return wanted;
602 }
603 
604 
605 void*
606 MSLCM_DK2008::inform(void* info, MSVehicle* /*sender*/) {
607  Info* pinfo = (Info*) info;
608  //myOwnState &= 0xffffffff; // reset all bits of MyLCAEnum but only those
609  myOwnState |= pinfo->second;
610  delete pinfo;
611  return (void*) true;
612 }
613 
614 
615 void
617  myOwnState = 0;
620  myLeftSpace = 0;
621  myVSafes.clear();
622  myDontBrake = false;
623 }
624 
625 
626 void
628  int& blocked,
629  int dir,
630  const std::pair<MSVehicle*, double>& neighLead,
631  const std::pair<MSVehicle*, double>& neighFollow) {
632  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
633  assert(neighFollow.first != 0);
634  MSVehicle* nv = neighFollow.first;
635  double decelGap =
636  neighFollow.second
637  + SPEED2DIST(myVehicle.getSpeed()) * (double) 2.0
638  - MAX2(nv->getSpeed() - (double) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (double) 2.0, (double) 0);
639  if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())) {
640  double vsafe = myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
641  msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
642  } else {
643  double vsafe = neighFollow.second <= 0 ? 0 : myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
645  }
646  }
647  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
648  if (neighLead.first != 0 && neighLead.second > 0) {
649  msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
650  }
651  }
652 }
653 
654 
655 void
658  myOwnState = 0;
660  myLeftSpace = 0;
661  myVSafes.clear();
662  myDontBrake = false;
663  // truncate myChangeProbability to work around numerical instability between different builds
664  myChangeProbability = ceil(myChangeProbability * 100000.0) * 0.00001;
665 }
666 
667 
668 /****************************************************************************/
669 
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:462
double myChangeProbability
Definition: MSLCM_DK2008.h:158
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:582
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
The action is done to help someone else.
#define min(a, b)
Definition: polyfonts.c:66
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:488
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive...
Definition: MSVehicle.h:714
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel) const =0
Computes the vehicle&#39;s follow speed (no dawdling)
The car-following model abstraction.
Definition: MSCFModel.h:60
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:375
virtual void prepareStep()
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
Wants go to the right.
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:193
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:192
T MAX2(T a, T b)
Definition: StdDefs.h:70
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
Definition: MSLCM_DK2008.h:146
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:484
virtual double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel)
Called to adapt the speed in order to allow a lane change.
virtual bool predInteraction(const std::pair< MSVehicle *, double > &leader)
#define TS
Definition: SUMOTime.h:52
MSLCM_DK2008(MSVehicle &v)
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:706
Wants go to the left.
The action is due to the wish to be faster (tactical lc)
#define LOOK_FORWARD_FAR
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
std::string gDebugSelectedVehicle
Definition: StdDefs.cpp:37
virtual int wantsChangeToRight(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change to right This method gets the information about...
Needs to stay on the current lane.
A class responsible for exchanging messages between cars involved in lane-change interaction.
MSLane * lane
The described lane.
Definition: MSVehicle.h:704
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:796
#define max(a, b)
Definition: polyfonts.c:65
#define ACCEL2DIST(x)
Definition: SUMOTime.h:59
blocked in all directions
The action is urgent (to be defined by lc-model)
virtual int wantsChangeToLeft(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change to left This method gets the information about ...
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:476
double getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
T MIN2(T a, T b)
Definition: StdDefs.h:64
The action is needed to follow the route (navigational lc)
A structure representing the best lanes for continuing the current route starting at &#39;lane&#39;...
Definition: MSVehicle.h:702
#define LOOK_FORWARD_SPEED_DIVIDER
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
bool amBlockingFollowerPlusNB()
Definition: MSLCM_DK2008.h:143
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:249
int myOwnState
The current state of the vehicle.
#define JAM_FACTOR2
double myLeftSpace
Definition: MSLCM_DK2008.h:161
virtual ~MSLCM_DK2008()
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:710
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
Definition: MSLCM_DK2008.h:149
double myLeadingBlockerLength
Definition: MSLCM_DK2008.h:160
std::vector< double > myVSafes
Definition: MSLCM_DK2008.h:163
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:56
std::pair< double, int > Info
Definition: MSLCM_DK2008.h:153
double getSecureGap(const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.h:276
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1597
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:442
The edge is an internal edge.
Definition: MSEdge.h:97
blocker by follower
#define LOOK_FORWARD_NEAR
const std::string & getID() const
Returns the name of the vehicle.
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
const MSCFModel & myCarFollowModel
The vehicle&#39;s car following model.
virtual void * inform(void *info, MSVehicle *sender)
void informBlocker(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int &blocked, int dir, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow)
Interface for lane-change models.
virtual double stopSpeed(const MSVehicle *const veh, const double speed, double gap) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...
virtual void changed()
virtual bool congested(const MSVehicle *const neighLeader)