SUMO - Simulation of Urban MObility
MSCFModel_Wiedemann.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00008 // The psycho-physical model of Wiedemann
00009 // references:
00010 // Andre Stebens - Traffic simulation with the Wiedemann model
00011 // Werner - Integration von Fahrzeugfolge- und Fahrstreifenwechselmodellen in die Nachtfahrsimulation LucidDrive
00012 // Olstam, Tapani - Comparison of Car-following models
00013 /****************************************************************************/
00014 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00015 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00016 /****************************************************************************/
00017 //
00018 //   This file is part of SUMO.
00019 //   SUMO is free software: you can redistribute it and/or modify
00020 //   it under the terms of the GNU General Public License as published by
00021 //   the Free Software Foundation, either version 3 of the License, or
00022 //   (at your option) any later version.
00023 //
00024 /****************************************************************************/
00025 
00026 
00027 // ===========================================================================
00028 // included modules
00029 // ===========================================================================
00030 #ifdef _MSC_VER
00031 #include <windows_config.h>
00032 #else
00033 #include <config.h>
00034 #endif
00035 
00036 #include <cmath>
00037 #include "MSCFModel_Wiedemann.h"
00038 #include <microsim/MSVehicle.h>
00039 #include <microsim/MSLane.h>
00040 #include <utils/common/RandHelper.h>
00041 
00042 
00043 // ===========================================================================
00044 // static members
00045 // ===========================================================================
00046 
00047 // magic constant proposed by Wiedemann (based on real world measurements)
00048 const SUMOReal MSCFModel_Wiedemann::D_MAX = 150;
00049 
00050 
00051 // ===========================================================================
00052 // method definitions
00053 // ===========================================================================
00054 MSCFModel_Wiedemann::MSCFModel_Wiedemann(const MSVehicleType* vtype,
00055         SUMOReal accel, SUMOReal decel,
00056         SUMOReal security, SUMOReal estimation) :
00057     MSCFModel(vtype, accel, decel, 1.0),
00058     mySecurity(security),
00059     myEstimation(estimation),
00060     myAX(vtype->getLength() + 1. + 2. * security),
00061     myCX(25. *(1. + security + estimation)),
00062     myMinAccel(0.2 * myAccel) { // +noise?
00063 }
00064 
00065 
00066 MSCFModel_Wiedemann::~MSCFModel_Wiedemann() {}
00067 
00068 
00069 SUMOReal
00070 MSCFModel_Wiedemann::moveHelper(MSVehicle* const veh, SUMOReal vPos) const {
00071     const SUMOReal vNext = MSCFModel::moveHelper(veh, vPos);
00072     VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
00073     vars->accelSign = vNext > veh->getSpeed() ? 1. : -1.;
00074     return vNext;
00075 }
00076 
00077 
00078 SUMOReal
00079 MSCFModel_Wiedemann::followSpeed(const MSVehicle* const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal /*predMaxDecel*/) const {
00080     return _v(veh, predSpeed, gap2pred);
00081 }
00082 
00083 
00084 SUMOReal
00085 MSCFModel_Wiedemann::stopSpeed(const MSVehicle* const veh, SUMOReal gap) const {
00086     /* Wiedemann does not handle approaching junctions or stops very well:
00087      * regime approaching() fails when dv = 0 (i.e. a vehicle inserted with speed 0 does not accelerate to reach a stop)
00088      * for dv ~ 0 the standard decision tree will switch to following() which
00089      * does a lousy job of closing in on a stop / junction
00090      * hence we borrow from Krauss here
00091      */
00092     return MAX2(getSpeedAfterMaxDecel(veh->getSpeed()), MIN2(krauss_vsafe(gap, 0), maxNextSpeed(veh->getSpeed())));
00093 }
00094 
00095 
00096 SUMOReal
00097 MSCFModel_Wiedemann::interactionGap(const MSVehicle* const , SUMOReal vL) const {
00098     UNUSED_PARAMETER(vL);
00099     return D_MAX;
00100 }
00101 
00102 
00103 MSCFModel*
00104 MSCFModel_Wiedemann::duplicate(const MSVehicleType* vtype) const {
00105     return new MSCFModel_Wiedemann(vtype, myAccel, myDecel, mySecurity, myEstimation);
00106 }
00107 
00108 
00109 SUMOReal
00110 MSCFModel_Wiedemann::_v(const MSVehicle* veh, SUMOReal predSpeed, SUMOReal gap) const {
00111     const VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
00112     const SUMOReal dx = gap + myType->getLength(); // wiedemann uses brutto gap
00113     const SUMOReal v = veh->getSpeed();
00114     const SUMOReal vpref = veh->getMaxSpeed();
00115     const SUMOReal dv = v - predSpeed;
00116     const SUMOReal bx = myAX + (1 + 7 * mySecurity) * sqrt(v); // Harding propose a factor of  *.8 here
00117     const SUMOReal ex = 2 - myEstimation; // + RandHelper::randNorm(0.5, 0.15)
00118     const SUMOReal sdx = myAX + ex * (bx - myAX); 
00119     const SUMOReal sdv_root = (dx - myAX) / myCX;
00120     const SUMOReal sdv = sdv_root * sdv_root;
00121     const SUMOReal cldv = sdv * ex * ex;
00122     const SUMOReal opdv = cldv * (-1 - 2 * RandHelper::randNorm(0.5, 0.15));
00123     // select the regime, get new acceleration, compute new speed based
00124     SUMOReal accel;
00125     if (dx <= bx) {
00126         accel = emergency(dv, dx);
00127     } else if (dx < sdx) {
00128         if (dv > cldv) {
00129             accel = approaching(dv, dx, bx);
00130         } else if (dv > opdv) {
00131             accel = following(vars->accelSign);
00132         } else {
00133             accel = fullspeed(v, vpref, dx, bx);
00134         }
00135     } else {
00136         if (dv > sdv && dx < D_MAX) { //@note other versions have an disjunction instead of conjunction
00137             accel = approaching(dv, dx, bx);
00138         } else {
00139             accel = fullspeed(v, vpref, dx, bx);
00140         }
00141     }
00142     // since we have hard constrainst on accel we may as well use them here
00143     accel = MAX2(MIN2(accel, myAccel), -myDecel);
00144     const SUMOReal vNew = MAX2(SUMOReal(0), v + ACCEL2SPEED(accel)); // don't allow negative speeds
00145     return vNew;
00146 }
00147 
00148 
00149 SUMOReal
00150 MSCFModel_Wiedemann::fullspeed(SUMOReal v, SUMOReal vpref, SUMOReal dx, SUMOReal bx) const {
00151     SUMOReal bmax = 0.2 + 0.8 * myAccel * (7 - sqrt(v));
00152     // if veh just drifted out of a 'following' process the acceleration is reduced
00153     SUMOReal accel = dx <= 2 * bx ? MIN2(myMinAccel, bmax * (dx - bx) / bx) : bmax;
00154     if (v > vpref) {
00155         accel = - accel;
00156     }
00157     return accel;
00158 }
00159 
00160 
00161 SUMOReal
00162 MSCFModel_Wiedemann::following(SUMOReal sign) const {
00163     return myMinAccel * sign;
00164 }
00165 
00166 
00167 SUMOReal
00168 MSCFModel_Wiedemann::approaching(SUMOReal dv, SUMOReal dx, SUMOReal bx) const {
00169     // there is singularity in the formula. we do the sanity check outside
00170     return 0.5 * dv * dv / (bx - dx); // + predAccel at t-reaction_time if this is value is above a treshold
00171 }
00172 
00173 
00174 SUMOReal
00175 MSCFModel_Wiedemann::emergency(SUMOReal dv, SUMOReal dx) const {
00176     /* emergency according to A.Stebens
00177     // wiedemann assumes that dx will always be larger than myAX (sumo may
00178     // violate this assumption when crashing (-:
00179     if (dx > myAX) {
00180         SUMOReal accel = 0.5 * dv * dv / (myAX - dx); // + predAccel at t-reaction_time if this is value is above a treshold
00181         // one would assume that in an emergency accel must be negative. However the
00182         // wiedemann formula allows for accel = 0 whenever dv = 0
00183         assert(accel <= 0);
00184         return accel;
00185     } else {
00186         return = -myDecel;
00187     }
00188     */
00189 
00190     // emergency according to C.Werner
00191     return -myDecel;
00192 }
00193 
00194 
00195 SUMOReal
00196 MSCFModel_Wiedemann::krauss_vsafe(SUMOReal gap, SUMOReal predSpeed) const {
00197     if (predSpeed == 0 && gap < 0.01) {
00198         return 0;
00199     }
00200     const SUMOReal tauDecel = myDecel * myHeadwayTime;
00201     const SUMOReal speedReduction = ACCEL2SPEED(myDecel);
00202     const int predSteps = int(predSpeed / speedReduction);
00203     const SUMOReal leaderContrib = 2. * myDecel * (gap + SPEED2DIST(predSteps * predSpeed - speedReduction * predSteps * (predSteps + 1) / 2));
00204     return (SUMOReal)(-tauDecel + sqrt(tauDecel * tauDecel + leaderContrib));
00205 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines