Eclipse 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.dev/sumo
3 // Copyright (C) 2005-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
22 // A lane change model developed by D. Krajzewicz between 2004 and 2010
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include <iostream>
28 #include <microsim/MSEdge.h>
29 #include <microsim/MSLane.h>
30 #include <microsim/MSLink.h>
31 #include <microsim/MSNet.h>
32 #include "MSLCM_DK2008.h"
33 
34 // ===========================================================================
35 // variable definitions
36 // ===========================================================================
37 // 80km/h will be the threshold for dividing between long/short foresight
38 #define LOOK_FORWARD_SPEED_DIVIDER 14.
39 
40 #define LOOK_FORWARD_FAR 15.
41 #define LOOK_FORWARD_NEAR 5.
42 
43 
44 
45 #define JAM_FACTOR 2.
46 #define JAM_FACTOR2 1.
47 
48 
49 // ===========================================================================
50 // member method definitions
51 // ===========================================================================
54  myChangeProbability(0),
55  myLeadingBlockerLength(0), myLeftSpace(0) {}
56 
58  changed();
59 }
60 
61 int
63  int laneOffset,
64  MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
65  const std::pair<MSVehicle*, double>& leader,
66  const std::pair<MSVehicle*, double>& /*follower*/,
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  const 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(getCarFollowModel().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(getCarFollowModel().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, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
249  } else {
250  // @todo: what if leader is below safe gap?!!!
251  neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
252  }
253  if (leader.first == 0) {
254  thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
255  } else {
256  // @todo: what if leader is below safe gap?!!!
257  thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
258  }
259 
260  thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getMaxSpeed());
261  neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.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"
273  double vmax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
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  const 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(getCarFollowModel().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(getCarFollowModel().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, getCarFollowModel().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, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
466  }
467  if (leader.first == 0) {
468  thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
469  } else {
470  // @todo: what if leader is below safe gap?!!!
471  thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
472  }
473  thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getMaxSpeed());
474  neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.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, MSCFModel::CalcReason::LANE_CHANGE);
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, &myVehicle,
617  double vsafe = getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
618  msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
619  } else {
620  double vsafe = neighFollow.second <= 0 ? 0 : getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
622  }
623  }
624  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
625  if (neighLead.first != 0 && neighLead.second > 0) {
626  msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
627  }
628  }
629 }
630 
631 
632 void
635  myOwnState = 0;
637  myLeftSpace = 0;
638  myVSafes.clear();
639  myDontBrake = false;
640  // truncate myChangeProbability to work around numerical instability between different builds
641  myChangeProbability = ceil(myChangeProbability * 100000.0) * 0.00001;
642  resetSpeedLat();
643 }
644 
645 
646 /****************************************************************************/
#define JAM_FACTOR2
#define LOOK_FORWARD_NEAR
#define LOOK_FORWARD_SPEED_DIVIDER
#define LOOK_FORWARD_FAR
#define SPEED2DIST(x)
Definition: SUMOTime.h:45
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:51
#define TS
Definition: SUMOTime.h:42
#define ACCEL2DIST(x)
Definition: SUMOTime.h:49
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_BLOCKED_BY_LEADER
blocked by leader
@ LCA_AMBACKBLOCKER
@ LCA_AMBLOCKINGLEADER
@ LCA_AMBLOCKINGFOLLOWER_DONTBRAKE
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_LEFT
Wants go to the left.
@ LCA_MRIGHT
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_AMBACKBLOCKER_STANDING
@ LCA_SPEEDGAIN
The action is due to the wish to be faster (tactical lc)
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_MLEFT
@ LCA_BLOCKED_BY_FOLLOWER
blocker by follower
@ LCA_AMBLOCKINGFOLLOWER
LaneChangeModel
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:58
T MAX2(T a, T b)
Definition: StdDefs.h:82
A class responsible for exchanging messages between cars involved in lane-change interaction.
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
Interface for lane-change models.
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
int myOwnState
The current state of the vehicle.
virtual bool predInteraction(const std::pair< MSVehicle *, double > &leader)
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
virtual bool congested(const MSVehicle *const neighLeader)
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
The car-following model abstraction.
Definition: MSCFModel.h:55
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:292
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, 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.cpp:166
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:264
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const =0
Computes the vehicle's follow speed (no dawdling)
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition: MSCFModel.h:168
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
double myLeftSpace
Definition: MSLCM_DK2008.h:142
std::vector< double > myVSafes
Definition: MSLCM_DK2008.h:144
std::pair< double, int > Info
Definition: MSLCM_DK2008.h:134
MSLCM_DK2008(MSVehicle &v)
virtual ~MSLCM_DK2008()
bool amBlockingFollowerPlusNB()
Definition: MSLCM_DK2008.h:124
virtual void changed()
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...
double myChangeProbability
Definition: MSLCM_DK2008.h:139
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, 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...
void informBlocker(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int &blocked, int dir, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow)
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
Definition: MSLCM_DK2008.h:130
double myLeadingBlockerLength
Definition: MSLCM_DK2008.h:141
virtual void * inform(void *info, MSVehicle *sender)
virtual void prepareStep()
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 ...
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.
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
Definition: MSLCM_DK2008.h:127
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:712
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:584
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:566
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:752
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:974
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getMinGap() const
Get the free space in front of vehicles of this class.
A structure representing the best lanes for continuing the current route starting at 'lane'.
Definition: MSVehicle.h:865
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:869
MSLane * lane
The described lane.
Definition: MSVehicle.h:867
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition: MSVehicle.h:877
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:873