LCOV - code coverage report
Current view: top level - src/microsim/cfmodels - MSCFModel_SmartSK.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.9 % 79 71
Test Date: 2026-06-15 15:46:12 Functions: 91.7 % 12 11

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2012-2026 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              : #include <utils/xml/SUMOSAXAttributes.h>
      32              : 
      33              : //#define SmartSK_DEBUG
      34              : 
      35              : // ===========================================================================
      36              : // method definitions
      37              : // ===========================================================================
      38           18 : MSCFModel_SmartSK::MSCFModel_SmartSK(const MSVehicleType* vtype) :
      39              : // check whether setting these variables here with default values is ''good'' SUMO design
      40              : //        double tmp1=0.0, double tmp2=5.0, double tmp3=0.0, double tmp4, double tmp5)
      41              :     MSCFModel(vtype),
      42           18 :     myDawdle(vtype->getParameter().getCFParam(SUMO_ATTR_SIGMA, SUMOVTypeParameter::getDefaultImperfection(vtype->getParameter().vehicleClass))),
      43           18 :     myTauDecel(myDecel * myHeadwayTime),
      44           18 :     myTmp1(vtype->getParameter().getCFParam(SUMO_ATTR_TMP1, 1.0)),
      45           18 :     myTmp2(vtype->getParameter().getCFParam(SUMO_ATTR_TMP2, 1.0)),
      46           18 :     myTmp3(vtype->getParameter().getCFParam(SUMO_ATTR_TMP3, 1.0)),
      47           18 :     myTmp4(vtype->getParameter().getCFParam(SUMO_ATTR_TMP4, 1.0)),
      48           36 :     myTmp5(vtype->getParameter().getCFParam(SUMO_ATTR_TMP5, 1.0)) {
      49              :     // the variable tmp1 is the acceleration delay time, e.g. two seconds (or something like this).
      50              :     // for use in the upate process, a rule like if (v<myTmp1) vsafe = 0; is needed.
      51              :     // To have this, we have to transform myTmp1 (which is a time) into an equivalent speed. This is done by the
      52              :     // using the vsafe formula and computing:
      53              :     // v(t=myTmp1) = -myTauDecel + sqrt(myTauDecel*myTauDecel + accel*(accel + decel)*t*t + accel*decel*t*TS);
      54           18 :     double t = myTmp1;
      55           18 :     myS2Sspeed = -myTauDecel + sqrt(myTauDecel * myTauDecel + myAccel * (myAccel + myDecel) * t * t + myAccel * myDecel * t * TS);
      56              : #ifdef SmartSK_DEBUG
      57              :     std::cout << "# s2s-speed: " << myS2Sspeed << std::endl;
      58              : #endif
      59           18 :     if (myS2Sspeed > 5.0) {
      60            0 :         myS2Sspeed = 5.0;
      61              :     }
      62              : // double maxDeltaGap = -0.5*ACCEL2DIST(myDecel + myAccel);
      63           18 :     maxDeltaGap = -0.5 * (myDecel + myAccel) * TS * TS;
      64              : #ifdef SmartSK_DEBUG
      65              :     std::cout << "# maxDeltaGap = " << maxDeltaGap << std::endl;
      66              : #endif
      67           18 :     myTmp2 = TS / myTmp2;
      68           18 :     myTmp3 = sqrt(TS) * myTmp3;
      69           18 : }
      70              : 
      71              : 
      72           36 : MSCFModel_SmartSK::~MSCFModel_SmartSK() {}
      73              : 
      74              : 
      75              : void
      76           10 : MSCFModel_SmartSK::SSKVehicleVariables::saveState(OutputDevice& out, const MSCFModel& /*cfm*/) const {
      77           10 :     out.openTag(SUMO_TAG_CFM_VARIABLES);
      78           10 :     out.writeAttr(SUMO_ATTR_ID, "SmartSK");
      79           10 :     std::ostringstream internals;
      80           10 :     internals << gOld << " ";
      81           10 :     internals << myHeadway << " ";
      82           10 :     internals << ggOld.size() << " ";
      83           10 :     for (auto item : ggOld) {
      84            0 :         internals << item.first << " " << item.second << " ";
      85              :     }
      86           10 :     out.writeAttr(SUMO_ATTR_STATE, internals.str());
      87           10 :     out.closeTag();
      88           10 : }
      89              : 
      90              : 
      91              : void
      92           10 : MSCFModel_SmartSK::SSKVehicleVariables::loadState(const SUMOSAXAttributes& attrs) {
      93           10 :     bool ok = true;
      94           10 :     const std::string cfmID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
      95           10 :     if (cfmID != "SmartSK") {
      96            0 :         throw ProcessError(TLF("incompatible carFollowModel '%' when loading state for SmartSK", cfmID));
      97              :     }
      98           10 :     std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
      99           10 :     bis >> gOld;
     100           10 :     bis >> myHeadway;
     101              :     int ggOldSize;
     102           10 :     bis >> ggOldSize;
     103           10 :     for (int i = 0; i < ggOldSize; i++) {
     104              :         int k;
     105              :         double v;
     106            0 :         bis >> k;
     107              :         bis >> v;
     108            0 :         ggOld[k] = v;
     109              :     }
     110           20 : }
     111              : 
     112              : 
     113              : double
     114        22926 : MSCFModel_SmartSK::finalizeSpeed(MSVehicle* const veh, double vPos) const {
     115        22926 :     const double vNext = MSCFModel::finalizeSpeed(veh, vPos);
     116        22926 :     updateMyHeadway(veh);
     117              :     SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables();
     118              : #ifdef SmartSK_DEBUG
     119              :     if (vars->ggOld.size() > 1) {
     120              :         std::cout << "# more than one entry in ggOld list. Speed is " << vPos << ", corresponding dist is " << vars->ggOld[(int) vPos] << "\n";
     121              :         for (std::map<int, double>::iterator I = vars->ggOld.begin(); I != vars->ggOld.end(); I++) {
     122              :             std::cout << "# " << (*I).first << ' ' << (*I).second << std::endl;
     123              :         }
     124              :     }
     125              : #endif
     126        22926 :     vars->gOld = vars->ggOld[(int) vPos];
     127              :     vars->ggOld.clear();
     128        22926 :     return vNext;
     129              : }
     130              : 
     131              : double
     132        21050 : MSCFModel_SmartSK::followSpeed(const MSVehicle* const veh, double speed, double gap, double predSpeed, double /*predMaxDecel*/, const MSVehicle* const /*pred*/, const CalcReason /*usage*/) const {
     133              :     SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables();
     134              : 
     135              : // if (((gap - vars->gOld) < maxDeltaGap) && (speed>=5.0) && gap>=5.0) {
     136        21050 :     if ((gap - vars->gOld) < maxDeltaGap) {
     137          588 :         double tTauTest = gap / speed;
     138              : // allow  headway only to decrease only, never to increase. Increase is handled automatically by the headway dynamics in finalizeSpeed()!!!
     139          588 :         if ((tTauTest < vars->myHeadway) && (tTauTest > TS)) {
     140            2 :             vars->myHeadway = tTauTest;
     141              :         }
     142              :     }
     143              : 
     144        21050 :     double vsafe = _vsafe(veh, gap, predSpeed);
     145        21050 :     if ((speed <= 0.0) && (vsafe < myS2Sspeed)) {
     146              :         vsafe = 0;
     147              :     }
     148              : 
     149        42100 :     double vNew = MAX2(getSpeedAfterMaxDecel(speed), MIN2(vsafe, maxNextSpeed(speed, veh)));
     150              :     // there must be a better place to do the following assignment!!!
     151        21050 :     vars->gOld = gap;
     152        21050 :     vars->ggOld[(int)vNew] = gap;
     153        21050 :     return vNew;
     154              : }
     155              : 
     156              : double
     157        28460 : MSCFModel_SmartSK::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double /*decel*/, const CalcReason /*usage*/) const {
     158              :     SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables();
     159              : 
     160              : // if (((gap - vars->gOld) < maxDeltaGap) && (speed>=5.0) && gap>=5.0) {
     161        28460 :     if ((gap - vars->gOld) < maxDeltaGap) {
     162            6 :         double tTauTest = gap / speed;
     163              : // allow  headway only to decrease only, never to increase. Increase is handled automatically by the headway dynamics in finalizeSpeed()!!!
     164            6 :         if ((tTauTest < vars->myHeadway) && (tTauTest > TS)) {
     165            0 :             vars->myHeadway = tTauTest;
     166              :         }
     167              :     }
     168              : 
     169        56920 :     return MAX2(getSpeedAfterMaxDecel(speed), MIN2(_vsafe(veh, gap, 0), maxNextSpeed(speed, veh)));
     170              : }
     171              : 
     172              : double
     173        22926 : MSCFModel_SmartSK::patchSpeedBeforeLC(const MSVehicle* veh, double /*vMin*/, double /*vMax*/) const {
     174        22926 :     return dawdle(veh->getSpeed(), veh->getRNG());
     175              : }
     176              : 
     177              : double
     178        22926 : MSCFModel_SmartSK::dawdle(double speed, SumoRNG* rng) const {
     179        22926 :     return MAX2(0., speed - ACCEL2SPEED(myDawdle * myAccel * RandHelper::rand(rng)));
     180              : }
     181              : 
     182              : 
     183              : /** Returns the SK-vsafe. */
     184        49510 : double MSCFModel_SmartSK::_vsafe(const MSVehicle* const veh, double gap, double predSpeed) const {
     185        49510 :     if (predSpeed == 0 && gap < 0.01) {
     186              :         return 0;
     187              :     }
     188              :     SSKVehicleVariables* vars = (SSKVehicleVariables*)veh->getCarFollowVariables();
     189              :     // this is the most obvious change to the normal SK: the model uses the variable vars->myHeadway instead of the constant
     190              :     // myHeadwayTime as the "desired headway" tau
     191        49510 :     double bTau = myDecel * (vars->myHeadway);
     192              :     double vsafe = (double)(-1. * bTau
     193        49510 :                             + sqrt(
     194        49510 :                                 bTau * bTau
     195        49510 :                                 + (predSpeed * predSpeed)
     196        49510 :                                 + (2. * myDecel * gap)
     197        49510 :                             ));
     198              :     assert(vsafe >= 0);
     199        49510 :     return vsafe;
     200              : }
     201              : 
     202              : 
     203              : MSCFModel*
     204            0 : MSCFModel_SmartSK::duplicate(const MSVehicleType* vtype) const {
     205            0 :     return new MSCFModel_SmartSK(vtype);
     206              : }
        

Generated by: LCOV version 2.0-1