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