void MSLCM_DK2004::informBlocker(MSAbstractLaneChangeModel::MSLCMessager& msgPass, int& blocked, int dir, const std::pair<MSVehicle*, SUMOReal>& neighLead, const std::pair<MSVehicle*, SUMOReal>& neighFollow) { if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) { assert(neighFollow.first != 0); MSVehicle* nv = neighFollow.first; SUMOReal decelGap = neighFollow.second + SPEED2DIST(myVehicle.getSpeed()) * (SUMOReal) 2.0 - MAX2(nv->getSpeed() - (SUMOReal) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (SUMOReal) 2.0, (SUMOReal) 0); if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())) { SUMOReal vsafe = myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel()); msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle); } else { SUMOReal vsafe = neighFollow.second <= 0 ? 0 : myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel()); msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER_DONTBRAKE), &myVehicle); } } if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) { if (neighLead.first != 0 && neighLead.second > 0) { msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle); } } }
void MSLCM_LC2013::informFollower(MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked, int dir, const std::pair<MSVehicle*, SUMOReal>& neighFollow, SUMOReal remainingSeconds, SUMOReal plannedSpeed) { if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) { assert(neighFollow.first != 0); MSVehicle* nv = neighFollow.first; // are we fast enough to cut in without any help? if (plannedSpeed - nv->getSpeed() >= HELP_OVERTAKE) { const SUMOReal neededGap = nv->getCarFollowModel().getSecureGap(nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel()); if ((neededGap - neighFollow.second) / remainingSeconds < (plannedSpeed - nv->getSpeed())) { // follower might even accelerate but not to much msgPass.informNeighFollower(new Info(plannedSpeed - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle); return; } } // decide whether we will request help to cut in before the follower or allow to be overtaken // PARAMETERS // assume other vehicle will assume the equivalent of 1 second of // maximum deceleration to help us (will probably be spread over // multiple seconds) // ----------- const SUMOReal helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR ; // change in the gap between ego and blocker over 1 second (not STEP!) const SUMOReal neighNewSpeed = MAX2((SUMOReal)0, nv->getSpeed() - ACCEL2SPEED(helpDecel)); const SUMOReal neighNewSpeed1s = MAX2((SUMOReal)0, nv->getSpeed() - helpDecel); const SUMOReal dv = plannedSpeed - neighNewSpeed1s; // new gap between follower and self in case the follower does brake for 1s const SUMOReal decelGap = neighFollow.second + dv; const SUMOReal secureGap = nv->getCarFollowModel().getSecureGap(neighNewSpeed1s, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel()); if (decelGap > 0 && decelGap >= secureGap) { // if the blocking neighbor brakes it could actually help // how hard does it actually need to be? const SUMOReal vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed( nv, nv->getSpeed(), neighFollow.second, plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel())); msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle); } else if (dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS)) { // decelerating once is sufficient to open up a large enough gap in time msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle); } else { SUMOReal vhelp = MAX2(nv->getSpeed(), myVehicle.getSpeed() + HELP_OVERTAKE); //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE && // nv->getSpeed() > myVehicle.getSpeed()) { if (nv->getSpeed() > myVehicle.getSpeed() && ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft) )) { // let the follower slow down to increase the likelyhood that later vehicles will be slow enough to help // follower should still be fast enough to open a gap vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE); if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) { msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle); return; } } msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle); // this follower is supposed to overtake us. slow down smoothly to allow this const SUMOReal overtakeDist = (neighFollow.second // follower reaches ego back + myVehicle.getVehicleType().getLengthWithGap() // follower reaches ego front + nv->getVehicleType().getLength() // follower back at ego front + myVehicle.getCarFollowModel().getSecureGap( // follower has safe dist to ego plannedSpeed, vhelp, nv->getCarFollowModel().getMaxDecel())); // speed difference to create a sufficiently large gap const SUMOReal needDV = overtakeDist / remainingSeconds; // make sure the deceleration is not to strong myVSafes.push_back(MAX2(vhelp - needDV, myVehicle.getSpeed() - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel()))); } } }