SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSCFModel_Wiedemann.cpp
Go to the documentation of this file.
1 /****************************************************************************/
8 // The psycho-physical model of Wiedemann
9 // references:
10 // Andre Stebens - Traffic simulation with the Wiedemann model
11 // Werner - Integration von Fahrzeugfolge- und Fahrstreifenwechselmodellen in die Nachtfahrsimulation LucidDrive
12 // Olstam, Tapani - Comparison of Car-following models
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
15 // Copyright (C) 2001-2012 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 <cmath>
37 #include "MSCFModel_Wiedemann.h"
38 #include <microsim/MSVehicle.h>
39 #include <microsim/MSLane.h>
41 
42 
43 // ===========================================================================
44 // static members
45 // ===========================================================================
46 
47 // magic constant proposed by Wiedemann (based on real world measurements)
49 
50 
51 // ===========================================================================
52 // method definitions
53 // ===========================================================================
55  SUMOReal accel, SUMOReal decel,
56  SUMOReal security, SUMOReal estimation) :
57  MSCFModel(vtype, accel, decel, 1.0),
58  mySecurity(security),
59  myEstimation(estimation),
60  myAX(vtype->getLength() + 1. + 2. * security),
61  myCX(25. *(1. + security + estimation)),
62  myMinAccel(0.2 * myAccel) { // +noise?
63 }
64 
65 
67 
68 
71  const SUMOReal vNext = MSCFModel::moveHelper(veh, vPos);
73  vars->accelSign = vNext > veh->getSpeed() ? 1. : -1.;
74  return vNext;
75 }
76 
77 
79 MSCFModel_Wiedemann::followSpeed(const MSVehicle* const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal /*predMaxDecel*/) const {
80  return _v(veh, predSpeed, gap2pred);
81 }
82 
83 
85 MSCFModel_Wiedemann::stopSpeed(const MSVehicle* const veh, SUMOReal gap) const {
86  /* Wiedemann does not handle approaching junctions or stops very well:
87  * regime approaching() fails when dv = 0 (i.e. a vehicle inserted with speed 0 does not accelerate to reach a stop)
88  * for dv ~ 0 the standard decision tree will switch to following() which
89  * does a lousy job of closing in on a stop / junction
90  * hence we borrow from Krauss here
91  */
92  return MAX2(getSpeedAfterMaxDecel(veh->getSpeed()), MIN2(krauss_vsafe(gap, 0), maxNextSpeed(veh->getSpeed())));
93 }
94 
95 
98  UNUSED_PARAMETER(vL);
99  return D_MAX;
100 }
101 
102 
103 MSCFModel*
106 }
107 
108 
109 SUMOReal
110 MSCFModel_Wiedemann::_v(const MSVehicle* veh, SUMOReal predSpeed, SUMOReal gap) const {
112  const SUMOReal dx = gap + myType->getLength(); // wiedemann uses brutto gap
113  const SUMOReal v = veh->getSpeed();
114  const SUMOReal vpref = veh->getMaxSpeed();
115  const SUMOReal dv = v - predSpeed;
116  const SUMOReal bx = myAX + (1 + 7 * mySecurity) * sqrt(v); // Harding propose a factor of *.8 here
117  const SUMOReal ex = 2 - myEstimation; // + RandHelper::randNorm(0.5, 0.15)
118  const SUMOReal sdx = myAX + ex * (bx - myAX);
119  const SUMOReal sdv_root = (dx - myAX) / myCX;
120  const SUMOReal sdv = sdv_root * sdv_root;
121  const SUMOReal cldv = sdv * ex * ex;
122  const SUMOReal opdv = cldv * (-1 - 2 * RandHelper::randNorm(0.5, 0.15));
123  // select the regime, get new acceleration, compute new speed based
124  SUMOReal accel;
125  if (dx <= bx) {
126  accel = emergency(dv, dx);
127  } else if (dx < sdx) {
128  if (dv > cldv) {
129  accel = approaching(dv, dx, bx);
130  } else if (dv > opdv) {
131  accel = following(vars->accelSign);
132  } else {
133  accel = fullspeed(v, vpref, dx, bx);
134  }
135  } else {
136  if (dv > sdv && dx < D_MAX) { //@note other versions have an disjunction instead of conjunction
137  accel = approaching(dv, dx, bx);
138  } else {
139  accel = fullspeed(v, vpref, dx, bx);
140  }
141  }
142  // since we have hard constrainst on accel we may as well use them here
143  accel = MAX2(MIN2(accel, myAccel), -myDecel);
144  const SUMOReal vNew = MAX2(SUMOReal(0), v + ACCEL2SPEED(accel)); // don't allow negative speeds
145  return vNew;
146 }
147 
148 
149 SUMOReal
151  SUMOReal bmax = 0.2 + 0.8 * myAccel * (7 - sqrt(v));
152  // if veh just drifted out of a 'following' process the acceleration is reduced
153  SUMOReal accel = dx <= 2 * bx ? MIN2(myMinAccel, bmax * (dx - bx) / bx) : bmax;
154  if (v > vpref) {
155  accel = - accel;
156  }
157  return accel;
158 }
159 
160 
161 SUMOReal
163  return myMinAccel * sign;
164 }
165 
166 
167 SUMOReal
169  // there is singularity in the formula. we do the sanity check outside
170  return 0.5 * dv * dv / (bx - dx); // + predAccel at t-reaction_time if this is value is above a treshold
171 }
172 
173 
174 SUMOReal
176  /* emergency according to A.Stebens
177  // wiedemann assumes that dx will always be larger than myAX (sumo may
178  // violate this assumption when crashing (-:
179  if (dx > myAX) {
180  SUMOReal accel = 0.5 * dv * dv / (myAX - dx); // + predAccel at t-reaction_time if this is value is above a treshold
181  // one would assume that in an emergency accel must be negative. However the
182  // wiedemann formula allows for accel = 0 whenever dv = 0
183  assert(accel <= 0);
184  return accel;
185  } else {
186  return = -myDecel;
187  }
188  */
189 
190  // emergency according to C.Werner
191  return -myDecel;
192 }
193 
194 
195 SUMOReal
197  if (predSpeed == 0 && gap < 0.01) {
198  return 0;
199  }
200  const SUMOReal tauDecel = myDecel * myHeadwayTime;
201  const SUMOReal speedReduction = ACCEL2SPEED(myDecel);
202  const int predSteps = int(predSpeed / speedReduction);
203  const SUMOReal leaderContrib = 2. * myDecel * (gap + SPEED2DIST(predSteps * predSpeed - speedReduction * predSteps * (predSteps + 1) / 2));
204  return (SUMOReal)(-tauDecel + sqrt(tauDecel * tauDecel + leaderContrib));
205 }