int MSLCM_LC2013::_wantsChange( int laneOffset, MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked, const std::pair<MSVehicle*, SUMOReal>& leader, const std::pair<MSVehicle*, SUMOReal>& neighLead, const std::pair<MSVehicle*, SUMOReal>& neighFollow, const MSLane& neighLane, const std::vector<MSVehicle::LaneQ>& preb, MSVehicle** lastBlocked, MSVehicle** firstBlocked) { assert(laneOffset == 1 || laneOffset == -1); const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep(); // compute bestLaneOffset MSVehicle::LaneQ curr, neigh, best; int bestLaneOffset = 0; SUMOReal currentDist = 0; SUMOReal neighDist = 0; int currIdx = 0; MSLane* prebLane = myVehicle.getLane(); if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) { // internal edges are not kept inside the bestLanes structure prebLane = prebLane->getLinkCont()[0]->getLane(); } for (int p = 0; p < (int) preb.size(); ++p) { if (preb[p].lane == prebLane && p + laneOffset >= 0) { assert(p + laneOffset < (int)preb.size()); curr = preb[p]; neigh = preb[p + laneOffset]; currentDist = curr.length; neighDist = neigh.length; bestLaneOffset = curr.bestLaneOffset; if (bestLaneOffset == 0 && preb[p + laneOffset].bestLaneOffset == 0) { bestLaneOffset = laneOffset; } best = preb[p + bestLaneOffset]; currIdx = p; break; } } // direction specific constants const bool right = (laneOffset == -1); const int lca = (right ? LCA_RIGHT : LCA_LEFT); const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT); const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT); const bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0); // keep information about being a leader/follower int ret = (myOwnState & 0xffff0000); ret = slowDownForBlocked(lastBlocked, ret); if (lastBlocked != firstBlocked) { ret = slowDownForBlocked(firstBlocked, ret); } // we try to estimate the distance which is necessary to get on a lane // we have to get on in order to keep our route // we assume we need something that depends on our velocity // and compare this with the free space on our wished lane // // if the free space is somehow less than the space we need, we should // definitely try to get to the desired lane // // this rule forces our vehicle to change the lane if a lane changing is necessary soon // lookAheadDistance: // we do not want the lookahead distance to change all the time so we discrectize the speed a bit if (myVehicle.getSpeed() > myLookAheadSpeed) { myLookAheadSpeed = myVehicle.getSpeed(); } else { myLookAheadSpeed = MAX2(LOOK_AHEAD_MIN_SPEED, (LOOK_AHEAD_SPEED_MEMORY * myLookAheadSpeed + (1 - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getSpeed())); } SUMOReal laDist = myLookAheadSpeed * (right ? LOOK_FORWARD_RIGHT : LOOK_FORWARD_LEFT); laDist += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.; // free space that is available for changing //const SUMOReal neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() : // neighFollow.first != 0 ? neighFollow.first->getSpeed() : // best.lane->getSpeedLimit()); // @note: while this lets vehicles change earlier into the correct direction // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others int roundaboutEdgesAhead = 0; for (std::vector<MSLane*>::iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) { if ((*it) != 0 && (*it)->getEdge().isRoundabout()) { roundaboutEdgesAhead += 1; } else if (roundaboutEdgesAhead > 0) { // only check the next roundabout break; } } int roundaboutEdgesAheadNeigh = 0; for (std::vector<MSLane*>::iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) { if ((*it) != 0 && (*it)->getEdge().isRoundabout()) { roundaboutEdgesAheadNeigh += 1; } else if (roundaboutEdgesAheadNeigh > 0) { // only check the next roundabout break; } } if (roundaboutEdgesAhead > 1) { currentDist += roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS; neighDist += roundaboutEdgesAheadNeigh * ROUNDABOUT_DIST_BONUS; } const SUMOReal usableDist = (currentDist - myVehicle.getPositionOnLane() - best.occupation * JAM_FACTOR); const SUMOReal maxJam = MAX2(preb[currIdx + laneOffset].occupation, preb[currIdx].occupation); const SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam); if (changeToBest && bestLaneOffset == curr.bestLaneOffset && currentDistDisallows(usableDist, bestLaneOffset, laDist)) { /// @brief we urgently need to change lanes to follow our route ret = ret | lca | LCA_STRATEGIC | LCA_URGENT; } else { if (!myAllowOvertakingRight && !right && !myVehicle.congested() && neighLead.first != 0) { // check for slower leader on the left. we should not overtake but // rather move left ourselves (unless congested) MSVehicle* nv = neighLead.first; if (nv->getSpeed() < myVehicle.getSpeed()) { myVSafes.push_back(myCarFollowModel.followSpeed( &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel())); if (nv->getSpeed() + 5 / 3.6 < myVehicle.getSpeed()) { mySpeedGainProbability += CHANGE_PROB_THRESHOLD_LEFT / 3; } } } if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) { // the opposite lane-changing direction should be done than the one examined herein // we'll check whether we assume we could change anyhow and get back in time... // // this rule prevents the vehicle from moving in opposite direction of the best lane // unless the way till the end where the vehicle has to be on the best lane // is long enough ret = ret | LCA_STAY | LCA_STRATEGIC; } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) { // the current lane is the best and a lane-changing would cause a situation // of which we assume we will not be able to return to the lane we have to be on. // this rule prevents the vehicle from leaving the current, best lane when it is // close to this lane's end ret = ret | LCA_STAY | LCA_STRATEGIC; } } // check for overriding TraCI requests ret = myVehicle.influenceChangeDecision(ret); if ((ret & lcaCounter) != 0) { // we are not interested in traci requests for the opposite direction here ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT); } if ((ret & LCA_STAY) != 0) { return ret; } if ((ret & LCA_URGENT) != 0) { // prepare urgent lane change maneuver // save the left space myLeftSpace = currentDist - myVehicle.getPositionOnLane(); if (changeToBest && abs(bestLaneOffset) > 1) { // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet myLeadingBlockerLength = MAX2((SUMOReal)(right ? 20.0 : 40.0), myLeadingBlockerLength); } // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1 // if there is a leader and he wants to change to the opposite direction saveBlockerLength(neighLead.first, lcaCounter); if (*firstBlocked != neighLead.first) { saveBlockerLength(*firstBlocked, lcaCounter); } const SUMOReal remainingSeconds = ((ret & LCA_TRACI) == 0 ? MAX2((SUMOReal)STEPS2TIME(TS), myLeftSpace / myLookAheadSpeed / abs(bestLaneOffset) / URGENCY) : myVehicle.getInfluencer().changeRequestRemainingSeconds(currentTime)); const SUMOReal plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds); if (plannedSpeed >= 0) { // maybe we need to deal with a blocking follower informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed); } return ret; } if (roundaboutEdgesAhead > 1) { // try to use the inner lanes of a roundabout to increase throughput // unless we are approaching the exit if (lca == LCA_LEFT) { return ret | lca | LCA_COOPERATIVE; } else { return ret | LCA_STAY | LCA_COOPERATIVE; } } // let's also regard the case where the vehicle is driving on a highway... // in this case, we do not want to get to the dead-end of an on-ramp if (right) { if (bestLaneOffset == 0 && myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle) > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) { return ret | LCA_STAY | LCA_STRATEGIC; } } // -------- // -------- make place on current lane if blocking follower //if (amBlockingFollowerPlusNB()) { // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist) // << " neighDist=" << neighDist // << " currentDist=" << currentDist // << "\n"; //} if (amBlockingFollowerPlusNB() && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) { return ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP; } // -------- //// -------- security checks for krauss //// (vsafe fails when gap<0) //if ((blocked & LCA_BLOCKED) != 0) { // return ret; //} //// -------- // -------- higher speed //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!! // return ret; //} SUMOReal thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle); SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle); if (neighLead.first == 0) { neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); } else { // @todo: what if leader is below safe gap?!!! neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed( &myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())); } if (leader.first == 0) { thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0)); } else { // @todo: what if leader is below safe gap?!!! thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel())); } thisLaneVSafe = MIN3(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)); neighLaneVSafe = MIN3(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), neighLane.getVehicleMaxSpeed(&myVehicle)); const SUMOReal relativeGain = (neighLaneVSafe - thisLaneVSafe) / neighLaneVSafe; if (right) { // ONLY FOR CHANGING TO THE RIGHT if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) { // ok, the current lane is faster than the right one... if (mySpeedGainProbability < 0) { mySpeedGainProbability /= 2.0; //myKeepRightProbability /= 2.0; } } else { // ok, the current lane is not faster than the right one mySpeedGainProbability -= relativeGain; // honor the obligation to keep right (Rechtsfahrgebot) // XXX consider fast approaching followers on the current lane //const SUMOReal vMax = myLookAheadSpeed; const SUMOReal vMax = MIN2(myVehicle.getVehicleType().getMaxSpeed(), myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)); const SUMOReal acceptanceTime = KEEP_RIGHT_ACCEPTANCE * vMax * MAX2((SUMOReal)1, myVehicle.getSpeed()) / myVehicle.getLane()->getSpeedLimit(); SUMOReal fullSpeedGap = MAX2((SUMOReal)0, neighDist - myVehicle.getCarFollowModel().brakeGap(vMax)); SUMOReal fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax); if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) { fullSpeedGap = MAX2((SUMOReal)0, MIN2(fullSpeedGap, neighLead.second - myVehicle.getCarFollowModel().getSecureGap( vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))); fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed())); } const SUMOReal deltaProb = (CHANGE_PROB_THRESHOLD_RIGHT * STEPS2TIME(DELTA_T) * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME); myKeepRightProbability -= deltaProb; if (gDebugFlag2) { std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " vMax=" << vMax << " neighDist=" << neighDist << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed()) << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed()) << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap( myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())) << " acceptanceTime=" << acceptanceTime << " fullSpeedGap=" << fullSpeedGap << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds << " dProb=" << deltaProb << "\n"; } if (myKeepRightProbability < -CHANGE_PROB_THRESHOLD_RIGHT) { return ret | lca | LCA_KEEPRIGHT; } } if (mySpeedGainProbability < -CHANGE_PROB_THRESHOLD_RIGHT && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1 return ret | lca | LCA_SPEEDGAIN; } } else { // ONLY FOR CHANGING TO THE LEFT if (thisLaneVSafe > neighLaneVSafe) { // this lane is better if (mySpeedGainProbability > 0) { mySpeedGainProbability /= 2.0; } } else { // left lane is better mySpeedGainProbability += relativeGain; } if (mySpeedGainProbability > CHANGE_PROB_THRESHOLD_LEFT && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1 return ret | lca | LCA_SPEEDGAIN; } } // -------- if (changeToBest && bestLaneOffset == curr.bestLaneOffset && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) { // change towards the correct lane, speedwise it does not hurt return ret | lca | LCA_STRATEGIC; } return ret; }
int MSLCM_DK2004::wantsChangeToRight(MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked, const std::pair<MSVehicle*, SUMOReal>& leader, const std::pair<MSVehicle*, SUMOReal>& neighLead, const std::pair<MSVehicle*, SUMOReal>& neighFollow, const MSLane& neighLane, const std::vector<MSVehicle::LaneQ>& preb, MSVehicle** lastBlocked) { #ifdef DEBUG_VEHICLE_GUI_SELECTION if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(&myVehicle)->getGlID())) { int bla = 0; } #endif MSVehicle::LaneQ curr, best; int bestLaneOffset = 0; SUMOReal currentDist = 0; SUMOReal neighDist = 0; SUMOReal neighExtDist = 0; SUMOReal currExtDist = 0; int currIdx = 0; for (int p = 0; p < (int) preb.size(); ++p) { if (preb[p].lane == myVehicle.getLane()) { curr = preb[p]; bestLaneOffset = curr.bestLaneOffset; currentDist = curr.length; currExtDist = curr.lane->getLength(); neighDist = preb[p - 1].length; neighExtDist = preb[p - 1].lane->getLength(); best = preb[p + bestLaneOffset]; currIdx = p; } } // keep information about being a leader/follower int ret = (myOwnState & 0x00ffff00); if (leader.first != 0 && (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0 && (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) { myOwnState &= (0xffffffff - LCA_AMBLOCKINGFOLLOWER_DONTBRAKE); if (myVehicle.getSpeed() > 0.1) { myOwnState |= LCA_AMBACKBLOCKER; } else { ret |= LCA_AMBACKBLOCKER; myDontBrake = true; } } // process information about the last blocked vehicle // if this vehicle is blocking someone in front, we maybe decelerate to let him in if ((*lastBlocked) != 0) { SUMOReal gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap(); if (gap > 0.1) { if (myVehicle.getSpeed() < ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())) { if ((*lastBlocked)->getSpeed() < 0.1) { ret |= LCA_AMBACKBLOCKER_STANDING; } else { ret |= LCA_AMBACKBLOCKER; } myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), (SUMOReal)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel())); (*lastBlocked) = 0; } return ret; } } // we try to estimate the distance which is necessary to get on a lane // we have to get on in order to keep our route // we assume we need something that depends on our velocity // and compare this with the free space on our wished lane // // if the free space is somehow less than the space we need, we should // definitely try to get to the desired lane // // this rule forces our vehicle to change the lane if a lane changing is necessary soon SUMOReal rv = myVehicle.getSpeed() > LOOK_FORWARD_SPEED_DIVIDER ? myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_FAR : myVehicle.getSpeed() * (SUMOReal) LOOK_FORWARD_NEAR; rv += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.; SUMOReal tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (SUMOReal) JAM_FACTOR2; if (fabs(best.length - curr.length) > MIN2((SUMOReal) .1, best.lane->getLength()) && bestLaneOffset < 0 && currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, rv)) { informBlocker(msgPass, blocked, LCA_MRIGHT, neighLead, neighFollow); if (neighLead.second > 0 && neighLead.second > leader.second) { myVSafes.push_back(myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (SUMOReal) 0.5); } // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, right // if there is a leader and he wants to change to left (we want to change to right) if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_LEFT) != 0) { // save at least his length in myLeadingBlockerLength myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength); // save the left space myLeftSpace = currentDist - myVehicle.getPositionOnLane(); } // return ret | LCA_RIGHT | LCA_URGENT; } // the opposite lane-changing direction should be done than the one examined herein // we'll check whether we assume we could change anyhow and get back in time... // // this rule prevents the vehicle from moving in opposite direction of the best lane // unless the way till the end where the vehicle has to be on the best lane // is long enough SUMOReal maxJam = MAX2(preb[currIdx - 1].occupation, preb[currIdx].occupation); SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam); if (bestLaneOffset >= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset + 2, rv))) { // ...we will not change the lane if not return ret; } // if the current lane is the best and a lane-changing would cause a situation // of which we assume we will not be able to return to the lane we have to be on... // // this rule prevents the vehicle from leaving the current, best lane when it is // close to this lane's end if (currExtDist > neighExtDist && (neighLeftPlace * 2. < rv/*||currE[currIdx+1].length<currentDist*/)) { return ret; } // let's also regard the case where the vehicle is driving on a highway... // in this case, we do not want to get to the dead-end of an on-ramp // // THIS RULE APPLIES ONLY TO CHANGING TO THE RIGHT LANE if (bestLaneOffset == 0 && preb[currIdx - 1].bestLaneOffset != 0 && myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle) > 80. / 3.6) { return ret; } // -------- // -------- make place on current lane if blocking follower if (amBlockingFollowerPlusNB() && (currentDistAllows(neighDist, bestLaneOffset, rv) || neighDist >= currentDist)) { return ret | LCA_RIGHT | LCA_URGENT; } // -------- // -------- security checks for krauss // (vsafe fails when gap<0) if ((blocked & LCA_BLOCKED) != 0) { return ret; } // -------- // -------- higher speed if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!! return ret; } SUMOReal thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle); SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle); if (neighLead.first == 0) { neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); } else { // @todo: what if leader is below safe gap?!!! neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())); } if (leader.first == 0) { thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0)); } else { // @todo: what if leader is below safe gap?!!! thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel())); } thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed()); neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed()); if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) { // ok, the current lane is faster than the right one... if (myChangeProbability < 0) { myChangeProbability /= 2.0; } } else { // ok, the right lane is faster than the current myChangeProbability -= (SUMOReal)((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle))); } // let's recheck the "Rechtsfahrgebot" SUMOReal vmax = MIN2(myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle), myVehicle.getVehicleType().getMaxSpeed()); vmax -= (SUMOReal)(5. / 2.6); if (neighLaneVSafe >= vmax) { #ifndef NO_TRACI /* if there was a request by TraCI for changing to this lane and holding it, this rule is ignored */ if (myChangeRequest != MSVehicle::REQUEST_HOLD) { #endif myChangeProbability -= (SUMOReal)((neighLaneVSafe - vmax) / (vmax)); #ifndef NO_TRACI } #endif } if (myChangeProbability < -2 && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1 return ret | LCA_RIGHT | LCA_SPEEDGAIN; } // -------- #ifndef NO_TRACI // If there is a request by TraCI, try to change the lane if (myChangeRequest == MSVehicle::REQUEST_RIGHT) { return ret | LCA_RIGHT; } #endif return ret; }