48#define EST_REAC_THRESHOLD 3.
49#define ClutchEngageSpeed 0.5
50#define EIDM_POS_ACC_EPS 0.05
77 WRITE_WARNINGF(
"CarFollowModel EIDM is not compatible with actionStepLength % in vType '%'", STEPS2TIME(vtype->getActionStepLength()), vtype->getID());
122 x = (-b + sqrt(b * b - 4.*a * c)) / (2.*a);
132 if (origSafeDecel >
myDecel + NUMERICAL_EPS) {
139#ifdef DEBUG_EMERGENCYDECEL
141 std::cout <<
SIMTIME <<
" initial vsafe=" << x
142 <<
" egoSpeed=" << egoSpeed <<
" (origSafeDecel=" << origSafeDecel <<
")"
143 <<
" predSpeed=" << predSpeed <<
" (predDecel=" << predMaxDecel <<
")"
144 <<
" safeDecel=" << safeDecel
151 safeDecel =
MIN2(safeDecel, origSafeDecel);
157#ifdef DEBUG_EMERGENCYDECEL
159 std::cout <<
" -> corrected emergency deceleration: " << safeDecel << std::endl;
166 assert(!std::isnan(x));
174 const double g = gap - NUMERICAL_EPS;
189 vsafe = (-b + sqrt(b * b - 4.*a * c)) / (2.*a);
217 const double intensity =
MIN3(Accel_vMax, 1.5,
MAX2(vMax - 0.5 * Accel_vMax, 0.0));
218 const double criticality =
MIN2(
MAX2(s / vars->
mys_est - 0.5, -0.4), 0.0);
220 const double drivingerror =
mySigmaerror * vars->
myw_error * intensity * (2.75 * 2.75 * criticality * criticality + 1.0);
235 if (newSpeed == 0 || newSpeed <= currentSpeed) {
239 double remainingDelay = 0.0;
240 if (newSpeed != vMax) {
244 double v_corr = currentSpeed;
259 v_corr = v_corr + (newSpeed - currentSpeed) /
myIterations;
271 const double oldV = veh->
getSpeed();
278 for (
auto it = vars->
stop.cbegin(); it != vars->
stop.cend(); ++it) {
279 if (vPos > oldV +
ACCEL2SPEED(it->first) - NUMERICAL_EPS && vPos < oldV +
ACCEL2SPEED(it->first) + NUMERICAL_EPS) {
293 vMax =
MAX2(vMin, vMax);
298 <<
" EIDM::finalizeSpeed "
299 <<
" veh=" << veh->
getID()
302 <<
" _vPos=" << _vPos
303 <<
" vStop=" << vStop
304 <<
" vMinEmergency=" << vMinEmergency
329 }
else if (vNext <= oldV && vNext < vMax - NUMERICAL_EPS && oldV >
ClutchEngageSpeed * 2) {
354 vNext =
MAX2(vNext, vMin);
369 <<
" EIDM::finalizeSpeed (2) "
370 <<
" veh=" << veh->
getID()
373 <<
" addTime=" << addTime
374 <<
" vDelay=" << vDelay
376 <<
" vNext=" << vNext
401 <<
" EIDM::finalizeSpeed (3) "
402 <<
" veh=" << veh->
getID()
403 <<
" vars->myw_gap=" << vars->
myw_gap
404 <<
" vars->myw_speed=" << vars->
myw_speed
405 <<
" vars->myw_error=" << vars->
myw_error
406 <<
" vars->lastacc=" << vars->
lastacc
465 <<
" EIDM::followSpeed "
466 <<
" veh=" << veh->
getID()
467 <<
" speed=" << speed
468 <<
" gap2pred=" << gap2pred
469 <<
" predSpeed=" << predSpeed
470 <<
" vars->v0_int=" << vars->
v0_int
476 double result =
_v(veh, gap2pred, speed, predSpeed, vars->
v0_int,
true,
update, _vUsage);
504 <<
" EIDM::stopSpeed "
505 <<
" veh=" << veh->
getID()
506 <<
" speed=" << speed
508 <<
" vars->v0_int=" << vars->
v0_int
514 double result =
_v(veh, gap, speed, 0, vars->
v0_int,
false,
update, _vUsage);
524MSCFModel_EIDM::freeSpeed(
const double currentSpeed,
const double decel,
const double dist,
const double targetSpeed,
const bool onInsertion) {
540 const double y =
MAX2(0.0, ((sqrt((b + 2.0 * v) * (b + 2.0 * v) + 8.0 * b * dist) - b) * 0.5 - v) / b);
541 const double yFull = floor(y);
542 const double exactGap = (yFull * yFull + yFull) * 0.5 * b + yFull * v + (y > yFull ? v : 0.0);
543 const double fullSpeedGain = (yFull + (onInsertion ? 1. : 0.)) *
ACCEL2SPEED(decel);
544 return DIST2SPEED(
MAX2(0.0, dist - exactGap) / (yFull + 1)) + fullSpeedGain + targetSpeed;
559 assert(currentSpeed >= 0);
560 assert(targetSpeed >= 0);
562 const double dt = onInsertion ? 0 :
TS;
563 const double v0 = currentSpeed;
564 const double vT = targetSpeed;
565 const double b = decel;
566 const double d = dist - NUMERICAL_EPS;
575 if (0.5 * (v0 + vT)*dt >= d) {
579 const double q = ((dt * v0 - 2 * d) * b - vT * vT);
580 const double p = 0.5 * b * dt;
581 return -p + sqrt(p * p - q);
610 <<
" EIDM::freeSpeed "
611 <<
" veh=" << veh->
getID()
612 <<
" speed=" << speed
614 <<
" maxSpeed=" << maxSpeed
616 <<
" onInsertion=" << onInsertion
629 double vSafe, remaining_time, targetDecel;
643 targetDecel = (speed - maxSpeed) / remaining_time;
676 vSafe =
_v(veh, 500., speed, maxSpeed, vars->
v0_int,
true,
update, _vUsage);
690 const double vNext = veh->
getSpeed() + acc;
691 const double gap = (vNext - vL) * (veh->
getSpeed() + vL) / (2 *
myDecel) + vL;
703 const double delta_v = speed - leaderSpeed;
720 const double delta_v = speed - leaderSpeed;
726 if (speed <= vars->v0_int) {
727 erg = sqrt((s * s) / (
MAX2(targetDecel / Accel_speed + 1.0, 1.0)));
730 erg = sqrt((s * s) / (
MAX2(targetDecel / Accel_speed + 1.0 + a_free / Accel_speed, 1.0)));
741 double v_limcurr, v_limprev;
748 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*veh, view, *lane, bestLaneConts);
751 bool activeGLOSA =
false;
764 double speedlim = 200;
804 if ((*link)->getViaLane() ==
nullptr) {
807 lane = (*link)->getViaLaneOrLane();
822 if (!(v_limprev < v0 + NUMERICAL_EPS && v_limprev > v0 - NUMERICAL_EPS) ||
823 (v_limprev < v0 + NUMERICAL_EPS && v_limprev > v0 - NUMERICAL_EPS && !(v_limprev < v_limcurr + NUMERICAL_EPS && v_limprev > v_limcurr - NUMERICAL_EPS))) {
825 if ((v_limcurr < v_limprev + NUMERICAL_EPS && v_limcurr < v0 + NUMERICAL_EPS && v_limprev > v0 - NUMERICAL_EPS) ||
826 (v_limcurr > v_limprev - NUMERICAL_EPS && v_limcurr > v0 - NUMERICAL_EPS && v_limprev < v0 + NUMERICAL_EPS)) {
829 if (v_limcurr >= v0 - NUMERICAL_EPS) {
837 if (v_limcurr < v0 + NUMERICAL_EPS && v_limcurr > v0 - NUMERICAL_EPS) {
845 }
else if (!(v_limprev < v0 + NUMERICAL_EPS && v_limprev > v0 - NUMERICAL_EPS) ||
846 (v_limprev < v0 + NUMERICAL_EPS && v_limprev > v0 - NUMERICAL_EPS && !(v_limprev < v_limcurr + NUMERICAL_EPS && v_limprev > v_limcurr - NUMERICAL_EPS))) {
848 if ((v_limcurr < v_limprev + NUMERICAL_EPS && v_limcurr < v0 + NUMERICAL_EPS && v_limprev > v0 - NUMERICAL_EPS) ||
849 (v_limcurr > v_limprev - NUMERICAL_EPS && v_limcurr > v0 - NUMERICAL_EPS && v_limprev < v0 + NUMERICAL_EPS)) {
852 if (v_limcurr >= v0 - NUMERICAL_EPS) {
860 if (v_limcurr < v0 + NUMERICAL_EPS && v_limcurr > v0 - NUMERICAL_EPS) {
871 const double predSpeed,
const double desSpeed,
const bool respectMinGap,
const int update,
const CalcReason usage)
const {
873 double v0 =
MAX2(NUMERICAL_EPS, desSpeed);
885 double wantedacc = 0., a_free;
886 double wouldacc = 0., woulds, woulda_free;
888 double estSpeed, estleaderSpeed, estGap;
889 double current_estSpeed, current_estGap, current_estleaderSpeed;
892 double a_leader = NUMERICAL_EPS;
893 double newSpeed = egoSpeed;
894 bool lastrespectMinGap = respectMinGap;
900 current_gap =
MAX2(NUMERICAL_EPS, gap2pred +
MAX2(NUMERICAL_EPS,
myType->getMinGap() - 0.25));
903 current_gap =
MAX2(NUMERICAL_EPS, gap2pred + minGapStop_EPS);
906 double newGap = current_gap;
911 current_estSpeed = newSpeed;
917 current_estleaderSpeed = predSpeed;
920 current_estGap = newGap;
930 estSpeed = current_estSpeed;
931 estleaderSpeed = current_estleaderSpeed;
932 estGap = current_estGap;
942 if (lastrespectMinGap) {
954 estSpeed = current_estSpeed;
955 estleaderSpeed = current_estleaderSpeed;
956 estGap = current_estGap;
966 double s =
MAX2(0., estSpeed * headwayTime + estSpeed * (estSpeed - estleaderSpeed) / (2 * sqrt(Accel_estSpeed *
myDecel)));
967 if (lastrespectMinGap) {
975 if (lastrespectMinGap) {
1003 if (estSpeed <= v0) {
1004 a_free = Accel_estSpeed * (1. - pow(estSpeed / v0,
myDelta));
1006 wantedacc = Accel_estSpeed * (1. - (s * s) / (estGap * estGap));
1008 wantedacc = a_free * (1. - pow(s / estGap, 2 * Accel_estSpeed / a_free));
1013 wantedacc = a_free + Accel_estSpeed * (1. - (s * s) / (estGap * estGap));
1023 woulds =
MAX2(0., current_estSpeed * headwayTime + current_estSpeed * (current_estSpeed - current_estleaderSpeed) / (2 * sqrt(Accel_current_estSpeed *
myDecel)));
1024 if (respectMinGap) {
1030 if (current_estSpeed <= v0) {
1031 woulda_free = Accel_current_estSpeed * (1. - pow(current_estSpeed / v0,
myDelta));
1032 if (woulds >= current_estGap) {
1033 wouldacc = Accel_current_estSpeed * (1. - (woulds * woulds) / (current_estGap * current_estGap));
1035 wouldacc = woulda_free * (1. - pow(woulds / current_estGap, 2 * Accel_current_estSpeed / woulda_free));
1038 woulda_free = -
myDecel * (1. - pow(v0 / current_estSpeed, Accel_current_estSpeed *
myDelta /
myDecel));
1039 if (woulds >= current_estGap) {
1040 wouldacc = woulda_free + Accel_current_estSpeed * (1. - (woulds * woulds) / (current_estGap * current_estGap));
1042 wouldacc = woulda_free;
1054 double calc_gap = estGap;
1067 if (estSpeed <= v0) {
1068 a_free = Accel_estSpeed * (1. - pow(estSpeed / v0,
myDelta));
1069 if (s >= calc_gap) {
1070 acc = Accel_estSpeed * (1. - (s * s) / (calc_gap * calc_gap));
1072 acc = a_free * (1. - pow(s / calc_gap, 2 * Accel_estSpeed / a_free));
1076 if (s >= calc_gap) {
1077 acc = a_free + Accel_estSpeed * (1. - (s * s) / (calc_gap * calc_gap));
1089 if (leader !=
nullptr && lastrespectMinGap && estleaderSpeed >= SPEED_EPS) {
1092 if (estGap > s * 3 / 2) {
1093 a_leader = a_leader * (s * 3 / 2) / estGap;
1098 if (estleaderSpeed < SPEED_EPS) {
1099 estleaderSpeed = SPEED_EPS;
1105 if (estleaderSpeed * (estSpeed - estleaderSpeed) <= -2 * estGap * a_leader) {
1106 a_cah = (estSpeed * estSpeed * a_leader) / (estleaderSpeed * estleaderSpeed - 2 * estGap * a_leader);
1108 if (estSpeed - estleaderSpeed >= 0) {
1109 a_cah = a_leader - ((estSpeed - estleaderSpeed) * (estSpeed - estleaderSpeed)) / (2 * estGap);
1155 <<
" veh=" << veh->
getID()
1156 <<
" vars->minaccel=" << vars->
minaccel
1158 <<
" vars->myv_est_l=" << vars->
myv_est_l
1159 <<
" vars->myv_est=" << vars->
myv_est
1160 <<
" vars->mys_est=" << vars->
mys_est
1161 <<
" vars->wouldacc=" << vars->
wouldacc
1162 <<
" vars->realacc=" << vars->
realacc
1166 <<
" veh=" << veh->
getID()
1167 <<
" newSpeed=" << newSpeed
1168 <<
" newGap=" << newGap
1169 <<
" predSpeed=" << predSpeed
1170 <<
" estSpeed=" << estSpeed
1171 <<
" estleaderSpeed=" << estleaderSpeed
1172 <<
" estGap=" << estGap
1173 <<
" wantedacc=" << wantedacc
1174 <<
" wouldacc=" << wouldacc
1216 vars->
stop.push_back(std::make_pair(acc, gap2pred));
1219 return MAX2(0., newSpeed);
#define EMERGENCY_DECEL_AMPLIFIER
#define ClutchEngageSpeed
#define EST_REAC_THRESHOLD
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ TURN
The link is a 180 degree turn.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ TURN_LEFTHAND
The link is a 180 degree turn (left-hand network).
@ PARTRIGHT
The link is a partial right direction.
@ NODIR
The link has no direction (is a dead end link).
@ SUMO_ATTR_CF_EIDM_T_ACC_MAX
@ SUMO_ATTR_CF_EIDM_EPSILON_ACC
@ SUMO_ATTR_CF_EIDM_T_LOOK_AHEAD
@ SUMO_ATTR_CF_EIDM_USEVEHDYNAMICS
@ SUMO_ATTR_CF_EIDM_C_COOLNESS
@ SUMO_ATTR_CF_EIDM_SIG_ERROR
@ SUMO_ATTR_CF_EIDM_T_REACTION
@ SUMO_ATTR_CF_EIDM_T_PERSISTENCE_ESTIMATE
@ SUMO_ATTR_CF_EIDM_SIG_GAP
@ SUMO_ATTR_CF_EIDM_JERK_MAX
@ SUMO_ATTR_CF_IDM_STEPPING
@ SUMO_ATTR_COLLISION_MINGAP_FACTOR
@ SUMO_ATTR_CF_EIDM_M_FLATNESS
@ SUMO_ATTR_CF_EIDM_M_BEGIN
@ SUMO_ATTR_CF_EIDM_T_PERSISTENCE_DRIVE
@ SUMO_ATTR_CF_EIDM_SIG_LEADER
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
virtual double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel)=0
Called to adapt the speed in order to allow a lane change. It uses information on LC-related desired ...
virtual bool isSelected() const
whether this vehicle is selected in the GUI
double getChosenSpeedFactor() const
Returns the precomputed factor by which the driver wants to be faster than the speed limit.
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists, nullptr otherwise.
std::vector< std::pair< double, double > > stop
const double myTPersEstimate
double patchSpeedBeforeLCEIDM(const MSVehicle *veh, double vMin, double vMax, const VehicleVariables *vars) const
Applies dawdling / driving error.
const double myTPersDrive
const bool myUseVehDynamics
~MSCFModel_EIDM()
Destructor.
const double mySigmaleader
const double myEpsilonacc
double slowToStartTerm(MSVehicle *const veh, const double newSpeed, const double currentSpeed, const double vMax, VehicleVariables *vars) const
double maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion=false, const CalcReason usage=CalcReason::CURRENT) const
Returns the maximum safe velocity for following the given leader.
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1) const
Returns the maximum next velocity for stopping within gap.
double insertionFollowSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const
Computes the vehicle's safe speed (no dawdling) This method is used during the insertion stage....
double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences.
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.
MSCFModel_EIDM(const MSVehicleType *vtype)
Constructor.
double insertionStopSpeed(const MSVehicle *const veh, double speed, double gap) const
Computes the vehicle's safe speed for approaching an obstacle at insertion without constraints due to...
double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed without a leader.
double internalsecuregap(const MSVehicle *const veh, const double speed, const double leaderSpeed, const double targetDecel) 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.
void internalspeedlimit(MSVehicle *const veh, const double oldV) const
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).
MSCFModel * duplicate(const MSVehicleType *vtype) const
Duplicates the car-following model.
double interactionGap(const MSVehicle *const, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
const double mySigmaerror
double _v(const MSVehicle *const veh, const double gap2pred, const double mySpeed, const double predSpeed, const double desSpeed, const bool respectMinGap, const int update, const CalcReason usage) const
The car-following model abstraction.
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
virtual double getCurrentAccel(const double speed) const
Get the vehicle type's maximum acceleration [m/s^2].
virtual double minNextSpeedEmergency(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed after emergency braking, given the current speed (depends on the numerical ...
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
try to get the given parameter for this carFollowingModel
virtual double applyStartupDelay(const MSVehicle *veh, const double vMin, const double vMax, const SUMOTime addTime=0) const
apply speed adaptation on startup
double getEmergencyDecel() const
Get the vehicle type's maximal physically possible deceleration [m/s^2].
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
SUMOTime myStartupDelay
The startup delay after halting [s].
double myEmergencyDecel
The vehicle's maximum emergency deceleration [m/s^2].
CalcReason
What the return value of stop/follow/free-Speed is used for.
@ FUTURE
the return value is used for calculating future speeds
@ LANE_CHANGE
the return value is used for lane change calculations
@ CURRENT
the return value is used for calculating the next speed
@ CURRENT_WAIT
the return value is used for calculating junction stop speeds
double myCollisionMinGapFactor
The factor of minGap that must be maintained to avoid a collision event.
double calculateEmergencyDeceleration(double gap, double egoSpeed, double predSpeed, double predMaxDecel) const
Returns the minimal deceleration for following the given leader safely.
MSCFModel(const MSVehicleType *vtype)
Constructor.
double myDecel
The vehicle's maximum deceleration [m/s^2].
const MSVehicleType * myType
The type to which this model definition belongs to.
double maximumSafeStopSpeedBallistic(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1) const
Returns the maximum next velocity for stopping within gap when using the ballistic positional update.
double myHeadwayTime
The driver's desired time headway (aka reaction time tau) [s].
A device which collects info on the vehicle trip (mainly on departure and arrival).
bool isSpeedAdviceActive() const
Returns if the GLOSA device is currently changing the speedFactor.
double getOriginalSpeedFactor() const
Returns the precomputed, original factor by which the driver wants to be faster than the speed limit.
static bool gSemiImplicitEulerUpdate
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Representation of a lane in the micro simulation.
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
double getLength() const
Returns the lane's length.
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Representation of a vehicle in the micro simulation.
SUMOTime getTimeSinceStartup() const
Returns the SUMOTime spent driving since startup (speed was larger than 0.1m/s).
MSAbstractLaneChangeModel & getLaneChangeModel()
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
const MSLane * getLane() const
Returns the lane the vehicle is on.
double getSpeed() const
Returns the vehicle's current speed.
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
double getPositionOnLane() const
Get the vehicle's position along the lane.
MSCFModel::VehicleVariables * getCarFollowVariables() const
Returns the vehicle's car following model variables.
std::pair< const MSVehicle *const, double > getLeader(double dist=0, bool considerFoes=true) const
Returns the leader of the vehicle looking for a fixed distance.
The car-following model and parameter.
const SUMOVTypeParameter & getParameter() const
SUMOTime getActionStepLength() const
Returns this type's default action step length.
const std::string & getID() const
Returns the id.
static double randNorm(double mean, double variance, SumoRNG *rng=nullptr)
Access to a random number from a normal distribution.