Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSCFModel_ACC.cpp
Go to the documentation of this file.
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/****************************************************************************/
18// ACC car-following model based on [1], [2].
19// [1] Milanes, V., and S. E. Shladover. Handling Cut-In Vehicles in Strings
20// of Cooperative Adaptive Cruise Control Vehicles. Journal of Intelligent
21// Transportation Systems, Vol. 20, No. 2, 2015, pp. 178-191.
22// [2] Xiao, L., M. Wang and B. van Arem. Realistic Car-Following Models for
23// Microscopic Simulation of Adaptive and Cooperative Adaptive Cruise
24// Control Vehicles. Transportation Research Record: Journal of the
25// Transportation Research Board, No. 2623, 2017. (DOI: 10.3141/2623-01).
26//[3] Xiao, L., Wang, M., Schakel, W., & van Arem, B. (2018). Unravelling
27// effects of cooperative adaptive cruise control deactivation on
28// traffic flow characteristics at merging bottlenecks. Transportation
29// Research Part C: Emerging Technologies, 96, 380–397.
30// <https://doi.org/10.1016/j.trc.2018.10.008>
31/****************************************************************************/
32#include <config.h>
33
34#include <stdio.h>
35#include <iostream>
36
37#include "MSCFModel_ACC.h"
38#include <microsim/MSVehicle.h>
39#include <microsim/MSLane.h>
44#include <math.h>
45#include <microsim/MSNet.h>
46
47// ===========================================================================
48// debug flags
49// ===========================================================================
50//#define DEBUG_ACC
51//#define DEBUG_COND (true)
52//#define DEBUG_COND (veh->isSelected())
53
54
55// ===========================================================================
56// defaults
57// ===========================================================================
58#define DEFAULT_SC_GAIN -0.4
59#define DEFAULT_GCC_GAIN_SPEED 0.8
60#define DEFAULT_GCC_GAIN_SPACE 0.04
61#define DEFAULT_GC_GAIN_SPEED 0.07
62#define DEFAULT_GC_GAIN_SPACE 0.23
63#define DEFAULT_CA_GAIN_SPACE 0.8
64#define DEFAULT_CA_GAIN_SPEED 0.23
65
66// ===========================================================================
67// thresholds
68// ===========================================================================
69#define GAP_THRESHOLD_SPEEDCTRL 120
70#define GAP_THRESHOLD_GAPCTRL 100
71// override followSpeed when deemed unsafe by the given margin (the value was selected to reduce the number of necessary interventions)
72#define DEFAULT_EMERGENCY_OVERRIDE_THRESHOLD 2.0
73
75
76// ===========================================================================
77// method definitions
78// ===========================================================================
80 MSCFModel(vtype),
81 mySpeedControlGain(vtype->getParameter().getCFParam(SUMO_ATTR_SC_GAIN, DEFAULT_SC_GAIN)),
82 myGapClosingControlGainSpeed(vtype->getParameter().getCFParam(SUMO_ATTR_GCC_GAIN_SPEED, DEFAULT_GCC_GAIN_SPEED)),
83 myGapClosingControlGainSpace(vtype->getParameter().getCFParam(SUMO_ATTR_GCC_GAIN_SPACE, DEFAULT_GCC_GAIN_SPACE)),
84 myGapControlGainSpeed(vtype->getParameter().getCFParam(SUMO_ATTR_GC_GAIN_SPEED, DEFAULT_GC_GAIN_SPEED)),
85 myGapControlGainSpace(vtype->getParameter().getCFParam(SUMO_ATTR_GC_GAIN_SPACE, DEFAULT_GC_GAIN_SPACE)),
86 myCollisionAvoidanceGainSpeed(vtype->getParameter().getCFParam(SUMO_ATTR_CA_GAIN_SPEED, DEFAULT_CA_GAIN_SPEED)),
87 myCollisionAvoidanceGainSpace(vtype->getParameter().getCFParam(SUMO_ATTR_CA_GAIN_SPACE, DEFAULT_CA_GAIN_SPACE)),
88 myApplyDriverstate(vtype->getParameter().getCFParam(SUMO_ATTR_APPLYDRIVERSTATE, 0)),
89 myEmergencyThreshold(vtype->getParameter().getCFParam(SUMO_ATTR_CA_OVERRIDE, DEFAULT_EMERGENCY_OVERRIDE_THRESHOLD)) {
90 // ACC does not drive very precise and often violates minGap
92}
93
95
96
97void
100 out.writeAttr(SUMO_ATTR_ID, "ACC");
101 std::ostringstream internals;
102 internals << ACC_ControlMode << " ";
103 internals << lastUpdateTime;
104 out.writeAttr(SUMO_ATTR_STATE, internals.str());
105 out.closeTag();
106}
107
108
109void
111 bool ok = true;
112 const std::string cfmID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
113 if (cfmID != "ACC") {
114 throw ProcessError(TLF("incompatible carFollowModel '%' when loading state for ACC", cfmID));
115 }
116 std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
117 bis >> ACC_ControlMode;
118 bis >> lastUpdateTime;
119}
120
121double
122MSCFModel_ACC::followSpeed(const MSVehicle* const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle* const pred, const CalcReason /*usage*/) const {
123 if (myApplyDriverstate) {
124 applyHeadwayAndSpeedDifferencePerceptionErrors(veh, speed, gap2pred, predSpeed, predMaxDecel, pred);
125 }
126 const double desSpeed = MIN2(veh->getLane()->getSpeedLimit(), veh->getMaxSpeed());
127 const double vACC = _v(veh, gap2pred, speed, predSpeed, desSpeed, true);
128 const double vSafe = maximumSafeFollowSpeed(gap2pred, speed, predSpeed, predMaxDecel);
129 if (vSafe + myEmergencyThreshold < vACC) {
130 //ACCVehicleVariables* vars = (ACCVehicleVariables*)veh->getCarFollowVariables();
131 //std::cout << SIMTIME << " veh=" << veh->getID() << " v=" << speed << " vL=" << predSpeed << " gap=" << gap2pred << " vACC=" << vACC << " vSafe=" << vSafe << " cm=" << vars->ACC_ControlMode << "\n";
132 return vSafe + myEmergencyThreshold;
133 }
134 return vACC;
135}
136
137
138double
139MSCFModel_ACC::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double decel, const CalcReason /*usage*/) const {
140 if (myApplyDriverstate) {
141 applyHeadwayPerceptionError(veh, speed, gap);
142 }
143 // NOTE: This allows return of smaller values than minNextSpeed().
144 // Only relevant for the ballistic update: We give the argument headway=TS, to assure that
145 // the stopping position is approached with a uniform deceleration also for tau!=TS.
146 return MIN2(maximumSafeStopSpeed(gap, decel, speed, false, veh->getActionStepLengthSecs()), maxNextSpeed(speed, veh));
147}
148
149
150double
151MSCFModel_ACC::getSecureGap(const MSVehicle* const /*veh*/, const MSVehicle* const /*pred*/, const double speed, const double leaderSpeed, const double /* leaderMaxDecel */) const {
152 // Accel in gap mode should vanish:
153 // 0 = myGapControlGainSpeed * (leaderSpeed - speed) + myGapControlGainSpace * (g - myHeadwayTime * speed);
154 // <=> myGapControlGainSpace * g = - myGapControlGainSpeed * (leaderSpeed - speed) + myGapControlGainSpace * myHeadwayTime * speed;
155 // <=> g = - myGapControlGainSpeed * (leaderSpeed - speed) / myGapControlGainSpace + myHeadwayTime * speed;
156 return myGapControlGainSpeed * (speed - leaderSpeed) / myGapControlGainSpace + myHeadwayTime * speed;
157}
158
159
160double
161MSCFModel_ACC::insertionFollowSpeed(const MSVehicle* const v, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle* const /*pred*/) const {
162//#ifdef DEBUG_ACC
163// std::cout << "MSCFModel_ACC::insertionFollowSpeed(), speed="<<speed<< std::endl;
164//#endif
165 // iterate to find a stationary value for
166 // speed = followSpeed(v, speed, gap2pred, predSpeed, predMaxDecel, nullptr, CalcReason::FUTURE)
167 const int max_iter = 50;
168 int n_iter = 0;
169 const double tol = 0.1;
170 const double damping = 0.1;
171
172 double res = speed;
173 while (n_iter < max_iter) {
174 // proposed acceleration
175 const double a = SPEED2ACCEL(followSpeed(v, res, gap2pred, predSpeed, predMaxDecel, nullptr, CalcReason::FUTURE) - res);
176 res = res + damping * a;
177//#ifdef DEBUG_ACC
178// std::cout << " n_iter=" << n_iter << ", a=" << a << ", res=" << res << std::endl;
179//#endif
180 if (fabs(a) < tol) {
181 break;
182 } else {
183 n_iter++;
184 }
185 }
186 return res;
187}
188
189
191double
192MSCFModel_ACC::interactionGap(const MSVehicle* const /*veh */, double /* vL */) const {
193 /*maximum radar range is ACC is enabled*/
194 return 250;
195}
196
197double MSCFModel_ACC::accelSpeedControl(double vErr) const {
198 // Speed control law
199 return mySpeedControlGain * vErr;
200}
201
202double
203MSCFModel_ACC::accelGapControl(const MSVehicle* const /* veh */, const double gap2pred, const double speed, const double predSpeed, double vErr) const {
204 // Gap control law
205 double gclAccel = 0.0;
206 const double deltaVel = predSpeed - speed;
207
208 // see dynamic gap margin definition from (Xiao et. al, 2018)[3], equation 5 reformulated as min/max to avoid discontinuities
209 const double d0 = MAX2(0., MIN2(75. / speed - 5., 2.));
210 // this is equation 4, gap2pred is the difference in vehicle positions minus the length
211 const double spacingErr = gap2pred - myHeadwayTime * speed - d0;
212
213
214 if (fabs(spacingErr) < 0.2 && fabs(vErr) < 0.1) {
215 // gap mode
216 gclAccel = myGapControlGainSpeed * deltaVel + myGapControlGainSpace * spacingErr;
217#ifdef DEBUG_ACC
218 if (DEBUG_COND) {
219 std::cout << " applying gap control: spacingErr=" << spacingErr << " speedErr=" << vErr << std::endl;
220 }
221#endif
222 } else if (spacingErr < 0) {
223 // collision avoidance mode
224 gclAccel = myCollisionAvoidanceGainSpeed * deltaVel + myCollisionAvoidanceGainSpace * spacingErr;
225#ifdef DEBUG_ACC
226 if (DEBUG_COND) {
227 std::cout << " applying collision avoidance: spacingErr=" << spacingErr << " speedErr=" << vErr << std::endl;
228 }
229#endif
230 } else {
231 // gap closing mode
232 gclAccel = myGapClosingControlGainSpeed * deltaVel + myGapClosingControlGainSpace * spacingErr;
233#ifdef DEBUG_ACC
234 if (DEBUG_COND) {
235 std::cout << " applying gap closing: spacingErr=" << spacingErr << " speedErr=" << vErr << std::endl;
236 }
237#endif
238 }
239 return gclAccel;
240}
241
242
243double
244MSCFModel_ACC::_v(const MSVehicle* const veh, const double gap2pred, const double speed,
245 const double predSpeed, const double desSpeed, const bool /* respectMinGap */) const {
246
247 double accelACC = 0;
248 double gapLimit_SC = GAP_THRESHOLD_SPEEDCTRL; // lower gap limit in meters to enable speed control law
249 double gapLimit_GC = GAP_THRESHOLD_GAPCTRL; // upper gap limit in meters to enable gap control law
250
251#ifdef DEBUG_ACC
252 if (DEBUG_COND) {
253 std::cout << SIMTIME << " MSCFModel_ACC::_v() for veh '" << veh->getID() << "'\n"
254 << " gap=" << gap2pred << " speed=" << speed << " predSpeed=" << predSpeed
255 << " desSpeed=" << desSpeed << " tau=" << myHeadwayTime << std::endl;
256 }
257#endif
258
259
260 /* Velocity error */
261 double vErr = speed - desSpeed;
262 int setControlMode = 0;
266 setControlMode = 1;
267 }
268 if (gap2pred > gapLimit_SC) {
269
270#ifdef DEBUG_ACC
271 if (DEBUG_COND) {
272 std::cout << " applying speedControl" << std::endl;
273 }
274#endif
275 // Find acceleration - Speed control law
276 accelACC = accelSpeedControl(vErr);
277 // Set cl to vehicle parameters
278 if (setControlMode) {
279 vars->ACC_ControlMode = 0;
280 }
281 } else if (gap2pred < gapLimit_GC) {
282 // Find acceleration - Gap control law
283 accelACC = accelGapControl(veh, gap2pred, speed, predSpeed, vErr);
284 // Set cl to vehicle parameters
285 if (setControlMode) {
286 vars->ACC_ControlMode = 1;
287 }
288 } else {
289 // Follow previous applied law
290 int cm = vars->ACC_ControlMode;
291 if (!cm) {
292
293#ifdef DEBUG_ACC
294 if (DEBUG_COND) {
295 std::cout << " applying speedControl" << std::endl;
296 }
297#endif
298 accelACC = accelSpeedControl(vErr);
299 } else {
300 accelACC = accelGapControl(veh, gap2pred, speed, predSpeed, vErr);
301 }
302
303 }
304
305 double newSpeed = speed + ACCEL2SPEED(accelACC);
306
307#ifdef DEBUG_ACC
308 if (DEBUG_COND) {
309 std::cout << " result: accel=" << accelACC << " newSpeed=" << newSpeed << std::endl;
310 }
311#endif
312
313 return MAX2(0., newSpeed);
314}
315
316
319 return new MSCFModel_ACC(vtype);
320}
#define DEFAULT_GC_GAIN_SPACE
#define DEFAULT_GCC_GAIN_SPEED
#define DEFAULT_GCC_GAIN_SPACE
#define DEFAULT_CA_GAIN_SPACE
#define DEFAULT_GC_GAIN_SPEED
#define DEFAULT_CA_GAIN_SPEED
#define GAP_THRESHOLD_SPEEDCTRL
#define DEFAULT_EMERGENCY_OVERRIDE_THRESHOLD
#define GAP_THRESHOLD_GAPCTRL
#define DEFAULT_SC_GAIN
#define TLF(string,...)
Definition MsgHandler.h:306
#define ACCEL2SPEED(x)
Definition SUMOTime.h:54
#define SIMTIME
Definition SUMOTime.h:65
#define SPEED2ACCEL(x)
Definition SUMOTime.h:56
@ SUMO_TAG_CFM_VARIABLES
@ SUMO_ATTR_GCC_GAIN_SPEED
@ SUMO_ATTR_GC_GAIN_SPACE
@ SUMO_ATTR_CA_GAIN_SPACE
@ SUMO_ATTR_CA_OVERRIDE
@ SUMO_ATTR_GCC_GAIN_SPACE
@ SUMO_ATTR_COLLISION_MINGAP_FACTOR
@ SUMO_ATTR_CA_GAIN_SPEED
@ SUMO_ATTR_APPLYDRIVERSTATE
@ SUMO_ATTR_ID
@ SUMO_ATTR_GC_GAIN_SPEED
@ SUMO_ATTR_SC_GAIN
@ SUMO_ATTR_STATE
The state of a link.
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)
void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the vehicle variables from the given description.
int ACC_ControlMode
The vehicle's ACC control mode. 0 for speed control and 1 for gap control.
void saveState(OutputDevice &out, const MSCFModel &cfm) const
Saves the vehicle variables.
The ACC car-following model.
double accelSpeedControl(double vErr) const
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 myCollisionAvoidanceGainSpeed
double myCollisionAvoidanceGainSpace
double myGapControlGainSpace
double interactionGap(const MSVehicle *const, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
double stopSpeed(const MSVehicle *const veh, const double speed, double gap2pred, double decel, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
double accelGapControl(const MSVehicle *const veh, const double gap2pred, const double speed, const double predSpeed, double vErr) const
double myGapClosingControlGainSpeed
double insertionFollowSpeed(const MSVehicle *const v, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const
Computes the vehicle's acceptable speed at insertion.
double myGapControlGainSpeed
double getSecureGap(const MSVehicle *const veh, const MSVehicle *const pred, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the a gap such that the gap mode acceleration of the follower is zero.
~MSCFModel_ACC()
Destructor.
MSCFModel_ACC(const MSVehicleType *vtype)
Constructor.
double myEmergencyThreshold
MSCFModel * duplicate(const MSVehicleType *vtype) const
Duplicates the car-following model.
double _v(const MSVehicle *const veh, const double gap2pred, const double mySpeed, const double predSpeed, const double desSpeed, const bool respectMinGap=true) const
double myApplyDriverstate
double myGapClosingControlGainSpace
double mySpeedControlGain
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.
void applyHeadwayPerceptionError(const MSVehicle *const veh, double speed, double &gap) const
Overwrites gap by the perceived value obtained from the vehicle's driver state.
void applyHeadwayAndSpeedDifferencePerceptionErrors(const MSVehicle *const veh, double speed, double &gap, double &predSpeed, double predMaxDecel, const MSVehicle *const pred) const
Overwrites gap2pred and predSpeed by the perceived values obtained from the vehicle's driver state,...
double maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion=false) const
Returns the maximum safe velocity for following the given leader.
CalcReason
What the return value of stop/follow/free-Speed is used for.
Definition MSCFModel.h:95
@ FUTURE
the return value is used for calculating future speeds
Definition MSCFModel.h:99
double myCollisionMinGapFactor
The factor of minGap that must be maintained to avoid a collision event.
Definition MSCFModel.h:768
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 myHeadwayTime
The driver's desired time headway (aka reaction time tau) [s].
Definition MSCFModel.h:771
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:603
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:199
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
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
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
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:74
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.
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.
double getCFParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
#define DEBUG_COND