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