SUMO - Simulation of Urban MObility
|
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 }