LCOV - code coverage report
Current view: top level - src/microsim/cfmodels - MSCFModel.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 88.2 % 355 313
Test Date: 2026-06-15 15:46:12 Functions: 88.1 % 42 37

            Line data    Source code
       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              : /****************************************************************************/
      14              : /// @file    MSCFModel.cpp
      15              : /// @author  Tobias Mayer
      16              : /// @author  Daniel Krajzewicz
      17              : /// @author  Jakob Erdmann
      18              : /// @author  Michael Behrisch
      19              : /// @author  Laura Bieker
      20              : /// @author  Leonhard Lücken
      21              : /// @date    Mon, 27 Jul 2009
      22              : ///
      23              : // The car-following model abstraction
      24              : /****************************************************************************/
      25              : #include <config.h>
      26              : 
      27              : #include <cmath>
      28              : #include <microsim/MSGlobals.h>
      29              : #include <microsim/MSVehicleType.h>
      30              : #include <microsim/MSVehicle.h>
      31              : #include <microsim/MSNet.h>
      32              : #include <microsim/MSLane.h>
      33              : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
      34              : #include <microsim/MSDriverState.h>
      35              : #include "MSCFModel.h"
      36              : 
      37              : // ===========================================================================
      38              : // DEBUG constants
      39              : // ===========================================================================
      40              : //#define DEBUG_FINALIZE_SPEED
      41              : //#define DEBUG_DRIVER_ERRORS
      42              : //#define DEBUG_EMERGENCYDECEL
      43              : //#define DEBUG_COND (true)
      44              : #define DEBUG_COND (veh->isSelected())
      45              : //#define DEBUG_COND (veh->getID() == "follower")
      46              : //#define DEBUG_COND2 (SIMTIME == 176)
      47              : //#define DEBUG_COND2 (true)
      48              : #define DEBUG_COND2 (gDebugFlag1)
      49              : 
      50              : 
      51              : 
      52              : // ===========================================================================
      53              : // method definitions
      54              : // ===========================================================================
      55       319819 : MSCFModel::MSCFModel(const MSVehicleType* vtype) :
      56       319819 :     myType(vtype),
      57       319819 :     myAccel(vtype->getParameter().getCFParam(SUMO_ATTR_ACCEL, SUMOVTypeParameter::getDefaultAccel(vtype->getParameter().vehicleClass))),
      58       319819 :     myDecel(vtype->getParameter().getCFParam(SUMO_ATTR_DECEL, SUMOVTypeParameter::getDefaultDecel(vtype->getParameter().vehicleClass))),
      59       319819 :     myEmergencyDecel(vtype->getParameter().getCFParam(SUMO_ATTR_EMERGENCYDECEL,
      60       319819 :                      SUMOVTypeParameter::getDefaultEmergencyDecel(vtype->getParameter().vehicleClass, myDecel, MSGlobals::gDefaultEmergencyDecel))),
      61       319819 :     myApparentDecel(vtype->getParameter().getCFParam(SUMO_ATTR_APPARENTDECEL, myDecel)),
      62       319819 :     myCollisionMinGapFactor(vtype->getParameter().getCFParam(SUMO_ATTR_COLLISION_MINGAP_FACTOR, 1)),
      63       319819 :     myHeadwayTime(vtype->getParameter().getCFParam(SUMO_ATTR_TAU, 1.0)),
      64       319819 :     myStartupDelay(TIME2STEPS(vtype->getParameter().getCFParam(SUMO_ATTR_STARTUP_DELAY, 0.0))),
      65       319819 :     myMaxAccelProfile(vtype->getParameter().getCFProfile(SUMO_ATTR_MAXACCEL_PROFILE, SUMOVTypeParameter::getDefaultMaxAccelProfile(vtype->getParameter().vehicleClass, myAccel))),
      66       639638 :     myDesAccelProfile(vtype->getParameter().getCFProfile(SUMO_ATTR_DESACCEL_PROFILE, SUMOVTypeParameter::getDefaultDesAccelProfile(vtype->getParameter().vehicleClass, myAccel)))
      67       319819 : { }
      68              : 
      69              : 
      70       315936 : MSCFModel::~MSCFModel() {}
      71              : 
      72              : 
      73        45619 : MSCFModel::VehicleVariables::~VehicleVariables() {}
      74              : 
      75              : void
      76           10 : MSCFModel::VehicleVariables::saveState(OutputDevice& /* out */, const MSCFModel& cfm) const {
      77           20 :     WRITE_WARNINGF(TL("carFollowModel of vType '%' cannot save state"), cfm.myType->getID());
      78           10 : }
      79              : 
      80              : 
      81              : void
      82            0 : MSCFModel::VehicleVariables::loadState(const SUMOSAXAttributes& /* attrs */) {
      83            0 : }
      84              : 
      85              : 
      86              : double
      87  13199836301 : MSCFModel::brakeGap(const double speed, const double decel, const double headwayTime) const {
      88  13199836301 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
      89  12159153227 :         return brakeGapEuler(speed, decel, headwayTime);
      90              :     } else {
      91              :         // ballistic
      92   1040683074 :         if (speed <= 0) {
      93              :             return 0.;
      94              :         } else {
      95    861556697 :             return speed * (headwayTime + 0.5 * speed / decel);
      96              :         }
      97              :     }
      98              : }
      99              : 
     100              : 
     101              : double
     102  12163471180 : MSCFModel::brakeGapEuler(const double speed, const double decel, const double headwayTime) {
     103              :     /* one possibility to speed this up is to calculate speedReduction * steps * (steps+1) / 2
     104              :        for small values of steps (up to 10 maybe) and store them in an array */
     105  12163471180 :     const double speedReduction = ACCEL2SPEED(decel);
     106  12163471180 :     const int steps = int(speed / speedReduction);
     107  12163471180 :     return SPEED2DIST(steps * speed - speedReduction * steps * (steps + 1) / 2) + speed * headwayTime;
     108              : }
     109              : 
     110              : 
     111              : double
     112    847133507 : MSCFModel::freeSpeed(const double currentSpeed, const double decel, const double dist, const double targetSpeed, const bool onInsertion, const double actionStepLength) {
     113              :     // XXX: (Leo) This seems to be exclusively called with decel = myDecel (max deceleration) and is not overridden
     114              :     // by any specific CFModel. That may cause undesirable hard braking (at junctions where the vehicle
     115              :     // changes to a road with a lower speed limit).
     116              : 
     117    847133507 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     118              :         // adapt speed to succeeding lane, no reaction time is involved
     119              :         // when breaking for y steps the following distance g is covered
     120              :         // (drive with v in the final step)
     121              :         // g = (y^2 + y) * 0.5 * b + y * v
     122              :         // y = ((((sqrt((b + 2.0*v)*(b + 2.0*v) + 8.0*b*g)) - b)*0.5 - v)/b)
     123    798165464 :         const double v = SPEED2DIST(targetSpeed);
     124    798165464 :         if (dist < v) {
     125              :             return targetSpeed;
     126              :         }
     127    753614799 :         const double b = ACCEL2DIST(decel);
     128    753614799 :         const double y = MAX2(0.0, ((sqrt((b + 2.0 * v) * (b + 2.0 * v) + 8.0 * b * dist) - b) * 0.5 - v) / b);
     129    753614799 :         const double yFull = floor(y);
     130    753614799 :         const double exactGap = (yFull * yFull + yFull) * 0.5 * b + yFull * v + (y > yFull ? v : 0.0);
     131    753614799 :         const double fullSpeedGain = (yFull + (onInsertion ? 1. : 0.)) * ACCEL2SPEED(decel);
     132   1247017526 :         return DIST2SPEED(MAX2(0.0, dist - exactGap) / (yFull + 1)) + fullSpeedGain + targetSpeed;
     133              :     } else {
     134              :         // ballistic update (Leo)
     135              :         // calculate maximum next speed vN that is adjustable to vT=targetSpeed after a distance d=dist
     136              :         // and given a maximal deceleration b=decel, denote the current speed by v0.
     137              :         // the distance covered by a trajectory that attains vN in the next action step (length=dt) and decelerates afterwards
     138              :         // with b is given as
     139              :         // d = 0.5*dt*(v0+vN) + (t-dt)*vN - 0.5*b*(t-dt)^2, (1)
     140              :         // where time t of arrival at d with speed vT is
     141              :         // t = dt + (vN-vT)/b.  (2)
     142              :         // We insert (2) into (1) to obtain
     143              :         // d = 0.5*dt*(v0+vN) + vN*(vN-vT)/b - 0.5*b*((vN-vT)/b)^2
     144              :         // 0 = (dt*b*v0 - vT*vT - 2*b*d) + dt*b*vN + vN*vN
     145              :         // and solve for vN
     146              : 
     147              :         assert(currentSpeed >= 0);
     148              :         assert(targetSpeed >= 0);
     149              : 
     150     48968043 :         const double dt = onInsertion ? 0 : actionStepLength; // handles case that vehicle is inserted just now (at the end of move)
     151              :         const double v0 = currentSpeed;
     152              :         const double vT = targetSpeed;
     153              :         const double b = decel;
     154     48968043 :         const double d = dist - NUMERICAL_EPS; // prevent returning a value > targetSpeed due to rounding errors
     155              : 
     156              :         // Solvability for positive vN (if d is small relative to v0):
     157              :         // 1) If 0.5*(v0+vT)*dt > d, we set vN=vT.
     158              :         // (In case vT<v0, this implies that on the interpolated trajectory there are points beyond d where
     159              :         //  the interpolated velocity is larger than vT, but at least on the temporal discretization grid, vT is not exceeded)
     160              :         // 2) We ignore the (possible) constraint vN >= v0 - b*dt, which could lead to a problem if v0 - t*b > vT.
     161              :         //    (finalizeSpeed() is responsible for assuring that the next velocity is chosen in accordance with maximal decelerations)
     162              : 
     163              :         // If implied accel a leads to v0 + a*asl < vT, choose acceleration s.th. v0 + a*asl = vT
     164     48968043 :         if (0.5 * (v0 + vT)*dt >= d) {
     165              :             // Attain vT after time asl
     166      1578178 :             return v0 + TS * (vT - v0) / actionStepLength;
     167              :         } else {
     168     47389865 :             const double q = ((dt * v0 - 2 * d) * b - vT * vT); // (q < 0 is fulfilled because of (#))
     169     47389865 :             const double p = 0.5 * b * dt;
     170     47389865 :             const double vN = -p + sqrt(p * p - q); // target speed at time t0+asl
     171     47389865 :             return v0 + TS * (vN - v0) / actionStepLength;
     172              :         }
     173              :     }
     174              : }
     175              : 
     176              : 
     177              : double
     178   3313044772 : MSCFModel::getSecureGap(const MSVehicle* const veh, const MSVehicle* const /*pred*/, const double speed, const double leaderSpeed, const double leaderMaxDecel) const {
     179              :     // The solution approach leaderBrakeGap >= followerBrakeGap is not
     180              :     // secure when the follower can brake harder than the leader because the paths may still cross.
     181              :     // As a workaround we use a value of leaderDecel which errs on the side of caution
     182   3313044772 :     const double maxDecel = MAX2(myDecel, leaderMaxDecel);
     183   3313044772 :     const double bgLeader = brakeGap(leaderSpeed, maxDecel, 0);
     184   3313044772 :     double secureGap = MAX2(0.0, brakeGap(speed, myDecel, myHeadwayTime) - bgLeader);
     185   3313044772 :     if (MSGlobals::gComputeLC && veh->getAcceleration() < -NUMERICAL_EPS) {
     186              :         // vehicle can react instantly in the next step
     187              :         // we only apply 'myHeadWayTime' to avoid sudden braking after lane change
     188              :         // thus we can reduce the required brakeGap if the vehicle is braking anyway
     189              :         // (but we shouldn't assume continued emergency deceleration)
     190    985472729 :         const double secureGapDecel = MAX2(0.0, brakeGap(speed, MIN2(-veh->getAcceleration(), myDecel), 0) - bgLeader);
     191              :         // the secureGapDecel doesn't leave room for lcAssertive behavior
     192    972184918 :         secureGap = MIN2(secureGap, secureGapDecel / veh->getLaneChangeModel().getSafetyFactor());
     193              :     }
     194   3313044772 :     return secureGap;
     195              : }
     196              : 
     197              : 
     198              : double
     199    626912231 : MSCFModel::finalizeSpeed(MSVehicle* const veh, double vPos) const {
     200              :     // save old v for optional acceleration computation
     201    626912231 :     const double oldV = veh->getSpeed();
     202              :     // process stops (includes update of stopping state)
     203    626912231 :     const double vStop = MIN2(vPos, veh->processNextStop(vPos));
     204              :     // apply deceleration bounds
     205    623098030 :     const double vMinEmergency = minNextSpeedEmergency(oldV, veh);
     206              :     // vPos contains the uppper bound on safe speed. allow emergency braking here
     207    623098030 :     const double vMin = MIN2(minNextSpeed(oldV, veh), MAX2(vPos, vMinEmergency));
     208    623098030 :     const double fric = veh->getFriction();
     209              :     // adapt speed limit of road to "perceived" friction
     210    623098030 :     const double factor = fric == 1. ? 1. : -0.3491 * fric * fric + 0.8922 * fric + 0.4493; //2nd degree polyfit
     211              : 
     212              :     // aMax: Maximal admissible acceleration until the next action step, such that the vehicle's maximal
     213              :     // desired speed on the current lane will not be exceeded when the
     214              :     // acceleration is maintained until the next action step.
     215   1246196060 :     double aMax = (MAX2(veh->getLane()->getVehicleMaxSpeed(veh), vPos) * factor - oldV) / veh->getActionStepLengthSecs();
     216              :     // apply planned speed constraints and acceleration constraints
     217    623098030 :     double vMax = MIN3(oldV + ACCEL2SPEED(aMax), maxNextSpeed(oldV, veh), vStop);
     218              :     // do not exceed max decel even if it is unsafe
     219              : #ifdef _DEBUG
     220              :     //if (vMin > vMax) {
     221              :     //    WRITE_WARNINGF(TL("Maximum speed of vehicle '%' is lower than the minimum speed (min: %, max: %)."), veh->getID(), toString(vMin), toString(vMax));
     222              :     //}
     223              : #endif
     224              : 
     225              : #ifdef DEBUG_FINALIZE_SPEED
     226              :     if (DEBUG_COND) {
     227              :         std::cout << "\n" << SIMTIME << " FINALIZE_SPEED\n";
     228              :     }
     229              : #endif
     230              : 
     231              :     vMax = MAX2(vMin, vMax);
     232    623098030 :     double vNext = patchSpeedBeforeLC(veh, vMin, vMax);
     233              : #ifdef DEBUG_FINALIZE_SPEED
     234              :     double vDawdle = vNext;
     235              : #endif
     236              :     assert(vNext >= vMin);
     237              :     assert(vNext <= vMax);
     238              :     // apply lane-changing related speed adaptations
     239    623098030 :     vNext = veh->getLaneChangeModel().patchSpeed(vMin, vNext, vMax, *this);
     240              : #ifdef DEBUG_FINALIZE_SPEED
     241              :     double vPatchLC = vNext;
     242              : #endif
     243              :     // apply further speed adaptations
     244    623098030 :     vNext = applyStartupDelay(veh, vMin, vNext);
     245              : 
     246              :     assert(vNext >= vMinEmergency); // stronger braking is permitted in lane-changing related emergencies
     247              :     assert(vNext <= vMax);
     248              : 
     249              : #ifdef DEBUG_FINALIZE_SPEED
     250              :     if (DEBUG_COND) {
     251              :         std::cout << std::setprecision(gPrecision)
     252              :                   << "veh '" << veh->getID() << "' oldV=" << oldV
     253              :                   << " vPos" << vPos
     254              :                   << " vMin=" << vMin
     255              :                   << " aMax=" << aMax
     256              :                   << " vMax=" << vMax
     257              :                   << " vStop=" << vStop
     258              :                   << " vDawdle=" << vDawdle
     259              :                   << " vPatchLC=" << vPatchLC
     260              :                   << " vNext=" << vNext
     261              :                   << "\n";
     262              :     }
     263              : #endif
     264    623098030 :     return vNext;
     265              : }
     266              : 
     267              : 
     268              : double
     269    628861427 : MSCFModel::applyStartupDelay(const MSVehicle* veh, const double vMin, const double vMax, const SUMOTime addTime) const {
     270              :     UNUSED_PARAMETER(vMin);
     271              :     // timeSinceStartup was already incremented by DELTA_T
     272    628861427 :     if (veh->getTimeSinceStartup() > 0 && veh->getTimeSinceStartup() - DELTA_T < myStartupDelay + addTime) {
     273              :         assert(veh->getSpeed() <= SUMO_const_haltingSpeed);
     274        46885 :         const SUMOTime remainingDelay = myStartupDelay + addTime - (veh->getTimeSinceStartup() - DELTA_T);
     275              :         //std::cout << SIMTIME << " applyStartupDelay veh=" << veh->getID() << " remainingDelay=" << remainingDelay << "\n";
     276        46885 :         if (remainingDelay >= DELTA_T) {
     277              :             // delay startup by at least a whole step
     278              :             return 0;
     279              :         } else {
     280              :             // reduce acceleration for fractional startup delay
     281         2899 :             return (double)(DELTA_T - remainingDelay) / (double)DELTA_T * vMax;
     282              :         }
     283              :     }
     284              :     return vMax;
     285              : }
     286              : 
     287              : 
     288              : double
     289            0 : MSCFModel::interpolateProfile(const double speed, const std::vector<std::pair<double, double> > profile) const {
     290              :     double val;
     291              :     // extrapolate, means using the first/last value of the array
     292            0 :     if (speed < profile[0].first) {
     293            0 :         val = profile[0].second;
     294            0 :     } else if (speed > profile.back().first) {
     295            0 :         val = profile.back().second;
     296              :     } else { // interpolate
     297              :         int x = 0;
     298            0 :         while (speed > profile[x + 1].first) {
     299              :             x++;
     300              :         }
     301            0 :         double diff = (profile[x + 1].second - profile[x].second) / (profile[x + 1].first - profile[x].first);
     302            0 :         val = profile[x].second + diff * (speed - profile[x].first);
     303              :     }
     304            0 :     return val;
     305              : }
     306              : 
     307              : 
     308              : double
     309            0 : MSCFModel::interactionGap(const MSVehicle* const veh, double vL) const {
     310              :     // Resolve the vsafe equation to gap. Assume predecessor has
     311              :     // speed != 0 and that vsafe will be the current speed plus acceleration,
     312              :     // i.e that with this gap there will be no interaction.
     313            0 :     const double vNext = MIN2(maxNextSpeed(veh->getSpeed(), veh), veh->getLane()->getVehicleMaxSpeed(veh));
     314            0 :     const double gap = (vNext - vL) *
     315            0 :                        ((veh->getSpeed() + vL) / (2.*myDecel) + myHeadwayTime) +
     316            0 :                        vL * myHeadwayTime;
     317              : 
     318              :     // Don't allow timeHeadWay < deltaT situations.
     319            0 :     return MAX2(gap, SPEED2DIST(vNext));
     320              : }
     321              : 
     322              : 
     323              : double
     324   5156563775 : MSCFModel::maxNextSpeed(double speed, const MSVehicle* const /*veh*/) const {
     325   5156563775 :     return MIN2(speed + (double) ACCEL2SPEED(getCurrentAccel(speed)), myType->getMaxSpeed());
     326              : }
     327              : 
     328              : 
     329              : double
     330   1197629581 : MSCFModel::minNextSpeed(double speed, const MSVehicle* const /*veh*/) const {
     331   1197629581 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     332   1143685178 :         return MAX2(speed - ACCEL2SPEED(myDecel), 0.);
     333              :     } else {
     334              :         // NOTE: ballistic update allows for negative speeds to indicate a stop within the next timestep
     335     53944403 :         return speed - ACCEL2SPEED(myDecel);
     336              :     }
     337              : }
     338              : 
     339              : 
     340              : double
     341    801475374 : MSCFModel::minNextSpeedEmergency(double speed, const MSVehicle* const /*veh*/) const {
     342    801475374 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     343    601283334 :         return MAX2(speed - ACCEL2SPEED(myEmergencyDecel), 0.);
     344              :     } else {
     345              :         // NOTE: ballistic update allows for negative speeds to indicate a stop within the next timestep
     346    200192040 :         return speed - ACCEL2SPEED(myEmergencyDecel);
     347              :     }
     348              : }
     349              : 
     350              : 
     351              : 
     352              : double
     353    847133497 : MSCFModel::freeSpeed(const MSVehicle* const veh, double speed, double seen, double maxSpeed, const bool onInsertion, const CalcReason /*usage*/) const {
     354    847133497 :     if (maxSpeed < 0.) {
     355              :         // can occur for ballistic update (in context of driving at red light)
     356              :         return maxSpeed;
     357              :     }
     358    847133492 :     double vSafe = freeSpeed(speed, myDecel, seen, maxSpeed, onInsertion, veh->getActionStepLengthSecs());
     359    847133492 :     return vSafe;
     360              : }
     361              : 
     362              : 
     363              : double
     364      8027632 : MSCFModel::insertionFollowSpeed(const MSVehicle* const /* v */, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle* const /*pred*/) const {
     365      8027632 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     366      7035182 :         return maximumSafeFollowSpeed(gap2pred, speed, predSpeed, predMaxDecel, true);
     367              :     } else {
     368              :         // NOTE: Even for ballistic update, the current speed is irrelevant at insertion, therefore passing 0. (Leo)
     369       992450 :         return maximumSafeFollowSpeed(gap2pred, 0., predSpeed, predMaxDecel, true);
     370              :     }
     371              : }
     372              : 
     373              : 
     374              : double
     375        65032 : MSCFModel::insertionStopSpeed(const MSVehicle* const veh, double speed, double gap) const {
     376        65032 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     377        60933 :         return stopSpeed(veh, speed, gap, CalcReason::FUTURE);
     378              :     } else {
     379         4099 :         return MIN2(maximumSafeStopSpeed(gap, myDecel, 0., true, 0., false), myType->getMaxSpeed());
     380              :     }
     381              : }
     382              : 
     383              : 
     384              : double
     385       504856 : MSCFModel::followSpeedTransient(double duration, const MSVehicle* const /*veh*/, double /*speed*/, double gap2pred, double predSpeed, double predMaxDecel) const {
     386              :     // minimium distance covered by the leader if braking
     387       504856 :     double leaderMinDist = gap2pred + distAfterTime(duration, predSpeed, -predMaxDecel);
     388              :     // if ego would not brake it could drive with speed leaderMinDist / duration
     389              :     // due to potentential ego braking it can safely drive faster
     390       504856 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     391              :         // number of potential braking steps
     392       427153 :         const int a = (int)ceil(duration / TS - TS);
     393              :         // can we brake for the whole time?
     394       427153 :         if (brakeGap(a * myDecel, myDecel, 0) <= leaderMinDist) {
     395              :             // braking continuously for duration
     396              :             // distance reduction due to braking
     397       351590 :             const double b = TS * getMaxDecel() * 0.5 * (a * a - a);
     398       351590 :             if (gDebugFlag2) std::cout << "    followSpeedTransient"
     399              :                                            << " duration=" << duration
     400              :                                            << " gap=" << gap2pred
     401              :                                            << " leaderMinDist=" << leaderMinDist
     402              :                                            << " decel=" << getMaxDecel()
     403              :                                            << " a=" << a
     404            0 :                                            << " bg=" << brakeGap(a * myDecel, myDecel, 0)
     405              :                                            << " b=" << b
     406            0 :                                            << " x=" << (b + leaderMinDist) / duration
     407            0 :                                            << "\n";
     408       351590 :             return (b + leaderMinDist) / duration;
     409              :         } else {
     410              :             // @todo improve efficiency
     411              :             double bg = 0;
     412              :             double speed = 0;
     413      1492982 :             while (bg < leaderMinDist) {
     414      1417419 :                 speed += ACCEL2SPEED(myDecel);
     415      1417419 :                 bg += SPEED2DIST(speed);
     416              :             }
     417        75563 :             speed -= DIST2SPEED(bg - leaderMinDist);
     418        75563 :             return speed;
     419              :         }
     420              :     } else {
     421              :         // can we brake for the whole time?
     422        77703 :         const double fullBrakingSeconds = sqrt(leaderMinDist * 2 / myDecel);
     423        77703 :         if (fullBrakingSeconds >= duration) {
     424              :             // braking continuously for duration
     425              :             // average speed after braking for duration is x2 = x - 0.5 * duration * myDecel
     426              :             // x2 * duration <= leaderMinDist must hold
     427        61450 :             return leaderMinDist / duration + duration * getMaxDecel() / 2;
     428              :         } else {
     429        16253 :             return fullBrakingSeconds * myDecel;
     430              :         }
     431              :     }
     432              : }
     433              : 
     434              : double
     435       504856 : MSCFModel::distAfterTime(double t, double speed, const double accel) const {
     436       504856 :     if (accel >= 0.) {
     437            0 :         return (speed + 0.5 * accel * t) * t;
     438              :     }
     439       504856 :     const double decel = -accel;
     440       504856 :     if (speed <= decel * t) {
     441              :         // braking to a full stop
     442       334213 :         return brakeGap(speed, decel, 0);
     443              :     }
     444       170643 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     445              :         // @todo improve efficiency
     446              :         double result = 0;
     447       717875 :         while (t > 0) {
     448       572889 :             speed -= ACCEL2SPEED(decel);
     449       572889 :             result += MAX2(0.0, SPEED2DIST(speed));
     450       572889 :             t -= TS;
     451              :         }
     452       144986 :         return result;
     453              :     } else {
     454        25657 :         const double speed2 = speed - t * decel;
     455        25657 :         return 0.5 * (speed + speed2) * t;
     456              :     }
     457              : }
     458              : 
     459              : 
     460              : SUMOTime
     461    864331447 : MSCFModel::getMinimalArrivalTime(double dist, double currentSpeed, double arrivalSpeed) const {
     462    864331447 :     if (dist <= 0.) {
     463              :         return 0;
     464              :     }
     465              :     // will either drive as fast as possible and decelerate as late as possible
     466              :     // or accelerate as fast as possible and then hold that speed
     467              :     arrivalSpeed = MAX2(0.0, arrivalSpeed); // ballistic model may call this with -std::numeric_limits<double>::max()
     468    864176472 :     const double accel = (arrivalSpeed >= currentSpeed) ? getMaxAccel() : -getMaxDecel();
     469    864176472 :     const double accelTime = accel == 0. ? 0. : (arrivalSpeed - currentSpeed) / accel;
     470    864176472 :     const double accelWay = accelTime * (arrivalSpeed + currentSpeed) * 0.5;
     471    864176472 :     if (dist >= accelWay) {
     472    853556015 :         const double nonAccelWay = dist - accelWay;
     473              :         const double nonAccelSpeed = MAX3(currentSpeed, arrivalSpeed, SUMO_const_haltingSpeed);
     474    853556015 :         return TIME2STEPS(accelTime + nonAccelWay / nonAccelSpeed);
     475              :     }
     476              :     // find time x so that
     477              :     // x * (currentSpeed + currentSpeed + x * accel) * 0.5 = dist
     478     10620457 :     return TIME2STEPS(-(currentSpeed - sqrt(currentSpeed * currentSpeed + 2 * accel * dist)) / accel);
     479              : }
     480              : 
     481              : 
     482              : double
     483       296368 : MSCFModel::estimateArrivalTime(double dist, double speed, double maxSpeed, double accel) {
     484              :     assert(speed >= 0.);
     485              :     assert(dist >= 0.);
     486              : 
     487       296368 :     if (dist < NUMERICAL_EPS) {
     488              :         return 0.;
     489              :     }
     490              : 
     491       296368 :     if ((accel < 0. && -0.5 * speed * speed / accel < dist) || (accel <= 0. && speed == 0.)) {
     492              :         // distance will never be covered with these values
     493              :         return INVALID_DOUBLE;
     494              :     }
     495              : 
     496       118268 :     if (fabs(accel) < NUMERICAL_EPS) {
     497       100886 :         return dist / speed;
     498              :     }
     499              : 
     500        17382 :     double p = speed / accel;
     501              : 
     502        17382 :     if (accel < 0.) {
     503              :         // we already know, that the distance will be covered despite breaking
     504        17382 :         return (-p - sqrt(p * p + 2 * dist / accel));
     505              :     }
     506              : 
     507              :     // Here, accel > 0
     508              :     // t1 is the time to use the given acceleration
     509            0 :     double t1 = (maxSpeed - speed) / accel;
     510              :     // distance covered until t1
     511            0 :     double d1 = speed * t1 + 0.5 * accel * t1 * t1;
     512            0 :     if (d1 >= dist) {
     513              :         // dist is covered before changing the speed
     514            0 :         return (-p + sqrt(p * p + 2 * dist / accel));
     515              :     } else {
     516            0 :         return (-p + sqrt(p * p + 2 * d1 / accel)) + (dist - d1) / maxSpeed;
     517              :     }
     518              : 
     519              : }
     520              : 
     521              : double
     522        75834 : MSCFModel::estimateArrivalTime(double dist, double initialSpeed, double arrivalSpeed, double maxSpeed, double accel, double decel) {
     523              :     UNUSED_PARAMETER(arrivalSpeed); // only in assertion
     524              :     UNUSED_PARAMETER(decel); // only in assertion
     525        75834 :     if (dist <= 0) {
     526              :         return 0.;
     527              :     }
     528              : 
     529              :     // stub-assumptions
     530              :     assert(accel == decel);
     531              :     assert(accel > 0);
     532              :     assert(initialSpeed == 0);
     533              :     assert(arrivalSpeed == 0);
     534              :     assert(maxSpeed > 0);
     535              : 
     536              : 
     537        75834 :     double accelTime = (maxSpeed - initialSpeed) / accel;
     538              :     // "ballistic" estimate for the distance covered during acceleration phase
     539        75834 :     double accelDist = accelTime * (initialSpeed + 0.5 * (maxSpeed - initialSpeed));
     540              :     double arrivalTime;
     541        75834 :     if (accelDist >= dist * 0.5) {
     542              :         // maximal speed will not be attained during maneuver
     543         2973 :         arrivalTime = 4 * sqrt(dist / accel);
     544              :     } else {
     545              :         // Calculate time to move with constant, maximal lateral speed
     546        72861 :         const double constSpeedTime = (dist - accelDist * 2) / maxSpeed;
     547        72861 :         arrivalTime = accelTime + constSpeedTime;
     548              :     }
     549              :     return arrivalTime;
     550              : }
     551              : 
     552              : 
     553              : double
     554       748810 : MSCFModel::avoidArrivalAccel(double dist, double time, double speed, double maxDecel) {
     555              :     assert(time > 0 || dist == 0);
     556       748810 :     if (dist <= 0) {
     557          602 :         return -maxDecel;
     558       748208 :     } else if (time * speed > 2 * dist) {
     559              :         // stop before dist is necessary. We need
     560              :         //            d = v*v/(2*a)
     561         5835 :         return - 0.5 * speed * speed / dist;
     562              :     } else {
     563              :         // we seek the solution a of
     564              :         //            d = v*t + a*t*t/2
     565       742373 :         return 2 * (dist / time - speed) / time;
     566              :     }
     567              : }
     568              : 
     569              : 
     570              : double
     571      2714457 : MSCFModel::getMinimalArrivalSpeed(double dist, double currentSpeed) const {
     572              :     // ballistic update
     573      2714457 :     return estimateSpeedAfterDistance(dist - currentSpeed * getHeadwayTime(), currentSpeed, -getMaxDecel());
     574              : }
     575              : 
     576              : 
     577              : double
     578     54011606 : MSCFModel::getMinimalArrivalSpeedEuler(double dist, double currentSpeed) const {
     579              :     double arrivalSpeedBraking;
     580              :     // Because we use a continuous formula for computing the possible slow-down
     581              :     // we need to handle the mismatch with the discrete dynamics
     582     54011606 :     if (dist < currentSpeed) {
     583              :         arrivalSpeedBraking = INVALID_SPEED; // no time left for braking after this step
     584              :         //      (inserted max() to get rid of arrivalSpeed dependency within method) (Leo)
     585     27049858 :     } else if (2 * (dist - currentSpeed * getHeadwayTime()) * -getMaxDecel() + currentSpeed * currentSpeed >= 0) {
     586     27048422 :         arrivalSpeedBraking = estimateSpeedAfterDistance(dist - currentSpeed * getHeadwayTime(), currentSpeed, -getMaxDecel());
     587              :     } else {
     588              :         arrivalSpeedBraking = getMaxDecel();
     589              :     }
     590     54011606 :     return arrivalSpeedBraking;
     591              : }
     592              : 
     593              : 
     594              : 
     595              : 
     596              : double
     597     25415558 : MSCFModel::gapExtrapolation(const double duration, const double currentGap, double v1,  double v2, double a1, double a2, const double maxV1, const double maxV2) {
     598              : 
     599              :     double newGap = currentGap;
     600              : 
     601     25415558 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     602     20760635 :         for (unsigned int steps = 1; steps * TS <= duration; ++steps) {
     603            0 :             v1 = MIN2(MAX2(v1 + a1, 0.), maxV1);
     604            0 :             v2 = MIN2(MAX2(v2 + a2, 0.), maxV2);
     605            0 :             newGap += TS * (v1 - v2);
     606              :         }
     607              :     } else {
     608              :         // determine times t1, t2 for which vehicles can break until stop (within duration)
     609              :         // and t3, t4 for which they reach their maximal speed on their current lanes.
     610      4654923 :         double t1 = 0, t2 = 0, t3 = 0, t4 = 0;
     611              : 
     612              :         // t1: ego veh stops
     613      4654923 :         if (a1 < 0 && v1 > 0) {
     614      1533282 :             const double leaderStopTime =  - v1 / a1;
     615      1533282 :             t1 = MIN2(leaderStopTime, duration);
     616      4654923 :         } else if (a1 >= 0) {
     617      3049089 :             t1 = duration;
     618              :         }
     619              :         // t2: veh2 stops
     620      4654923 :         if (a2 < 0 && v2 > 0) {
     621       156128 :             const double followerStopTime = -v2 / a2;
     622       156128 :             t2 = MIN2(followerStopTime, duration);
     623      4654923 :         } else if (a2 >= 0) {
     624      4459046 :             t2 = duration;
     625              :         }
     626              :         // t3: ego veh reaches vMax
     627      4654923 :         if (a1 > 0 && v1 < maxV1) {
     628      1884778 :             const double leaderMaxSpeedTime = (maxV1 - v1) / a1;
     629      1884778 :             t3 = MIN2(leaderMaxSpeedTime, duration);
     630      4654923 :         } else if (a1 <= 0) {
     631      2770145 :             t3 = duration;
     632              :         }
     633              :         // t4: veh2 reaches vMax
     634      4654923 :         if (a2 > 0 && v2 < maxV2) {
     635      1816034 :             const double followerMaxSpeedTime = (maxV2 - v2) / a2;
     636      1816034 :             t4 = MIN2(followerMaxSpeedTime, duration);
     637      4654923 :         } else if (a2 <= 0) {
     638      2838889 :             t4 = duration;
     639              :         }
     640              : 
     641              :         // NOTE: this assumes that the accelerations a1 and a2 are constant over the next
     642              :         //       followerBreakTime seconds (if no vehicle stops before or reaches vMax)
     643              :         std::list<double> l;
     644              :         l.push_back(t1);
     645              :         l.push_back(t2);
     646              :         l.push_back(t3);
     647              :         l.push_back(t4);
     648      4654923 :         l.sort();
     649              :         std::list<double>::const_iterator i;
     650              :         double tLast = 0.;
     651      4879384 :         for (i = l.begin(); i != l.end(); ++i) {
     652      4879384 :             if (*i != tLast) {
     653      2681343 :                 double dt = MIN2(*i, duration) - tLast; // time between *i and tLast
     654      2681343 :                 double dv = v1 - v2; // current velocity difference
     655      2681343 :                 double da = a1 - a2; // current acceleration difference
     656      2681343 :                 newGap += dv * dt + da * dt * dt / 2.; // update gap
     657      2681343 :                 v1 += dt * a1;
     658      2681343 :                 v2 += dt * a2;
     659              :             }
     660      4879384 :             if (*i == t1 || *i == t3) {
     661              :                 // ego veh reached velocity bound
     662              :                 a1 = 0.;
     663              :             }
     664              : 
     665      4879384 :             if (*i == t2 || *i == t4) {
     666              :                 // veh2 reached velocity bound
     667              :                 a2 = 0.;
     668              :             }
     669              : 
     670              :             tLast = MIN2(*i, duration);
     671      4879384 :             if (tLast == duration) {
     672              :                 break;
     673              :             }
     674              :         }
     675              : 
     676      4654923 :         if (duration != tLast) {
     677              :             // (both vehicles have zero acceleration)
     678              :             assert(a1 == 0. && a2 == 0.);
     679            0 :             double dt = duration - tLast; // remaining time until duration
     680            0 :             double dv = v1 - v2; // current velocity difference
     681            0 :             newGap += dv * dt; // update gap
     682              :         }
     683              :     }
     684              : 
     685     25415558 :     return newGap;
     686              : }
     687              : 
     688              : 
     689              : 
     690              : double
     691     53293336 : MSCFModel::passingTime(const double lastPos, const double passedPos, const double currentPos, const double lastSpeed, const double currentSpeed) {
     692              : 
     693              :     assert(passedPos <= currentPos);
     694              :     assert(passedPos >= lastPos);
     695              :     assert(currentPos > lastPos);
     696              :     assert(currentSpeed >= 0);
     697              : 
     698     53293336 :     if (passedPos > currentPos || passedPos < lastPos) {
     699            0 :         std::stringstream ss;
     700              :         // Debug (Leo)
     701            0 :         if (!MSGlobals::gSemiImplicitEulerUpdate) {
     702              :             // NOTE: error is guarded to maintain original test output for euler update (Leo).
     703            0 :             ss << "passingTime(): given argument passedPos = " << passedPos << " doesn't lie within [lastPos, currentPos] = [" << lastPos << ", " << currentPos << "]\nExtrapolating...";
     704            0 :             std::cout << ss.str() << "\n";
     705            0 :             WRITE_ERROR(ss.str());
     706              :         }
     707            0 :         const double lastCoveredDist = currentPos - lastPos;
     708            0 :         const double extrapolated = passedPos > currentPos ? TS * (passedPos - lastPos) / lastCoveredDist : TS * (currentPos - passedPos) / lastCoveredDist;
     709              :         return extrapolated;
     710     53293336 :     } else if (currentSpeed < 0) {
     711            0 :         WRITE_ERROR("passingTime(): given argument 'currentSpeed' is negative. This case is not handled yet.");
     712            0 :         return -1;
     713              :     }
     714              : 
     715     53293336 :     const double distanceOldToPassed = passedPos - lastPos; // assert: >=0
     716              : 
     717     53293336 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     718              :         // euler update (constantly moving with currentSpeed during [0,TS])
     719     51871160 :         if (currentSpeed == 0) {
     720            0 :             return TS;
     721              :         }
     722     51871160 :         const double t = distanceOldToPassed / currentSpeed;
     723     51871160 :         return MIN2(TS, MAX2(0., t)); //rounding errors could give results out of the admissible result range
     724              : 
     725              :     } else {
     726              :         // ballistic update (constant acceleration a during [0,TS], except in case of a stop)
     727              : 
     728              :         // determine acceleration
     729              :         double a;
     730      1422176 :         if (currentSpeed > 0) {
     731              :             // the acceleration was constant within the last time step
     732      1422028 :             a = SPEED2ACCEL(currentSpeed - lastSpeed);
     733              :         } else {
     734              :             // the currentSpeed is zero (the last was not because lastPos<currentPos).
     735              :             assert(currentSpeed == 0 && lastSpeed != 0);
     736              :             // In general the stop has taken place within the last time step.
     737              :             // The acceleration (a<0) is obtained from
     738              :             // deltaPos = - lastSpeed^2/(2*a)
     739          148 :             a = lastSpeed * lastSpeed / (2 * (lastPos - currentPos));
     740              : 
     741              :             assert(a < 0);
     742              :         }
     743              : 
     744              :         // determine passing time t
     745              :         // we solve distanceOldToPassed = lastSpeed*t + a*t^2/2
     746      1422176 :         if (fabs(a) < NUMERICAL_EPS) {
     747              :             // treat as constant speed within [0, TS]
     748       359203 :             const double t = 2 * distanceOldToPassed / (lastSpeed + currentSpeed);
     749       359203 :             return MIN2(TS, MAX2(0., t)); //rounding errors could give results out of the admissible result range
     750      1062973 :         } else if (a > 0) {
     751              :             // positive acceleration => only one positive solution
     752       572716 :             const double va = lastSpeed / a;
     753       572716 :             const double t = -va + sqrt(va * va + 2 * distanceOldToPassed / a);
     754              :             assert(t < 1 && t >= 0);
     755       572716 :             return t;
     756              :         } else {
     757              :             // negative acceleration => two positive solutions (pick the smaller one.)
     758       490257 :             const double va = lastSpeed / a;
     759       490257 :             const double t = -va - sqrt(va * va + 2 * distanceOldToPassed / a);
     760              :             // emergency braking at red light could give results out of the admissible result range
     761              :             // because the dynamics are euler-like (full forward speed with instant deceleration)
     762       490257 :             return MIN2(TS, MAX2(0., t));
     763              :         }
     764              :     }
     765              : }
     766              : 
     767              : 
     768              : double
     769     67427785 : MSCFModel::speedAfterTime(const double t, const double v0, const double dist) {
     770              :     assert(dist >= 0);
     771              :     assert(t >= 0 && t <= TS);
     772     67427785 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     773              :         // euler: constant speed within [0,TS]
     774     66368137 :         return DIST2SPEED(dist);
     775              :     } else {
     776              :         // ballistic: piecewise constant acceleration in [0,TS] (may become 0 for a stop within TS)
     777              :         // We reconstruct acceleration at time t=0. Note that the covered distance in case
     778              :         // of a stop exactly at t=TS is TS*v0/2.
     779      1059648 :         if (dist <  TS * v0 / 2) {
     780              :             // stop must have occurred within [0,TS], use dist = -v0^2/(2a) (stopping dist),
     781              :             // i.e., a = -v0^2/(2*dist)
     782           82 :             const double accel = - v0 * v0 / (2 * dist);
     783              :             // The speed at time t is then
     784           82 :             return v0 + accel * t;
     785              :         } else {
     786              :             // no stop occurred within [0,TS], thus (from dist = v0*TS + accel*TS^2/2)
     787      1059566 :             const double accel = 2 * (dist / TS - v0) / TS;
     788              :             // The speed at time t is then
     789      1059566 :             return v0 + accel * t;
     790              :         }
     791              :     }
     792              : }
     793              : 
     794              : 
     795              : 
     796              : 
     797              : double
     798   2093555398 : MSCFModel::estimateSpeedAfterDistance(const double dist, const double v, const double accel) const {
     799              :     // dist=v*t + 0.5*accel*t^2, solve for t and use v1 = v + accel*t
     800   2093555398 :     return MIN2(myType->getMaxSpeed(),
     801   2093555398 :                 (double)sqrt(MAX2(0., 2 * dist * accel + v * v)));
     802              : }
     803              : 
     804              : 
     805              : 
     806              : double
     807   3209284813 : MSCFModel::maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion, double headway, bool relaxEmergency) const {
     808              :     double vsafe;
     809   3209284813 :     if (MSGlobals::gSemiImplicitEulerUpdate) {
     810   2971811353 :         vsafe = maximumSafeStopSpeedEuler(gap, decel, onInsertion, headway);
     811              :     } else {
     812    237473460 :         vsafe = maximumSafeStopSpeedBallistic(gap, decel, currentSpeed, onInsertion, headway);
     813              :     }
     814              : 
     815   3209284813 :     if (relaxEmergency && myDecel != myEmergencyDecel) {
     816              : #ifdef DEBUG_EMERGENCYDECEL
     817              :         if (true) {
     818              :             std::cout << SIMTIME << " maximumSafeStopSpeed()"
     819              :                       << " g=" << gap
     820              :                       << " v=" << currentSpeed
     821              :                       << " initial vsafe=" << vsafe << "(decel=" << SPEED2ACCEL(v - vsafe) << ")" << std::endl;
     822              :         }
     823              : #endif
     824              : 
     825    805491063 :         double origSafeDecel = SPEED2ACCEL(currentSpeed - vsafe);
     826    805491063 :         if (origSafeDecel > myDecel + NUMERICAL_EPS) {
     827              :             // emergency deceleration required
     828              : 
     829              : #ifdef DEBUG_EMERGENCYDECEL
     830              :             if (true) {
     831              :                 std::cout << SIMTIME << " maximumSafeStopSpeed() results in emergency deceleration "
     832              :                           << "initial vsafe=" << vsafe  << " egoSpeed=" << v << "(decel=" << SPEED2ACCEL(v - vsafe) << ")" << std::endl;
     833              :             }
     834              : #endif
     835              : 
     836     22965643 :             double safeDecel = EMERGENCY_DECEL_AMPLIFIER * calculateEmergencyDeceleration(gap, currentSpeed, 0., 1);
     837              :             // Don't be riskier than the usual method (myDecel <= safeDecel may occur, because a headway>0 is used above)
     838     22965643 :             safeDecel = MAX2(safeDecel, myDecel);
     839              :             // don't brake harder than originally planned (possible due to euler/ballistic mismatch)
     840              :             safeDecel = MIN2(safeDecel, origSafeDecel);
     841     22965643 :             vsafe = currentSpeed - ACCEL2SPEED(safeDecel);
     842     22965643 :             if (MSGlobals::gSemiImplicitEulerUpdate) {
     843              :                 vsafe = MAX2(vsafe, 0.);
     844              :             }
     845              : 
     846              : #ifdef DEBUG_EMERGENCYDECEL
     847              :             if (true) {
     848              :                 std::cout << "     -> corrected emergency deceleration: " << SPEED2ACCEL(v - vsafe) << std::endl;
     849              :             }
     850              : #endif
     851              : 
     852              :         }
     853              :     }
     854              : 
     855   3209284813 :     return vsafe;
     856              : }
     857              : 
     858              : 
     859              : double
     860   2971811353 : MSCFModel::maximumSafeStopSpeedEuler(double gap, double decel, bool /* onInsertion */, double headway) const {
     861              :     // decrease gap slightly (to avoid passing end of lane by values of magnitude ~1e-12, when exact stop is required)
     862   2971811353 :     const double g = gap - NUMERICAL_EPS;
     863   2971811353 :     if (g < 0.) {
     864              :         return 0.;
     865              :     }
     866   2885453794 :     const double b = ACCEL2SPEED(decel);
     867   2885453794 :     const double t = headway >= 0 ? headway : myHeadwayTime;
     868              :     const double s = TS;
     869              : 
     870              :     // h = the distance that would be covered if it were possible to stop
     871              :     // exactly after gap and decelerate with b every simulation step
     872              :     // h = 0.5 * n * (n-1) * b * s + n * b * t (solve for n)
     873              :     //n = ((1.0/2.0) - ((t + (pow(((s*s) + (4.0*((s*((2.0*h/b) - t)) + (t*t)))), (1.0/2.0))*sign/2.0))/s));
     874   2885453794 :     const double n = floor(.5 - ((t + (sqrt(((s * s) + (4.0 * ((s * (2.0 * g / b - t)) + (t * t))))) * -0.5)) / s));
     875   2885453794 :     const double h = 0.5 * n * (n - 1) * b * s + n * b * t;
     876              :     assert(h <= g + NUMERICAL_EPS);
     877              :     // compute the additional speed that must be used during deceleration to fix
     878              :     // the discrepancy between g and h
     879   2885453794 :     const double r = (g - h) / (n * s + t);
     880   2885453794 :     const double x = n * b + r;
     881              :     assert(x >= 0);
     882   2885453794 :     return x;
     883              : //    return onInsertion ? x + b: x; // see #2574
     884              : }
     885              : 
     886              : 
     887              : double
     888    238239534 : MSCFModel::maximumSafeStopSpeedBallistic(double gap, double decel, double currentSpeed, bool onInsertion, double headway) const {
     889              :     // decrease gap slightly (to avoid passing end of lane by values of magnitude ~1e-12, when exact stop is required)
     890    238239534 :     const double g = MAX2(0., gap - NUMERICAL_EPS);
     891    238239534 :     headway = headway >= 0 ? headway : myHeadwayTime;
     892              : 
     893              :     // (Leo) Note that in contrast to the Euler update, for the ballistic update
     894              :     // the distance covered in the coming step depends on the current velocity, in general.
     895              :     // one exception is the situation when the vehicle is just being inserted.
     896              :     // In that case, it will not cover any distance until the next timestep by convention.
     897              : 
     898              :     // We treat the latter case first:
     899    238239534 :     if (onInsertion) {
     900              :         // The distance covered with constant insertion speed v0 until time tau is given as
     901              :         // G1 = tau*v0
     902              :         // The distance covered between time tau and the stopping moment at time tau+v0/b is
     903              :         // G2 = v0^2/(2b),
     904              :         // where b is an assumed constant deceleration (= decel)
     905              :         // We solve g = G1 + G2 for v0:
     906      5504421 :         const double btau = decel * headway;
     907      5504421 :         const double v0 = -btau + sqrt(btau * btau + 2 * decel * g);
     908      5504421 :         return v0;
     909              :     }
     910              : 
     911              :     // In the usual case during the driving task, the vehicle goes by
     912              :     // a current speed v0=v, and we seek to determine a safe acceleration a (possibly <0)
     913              :     // such that starting to break after accelerating with a for the time tau=headway
     914              :     // still allows us to stop in time.
     915              : 
     916    232735113 :     const double tau = headway == 0 ? TS : headway;
     917              :     const double v0 = MAX2(0., currentSpeed);
     918              :     // We first consider the case that a stop has to take place within time tau
     919              :     // (the distance driven when decelerating from v0 to 0 in tau is v0 * tau / 2)
     920    232735113 :     if (g <= v0 * tau * 0.5) {
     921     18021496 :         if (g == 0.) {
     922      9935906 :             if (v0 > 0.) {
     923              :                 // indicate to brake as hard as possible
     924      7675980 :                 return -ACCEL2SPEED(myEmergencyDecel);
     925              :             } else {
     926              :                 // stay stopped
     927              :                 return 0.;
     928              :             }
     929              :         }
     930              :         // In general we solve g = v0^2/(-2a), where the rhs is the distance
     931              :         // covered until stop when braking with a<0
     932      8085590 :         const double a = -v0 * v0 / (2 * g);
     933      8085590 :         return v0 + a * TS;
     934              :     }
     935              : 
     936              :     // The last case corresponds to a situation, where the vehicle may go with a positive
     937              :     // speed v1 = v0 + tau*a after time tau. (v1 is the maximum possible speed
     938              :     // for this and unconstrained by current speed or acceleration limits)
     939              :     //
     940              :     // The distance covered until time tau is given as
     941              :     // G1 = tau*(v0+v1)/2
     942              :     // The distance covered between time tau and the stopping moment at time tau+v1/b is
     943              :     // G2 = v1^2/(2b),
     944              :     // where b is an assumed constant deceleration (= decel)
     945              :     // We solve g = G1 + G2 for v1>0:
     946              :     // <=> 0 = v1^2 + b*tau*v1 + b*tau*v0 - 2bg
     947              :     //  => v1 = -b*tau/2 + sqrt( (b*tau)^2/4 + b(2g - tau*v0) )
     948              : 
     949    214713617 :     const double btau2 = decel * tau / 2;
     950    214713617 :     const double v1 = -btau2 + sqrt(btau2 * btau2 + decel * (2 * g - tau * v0));
     951    214713617 :     const double a = (v1 - v0) / tau;
     952    214713617 :     return v0 + a * TS;
     953              : }
     954              : 
     955              : 
     956              : /** Returns the SK-vsafe. */
     957              : double
     958   2344757869 : MSCFModel::maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion) const {
     959              :     // the speed is safe if allows the ego vehicle to come to a stop behind the leader even if
     960              :     // the leaders starts braking hard until stopped
     961              :     // unfortunately it is not sufficient to compare stopping distances if the follower can brake harder than the leader
     962              :     // (the trajectories might intersect before both vehicles are stopped even if the follower has a shorter stopping distance than the leader)
     963              :     // To make things safe, we ensure that the leaders brake distance is computed with an deceleration that is at least as high as the follower's.
     964              :     // @todo: this is a conservative estimate for safe speed which could be increased
     965              : 
     966              : //    // For negative gaps, we return the lowest meaningful value by convention
     967              : //    // XXX: check whether this is desireable (changes test results, therefore I exclude it for now (Leo), refs. #2575)
     968              : 
     969              : //    //      It must be done. Otherwise, negative gaps at high speeds can create nonsense results from the call to maximumSafeStopSpeed() below
     970              : 
     971              : //    if(gap<0){
     972              : //        if(MSGlobals::gSemiImplicitEulerUpdate){
     973              : //            return 0.;
     974              : //        } else {
     975              : //            return -INVALID_SPEED;
     976              : //        }
     977              : //    }
     978              : 
     979              :     // The following commented code is a variant to assure brief stopping behind a stopped leading vehicle:
     980              :     // if leader is stopped, calculate stopSpeed without time-headway to prevent creeping stop
     981              :     // NOTE: this can lead to the strange phenomenon (for the Krauss-model at least) that if the leader comes to a stop,
     982              :     //       the follower accelerates for a short period of time. Refs #2310 (Leo)
     983              :     //    const double headway = predSpeed > 0. ? myHeadwayTime : 0.;
     984              : 
     985   2344757869 :     const double headway = myHeadwayTime;
     986              :     double x;
     987   2344757869 :     if (gap >= 0 || MSGlobals::gComputeLC) {
     988   4582857653 :         x = maximumSafeStopSpeed(gap + brakeGap(predSpeed, MAX2(myDecel, predMaxDecel), 0), myDecel, egoSpeed, onInsertion, headway, false);
     989              :     } else {
     990       581511 :         x = egoSpeed - ACCEL2SPEED(myEmergencyDecel);
     991       581511 :         if (MSGlobals::gSemiImplicitEulerUpdate) {
     992              :             x = MAX2(x, 0.);
     993              :         }
     994              :     }
     995              : 
     996   2344757869 :     if (myDecel != myEmergencyDecel && !onInsertion && !MSGlobals::gComputeLC) {
     997   1514370371 :         double origSafeDecel = SPEED2ACCEL(egoSpeed - x);
     998   1514370371 :         if (origSafeDecel > myDecel + NUMERICAL_EPS) {
     999              :             // Braking harder than myDecel was requested -> calculate required emergency deceleration.
    1000              :             // Note that the resulting safeDecel can be smaller than the origSafeDecel, since the call to maximumSafeStopSpeed() above
    1001              :             // can result in corrupted values (leading to intersecting trajectories) if, e.g. leader and follower are fast (leader still faster) and the gap is very small,
    1002              :             // such that braking harder than myDecel is required.
    1003              : 
    1004      3817019 :             double safeDecel = EMERGENCY_DECEL_AMPLIFIER * calculateEmergencyDeceleration(gap, egoSpeed, predSpeed, predMaxDecel);
    1005              : #ifdef DEBUG_EMERGENCYDECEL
    1006              :             if (DEBUG_COND2) {
    1007              :                 std::cout << SIMTIME << " initial vsafe=" << x
    1008              :                           << " egoSpeed=" << egoSpeed << " (origSafeDecel=" << origSafeDecel << ")"
    1009              :                           << " predSpeed=" << predSpeed << " (predDecel=" << predMaxDecel << ")"
    1010              :                           << " safeDecel=" << safeDecel
    1011              :                           << std::endl;
    1012              :             }
    1013              : #endif
    1014              :             // Don't be riskier than the usual method (myDecel <= safeDecel may occur, because a headway>0 is used above)
    1015      3817019 :             safeDecel = MAX2(safeDecel, myDecel);
    1016              :             // don't brake harder than originally planned (possible due to euler/ballistic mismatch)
    1017              :             safeDecel = MIN2(safeDecel, origSafeDecel);
    1018      3817019 :             x = egoSpeed - ACCEL2SPEED(safeDecel);
    1019      3817019 :             if (MSGlobals::gSemiImplicitEulerUpdate) {
    1020              :                 x = MAX2(x, 0.);
    1021              :             }
    1022              : 
    1023              : #ifdef DEBUG_EMERGENCYDECEL
    1024              :             if (DEBUG_COND2) {
    1025              :                 std::cout << "     -> corrected emergency deceleration: " << safeDecel << " newVSafe=" << x << std::endl;
    1026              :             }
    1027              : #endif
    1028              : 
    1029              :         }
    1030              :     }
    1031              :     assert(x >= 0 || !MSGlobals::gSemiImplicitEulerUpdate);
    1032              :     assert(!std::isnan(x));
    1033   2344757869 :     return x;
    1034              : }
    1035              : 
    1036              : 
    1037              : double
    1038     26782662 : MSCFModel::calculateEmergencyDeceleration(double gap, double egoSpeed, double predSpeed, double predMaxDecel) const {
    1039              :     // There are two cases:
    1040              :     // 1) Either, stopping in time is possible with a deceleration b <= predMaxDecel, then this value is returned
    1041              :     // 2) Or, b > predMaxDecel is required in this case the minimal value b allowing to stop safely under the assumption maxPredDecel=b is returned
    1042     26782662 :     if (gap <= 0.) {
    1043      2273656 :         return myEmergencyDecel;
    1044              :     }
    1045              : 
    1046              :     // Apparent braking distance for the leader
    1047     24509006 :     const double predBrakeDist = 0.5 * predSpeed * predSpeed / predMaxDecel;
    1048              :     // Required deceleration according to case 1)
    1049     24509006 :     const double b1 = 0.5 * egoSpeed * egoSpeed / (gap + predBrakeDist);
    1050              : 
    1051              : #ifdef DEBUG_EMERGENCYDECEL
    1052              :     if (DEBUG_COND2) {
    1053              :         std::cout << SIMTIME << " calculateEmergencyDeceleration()"
    1054              :                   << " gap=" << gap << " egoSpeed=" << egoSpeed << " predSpeed=" << predSpeed
    1055              :                   << " predBrakeDist=" << predBrakeDist
    1056              :                   << " b1=" << b1
    1057              :                   << std::endl;
    1058              :     }
    1059              : #endif
    1060              : 
    1061     24509006 :     if (b1 <= predMaxDecel) {
    1062              :         // Case 1) applies
    1063              : #ifdef DEBUG_EMERGENCYDECEL
    1064              :         if (DEBUG_COND2) {
    1065              :             std::cout << "       case 1 ..." << std::endl;
    1066              :         }
    1067              : #endif
    1068              :         return b1;
    1069              :     }
    1070              : #ifdef DEBUG_EMERGENCYDECEL
    1071              :     if (DEBUG_COND2) {
    1072              :         std::cout << "       case 2 ...";
    1073              :     }
    1074              : #endif
    1075              : 
    1076              :     // Case 2) applies
    1077              :     // Required deceleration according to case 2)
    1078     23742946 :     const double b2 = 0.5 * (egoSpeed * egoSpeed - predSpeed * predSpeed) / gap;
    1079              : 
    1080              : #ifdef DEBUG_EMERGENCYDECEL
    1081              :     if (DEBUG_COND2) {
    1082              :         std::cout << " b2=" << b2 << std::endl;
    1083              :     }
    1084              : #endif
    1085     23742946 :     return b2;
    1086              : }
    1087              : 
    1088              : 
    1089              : void
    1090    618646863 : MSCFModel::applyOwnSpeedPerceptionError(const MSVehicle* const veh, double& speed) const {
    1091    618646863 :     if (!veh->hasDriverState()) {
    1092              :         return;
    1093              :     }
    1094       812818 :     speed = veh->getDriverState()->getPerceivedOwnSpeed(speed);
    1095              : }
    1096              : 
    1097              : 
    1098              : void
    1099   2405727841 : MSCFModel::applyHeadwayAndSpeedDifferencePerceptionErrors(const MSVehicle* const veh, double speed, double& gap, double& predSpeed, double predMaxDecel, const MSVehicle* const pred) const {
    1100              :     UNUSED_PARAMETER(speed);
    1101              :     UNUSED_PARAMETER(predMaxDecel);
    1102   2405727841 :     if (!veh->hasDriverState()) {
    1103              :         return;
    1104              :     }
    1105              : 
    1106              :     // Obtain perceived gap and headway from the driver state
    1107       960319 :     const double perceivedGap = veh->getDriverState()->getPerceivedHeadway(gap, pred);
    1108       960319 :     const double perceivedSpeedDifference = veh->getDriverState()->getPerceivedSpeedDifference(predSpeed - speed, gap, pred);
    1109              : 
    1110              : #ifdef DEBUG_DRIVER_ERRORS
    1111              :     if (DEBUG_COND) {
    1112              :         if (!veh->getDriverState()->debugLocked()) {
    1113              :             veh->getDriverState()->lockDebug();
    1114              :             std::cout << SIMTIME << " veh '" << veh->getID() << "' -> MSCFModel_Krauss::applyHeadwayAndSpeedDifferencePerceptionErrors()\n"
    1115              :                       << "  speed=" << speed << " gap=" << gap << " leaderSpeed=" << predSpeed
    1116              :                       << "\n  perceivedGap=" << perceivedGap << " perceivedLeaderSpeed=" << speed + perceivedSpeedDifference
    1117              :                       << " perceivedSpeedDifference=" << perceivedSpeedDifference
    1118              :                       << std::endl;
    1119              :             const double exactFollowSpeed = followSpeed(veh, speed, gap, predSpeed, predMaxDecel, pred, CalcReason::FUTURE);
    1120              :             const double errorFollowSpeed = followSpeed(veh, speed, perceivedGap, speed + perceivedSpeedDifference, predMaxDecel, pred, CalcReason::FUTURE);
    1121              :             const double accelError = SPEED2ACCEL(errorFollowSpeed - exactFollowSpeed);
    1122              :             std::cout << "  gapError=" << perceivedGap - gap << "  dvError=" << perceivedSpeedDifference - (predSpeed - speed)
    1123              :                       << "\n  resulting accelError: " << accelError << std::endl;
    1124              :             veh->getDriverState()->unlockDebug();
    1125              :         }
    1126              :     }
    1127              : #endif
    1128              : 
    1129       960319 :     gap = perceivedGap;
    1130       960319 :     predSpeed = speed + perceivedSpeedDifference;
    1131              : }
    1132              : 
    1133              : 
    1134              : void
    1135    814671393 : MSCFModel::applyHeadwayPerceptionError(const MSVehicle* const veh, double speed, double& gap) const {
    1136              :     UNUSED_PARAMETER(speed);
    1137    814671393 :     if (!veh->hasDriverState()) {
    1138              :         return;
    1139              :     }
    1140              :     // @todo: Provide objectID (e.g. pointer address for the relevant object at the given distance(gap))
    1141              :     //        This is for item related management of known object and perception updates when the distance
    1142              :     //        changes significantly. (Should not be too important for stationary objects though.)
    1143              : 
    1144              :     // Obtain perceived gap from driver state
    1145       237408 :     const double perceivedGap = veh->getDriverState()->getPerceivedHeadway(gap);
    1146              : 
    1147              : #ifdef DEBUG_DRIVER_ERRORS
    1148              :     if (DEBUG_COND) {
    1149              :         if (!veh->getDriverState()->debugLocked()) {
    1150              :             veh->getDriverState()->lockDebug();
    1151              :             std::cout << SIMTIME << " veh '" << veh->getID() << "' -> MSCFModel_Krauss::applyHeadwayPerceptionError()\n"
    1152              :                       << "  speed=" << speed << " gap=" << gap << "\n  perceivedGap=" << perceivedGap << std::endl;
    1153              :             const double exactStopSpeed = stopSpeed(veh, speed, gap, CalcReason::FUTURE);
    1154              :             const double errorStopSpeed = stopSpeed(veh, speed, perceivedGap, CalcReason::FUTURE);
    1155              :             const double accelError = SPEED2ACCEL(errorStopSpeed - exactStopSpeed);
    1156              :             std::cout << "  gapError=" << perceivedGap - gap << "\n  resulting accelError: " << accelError << std::endl;
    1157              :             veh->getDriverState()->unlockDebug();
    1158              :         }
    1159              :     }
    1160              : #endif
    1161              : 
    1162       237408 :     gap = perceivedGap;
    1163              : }
    1164              : 
    1165              : 
    1166              : double
    1167   5685185776 : MSCFModel::getCurrentAccel(const double speed) const {
    1168   5685185776 :     double result = myAccel;
    1169   5685185776 :     if (!myDesAccelProfile.empty()) {
    1170        10676 :         result = MIN2(result, LinearApproxHelpers::getInterpolatedValue(myDesAccelProfile, speed));
    1171              :     }
    1172   5685185776 :     if (!myMaxAccelProfile.empty()) {
    1173              :         // @todo maxAccel should interact with slope
    1174         3292 :         result = MIN2(result, LinearApproxHelpers::getInterpolatedValue(myMaxAccelProfile, speed));
    1175              :     }
    1176   5685185776 :     return result;
    1177              : }
    1178              : 
    1179              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1