Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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_Krauss.cpp
15 : /// @author Tobias Mayer
16 : /// @author Daniel Krajzewicz
17 : /// @author Jakob Erdmann
18 : /// @author Michael Behrisch
19 : /// @author Laura Bieker
20 : /// @date Mon, 04 Aug 2009
21 : ///
22 : // Krauss car-following model, with acceleration decrease and faster start
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include <microsim/MSVehicle.h>
27 : #include <microsim/MSLane.h>
28 : #include <microsim/MSGlobals.h>
29 : #include "MSCFModel_Krauss.h"
30 : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
31 : #include <utils/common/RandHelper.h>
32 : #include <utils/xml/SUMOSAXAttributes.h>
33 :
34 :
35 :
36 : // ===========================================================================
37 : // DEBUG constants
38 : // ===========================================================================
39 : //#define DEBUG_COND (true)
40 : #define DEBUG_COND (veh->isSelected())
41 : #define DEBUG_DRIVER_ERRORS
42 :
43 32 : MSCFModel_Krauss::VehicleVariables::VehicleVariables(SUMOTime dawdleStep)
44 32 : : accelDawdle(1e6), updateOffset(SIMSTEP % dawdleStep + DELTA_T) { }
45 :
46 : // ===========================================================================
47 : // method definitions
48 : // ===========================================================================
49 307991 : MSCFModel_Krauss::MSCFModel_Krauss(const MSVehicleType* vtype) :
50 : MSCFModel_KraussOrig1(vtype),
51 307991 : myDawdleStep(TIME2STEPS(vtype->getParameter().getCFParam(SUMO_ATTR_SIGMA_STEP, TS))) {
52 307991 : if (myDawdleStep % DELTA_T != 0) {
53 : SUMOTime rem = myDawdleStep % DELTA_T;
54 4 : if (rem < DELTA_T / 2) {
55 0 : myDawdleStep += -rem;
56 : } else {
57 4 : myDawdleStep += DELTA_T - rem;
58 : }
59 12 : WRITE_WARNINGF(TL("Rounding 'sigmaStep' to % for vType '%'"), STEPS2TIME(myDawdleStep), vtype->getID());
60 :
61 : }
62 307991 : }
63 :
64 :
65 608247 : MSCFModel_Krauss::~MSCFModel_Krauss() {}
66 :
67 :
68 : void
69 10 : MSCFModel_Krauss::VehicleVariables::saveState(OutputDevice& out, const MSCFModel& /*cfm*/) const {
70 10 : out.openTag(SUMO_TAG_CFM_VARIABLES);
71 10 : out.writeAttr(SUMO_ATTR_ID, "Krauss");
72 10 : std::ostringstream internals;
73 10 : internals << accelDawdle << " ";
74 10 : internals << updateOffset;
75 10 : out.writeAttr(SUMO_ATTR_STATE, internals.str());
76 10 : out.closeTag();
77 10 : }
78 :
79 :
80 : void
81 10 : MSCFModel_Krauss::VehicleVariables::loadState(const SUMOSAXAttributes& attrs) {
82 10 : bool ok = true;
83 10 : const std::string cfmID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
84 10 : if (cfmID != "Krauss") {
85 0 : throw ProcessError(TLF("incompatible carFollowModel '%' when loading state for Krauss", cfmID));
86 : }
87 10 : std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
88 10 : bis >> accelDawdle;
89 10 : bis >> updateOffset;
90 20 : }
91 :
92 :
93 : double
94 549981867 : MSCFModel_Krauss::patchSpeedBeforeLC(const MSVehicle* veh, double vMin, double vMax) const {
95 549981867 : const double sigma = (veh->passingMinor()
96 549981867 : ? veh->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_SIGMA_MINOR, myDawdle)
97 : : myDawdle);
98 : double vDawdle;
99 549981867 : if (myDawdleStep > DELTA_T) {
100 : VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
101 5753 : if (SIMSTEP % myDawdleStep == vars->updateOffset) {
102 1428 : const double vD = MAX2(vMin, dawdle2(vMax, sigma, veh->getRNG()));
103 1428 : const double a1 = SPEED2ACCEL(vMax - veh->getSpeed());
104 1428 : const double a2 = SPEED2ACCEL(vD - vMax);
105 1428 : const double accelMax = (veh->getLane()->getVehicleMaxSpeed(veh) - veh->getSpeed()) / STEPS2TIME(myDawdleStep);
106 : // avoid exceeding maxSpeed before the next sigmaStep
107 1428 : vars->accelDawdle = MIN2(a1, accelMax) + a2;
108 1428 : vDawdle = veh->getSpeed() + ACCEL2SPEED(vars->accelDawdle);
109 : //std::cout << SIMTIME << " v=" << veh->getSpeed() << " updated vD=" << vD<< " a1=" << a1 << " a2=" << a2 << " aM=" << accelMax << " accelDawdle=" << vars->accelDawdle << " vDawdle=" << vDawdle << "\n";
110 : } else {
111 4325 : const double safeAccel = SPEED2ACCEL(vMax - veh->getSpeed());
112 4325 : const double accel = MIN2(safeAccel, vars->accelDawdle);
113 4325 : vDawdle = MAX2(vMin, MIN2(vMax, veh->getSpeed() + ACCEL2SPEED(accel)));
114 : //std::cout << SIMTIME << " v=" << veh->getSpeed() << " safeAccel=" << safeAccel << " accel=" << accel << " vDawdle=" << vDawdle << "\n";
115 : }
116 : } else {
117 549976114 : vDawdle = MAX2(vMin, dawdle2(vMax, sigma, veh->getRNG()));
118 : //const double accel1 = SPEED2ACCEL(vMax - veh->getSpeed());
119 : //const double accel2 = SPEED2ACCEL(vDawdle - vMax);
120 : //std::cout << SIMTIME << " v=" << veh->getSpeed() << " updated vDawdle=" << vDawdle << " a1=" << accel1 << " a2=" << accel2 << " accelDawdle=" << SPEED2ACCEL(vDawdle - veh->getSpeed()) << "\n";
121 : }
122 549981867 : return vDawdle;
123 : }
124 :
125 :
126 : double
127 736446278 : MSCFModel_Krauss::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double decel, const CalcReason usage) const {
128 : // NOTE: This allows return of smaller values than minNextSpeed().
129 : // Only relevant for the ballistic update: We give the argument headway=veh->getActionStepLengthSecs(), to assure that
130 : // the stopping position is approached with a uniform deceleration also for tau!=veh->getActionStepLengthSecs().
131 736446278 : applyHeadwayPerceptionError(veh, speed, gap);
132 736446278 : const bool relaxEmergency = usage != FUTURE; // do not relax insertionStopSpeed
133 736446278 : return MIN2(maximumSafeStopSpeed(gap, decel, speed, false, veh->getActionStepLengthSecs(), relaxEmergency), maxNextSpeed(speed, veh));
134 : }
135 :
136 :
137 : double
138 2172620679 : MSCFModel_Krauss::followSpeed(const MSVehicle* const veh, double speed, double gap, double predSpeed, double predMaxDecel, const MSVehicle* const pred, const CalcReason /*usage*/) const {
139 : //gDebugFlag1 = DEBUG_COND;
140 2172620679 : applyHeadwayAndSpeedDifferencePerceptionErrors(veh, speed, gap, predSpeed, predMaxDecel, pred);
141 : //gDebugFlag1 = DEBUG_COND; // enable for DEBUG_EMERGENCYDECEL
142 2172620679 : const double vsafe = maximumSafeFollowSpeed(gap, speed, predSpeed, predMaxDecel);
143 : //gDebugFlag1 = false;
144 2172620679 : const double vmax = maxNextSpeed(speed, veh);
145 2172620679 : if (MSGlobals::gSemiImplicitEulerUpdate) {
146 : return MIN2(vsafe, vmax);
147 : } else {
148 : // ballistic
149 : // XXX: the euler variant can break as strong as it wishes immediately! The ballistic cannot, refs. #2575.
150 172456055 : return MAX2(MIN2(vsafe, vmax), minNextSpeedEmergency(speed));
151 : }
152 : }
153 :
154 : double
155 549977542 : MSCFModel_Krauss::dawdle2(double speed, double sigma, SumoRNG* rng) const {
156 549977542 : if (!MSGlobals::gSemiImplicitEulerUpdate) {
157 : // in case of the ballistic update, negative speeds indicate
158 : // a desired stop before the completion of the next timestep.
159 : // We do not allow dawdling to overwrite this indication
160 25972740 : if (speed < 0) {
161 : return speed;
162 : }
163 : }
164 : // generate random number out of [0,1)
165 549541194 : const double random = RandHelper::rand(rng);
166 : // Dawdle.
167 549541194 : if (speed < myAccel) {
168 : // we should not prevent vehicles from driving just due to dawdling
169 : // if someone is starting, he should definitely start
170 : // (but what about slow-to-start?)!!!
171 122217882 : speed -= ACCEL2SPEED(sigma * speed * random);
172 : } else {
173 427323312 : speed -= ACCEL2SPEED(sigma * myAccel * random);
174 : }
175 : return MAX2(0., speed);
176 : }
177 :
178 :
179 : MSCFModel*
180 1390 : MSCFModel_Krauss::duplicate(const MSVehicleType* vtype) const {
181 1390 : return new MSCFModel_Krauss(vtype);
182 : }
183 :
184 :
185 : /****************************************************************************/
|