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