LCOV - code coverage report
Current view: top level - src/microsim/cfmodels - MSCFModel_PWag2009.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 94.5 % 55 52
Test Date: 2026-06-15 15:46:12 Functions: 90.0 % 10 9

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2010-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_PWag2009.cpp
      15              : /// @author  Peter Wagner
      16              : /// @author  Daniel Krajzewicz
      17              : /// @author  Laura Bieker
      18              : /// @author  Michael Behrisch
      19              : /// @date    03.04.2010
      20              : ///
      21              : // Scalable model based on Krauss by Peter Wagner
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <microsim/MSVehicle.h>
      26              : #include <microsim/MSLane.h>
      27              : #include "MSCFModel_PWag2009.h"
      28              : #include <utils/common/RandHelper.h>
      29              : #include <utils/xml/SUMOSAXAttributes.h>
      30              : 
      31              : 
      32              : // ===========================================================================
      33              : // method definitions
      34              : // ===========================================================================
      35           25 : MSCFModel_PWag2009::MSCFModel_PWag2009(const MSVehicleType* vtype) :
      36              :     MSCFModel(vtype),
      37           25 :     myDawdle(vtype->getParameter().getCFParam(SUMO_ATTR_SIGMA, SUMOVTypeParameter::getDefaultImperfection(vtype->getParameter().vehicleClass))),
      38           25 :     myTauDecel(myDecel * myHeadwayTime),
      39           25 :     myDecelDivTau(myDecel / myHeadwayTime),
      40           25 :     myTauLastDecel(myDecel * vtype->getParameter().getCFParam(SUMO_ATTR_CF_PWAGNER2009_TAULAST, 0.3)),
      41           50 :     myActionPointProbability(vtype->getParameter().getCFParam(SUMO_ATTR_CF_PWAGNER2009_APPROB, 0.5)) {
      42              :     // PWag2009 does not drive very precise and may violate minGap on occasion
      43           25 :     myCollisionMinGapFactor = vtype->getParameter().getCFParam(SUMO_ATTR_COLLISION_MINGAP_FACTOR, 0.1);
      44           25 : }
      45              : 
      46              : 
      47           50 : MSCFModel_PWag2009::~MSCFModel_PWag2009() {}
      48              : 
      49              : 
      50              : void
      51           10 : MSCFModel_PWag2009::VehicleVariables::saveState(OutputDevice& out, const MSCFModel& /*cfm*/) const {
      52           10 :     out.openTag(SUMO_TAG_CFM_VARIABLES);
      53           10 :     out.writeAttr(SUMO_ATTR_ID, "PWagner2009");
      54           10 :     std::ostringstream internals;
      55           10 :     internals << aOld;
      56           10 :     out.writeAttr(SUMO_ATTR_STATE, internals.str());
      57           10 :     out.closeTag();
      58           10 : }
      59              : 
      60              : 
      61              : void
      62           10 : MSCFModel_PWag2009::VehicleVariables::loadState(const SUMOSAXAttributes& attrs) {
      63           10 :     bool ok = true;
      64           10 :     const std::string cfmID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
      65           10 :     if (cfmID != "PWagner2009") {
      66            0 :         throw ProcessError(TLF("incompatible carFollowModel '%' when loading state for PWagner2009", cfmID));
      67              :     }
      68           10 :     std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
      69           10 :     bis >> aOld;
      70           20 : }
      71              : 
      72              : 
      73              : double
      74         9199 : MSCFModel_PWag2009::finalizeSpeed(MSVehicle* const veh, double vPos) const {
      75         9199 :     const double vNext = MSCFModel::finalizeSpeed(veh, vPos);
      76              :     VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
      77         9199 :     double apref = SPEED2ACCEL(vNext - veh->getSpeed());
      78         9199 :     vars->aOld = apref;
      79         9199 :     return vNext;
      80              : }
      81              : 
      82              : double
      83         9199 : MSCFModel_PWag2009::patchSpeedBeforeLC(const MSVehicle* veh, double vMin, double vMax) const {
      84              :     UNUSED_PARAMETER(veh);
      85              :     UNUSED_PARAMETER(vMin);
      86         9199 :     return vMax;
      87              : }
      88              : 
      89              : // in addition, the parameters myTauLast, probAP, and sigmaAcc are needed; sigmaAcc can use myDawdle
      90              : // myTauLast might use the current time-step size, but this yields eventually an extreme model, I would be
      91              : // more careful and set it to something around 0.3 or 0.4, which are among the shortest headways I have
      92              : // seen so far in data ...
      93              : 
      94              : double
      95        20982 : MSCFModel_PWag2009::followSpeed(const MSVehicle* const veh, double speed, double gap, double predSpeed, double /*predMaxDecel*/, const MSVehicle* const /*pred*/, const CalcReason /*usage*/) const {
      96        20982 :     if (predSpeed == 0 && gap < 0.01) {
      97              :         return 0;
      98              :     }
      99        20310 :     const double vsafe = -myTauLastDecel + sqrt(myTauLastDecel * myTauLastDecel + predSpeed * predSpeed + 2.0 * myDecel * gap);
     100        20310 :     const double asafe = SPEED2ACCEL(vsafe - speed);
     101              :     VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
     102        20310 :     double apref = vars->aOld;
     103        20310 :     if (apref <= asafe && RandHelper::rand(veh->getRNG()) <= myActionPointProbability * TS) {
     104        10108 :         apref = myDecelDivTau * (gap + (predSpeed - speed) * myHeadwayTime - speed * myHeadwayTime) / (speed + myTauDecel);
     105        10108 :         apref = MIN2(apref, myAccel);
     106        10108 :         apref = MAX2(apref, -myDecel);
     107        20216 :         apref += myDawdle * RandHelper::rand((double) - 1., (double)1., veh->getRNG());
     108              :     }
     109        20310 :     if (apref > asafe) {
     110              :         apref = asafe;
     111              :     }
     112        20310 :     return MAX2(0., speed + ACCEL2SPEED(apref));
     113              : }
     114              : 
     115              : // uses the safe speed and preferred acceleration with the same NORMAL tau to compute stopSpeed
     116              : double
     117        23264 : MSCFModel_PWag2009::stopSpeed(const MSVehicle* const /* veh */, const double speed, double gap, double /*decel*/, const CalcReason /*usage*/) const {
     118        23264 :     if (gap < 0.01) {
     119              :         return 0.;
     120              :     }
     121        23145 :     const double vsafe = -myTauDecel + sqrt(myTauDecel * myTauDecel +  2.0 * myDecel * gap);
     122        23145 :     const double asafe = SPEED2ACCEL(vsafe - speed);
     123              : //    VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
     124        23145 :     double apref = myDecelDivTau * (gap  - 2 * speed * myHeadwayTime) / (speed + myTauDecel);
     125        23145 :     if (apref <= asafe) {
     126           24 :         apref = MIN2(apref, myAccel);
     127           24 :         apref = MAX2(apref, -myDecel);
     128              :     } else {
     129              :         apref = asafe;
     130              :     }
     131        23145 :     return MAX2(0., vsafe + ACCEL2SPEED(apref));
     132              : }
     133              : 
     134              : 
     135              : MSCFModel*
     136            0 : MSCFModel_PWag2009::duplicate(const MSVehicleType* vtype) const {
     137            0 :     return new MSCFModel_PWag2009(vtype);
     138              : }
        

Generated by: LCOV version 2.0-1