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