SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSLCM_DK2004.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A lane change model developed by D. Krajzewicz between 2004 and 2010
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <iostream>
36 #include "MSEdge.h"
37 #include "MSLCM_DK2004.h"
38 
39 #ifdef CHECK_MEMORY_LEAKS
40 #include <foreign/nvwa/debug_new.h>
41 #endif // CHECK_MEMORY_LEAKS
42 
43 //#define DEBUG_VEHICLE_GUI_SELECTION 1
44 #ifdef DEBUG_VEHICLE_GUI_SELECTION
46 #include <guisim/GUIVehicle.h>
47 #include <guisim/GUILane.h>
48 #endif
49 
50 
51 
52 // ===========================================================================
53 // variable definitions
54 // ===========================================================================
55 // 80km/h will be the threshold for dividing between long/short foresight
56 #define LOOK_FORWARD_SPEED_DIVIDER 14.
57 
58 #define LOOK_FORWARD_FAR 15.
59 #define LOOK_FORWARD_NEAR 5.
60 
61 
62 
63 #define JAM_FACTOR 2.
64 #define JAM_FACTOR2 1.
65 
66 
67 // ===========================================================================
68 // member method definitions
69 // ===========================================================================
72  myChangeProbability(0),
73  myLeadingBlockerLength(0), myLeftSpace(0) {}
74 
76  changed();
77 }
78 
79 
80 int
82  int blocked,
83  const std::pair<MSVehicle*, SUMOReal>& leader,
84  const std::pair<MSVehicle*, SUMOReal>& neighLead,
85  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
86  const MSLane& neighLane,
87  const std::vector<MSVehicle::LaneQ>& preb,
88  MSVehicle** lastBlocked) {
89 #ifdef DEBUG_VEHICLE_GUI_SELECTION
90  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) {
91  int bla = 0;
92  }
93 #endif
94  MSVehicle::LaneQ curr, best;
95  int bestLaneOffset = 0;
96  SUMOReal currentDist = 0;
97  SUMOReal neighDist = 0;
98  SUMOReal neighExtDist = 0;
99  SUMOReal currExtDist = 0;
100  int currIdx = 0;
101  for (int p = 0; p < (int) preb.size(); ++p) {
102  if (preb[p].lane == myVehicle.getLane()) {
103  curr = preb[p];
104  bestLaneOffset = curr.bestLaneOffset;
105  currentDist = curr.length;
106  currExtDist = curr.lane->getLength();
107  neighDist = preb[p - 1].length;
108  neighExtDist = preb[p - 1].lane->getLength();
109  best = preb[p + bestLaneOffset];
110  currIdx = p;
111  }
112  }
113 
114  // keep information about being a leader/follower
115  int ret = (myOwnState & 0x00ffff00);
116 
117  if (leader.first != 0
118  &&
120  &&
121  (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
122 
124  if (myVehicle.getSpeed() > 0.1) {
126  } else {
127  ret |= LCA_AMBACKBLOCKER;
128  myDontBrake = true;
129  }
130  }
131 
132  // process information about the last blocked vehicle
133  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
134  if ((*lastBlocked) != 0) {
135  SUMOReal gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
136  if (gap > 0.1) {
138  if ((*lastBlocked)->getSpeed() < 0.1) {
140  } else {
141  ret |= LCA_AMBACKBLOCKER;
142  }
143  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (SUMOReal)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
144  (*lastBlocked) = 0;
145  }
146  return ret;
147  }
148  }
149 
150  // we try to estimate the distance which is necessary to get on a lane
151  // we have to get on in order to keep our route
152  // we assume we need something that depends on our velocity
153  // and compare this with the free space on our wished lane
154  //
155  // if the free space is somehow less than the space we need, we should
156  // definitely try to get to the desired lane
157  //
158  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
163 
164  SUMOReal tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (SUMOReal) JAM_FACTOR2;
165 
166  if (fabs(best.length - curr.length) > MIN2((SUMOReal) .1, best.lane->getLength()) && bestLaneOffset < 0 && currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, rv)) {
167  informBlocker(msgPass, blocked, LCA_MRIGHT, neighLead, neighFollow);
168  if (neighLead.second > 0 && neighLead.second > leader.second) {
169  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (SUMOReal) 0.5);
170  }
171 
172  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, right
173  // if there is a leader and he wants to change to left (we want to change to right)
174  if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_LEFT) != 0) {
175  // save at least his length in myLeadingBlockerLength
176  myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
177  // save the left space
178  myLeftSpace = currentDist - myVehicle.getPositionOnLane();
179  }
180  //
181 
182  return ret | LCA_RIGHT | LCA_URGENT;
183  }
184 
185 
186  // the opposite lane-changing direction should be done than the one examined herein
187  // we'll check whether we assume we could change anyhow and get back in time...
188  //
189  // this rule prevents the vehicle from moving in opposite direction of the best lane
190  // unless the way till the end where the vehicle has to be on the best lane
191  // is long enough
192  SUMOReal maxJam = MAX2(preb[currIdx - 1].occupation, preb[currIdx].occupation);
193  SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
194  if (bestLaneOffset >= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset + 2, rv))) {
195  // ...we will not change the lane if not
196  return ret;
197  }
198 
199 
200  // if the current lane is the best and a lane-changing would cause a situation
201  // of which we assume we will not be able to return to the lane we have to be on...
202  //
203  // this rule prevents the vehicle from leaving the current, best lane when it is
204  // close to this lane's end
205  if (currExtDist > neighExtDist && (neighLeftPlace * 2. < rv/*||currE[currIdx+1].length<currentDist*/)) {
206  return ret;
207  }
208 
209  // let's also regard the case where the vehicle is driving on a highway...
210  // in this case, we do not want to get to the dead-end of an on-ramp
211  //
212  // THIS RULE APPLIES ONLY TO CHANGING TO THE RIGHT LANE
213  if (bestLaneOffset == 0 && preb[currIdx - 1].bestLaneOffset != 0 && myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle) > 80. / 3.6) {
214  return ret;
215  }
216  // --------
217 
218  // -------- make place on current lane if blocking follower
220  &&
221  (currentDistAllows(neighDist, bestLaneOffset, rv) || neighDist >= currentDist)) {
222 
223  return ret | LCA_RIGHT | LCA_URGENT;
224  }
225  // --------
226 
227 
228  // -------- security checks for krauss
229  // (vsafe fails when gap<0)
230  if ((blocked & LCA_BLOCKED) != 0) {
231  return ret;
232  }
233  // --------
234 
235  // -------- higher speed
236  if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) {
237  return ret;
238  }
240  SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
241  if (neighLead.first == 0) {
242  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
243  } else {
244  // @todo: what if leader is below safe gap?!!!
245  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
246  }
247  if (leader.first == 0) {
248  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
249  } else {
250  // @todo: what if leader is below safe gap?!!!
251  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
252  }
253 
254  thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
255  neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
256  if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) {
257  // ok, the current lane is faster than the right one...
258  if (myChangeProbability < 0) {
259  myChangeProbability /= 2.0;
260  }
261  } else {
262  // ok, the right lane is faster than the current
263  myChangeProbability -= (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)));
264  }
265 
266  // let's recheck the "Rechtsfahrgebot"
268  vmax -= (SUMOReal)(5. / 2.6);
269  if (neighLaneVSafe >= vmax) {
270 #ifndef NO_TRACI
271  /* if there was a request by TraCI for changing to this lane
272  and holding it, this rule is ignored */
274 #endif
275  myChangeProbability -= (SUMOReal)((neighLaneVSafe - vmax) / (vmax));
276 #ifndef NO_TRACI
277  }
278 #endif
279  }
280 
281  if (myChangeProbability < -2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1
282  return ret | LCA_RIGHT | LCA_SPEEDGAIN;
283  }
284  // --------
285 
286 #ifndef NO_TRACI
287  // If there is a request by TraCI, try to change the lane
289  return ret | LCA_RIGHT;
290  }
291 #endif
292 
293  return ret;
294 }
295 
296 
297 int
299  int blocked,
300  const std::pair<MSVehicle*, SUMOReal>& leader,
301  const std::pair<MSVehicle*, SUMOReal>& neighLead,
302  const std::pair<MSVehicle*, SUMOReal>& neighFollow,
303  const MSLane& neighLane,
304  const std::vector<MSVehicle::LaneQ>& preb,
305  MSVehicle** lastBlocked) {
306 #ifdef DEBUG_VEHICLE_GUI_SELECTION
307  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) {
308  int bla = 0;
309  }
310 #endif
311  MSVehicle::LaneQ curr, best;
312  int bestLaneOffset = 0;
313  SUMOReal currentDist = 0;
314  SUMOReal neighDist = 0;
315  SUMOReal neighExtDist = 0;
316  SUMOReal currExtDist = 0;
317  int currIdx = 0;
318  for (int p = 0; p < (int) preb.size(); ++p) {
319  if (preb[p].lane == myVehicle.getLane()) {
320  curr = preb[p];
321  bestLaneOffset = curr.bestLaneOffset;
322  currentDist = curr.length;
323  currExtDist = curr.lane->getLength();
324  neighDist = preb[p + 1].length;
325  neighExtDist = preb[p + 1].lane->getLength();
326  best = preb[p + bestLaneOffset];
327  currIdx = p;
328  }
329  }
330  // keep information about being a leader/follower
331  int ret = (myOwnState & 0x00ffff00);
332 
333  // ?!!!
334  if (leader.first != 0
335  &&
337  &&
338  (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
339 
341  if (myVehicle.getSpeed() > 0.1) {
343  } else {
344  ret |= LCA_AMBACKBLOCKER;
345  myDontBrake = true;
346  }
347  }
348 
349  // process information about the last blocked vehicle
350  // if this vehicle is blocking someone in front, we maybe decelerate to let him in
351  if ((*lastBlocked) != 0) {
352  SUMOReal gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
353  if (gap > 0.1) {
355  if ((*lastBlocked)->getSpeed() < 0.1) {
357  } else {
358  ret |= LCA_AMBACKBLOCKER;
359  }
360  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (SUMOReal)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
361  (*lastBlocked) = 0;
362  }
363  return ret;
364  }
365  }
366 
367  // we try to estimate the distance which is necessary to get on a lane
368  // we have to get on in order to keep our route
369  // we assume we need something that depends on our velocity
370  // and compare this with the free space on our wished lane
371  //
372  // if the free space is somehow less than the space we need, we should
373  // definitely try to get to the desired lane
374  //
375  // this rule forces our vehicle to change the lane if a lane changing is necessary soon
380 
381 
382  SUMOReal tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (SUMOReal) JAM_FACTOR2;
383  if (fabs(best.length - curr.length) > MIN2((SUMOReal) .1, best.lane->getLength()) && bestLaneOffset > 0
384  &&
385  currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, lv)) {
386  informBlocker(msgPass, blocked, LCA_MLEFT, neighLead, neighFollow);
387  if (neighLead.second > 0 && neighLead.second > leader.second) {
388  myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (SUMOReal) 0.5);
389  }
390 
391  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, left
392  // if there is a leader and he wants to change to right (we want to change to left)
393  if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_RIGHT) != 0) {
394  // save at least his length in myLeadingBlockerLength
395  myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
396  // save the left space
397  myLeftSpace = currentDist - myVehicle.getPositionOnLane();
398  }
399  //
400 
401  return ret | LCA_LEFT | LCA_URGENT;
402  }
403 
404  // the opposite lane-changing direction should be rather done, not
405  // the one examined herein
406  // we'll check whether we assume we could change anyhow and get back in time...
407  //
408  // this rule prevents the vehicle from moving in opposite direction of the best lane
409  // unless the way till the end where the vehicle has to be on the best lane
410  // is long enough
411  SUMOReal maxJam = MAX2(preb[currIdx + 1].occupation, preb[currIdx].occupation);
412  SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
413  if (bestLaneOffset <= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset - 2, lv))) {
414  // ...we will not change the lane if not
415  return ret;
416  }
417 
418 
419  // if the current lane is the best and a lane-changing would cause a situation
420  // of which we assume we will not be able to return to the lane we have to be on...
421  //
422  // this rule prevents the vehicle from leaving the current, best lane when it is
423  // close to this lane's end
424  if (currExtDist > neighExtDist && (neighLeftPlace * 2. < lv/*||currE[currIdx+1].length<currentDist*/)) {
425  // ... let's not change the lane
426  return ret;
427  }
428 
429  /*
430  // let's also regard the case where the vehicle is driving on a highway...
431  // in this case, we do not want to get to the dead-end of an on-ramp
432  if(bestLaneOffset==0&&myVehicle.getLane().getMaxSpeed()>80./3.6) {
433  return ret;
434  }
435  */
436 
437 
438  /*
439  // if the current lane is the
440  if(bestLaneOffset==0&&(neighDist==0||curr.seenVehicles2*JAM_FACTOR>=neighExtDist-curr.length)) {
441  return ret;
442  }
443  */
444  // --------
445 
446  // -------- make place on current lane if blocking follower
448  &&
449  (currentDistAllows(neighDist, bestLaneOffset, lv) || neighDist >= currentDist)) {
450 
451  return ret | LCA_LEFT | LCA_URGENT;
452  }
453  // --------
454 
455  // -------- security checks for krauss
456  // (vsafe fails when gap<0)
457  if ((blocked & LCA_BLOCKED) != 0) {
458  return ret;
459  }
460 
461  // -------- higher speed
462  if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) {
463  return ret;
464  }
465  SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
467  if (neighLead.first == 0) {
468  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); // !!! warum nicht die Folgesgeschw.?
469  } else {
470  // @todo: what if leader is below safe gap?!!!
471  neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
472  }
473  if (leader.first == 0) {
474  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
475  } else {
476  // @todo: what if leader is below safe gap?!!!
477  thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
478  }
479  thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
480  neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
481  if (thisLaneVSafe > neighLaneVSafe) {
482  // this lane is better
483  if (myChangeProbability > 0) {
484  myChangeProbability /= 2.0;
485  }
486  } else {
487  // right lane is better
488  myChangeProbability += (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle))); // !!! Fahrzeuggeschw.!
489  }
490  if (myChangeProbability > .2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1
491  return ret | LCA_LEFT | LCA_SPEEDGAIN | LCA_URGENT;
492  }
493  // --------
494 
495 #ifndef NO_TRACI
496  // If there is a request by TraCI, try to change the lane
498  return ret | LCA_LEFT;
499  }
500 #endif
501 
502  return ret;
503 }
504 
505 
506 SUMOReal
507 MSLCM_DK2004::patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
508 #ifdef DEBUG_VEHICLE_GUI_SELECTION
509  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) {
510  int bla = 0;
511  }
512 #endif
513  int state = myOwnState;
514  myOwnState = 0;
515 
516  // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
517  SUMOReal MAGIC_offset = 1.;
518  // if we want to change and have a blocking leader and there is enough room for him in front of us
519  if (myLeadingBlockerLength != 0) {
521  if (space > 0) {
522  // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
523  SUMOReal safe = cfModel.stopSpeed(&myVehicle, space);
524  // if we are approaching this place
525  if (safe < wanted) {
526  // return this speed as the speed to use
527  return MAX2(min, safe);
528  }
529  }
530  }
531 
532  // just to make sure to be notified about lane chaning end
533  if (myVehicle.getLane()->getEdge().getLanes().size() == 1) {
534  // remove chaning information if on a road with a single lane
535  changed();
536  return wanted;
537  }
538 
539  SUMOReal nVSafe = wanted;
540  bool gotOne = false;
541  for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
542  SUMOReal v = (*i);
543  if (v >= min && v <= max) {
544  nVSafe = MIN2(v, nVSafe);
545  gotOne = true;
546  }
547  }
548 
549  // check whether the vehicle is blocked
550  if ((state & LCA_WANTS_LANECHANGE) != 0) {
551  if (gotOne && !myDontBrake) {
552  return nVSafe;
553  }
554  // check whether the vehicle maybe has to be swapped with one of
555  // the blocking vehicles
556  if ((state & LCA_BLOCKED) != 0) {
557  if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
558  // if interacting with leader and not too slow
559  return (min + wanted) / (SUMOReal) 2.0;
560  }
561  if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
562  return (max + wanted) / (SUMOReal) 2.0;
563  }
564  return (min + wanted) / (SUMOReal) 2.0;
565  }
566  }
567 
568 
569  // decelerate if being a blocking follower
570  // (and does not have to change lanes)
571  if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
572  if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
573  return 0;
574  }
575  return (min + wanted) / (SUMOReal) 2.0;
576  }
577  if ((state & LCA_AMBACKBLOCKER) != 0) {
578  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
579  return min;
580  }
581  }
582  if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
583  return min;
584  }
585  // accelerate if being a blocking leader or blocking follower not able to brake
586  // (and does not have to change lanes)
587  if ((state & LCA_AMBLOCKINGLEADER) != 0) {
588  return (max + wanted) / (SUMOReal) 2.0;
589  }
590  if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
591  if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
592  return wanted;
593  }
594  return (min + wanted) / (SUMOReal) 2.0;
595  }
596  return wanted;
597 }
598 
599 
600 void*
601 MSLCM_DK2004::inform(void* info, MSVehicle* /*sender*/) {
602  Info* pinfo = (Info*) info;
603  myOwnState &= 0xffffffff;
604  myOwnState |= pinfo->second;
605  delete pinfo;
606  return (void*) true;
607 }
608 
609 
610 void
613  myOwnState = 0;
615  myLeftSpace = 0;
616  myVSafes.clear();
617  myDontBrake = false;
618 }
619 
620 
621 void
623  int& blocked,
624  int dir,
625  const std::pair<MSVehicle*, SUMOReal>& neighLead,
626  const std::pair<MSVehicle*, SUMOReal>& neighFollow) {
627  if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
628  assert(neighFollow.first != 0);
629  MSVehicle* nv = neighFollow.first;
630  SUMOReal decelGap =
631  neighFollow.second
633  - MAX2(nv->getSpeed() - (SUMOReal) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (SUMOReal) 2.0, (SUMOReal) 0);
634  if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())) {
635  SUMOReal vsafe = myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
636  msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
637  } else {
638  SUMOReal vsafe = neighFollow.second <= 0 ? 0 : myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
640  }
641  }
642  if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
643  if (neighLead.first != 0 && neighLead.second > 0) {
644  msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
645  }
646  }
647 }
648 
649 
650 void
653  myLeftSpace = 0;
654  myVSafes.clear();
655  myDontBrake = false;
656  // truncate myChangeProbability to work around numerical instability between different builds
657  myChangeProbability = ceil(myChangeProbability * 100000.0) * 0.00001;
658 }
659 
660 
661 SUMOReal
663  return myChangeProbability;
664 }
665 
666 
667 /****************************************************************************/
668