Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2012-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 MSCFModel_SmartSK.cpp 15 : /// @author Daniel Krajzewicz 16 : /// @author Jakob Erdmann 17 : /// @author Michael Behrisch 18 : /// @author Peter Wagner 19 : /// @date Tue, 05 Jun 2012 20 : /// 21 : // A smarter SK 22 : /****************************************************************************/ 23 : #include <config.h> 24 : 25 : #include <map> 26 : #include <microsim/MSVehicle.h> 27 : #include <microsim/MSLane.h> 28 : #include "MSCFModel_SmartSK.h" 29 : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h> 30 : #include <utils/common/RandHelper.h> 31 : 32 : //#define SmartSK_DEBUG 33 : 34 : // =========================================================================== 35 : // method definitions 36 : // =========================================================================== 37 7 : MSCFModel_SmartSK::MSCFModel_SmartSK(const MSVehicleType* vtype) : 38 : // check whether setting these variables here with default values is ''good'' SUMO design 39 : // double tmp1=0.0, double tmp2=5.0, double tmp3=0.0, double tmp4, double tmp5) 40 : MSCFModel(vtype), 41 7 : myDawdle(vtype->getParameter().getCFParam(SUMO_ATTR_SIGMA, SUMOVTypeParameter::getDefaultImperfection(vtype->getParameter().vehicleClass))), 42 7 : myTauDecel(myDecel * myHeadwayTime), 43 7 : myTmp1(vtype->getParameter().getCFParam(SUMO_ATTR_TMP1, 1.0)), 44 7 : myTmp2(vtype->getParameter().getCFParam(SUMO_ATTR_TMP2, 1.0)), 45 7 : myTmp3(vtype->getParameter().getCFParam(SUMO_ATTR_TMP3, 1.0)), 46 7 : myTmp4(vtype->getParameter().getCFParam(SUMO_ATTR_TMP4, 1.0)), 47 14 : myTmp5(vtype->getParameter().getCFParam(SUMO_ATTR_TMP5, 1.0)) { 48 : // the variable tmp1 is the acceleration delay time, e.g. two seconds (or something like this). 49 : // for use in the upate process, a rule like if (v<myTmp1) vsafe = 0; is needed. 50 : // To have this, we have to transform myTmp1 (which is a time) into an equivalent speed. This is done by the 51 : // using the vsafe formula and computing: 52 : // v(t=myTmp1) = -myTauDecel + sqrt(myTauDecel*myTauDecel + accel*(accel + decel)*t*t + accel*decel*t*TS); 53 7 : double t = myTmp1; 54 7 : myS2Sspeed = -myTauDecel + sqrt(myTauDecel * myTauDecel + myAccel * (myAccel + myDecel) * t * t + myAccel * myDecel * t * TS); 55 : #ifdef SmartSK_DEBUG 56 : std::cout << "# s2s-speed: " << myS2Sspeed << std::endl; 57 : #endif 58 7 : if (myS2Sspeed > 5.0) { 59 0 : myS2Sspeed = 5.0; 60 : } 61 : // double maxDeltaGap = -0.5*ACCEL2DIST(myDecel + myAccel); 62 7 : maxDeltaGap = -0.5 * (myDecel + myAccel) * TS * TS; 63 : #ifdef SmartSK_DEBUG 64 : std::cout << "# maxDeltaGap = " << maxDeltaGap << std::endl; 65 : #endif 66 7 : myTmp2 = TS / myTmp2; 67 7 : myTmp3 = sqrt(TS) * myTmp3; 68 7 : } 69 : 70 : 71 14 : MSCFModel_SmartSK::~MSCFModel_SmartSK() {} 72 : 73 : 74 : double 75 14950 : MSCFModel_SmartSK::finalizeSpeed(MSVehicle* const veh, double vPos) const { 76 14950 : const double vNext = MSCFModel::finalizeSpeed(veh, vPos); 77 14950 : updateMyHeadway(veh); 78 : SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables(); 79 : #ifdef SmartSK_DEBUG 80 : if (vars->ggOld.size() > 1) { 81 : std::cout << "# more than one entry in ggOld list. Speed is " << vPos << ", corresponding dist is " << vars->ggOld[(int) vPos] << "\n"; 82 : for (std::map<int, double>::iterator I = vars->ggOld.begin(); I != vars->ggOld.end(); I++) { 83 : std::cout << "# " << (*I).first << ' ' << (*I).second << std::endl; 84 : } 85 : } 86 : #endif 87 14950 : vars->gOld = vars->ggOld[(int) vPos]; 88 : vars->ggOld.clear(); 89 14950 : return vNext; 90 : } 91 : 92 : double 93 14352 : MSCFModel_SmartSK::followSpeed(const MSVehicle* const veh, double speed, double gap, double predSpeed, double /*predMaxDecel*/, const MSVehicle* const /*pred*/, const CalcReason /*usage*/) const { 94 : SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables(); 95 : 96 : // if (((gap - vars->gOld) < maxDeltaGap) && (speed>=5.0) && gap>=5.0) { 97 14352 : if ((gap - vars->gOld) < maxDeltaGap) { 98 0 : double tTauTest = gap / speed; 99 : // allow headway only to decrease only, never to increase. Increase is handled automatically by the headway dynamics in finalizeSpeed()!!! 100 0 : if ((tTauTest < vars->myHeadway) && (tTauTest > TS)) { 101 0 : vars->myHeadway = tTauTest; 102 : } 103 : } 104 : 105 14352 : double vsafe = _vsafe(veh, gap, predSpeed); 106 14352 : if ((speed <= 0.0) && (vsafe < myS2Sspeed)) { 107 : vsafe = 0; 108 : } 109 : 110 28704 : double vNew = MAX2(getSpeedAfterMaxDecel(speed), MIN2(vsafe, maxNextSpeed(speed, veh))); 111 : // there must be a better place to do the following assignment!!! 112 14352 : vars->gOld = gap; 113 14352 : vars->ggOld[(int)vNew] = gap; 114 14352 : return vNew; 115 : } 116 : 117 : double 118 44850 : MSCFModel_SmartSK::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double /*decel*/, const CalcReason /*usage*/) const { 119 : SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables(); 120 : 121 : // if (((gap - vars->gOld) < maxDeltaGap) && (speed>=5.0) && gap>=5.0) { 122 44850 : if ((gap - vars->gOld) < maxDeltaGap) { 123 0 : double tTauTest = gap / speed; 124 : // allow headway only to decrease only, never to increase. Increase is handled automatically by the headway dynamics in finalizeSpeed()!!! 125 0 : if ((tTauTest < vars->myHeadway) && (tTauTest > TS)) { 126 0 : vars->myHeadway = tTauTest; 127 : } 128 : } 129 : 130 89700 : return MAX2(getSpeedAfterMaxDecel(speed), MIN2(_vsafe(veh, gap, 0), maxNextSpeed(speed, veh))); 131 : } 132 : 133 : double 134 14950 : MSCFModel_SmartSK::patchSpeedBeforeLC(const MSVehicle* veh, double /*vMin*/, double /*vMax*/) const { 135 14950 : return dawdle(veh->getSpeed(), veh->getRNG()); 136 : } 137 : 138 : double 139 14950 : MSCFModel_SmartSK::dawdle(double speed, SumoRNG* rng) const { 140 14950 : return MAX2(0., speed - ACCEL2SPEED(myDawdle * myAccel * RandHelper::rand(rng))); 141 : } 142 : 143 : 144 : /** Returns the SK-vsafe. */ 145 59202 : double MSCFModel_SmartSK::_vsafe(const MSVehicle* const veh, double gap, double predSpeed) const { 146 59202 : if (predSpeed == 0 && gap < 0.01) { 147 : return 0; 148 : } 149 : SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables(); 150 : // this is the most obvious change to the normal SK: the model uses the variable vars->myHeadway instead of the constant 151 : // myHeadwayTime as the "desired headway" tau 152 59202 : double bTau = myDecel * (vars->myHeadway); 153 : double vsafe = (double)(-1. * bTau 154 59202 : + sqrt( 155 59202 : bTau * bTau 156 59202 : + (predSpeed * predSpeed) 157 59202 : + (2. * myDecel * gap) 158 59202 : )); 159 : assert(vsafe >= 0); 160 59202 : return vsafe; 161 : } 162 : 163 : 164 : MSCFModel* 165 0 : MSCFModel_SmartSK::duplicate(const MSVehicleType* vtype) const { 166 0 : return new MSCFModel_SmartSK(vtype); 167 : }