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()))); } } }
SUMOReal MSLCM_LC2013::informLeader(MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked, int dir, const std::pair<MSVehicle*, SUMOReal>& neighLead, SUMOReal remainingSeconds) { SUMOReal plannedSpeed = MIN2(myVehicle.getSpeed(), myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), myLeftSpace - myLeadingBlockerLength)); for (std::vector<SUMOReal>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) { SUMOReal v = (*i); if (v >= myVehicle.getSpeed() - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) { plannedSpeed = MIN2(plannedSpeed, v); } } if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) { assert(neighLead.first != 0); MSVehicle* nv = neighLead.first; // decide whether we want to overtake the leader or follow it const SUMOReal dv = plannedSpeed - nv->getSpeed(); const SUMOReal overtakeDist = (neighLead.second // drive to back of follower + nv->getVehicleType().getLengthWithGap() // drive to front of follower + myVehicle.getVehicleType().getLength() // ego back reaches follower front + nv->getCarFollowModel().getSecureGap( // save gap to follower nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())); if (dv < 0 // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft) || (dir == LCA_MLEFT && !myVehicle.congested()) // not enough space to overtake? || myLeftSpace < overtakeDist // not enough time to overtake? || dv * remainingSeconds < overtakeDist) { // cannot overtake msgPass.informNeighLeader(new Info(-1, dir | LCA_AMBLOCKINGLEADER), &myVehicle); // slow down smoothly to follow leader const SUMOReal targetSpeed = myCarFollowModel.followSpeed( &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel()); if (targetSpeed < myVehicle.getSpeed()) { // slow down smoothly to follow leader const SUMOReal decel = ACCEL2SPEED(MIN2(myVehicle.getCarFollowModel().getMaxDecel(), MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds))); const SUMOReal nextSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() - decel); myVSafes.push_back(nextSpeed); return nextSpeed; } else { // leader is fast enough anyway myVSafes.push_back(targetSpeed); return plannedSpeed; } } else { // overtaking, leader should not accelerate msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle); return -1; } } else if (neighLead.first != 0) { // (remainUnblocked) // we are not blocked now. make sure we stay far enough from the leader MSVehicle* nv = neighLead.first; const SUMOReal nextNVSpeed = nv->getSpeed() - HELP_OVERTAKE; // conservative const SUMOReal dv = SPEED2DIST(myVehicle.getSpeed() - nextNVSpeed); const SUMOReal targetSpeed = myCarFollowModel.followSpeed( &myVehicle, myVehicle.getSpeed(), neighLead.second - dv, nextNVSpeed, nv->getCarFollowModel().getMaxDecel()); myVSafes.push_back(targetSpeed); return MIN2(targetSpeed, plannedSpeed); } else { // not overtaking return plannedSpeed; } }