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