SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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();
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)) {
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)) {
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();
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;
627 }
628 
629 
630 void
632  int& blocked,
633  int dir,
634  const std::pair<MSVehicle*, SUMOReal>& neighLead,
635  const std::pair<MSVehicle*, SUMOReal>& neighFollow) {
636  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
637  assert(neighFollow.first != 0);
638  MSVehicle* nv = neighFollow.first;
639  SUMOReal decelGap =
640  neighFollow.second
642  - MAX2(nv->getSpeed() - (SUMOReal) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (SUMOReal) 2.0, (SUMOReal) 0);
643  if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())) {
644  SUMOReal vsafe = myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
645  msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
646  } else {
647  SUMOReal vsafe = neighFollow.second <= 0 ? 0 : myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
649  }
650  }
651  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
652  if (neighLead.first != 0 && neighLead.second > 0) {
653  msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
654  }
655  }
656 }
657 
658 
659 void
661  myOwnState = 0;
663  myLeftSpace = 0;
664  myVSafes.clear();
665  myDontBrake = false;
666  // truncate myChangeProbability to work around numerical instability between different builds
667  myChangeProbability = ceil(myChangeProbability * 100000.0) * 0.00001;
668 }
669 
670 
671 /****************************************************************************/
672 
SUMOReal myChangeProbability
Definition: MSLCM_DK2008.h:158
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:571
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:82
SUMOReal getMaxSpeed() const
Get vehicle's maximum speed [m/s].
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
The action is done to help someone else.
#define min(a, b)
Definition: polyfonts.c:66
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:758
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
virtual bool predInteraction(const std::pair< MSVehicle *, SUMOReal > &leader)
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:192
SUMOReal getLengthWithGap() const
Get vehicle'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:681
virtual SUMOReal followSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const =0
Computes the vehicle's follow speed (no dawdling)
SUMOReal getLength() const
Returns the lane's length.
Definition: MSLane.h:480
virtual SUMOReal maxNextSpeed(SUMOReal speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:190
The car-following model abstraction.
Definition: MSCFModel.h:60
virtual void prepareStep()
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
Wants go to the right.
bool currentDistDisallows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_DK2008.h:146
T MAX2(T a, T b)
Definition: StdDefs.h:75
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 (>=0)
Definition: MSCFModel.h:276
SUMOReal myLeadingBlockerLength
Definition: MSLCM_DK2008.h:160
SUMOReal getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:374
#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 ...
Wants go to the left.
The action is due to the wish to be faster (tactical lc)
#define LOOK_FORWARD_FAR
SUMOReal length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:673
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
std::string gDebugSelectedVehicle
Definition: StdDefs.cpp:95
Needs to stay on the current lane.
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.
MSLane * lane
The described lane.
Definition: MSVehicle.h:671
#define max(a, b)
Definition: polyfonts.c:65
#define ACCEL2DIST(x)
Definition: SUMOTime.h:59
The action is urgent (to be defined by lc-model)
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.
T MIN2(T a, T b)
Definition: StdDefs.h:69
The action is needed to follow the route (navigational lc)
SUMOReal getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:472
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:669
#define LOOK_FORWARD_SPEED_DIVIDER
SUMOReal getMaxDecel() const
Get the vehicle type's maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
bool amBlockingFollowerPlusNB()
Definition: MSLCM_DK2008.h:143
int myOwnState
The current state of the vehicle.
#define JAM_FACTOR2
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.
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:249
SUMOReal occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:677
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
void informBlocker(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int &blocked, int dir, const std::pair< MSVehicle *, SUMOReal > &neighLead, const std::pair< MSVehicle *, SUMOReal > &neighFollow)
virtual SUMOReal stopSpeed(const MSVehicle *const veh, const SUMOReal speed, SUMOReal gap) const =0
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling) ...
const SUMOReal SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:57
SUMOReal getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:441
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:214
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:1512
SUMOReal getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:458
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:487
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:79
const MSCFModel & myCarFollowModel
The vehicle's car following model.
virtual void * inform(void *info, MSVehicle *sender)
SUMOReal myLeftSpace
Definition: MSLCM_DK2008.h:161
Interface for lane-change models.
virtual void changed()
const std::string & getID() const
Returns the name of the vehicle.
virtual bool congested(const MSVehicle *const neighLeader)
std::vector< SUMOReal > myVSafes
Definition: MSLCM_DK2008.h:163