|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 // A lane change model developed by D. Krajzewicz between 2004 and 2010 00011 /****************************************************************************/ 00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00014 /****************************************************************************/ 00015 // 00016 // This file is part of SUMO. 00017 // SUMO is free software: you can redistribute it and/or modify 00018 // it under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation, either version 3 of the License, or 00020 // (at your option) any later version. 00021 // 00022 /****************************************************************************/ 00023 00024 00025 // =========================================================================== 00026 // included modules 00027 // =========================================================================== 00028 #ifdef _MSC_VER 00029 #include <windows_config.h> 00030 #else 00031 #include <config.h> 00032 #endif 00033 00034 #include "MSLCM_DK2004.h" 00035 #include <utils/common/RandHelper.h> 00036 #include <iostream> 00037 00038 #ifdef CHECK_MEMORY_LEAKS 00039 #include <foreign/nvwa/debug_new.h> 00040 #endif // CHECK_MEMORY_LEAKS 00041 00042 //#define DEBUG_VEHICLE_GUI_SELECTION 1 00043 #ifdef DEBUG_VEHICLE_GUI_SELECTION 00044 #include <utils/gui/div/GUIGlobalSelection.h> 00045 #include <guisim/GUIVehicle.h> 00046 #include <guisim/GUILane.h> 00047 #endif 00048 00049 00050 00051 // =========================================================================== 00052 // variable definitions 00053 // =========================================================================== 00054 // 80km/h will be the threshold for dividing between long/short foresight 00055 #define LOOK_FORWARD_SPEED_DIVIDER 14. 00056 00057 #define LOOK_FORWARD_FAR 15. 00058 #define LOOK_FORWARD_NEAR 5. 00059 00060 00061 00062 #define JAM_FACTOR 2. 00063 #define JAM_FACTOR2 1. 00064 00065 00066 // =========================================================================== 00067 // member method definitions 00068 // =========================================================================== 00069 MSLCM_DK2004::MSLCM_DK2004(MSVehicle& v) 00070 : MSAbstractLaneChangeModel(v), 00071 myChangeProbability(0), 00072 myLeadingBlockerLength(0), myLeftSpace(0) {} 00073 00074 MSLCM_DK2004::~MSLCM_DK2004() { 00075 changed(); 00076 } 00077 00078 00079 int 00080 MSLCM_DK2004::wantsChangeToRight(MSAbstractLaneChangeModel::MSLCMessager& msgPass, 00081 int blocked, 00082 const std::pair<MSVehicle*, SUMOReal> &leader, 00083 const std::pair<MSVehicle*, SUMOReal> &neighLead, 00084 const std::pair<MSVehicle*, SUMOReal> &neighFollow, 00085 const MSLane& neighLane, 00086 const std::vector<MSVehicle::LaneQ> &preb, 00087 MSVehicle** lastBlocked) { 00088 #ifdef DEBUG_VEHICLE_GUI_SELECTION 00089 if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) { 00090 int bla = 0; 00091 } 00092 #endif 00093 MSVehicle::LaneQ curr, best; 00094 int bestLaneOffset = 0; 00095 SUMOReal currentDist = 0; 00096 SUMOReal neighDist = 0; 00097 SUMOReal neighExtDist = 0; 00098 SUMOReal currExtDist = 0; 00099 int currIdx = 0; 00100 for (int p = 0; p < (int) preb.size(); ++p) { 00101 if (preb[p].lane == myVehicle.getLane()) { 00102 curr = preb[p]; 00103 bestLaneOffset = curr.bestLaneOffset; 00104 currentDist = curr.length; 00105 currExtDist = curr.lane->getLength(); 00106 neighDist = preb[p - 1].length; 00107 neighExtDist = preb[p - 1].lane->getLength(); 00108 best = preb[p + bestLaneOffset]; 00109 currIdx = p; 00110 } 00111 } 00112 00113 // keep information about being a leader/follower 00114 int ret = (myOwnState & 0x00ffff00); 00115 00116 if (leader.first != 0 00117 && 00118 (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0 00119 && 00120 (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) { 00121 00122 myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE); 00123 if (myVehicle.getSpeed() > 0.1) { 00124 myOwnState |= LCA_AMBACKBLOCKER; 00125 } else { 00126 ret |= LCA_AMBACKBLOCKER; 00127 myDontBrake = true; 00128 } 00129 } 00130 00131 // process information about the last blocked vehicle 00132 // if this vehicle is blocking someone in front, we maybe decelerate to let him in 00133 if ((*lastBlocked) != 0) { 00134 SUMOReal gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLengthWithGap() - myVehicle.getPositionOnLane(); 00135 if (gap > 0.1) { 00136 if (myVehicle.getSpeed() < ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) { 00137 if ((*lastBlocked)->getSpeed() < 0.1) { 00138 ret |= LCA_AMBACKBLOCKER_STANDING; 00139 } else { 00140 ret |= LCA_AMBACKBLOCKER; 00141 } 00142 myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (SUMOReal)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel())); 00143 (*lastBlocked) = 0; 00144 } 00145 return ret; 00146 } 00147 } 00148 00149 // we try to estimate the distance which is necessary to get on a lane 00150 // we have to get on in order to keep our route 00151 // we assume we need something that depends on our velocity 00152 // and compare this with the free space on our wished lane 00153 // 00154 // if the free space is somehow less than the space we need, we should 00155 // definitely try to get to the desired lane 00156 // 00157 // this rule forces our vehicle to change the lane if a lane changing is necessary soon 00158 SUMOReal rv = myVehicle.getSpeed() > LOOK_FORWARD_SPEED_DIVIDER 00159 ? myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_FAR 00160 : myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_NEAR; 00161 rv += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.; 00162 00163 SUMOReal tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (SUMOReal) JAM_FACTOR2; 00164 00165 if (fabs(best.length - curr.length) > MIN2((SUMOReal) .1, best.lane->getLength()) && bestLaneOffset < 0 && currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, rv)) { 00166 informBlocker(msgPass, blocked, LCA_MRIGHT, neighLead, neighFollow); 00167 if (neighLead.second > 0 && neighLead.second > leader.second) { 00168 myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (SUMOReal) 0.5); 00169 } 00170 00171 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, right 00172 // if there is a leader and he wants to change to left (we want to change to right) 00173 if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_LEFT) != 0) { 00174 // save at least his length in myLeadingBlockerLength 00175 myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength); 00176 // save the left space 00177 myLeftSpace = currentDist - myVehicle.getPositionOnLane(); 00178 } 00179 // 00180 00181 return ret | LCA_RIGHT | LCA_URGENT; 00182 } 00183 00184 00185 // the opposite lane-changing direction should be done than the one examined herein 00186 // we'll check whether we assume we could change anyhow and get back in time... 00187 // 00188 // this rule prevents the vehicle from moving in opposite direction of the best lane 00189 // unless the way till the end where the vehicle has to be on the best lane 00190 // is long enough 00191 SUMOReal maxJam = MAX2(preb[currIdx - 1].occupation, preb[currIdx].occupation); 00192 SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam); 00193 if (bestLaneOffset >= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset + 2, rv))) { 00194 // ...we will not change the lane if not 00195 return ret; 00196 } 00197 00198 00199 // if the current lane is the best and a lane-changing would cause a situation 00200 // of which we assume we will not be able to return to the lane we have to be on... 00201 // 00202 // this rule prevents the vehicle from leaving the current, best lane when it is 00203 // close to this lane's end 00204 if (currExtDist > neighExtDist && (neighLeftPlace * 2. < rv/*||currE[currIdx+1].length<currentDist*/)) { 00205 return ret; 00206 } 00207 00208 // let's also regard the case where the vehicle is driving on a highway... 00209 // in this case, we do not want to get to the dead-end of an on-ramp 00210 // 00211 // THIS RULE APPLIES ONLY TO CHANGING TO THE RIGHT LANE 00212 if (bestLaneOffset == 0 && preb[currIdx - 1].bestLaneOffset != 0 && myVehicle.getLane()->getMaxSpeed() > 80. / 3.6) { 00213 return ret; 00214 } 00215 // -------- 00216 00217 // -------- make place on current lane if blocking follower 00218 if (amBlockingFollowerPlusNB() 00219 && 00220 (currentDistAllows(neighDist, bestLaneOffset, rv) || neighDist >= currentDist)) { 00221 00222 return ret | LCA_RIGHT | LCA_URGENT; 00223 } 00224 // -------- 00225 00226 00227 // -------- security checks for krauss 00228 // (vsafe fails when gap<0) 00229 if ((blocked & LCA_BLOCKED) != 0) { 00230 return ret; 00231 } 00232 // -------- 00233 00234 // -------- higher speed 00235 if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { 00236 return ret; 00237 } 00238 SUMOReal thisLaneVSafe = myVehicle.getLane()->getMaxSpeed(); 00239 SUMOReal neighLaneVSafe = neighLane.getMaxSpeed(); 00240 if (neighLead.first == 0) { 00241 neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); 00242 } else { 00243 // @todo: what if leader is below safe gap?!!! 00244 neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())); 00245 } 00246 if (leader.first == 0) { 00247 thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0)); 00248 } else { 00249 // @todo: what if leader is below safe gap?!!! 00250 thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel())); 00251 } 00252 00253 thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed()); 00254 neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed()); 00255 if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) { 00256 // ok, the current lane is faster than the right one... 00257 if (myChangeProbability < 0) { 00258 myChangeProbability /= 2.0; 00259 } 00260 } else { 00261 // ok, the right lane is faster than the current 00262 myChangeProbability -= (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getMaxSpeed())); 00263 } 00264 00265 // let's recheck the "Rechtsfahrgebot" 00266 SUMOReal vmax = MIN2(myVehicle.getLane()->getMaxSpeed(), myVehicle.getVehicleType().getMaxSpeed()); 00267 vmax -= (SUMOReal)(5. / 2.6); 00268 if (neighLaneVSafe >= vmax) { 00269 #ifndef NO_TRACI 00270 /* if there was a request by TraCI for changing to this lane 00271 and holding it, this rule is ignored */ 00272 if (myChangeRequest != MSVehicle::REQUEST_HOLD) { 00273 #endif 00274 myChangeProbability -= (SUMOReal)((neighLaneVSafe - vmax) / (vmax)); 00275 #ifndef NO_TRACI 00276 } 00277 #endif 00278 } 00279 00280 if (myChangeProbability < -2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1 00281 return ret | LCA_RIGHT | LCA_SPEEDGAIN; 00282 } 00283 // -------- 00284 00285 #ifndef NO_TRACI 00286 // If there is a request by TraCI, try to change the lane 00287 if (myChangeRequest == MSVehicle::REQUEST_RIGHT) { 00288 return ret | LCA_RIGHT; 00289 } 00290 #endif 00291 00292 return ret; 00293 } 00294 00295 00296 int 00297 MSLCM_DK2004::wantsChangeToLeft(MSAbstractLaneChangeModel::MSLCMessager& msgPass, 00298 int blocked, 00299 const std::pair<MSVehicle*, SUMOReal> &leader, 00300 const std::pair<MSVehicle*, SUMOReal> &neighLead, 00301 const std::pair<MSVehicle*, SUMOReal> &neighFollow, 00302 const MSLane& neighLane, 00303 const std::vector<MSVehicle::LaneQ> &preb, 00304 MSVehicle** lastBlocked) { 00305 #ifdef DEBUG_VEHICLE_GUI_SELECTION 00306 if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) { 00307 int bla = 0; 00308 } 00309 #endif 00310 MSVehicle::LaneQ curr, best; 00311 int bestLaneOffset = 0; 00312 SUMOReal currentDist = 0; 00313 SUMOReal neighDist = 0; 00314 SUMOReal neighExtDist = 0; 00315 SUMOReal currExtDist = 0; 00316 int currIdx = 0; 00317 for (int p = 0; p < (int) preb.size(); ++p) { 00318 if (preb[p].lane == myVehicle.getLane()) { 00319 curr = preb[p]; 00320 bestLaneOffset = curr.bestLaneOffset; 00321 currentDist = curr.length; 00322 currExtDist = curr.lane->getLength(); 00323 neighDist = preb[p + 1].length; 00324 neighExtDist = preb[p + 1].lane->getLength(); 00325 best = preb[p + bestLaneOffset]; 00326 currIdx = p; 00327 } 00328 } 00329 // keep information about being a leader/follower 00330 int ret = (myOwnState & 0x00ffff00); 00331 00332 // ?!!! 00333 if (leader.first != 0 00334 && 00335 (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0 00336 && 00337 (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) { 00338 00339 myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE); 00340 if (myVehicle.getSpeed() > 0.1) { 00341 myOwnState |= LCA_AMBACKBLOCKER; 00342 } else { 00343 ret |= LCA_AMBACKBLOCKER; 00344 myDontBrake = true; 00345 } 00346 } 00347 00348 // process information about the last blocked vehicle 00349 // if this vehicle is blocking someone in front, we maybe decelerate to let him in 00350 if ((*lastBlocked) != 0) { 00351 SUMOReal gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLengthWithGap() - myVehicle.getPositionOnLane(); 00352 if (gap > 0.1) { 00353 if (myVehicle.getSpeed() < ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) { 00354 if ((*lastBlocked)->getSpeed() < 0.1) { 00355 ret |= LCA_AMBACKBLOCKER_STANDING; 00356 } else { 00357 ret |= LCA_AMBACKBLOCKER; 00358 } 00359 myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (SUMOReal)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel())); 00360 (*lastBlocked) = 0; 00361 } 00362 return ret; 00363 } 00364 } 00365 00366 // we try to estimate the distance which is necessary to get on a lane 00367 // we have to get on in order to keep our route 00368 // we assume we need something that depends on our velocity 00369 // and compare this with the free space on our wished lane 00370 // 00371 // if the free space is somehow less than the space we need, we should 00372 // definitely try to get to the desired lane 00373 // 00374 // this rule forces our vehicle to change the lane if a lane changing is necessary soon 00375 SUMOReal lv = myVehicle.getSpeed() > LOOK_FORWARD_SPEED_DIVIDER 00376 ? myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_FAR 00377 : myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_NEAR; 00378 lv += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.; 00379 00380 00381 SUMOReal tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (SUMOReal) JAM_FACTOR2; 00382 if (fabs(best.length - curr.length) > MIN2((SUMOReal) .1, best.lane->getLength()) && bestLaneOffset > 0 00383 && 00384 currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, lv)) { 00385 informBlocker(msgPass, blocked, LCA_MLEFT, neighLead, neighFollow); 00386 if (neighLead.second > 0 && neighLead.second > leader.second) { 00387 myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (SUMOReal) 0.5); 00388 } 00389 00390 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, left 00391 // if there is a leader and he wants to change to right (we want to change to left) 00392 if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_RIGHT) != 0) { 00393 // save at least his length in myLeadingBlockerLength 00394 myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength); 00395 // save the left space 00396 myLeftSpace = currentDist - myVehicle.getPositionOnLane(); 00397 } 00398 // 00399 00400 return ret | LCA_LEFT | LCA_URGENT; 00401 } 00402 00403 // the opposite lane-changing direction should be rather done, not 00404 // the one examined herein 00405 // we'll check whether we assume we could change anyhow and get back in time... 00406 // 00407 // this rule prevents the vehicle from moving in opposite direction of the best lane 00408 // unless the way till the end where the vehicle has to be on the best lane 00409 // is long enough 00410 SUMOReal maxJam = MAX2(preb[currIdx + 1].occupation, preb[currIdx].occupation); 00411 SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam); 00412 if (bestLaneOffset <= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset - 2, lv))) { 00413 // ...we will not change the lane if not 00414 return ret; 00415 } 00416 00417 00418 // if the current lane is the best and a lane-changing would cause a situation 00419 // of which we assume we will not be able to return to the lane we have to be on... 00420 // 00421 // this rule prevents the vehicle from leaving the current, best lane when it is 00422 // close to this lane's end 00423 if (currExtDist > neighExtDist && (neighLeftPlace * 2. < lv/*||currE[currIdx+1].length<currentDist*/)) { 00424 // ... let's not change the lane 00425 return ret; 00426 } 00427 00428 /* 00429 // let's also regard the case where the vehicle is driving on a highway... 00430 // in this case, we do not want to get to the dead-end of an on-ramp 00431 if(bestLaneOffset==0&&myVehicle.getLane().getMaxSpeed()>80./3.6) { 00432 return ret; 00433 } 00434 */ 00435 00436 00437 /* 00438 // if the current lane is the 00439 if(bestLaneOffset==0&&(neighDist==0||curr.seenVehicles2*JAM_FACTOR>=neighExtDist-curr.length)) { 00440 return ret; 00441 } 00442 */ 00443 // -------- 00444 00445 // -------- make place on current lane if blocking follower 00446 if (amBlockingFollowerPlusNB() 00447 && 00448 (currentDistAllows(neighDist, bestLaneOffset, lv) || neighDist >= currentDist)) { 00449 00450 return ret | LCA_LEFT | LCA_URGENT; 00451 } 00452 // -------- 00453 00454 // -------- security checks for krauss 00455 // (vsafe fails when gap<0) 00456 if ((blocked & LCA_BLOCKED) != 0) { 00457 return ret; 00458 } 00459 00460 // -------- higher speed 00461 if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { 00462 return ret; 00463 } 00464 SUMOReal neighLaneVSafe = neighLane.getMaxSpeed(); 00465 SUMOReal thisLaneVSafe = myVehicle.getLane()->getMaxSpeed(); 00466 if (neighLead.first == 0) { 00467 neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); // !!! warum nicht die Folgesgeschw.? 00468 } else { 00469 // @todo: what if leader is below safe gap?!!! 00470 neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())); 00471 } 00472 if (leader.first == 0) { 00473 thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0)); 00474 } else { 00475 // @todo: what if leader is below safe gap?!!! 00476 thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel())); 00477 } 00478 thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed()); 00479 neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed()); 00480 if (thisLaneVSafe > neighLaneVSafe) { 00481 // this lane is better 00482 if (myChangeProbability > 0) { 00483 myChangeProbability /= 2.0; 00484 } 00485 } else { 00486 // right lane is better 00487 myChangeProbability += (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getMaxSpeed())); // !!! Fahrzeuggeschw.! 00488 } 00489 if (myChangeProbability > .2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1 00490 return ret | LCA_LEFT | LCA_SPEEDGAIN | LCA_URGENT; 00491 } 00492 // -------- 00493 00494 #ifndef NO_TRACI 00495 // If there is a request by TraCI, try to change the lane 00496 if (myChangeRequest == MSVehicle::REQUEST_LEFT) { 00497 return ret | LCA_LEFT; 00498 } 00499 #endif 00500 00501 return ret; 00502 } 00503 00504 00505 SUMOReal 00506 MSLCM_DK2004::patchSpeed(const SUMOReal min, const SUMOReal wanted, const SUMOReal max, const MSCFModel& cfModel) { 00507 #ifdef DEBUG_VEHICLE_GUI_SELECTION 00508 if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) { 00509 int bla = 0; 00510 } 00511 #endif 00512 int state = myOwnState; 00513 myOwnState = 0; 00514 00515 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2 00516 SUMOReal MAGIC_offset = 1.; 00517 // if we want to change and have a blocking leader and there is enough room for him in front of us 00518 if (myLeadingBlockerLength != 0) { 00519 SUMOReal space = myLeftSpace - myLeadingBlockerLength - MAGIC_offset; 00520 if (space > 0) { 00521 // compute speed for decelerating towards a place which allows the blocking leader to merge in in front 00522 SUMOReal safe = cfModel.stopSpeed(&myVehicle, space); 00523 // if we are approaching this place 00524 if (safe < wanted) { 00525 // return this speed as the speed to use 00526 return MAX2(min, safe); 00527 } 00528 } 00529 } 00530 00531 // just to make sure to be notified about lane chaning end 00532 if (myVehicle.getLane()->getEdge().getLanes().size() == 1) { 00533 // remove chaning information if on a road with a single lane 00534 changed(); 00535 return wanted; 00536 } 00537 00538 SUMOReal nVSafe = wanted; 00539 bool gotOne = false; 00540 for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) { 00541 SUMOReal v = (*i); 00542 if (v >= min && v <= max) { 00543 nVSafe = MIN2(v, nVSafe); 00544 gotOne = true; 00545 } 00546 } 00547 00548 // check whether the vehicle is blocked 00549 if ((state & LCA_WANTS_LANECHANGE) != 0) { 00550 if (gotOne && !myDontBrake) { 00551 return nVSafe; 00552 } 00553 // check whether the vehicle maybe has to be swapped with one of 00554 // the blocking vehicles 00555 if ((state & LCA_BLOCKED) != 0) { 00556 if ((state & LCA_BLOCKED_BY_LEADER) != 0) { 00557 // if interacting with leader and not too slow 00558 return (min + wanted) / (SUMOReal) 2.0; 00559 } 00560 if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) { 00561 return (max + wanted) / (SUMOReal) 2.0; 00562 } 00563 return (min + wanted) / (SUMOReal) 2.0; 00564 } 00565 } 00566 00567 00568 // decelerate if being a blocking follower 00569 // (and does not have to change lanes) 00570 if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) { 00571 if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed())) < 0.001 && min == 0) { // !!! was standing 00572 return 0; 00573 } 00574 return (min + wanted) / (SUMOReal) 2.0; 00575 } 00576 if ((state & LCA_AMBACKBLOCKER) != 0) { 00577 if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed()) && min == 0) { // !!! was standing 00578 return min; 00579 } 00580 } 00581 if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) { 00582 return min; 00583 } 00584 // accelerate if being a blocking leader or blocking follower not able to brake 00585 // (and does not have to change lanes) 00586 if ((state & LCA_AMBLOCKINGLEADER) != 0) { 00587 return (max + wanted) / (SUMOReal) 2.0; 00588 } 00589 if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) { 00590 if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed()) && min == 0) { // !!! was standing 00591 return wanted; 00592 } 00593 return (min + wanted) / (SUMOReal) 2.0; 00594 } 00595 return wanted; 00596 } 00597 00598 00599 void* 00600 MSLCM_DK2004::inform(void* info, MSVehicle* /*sender*/) { 00601 Info* pinfo = (Info*) info; 00602 myOwnState &= 0xffffffff; 00603 myOwnState |= pinfo->second; 00604 delete pinfo; 00605 return (void*) true; 00606 } 00607 00608 00609 void 00610 MSLCM_DK2004::changed() { 00611 myChangeProbability = 0; 00612 myOwnState = 0; 00613 myLeadingBlockerLength = 0; 00614 myLeftSpace = 0; 00615 myVSafes.clear(); 00616 myDontBrake = false; 00617 } 00618 00619 00620 void 00621 MSLCM_DK2004::informBlocker(MSAbstractLaneChangeModel::MSLCMessager& msgPass, 00622 int& blocked, 00623 int dir, 00624 const std::pair<MSVehicle*, SUMOReal> &neighLead, 00625 const std::pair<MSVehicle*, SUMOReal> &neighFollow) { 00626 if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) { 00627 assert(neighFollow.first != 0); 00628 MSVehicle* nv = neighFollow.first; 00629 SUMOReal decelGap = 00630 neighFollow.second 00631 + SPEED2DIST(myVehicle.getSpeed()) * (SUMOReal) 2.0 00632 - MAX2(nv->getSpeed() - (SUMOReal) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (SUMOReal) 2.0, (SUMOReal) 0); 00633 if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())) { 00634 SUMOReal vsafe = myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel()); 00635 msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle); 00636 } else { 00637 SUMOReal vsafe = neighFollow.second <= 0 ? 0 : myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel()); 00638 msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER_DONTBRAKE), &myVehicle); 00639 } 00640 } 00641 if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) { 00642 if (neighLead.first != 0 && neighLead.second > 0) { 00643 msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle); 00644 } 00645 } 00646 } 00647 00648 00649 void 00650 MSLCM_DK2004::prepareStep() { 00651 myLeadingBlockerLength = 0; 00652 myLeftSpace = 0; 00653 myVSafes.clear(); 00654 myDontBrake = false; 00655 } 00656 00657 00658 SUMOReal 00659 MSLCM_DK2004::getProb() const { 00660 return myChangeProbability; 00661 } 00662 00663 00664 /****************************************************************************/ 00665