Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSCFModel_Wiedemann.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2011-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/****************************************************************************/
20// The psycho-physical model of Wiedemann
21// references:
22// Andre Stebens - Traffic simulation with the Wiedemann model
23// Werner - Integration von Fahrzeugfolge- und Fahrstreifenwechselmodellen in die Nachtfahrsimulation LucidDrive
24// Olstam, Tapani - Comparison of Car-following models
25// Higgs, B. et.al - Analysis of theWiedemann car following model over different speeds using naturalistic data.
26// Ahmed, H.U.; Huang, Y.; Lu, P. - A Review of Car-Following Models and Modeling Tools forHuman and Autonomous-Ready Driving Behaviors in Micro-Simulation
27
28/****************************************************************************/
29#include <config.h>
30
31#include <cmath>
32#include "MSCFModel_Wiedemann.h"
33#include <microsim/MSVehicle.h>
34#include <microsim/MSLane.h>
37
38//#define DEBUG_V
39
40// ===========================================================================
41// static members
42// ===========================================================================
43
44// magic constant proposed by Wiedemann (based on real world measurements)
45const double MSCFModel_Wiedemann::D_MAX = 150;
46
47#define B_MIN_MULT 0
48#define B_MIN_ADD -1
49#define PRED_DECEL_MULT 0.5
50#define PRED_DECEL_MULT_EMERGENCY 0.55
51
52// ===========================================================================
53// method definitions
54// ===========================================================================
56 MSCFModel(vtype),
59 myAX(vtype->getLength() + 1. + 2. * mySecurity),
60 myCX(25. *(1. + mySecurity + myEstimation)),
61 myMinAccel(0.2 * myAccel),
63 // Wiedemann does not drive very precise and may violate minGap on occasion
65}
66
67
69
70
71void
74 out.writeAttr(SUMO_ATTR_ID, "Wiedemann");
75 std::ostringstream internals;
76 internals << accelSign;
77 out.writeAttr(SUMO_ATTR_STATE, internals.str());
78 out.closeTag();
79}
80
81
82void
84 bool ok = true;
85 const std::string cfmID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
86 if (cfmID != "Wiedemann") {
87 throw ProcessError(TLF("incompatible carFollowModel '%' when loading state for Wiedemann", cfmID));
88 }
89 std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
90 bis >> accelSign;
91}
92
93
94double
95MSCFModel_Wiedemann::finalizeSpeed(MSVehicle* const veh, double vPos) const {
96 const double vNext = MSCFModel::finalizeSpeed(veh, vPos);
98 vars->accelSign = vNext > veh->getSpeed() ? 1. : -1.;
99 return vNext;
100}
101
102
103double
104MSCFModel_Wiedemann::followSpeed(const MSVehicle* const veh, double /* speed */, double gap2pred, double predSpeed, double /*predMaxDecel*/, const MSVehicle* const pred, const CalcReason /*usage*/) const {
105 return _v(veh, predSpeed, gap2pred, pred != nullptr ? pred->getAcceleration() : 0);
106}
107
108
109double
110MSCFModel_Wiedemann::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double decel, const CalcReason /*usage*/) const {
111 /* Wiedemann does not handle approaching junctions or stops very well:
112 * regime approaching() fails when dv = 0 (i.e. a vehicle inserted with speed 0 does not accelerate to reach a stop)
113 * for dv ~ 0 the standard decision tree will switch to following() which
114 * does a lousy job of closing in on a stop / junction
115 * hence we borrow from Krauss here
116 */
117 return MIN2(maximumSafeStopSpeed(gap, decel, speed, false, veh->getActionStepLengthSecs()), maxNextSpeed(speed, veh));
118}
119
120
121double
122MSCFModel_Wiedemann::interactionGap(const MSVehicle* const, double vL) const {
124 return D_MAX;
125}
126
127
130 return new MSCFModel_Wiedemann(vtype);
131}
132
133
134double
135MSCFModel_Wiedemann::getSecureGap(const MSVehicle* const veh, const MSVehicle* const pred, const double speed, const double leaderSpeed, const double leaderMaxDecel) const {
136 const double bx = (1 + 7 * mySecurity) * sqrt(speed);
137 const double abx = myAX + bx - myType->getLength(); // abx is the brutto gap
138 return MAX2(abx, MSCFModel::getSecureGap(veh, pred, speed, leaderSpeed, leaderMaxDecel));
139}
140
141
142double
143MSCFModel_Wiedemann::_v(const MSVehicle* veh, double predSpeed, double gap, double predAccel) const {
145 const double dx = gap + myType->getLength(); // wiedemann uses brutto gap
146 const double v = veh->getSpeed();
147 const double vpref = veh->getMaxSpeed();
148 const double dv = v - predSpeed;
149 // desired minimum following distance at low speed difference
150 const double bx = (1 + 7 * mySecurity) * sqrt(v); // Harding propose a factor of *.8 here
151 const double abx = myAX + bx; // Harding propose a factor of *.8 here
152 const double ex = 2 - myEstimation; // + RandHelper::randNorm(0.5, 0.15)
153 const double sdx = myAX + ex * bx;
154 const double sdv_root = (dx - myAX) / myCX;
155 const double sdv = sdv_root * sdv_root;
156 const double cldv = sdv * ex * ex;
157 const double opdv = cldv * (-1 - 2 * RandHelper::randNorm(0.5, 0.15, veh->getRNG()));
158 // D_MAX is too low to brake safely when driving at speeds above 36m/s
159 const double dmax = MAX2(D_MAX, brakeGap(v, myDecel, 0));
160 // select the regime, get new acceleration, compute new speed based
161 double accel;
162 int branch = 0;
163 if (dx <= abx) {
164 accel = emergency(dv, dx, predAccel, v, gap, abx, bx);
165 branch = 1;
166 } else if (dx < sdx) {
167 if (dv > cldv) {
168 accel = approaching(dv, dx, abx, predAccel);
169 branch = 2;
170 } else if (dv > opdv) {
171 accel = following(vars->accelSign);
172 branch = 3;
173 } else {
174 accel = fullspeed(v, vpref, dx, abx);
175 branch = 4;
176 }
177 } else {
178 if (dv > sdv && dx < dmax) { //@note other versions have an disjunction instead of conjunction
179 accel = approaching(dv, dx, abx, predAccel);
180 branch = 5;
181 } else {
182 accel = fullspeed(v, vpref, dx, abx);
183 branch = 6;
184 }
185 }
186 // since we have hard constraints on accel we may as well use them here
187#ifdef DEBUG_V
188 const double rawAccel = accel;
189#endif
190 accel = MAX2(MIN2(accel, myAccel), -myEmergencyDecel);
191 const double vNew = MAX2(0., v + ACCEL2SPEED(accel)); // don't allow negative speeds
192#ifdef DEBUG_V
193 if (veh->isSelected() && !MSGlobals::gComputeLC) {
194 std::cout << SIMTIME << " Wiedemann::_v veh=" << veh->getID()
195 << " v=" << v << " pV=" << predSpeed << " pA=" << predAccel << " gap=" << gap
196 << " dv=" << dv << " dx=" << dx << " ax=" << myAX << " bx=" << bx << " abx=" << abx
197 << " sdx=" << sdx << " sdv=" << sdv << " cldv=" << cldv << " opdv=" << opdv
198 << " branch=" << branch << " rawAccel=" << rawAccel
199 << " accel=" << accel << " vNew=" << vNew << "\n";
200 }
201#else
202 UNUSED_PARAMETER(branch);
203#endif
204 return vNew;
205}
206
207
208double
209MSCFModel_Wiedemann::fullspeed(double v, double vpref, double dx, double abx) const {
210 // maximum acceleration is reduced with increasing speed
211 double bmax = 0.2 + 0.8 * myAccel * (7 - sqrt(v));
212 // if veh just drifted out of a 'following' process the acceleration is reduced
213 double accel = dx <= 2 * abx ? MIN2(myMinAccel, bmax * (dx - abx) / abx) : bmax;
214 if (v > vpref) {
215 accel = - accel;
216 }
217 return accel;
218}
219
220
221double
223 return myMinAccel * sign;
224}
225
226
227double
228MSCFModel_Wiedemann::approaching(double dv, double dx, double abx, double predAccel) const {
229 // there is singularity in the formula. we do the sanity check outside
230 assert(abx < dx);
231 // @note: the original model does not have a limit on maximum deceleration here.
232 // We add this to avoid cascading emergency deceleration
233 // also, the multiplier on predAccel is always 1 in the original model
234 return MAX2(0.5 * dv * dv / (abx - dx) + predAccel * PRED_DECEL_MULT, -myMaxApproachingDecel);
235}
236
237
238double
239MSCFModel_Wiedemann::emergency(double dv, double dx, double predAccel, double v, double gap, double abx, double bx) const {
240 // wiedemann assumes that dx will always be larger than myAX (sumo may
241 // violate this assumption when crashing (-:
242 //
243 // predAccel is called b_(n-1) in the literature and it's multipleir is always 1
244
245 if (dx > myAX) {
246 const double bmin = B_MIN_ADD + B_MIN_MULT * v;
247 const double accel = (0.5 * dv * dv / (myAX - dx)
248 + predAccel * PRED_DECEL_MULT_EMERGENCY
249 + bmin * (abx - gap) / bx);
250 return accel;
251 } else {
252 return -myEmergencyDecel;
253 }
254
255 // emergency according to C.Werner
256 //return -myEmergencyDecel;
257}
#define PRED_DECEL_MULT
#define B_MIN_ADD
#define PRED_DECEL_MULT_EMERGENCY
#define B_MIN_MULT
#define TLF(string,...)
Definition MsgHandler.h:306
#define ACCEL2SPEED(x)
Definition SUMOTime.h:54
#define SIMTIME
Definition SUMOTime.h:65
@ SUMO_TAG_CFM_VARIABLES
@ SUMO_ATTR_CF_WIEDEMANN_SECURITY
@ SUMO_ATTR_COLLISION_MINGAP_FACTOR
@ SUMO_ATTR_ID
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_CF_WIEDEMANN_ESTIMATION
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed).
virtual bool isSelected() const
whether this vehicle is selected in the GUI
SumoRNG * getRNG() const
double accelSign
state variable for remembering the drift direction
void saveState(OutputDevice &out, const MSCFModel &cfm) const
Saves the vehicle variables.
void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the vehicle variables from the given description.
MSCFModel * duplicate(const MSVehicleType *vtype) const
Duplicates the car-following model.
double following(double sign) const
double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences.
double getSecureGap(const MSVehicle *const veh, const MSVehicle *const pred, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0).
const double myMinAccel
The vehicle's minimum acceleration [m/s^2] // also b_null.
double approaching(double dv, double dx, double abx, double predAccel) const
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, double decel, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling).
const double myMaxApproachingDecel
The maximum deceleration when approaching.
double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed (no dawdling).
double _v(const MSVehicle *veh, double predSpeed, double gap, double predAccel) const
static const double D_MAX
free-flow distance in m
const double myEstimation
The driver's estimation parameter // also 'ZF2'.
double fullspeed(double v, double vpref, double dx, double bx) const
MSCFModel_Wiedemann(const MSVehicleType *vtype)
Constructor.
double emergency(double dv, double dx, double predAccel, double v, double gap, double abx, double bx) const
const double myAX
the minimum front-bumper to front-bumper distance when standing
const double myCX
perception threshold modifier
double interactionGap(const MSVehicle *const, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
const double mySecurity
The driver's security parameter // also 'ZF1'.
The car-following model abstraction.
Definition MSCFModel.h:59
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
try to get the given parameter for this carFollowingModel
Definition MSCFModel.h:707
virtual double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences. Called at most once per simulation...
double myEmergencyDecel
The vehicle's maximum emergency deceleration [m/s^2].
Definition MSCFModel.h:764
CalcReason
What the return value of stop/follow/free-Speed is used for.
Definition MSCFModel.h:95
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0).
double myCollisionMinGapFactor
The factor of minGap that must be maintained to avoid a collision event.
Definition MSCFModel.h:768
MSCFModel(const MSVehicleType *vtype)
Constructor.
Definition MSCFModel.cpp:55
double myDecel
The vehicle's maximum deceleration [m/s^2].
Definition MSCFModel.h:762
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition MSCFModel.h:424
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1, bool relaxEmergency=true) const
Returns the maximum next velocity for stopping within gap.
double myAccel
The vehicle's maximum acceleration [m/s^2].
Definition MSCFModel.h:759
const MSVehicleType * myType
The type to which this model definition belongs to.
Definition MSCFModel.h:756
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Definition MSGlobals.h:140
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition MSVehicle.h:533
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition MSVehicle.h:514
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
MSCFModel::VehicleVariables * getCarFollowVariables() const
Returns the vehicle's car following model variables.
Definition MSVehicle.h:994
The car-following model and parameter.
const SUMOVTypeParameter & getParameter() const
const std::string & getID() const
Returns the id.
Definition Named.h:73
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static double randNorm(double mean, double variance, SumoRNG *rng=nullptr)
Access to a random number from a normal distribution.
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
#define UNUSED_PARAMETER(x)