SUMO - Simulation of Urban MObility

MSLCM_DK2004.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00010 // A lane change model developed by D. Krajzewicz between 2004 and 2010
00011 /****************************************************************************/
00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00014 /****************************************************************************/
00015 //
00016 //   This file is part of SUMO.
00017 //   SUMO is free software: you can redistribute it and/or modify
00018 //   it under the terms of the GNU General Public License as published by
00019 //   the Free Software Foundation, either version 3 of the License, or
00020 //   (at your option) any later version.
00021 //
00022 /****************************************************************************/
00023 
00024 
00025 // ===========================================================================
00026 // included modules
00027 // ===========================================================================
00028 #ifdef _MSC_VER
00029 #include <windows_config.h>
00030 #else
00031 #include <config.h>
00032 #endif
00033 
00034 #include "MSLCM_DK2004.h"
00035 #include <utils/common/RandHelper.h>
00036 #include <iostream>
00037 
00038 #ifdef CHECK_MEMORY_LEAKS
00039 #include <foreign/nvwa/debug_new.h>
00040 #endif // CHECK_MEMORY_LEAKS
00041 
00042 //#define DEBUG_VEHICLE_GUI_SELECTION 1
00043 #ifdef DEBUG_VEHICLE_GUI_SELECTION
00044 #include <utils/gui/div/GUIGlobalSelection.h>
00045 #include <guisim/GUIVehicle.h>
00046 #include <guisim/GUILane.h>
00047 #endif
00048 
00049 
00050 
00051 // ===========================================================================
00052 // variable definitions
00053 // ===========================================================================
00054 // 80km/h will be the threshold for dividing between long/short foresight
00055 #define LOOK_FORWARD_SPEED_DIVIDER 14.
00056 
00057 #define LOOK_FORWARD_FAR  15.
00058 #define LOOK_FORWARD_NEAR 5.
00059 
00060 
00061 
00062 #define JAM_FACTOR 2.
00063 #define JAM_FACTOR2 1.
00064 
00065 
00066 // ===========================================================================
00067 // member method definitions
00068 // ===========================================================================
00069 MSLCM_DK2004::MSLCM_DK2004(MSVehicle& v)
00070     : MSAbstractLaneChangeModel(v),
00071       myChangeProbability(0),
00072       myLeadingBlockerLength(0), myLeftSpace(0) {}
00073 
00074 MSLCM_DK2004::~MSLCM_DK2004() {
00075     changed();
00076 }
00077 
00078 
00079 int
00080 MSLCM_DK2004::wantsChangeToRight(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
00081                                  int blocked,
00082                                  const std::pair<MSVehicle*, SUMOReal> &leader,
00083                                  const std::pair<MSVehicle*, SUMOReal> &neighLead,
00084                                  const std::pair<MSVehicle*, SUMOReal> &neighFollow,
00085                                  const MSLane& neighLane,
00086                                  const std::vector<MSVehicle::LaneQ> &preb,
00087                                  MSVehicle** lastBlocked) {
00088 #ifdef DEBUG_VEHICLE_GUI_SELECTION
00089     if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) {
00090         int bla = 0;
00091     }
00092 #endif
00093     MSVehicle::LaneQ curr, best;
00094     int bestLaneOffset = 0;
00095     SUMOReal currentDist = 0;
00096     SUMOReal neighDist = 0;
00097     SUMOReal neighExtDist = 0;
00098     SUMOReal currExtDist = 0;
00099     int currIdx = 0;
00100     for (int p = 0; p < (int) preb.size(); ++p) {
00101         if (preb[p].lane == myVehicle.getLane()) {
00102             curr = preb[p];
00103             bestLaneOffset = curr.bestLaneOffset;
00104             currentDist = curr.length;
00105             currExtDist = curr.lane->getLength();
00106             neighDist = preb[p - 1].length;
00107             neighExtDist = preb[p - 1].lane->getLength();
00108             best = preb[p + bestLaneOffset];
00109             currIdx = p;
00110         }
00111     }
00112 
00113     // keep information about being a leader/follower
00114     int ret = (myOwnState & 0x00ffff00);
00115 
00116     if (leader.first != 0
00117             &&
00118             (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0
00119             &&
00120             (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
00121 
00122         myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE);
00123         if (myVehicle.getSpeed() > 0.1) {
00124             myOwnState |= LCA_AMBACKBLOCKER;
00125         } else {
00126             ret |= LCA_AMBACKBLOCKER;
00127             myDontBrake = true;
00128         }
00129     }
00130 
00131     // process information about the last blocked vehicle
00132     //  if this vehicle is blocking someone in front, we maybe decelerate to let him in
00133     if ((*lastBlocked) != 0) {
00134         SUMOReal gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLengthWithGap() - myVehicle.getPositionOnLane();
00135         if (gap > 0.1) {
00136             if (myVehicle.getSpeed() < ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) {
00137                 if ((*lastBlocked)->getSpeed() < 0.1) {
00138                     ret |= LCA_AMBACKBLOCKER_STANDING;
00139                 } else {
00140                     ret |= LCA_AMBACKBLOCKER;
00141                 }
00142                 myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (SUMOReal)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
00143                 (*lastBlocked) = 0;
00144             }
00145             return ret;
00146         }
00147     }
00148 
00149     // we try to estimate the distance which is necessary to get on a lane
00150     //  we have to get on in order to keep our route
00151     // we assume we need something that depends on our velocity
00152     // and compare this with the free space on our wished lane
00153     //
00154     // if the free space is somehow less than the space we need, we should
00155     //  definitely try to get to the desired lane
00156     //
00157     // this rule forces our vehicle to change the lane if a lane changing is necessary soon
00158     SUMOReal rv = myVehicle.getSpeed() > LOOK_FORWARD_SPEED_DIVIDER
00159                   ? myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_FAR
00160                   : myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_NEAR;
00161     rv += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.;
00162 
00163     SUMOReal tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (SUMOReal) JAM_FACTOR2;
00164 
00165     if (fabs(best.length - curr.length) > MIN2((SUMOReal) .1, best.lane->getLength()) && bestLaneOffset < 0 && currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, rv)) {
00166         informBlocker(msgPass, blocked, LCA_MRIGHT, neighLead, neighFollow);
00167         if (neighLead.second > 0 && neighLead.second > leader.second) {
00168             myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (SUMOReal) 0.5);
00169         }
00170 
00171         // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, right
00172         //   if there is a leader and he wants to change to left (we want to change to right)
00173         if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_LEFT) != 0) {
00174             // save at least his length in myLeadingBlockerLength
00175             myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
00176             // save the left space
00177             myLeftSpace = currentDist - myVehicle.getPositionOnLane();
00178         }
00179         //
00180 
00181         return ret | LCA_RIGHT | LCA_URGENT;
00182     }
00183 
00184 
00185     // the opposite lane-changing direction should be done than the one examined herein
00186     //  we'll check whether we assume we could change anyhow and get back in time...
00187     //
00188     // this rule prevents the vehicle from moving in opposite direction of the best lane
00189     //  unless the way till the end where the vehicle has to be on the best lane
00190     //  is long enough
00191     SUMOReal maxJam = MAX2(preb[currIdx - 1].occupation, preb[currIdx].occupation);
00192     SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
00193     if (bestLaneOffset >= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset + 2, rv))) {
00194         // ...we will not change the lane if not
00195         return ret;
00196     }
00197 
00198 
00199     // if the current lane is the best and a lane-changing would cause a situation
00200     //  of which we assume we will not be able to return to the lane we have to be on...
00201     //
00202     // this rule prevents the vehicle from leaving the current, best lane when it is
00203     //  close to this lane's end
00204     if (currExtDist > neighExtDist && (neighLeftPlace * 2. < rv/*||currE[currIdx+1].length<currentDist*/)) {
00205         return ret;
00206     }
00207 
00208     // let's also regard the case where the vehicle is driving on a highway...
00209     //  in this case, we do not want to get to the dead-end of an on-ramp
00210     //
00211     // THIS RULE APPLIES ONLY TO CHANGING TO THE RIGHT LANE
00212     if (bestLaneOffset == 0 && preb[currIdx - 1].bestLaneOffset != 0 && myVehicle.getLane()->getMaxSpeed() > 80. / 3.6) {
00213         return ret;
00214     }
00215     // --------
00216 
00217     // -------- make place on current lane if blocking follower
00218     if (amBlockingFollowerPlusNB()
00219             &&
00220             (currentDistAllows(neighDist, bestLaneOffset, rv) || neighDist >= currentDist)) {
00221 
00222         return ret | LCA_RIGHT | LCA_URGENT;
00223     }
00224     // --------
00225 
00226 
00227     // -------- security checks for krauss
00228     //  (vsafe fails when gap<0)
00229     if ((blocked & LCA_BLOCKED) != 0) {
00230         return ret;
00231     }
00232     // --------
00233 
00234     // -------- higher speed
00235     if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { 
00236         return ret;
00237     }
00238     SUMOReal thisLaneVSafe = myVehicle.getLane()->getMaxSpeed();
00239     SUMOReal neighLaneVSafe = neighLane.getMaxSpeed();
00240     if (neighLead.first == 0) {
00241         neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
00242     } else {
00243         // @todo: what if leader is below safe gap?!!!
00244         neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
00245     }
00246     if (leader.first == 0) {
00247         thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
00248     } else {
00249         // @todo: what if leader is below safe gap?!!!
00250         thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
00251     }
00252 
00253     thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
00254     neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
00255     if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) {
00256         // ok, the current lane is faster than the right one...
00257         if (myChangeProbability < 0) {
00258             myChangeProbability /= 2.0;
00259         }
00260     } else {
00261         // ok, the right lane is faster than the current
00262         myChangeProbability -= (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getMaxSpeed()));
00263     }
00264 
00265     // let's recheck the "Rechtsfahrgebot"
00266     SUMOReal vmax = MIN2(myVehicle.getLane()->getMaxSpeed(), myVehicle.getVehicleType().getMaxSpeed());
00267     vmax -= (SUMOReal)(5. / 2.6);
00268     if (neighLaneVSafe >= vmax) {
00269 #ifndef NO_TRACI
00270         /* if there was a request by TraCI for changing to this lane
00271         and holding it, this rule is ignored */
00272         if (myChangeRequest != MSVehicle::REQUEST_HOLD) {
00273 #endif
00274             myChangeProbability -= (SUMOReal)((neighLaneVSafe - vmax) / (vmax));
00275 #ifndef NO_TRACI
00276         }
00277 #endif
00278     }
00279 
00280     if (myChangeProbability < -2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1
00281         return ret | LCA_RIGHT | LCA_SPEEDGAIN;
00282     }
00283     // --------
00284 
00285 #ifndef NO_TRACI
00286     // If there is a request by TraCI, try to change the lane
00287     if (myChangeRequest == MSVehicle::REQUEST_RIGHT) {
00288         return ret | LCA_RIGHT;
00289     }
00290 #endif
00291 
00292     return ret;
00293 }
00294 
00295 
00296 int
00297 MSLCM_DK2004::wantsChangeToLeft(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
00298                                 int blocked,
00299                                 const std::pair<MSVehicle*, SUMOReal> &leader,
00300                                 const std::pair<MSVehicle*, SUMOReal> &neighLead,
00301                                 const std::pair<MSVehicle*, SUMOReal> &neighFollow,
00302                                 const MSLane& neighLane,
00303                                 const std::vector<MSVehicle::LaneQ> &preb,
00304                                 MSVehicle** lastBlocked) {
00305 #ifdef DEBUG_VEHICLE_GUI_SELECTION
00306     if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) {
00307         int bla = 0;
00308     }
00309 #endif
00310     MSVehicle::LaneQ curr, best;
00311     int bestLaneOffset = 0;
00312     SUMOReal currentDist = 0;
00313     SUMOReal neighDist = 0;
00314     SUMOReal neighExtDist = 0;
00315     SUMOReal currExtDist = 0;
00316     int currIdx = 0;
00317     for (int p = 0; p < (int) preb.size(); ++p) {
00318         if (preb[p].lane == myVehicle.getLane()) {
00319             curr = preb[p];
00320             bestLaneOffset = curr.bestLaneOffset;
00321             currentDist = curr.length;
00322             currExtDist = curr.lane->getLength();
00323             neighDist = preb[p + 1].length;
00324             neighExtDist = preb[p + 1].lane->getLength();
00325             best = preb[p + bestLaneOffset];
00326             currIdx = p;
00327         }
00328     }
00329     // keep information about being a leader/follower
00330     int ret = (myOwnState & 0x00ffff00);
00331 
00332     // ?!!!
00333     if (leader.first != 0
00334             &&
00335             (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0
00336             &&
00337             (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
00338 
00339         myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE);
00340         if (myVehicle.getSpeed() > 0.1) {
00341             myOwnState |= LCA_AMBACKBLOCKER;
00342         } else {
00343             ret |= LCA_AMBACKBLOCKER;
00344             myDontBrake = true;
00345         }
00346     }
00347 
00348     // process information about the last blocked vehicle
00349     //  if this vehicle is blocking someone in front, we maybe decelerate to let him in
00350     if ((*lastBlocked) != 0) {
00351         SUMOReal gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLengthWithGap() - myVehicle.getPositionOnLane();
00352         if (gap > 0.1) {
00353             if (myVehicle.getSpeed() < ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) {
00354                 if ((*lastBlocked)->getSpeed() < 0.1) {
00355                     ret |= LCA_AMBACKBLOCKER_STANDING;
00356                 } else {
00357                     ret |= LCA_AMBACKBLOCKER;
00358                 }
00359                 myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (SUMOReal)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
00360                 (*lastBlocked) = 0;
00361             }
00362             return ret;
00363         }
00364     }
00365 
00366     // we try to estimate the distance which is necessary to get on a lane
00367     //  we have to get on in order to keep our route
00368     // we assume we need something that depends on our velocity
00369     // and compare this with the free space on our wished lane
00370     //
00371     // if the free space is somehow less than the space we need, we should
00372     //  definitely try to get to the desired lane
00373     //
00374     // this rule forces our vehicle to change the lane if a lane changing is necessary soon
00375     SUMOReal lv = myVehicle.getSpeed() > LOOK_FORWARD_SPEED_DIVIDER
00376                   ? myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_FAR
00377                   : myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_NEAR;
00378     lv += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.;
00379 
00380 
00381     SUMOReal tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (SUMOReal) JAM_FACTOR2;
00382     if (fabs(best.length - curr.length) > MIN2((SUMOReal) .1, best.lane->getLength()) && bestLaneOffset > 0
00383             &&
00384             currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, lv)) {
00385         informBlocker(msgPass, blocked, LCA_MLEFT, neighLead, neighFollow);
00386         if (neighLead.second > 0 && neighLead.second > leader.second) {
00387             myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (SUMOReal) 0.5);
00388         }
00389 
00390         // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, left
00391         //   if there is a leader and he wants to change to right (we want to change to left)
00392         if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_RIGHT) != 0) {
00393             // save at least his length in myLeadingBlockerLength
00394             myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
00395             // save the left space
00396             myLeftSpace = currentDist - myVehicle.getPositionOnLane();
00397         }
00398         //
00399 
00400         return ret | LCA_LEFT | LCA_URGENT;
00401     }
00402 
00403     // the opposite lane-changing direction should be rather done, not
00404     //  the one examined herein
00405     //  we'll check whether we assume we could change anyhow and get back in time...
00406     //
00407     // this rule prevents the vehicle from moving in opposite direction of the best lane
00408     //  unless the way till the end where the vehicle has to be on the best lane
00409     //  is long enough
00410     SUMOReal maxJam = MAX2(preb[currIdx + 1].occupation, preb[currIdx].occupation);
00411     SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
00412     if (bestLaneOffset <= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset - 2, lv))) {
00413         // ...we will not change the lane if not
00414         return ret;
00415     }
00416 
00417 
00418     // if the current lane is the best and a lane-changing would cause a situation
00419     //  of which we assume we will not be able to return to the lane we have to be on...
00420     //
00421     // this rule prevents the vehicle from leaving the current, best lane when it is
00422     //  close to this lane's end
00423     if (currExtDist > neighExtDist && (neighLeftPlace * 2. < lv/*||currE[currIdx+1].length<currentDist*/)) {
00424         // ... let's not change the lane
00425         return ret;
00426     }
00427 
00428     /*
00429     // let's also regard the case where the vehicle is driving on a highway...
00430     //  in this case, we do not want to get to the dead-end of an on-ramp
00431     if(bestLaneOffset==0&&myVehicle.getLane().getMaxSpeed()>80./3.6) {
00432         return ret;
00433     }
00434     */
00435 
00436 
00437     /*
00438     // if the current lane is the
00439     if(bestLaneOffset==0&&(neighDist==0||curr.seenVehicles2*JAM_FACTOR>=neighExtDist-curr.length)) {
00440         return ret;
00441     }
00442     */
00443     // --------
00444 
00445     // -------- make place on current lane if blocking follower
00446     if (amBlockingFollowerPlusNB()
00447             &&
00448             (currentDistAllows(neighDist, bestLaneOffset, lv) || neighDist >= currentDist)) {
00449 
00450         return ret | LCA_LEFT | LCA_URGENT;
00451     }
00452     // --------
00453 
00454     // -------- security checks for krauss
00455     //  (vsafe fails when gap<0)
00456     if ((blocked & LCA_BLOCKED) != 0) {
00457         return ret;
00458     }
00459 
00460     // -------- higher speed
00461     if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { 
00462         return ret;
00463     }
00464     SUMOReal neighLaneVSafe = neighLane.getMaxSpeed();
00465     SUMOReal thisLaneVSafe = myVehicle.getLane()->getMaxSpeed();
00466     if (neighLead.first == 0) {
00467         neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); // !!! warum nicht die Folgesgeschw.?
00468     } else {
00469         // @todo: what if leader is below safe gap?!!!
00470         neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
00471     }
00472     if (leader.first == 0) {
00473         thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
00474     } else {
00475         // @todo: what if leader is below safe gap?!!!
00476         thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
00477     }
00478     thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
00479     neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed());
00480     if (thisLaneVSafe > neighLaneVSafe) {
00481         // this lane is better
00482         if (myChangeProbability > 0) {
00483             myChangeProbability /= 2.0;
00484         }
00485     } else {
00486         // right lane is better
00487         myChangeProbability += (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getMaxSpeed())); // !!! Fahrzeuggeschw.!
00488     }
00489     if (myChangeProbability > .2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1
00490         return ret | LCA_LEFT | LCA_SPEEDGAIN | LCA_URGENT;
00491     }
00492     // --------
00493 
00494 #ifndef NO_TRACI
00495     // If there is a request by TraCI, try to change the lane
00496     if (myChangeRequest == MSVehicle::REQUEST_LEFT) {
00497         return ret | LCA_LEFT;
00498     }
00499 #endif
00500 
00501     return ret;
00502 }
00503 
00504 
00505 SUMOReal
00506 MSLCM_DK2004::patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) {
00507 #ifdef DEBUG_VEHICLE_GUI_SELECTION
00508     if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) {
00509         int bla = 0;
00510     }
00511 #endif
00512     int state = myOwnState;
00513     myOwnState = 0;
00514 
00515     // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
00516     SUMOReal MAGIC_offset = 1.;
00517     //   if we want to change and have a blocking leader and there is enough room for him in front of us
00518     if (myLeadingBlockerLength != 0) {
00519         SUMOReal space = myLeftSpace - myLeadingBlockerLength - MAGIC_offset;
00520         if (space > 0) {
00521             // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
00522             SUMOReal safe = cfModel.stopSpeed(&myVehicle, space);
00523             // if we are approaching this place
00524             if (safe < wanted) {
00525                 // return this speed as the speed to use
00526                 return MAX2(min, safe);
00527             }
00528         }
00529     }
00530 
00531     // just to make sure to be notified about lane chaning end
00532     if (myVehicle.getLane()->getEdge().getLanes().size() == 1) {
00533         // remove chaning information if on a road with a single lane
00534         changed();
00535         return wanted;
00536     }
00537 
00538     SUMOReal nVSafe = wanted;
00539     bool gotOne = false;
00540     for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
00541         SUMOReal v = (*i);
00542         if (v >= min && v <= max) {
00543             nVSafe = MIN2(v, nVSafe);
00544             gotOne = true;
00545         }
00546     }
00547 
00548     // check whether the vehicle is blocked
00549     if ((state & LCA_WANTS_LANECHANGE) != 0) {
00550         if (gotOne && !myDontBrake) {
00551             return nVSafe;
00552         }
00553         // check whether the vehicle maybe has to be swapped with one of
00554         //  the blocking vehicles
00555         if ((state & LCA_BLOCKED) != 0) {
00556             if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
00557                 // if interacting with leader and not too slow
00558                 return (min + wanted) / (SUMOReal) 2.0;
00559             }
00560             if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
00561                 return (max + wanted) / (SUMOReal) 2.0;
00562             }
00563             return (min + wanted) / (SUMOReal) 2.0;
00564         }
00565     }
00566 
00567 
00568     // decelerate if being a blocking follower
00569     //  (and does not have to change lanes)
00570     if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
00571         if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed())) < 0.001 && min == 0) { // !!! was standing
00572             return 0;
00573         }
00574         return (min + wanted) / (SUMOReal) 2.0;
00575     }
00576     if ((state & LCA_AMBACKBLOCKER) != 0) {
00577         if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed()) && min == 0) { // !!! was standing
00578             return min;
00579         }
00580     }
00581     if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
00582         return min;
00583     }
00584     // accelerate if being a blocking leader or blocking follower not able to brake
00585     //  (and does not have to change lanes)
00586     if ((state & LCA_AMBLOCKINGLEADER) != 0) {
00587         return (max + wanted) / (SUMOReal) 2.0;
00588     }
00589     if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
00590         if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed()) && min == 0) { // !!! was standing
00591             return wanted;
00592         }
00593         return (min + wanted) / (SUMOReal) 2.0;
00594     }
00595     return wanted;
00596 }
00597 
00598 
00599 void*
00600 MSLCM_DK2004::inform(void* info, MSVehicle* /*sender*/) {
00601     Info* pinfo = (Info*) info;
00602     myOwnState &= 0xffffffff;
00603     myOwnState |= pinfo->second;
00604     delete pinfo;
00605     return (void*) true;
00606 }
00607 
00608 
00609 void
00610 MSLCM_DK2004::changed() {
00611     myChangeProbability = 0;
00612     myOwnState = 0;
00613     myLeadingBlockerLength = 0;
00614     myLeftSpace = 0;
00615     myVSafes.clear();
00616     myDontBrake = false;
00617 }
00618 
00619 
00620 void
00621 MSLCM_DK2004::informBlocker(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
00622                             int& blocked,
00623                             int dir,
00624                             const std::pair<MSVehicle*, SUMOReal> &neighLead,
00625                             const std::pair<MSVehicle*, SUMOReal> &neighFollow) {
00626     if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
00627         assert(neighFollow.first != 0);
00628         MSVehicle* nv = neighFollow.first;
00629         SUMOReal decelGap =
00630             neighFollow.second
00631             + SPEED2DIST(myVehicle.getSpeed()) * (SUMOReal) 2.0
00632             - MAX2(nv->getSpeed() - (SUMOReal) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (SUMOReal) 2.0, (SUMOReal) 0);
00633         if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())) {
00634             SUMOReal vsafe = myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
00635             msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
00636         } else {
00637             SUMOReal vsafe = neighFollow.second <= 0 ? 0 : myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
00638             msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER_DONTBRAKE), &myVehicle);
00639         }
00640     }
00641     if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
00642         if (neighLead.first != 0 && neighLead.second > 0) {
00643             msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
00644         }
00645     }
00646 }
00647 
00648 
00649 void
00650 MSLCM_DK2004::prepareStep() {
00651     myLeadingBlockerLength = 0;
00652     myLeftSpace = 0;
00653     myVSafes.clear();
00654     myDontBrake = false;
00655 }
00656 
00657 
00658 SUMOReal
00659 MSLCM_DK2004::getProb() const {
00660     return myChangeProbability;
00661 }
00662 
00663 
00664 /****************************************************************************/
00665 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines