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 : }
|