LCOV - code coverage report
Current view: top level - src/microsim/lcmodels - MSLCM_DK2008.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 115 233 49.4 %
Date: 2024-09-16 15:39:55 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2005-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    MSLCM_DK2008.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Friedemann Wesner
      17             : /// @author  Sascha Krieg
      18             : /// @author  Michael Behrisch
      19             : /// @author  Jakob Erdmann
      20             : /// @date    Tue, 29.05.2005
      21             : ///
      22             : // A lane change model developed by D. Krajzewicz between 2004 and 2010
      23             : /****************************************************************************/
      24             : #include <config.h>
      25             : 
      26             : #include <iostream>
      27             : #include <utils/common/RandHelper.h>
      28             : #include <microsim/MSEdge.h>
      29             : #include <microsim/MSLane.h>
      30             : #include <microsim/MSLink.h>
      31             : #include <microsim/MSNet.h>
      32             : #include "MSLCM_DK2008.h"
      33             : 
      34             : // ===========================================================================
      35             : // variable definitions
      36             : // ===========================================================================
      37             : // 80km/h will be the threshold for dividing between long/short foresight
      38             : #define LOOK_FORWARD_SPEED_DIVIDER 14.
      39             : 
      40             : #define LOOK_FORWARD_FAR  15.
      41             : #define LOOK_FORWARD_NEAR 5.
      42             : 
      43             : 
      44             : 
      45             : #define JAM_FACTOR 2.
      46             : #define JAM_FACTOR2 1.
      47             : 
      48             : 
      49             : // ===========================================================================
      50             : // member method definitions
      51             : // ===========================================================================
      52           8 : MSLCM_DK2008::MSLCM_DK2008(MSVehicle& v)
      53             :     : MSAbstractLaneChangeModel(v, LaneChangeModel::DK2008),
      54           8 :       myChangeProbability(0),
      55           8 :       myLeadingBlockerLength(0), myLeftSpace(0) {}
      56             : 
      57          16 : MSLCM_DK2008::~MSLCM_DK2008() {
      58           8 :     changed();
      59          16 : }
      60             : 
      61             : int
      62         167 : MSLCM_DK2008::wantsChange(
      63             :     int laneOffset,
      64             :     MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
      65             :     const std::pair<MSVehicle*, double>& leader,
      66             :     const std::pair<MSVehicle*, double>& /*follower*/,
      67             :     const std::pair<MSVehicle*, double>& neighLead,
      68             :     const std::pair<MSVehicle*, double>& neighFollow,
      69             :     const MSLane& neighLane,
      70             :     const std::vector<MSVehicle::LaneQ>& preb,
      71             :     MSVehicle** lastBlocked,
      72             :     MSVehicle** firstBlocked) {
      73             :     UNUSED_PARAMETER(firstBlocked);
      74         167 :     return (laneOffset == -1 ?
      75          27 :             wantsChangeToRight(msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked)
      76         140 :             : wantsChangeToLeft(msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked));
      77             : 
      78             : }
      79             : 
      80             : 
      81             : int
      82          27 : MSLCM_DK2008::wantsChangeToRight(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
      83             :                                  int blocked,
      84             :                                  const std::pair<MSVehicle*, double>& leader,
      85             :                                  const std::pair<MSVehicle*, double>& neighLead,
      86             :                                  const std::pair<MSVehicle*, double>& neighFollow,
      87             :                                  const MSLane& neighLane,
      88             :                                  const std::vector<MSVehicle::LaneQ>& preb,
      89             :                                  MSVehicle** lastBlocked,
      90             :                                  MSVehicle** firstBlocked) {
      91             :     UNUSED_PARAMETER(firstBlocked);
      92             :     MSVehicle::LaneQ curr, best;
      93             :     int bestLaneOffset = 0;
      94             :     double currentDist = 0;
      95             :     double neighDist = 0;
      96             :     double neighExtDist = 0;
      97             :     double currExtDist = 0;
      98             :     int currIdx = 0;
      99          27 :     const MSLane* prebLane = myVehicle.getLane();
     100          27 :     if (prebLane->getEdge().isInternal()) {
     101             :         // internal edges are not kept inside the bestLanes structure
     102           0 :         prebLane = prebLane->getLinkCont()[0]->getLane();
     103             :     }
     104          54 :     for (int p = 0; p < (int) preb.size(); ++p) {
     105          54 :         if (preb[p].lane == prebLane && p > 0) {
     106             :             curr = preb[p];
     107          27 :             bestLaneOffset = curr.bestLaneOffset;
     108          27 :             currentDist = curr.length;
     109          27 :             currExtDist = curr.lane->getLength();
     110          27 :             neighDist = preb[p - 1].length;
     111          27 :             neighExtDist = preb[p - 1].lane->getLength();
     112          27 :             best = preb[p + bestLaneOffset];
     113             :             currIdx = p;
     114             :             break;
     115             :         }
     116             :     }
     117             : 
     118             :     // keep information about being a leader/follower
     119          27 :     int ret = (myOwnState & 0xffff0000);
     120             : 
     121          27 :     if (leader.first != 0
     122           0 :             &&
     123           0 :             (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0
     124          27 :             &&
     125           0 :             (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
     126             : 
     127           0 :         myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE);
     128           0 :         if (myVehicle.getSpeed() > SUMO_const_haltingSpeed) {
     129           0 :             myOwnState |= LCA_AMBACKBLOCKER;
     130             :         } else {
     131           0 :             ret |= LCA_AMBACKBLOCKER;
     132           0 :             myDontBrake = true;
     133             :         }
     134             :     }
     135             : 
     136             :     // process information about the last blocked vehicle
     137             :     //  if this vehicle is blocking someone in front, we maybe decelerate to let him in
     138          27 :     if ((*lastBlocked) != nullptr) {
     139           0 :         double gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
     140           0 :         if (gap > 0.1) {
     141           0 :             if (myVehicle.getSpeed() < ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) {
     142           0 :                 if ((*lastBlocked)->getSpeed() < SUMO_const_haltingSpeed) {
     143           0 :                     ret |= LCA_AMBACKBLOCKER_STANDING;
     144             :                 } else {
     145           0 :                     ret |= LCA_AMBACKBLOCKER;
     146             :                 }
     147           0 :                 myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), (double)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
     148           0 :                 (*lastBlocked) = nullptr;
     149             :             }
     150           0 :             return ret;
     151             :         }
     152             :     }
     153             : 
     154             :     // we try to estimate the distance which is necessary to get on a lane
     155             :     //  we have to get on in order to keep our route
     156             :     // we assume we need something that depends on our velocity
     157             :     // and compare this with the free space on our wished lane
     158             :     //
     159             :     // if the free space is somehow less than the space we need, we should
     160             :     //  definitely try to get to the desired lane
     161             :     //
     162             :     // this rule forces our vehicle to change the lane if a lane changing is necessary soon
     163          27 :     double rv = myVehicle.getSpeed() > LOOK_FORWARD_SPEED_DIVIDER
     164          54 :                 ? myVehicle.getSpeed() * (double) LOOK_FORWARD_FAR
     165          27 :                 : myVehicle.getSpeed() * (double) LOOK_FORWARD_NEAR;
     166          27 :     rv += myVehicle.getVehicleType().getLengthWithGap() * (double) 2.;
     167             : 
     168          27 :     double tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (double) JAM_FACTOR2;
     169             : 
     170             :     // assert(best.length > curr.length);
     171             :     // XXX if (curr.length != best.length) && ...
     172          27 :     if (fabs(best.length - curr.length) > MIN2((double) .1, best.lane->getLength()) && bestLaneOffset < 0 && currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, rv)) {
     173           0 :         informBlocker(msgPass, blocked, LCA_MRIGHT, neighLead, neighFollow);
     174           0 :         if (neighLead.second > 0 && neighLead.second > leader.second) {
     175           0 :             myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (double) 0.5);
     176             :         }
     177             : 
     178             :         // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, right
     179             :         //   if there is a leader and he wants to change to left (we want to change to right)
     180           0 :         if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_LEFT) != 0) {
     181             :             // save at least his length in myLeadingBlockerLength
     182           0 :             myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
     183             :             // save the left space
     184           0 :             myLeftSpace = currentDist - myVehicle.getPositionOnLane();
     185             :         }
     186             :         //
     187             : 
     188           0 :         return ret | LCA_RIGHT | LCA_STRATEGIC | LCA_URGENT;
     189             :     }
     190             : 
     191             : 
     192             :     // the opposite lane-changing direction should be done than the one examined herein
     193             :     //  we'll check whether we assume we could change anyhow and get back in time...
     194             :     //
     195             :     // this rule prevents the vehicle from moving in opposite direction of the best lane
     196             :     //  unless the way till the end where the vehicle has to be on the best lane
     197             :     //  is long enough
     198          27 :     double maxJam = MAX2(preb[currIdx - 1].occupation, preb[currIdx].occupation);
     199          27 :     double neighLeftPlace = MAX2((double) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
     200          27 :     if (bestLaneOffset >= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset + 2, rv))) {
     201             :         // ...we will not change the lane if not
     202          27 :         return ret | LCA_STAY | LCA_STRATEGIC;
     203             :     }
     204             : 
     205             : 
     206             :     // if the current lane is the best and a lane-changing would cause a situation
     207             :     //  of which we assume we will not be able to return to the lane we have to be on...
     208             :     //
     209             :     // this rule prevents the vehicle from leaving the current, best lane when it is
     210             :     //  close to this lane's end
     211           0 :     if (currExtDist > neighExtDist && (neighLeftPlace * 2. < rv/*||currE[currIdx+1].length<currentDist*/)) {
     212           0 :         return ret | LCA_STAY | LCA_STRATEGIC;
     213             :     }
     214             : 
     215             :     // let's also regard the case where the vehicle is driving on a highway...
     216             :     //  in this case, we do not want to get to the dead-end of an on-ramp
     217             :     //
     218             :     // THIS RULE APPLIES ONLY TO CHANGING TO THE RIGHT LANE
     219           0 :     if (bestLaneOffset == 0 && preb[currIdx - 1].bestLaneOffset != 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6) {
     220           0 :         return ret | LCA_STAY | LCA_STRATEGIC;
     221             :     }
     222             :     // --------
     223             : 
     224             :     // -------- make place on current lane if blocking follower
     225             :     if (amBlockingFollowerPlusNB()
     226           0 :             &&
     227           0 :             (currentDistAllows(neighDist, bestLaneOffset, rv) || neighDist >= currentDist)) {
     228             : 
     229           0 :         return ret | LCA_RIGHT | LCA_COOPERATIVE | LCA_URGENT;
     230             :     }
     231             :     // --------
     232             : 
     233             : 
     234             :     // -------- security checks for krauss
     235             :     //  (vsafe fails when gap<0)
     236           0 :     if ((blocked & LCA_BLOCKED) != 0) {
     237             :         return ret;
     238             :     }
     239             :     // --------
     240             : 
     241             :     // -------- higher speed
     242           0 :     if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader)) { //!!!
     243           0 :         return ret;
     244             :     }
     245           0 :     double thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
     246           0 :     double neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
     247           0 :     if (neighLead.first == 0) {
     248           0 :         neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
     249             :     } else {
     250             :         // @todo: what if leader is below safe gap?!!!
     251           0 :         neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
     252             :     }
     253           0 :     if (leader.first == 0) {
     254           0 :         thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
     255             :     } else {
     256             :         // @todo: what if leader is below safe gap?!!!
     257           0 :         thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
     258             :     }
     259             : 
     260           0 :     thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getMaxSpeed());
     261           0 :     neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getMaxSpeed());
     262           0 :     if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) {
     263             :         // ok, the current lane is faster than the right one...
     264           0 :         if (myChangeProbability < 0) {
     265           0 :             myChangeProbability *= pow(0.5, TS);
     266             :         }
     267             :     } else {
     268             :         // ok, the right lane is faster than the current
     269           0 :         myChangeProbability -= TS * ((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)));
     270             :     }
     271             : 
     272             :     // let's recheck the "Rechtsfahrgebot"
     273           0 :     double vmax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
     274           0 :     vmax -= (double)(5. / 2.6);
     275           0 :     if (neighLaneVSafe >= vmax) {
     276           0 :         myChangeProbability -= TS * ((neighLaneVSafe - vmax) / (vmax));
     277             :     }
     278             : 
     279           0 :     if (myChangeProbability < -2 && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((double) .1, myVehicle.getSpeed())) { // -.1
     280           0 :         return ret | LCA_RIGHT | LCA_SPEEDGAIN;
     281             :     }
     282             :     // --------
     283             : 
     284             :     return ret;
     285             : }
     286             : 
     287             : 
     288             : int
     289         140 : MSLCM_DK2008::wantsChangeToLeft(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
     290             :                                 int blocked,
     291             :                                 const std::pair<MSVehicle*, double>& leader,
     292             :                                 const std::pair<MSVehicle*, double>& neighLead,
     293             :                                 const std::pair<MSVehicle*, double>& neighFollow,
     294             :                                 const MSLane& neighLane,
     295             :                                 const std::vector<MSVehicle::LaneQ>& preb,
     296             :                                 MSVehicle** lastBlocked,
     297             :                                 MSVehicle** firstBlocked) {
     298             :     UNUSED_PARAMETER(firstBlocked);
     299             :     MSVehicle::LaneQ curr, best;
     300             :     int bestLaneOffset = 0;
     301             :     double currentDist = 0;
     302             :     double neighDist = 0;
     303             :     double neighExtDist = 0;
     304             :     double currExtDist = 0;
     305             :     int currIdx = 0;
     306         140 :     const MSLane* prebLane = myVehicle.getLane();
     307         140 :     if (prebLane->getEdge().isInternal()) {
     308             :         // internal edges are not kept inside the bestLanes structure
     309           0 :         prebLane = prebLane->getLinkCont()[0]->getLane();
     310             :     }
     311         167 :     for (int p = 0; p < (int) preb.size(); ++p) {
     312         167 :         if (preb[p].lane == prebLane) {
     313             :             curr = preb[p];
     314         140 :             bestLaneOffset = curr.bestLaneOffset;
     315         140 :             currentDist = curr.length;
     316         140 :             currExtDist = curr.lane->getLength();
     317         140 :             neighDist = preb[p + 1].length;
     318         140 :             neighExtDist = preb[p + 1].lane->getLength();
     319         140 :             best = preb[p + bestLaneOffset];
     320             :             currIdx = p;
     321             :             break;
     322             :         }
     323             :     }
     324             :     // keep information about being a leader/follower
     325         140 :     int ret = (myOwnState & 0xffff0000);
     326             : 
     327             :     // ?!!!
     328         140 :     if (leader.first != 0
     329           0 :             &&
     330           0 :             (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0
     331         140 :             &&
     332           0 :             (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
     333             : 
     334           0 :         myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE);
     335           0 :         if (myVehicle.getSpeed() > SUMO_const_haltingSpeed) {
     336           0 :             myOwnState |= LCA_AMBACKBLOCKER;
     337             :         } else {
     338           0 :             ret |= LCA_AMBACKBLOCKER;
     339           0 :             myDontBrake = true;
     340             :         }
     341             :     }
     342             : 
     343             :     // process information about the last blocked vehicle
     344             :     //  if this vehicle is blocking someone in front, we maybe decelerate to let him in
     345         140 :     if ((*lastBlocked) != nullptr) {
     346           0 :         double gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
     347           0 :         if (gap > 0.1) {
     348           0 :             if (myVehicle.getSpeed() < ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) {
     349           0 :                 if ((*lastBlocked)->getSpeed() < SUMO_const_haltingSpeed) {
     350           0 :                     ret |= LCA_AMBACKBLOCKER_STANDING;
     351             :                 } else {
     352           0 :                     ret |= LCA_AMBACKBLOCKER;
     353             :                 }
     354           0 :                 myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), (double)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
     355           0 :                 (*lastBlocked) = nullptr;
     356             :             }
     357           0 :             return ret;
     358             :         }
     359             :     }
     360             : 
     361             :     // we try to estimate the distance which is necessary to get on a lane
     362             :     //  we have to get on in order to keep our route
     363             :     // we assume we need something that depends on our velocity
     364             :     // and compare this with the free space on our wished lane
     365             :     //
     366             :     // if the free space is somehow less than the space we need, we should
     367             :     //  definitely try to get to the desired lane
     368             :     //
     369             :     // this rule forces our vehicle to change the lane if a lane changing is necessary soon
     370         140 :     double lv = myVehicle.getSpeed() > LOOK_FORWARD_SPEED_DIVIDER
     371         280 :                 ? myVehicle.getSpeed() * (double) LOOK_FORWARD_FAR
     372         140 :                 : myVehicle.getSpeed() * (double) LOOK_FORWARD_NEAR;
     373         140 :     lv += myVehicle.getVehicleType().getLengthWithGap() * (double) 2.;
     374             : 
     375             : 
     376         140 :     double tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (double) JAM_FACTOR2;
     377         253 :     if (fabs(best.length - curr.length) > MIN2((double) .1, best.lane->getLength()) && bestLaneOffset > 0
     378         253 :             &&
     379             :             currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, lv)) {
     380           4 :         informBlocker(msgPass, blocked, LCA_MLEFT, neighLead, neighFollow);
     381           4 :         if (neighLead.second > 0 && neighLead.second > leader.second) {
     382           0 :             myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (double) 0.5);
     383             :         }
     384             : 
     385             :         // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, left
     386             :         //   if there is a leader and he wants to change to right (we want to change to left)
     387           4 :         if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_RIGHT) != 0) {
     388             :             // save at least his length in myLeadingBlockerLength
     389           0 :             myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
     390             :             // save the left space
     391           0 :             myLeftSpace = currentDist - myVehicle.getPositionOnLane();
     392             :         }
     393             :         //
     394             : 
     395           4 :         return ret | LCA_LEFT | LCA_STRATEGIC | LCA_URGENT;
     396             :     }
     397             : 
     398             :     // the opposite lane-changing direction should be rather done, not
     399             :     //  the one examined herein
     400             :     //  we'll check whether we assume we could change anyhow and get back in time...
     401             :     //
     402             :     // this rule prevents the vehicle from moving in opposite direction of the best lane
     403             :     //  unless the way till the end where the vehicle has to be on the best lane
     404             :     //  is long enough
     405         136 :     double maxJam = MAX2(preb[currIdx + 1].occupation, preb[currIdx].occupation);
     406         136 :     double neighLeftPlace = MAX2((double) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
     407         136 :     if (bestLaneOffset <= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset - 2, lv))) {
     408             :         // ...we will not change the lane if not
     409          27 :         return ret | LCA_STAY | LCA_STRATEGIC;
     410             :     }
     411             : 
     412             : 
     413             :     // if the current lane is the best and a lane-changing would cause a situation
     414             :     //  of which we assume we will not be able to return to the lane we have to be on...
     415             :     //
     416             :     // this rule prevents the vehicle from leaving the current, best lane when it is
     417             :     //  close to this lane's end
     418         109 :     if (currExtDist > neighExtDist && (neighLeftPlace * 2. < lv/*||currE[currIdx+1].length<currentDist*/)) {
     419             :         // ... let's not change the lane
     420           0 :         return ret | LCA_STAY | LCA_STRATEGIC;
     421             :     }
     422             : 
     423             :     /*
     424             :     // let's also regard the case where the vehicle is driving on a highway...
     425             :     //  in this case, we do not want to get to the dead-end of an on-ramp
     426             :     if(bestLaneOffset==0&&myVehicle.getLane().getMaxSpeed()>80./3.6) {
     427             :         return ret;
     428             :     }
     429             :     */
     430             : 
     431             : 
     432             :     /*
     433             :     // if the current lane is the
     434             :     if(bestLaneOffset==0&&(neighDist==0||curr.seenVehicles2*JAM_FACTOR>=neighExtDist-curr.length)) {
     435             :         return ret;
     436             :     }
     437             :     */
     438             :     // --------
     439             : 
     440             :     // -------- make place on current lane if blocking follower
     441             :     if (amBlockingFollowerPlusNB()
     442         109 :             &&
     443           0 :             (currentDistAllows(neighDist, bestLaneOffset, lv) || neighDist >= currentDist)) {
     444             : 
     445           0 :         return ret | LCA_LEFT | LCA_COOPERATIVE | LCA_URGENT;
     446             :     }
     447             :     // --------
     448             : 
     449             :     // -------- security checks for krauss
     450             :     //  (vsafe fails when gap<0)
     451         109 :     if ((blocked & LCA_BLOCKED) != 0) {
     452             :         return ret;
     453             :     }
     454             : 
     455             :     // -------- higher speed
     456         109 :     if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader)) { //!!!
     457           0 :         return ret;
     458             :     }
     459         109 :     double neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
     460         109 :     double thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
     461         109 :     if (neighLead.first == 0) {
     462         109 :         neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); // !!! warum nicht die Folgesgeschw.?
     463             :     } else {
     464             :         // @todo: what if leader is below safe gap?!!!
     465           0 :         neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
     466             :     }
     467         109 :     if (leader.first == 0) {
     468         109 :         thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
     469             :     } else {
     470             :         // @todo: what if leader is below safe gap?!!!
     471           0 :         thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
     472             :     }
     473         109 :     thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getMaxSpeed());
     474         109 :     neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getMaxSpeed());
     475         109 :     if (thisLaneVSafe > neighLaneVSafe) {
     476             :         // this lane is better
     477           0 :         if (myChangeProbability > 0) {
     478           0 :             myChangeProbability *= pow(0.5, TS);
     479             :         }
     480             :     } else {
     481             :         // right lane is better
     482         109 :         myChangeProbability += TS * ((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle))); // !!! Fahrzeuggeschw.!
     483             :     }
     484         109 :     if (myChangeProbability > .2 && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { // .1
     485           0 :         return ret | LCA_LEFT | LCA_SPEEDGAIN | LCA_URGENT;
     486             :     }
     487             :     // --------
     488             : 
     489             :     return ret;
     490             : }
     491             : 
     492             : 
     493             : double
     494         257 : MSLCM_DK2008::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
     495         257 :     int state = myOwnState;
     496             : 
     497             :     // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
     498             :     double MAGIC_offset = 1.;
     499             :     //   if we want to change and have a blocking leader and there is enough room for him in front of us
     500         257 :     if (myLeadingBlockerLength != 0) {
     501           0 :         double space = myLeftSpace - myLeadingBlockerLength - MAGIC_offset - myVehicle.getVehicleType().getMinGap();
     502           0 :         if (space > 0) {
     503             :             // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
     504           0 :             double safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space, MSCFModel::CalcReason::LANE_CHANGE);
     505             :             // if we are approaching this place
     506           0 :             if (safe < wanted) {
     507             :                 // return this speed as the speed to use
     508             :                 return MAX2(min, safe);
     509             :             }
     510             :         }
     511             :     }
     512             : 
     513             :     // just to make sure to be notified about lane chaning end
     514         257 :     if (myVehicle.getLane()->getEdge().getLanes().size() == 1 || myVehicle.getLane()->getEdge().isInternal()) {
     515             :         // remove chaning information if on a road with a single lane
     516          93 :         changed();
     517          93 :         return wanted;
     518             :     }
     519             : 
     520             :     double nVSafe = wanted;
     521             :     bool gotOne = false;
     522         164 :     for (std::vector<double>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
     523           0 :         double v = (*i);
     524           0 :         if (v >= min && v <= max) {
     525             :             nVSafe = MIN2(v, nVSafe);
     526             :             gotOne = true;
     527             :         }
     528             :     }
     529             : 
     530             :     // check whether the vehicle is blocked
     531         164 :     if ((state & LCA_WANTS_LANECHANGE) != 0) {
     532           4 :         if (gotOne && !myDontBrake) {
     533             :             return nVSafe;
     534             :         }
     535             :         // check whether the vehicle maybe has to be swapped with one of
     536             :         //  the blocking vehicles
     537           4 :         if ((state & LCA_BLOCKED) != 0) {
     538           0 :             if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
     539             :                 // if interacting with leader and not too slow
     540           0 :                 return (min + wanted) / (double) 2.0;
     541             :             }
     542           0 :             if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
     543           0 :                 return (max + wanted) / (double) 2.0;
     544             :             }
     545           0 :             return (min + wanted) / (double) 2.0;
     546             :         }
     547             :     }
     548             : 
     549             : 
     550             :     // decelerate if being a blocking follower
     551             :     //  (and does not have to change lanes)
     552         164 :     if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
     553           0 :         if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
     554             :             return 0;
     555             :         }
     556           0 :         return (min + wanted) / (double) 2.0;
     557             :     }
     558         164 :     if ((state & LCA_AMBACKBLOCKER) != 0) {
     559           0 :         if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
     560             :             return min;
     561             :         }
     562             :     }
     563         164 :     if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
     564             :         return min;
     565             :     }
     566             :     // accelerate if being a blocking leader or blocking follower not able to brake
     567             :     //  (and does not have to change lanes)
     568         164 :     if ((state & LCA_AMBLOCKINGLEADER) != 0) {
     569           0 :         return (max + wanted) / (double) 2.0;
     570             :     }
     571         164 :     if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
     572           0 :         if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
     573             :             return wanted;
     574             :         }
     575           0 :         return (min + wanted) / (double) 2.0;
     576             :     }
     577             :     return wanted;
     578             : }
     579             : 
     580             : 
     581             : void*
     582           0 : MSLCM_DK2008::inform(void* info, MSVehicle* /*sender*/) {
     583             :     Info* pinfo = (Info*) info;
     584             :     //myOwnState &= 0xffffffff; // reset all bits of MyLCAEnum but only those
     585           0 :     myOwnState |= pinfo->second;
     586           0 :     delete pinfo;
     587           0 :     return (void*) true;
     588             : }
     589             : 
     590             : 
     591             : void
     592         105 : MSLCM_DK2008::changed() {
     593         105 :     myOwnState = 0;
     594         105 :     myChangeProbability = 0;
     595         105 :     myLeadingBlockerLength = 0;
     596         105 :     myLeftSpace = 0;
     597             :     myVSafes.clear();
     598         105 :     myDontBrake = false;
     599         105 : }
     600             : 
     601             : 
     602             : void
     603           4 : MSLCM_DK2008::informBlocker(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
     604             :                             int& blocked,
     605             :                             int dir,
     606             :                             const std::pair<MSVehicle*, double>& neighLead,
     607             :                             const std::pair<MSVehicle*, double>& neighFollow) {
     608           4 :     if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
     609             :         assert(neighFollow.first != 0);
     610           0 :         MSVehicle* nv = neighFollow.first;
     611             :         double decelGap =
     612           0 :             neighFollow.second
     613           0 :             + SPEED2DIST(myVehicle.getSpeed()) * (double) 2.0
     614           0 :             - MAX2(nv->getSpeed() - (double) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (double) 2.0, (double) 0);
     615           0 :         if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv, &myVehicle,
     616           0 :                 nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())) {
     617           0 :             double vsafe = getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
     618           0 :             msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
     619             :         } else {
     620           0 :             double vsafe = neighFollow.second <= 0 ? 0 : getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
     621           0 :             msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER_DONTBRAKE), &myVehicle);
     622             :         }
     623             :     }
     624           4 :     if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
     625           0 :         if (neighLead.first != 0 && neighLead.second > 0) {
     626           0 :             msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
     627             :         }
     628             :     }
     629           4 : }
     630             : 
     631             : 
     632             : void
     633         249 : MSLCM_DK2008::prepareStep() {
     634         249 :     MSAbstractLaneChangeModel::prepareStep();
     635         249 :     myOwnState = 0;
     636         249 :     myLeadingBlockerLength = 0;
     637         249 :     myLeftSpace = 0;
     638             :     myVSafes.clear();
     639         249 :     myDontBrake = false;
     640             :     // truncate myChangeProbability to work around numerical instability between different builds
     641         249 :     myChangeProbability = ceil(myChangeProbability * 100000.0) * 0.00001;
     642         249 :     resetSpeedLat();
     643         249 : }
     644             : 
     645             : 
     646             : /****************************************************************************/

Generated by: LCOV version 1.14