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