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