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