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// ===========================================================================
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;
264 if (vars->lastUpdateTime != MSNet::getInstance()->getCurrentTimeStep()) {
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.
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.
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
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
MSCFModel(const MSVehicleType *vtype)
Constructor.
Definition MSCFModel.cpp:55
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: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.
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 DEBUG_COND