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.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
20 // The car-following model abstraction
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #include <config.h>
28 
29 #include <cmath>
30 #include <microsim/MSGlobals.h>
31 #include <microsim/MSVehicleType.h>
32 #include <microsim/MSVehicle.h>
33 #include <microsim/MSNet.h>
34 #include <microsim/MSLane.h>
36 #include <microsim/MSDriverState.h>
37 #include "MSCFModel.h"
38 
39 // ===========================================================================
40 // DEBUG constants
41 // ===========================================================================
42 //#define DEBUG_FINALIZE_SPEED
43 //#define DEBUG_DRIVER_ERRORS
44 //#define DEBUG_EMERGENCYDECEL
45 //#define DEBUG_COND (true)
46 #define DEBUG_COND (veh->isSelected())
47 //#define DEBUG_COND (veh->getID() == "follower")
48 //#define DEBUG_COND2 (SIMTIME == 176)
49 #define DEBUG_COND2 (gDebugFlag1)
50 
51 
52 
53 // ===========================================================================
54 // method definitions
55 // ===========================================================================
57  myType(vtype),
58  myAccel(vtype->getParameter().getCFParam(SUMO_ATTR_ACCEL, SUMOVTypeParameter::getDefaultAccel(vtype->getParameter().vehicleClass))),
59  myDecel(vtype->getParameter().getCFParam(SUMO_ATTR_DECEL, SUMOVTypeParameter::getDefaultDecel(vtype->getParameter().vehicleClass))),
60  myEmergencyDecel(vtype->getParameter().getCFParam(SUMO_ATTR_EMERGENCYDECEL,
61  SUMOVTypeParameter::getDefaultEmergencyDecel(vtype->getParameter().vehicleClass, myDecel, MSGlobals::gDefaultEmergencyDecel))),
62  myApparentDecel(vtype->getParameter().getCFParam(SUMO_ATTR_APPARENTDECEL, myDecel)),
63  myCollisionMinGapFactor(vtype->getParameter().getCFParam(SUMO_ATTR_COLLISION_MINGAP_FACTOR, 1)),
64  myHeadwayTime(vtype->getParameter().getCFParam(SUMO_ATTR_TAU, 1.0)) {
65 }
66 
67 
69 
70 
72 
73 
74 double
75 MSCFModel::brakeGap(const double speed, const double decel, const double headwayTime) {
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 double
165 MSCFModel::finalizeSpeed(MSVehicle* const veh, double vPos) const {
166  // save old v for optional acceleration computation
167  const double oldV = veh->getSpeed();
168  // process stops (includes update of stopping state)
169  const double vStop = MIN2(vPos, veh->processNextStop(vPos));
170  // apply deceleration bounds
171  const double vMinEmergency = minNextSpeedEmergency(oldV, veh);
172  // vPos contains the uppper bound on safe speed. allow emergency braking here
173  const double vMin = MIN2(minNextSpeed(oldV, veh), MAX2(vPos, vMinEmergency));
174  // aMax: Maximal admissible acceleration until the next action step, such that the vehicle's maximal
175  // desired speed on the current lane will not be exceeded when the
176  // acceleration is maintained until the next action step.
177  double aMax = (veh->getLane()->getVehicleMaxSpeed(veh) - oldV) / veh->getActionStepLengthSecs();
178  // apply planned speed constraints and acceleration constraints
179  double vMax = MIN3(oldV + ACCEL2SPEED(aMax), maxNextSpeed(oldV, veh), vStop);
180  // do not exceed max decel even if it is unsafe
181 #ifdef _DEBUG
182  //if (vMin > vMax) {
183  // WRITE_WARNING("Maximum speed of vehicle '" + veh->getID() + "' is lower than the minimum speed (min: " + toString(vMin) + ", max: " + toString(vMax) + ").");
184  //}
185 #endif
186 
187 #ifdef DEBUG_FINALIZE_SPEED
188  if DEBUG_COND {
189  std::cout << "\n" << SIMTIME << " FINALIZE_SPEED\n";
190 }
191 #endif
192 
193  vMax = MAX2(vMin, vMax);
194  // apply further speed adaptations
195  double vNext = patchSpeedBeforeLC(veh, vMin, vMax);
196 #ifdef DEBUG_FINALIZE_SPEED
197  double vDawdle = vNext;
198 #endif
199  assert(vNext >= vMin);
200  assert(vNext <= vMax);
201  // apply lane-changing related speed adaptations
202  vNext = veh->getLaneChangeModel().patchSpeed(vMin, vNext, vMax, *this);
203  assert(vNext >= vMin);
204  assert(vNext <= vMax);
205 
206 #ifdef DEBUG_FINALIZE_SPEED
207  if DEBUG_COND {
208  std::cout << std::setprecision(gPrecision)
209  << "veh '" << veh->getID() << "' oldV=" << oldV
210  << " vPos" << vPos
211  << " vMin=" << vMin
212  << " vMax=" << vMax
213  << " vStop=" << vStop
214  << " vDawdle=" << vDawdle
215  << " vNext=" << vNext
216  << "\n";
217  }
218 #endif
219  return vNext;
220 }
221 
222 
223 double
224 MSCFModel::interactionGap(const MSVehicle* const veh, double vL) const {
225  // Resolve the vsafe equation to gap. Assume predecessor has
226  // speed != 0 and that vsafe will be the current speed plus acceleration,
227  // i.e that with this gap there will be no interaction.
228  const double vNext = MIN2(maxNextSpeed(veh->getSpeed(), veh), veh->getLane()->getVehicleMaxSpeed(veh));
229  const double gap = (vNext - vL) *
230  ((veh->getSpeed() + vL) / (2.*myDecel) + myHeadwayTime) +
231  vL * myHeadwayTime;
232 
233  // Don't allow timeHeadWay < deltaT situations.
234  return MAX2(gap, SPEED2DIST(vNext));
235 }
236 
237 
238 double
239 MSCFModel::maxNextSpeed(double speed, const MSVehicle* const /*veh*/) const {
240  return MIN2(speed + (double) ACCEL2SPEED(getMaxAccel()), myType->getMaxSpeed());
241 }
242 
243 
244 double
245 MSCFModel::minNextSpeed(double speed, const MSVehicle* const /*veh*/) const {
247  return MAX2(speed - ACCEL2SPEED(myDecel), 0.);
248  } else {
249  // NOTE: ballistic update allows for negative speeds to indicate a stop within the next timestep
250  return speed - ACCEL2SPEED(myDecel);
251  }
252 }
253 
254 
255 double
256 MSCFModel::minNextSpeedEmergency(double speed, const MSVehicle* const /*veh*/) const {
258  return MAX2(speed - ACCEL2SPEED(myEmergencyDecel), 0.);
259  } else {
260  // NOTE: ballistic update allows for negative speeds to indicate a stop within the next timestep
261  return speed - ACCEL2SPEED(myEmergencyDecel);
262  }
263 }
264 
265 
266 
267 double
268 MSCFModel::freeSpeed(const MSVehicle* const veh, double speed, double seen, double maxSpeed, const bool onInsertion) const {
269  if (maxSpeed < 0.) {
270  // can occur for ballistic update (in context of driving at red light)
271  return maxSpeed;
272  }
273  double vSafe = freeSpeed(speed, myDecel, seen, maxSpeed, onInsertion, veh->getActionStepLengthSecs());
274  return vSafe;
275 }
276 
277 
278 double
279 MSCFModel::insertionFollowSpeed(const MSVehicle* const /* v */, double speed, double gap2pred, double predSpeed, double predMaxDecel) const {
281  return maximumSafeFollowSpeed(gap2pred, speed, predSpeed, predMaxDecel, true);
282  } else {
283  // NOTE: Even for ballistic update, the current speed is irrelevant at insertion, therefore passing 0. (Leo)
284  return maximumSafeFollowSpeed(gap2pred, 0., predSpeed, predMaxDecel, true);
285  }
286 }
287 
288 
289 double
290 MSCFModel::insertionStopSpeed(const MSVehicle* const veh, double speed, double gap) const {
292  return stopSpeed(veh, speed, gap);
293  } else {
294  return MIN2(maximumSafeStopSpeed(gap, 0., true, 0.), myType->getMaxSpeed());
295  }
296 }
297 
298 
299 double
300 MSCFModel::followSpeedTransient(double duration, const MSVehicle* const /*veh*/, double /*speed*/, double gap2pred, double predSpeed, double predMaxDecel) const {
301  // minimium distance covered by the leader if braking
302  double leaderMinDist = gap2pred + distAfterTime(duration, predSpeed, -predMaxDecel);
303  // if ego would not brake it could drive with speed leaderMinDist / duration
304  // due to potentential ego braking it can safely drive faster
306  // number of potential braking steps
307  int a = (int)ceil(duration / TS - TS);
308  // can we brake for the whole time?
309  const double bg = brakeGap(a * myDecel, myDecel, 0);
310  if (bg <= leaderMinDist) {
311  // braking continuously for duration
312  // distance reduction due to braking
313  double b = TS * getMaxDecel() * 0.5 * (a * a - a);
314  if (gDebugFlag2) std::cout << " followSpeedTransient"
315  << " duration=" << duration
316  << " gap=" << gap2pred
317  << " leaderMinDist=" << leaderMinDist
318  << " decel=" << getMaxDecel()
319  << " a=" << a
320  << " bg=" << bg
321  << " b=" << b
322  << " x=" << (b + leaderMinDist) / duration
323  << "\n";
324  return (b + leaderMinDist) / duration;
325  } else {
326  // @todo improve efficiency
327  double bg = 0;
328  double speed = 0;
329  while (bg < leaderMinDist) {
330  speed += ACCEL2SPEED(myDecel);
331  bg += SPEED2DIST(speed);
332  }
333  speed -= DIST2SPEED(bg - leaderMinDist);
334  return speed;
335  }
336  } else {
337  // can we brake for the whole time?
338  const double fullBrakingSeconds = sqrt(leaderMinDist * 2 / myDecel);
339  if (fullBrakingSeconds >= duration) {
340  // braking continuously for duration
341  // average speed after braking for duration is x2 = x - 0.5 * duration * myDecel
342  // x2 * duration <= leaderMinDist must hold
343  return leaderMinDist / duration + duration * getMaxDecel() / 2;
344  } else {
345  return fullBrakingSeconds * myDecel;
346  }
347  }
348 }
349 
350 double
351 MSCFModel::distAfterTime(double t, double speed, const double accel) {
352  if (accel >= 0.) {
353  return (speed + 0.5 * accel * t) * t;
354  }
355  const double decel = -accel;
356  if (speed <= decel * t) {
357  // braking to a full stop
358  return brakeGap(speed, decel, 0);
359  }
361  // @todo improve efficiency
362  double result = 0;
363  while (t > 0) {
364  speed -= ACCEL2SPEED(decel);
365  result += MAX2(0.0, SPEED2DIST(speed));
366  t -= TS;
367  }
368  return result;
369  } else {
370  const double speed2 = speed - t * decel;
371  return 0.5 * (speed + speed2) * t;
372  }
373 }
374 
375 SUMOTime
376 MSCFModel::getMinimalArrivalTime(double dist, double currentSpeed, double arrivalSpeed) const {
377  const double accel = (arrivalSpeed >= currentSpeed) ? getMaxAccel() : -getMaxDecel();
378  const double accelTime = (arrivalSpeed - currentSpeed) / accel;
379  const double accelWay = accelTime * (arrivalSpeed + currentSpeed) * 0.5;
380  const double nonAccelWay = MAX2(0., dist - accelWay);
381  // will either drive as fast as possible and decelerate as late as possible
382  // or accelerate as fast as possible and then hold that speed
383  const double nonAccelSpeed = MAX3(currentSpeed, arrivalSpeed, SUMO_const_haltingSpeed);
384  return TIME2STEPS(accelTime + nonAccelWay / nonAccelSpeed);
385 }
386 
387 
388 double
389 MSCFModel::estimateArrivalTime(double dist, double speed, double maxSpeed, double accel) {
390  assert(speed >= 0.);
391  assert(dist >= 0.);
392 
393  if (dist == 0.) {
394  return 0.;
395  }
396 
397  if ((accel < 0. && -0.5 * speed * speed / accel < dist) || (accel <= 0. && speed == 0.)) {
398  // distance will never be covered with these values
399  return INVALID_DOUBLE;
400  }
401 
402  if (accel == 0.) {
403  return dist / speed;
404  }
405 
406  double p = speed / accel;
407 
408  if (accel < 0.) {
409  // we already know, that the distance will be covered despite breaking
410  return (-p - sqrt(p * p + 2 * dist / accel));
411  }
412 
413  // Here, accel > 0
414  // t1 is the time to use the given acceleration
415  double t1 = (maxSpeed - speed) / accel;
416  // distance covered until t1
417  double d1 = speed * t1 + 0.5 * accel * t1 * t1;
418  if (d1 >= dist) {
419  // dist is covered before changing the speed
420  return (-p + sqrt(p * p + 2 * dist / accel));
421  } else {
422  return (-p + sqrt(p * p + 2 * d1 / accel)) + (dist - d1) / maxSpeed;
423  }
424 
425 }
426 
427 double
428 MSCFModel::estimateArrivalTime(double dist, double initialSpeed, double arrivalSpeed, double maxSpeed, double accel, double decel) {
429  UNUSED_PARAMETER(arrivalSpeed); // only in assertion
430  UNUSED_PARAMETER(decel); // only in assertion
431  if (dist <= 0) {
432  return 0.;
433  }
434 
435  // stub-assumptions
436  assert(accel == decel);
437  assert(accel > 0);
438  assert(initialSpeed == 0);
439  assert(arrivalSpeed == 0);
440  assert(maxSpeed > 0);
441 
442 
443  double accelTime = (maxSpeed - initialSpeed) / accel;
444  // "ballistic" estimate for the distance covered during acceleration phase
445  double accelDist = accelTime * (initialSpeed + 0.5 * (maxSpeed - initialSpeed));
446  double arrivalTime;
447  if (accelDist >= dist * 0.5) {
448  // maximal speed will not be attained during maneuver
449  arrivalTime = 4 * sqrt(accelDist) / accel;
450  } else {
451  // Calculate time to move with constant, maximal lateral speed
452  const double constSpeedTime = (dist - accelDist * 2) / maxSpeed;
453  arrivalTime = accelTime + constSpeedTime;
454  }
455  return arrivalTime;
456 }
457 
458 
459 double
460 MSCFModel::avoidArrivalAccel(double dist, double time, double speed) {
461  assert(time > 0 || dist == 0);
462  if (dist <= 0) {
463  return -std::numeric_limits<double>::max();
464  } else if (time * speed > 2 * dist) {
465  // stop before dist is necessary. We need
466  // d = v*v/(2*a)
467  return - 0.5 * speed * speed / dist;
468  } else {
469  // we seek the solution a of
470  // d = v*t + a*t*t/2
471  return 2 * (dist / time - speed) / time;
472  }
473 }
474 
475 
476 double
477 MSCFModel::getMinimalArrivalSpeed(double dist, double currentSpeed) const {
478  // ballistic update
479  return estimateSpeedAfterDistance(dist - currentSpeed * getHeadwayTime(), currentSpeed, -getMaxDecel());
480 }
481 
482 
483 double
484 MSCFModel::getMinimalArrivalSpeedEuler(double dist, double currentSpeed) const {
485  double arrivalSpeedBraking;
486  // Because we use a continuous formula for computing the possible slow-down
487  // we need to handle the mismatch with the discrete dynamics
488  if (dist < currentSpeed) {
489  arrivalSpeedBraking = INVALID_SPEED; // no time left for braking after this step
490  // (inserted max() to get rid of arrivalSpeed dependency within method) (Leo)
491  } else if (2 * (dist - currentSpeed * getHeadwayTime()) * -getMaxDecel() + currentSpeed * currentSpeed >= 0) {
492  arrivalSpeedBraking = estimateSpeedAfterDistance(dist - currentSpeed * getHeadwayTime(), currentSpeed, -getMaxDecel());
493  } else {
494  arrivalSpeedBraking = getMaxDecel();
495  }
496  return arrivalSpeedBraking;
497 }
498 
499 
500 
501 
502 double
503 MSCFModel::gapExtrapolation(const double duration, const double currentGap, double v1, double v2, double a1, double a2, const double maxV1, const double maxV2) {
504 
505  double newGap = currentGap;
506 
508  for (unsigned int steps = 1; steps * TS <= duration; ++steps) {
509  v1 = MIN2(MAX2(v1 + a1, 0.), maxV1);
510  v2 = MIN2(MAX2(v2 + a2, 0.), maxV2);
511  newGap += TS * (v1 - v2);
512  }
513  } else {
514  // determine times t1, t2 for which vehicles can break until stop (within duration)
515  // and t3, t4 for which they reach their maximal speed on their current lanes.
516  double t1 = 0, t2 = 0, t3 = 0, t4 = 0;
517 
518  // t1: ego veh stops
519  if (a1 < 0 && v1 > 0) {
520  const double leaderStopTime = - v1 / a1;
521  t1 = MIN2(leaderStopTime, duration);
522  } else if (a1 >= 0) {
523  t1 = duration;
524  }
525  // t2: veh2 stops
526  if (a2 < 0 && v2 > 0) {
527  const double followerStopTime = -v2 / a2;
528  t2 = MIN2(followerStopTime, duration);
529  } else if (a2 >= 0) {
530  t2 = duration;
531  }
532  // t3: ego veh reaches vMax
533  if (a1 > 0 && v1 < maxV1) {
534  const double leaderMaxSpeedTime = (maxV1 - v1) / a1;
535  t3 = MIN2(leaderMaxSpeedTime, duration);
536  } else if (a1 <= 0) {
537  t3 = duration;
538  }
539  // t4: veh2 reaches vMax
540  if (a2 > 0 && v2 < maxV2) {
541  const double followerMaxSpeedTime = (maxV2 - v2) / a2;
542  t4 = MIN2(followerMaxSpeedTime, duration);
543  } else if (a2 <= 0) {
544  t4 = duration;
545  }
546 
547  // NOTE: this assumes that the accelerations a1 and a2 are constant over the next
548  // followerBreakTime seconds (if no vehicle stops before or reaches vMax)
549  std::list<double> l;
550  l.push_back(t1);
551  l.push_back(t2);
552  l.push_back(t3);
553  l.push_back(t4);
554  l.sort();
555  std::list<double>::const_iterator i;
556  double tLast = 0.;
557  for (i = l.begin(); i != l.end(); ++i) {
558  if (*i != tLast) {
559  double dt = MIN2(*i, duration) - tLast; // time between *i and tLast
560  double dv = v1 - v2; // current velocity difference
561  double da = a1 - a2; // current acceleration difference
562  newGap += dv * dt + da * dt * dt / 2.; // update gap
563  v1 += dt * a1;
564  v2 += dt * a2;
565  }
566  if (*i == t1 || *i == t3) {
567  // ego veh reached velocity bound
568  a1 = 0.;
569  }
570 
571  if (*i == t2 || *i == t4) {
572  // veh2 reached velocity bound
573  a2 = 0.;
574  }
575 
576  tLast = MIN2(*i, duration);
577  if (tLast == duration) {
578  break;
579  }
580  }
581 
582  if (duration != tLast) {
583  // (both vehicles have zero acceleration)
584  assert(a1 == 0. && a2 == 0.);
585  double dt = duration - tLast; // remaining time until duration
586  double dv = v1 - v2; // current velocity difference
587  newGap += dv * dt; // update gap
588  }
589  }
590 
591  return newGap;
592 }
593 
594 
595 
596 double
597 MSCFModel::passingTime(const double lastPos, const double passedPos, const double currentPos, const double lastSpeed, const double currentSpeed) {
598 
599  assert(passedPos <= currentPos);
600  assert(passedPos >= lastPos);
601  assert(currentPos > lastPos);
602  assert(currentSpeed >= 0);
603 
604  if (passedPos > currentPos || passedPos < lastPos) {
605  std::stringstream ss;
606  // Debug (Leo)
608  // NOTE: error is guarded to maintain original test output for euler update (Leo).
609  ss << "passingTime(): given argument passedPos = " << passedPos << " doesn't lie within [lastPos, currentPos] = [" << lastPos << ", " << currentPos << "]\nExtrapolating...";
610  std::cout << ss.str() << "\n";
611  WRITE_ERROR(ss.str());
612  }
613  const double lastCoveredDist = currentPos - lastPos;
614  const double extrapolated = passedPos > currentPos ? TS * (passedPos - lastPos) / lastCoveredDist : TS * (currentPos - passedPos) / lastCoveredDist;
615  return extrapolated;
616  } else if (currentSpeed < 0) {
617  WRITE_ERROR("passingTime(): given argument 'currentSpeed' is negative. This case is not handled yet.");
618  return -1;
619  }
620 
621  const double distanceOldToPassed = passedPos - lastPos; // assert: >=0
622 
624  // euler update (constantly moving with currentSpeed during [0,TS])
625  const double t = distanceOldToPassed / currentSpeed;
626  return MIN2(TS, MAX2(0., t)); //rounding errors could give results out of the admissible result range
627 
628  } else {
629  // ballistic update (constant acceleration a during [0,TS], except in case of a stop)
630 
631  // determine acceleration
632  double a;
633  if (currentSpeed > 0) {
634  // the acceleration was constant within the last time step
635  a = SPEED2ACCEL(currentSpeed - lastSpeed);
636  } else {
637  // the currentSpeed is zero (the last was not because lastPos<currentPos).
638  assert(currentSpeed == 0 && lastSpeed != 0);
639  // In general the stop has taken place within the last time step.
640  // The acceleration (a<0) is obtained from
641  // deltaPos = - lastSpeed^2/(2*a)
642  a = lastSpeed * lastSpeed / (2 * (lastPos - currentPos));
643 
644  assert(a < 0);
645  }
646 
647  // determine passing time t
648  // we solve distanceOldToPassed = lastSpeed*t + a*t^2/2
649  if (fabs(a) < NUMERICAL_EPS) {
650  // treat as constant speed within [0, TS]
651  const double t = 2 * distanceOldToPassed / (lastSpeed + currentSpeed);
652  return MIN2(TS, MAX2(0., t)); //rounding errors could give results out of the admissible result range
653  } else if (a > 0) {
654  // positive acceleration => only one positive solution
655  const double va = lastSpeed / a;
656  const double t = -va + sqrt(va * va + 2 * distanceOldToPassed / a);
657  assert(t < 1 && t >= 0);
658  return t;
659  } else {
660  // negative acceleration => two positive solutions (pick the smaller one.)
661  const double va = lastSpeed / a;
662  const double t = -va - sqrt(va * va + 2 * distanceOldToPassed / a);
663  assert(t < 1 && t >= 0);
664  return t;
665  }
666  }
667 }
668 
669 
670 double
671 MSCFModel::speedAfterTime(const double t, const double v0, const double dist) {
672  assert(dist >= 0);
673  assert(t >= 0 && t <= TS);
675  // euler: constant speed within [0,TS]
676  return DIST2SPEED(dist);
677  } else {
678  // ballistic: piecewise constant acceleration in [0,TS] (may become 0 for a stop within TS)
679  // We reconstruct acceleration at time t=0. Note that the covered distance in case
680  // of a stop exactly at t=TS is TS*v0/2.
681  if (dist < TS * v0 / 2) {
682  // stop must have occurred within [0,TS], use dist = -v0^2/(2a) (stopping dist),
683  // i.e., a = -v0^2/(2*dist)
684  const double accel = - v0 * v0 / (2 * dist);
685  // The speed at time t is then
686  return v0 + accel * t;
687  } else {
688  // no stop occurred within [0,TS], thus (from dist = v0*TS + accel*TS^2/2)
689  const double accel = 2 * (dist / TS - v0) / TS;
690  // The speed at time t is then
691  return v0 + accel * t;
692  }
693  }
694 }
695 
696 
697 
698 
699 double
700 MSCFModel::estimateSpeedAfterDistance(const double dist, const double v, const double accel) const {
701  // dist=v*t + 0.5*accel*t^2, solve for t and use v1 = v + accel*t
702  return MAX2(0., MIN2(myType->getMaxSpeed(),
703  (double)sqrt(2 * dist * accel + v * v)));
704 }
705 
706 
707 
708 double
709 MSCFModel::maximumSafeStopSpeed(double g /*gap*/, double v /*currentSpeed*/, bool onInsertion, double headway) const {
710  double vsafe;
712  vsafe = maximumSafeStopSpeedEuler(g, headway);
713  } else {
714  vsafe = maximumSafeStopSpeedBallistic(g, v, onInsertion, headway);
715  }
716 
717 // if (myDecel != myEmergencyDecel) {
718 //#ifdef DEBUG_EMERGENCYDECEL
719 // if (true) {
720 // std::cout << SIMTIME << " maximumSafeStopSpeed()"
721 // << " g=" << g
722 // << " v=" << v
723 // << " initial vsafe=" << vsafe << "(decel=" << SPEED2ACCEL(v-vsafe) << ")" << std::endl;
724 // }
725 //#endif
726 //
727 // if (vsafe < v - ACCEL2SPEED(myDecel + NUMERICAL_EPS)) {
728 // // emergency deceleration required
729 //
730 //#ifdef DEBUG_EMERGENCYDECEL
731 // if (true) {
732 // std::cout << SIMTIME << " maximumSafeStopSpeed() results in emergency deceleration "
733 // << "initial vsafe=" << vsafe << " egoSpeed=" << v << "(decel=" << SPEED2ACCEL(v-vsafe) << ")" << std::endl;
734 // }
735 //#endif
736 //
737 // const double safeDecel = calculateEmergencyDeceleration(g, v, 0., 1);
738 // assert(myDecel <= safeDecel);
739 // vsafe = v - ACCEL2SPEED(myDecel + EMERGENCY_DECEL_AMPLIFIER * (safeDecel - myDecel));
740 //
741 // if(MSGlobals::gSemiImplicitEulerUpdate) {
742 // vsafe = MAX2(vsafe,0.);
743 // }
744 //
745 //#ifdef DEBUG_EMERGENCYDECEL
746 // if (true) {
747 // std::cout << " -> corrected emergency deceleration: " << SPEED2ACCEL(v-vsafe) << std::endl;
748 // }
749 //#endif
750 //
751 // }
752 // }
753 
754  return vsafe;
755 }
756 
757 
758 double
759 MSCFModel::maximumSafeStopSpeedEuler(double gap, double headway) const {
760  gap -= NUMERICAL_EPS; // lots of code relies on some slack XXX: it shouldn't...
761  if (gap <= 0) {
762  return 0;
763  }
764  const double g = gap;
765  const double b = ACCEL2SPEED(myDecel);
766  const double t = headway >= 0 ? headway : myHeadwayTime;
767  const double s = TS;
768 
769 
770  // h = the distance that would be covered if it were possible to stop
771  // exactly after gap and decelerate with b every simulation step
772  // h = 0.5 * n * (n-1) * b * s + n * b * t (solve for n)
773  //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));
774  const double n = floor(.5 - ((t + (sqrt(((s * s) + (4.0 * ((s * (2.0 * g / b - t)) + (t * t))))) * -0.5)) / s));
775  const double h = 0.5 * n * (n - 1) * b * s + n * b * t;
776  assert(h <= g + NUMERICAL_EPS);
777  // compute the additional speed that must be used during deceleration to fix
778  // the discrepancy between g and h
779  const double r = (g - h) / (n * s + t);
780  const double x = n * b + r;
781  assert(x >= 0);
782  return x;
783 }
784 
785 
786 double
787 MSCFModel::maximumSafeStopSpeedBallistic(double g /*gap*/, double v /*currentSpeed*/, bool onInsertion, double headway) const {
788  // decrease gap slightly (to avoid passing end of lane by values of magnitude ~1e-12, when exact stop is required)
789  g = MAX2(0., g - NUMERICAL_EPS);
790  headway = headway >= 0 ? headway : myHeadwayTime;
791 
792  // (Leo) Note that in contrast to the Euler update, for the ballistic update
793  // the distance covered in the coming step depends on the current velocity, in general.
794  // one exception is the situation when the vehicle is just being inserted.
795  // In that case, it will not cover any distance until the next timestep by convention.
796 
797  // We treat the latter case first:
798  if (onInsertion) {
799  // The distance covered with constant insertion speed v0 until time tau is given as
800  // G1 = tau*v0
801  // The distance covered between time tau and the stopping moment at time tau+v0/b is
802  // G2 = v0^2/(2b),
803  // where b is an assumed constant deceleration (= myDecel)
804  // We solve g = G1 + G2 for v0:
805  const double btau = myDecel * headway;
806  const double v0 = -btau + sqrt(btau * btau + 2 * myDecel * g);
807  return v0;
808  }
809 
810  // In the usual case during the driving task, the vehicle goes by
811  // a current speed v0=v, and we seek to determine a safe acceleration a (possibly <0)
812  // such that starting to break after accelerating with a for the time tau=headway
813  // still allows us to stop in time.
814 
815  const double tau = headway;
816  const double v0 = MAX2(0., v);
817  // We first consider the case that a stop has to take place within time tau
818  if (v0 * tau >= 2 * g) {
819  if (g == 0.) {
820  if (v0 > 0.) {
821  // indicate to brake as hard as possible
822  return -std::numeric_limits<double>::max();
823  } else {
824  // stay stopped
825  return 0.;
826  }
827  }
828  // In general we solve g = v0^2/(-2a), where the the rhs is the distance
829  // covered until stop when breaking with a<0
830  const double a = -v0 * v0 / (2 * g);
831  return v0 + a * TS;
832  }
833 
834  // The last case corresponds to a situation, where the vehicle may go with a positive
835  // speed v1 = v0 + tau*a after time tau.
836  // The distance covered until time tau is given as
837  // G1 = tau*(v0+v1)/2
838  // The distance covered between time tau and the stopping moment at time tau+v1/b is
839  // G2 = v1^2/(2b),
840  // where b is an assumed constant deceleration (= myDecel)
841  // We solve g = G1 + G2 for v1>0:
842  // <=> 0 = v1^2 + b*tau*v1 + b*tau*v0 - 2bg
843  // => v1 = -b*tau/2 + sqrt( (b*tau)^2/4 + b(2g - tau*v0) )
844 
845  const double btau2 = myDecel * tau / 2;
846  const double v1 = -btau2 + sqrt(btau2 * btau2 + myDecel * (2 * g - tau * v0));
847  const double a = (v1 - v0) / tau;
848  return v0 + a * TS;
849 }
850 
851 
853 double
854 MSCFModel::maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion) const {
855  // the speed is safe if allows the ego vehicle to come to a stop behind the leader even if
856  // the leaders starts braking hard until stopped
857  // unfortunately it is not sufficient to compare stopping distances if the follower can brake harder than the leader
858  // (the trajectories might intersect before both vehicles are stopped even if the follower has a shorter stopping distance than the leader)
859  // 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.
860  // @todo: this is a conservative estimate for safe speed which could be increased
861 
862 // // For negative gaps, we return the lowest meaningful value by convention
863 // // XXX: check whether this is desireable (changes test results, therefore I exclude it for now (Leo), refs. #2575)
864 
865 // // It must be done. Otherwise, negative gaps at high speeds can create nonsense results from the call to maximumSafeStopSpeed() below
866 
867 // if(gap<0){
868 // if(MSGlobals::gSemiImplicitEulerUpdate){
869 // return 0.;
870 // } else {
871 // return -INVALID_SPEED;
872 // }
873 // }
874 
875  // The following commented code is a variant to assure brief stopping behind a stopped leading vehicle:
876  // if leader is stopped, calculate stopSpeed without time-headway to prevent creeping stop
877  // NOTE: this can lead to the strange phenomenon (for the Krauss-model at least) that if the leader comes to a stop,
878  // the follower accelerates for a short period of time. Refs #2310 (Leo)
879  // const double headway = predSpeed > 0. ? myHeadwayTime : 0.;
880 
881  const double headway = myHeadwayTime;
882  double x = maximumSafeStopSpeed(gap + brakeGap(predSpeed, MAX2(myDecel, predMaxDecel), 0), egoSpeed, onInsertion, headway);
883 
884  if (myDecel != myEmergencyDecel && !onInsertion && !MSGlobals::gComputeLC) {
885  double origSafeDecel = SPEED2ACCEL(egoSpeed - x);
886  if (origSafeDecel > myDecel + NUMERICAL_EPS) {
887  // Braking harder than myDecel was requested -> calculate required emergency deceleration.
888  // Note that the resulting safeDecel can be smaller than the origSafeDecel, since the call to maximumSafeStopSpeed() above
889  // 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,
890  // such that braking harder than myDecel is required.
891 
892 #ifdef DEBUG_EMERGENCYDECEL
893  if (DEBUG_COND2) {
894  std::cout << SIMTIME << " initial vsafe=" << x
895  << " egoSpeed=" << egoSpeed << " (origSafeDecel=" << origSafeDecel << ")"
896  << " predSpeed=" << predSpeed << " (predDecel=" << predMaxDecel << ")"
897  << std::endl;
898  }
899 #endif
900 
901  double safeDecel = EMERGENCY_DECEL_AMPLIFIER * calculateEmergencyDeceleration(gap, egoSpeed, predSpeed, predMaxDecel);
902  // Don't be riskier than the usual method (myDecel <= safeDecel may occur, because a headway>0 is used above)
903  safeDecel = MAX2(safeDecel, myDecel);
904  // don't brake harder than originally planned (possible due to euler/ballistic mismatch)
905  safeDecel = MIN2(safeDecel, origSafeDecel);
906  x = egoSpeed - ACCEL2SPEED(safeDecel);
908  x = MAX2(x, 0.);
909  }
910 
911 #ifdef DEBUG_EMERGENCYDECEL
912  if (DEBUG_COND2) {
913  std::cout << " -> corrected emergency deceleration: " << safeDecel << " newVSafe=" << x << std::endl;
914  }
915 #endif
916 
917  }
918  }
919  assert(x >= 0 || !MSGlobals::gSemiImplicitEulerUpdate);
920  assert(!ISNAN(x));
921  return x;
922 }
923 
924 
925 double
926 MSCFModel::calculateEmergencyDeceleration(double gap, double egoSpeed, double predSpeed, double predMaxDecel) const {
927  // There are two cases:
928  // 1) Either, stopping in time is possible with a deceleration b <= predMaxDecel, then this value is returned
929  // 2) Or, b > predMaxDecel is required in this case the minimal value b allowing to stop safely under the assumption maxPredDecel=b is returned
930 
931  // Apparent braking distance for the leader
932  const double predBrakeDist = 0.5 * predSpeed * predSpeed / predMaxDecel;
933  // Required deceleration according to case 1)
934  const double b1 = 0.5 * egoSpeed * egoSpeed / (gap + predBrakeDist);
935 
936 #ifdef DEBUG_EMERGENCYDECEL
937  if (DEBUG_COND2) {
938  std::cout << SIMTIME << " calculateEmergencyDeceleration()"
939  << " gap=" << gap << " egoSpeed=" << egoSpeed << " predSpeed=" << predSpeed
940  << " predBrakeDist=" << predBrakeDist
941  << " b1=" << b1
942  << std::endl;
943  }
944 #endif
945 
946  if (b1 <= predMaxDecel) {
947  // Case 1) applies
948 #ifdef DEBUG_EMERGENCYDECEL
949  if (DEBUG_COND2) {
950  std::cout << " case 1 ..." << std::endl;
951  }
952 #endif
953  return b1;
954  }
955 #ifdef DEBUG_EMERGENCYDECEL
956  if (DEBUG_COND2) {
957  std::cout << " case 2 ...";
958  }
959 #endif
960 
961  // Case 2) applies
962  assert(gap < 0 || predSpeed < egoSpeed);
963  if (gap <= 0.) {
964  return - std::numeric_limits<double>::max();
965  }
966  // Required deceleration according to case 2)
967  const double b2 = 0.5 * (egoSpeed * egoSpeed - predSpeed * predSpeed) / gap;
968 
969 #ifdef DEBUG_EMERGENCYDECEL
970  if (DEBUG_COND2) {
971  std::cout << " b2=" << b2 << std::endl;
972  }
973 #endif
974  return b2;
975 }
976 
977 
978 
979 void
980 MSCFModel::applyHeadwayAndSpeedDifferencePerceptionErrors(const MSVehicle* const veh, double speed, double& gap, double& predSpeed, double predMaxDecel, const MSVehicle* const pred) const {
981  UNUSED_PARAMETER(speed);
982  UNUSED_PARAMETER(predMaxDecel);
983  assert(veh->hasDriverState());
984 
985  // Obtain perceived gap and headway from the driver state
986  const double perceivedGap = veh->getDriverState()->getPerceivedHeadway(gap, pred);
987  const double perceivedSpeedDifference = veh->getDriverState()->getPerceivedSpeedDifference(predSpeed - speed, gap, pred);
988 
989 #ifdef DEBUG_DRIVER_ERRORS
990  if DEBUG_COND {
991  if (!veh->getDriverState()->debugLocked()) {
992  veh->getDriverState()->lockDebug();
993  std::cout << SIMTIME << " veh '" << veh->getID() << "' -> MSCFModel_Krauss::applyHeadwayAndSpeedDifferencePerceptionErrors()\n"
994  << " speed=" << speed << " gap=" << gap << " leaderSpeed=" << predSpeed
995  << "\n perceivedGap=" << perceivedGap << " perceivedLeaderSpeed=" << speed + perceivedSpeedDifference
996  << " perceivedSpeedDifference=" << perceivedSpeedDifference
997  << std::endl;
998  const double exactFollowSpeed = followSpeed(veh, speed, gap, predSpeed, predMaxDecel);
999  const double errorFollowSpeed = followSpeed(veh, speed, perceivedGap, speed + perceivedSpeedDifference, predMaxDecel);
1000  const double accelError = SPEED2ACCEL(errorFollowSpeed - exactFollowSpeed);
1001  std::cout << " gapError=" << perceivedGap - gap << " dvError=" << perceivedSpeedDifference - (predSpeed - speed)
1002  << "\n resulting accelError: " << accelError << std::endl;
1003  veh->getDriverState()->unlockDebug();
1004  }
1005  }
1006 #endif
1007 
1008  gap = perceivedGap;
1009  predSpeed = speed + perceivedSpeedDifference;
1010 }
1011 
1012 
1013 void
1014 MSCFModel::applyHeadwayPerceptionError(const MSVehicle* const veh, double speed, double& gap) const {
1015  UNUSED_PARAMETER(speed);
1016  assert(veh->hasDriverState());
1017 
1018  // Obtain perceived gap from driver state
1019  const double perceivedGap = veh->getDriverState()->getPerceivedHeadway(gap);
1020 
1021 #ifdef DEBUG_DRIVER_ERRORS
1022  if DEBUG_COND {
1023  if (!veh->getDriverState()->debugLocked()) {
1024  veh->getDriverState()->lockDebug();
1025  std::cout << SIMTIME << " veh '" << veh->getID() << "' -> MSCFModel_Krauss::applyHeadwayPerceptionError()\n"
1026  << " speed=" << speed << " gap=" << gap << "\n perceivedGap=" << perceivedGap << std::endl;
1027  const double exactStopSpeed = stopSpeed(veh, speed, gap);
1028  const double errorStopSpeed = stopSpeed(veh, speed, perceivedGap);
1029  const double accelError = SPEED2ACCEL(errorStopSpeed - exactStopSpeed);
1030  std::cout << " gapError=" << perceivedGap - gap << "\n resulting accelError: " << accelError << std::endl;
1031  veh->getDriverState()->unlockDebug();
1032  }
1033  }
1034 #endif
1035 
1036  gap = perceivedGap;
1037 }
1038 
1039 
1040 
1041 
1042 
1043 /****************************************************************************/
static double speedAfterTime(const double t, const double oldSpeed, const double dist)
Calculates the speed after a time t [0,TS] given the initial speed and the distance traveled in an i...
Definition: MSCFModel.cpp:671
#define DIST2SPEED(x)
Definition: SUMOTime.h:50
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:492
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:854
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time tau (i...
Definition: MSCFModel.h:313
virtual double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false) const
Computes the vehicle&#39;s safe speed without a leader.
Definition: MSCFModel.cpp:268
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:79
long long int SUMOTime
Definition: SUMOTime.h:36
const MSVehicleType * myType
The type to which this model definition belongs to.
Definition: MSCFModel.h:587
#define SPEED2DIST(x)
Definition: SUMOTime.h:48
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:54
#define EMERGENCY_DECEL_AMPLIFIER
Definition: MSCFModel.h:35
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:565
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:245
Structure representing possible vehicle parameter.
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:27
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Definition: MSGlobals.h:121
MSCFModel(const MSVehicleType *vtype)
Constructor.
Definition: MSCFModel.cpp:56
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:239
T MAX2(T a, T b)
Definition: StdDefs.h:76
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
#define TS
Definition: SUMOTime.h:45
virtual double insertionStopSpeed(const MSVehicle *const veh, double speed, double gap) const
Computes the vehicle&#39;s safe speed for approaching an obstacle at insertion without constraints due to...
Definition: MSCFModel.cpp:290
static double avoidArrivalAccel(double dist, double time, double speed)
Computes the acceleration needed to arrive not before the given time.
Definition: MSCFModel.cpp:460
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:56
T MAX3(T a, T b, T c)
Definition: StdDefs.h:90
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:33
virtual double insertionFollowSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel) const
Computes the vehicle&#39;s safe speed (no dawdling) This method is used during the insertion stage...
Definition: MSCFModel.cpp:279
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:165
The car-following model and parameter.
Definition: MSVehicleType.h:66
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4307
#define SIMTIME
Definition: SUMOTime.h:65
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 getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:210
bool hasDriverState() const
Whether this vehicle is equipped with a MSDriverState.
Definition: MSVehicle.h:1000
static double distAfterTime(double t, double speed, double accel)
calculates the distance travelled after accelerating for time t
Definition: MSCFModel.cpp:351
double getActionStepLengthSecs() const
Returns the vehicle&#39;s action step length in secs, i.e. the interval between two action points...
Definition: MSVehicle.h:517
#define ACCEL2DIST(x)
Definition: SUMOTime.h:52
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:256
static double brakeGapEuler(const double speed, const double decel, const double headwayTime)
Definition: MSCFModel.cpp:90
double getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
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:224
T MIN2(T a, T b)
Definition: StdDefs.h:70
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:218
double calculateEmergencyDeceleration(double gap, double egoSpeed, double predSpeed, double predMaxDecel) const
Returns the minimal deceleration for following the given leader safely.
Definition: MSCFModel.cpp:926
double maximumSafeStopSpeed(double gap, double currentSpeed, bool onInsertion=false, double headway=-1) const
Returns the maximum next velocity for stopping within gap.
Definition: MSCFModel.cpp:709
double getMinimalArrivalSpeedEuler(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance for Euler update...
Definition: MSCFModel.cpp:484
T ISNAN(T a)
Definition: StdDefs.h:111
double myDecel
The vehicle&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:593
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&#39;s driver state...
Definition: MSCFModel.cpp:980
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:503
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:247
virtual ~MSCFModel()
Destructor.
Definition: MSCFModel.cpp:68
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:597
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
Definition: MSVehicle.cpp:1646
double maximumSafeStopSpeedBallistic(double gap, 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:787
virtual double getHeadwayTime() const
Get the driver&#39;s desired headway [s].
Definition: MSCFModel.h:259
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:389
double myEmergencyDecel
The vehicle&#39;s maximum emergency deceleration [m/s^2].
Definition: MSCFModel.h:595
double getMinimalArrivalSpeed(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance.
Definition: MSCFModel.cpp:477
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:376
#define INVALID_SPEED
Definition: MSCFModel.h:33
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:60
virtual double followSpeedTransient(double duration, const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel) const
Computes the vehicle&#39;s follow speed that avoids a collision for the given amount of time...
Definition: MSCFModel.cpp:300
double estimateSpeedAfterDistance(const double dist, const double v, const double accel) const
Definition: MSCFModel.cpp:700
virtual double patchSpeedBeforeLC(const MSVehicle *veh, double vMin, double vMax) const
apply custom speed adaptations within the given speed bounds
Definition: MSCFModel.h:89
#define DEBUG_COND
Definition: MSCFModel.cpp:46
bool gDebugFlag2
Definition: StdDefs.cpp:33
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:56
std::shared_ptr< MSSimpleDriverState > getDriverState() const
Returns the vehicle driver&#39;s state.
Definition: MSVehicle.h:900
T MIN3(T a, T b, T c)
Definition: StdDefs.h:83
#define NUMERICAL_EPS
Definition: config.h:148
const double INVALID_DOUBLE
Definition: StdDefs.h:62
double myHeadwayTime
The driver&#39;s desired time headway (aka reaction time tau) [s].
Definition: MSCFModel.h:602
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:483
double maximumSafeStopSpeedEuler(double gap, double headway=-1) const
Returns the maximum next velocity for stopping within gap when using the semi-implicit Euler update...
Definition: MSCFModel.cpp:759
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const =0
Computes the vehicle&#39;s follow speed (no dawdling)
const std::string & getID() const
Returns the name of the vehicle.
void applyHeadwayPerceptionError(const MSVehicle *const veh, double speed, double &gap) const
Overwrites gap by the perceived value obtained from the vehicle&#39;s driver state.
Definition: MSCFModel.cpp:1014
#define DEBUG_COND2
Definition: MSCFModel.cpp:49
virtual double stopSpeed(const MSVehicle *const veh, const double speed, double gap) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...