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 
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:442
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
SUMOReal getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
MSLCM_DK2004(MSVehicle &v)
#define LOOK_FORWARD_NEAR
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
#define min(a, b)
Definition: polyfonts.c:62
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:513
a vehicles
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:167
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:446
virtual SUMOReal followSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const =0
Computes the vehicle&#39;s safe speed (no dawdling)
SUMOReal getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:360
virtual SUMOReal maxNextSpeed(SUMOReal speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:86
The car-following model abstraction.
Definition: MSCFModel.h:58
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
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)
Called to examine whether the vehicle wants to change to right This method gets the information about...
T MAX2(T a, T b)
Definition: StdDefs.h:63
bool isSelected(GUIGlObjectType type, GUIGlID id)
Returns the information whether the object with the given type and id is selected.
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:227
SUMOReal getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:284
#define JAM_FACTOR2
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)
Called to examine whether the vehicle wants to change to left This method gets the information about ...
SUMOReal length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:440
The action is due to the wish to follow the route (navigational lc)
SUMOReal myChangeProbability
Definition: MSLCM_DK2004.h:147
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:438
#define max(a, b)
Definition: polyfonts.c:61
void informBlocker(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int &blocked, int dir, const std::pair< MSVehicle *, SUMOReal > &neighLead, const std::pair< MSVehicle *, SUMOReal > &neighFollow)
#define ACCEL2DIST(x)
Definition: SUMOTime.h:59
vehicle want&#39;s to change to right lane
Definition: MSVehicle.h:131
#define LOOK_FORWARD_FAR
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
SUMOReal myLeftSpace
Definition: MSLCM_DK2004.h:150
virtual void changed()
SUMOReal getProb() const
virtual void * inform(void *info, MSVehicle *sender)
bool currentDistDisallows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_DK2004.h:135
T MIN2(T a, T b)
Definition: StdDefs.h:57
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) ...
A structure representing the best lanes for continuing the route.
Definition: MSVehicle.h:436
virtual ~MSLCM_DK2004()
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:165
int myOwnState
The current state of the vehicle.
Wants go to the right.
#define LOOK_FORWARD_SPEED_DIVIDER
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.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
vehicle want&#39;s to change to left lane
Definition: MSVehicle.h:129
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
SUMOTime myLastLaneChangeOffset
information how long ago the vehicle has performed a lane-change
SUMOReal occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:442
std::pair< SUMOReal, int > Info
Definition: MSLCM_DK2004.h:142
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
Definition: MSBaseVehicle.h:94
const SUMOReal SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:49
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:292
virtual void prepareStep()
vehicle want&#39;s to keep the current lane
Definition: MSVehicle.h:133
#define SUMOReal
Definition: config.h:221
bool amBlockingFollowerPlusNB()
Definition: MSLCM_DK2004.h:132
std::vector< SUMOReal > myVSafes
Definition: MSLCM_DK2004.h:152
SUMOReal myLeadingBlockerLength
Definition: MSLCM_DK2004.h:149
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:344
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:323
bool currentDistAllows(SUMOReal dist, int laneOffset, SUMOReal lookForwardDist)
Definition: MSLCM_DK2004.h:138
GUISelectedStorage gSelected
A global holder of selected objects.
Representation of a lane in the micro simulation.
Definition: MSLane.h:73
const MSCFModel & myCarFollowModel
The vehicle&#39;s car following model.
Interface for lane-change models.
virtual bool congested(const MSVehicle *const neighLeader)
The action is due to the wish to be faster (tactical lc)
MSVehicle::ChangeRequest myChangeRequest