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