SUMO - Simulation of Urban MObility
MSCFModel.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 // The car-following model abstraction
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
15 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #include <math.h>
37 #include <microsim/MSGlobals.h>
38 #include <microsim/MSVehicleType.h>
39 #include <microsim/MSVehicle.h>
40 #include <microsim/MSLane.h>
42 #include "MSCFModel.h"
43 
44 
45 // ===========================================================================
46 // method definitions
47 // ===========================================================================
48 MSCFModel::MSCFModel(const MSVehicleType* vtype, double accel,
49  double decel, double emergencyDecel, double apparentDecel, double headwayTime) :
50  myType(vtype),
51  myAccel(accel),
52  myDecel(decel),
53  myEmergencyDecel(emergencyDecel),
54  myApparentDecel(apparentDecel),
55  myHeadwayTime(headwayTime) {
56 }
57 
58 
60 
61 
63 
64 
65 double
66 MSCFModel::brakeGap(const double speed, const double decel, const double headwayTime) {
68  /* one possibility to speed this up is to calculate speedReduction * steps * (steps+1) / 2
69  for small values of steps (up to 10 maybe) and store them in an array */
70  const double speedReduction = ACCEL2SPEED(decel);
71  const int steps = int(speed / speedReduction);
72  return SPEED2DIST(steps * speed - speedReduction * steps * (steps + 1) / 2) + speed * headwayTime;
73  } else {
74  // ballistic
75  if (speed <= 0) {
76  return 0.;
77  } else {
78  return speed * (headwayTime + 0.5 * speed / decel);
79  }
80  }
81 }
82 
83 
84 double
85 MSCFModel::freeSpeed(const double currentSpeed, const double decel, const double dist, const double targetSpeed, const bool onInsertion) {
86  // XXX: (Leo) This seems to be exclusively called with decel = myDecel (max deceleration) and is not overridden
87  // by any specific CFModel. That may cause undesirable hard braking (at junctions where the vehicle
88  // changes to a road with a lower speed limit).
89 
91  // adapt speed to succeeding lane, no reaction time is involved
92  // when breaking for y steps the following distance g is covered
93  // (drive with v in the final step)
94  // g = (y^2 + y) * 0.5 * b + y * v
95  // y = ((((sqrt((b + 2.0*v)*(b + 2.0*v) + 8.0*b*g)) - b)*0.5 - v)/b)
96  const double v = SPEED2DIST(targetSpeed);
97  if (dist < v) {
98  return targetSpeed;
99  }
100  const double b = ACCEL2DIST(decel);
101  const double y = MAX2(0.0, ((sqrt((b + 2.0 * v) * (b + 2.0 * v) + 8.0 * b * dist) - b) * 0.5 - v) / b);
102  const double yFull = floor(y);
103  const double exactGap = (yFull * yFull + yFull) * 0.5 * b + yFull * v + (y > yFull ? v : 0.0);
104  const double fullSpeedGain = (yFull + (onInsertion ? 1. : 0.)) * ACCEL2SPEED(decel);
105  return DIST2SPEED(MAX2(0.0, dist - exactGap) / (yFull + 1)) + fullSpeedGain + targetSpeed;
106  } else {
107  // ballistic update (Leo)
108  // calculate maximum next speed vN that is adjustable to vT=targetSpeed after a distance d=dist
109  // and given a maximal deceleration b=decel, denote the current speed by v0.
110  // the distance covered by a trajectory that attains vN in the next timestep and decelerates afterwards
111  // with b is given as
112  // d = 0.5*dt*(v0+vN) + (t-dt)*vN - 0.5*b*(t-dt)^2, (1)
113  // where time t of arrival at d with speed vT is
114  // t = dt + (vN-vT)/b. (2)
115  // We insert (2) into (1) to obtain
116  // d = 0.5*dt*(v0+vN) + vN*(vN-vT)/b - 0.5*b*((vN-vT)/b)^2
117  // 0 = (dt*b*v0 - vT*vT - 2*b*d) + dt*b*vN + vN*vN
118  // and solve for vN
119 
120  assert(currentSpeed >= 0);
121  assert(targetSpeed >= 0);
122 
123  const double dt = onInsertion ? 0 : TS; // handles case that vehicle is inserted just now (at the end of move)
124  const double v0 = currentSpeed;
125  const double vT = targetSpeed;
126  const double b = decel;
127  const double d = dist - NUMERICAL_EPS; // prevent returning a value > targetSpeed due to rounding errors
128 
129  // Solvability for positive vN (if d is small relative to v0):
130  // 1) If 0.5*(v0+vT)*dt > d, we set vN=vT.
131  // (In case vT<v0, this implies that on the interpolated trajectory there are points beyond d where
132  // the interpolated velocity is larger than vT, but at least on the temporal discretization grid, vT is not exceeded)
133  // 2) We ignore the (possible) constraint vN >= v0 - b*dt, which could lead to a problem if v0 - t*b > vT.
134  // (moveHelper() is responsible for assuring that the next velocity is chosen in accordance with maximal decelerations)
135 
136  if (0.5 * (v0 + vT)*dt >= d) {
137  return vT; // (#)
138  }
139 
140  const double q = ((dt * v0 - 2 * d) * b - vT * vT); // (q < 0 is fulfilled because of (#))
141  const double p = 0.5 * b * dt;
142  return -p + sqrt(p * p - q);
143  }
144 }
145 
146 double
147 MSCFModel::moveHelper(MSVehicle* const veh, double vPos) const {
148  const double oldV = veh->getSpeed(); // save old v for optional acceleration computation
149  const double vSafe = MIN2(vPos, veh->processNextStop(vPos)); // process stops
150  // we need the acceleration for emission computation;
151  // in this case, we neglect dawdling, nonetheless, using
152  // vSafe does not incorporate speed reduction due to interaction
153  // on lane changing
154  double vMin, vNext;
155  const double vMax = MIN3(veh->getMaxSpeedOnLane(), maxNextSpeed(oldV, veh), vSafe);
157  // we cannot rely on never braking harder than maxDecel because TraCI or strange cf models may decide to do so
158  vMin = MIN2(getSpeedAfterMaxDecel(oldV), vMax);
159  vNext = veh->getLaneChangeModel().patchSpeed(vMin, vMax, vMax, *this);
160  } else {
161  // for ballistic update, negative vnext must be allowed to
162  // indicate a stop within the coming timestep (i.e., to attain negative values)
163  vMin = MIN2(minNextSpeed(oldV, veh), vMax);
164  vNext = veh->getLaneChangeModel().patchSpeed(vMin, vMax, vMax, *this);
165  // (Leo) moveHelper() is responsible for assuring that the next
166  // velocity is chosen in accordance with maximal decelerations.
167  // At this point vNext may also be negative indicating a stop within next step.
168  // Moreover, because maximumSafeStopSpeed() does not consider deceleration bounds
169  // vNext can be a large negative value at this point. We cap vNext here.
170  vNext = MAX2(vNext, vMin);
171  }
172 
173  return vNext;
174 }
175 
176 
177 double
178 MSCFModel::interactionGap(const MSVehicle* const veh, double vL) const {
179  // Resolve the vsafe equation to gap. Assume predecessor has
180  // speed != 0 and that vsafe will be the current speed plus acceleration,
181  // i.e that with this gap there will be no interaction.
182  const double vNext = MIN2(maxNextSpeed(veh->getSpeed(), veh), veh->getLane()->getVehicleMaxSpeed(veh));
183  const double gap = (vNext - vL) *
184  ((veh->getSpeed() + vL) / (2.*myDecel) + myHeadwayTime) +
185  vL * myHeadwayTime;
186 
187  // Don't allow timeHeadWay < deltaT situations.
188  return MAX2(gap, SPEED2DIST(vNext));
189 }
190 
191 
192 double
193 MSCFModel::maxNextSpeed(double speed, const MSVehicle* const /*veh*/) const {
194  return MIN2(speed + (double) ACCEL2SPEED(getMaxAccel()), myType->getMaxSpeed());
195 }
196 
197 double
198 MSCFModel::minNextSpeed(double speed, const MSVehicle* const /*veh*/) const {
200 // return MAX2(speed - ACCEL2SPEED(getMaxDecel()), 0.);
201  return MAX2(speed - ACCEL2SPEED(myEmergencyDecel), 0.);
202  } else {
203  // NOTE: ballistic update allows for negative speeds to indicate a stop within the next timestep
204 // return speed - ACCEL2SPEED(getMaxDecel());
205  return speed - ACCEL2SPEED(myEmergencyDecel);
206  }
207 }
208 
209 
210 double
211 MSCFModel::freeSpeed(const MSVehicle* const /* veh */, double speed, double seen, double maxSpeed, const bool onInsertion) const {
212  double vSafe = freeSpeed(speed, myDecel, seen, maxSpeed, onInsertion);
213  return vSafe;
214 }
215 
216 
217 double
218 MSCFModel::insertionFollowSpeed(const MSVehicle* const /* v */, double speed, double gap2pred, double predSpeed, double predMaxDecel) const {
220  return maximumSafeFollowSpeed(gap2pred, speed, predSpeed, predMaxDecel);
221  } else {
222  // NOTE: Even for ballistic update, the current speed is irrelevant at insertion, therefore passing 0. (Leo)
223  return maximumSafeFollowSpeed(gap2pred, 0., predSpeed, predMaxDecel, true);
224  }
225 }
226 
227 
228 double
229 MSCFModel::insertionStopSpeed(const MSVehicle* const veh, double speed, double gap) const {
231  return stopSpeed(veh, speed, gap);
232  } else {
233  return MIN2(maximumSafeStopSpeed(gap, 0., true, 0.), myType->getMaxSpeed());
234  }
235 }
236 
237 
238 SUMOTime
239 MSCFModel::getMinimalArrivalTime(double dist, double currentSpeed, double arrivalSpeed) const {
240  const double accel = (arrivalSpeed >= currentSpeed) ? getMaxAccel() : -getMaxDecel();
241  const double accelTime = (arrivalSpeed - currentSpeed) / accel;
242  const double accelWay = accelTime * (arrivalSpeed + currentSpeed) * 0.5;
243  const double nonAccelWay = MAX2(0., dist - accelWay);
244  // will either drive as fast as possible and decelerate as late as possible
245  // or accelerate as fast as possible and then hold that speed
246  const double nonAccelSpeed = MAX3(currentSpeed, arrivalSpeed, SUMO_const_haltingSpeed);
247  return TIME2STEPS(accelTime + nonAccelWay / nonAccelSpeed);
248 }
249 
250 
251 double
252 MSCFModel::getMinimalArrivalSpeed(double dist, double currentSpeed) const {
253  // ballistic update
254  return estimateSpeedAfterDistance(dist - currentSpeed * getHeadwayTime(), currentSpeed, -getMaxDecel());
255 }
256 
257 
258 double
259 MSCFModel::getMinimalArrivalSpeedEuler(double dist, double currentSpeed) const {
260  double arrivalSpeedBraking;
261  // Because we use a continuous formula for computing the possible slow-down
262  // we need to handle the mismatch with the discrete dynamics
263  if (dist < currentSpeed) {
264  arrivalSpeedBraking = INVALID_SPEED; // no time left for braking after this step
265  // (inserted max() to get rid of arrivalSpeed dependency within method) (Leo)
266  } else if (2 * (dist - currentSpeed * getHeadwayTime()) * -getMaxDecel() + currentSpeed * currentSpeed >= 0) {
267  arrivalSpeedBraking = estimateSpeedAfterDistance(dist - currentSpeed * getHeadwayTime(), currentSpeed, -getMaxDecel());
268  } else {
269  arrivalSpeedBraking = getMaxDecel();
270  }
271  return arrivalSpeedBraking;
272 }
273 
274 
275 
276 
277 double
278 MSCFModel::gapExtrapolation(const double duration, const double currentGap, double v1, double v2, double a1, double a2, const double maxV1, const double maxV2) {
279 
280  double newGap = currentGap;
281 
283  for (unsigned int steps = 1; steps * TS <= duration; ++steps) {
284  v1 = MIN2(MAX2(v1 + a1, 0.), maxV1);
285  v2 = MIN2(MAX2(v2 + a2, 0.), maxV2);
286  newGap += TS * (v1 - v2);
287  }
288  } else {
289  // determine times t1, t2 for which vehicles can break until stop (within duration)
290  // and t3, t4 for which they reach their maximal speed on their current lanes.
291  double t1 = 0, t2 = 0, t3 = 0, t4 = 0;
292 
293  // t1: ego veh stops
294  if (a1 < 0 && v1 > 0) {
295  const double leaderStopTime = - v1 / a1;
296  t1 = MIN2(leaderStopTime, duration);
297  } else if (a1 >= 0) {
298  t1 = duration;
299  }
300  // t2: veh2 stops
301  if (a2 < 0 && v2 > 0) {
302  const double followerStopTime = -v2 / a2;
303  t2 = MIN2(followerStopTime, duration);
304  } else if (a2 >= 0) {
305  t2 = duration;
306  }
307  // t3: ego veh reaches vMax
308  if (a1 > 0 && v1 < maxV1) {
309  const double leaderMaxSpeedTime = (maxV1 - v1) / a1;
310  t3 = MIN2(leaderMaxSpeedTime, duration);
311  } else if (a1 <= 0) {
312  t3 = duration;
313  }
314  // t4: veh2 reaches vMax
315  if (a2 > 0 && v2 < maxV2) {
316  const double followerMaxSpeedTime = (maxV2 - v2) / a2;
317  t4 = MIN2(followerMaxSpeedTime, duration);
318  } else if (a2 <= 0) {
319  t4 = duration;
320  }
321 
322  // NOTE: this assumes that the accelerations a1 and a2 are constant over the next
323  // followerBreakTime seconds (if no vehicle stops before or reaches vMax)
324  std::list<double> l;
325  l.push_back(t1);
326  l.push_back(t2);
327  l.push_back(t3);
328  l.push_back(t4);
329  l.sort();
330  std::list<double>::const_iterator i;
331  double tLast = 0.;
332  for (i = l.begin(); i != l.end(); ++i) {
333  if (*i != tLast) {
334  double dt = MIN2(*i, duration) - tLast; // time between *i and tLast
335  double dv = v1 - v2; // current velocity difference
336  double da = a1 - a2; // current acceleration difference
337  newGap += dv * dt + da * dt * dt / 2.; // update gap
338  v1 += dt * a1;
339  v2 += dt * a2;
340  }
341  if (*i == t1 || *i == t3) {
342  // ego veh reached velocity bound
343  a1 = 0.;
344  }
345 
346  if (*i == t2 || *i == t4) {
347  // veh2 reached velocity bound
348  a2 = 0.;
349  }
350 
351  tLast = MIN2(*i, duration);
352  if (tLast == duration) {
353  break;
354  }
355  }
356 
357  if (duration != tLast) {
358  // (both vehicles have zero acceleration)
359  assert(a1 == 0. && a2 == 0.);
360  double dt = duration - tLast; // remaining time until duration
361  double dv = v1 - v2; // current velocity difference
362  newGap += dv * dt; // update gap
363  }
364  }
365 
366  return newGap;
367 }
368 
369 
370 
371 double
372 MSCFModel::passingTime(const double lastPos, const double passedPos, const double currentPos, const double lastSpeed, const double currentSpeed) {
373 
374  assert(passedPos <= currentPos && passedPos >= lastPos && currentPos > lastPos);
375  assert(currentSpeed >= 0);
376 
377  if (passedPos > currentPos || passedPos < lastPos) {
378  std::stringstream ss;
379  // Debug (Leo)
381  // NOTE: error is guarded to maintain original test output for euler update (Leo).
382  ss << "passingTime(): given argument passedPos = " << passedPos << " doesn't lie within [lastPos, currentPos] = [" << lastPos << ", " << currentPos << "]\nExtrapolating...";
383  std::cout << ss.str() << "\n";
384  WRITE_ERROR(ss.str());
385  }
386  const double lastCoveredDist = currentPos - lastPos;
387  const double extrapolated = passedPos > currentPos ? TS * (passedPos - lastPos) / lastCoveredDist : TS * (currentPos - passedPos) / lastCoveredDist;
388  return extrapolated;
389  } else if (currentSpeed < 0) {
390  WRITE_ERROR("passingTime(): given argument 'currentSpeed' is negative. This case is not handled yet.");
391  return -1;
392  }
393 
394  const double distanceOldToPassed = passedPos - lastPos; // assert: >=0
395 
397  // euler update (constantly moving with currentSpeed during [0,TS])
398  const double t = distanceOldToPassed / currentSpeed;
399  return MIN2(TS, MAX2(0., t)); //rounding errors could give results out of the admissible result range
400 
401  } else {
402  // ballistic update (constant acceleration a during [0,TS], except in case of a stop)
403 
404  // determine acceleration
405  double a;
406  if (currentSpeed > 0) {
407  // the acceleration was constant within the last time step
408  a = SPEED2ACCEL(currentSpeed - lastSpeed);
409  } else {
410  // the currentSpeed is zero (the last was not because lastPos<currentPos).
411  assert(currentSpeed == 0 && lastSpeed != 0);
412  // In general the stop has taken place within the last time step.
413  // The acceleration (a<0) is obtained from
414  // deltaPos = - lastSpeed^2/(2*a)
415  a = lastSpeed * lastSpeed / (2 * (lastPos - currentPos));
416 
417  assert(a < 0);
418  }
419 
420  // determine passing time t
421  // we solve distanceOldToPassed = lastSpeed*t + a*t^2/2
422  if (fabs(a) < NUMERICAL_EPS) {
423  // treat as constant speed within [0, TS]
424  const double t = 2 * distanceOldToPassed / (lastSpeed + currentSpeed);
425  return MIN2(TS, MAX2(0., t)); //rounding errors could give results out of the admissible result range
426  } else if (a > 0) {
427  // positive acceleration => only one positive solution
428  const double va = lastSpeed / a;
429  const double t = -va + sqrt(va * va + 2 * distanceOldToPassed / a);
430  assert(t < 1 && t >= 0);
431  return t;
432  } else {
433  // negative acceleration => two positive solutions (pick the smaller one.)
434  const double va = lastSpeed / a;
435  const double t = -va - sqrt(va * va + 2 * distanceOldToPassed / a);
436  assert(t < 1 && t >= 0);
437  return t;
438  }
439  }
440 }
441 
442 
443 double
444 MSCFModel::speedAfterTime(const double t, const double v0, const double dist) {
445  assert(dist >= 0);
446  assert(t >= 0 && t <= TS);
448  // euler: constant speed within [0,TS]
449  return DIST2SPEED(dist);
450  } else {
451  // ballistic: piecewise constant acceleration in [0,TS] (may become 0 for a stop within TS)
452  // We reconstruct acceleration at time t=0. Note that the covered distance in case
453  // of a stop exactly at t=TS is TS*v0/2.
454  if (dist < TS * v0 / 2) {
455  // stop must have occured within [0,TS], use dist = -v0^2/(2a) (stopping dist),
456  // i.e., a = -v0^2/(2*dist)
457  const double accel = - v0 * v0 / (2 * dist);
458  // The speed at time t is then
459  return v0 + accel * t;
460  } else {
461  // no stop occured within [0,TS], thus (from dist = v0*TS + accel*TS^2/2)
462  const double accel = 2 * (dist / TS - v0) / TS;
463  // The speed at time t is then
464  return v0 + accel * t;
465  }
466  }
467 }
468 
469 
470 
471 
472 double
473 MSCFModel::estimateSpeedAfterDistance(const double dist, const double v, const double accel) const {
474  // dist=v*t + 0.5*accel*t^2, solve for t and use v1 = v + accel*t
475  return MAX2(0., MIN2(myType->getMaxSpeed(),
476  (double)sqrt(2 * dist * accel + v * v)));
477 }
478 
479 
480 
481 double
482 MSCFModel::maximumSafeStopSpeed(double g /*gap*/, double v /*currentSpeed*/, bool onInsertion, double headway) const {
484  return maximumSafeStopSpeedEuler(g);
485  } else {
486  return maximumSafeStopSpeedBallistic(g, v, onInsertion, headway);
487  }
488 }
489 
490 
491 double
493  gap -= NUMERICAL_EPS; // lots of code relies on some slack XXX: it shouldn't...
494  if (gap <= 0) {
495  return 0;
496  } else if (gap <= ACCEL2SPEED(myDecel)) {
497  // workaround for #2310
498  return MIN2(ACCEL2SPEED(myDecel), DIST2SPEED(gap));
499  }
500  const double g = gap;
501  const double b = ACCEL2SPEED(myDecel);
502  const double t = myHeadwayTime;
503  const double s = TS;
504 
505 
506  // h = the distance that would be covered if it were possible to stop
507  // exactly after gap and decelerate with b every simulation step
508  // h = 0.5 * n * (n-1) * b * s + n * b * t (solve for n)
509  //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));
510  const double n = floor(.5 - ((t + (sqrt(((s * s) + (4.0 * ((s * (2.0 * g / b - t)) + (t * t))))) * -0.5)) / s));
511  const double h = 0.5 * n * (n - 1) * b * s + n * b * t;
512  assert(h <= g + NUMERICAL_EPS);
513  // compute the additional speed that must be used during deceleration to fix
514  // the discrepancy between g and h
515  const double r = (g - h) / (n * s + t);
516  const double x = n * b + r;
517  assert(x >= 0);
518  return x;
519 }
520 
521 
522 double
523 MSCFModel::maximumSafeStopSpeedBallistic(double g /*gap*/, double v /*currentSpeed*/, bool onInsertion, double headway) const {
524  // decrease gap slightly (to avoid passing end of lane by values of magnitude ~1e-12, when exact stop is required)
525  g = MAX2(0., g - NUMERICAL_EPS);
526  headway = headway >= 0 ? headway : myHeadwayTime;
527 
528  // (Leo) Note that in contrast to the Euler update, for the ballistic update
529  // the distance covered in the coming step depends on the current velocity, in general.
530  // one exception is the situation when the vehicle is just being inserted.
531  // In that case, it will not cover any distance until the next timestep by convention.
532 
533  // We treat the latter case first:
534  if (onInsertion) {
535  // The distance covered with constant insertion speed v0 until time tau is given as
536  // G1 = tau*v0
537  // The distance covered between time tau and the stopping moment at time tau+v0/b is
538  // G2 = v0^2/(2b),
539  // where b is an assumed constant deceleration (= myDecel)
540  // We solve g = G1 + G2 for v0:
541  const double btau = myDecel * headway;
542  const double v0 = -btau + sqrt(btau * btau + 2 * myDecel * g);
543  return v0;
544  }
545 
546  // In the usual case during the driving task, the vehicle goes by
547  // a current speed v0=v, and we seek to determine a safe acceleration a (possibly <0)
548  // such that starting to break after accelerating with a for the time tau
549  // still allows us to stop in time.
550 
551  const double tau = headway;
552  const double v0 = MAX2(0., v);
553  // We first consider the case that a stop has to take place within time tau
554  if (v0 * tau >= 2 * g) {
555  if (g == 0.) {
556  if (v0 > 0.) {
557  // indicate to brake as hard as possible
558  return -INVALID_SPEED;
559  } else {
560  // stay stopped
561  return 0.;
562  }
563  }
564  // In general we solve g = v0^2/(-2a), where the the rhs is the distance
565  // covered until stop when breaking with a<0
566  const double a = -v0 * v0 / (2 * g);
567  return v0 + a * TS;
568  }
569 
570  // The last case corresponds to a situation, where the vehicle may go with a positive
571  // speed v1 = v0 + tau*a after time tau.
572  // The distance covered until time tau is given as
573  // G1 = tau*(v0+v1)/2
574  // The distance covered between time tau and the stopping moment at time tau+v1/b is
575  // G2 = v1^2/(2b),
576  // where b is an assumed constant deceleration (= myDecel)
577  // We solve g = G1 + G2 for v1>0:
578  // <=> 0 = v1^2 + b*tau*v1 + b*tau*v0 - 2bg
579  // => v1 = -b*tau/2 + sqrt( (b*tau)^2/4 + b(2g - tau*v0) )
580 
581  const double btau2 = myDecel * tau / 2;
582  const double v1 = -btau2 + sqrt(btau2 * btau2 + myDecel * (2 * g - tau * v0));
583  const double a = (v1 - v0) / tau;
584  return v0 + a * TS;
585 }
586 
587 
589 double
590 MSCFModel::maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion) const {
591  // the speed is safe if allows the ego vehicle to come to a stop behind the leader even if
592  // the leaders starts braking hard until stopped
593  // unfortunately it is not sufficient to compare stopping distances if the follower can brake harder than the leader
594  // (the trajectories might intersect before both vehicles are stopped even if the follower has a shorter stopping distance than the leader)
595  // 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.
596  // @todo: this is a conservative estimate for safe speed which could be increased
597 
598 // // For negative gaps, we return the lowest meaningful value by convention
599 // // XXX: check whether this is desireable (changes test results, therefore I exclude it for now (Leo), refs. #2575)
600 // if(gap<0){
601 // if(MSGlobals::gSemiImplicitEulerUpdate){
602 // return 0.;
603 // } else {
604 // return -INVALID_SPEED;
605 // }
606 // }
607 
608  // The following commented code is a variant to assure brief stopping behind a stopped leading vehicle:
609  // if leader is stopped, calculate stopSpeed without time-headway to prevent creeping stop
610  // NOTE: this can lead to the strange phenomenon (for the Krauss-model at least) that if the leader comes to a stop,
611  // the follower accelerates for a short period of time. Refs #2310 (Leo)
612 // const double headway = predSpeed > 0. ? myHeadwayTime : 0.;
613 
614  const double headway = myHeadwayTime;
615  const double x = maximumSafeStopSpeed(gap + brakeGap(predSpeed, MAX2(myDecel, predMaxDecel), 0), egoSpeed, onInsertion, headway);
616  assert(x >= 0 || !MSGlobals::gSemiImplicitEulerUpdate);
617  assert(!ISNAN(x));
618  return x;
619 }
620 
621 
622 /****************************************************************************/
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:444
#define DIST2SPEED(x)
Definition: SUMOTime.h:57
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:462
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:590
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time, assuming that during...
Definition: MSCFModel.h:263
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:211
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
const MSVehicleType * myType
The type to which this model definition belongs to.
Definition: MSCFModel.h:463
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:61
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:488
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:198
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:193
T MAX2(T a, T b)
Definition: StdDefs.h:70
virtual double moveHelper(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences.
Definition: MSCFModel.cpp:147
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
#define TS
Definition: SUMOTime.h:52
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:229
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:63
T MAX3(T a, T b, T c)
Definition: StdDefs.h:84
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:218
The car-following model and parameter.
Definition: MSVehicleType.h:74
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:2921
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation...
Definition: MSVehicle.h:498
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.
double getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:193
#define ACCEL2DIST(x)
Definition: SUMOTime.h:59
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:178
T MIN2(T a, T b)
Definition: StdDefs.h:64
virtual double getSpeedAfterMaxDecel(double v) const
Returns the velocity after maximum deceleration.
Definition: MSCFModel.h:302
double getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
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:482
double getMinimalArrivalSpeedEuler(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance for Euler update...
Definition: MSCFModel.cpp:259
T ISNAN(T a)
Definition: StdDefs.h:105
double myDecel
The vehicle&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:469
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:278
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
virtual ~MSCFModel()
Destructor.
Definition: MSCFModel.cpp:59
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:372
double maximumSafeStopSpeedEuler(double gap) const
Returns the maximum next velocity for stopping within gap when using the semi-implicit Euler update...
Definition: MSCFModel.cpp:492
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
Definition: MSVehicle.cpp:1145
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:523
virtual double getHeadwayTime() const
Get the driver&#39;s reaction time [s].
Definition: MSCFModel.h:220
double myEmergencyDecel
The vehicle&#39;s maximum emergency deceleration [m/s^2].
Definition: MSCFModel.h:471
double getMinimalArrivalSpeed(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance.
Definition: MSCFModel.cpp:252
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:239
#define INVALID_SPEED
Definition: MSCFModel.h:40
MSCFModel(const MSVehicleType *vtype, double accel, double decel, double emergencyDecel, double apparentDecel, double headwayTime)
Constructor.
Definition: MSCFModel.cpp:48
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:56
double estimateSpeedAfterDistance(const double dist, const double v, const double accel) const
Definition: MSCFModel.cpp:473
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:63
T MIN3(T a, T b, T c)
Definition: StdDefs.h:77
long long int SUMOTime
Definition: TraCIDefs.h:52
#define NUMERICAL_EPS
Definition: config.h:151
double myHeadwayTime
The driver&#39;s desired time headway (aka reaction time tau) [s].
Definition: MSCFModel.h:476
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:442
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) ...