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

            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 2.0-1