Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2011-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_W99.cpp
15 : /// @author Jakob Erdmann
16 : /// @date June 2019
17 : ///
18 : // The psycho-physical model of Wiedemann (10-Parameter version from 1999)
19 : // references:
20 : // code adapted from https://github.com/glgh/w99-demo
21 : // (MIT License, Copyright (c) 2016 glgh)
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <cmath>
26 : #include "MSCFModel_W99.h"
27 : #include <microsim/MSVehicle.h>
28 : #include <microsim/MSLane.h>
29 : #include <utils/common/RandHelper.h>
30 : #include <utils/xml/SUMOXMLDefinitions.h>
31 :
32 :
33 : // only used by DK2008
34 : #define INTERACTION_GAP 150
35 :
36 : // ===========================================================================
37 : // DEBUG constants
38 : // ===========================================================================
39 : #define DEBUG_FOLLOW_SPEED
40 : //#define DEBUG_COND (veh->getID() == "flow.0")
41 : #define DEBUG_COND (veh->isSelected())
42 :
43 : // ===========================================================================
44 : // static members
45 : // ===========================================================================
46 :
47 :
48 : // ===========================================================================
49 : // method definitions
50 : // ===========================================================================
51 287 : MSCFModel_W99::MSCFModel_W99(const MSVehicleType* vtype) :
52 : MSCFModel(vtype),
53 287 : myCC1(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC1, 1.30)),
54 287 : myCC2(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC2, 8.00)),
55 287 : myCC3(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC3, -12.00)),
56 287 : myCC4(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC4, -0.25)),
57 287 : myCC5(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC5, 0.35)),
58 287 : myCC6(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC6, 6.00)),
59 287 : myCC7(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC7, 0.25)),
60 287 : myCC8(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC8, 2.00)),
61 574 : myCC9(vtype->getParameter().getCFParam(SUMO_ATTR_CF_W99_CC9, 1.50)) {
62 : // translate some values to make them show up correctly in the gui
63 287 : myHeadwayTime = myCC1;
64 287 : myAccel = myCC8;
65 : // W99 does not drive very precise and may violate minGap on occasion
66 287 : myCollisionMinGapFactor = vtype->getParameter().getCFParam(SUMO_ATTR_COLLISION_MINGAP_FACTOR, 0.1);
67 287 : }
68 :
69 :
70 574 : MSCFModel_W99::~MSCFModel_W99() {}
71 :
72 :
73 : void
74 85466219 : MSCFModel_W99::computeThresholds(double speed, double predSpeed, double leaderAccel, double rndVal,
75 : double& sdxc, double& sdxo, double& sdxv) const {
76 :
77 85466219 : const double dv = predSpeed - speed;
78 85466219 : sdxc = myType->getMinGap(); // cc0
79 85466219 : if (predSpeed > 0) {
80 85042771 : const double v_slower = (dv >= 0 || leaderAccel < 1) ? speed : predSpeed + dv * rndVal;
81 170031587 : sdxc += myCC1 * MAX2(0.0, v_slower);
82 : }
83 85466219 : sdxo = sdxc + myCC2; //maximum following distance (upper limit of car-following process)
84 85466219 : sdxv = sdxo + myCC3 * (dv - myCC4);
85 85466219 : }
86 :
87 :
88 : double
89 85466219 : MSCFModel_W99::followSpeed(const MSVehicle* const veh, double speed, double gap2pred, double predSpeed, double /*predMaxDecel*/, const MSVehicle* const pred, const CalcReason /*usage*/) const {
90 85466219 : const double dx = gap2pred + myType->getMinGap();
91 85466219 : const double dv = predSpeed - speed;
92 :
93 : const double cc0 = myType->getMinGap();
94 :
95 85466219 : const double leaderAccel = pred != nullptr ? pred->getAcceleration() : 0;
96 85466219 : const double oldAccel = veh->getAcceleration();
97 :
98 85466219 : const double rndVal = speed > 0 ? RandHelper::rand(veh->getRNG()) - 0.5 : 0.5;
99 : double sdxc, sdxo, sdxv;
100 85466219 : computeThresholds(speed, predSpeed, leaderAccel, rndVal, sdxc, sdxo, sdxv);
101 :
102 85466219 : const double sdv = myCC6 * dx * dx / 10000;
103 85466219 : const double sdvc = speed > 0 ? myCC4 - sdv : 0; //minimum closing dv
104 85466219 : const double sdvo = predSpeed > myCC5 ? sdv + myCC5 : sdv; //minimum opening dv
105 :
106 : double accel = 0; // resulting acceleration
107 : int status = 0;
108 :
109 85466219 : if (dv < sdvo && dx <= sdxc) {
110 : // 'Decelerate - Increase Distance';
111 : accel = 0;
112 : // code in addtion to w99-demo to fix collision (#10472)
113 1096398 : if (dx - SPEED2DIST(speed) < myType->getMinGap() * myCollisionMinGapFactor) {
114 : // prevent crashin in the next step
115 410238 : accel = -SPEED2ACCEL(speed);
116 : status = 9;
117 : }
118 1096398 : if (predSpeed > 0) {
119 1086746 : if (dv < 0) {
120 1084085 : if (dx > cc0) {
121 1062691 : accel = MIN2(leaderAccel + dv * dv / (cc0 - dx), 0.0);
122 : status = 0;
123 : } else {
124 21394 : accel = MIN2(leaderAccel + 0.5 * (dv - sdvo), 0.0);
125 : status = 1;
126 : }
127 : }
128 1086746 : if (accel > -myCC7) {
129 : accel = -myCC7;
130 : status = 2;
131 : } else {
132 1070065 : accel = MAX2(accel, -10 + 0.5 * sqrt(speed));
133 : status = 3;
134 : }
135 : }
136 :
137 84369821 : } else if (dv < sdvc && dx < sdxv) {
138 : // 'Decelerate - Decrease Distance';
139 2987700 : accel = 0.5 * dv * dv / (sdxc - dx - 0.1);
140 2987700 : status = 4;
141 : // deceleration is capped by myEmergencyDecel in MSCFModel::finalizeSpeed
142 81382121 : } else if (dv < sdvo && dx < sdxo) {
143 : // 'Accelerate/Decelerate - Keep Distance';
144 5664761 : if (oldAccel <= 0) {
145 4540372 : accel = MIN2(oldAccel, -myCC7);
146 : status = 5;
147 : } else {
148 1124389 : accel = MAX2(oldAccel, myCC7);
149 : status = 6;
150 : // acceleration is capped at desired speed in MSCFModel::finalizeSpeed
151 : }
152 : } else {
153 : // 'Accelerate/Relax - Increase/Keep Speed';
154 75717360 : if (dx > sdxc) {
155 : //if (follower.status === 'w') {
156 : // accel = cc7;
157 : //} else
158 : {
159 77830551 : const double accelMax = myCC8 + myCC9 * MIN2(speed, 80 / 3.6) + RandHelper::rand(veh->getRNG());
160 75701522 : if (dx < sdxo) {
161 1141150 : accel = MIN2(dv * dv / (sdxo - dx), accelMax);
162 : status = 7;
163 : } else {
164 : accel = accelMax;
165 : status = 8;
166 : }
167 : }
168 : // acceleration is capped at desired speed in MSCFModel::finalizeSpeed
169 : }
170 : }
171 85466219 : double vNew = speed + ACCEL2SPEED(accel);
172 : #ifdef DEBUG_FOLLOW_SPEED
173 85466219 : if (DEBUG_COND) {
174 0 : std::cout << SIMTIME << " W99::fS veh=" << veh->getID() << " pred=" << Named::getIDSecure(pred)
175 : << " v=" << speed << " pV=" << predSpeed << " g=" << gap2pred
176 : << " dv=" << dv << " dx=" << dx
177 0 : << " sdxc=" << sdxc << " sdxo=" << sdxo << " sdxv=" << sdxv << " sdv=" << sdv << " sdvo=" << sdvo << " sdvc=" << sdvc
178 : << " st=" << status
179 0 : << " a=" << accel << " V=" << vNew << "\n";
180 : }
181 : #else
182 : UNUSED_PARAMETER(status);
183 : #endif
184 85466219 : if (MSGlobals::gSemiImplicitEulerUpdate) {
185 : vNew = MAX2(0.0, vNew);
186 : }
187 85466219 : return vNew;
188 : }
189 :
190 :
191 :
192 : double
193 36593341 : MSCFModel_W99::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double decel, const CalcReason /*usage*/) const {
194 : // see reasoning in MSCFModel_Wiedemann::stopSpeed
195 36593341 : return MIN2(maximumSafeStopSpeed(gap, decel, speed, false, veh->getActionStepLengthSecs()), maxNextSpeed(speed, veh));
196 : }
197 :
198 :
199 : double
200 0 : MSCFModel_W99::interactionGap(const MSVehicle* const, double vL) const {
201 : UNUSED_PARAMETER(vL);
202 0 : return INTERACTION_GAP;
203 : }
204 :
205 :
206 : MSCFModel*
207 0 : MSCFModel_W99::duplicate(const MSVehicleType* vtype) const {
208 0 : return new MSCFModel_W99(vtype);
209 : }
|