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