SUMO - Simulation of Urban MObility

MSLCM_DK2004.cpp

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