#include <config.h>
#include "MSLaneChanger.h"
#include "MSNet.h"
#include "MSLink.h"
#include "MSVehicle.h"
#include "MSVehicleType.h"
#include "MSVehicleTransfer.h"
#include "MSStop.h"
#include "MSGlobals.h"
#include <cassert>
#include <iterator>
#include <cstdlib>
#include <cmath>
#include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
#include <microsim/transportables/MSTransportableControl.h>
#include <microsim/transportables/MSPModel.h>
#include <utils/common/MsgHandler.h>
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0
#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR 0.0
#define OPPOSITE_OVERTAKING_SAFETY_FACTOR 1.2
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 1000.0
#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE 1000.0
#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD 5
#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT 1
#define DEBUG_COND (vehicle->isSelected())
MSLaneChanger::ChangeElem::ChangeElem(MSLane* _lane) :
lead(nullptr),
lane(_lane),
hoppedVeh(nullptr),
lastBlocked(nullptr),
firstBlocked(nullptr),
lastStopped(nullptr),
ahead(_lane->getWidth()),
aheadNext(_lane->getWidth(), nullptr, 0.),
zipperDist(0),
lastBlockedBackPos(-1),
lastBlockedWaitingTime(-1) {
if (lane->isInternal()) {
for (auto ili : lane->getIncomingLanes()) {
if (ili.viaLink->getState() == LINKSTATE_ZIPPER) {
zipperDist = lane->getLength();
break;
}
}
} else {
for (const MSLink* link : lane->getLinkCont()) {
if (link->getState() == LINKSTATE_ZIPPER) {
zipperDist = MAX2(zipperDist, link->getFoeVisibilityDistance());
}
}
}
}
void
MSLaneChanger::ChangeElem::registerHop(MSVehicle* vehicle) {
lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
dens += vehicle->getVehicleType().getLengthWithGap();
hoppedVeh = vehicle;
}
MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging) :
myAllowsChanging(allowChanging),
myChangeToOpposite(lanes->front()->getEdge().canChangeToOpposite()) {
myChanger.reserve(lanes->size());
for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
myChanger.push_back(ChangeElem(*lane));
myChanger.back().mayChangeRight = lane != lanes->begin();
myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
if ((*lane)->isInternal()) {
if (myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
myChanger.back().mayChangeRight = false;
}
if (myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
myChanger.back().mayChangeLeft = false;
}
if (myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
myChanger.back().mayChangeRight = false;
}
if (myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
myChanger.back().mayChangeLeft = false;
}
}
}
}
MSLaneChanger::~MSLaneChanger() {
}
void
MSLaneChanger::postloadInitLC() {
checkOpened = false;
for (auto ce : myChanger) {
const MSLane* lane = ce.lane;
for (const MSLink* link : lane->getLinkCont()) {
if (link->getTLLogic() != nullptr || link->havePriority()) {
continue;
}
for (auto ce2 : myChanger) {
const MSLane* lane2 = ce2.lane;
if (lane == lane2) {
continue;
}
for (const MSLink* link2 : lane2->getLinkCont()) {
if (&link->getLane()->getEdge() == &link2->getLane()->getEdge()
&& link->getLane() != link2->getLane()
&& (lane->getPermissions() & lane2->getPermissions() & link->getLane()->getPermissions() & link2->getLane()->getPermissions()
& link->getViaLaneOrLane()->getPermissions() & link2->getViaLaneOrLane()->getPermissions() & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) != 0
&& link->getFoeLinks() != link2->getFoeLinks()) {
checkOpened = true;
return;
}
}
}
}
}
}
void
MSLaneChanger::laneChange(SUMOTime t) {
initChanger();
try {
while (vehInChanger()) {
const bool haveChanged = change();
updateChanger(haveChanged);
}
updateLanes(t);
} catch (const ProcessError&) {
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
ce->lane->releaseVehicles();
}
throw;
}
}
void
MSLaneChanger::initChanger() {
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
ce->lead = nullptr;
ce->hoppedVeh = nullptr;
ce->lastBlocked = nullptr;
ce->firstBlocked = nullptr;
ce->lastStopped = nullptr;
ce->dens = 0;
ce->lastBlockedBackPos = -1;
ce->lastBlockedWaitingTime = -1;
ce->lane->getVehiclesSecure();
}
}
void
MSLaneChanger::updateChanger(bool vehHasChanged) {
assert(veh(myCandi) != 0);
if (!vehHasChanged) {
myCandi->lead = veh(myCandi);
}
MSLane::VehCont& vehicles = myCandi->lane->myVehicles;
vehicles.pop_back();
}
void
MSLaneChanger::updateLanes(SUMOTime t) {
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
ce->lane->swapAfterLaneChange(t);
ce->lane->releaseVehicles();
if (ce->lastBlocked != nullptr) {
ce->lastBlockedBackPos = ce->lastBlocked->getBackPositionOnLane();
ce->lastBlockedWaitingTime = ce->lastBlocked->getWaitingTime();
}
}
}
MSLaneChanger::ChangerIt
MSLaneChanger::findCandidate() {
ChangerIt max = myChanger.end();
#ifdef DEBUG_CANDIDATE
std::cout << SIMTIME << " findCandidate() on edge " << myChanger.begin()->lane->getEdge().getID() << std::endl;
#endif
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
if (veh(ce) == nullptr) {
continue;
}
#ifdef DEBUG_CANDIDATE
std::cout << " lane = " << ce->lane->getID() << "\n";
std::cout << " check vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
#endif
if (max == myChanger.end()) {
#ifdef DEBUG_CANDIDATE
std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
#endif
max = ce;
continue;
}
assert(veh(ce) != 0);
assert(veh(max) != 0);
if (veh(max)->getPositionOnLane() < veh(ce)->getPositionOnLane()) {
#ifdef DEBUG_CANDIDATE
std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << " oldMaxPos=" << veh(max)->getPositionOnLane() << "\n";
#endif
max = ce;
}
}
assert(max != myChanger.end());
assert(veh(max) != 0);
return max;
}
bool
MSLaneChanger::mayChange(int direction) const {
if (direction == 0) {
return true;
}
if (!myAllowsChanging) {
return false;
}
SUMOVehicleClass svc = veh(myCandi)->getVClass();
if (direction == -1) {
return myCandi->mayChangeRight && (myCandi - 1)->lane->allowsVehicleClass(svc) && myCandi->lane->allowsChangingRight(svc);
} else if (direction == 1) {
return myCandi->mayChangeLeft && (myCandi + 1)->lane->allowsVehicleClass(svc) && myCandi->lane->allowsChangingLeft(svc);
} else {
return false;
}
}
bool
MSLaneChanger::change() {
#ifdef DEBUG_ACTIONSTEPS
#endif
myCandi = findCandidate();
MSVehicle* vehicle = veh(myCandi);
vehicle->getLaneChangeModel().clearNeighbors();
if (vehicle->getLaneChangeModel().isChangingLanes() && !vehicle->getLaneChangeModel().alreadyChanged()) {
return continueChange(vehicle, myCandi);
}
if (!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
registerUnchanged(vehicle);
if (vehicle->isStoppedOnLane()) {
myCandi->lastStopped = vehicle;
}
return false;
}
if (!vehicle->isActive()) {
#ifdef DEBUG_ACTIONSTEPS
if (DEBUG_COND) {
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
}
#endif
bool changed = false;
const int oldstate = vehicle->getLaneChangeModel().getOwnState();
checkTraCICommands(vehicle);
if (oldstate != vehicle->getLaneChangeModel().getOwnState()) {
changed = applyTraCICommands(vehicle);
}
if (!changed) {
registerUnchanged(vehicle);
}
return changed;
}
std::pair<MSVehicle* const, double> leader = getRealLeader(myCandi);
if (myChanger.size() == 1 || vehicle->getLaneChangeModel().isOpposite() || (!mayChange(-1) && !mayChange(1))) {
if (changeOpposite(vehicle, leader, myCandi->lastStopped)) {
return true;
}
registerUnchanged(vehicle);
return false;
}
vehicle->updateBestLanes();
for (int i = 0; i < (int) myChanger.size(); ++i) {
vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
}
const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
int stateRight = 0;
if (mayChange(-1)) {
stateRight = checkChangeWithinEdge(-1, leader, preb);
if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_BLOCKED) == 0) {
vehicle->getLaneChangeModel().setOwnState(stateRight);
return startChange(vehicle, myCandi, -1);
}
if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_URGENT) != 0) {
(myCandi - 1)->lastBlocked = vehicle;
if ((myCandi - 1)->firstBlocked == nullptr) {
(myCandi - 1)->firstBlocked = vehicle;
}
}
}
int stateLeft = 0;
if (mayChange(1)) {
stateLeft = checkChangeWithinEdge(1, leader, preb);
if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_BLOCKED) == 0) {
vehicle->getLaneChangeModel().setOwnState(stateLeft);
return startChange(vehicle, myCandi, 1);
}
if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_URGENT) != 0) {
(myCandi + 1)->lastBlocked = vehicle;
if ((myCandi + 1)->firstBlocked == nullptr) {
(myCandi + 1)->firstBlocked = vehicle;
}
}
}
if ((stateRight & LCA_URGENT) != 0 && (stateLeft & LCA_URGENT) != 0) {
stateLeft = 0;
}
vehicle->getLaneChangeModel().setOwnState(stateRight | stateLeft);
if ((vehicle->getVClass() == SVC_EMERGENCY
|| hasOppositeStop(vehicle))
&& changeOpposite(vehicle, leader, myCandi->lastStopped)) {
return true;
}
registerUnchanged(vehicle);
return false;
}
void
MSLaneChanger::registerUnchanged(MSVehicle* vehicle) {
myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
vehicle->getLaneChangeModel().unchanged();
}
void
MSLaneChanger::checkTraCICommands(MSVehicle* vehicle) {
#ifdef DEBUG_STATE
const int oldstate = vehicle->getLaneChangeModel().getOwnState();
#endif
vehicle->getLaneChangeModel().checkTraCICommands();
#ifdef DEBUG_STATE
if (DEBUG_COND) {
const int newstate = vehicle->getLaneChangeModel().getOwnState();
std::cout << SIMTIME
<< " veh=" << vehicle->getID()
<< " oldState=" << toString((LaneChangeAction) oldstate)
<< " newState=" << toString((LaneChangeAction) newstate)
<< ((newstate & LCA_BLOCKED) != 0 ? " (blocked)" : "")
<< ((newstate & LCA_OVERLAPPING) != 0 ? " (overlap)" : "")
<< "\n";
}
#endif
}
bool
MSLaneChanger::applyTraCICommands(MSVehicle* vehicle) {
bool changed = false;
const int state = vehicle->getLaneChangeModel().getOwnState();
const int dir = (state & LCA_RIGHT) != 0 ? -1 : ((state & LCA_LEFT) != 0 ? 1 : 0);
const bool execute = dir != 0 && ((state & LCA_BLOCKED) == 0);
if (execute) {
ChangerIt to = myCandi + dir;
bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(myCandi->lane, to->lane, dir);
if (continuous) {
changed = continueChange(vehicle, myCandi);
} else {
to->registerHop(vehicle);
changed = true;
}
}
return changed;
}
bool
MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
if (vehicle->isRemoteControlled()) {
registerUnchanged(vehicle);
return false;
}
ChangerIt to = from + direction;
const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
if (continuous) {
return continueChange(vehicle, myCandi);
} else {
to->registerHop(vehicle);
to->lane->requireCollisionCheck();
return true;
}
}
bool
MSLaneChanger::continueChange(MSVehicle* vehicle, ChangerIt& from) {
MSAbstractLaneChangeModel& lcm = vehicle->getLaneChangeModel();
const int direction = lcm.isOpposite() ? -lcm.getLaneChangeDirection() : lcm.getLaneChangeDirection();
const bool pastMidpoint = lcm.updateCompletion();
const double speedLat = lcm.isOpposite() ? -lcm.getSpeedLat() : lcm.getSpeedLat();
vehicle->myState.myPosLat += SPEED2DIST(speedLat);
vehicle->myCachedPosition = Position::INVALID;
if (pastMidpoint) {
MSLane* source = myCandi->lane;
MSLane* target = source->getParallelLane(direction);
vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
lcm.primaryLaneChanged(source, target, direction);
if (&source->getEdge() == &target->getEdge()) {
ChangerIt to = from + direction;
to->registerHop(vehicle);
}
target->requireCollisionCheck();
} else {
from->registerHop(vehicle);
from->lane->requireCollisionCheck();
}
if (!lcm.isChangingLanes()) {
vehicle->myState.myPosLat = 0;
lcm.endLaneChangeManeuver();
}
lcm.updateShadowLane();
if (lcm.getShadowLane() != nullptr && &lcm.getShadowLane()->getEdge() == &vehicle->getLane()->getEdge()) {
myChanger[lcm.getShadowLane()->getIndex()].hoppedVeh = vehicle;
lcm.getShadowLane()->requireCollisionCheck();
}
vehicle->myAngle = vehicle->computeAngle();
if (lcm.isOpposite()) {
vehicle->myAngle += M_PI;
}
#ifdef DEBUG_CONTINUE_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " continueChange veh=" << vehicle->getID()
<< " from=" << Named::getIDSecure(from->lane)
<< " dir=" << direction
<< " speedLat=" << speedLat
<< " pastMidpoint=" << pastMidpoint
<< " posLat=" << vehicle->getLateralPositionOnLane()
<< " completion=" << lcm.getLaneChangeCompletion()
<< " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
<< "\n";
}
#endif
return pastMidpoint && lcm.getShadowLane() == nullptr;
}
std::pair<MSVehicle* const, double>
MSLaneChanger::getRealLeader(const ChangerIt& target) const {
assert(veh(myCandi) != 0);
MSVehicle* vehicle = veh(myCandi);
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl;
}
#endif
MSVehicle* neighLead = target->lead;
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
if (neighLead != 0) {
std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl;
}
}
#endif
if (target->hoppedVeh != nullptr) {
double hoppedPos = target->hoppedVeh->getPositionOnLane();
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl;
}
#endif
if (hoppedPos > vehicle->getPositionOnLane() && (neighLead == nullptr || neighLead->getPositionOnLane() > hoppedPos)) {
neighLead = target->hoppedVeh;
}
}
const bool checkBidi = target->lane->getBidiLane() != nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
if (neighLead == nullptr || checkBidi) {
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << "Looking for leader on consecutive lanes." << std::endl;
}
#endif
MSLane* targetLane = target->lane;
const double egoBack = vehicle->getBackPositionOnLane();
double leaderBack = targetLane->getLength();
if (neighLead != nullptr) {
leaderBack = neighLead->getBackPositionOnLane(targetLane);
}
for (MSVehicle* pl : targetLane->myPartialVehicles) {
double plBack = pl->getBackPositionOnLane(targetLane);
if (pl->isBidiOn(targetLane)) {
plBack -= pl->getVehicleType().getLengthWithGap();
}
const double plPos = plBack + pl->getVehicleType().getLength();
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << " partial=" << pl->getID() << " plBack=" << plBack << " plPos=" << plPos << " leaderBack=" << leaderBack << " egoBack=" << egoBack << "\n";
}
#endif
if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
neighLead = pl;
leaderBack = plBack;
}
}
if (neighLead != nullptr) {
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << " found leader=" << neighLead->getID() << " (partial)\n";
}
#endif
const double gap = leaderBack - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
return std::pair<MSVehicle*, double>(neighLead, gap);
}
double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
double speed = vehicle->getSpeed();
double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
if (target->lane->getBidiLane() != nullptr) {
dist += target->lane->getBidiLane()->getMaximumBrakeDist();
}
if (seen > dist && !myCandi->lane->isInternal()) {
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << " found no leader within dist=" << dist << "\n";
}
#endif
return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
}
const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(targetLane);
std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << " found consecutiveLeader=" << Named::getIDSecure(result.first) << "\n";
}
#endif
return result;
} else {
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << " found leader=" << neighLead->getID() << "\n";
}
#endif
return std::pair<MSVehicle* const, double>(neighLead, neighLead->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap());
}
}
std::pair<MSVehicle* const, double>
MSLaneChanger::getRealFollower(const ChangerIt& target) const {
assert(veh(myCandi) != 0);
MSVehicle* vehicle = veh(myCandi);
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl;
}
#endif
const double candiPos = vehicle->getPositionOnLane();
MSVehicle* neighFollow = nullptr;
if (target != myCandi) {
neighFollow = veh(target);
} else {
if (target->lane->myVehicles.size() > 1) {
neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
}
}
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
if (neighFollow != 0) {
std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl;
} else {
std::cout << "veh(target) returns none." << std::endl;
}
}
#endif
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
}
}
#endif
neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
if (partialBehind != 0 && partialBehind != neighFollow) {
std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() << "' at position " << partialBehind->getPositionOnLane() << " is closer." << std::endl;
}
}
#endif
neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
if (neighFollow == nullptr) {
CLeaderDist consecutiveFollower = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true)[0];
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
if (consecutiveFollower.first == 0) {
std::cout << "no follower found." << std::endl;
} else {
std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl;
}
}
#endif
return std::make_pair(const_cast<MSVehicle*>(consecutiveFollower.first), consecutiveFollower.second);
} else {
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl;
}
#endif
return std::pair<MSVehicle* const, double>(neighFollow,
vehicle->getPositionOnLane() - vehicle->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
}
}
MSVehicle*
MSLaneChanger::getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2) {
if (follow1 == nullptr || follow1->getPositionOnLane() > maxPos) {
return follow2;
} else if (follow2 == nullptr || follow2->getPositionOnLane() > maxPos) {
return follow1;
} else {
if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
return follow1;
} else {
return follow2;
}
}
}
int
MSLaneChanger::checkChangeWithinEdge(
int laneOffset,
const std::pair<MSVehicle* const, double>& leader,
const std::vector<MSVehicle::LaneQ>& preb) const {
std::pair<MSVehicle*, double> follower = getRealFollower(myCandi);
std::pair<MSVehicle* const, double> neighLead = getRealLeader(myCandi + laneOffset);
std::pair<MSVehicle*, double> neighFollow = getRealFollower(myCandi + laneOffset);
if (neighLead.first != nullptr && neighLead.first == neighFollow.first) {
neighFollow.first = 0;
}
ChangerIt target = myCandi + laneOffset;
return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
}
int
MSLaneChanger::checkChange(
int laneOffset,
const MSLane* targetLane,
const std::pair<MSVehicle* const, double>& leader,
const std::pair<MSVehicle* const, double>& follower,
const std::pair<MSVehicle* const, double>& neighLead,
const std::pair<MSVehicle* const, double>& neighFollow,
const std::vector<MSVehicle::LaneQ>& preb) const {
MSVehicle* vehicle = veh(myCandi);
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout
<< "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'"
<< std::endl;
}
#endif
int blocked = 0;
int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
if (neighFollow.first != nullptr && neighFollow.second < 0) {
blocked |= (blockedByFollower | LCA_OVERLAPPING);
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " overlapping with follower..."
<< std::endl;
}
#endif
}
if (neighLead.first != nullptr && neighLead.second < 0) {
blocked |= (blockedByLeader | LCA_OVERLAPPING);
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " overlapping with leader..."
<< std::endl;
}
#endif
}
double secureFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
double secureBackGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
double secureOrigFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
const double tauRemainder = vehicle->getActionStepLength() == DELTA_T ? 0 : MAX2(vehicle->getCarFollowModel().getHeadwayTime() - TS, 0.);
if ((blocked & blockedByFollower) == 0 && neighFollow.first != nullptr) {
const double vNextFollower = neighFollow.first->getSpeed() + MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
const double vNextLeader = vehicle->getSpeed() + MIN2(0., tauRemainder * vehicle->getAcceleration());
secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
vNextLeader, vehicle->getCarFollowModel().getMaxDecel());
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " follower=" << neighFollow.first->getID()
<< " backGap=" << neighFollow.second
<< " vNextFollower=" << vNextFollower
<< " vNextEgo=" << vNextLeader
<< " secureGap=" << secureBackGap
<< " safetyFactor=" << vehicle->getLaneChangeModel().getSafetyFactor()
<< " blocked=" << (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor())
<< "\n";
}
#endif
if (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
if (vehicle->getLaneChangeModel().isOpposite()
&& neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << " ignoring opposite follower who changed in this step\n";
}
#endif
} else {
blocked |= blockedByFollower;
}
}
}
if ((blocked & blockedByLeader) == 0 && neighLead.first != nullptr) {
const double vNextFollower = vehicle->getSpeed() + MAX2(0., tauRemainder * vehicle->getAcceleration());
const double vNextLeader = neighLead.first->getSpeed() + MIN2(0., tauRemainder * neighLead.first->getAcceleration());
secureFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead.first, vNextFollower,
vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel());
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " leader=" << neighLead.first->getID()
<< " frontGap=" << neighLead.second
<< " vNextEgo=" << vNextFollower
<< " vNextLeader=" << vNextLeader
<< " secureGap=" << secureFrontGap
<< " safetyFactor=" << vehicle->getLaneChangeModel().getSafetyFactor()
<< " blocked=" << (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor())
<< "\n";
}
#endif
if (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
blocked |= blockedByLeader;
}
}
if (blocked == 0 && targetLane->hasPedestrians()) {
PersonDist nextLeader = targetLane->nextBlocking(vehicle->getBackPositionOnLane(),
vehicle->getRightSideOnLane(targetLane), vehicle->getRightSideOnLane(targetLane) + vehicle->getVehicleType().getWidth(),
ceil(vehicle->getSpeed() / vehicle->getCarFollowModel().getMaxDecel()));
if (nextLeader.first != 0) {
const double brakeGap = vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed());
const double gap = nextLeader.second - vehicle->getVehicleType().getLengthWithGap();
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME << " pedestrian on road " + leader.first->getID() << " gap=" << gap << " brakeGap=" << brakeGap << "\n";
}
#endif
if (brakeGap > gap) {
blocked |= blockedByLeader;
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME << " blocked by pedestrian " + leader.first->getID() << "\n";
}
#endif
}
}
}
if (leader.first != nullptr) {
secureOrigFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle, leader.first, vehicle->getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
}
MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
int state = blocked | vehicle->getLaneChangeModel().wantsChange(
laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != nullptr) {
const double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
const double speed = vehicle->getSpeed();
const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
if (seen < dist || myCandi->lane->isInternal()) {
std::pair<MSVehicle* const, double> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
if (neighLead2.first != nullptr && neighLead2.first != neighLead.first) {
const double secureGap = vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead2.first, vehicle->getSpeed(),
neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
const double secureGap2 = secureGap * vehicle->getLaneChangeModel().getSafetyFactor();
#ifdef DEBUG_SURROUNDING_VEHICLES
if (DEBUG_COND) {
std::cout << SIMTIME << " found critical leader=" << neighLead2.first->getID()
<< " gap=" << neighLead2.second << " secGap=" << secureGap << " secGap2=" << secureGap2 << "\n";
}
#endif
if (neighLead2.second < secureGap2) {
state |= blockedByLeader;
}
}
}
}
if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
double targetZipperDist = 0;
if (laneOffset == 0) {
targetZipperDist = myCandi->zipperDist;
} else if (laneOffset == 1) {
if ((myCandi + 1) != myChanger.end()) {
targetZipperDist = (myCandi + 1)->zipperDist;
}
} else if (laneOffset == -1) {
if (myCandi > myChanger.begin()) {
targetZipperDist = (myCandi - 1)->zipperDist;
}
}
if (vehicle->unsafeLinkAhead(targetLane, targetZipperDist)) {
state |= blockedByLeader;
}
}
if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
const double distToNeighLane = 0.5 * (vehicle->getLane()->getWidth() + targetLane->getWidth());
const MSAbstractLaneChangeModel& lcm = vehicle->getLaneChangeModel();
const double assumedDecel = lcm.getAssumedDecelForLaneChangeDuration();
const double estimatedLCDuration = lcm.estimateLCDuration(vehicle->getSpeed(), distToNeighLane, assumedDecel, (state & LCA_URGENT) != 0);
if (estimatedLCDuration == -1) {
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME << " checkChange() too slow to guarantee completion of continuous lane change."
<< "\nestimatedLCDuration=" << estimatedLCDuration
<< "\ndistToNeighLane=" << distToNeighLane
<< std::endl;
}
#endif
state |= LCA_INSUFFICIENT_SPEED;
} else {
const double decel = vehicle->getCarFollowModel().getMaxDecel() * estimatedLCDuration;
const double avgSpeed = 0.5 * (
MAX2(0., vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
MAX2(0., vehicle->getSpeed() - decel));
const double space2change = avgSpeed * estimatedLCDuration;
double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME << " checkChange() checking continuous lane change..."
<< "\ndistToNeighLane=" << distToNeighLane
<< " estimatedLCDuration=" << estimatedLCDuration
<< " space2change=" << space2change
<< " avgSpeed=" << avgSpeed
<< std::endl;
}
#endif
const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
int view = 1;
const MSLane* nextLane = vehicle->getLane();
std::vector<MSLink*>::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
while (!nextLane->isLinkEnd(link) && seen <= space2change) {
if ((*link)->getDirection() == LinkDirection::LEFT || (*link)->getDirection() == LinkDirection::RIGHT
|| (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
) {
state |= LCA_INSUFFICIENT_SPACE;
break;
}
if ((*link)->getViaLane() == nullptr) {
view++;
}
nextLane = (*link)->getViaLaneOrLane();
seen += nextLane->getLength();
link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
}
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << " available distance=" << seen << std::endl;
}
#endif
if (nextLane->isLinkEnd(link) && seen < space2change) {
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
}
#endif
state |= LCA_INSUFFICIENT_SPACE;
}
if ((state & LCA_BLOCKED) == 0) {
const double speed = vehicle->getSpeed();
seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
nextLane = vehicle->getLane();
view = 1;
const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
std::vector<MSLink*>::const_iterator nextLink = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
while (!nextLane->isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
nextLane = (*nextLink)->getViaLaneOrLane();
const MSLane* const parallelLane = nextLane->getParallelLane(laneOffset);
if (parallelLane == nullptr) {
state |= LCA_INSUFFICIENT_SPACE;
break;
} else {
std::pair<MSVehicle* const, double> neighLead2 = parallelLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
if (neighLead2.first != nullptr && neighLead2.first != neighLead.first
&& (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead2.first,
vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
state |= blockedByLeader;
break;
}
}
if ((*nextLink)->getViaLane() == nullptr) {
view++;
}
seen += nextLane->getLength();
nextLink = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
}
}
}
}
if (checkOpened && (state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0
&& vehicle->getLane()->isNormal()
&& vehicle->getBestLanesContinuation().size() > 1) {
const MSLink* link = vehicle->getLane()->getLinkTo(vehicle->getBestLanesContinuation()[1]);
if (link != nullptr && link->isEntryLink()) {
const MSLink* link2 = link->getParallelLink(laneOffset);
if (link2 != nullptr) {
auto api = link->getApproachingPtr(vehicle);
if (api != nullptr) {
if (!link2->opened(api->arrivalTime, api->arrivalSpeed, api->leaveSpeed, vehicle->getLength(),
vehicle->getImpatience(), vehicle->getCarFollowModel().getMaxDecel(), vehicle->getWaitingTime(), vehicle->getLateralPositionOnLane(),
nullptr, false, vehicle, api->dist)) {
state |= LCA_BLOCKED;
}
}
}
}
}
const int oldstate = state;
state = vehicle->influenceChangeDecision(state);
blocked = state & LCA_BLOCKED;
#ifdef DEBUG_CHECK_CHANGE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " veh=" << vehicle->getID()
<< " oldState=" << toString((LaneChangeAction)oldstate)
<< " newState=" << toString((LaneChangeAction)state)
<< ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
<< ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
<< "\n";
}
#endif
if (state & LCA_WANTS_LANECHANGE && blocked == 0) {
blocked = vehicle->getLaneChangeModel().checkChangeBeforeCommitting(vehicle, state);
state |= blocked;
}
vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
vehicle->getLaneChangeModel().setFollowerGaps(neighFollow, secureBackGap);
vehicle->getLaneChangeModel().setLeaderGaps(neighLead, secureFrontGap);
vehicle->getLaneChangeModel().setOrigLeaderGaps(leader, secureOrigFrontGap);
}
if (laneOffset != 0) {
vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollow, neighLead);
}
return state;
}
bool
MSLaneChanger::hasOppositeStop(MSVehicle* vehicle) {
if (vehicle->hasStops()) {
const MSStop& stop = vehicle->getNextStop();
if (stop.isOpposite && vehicle->nextStopDist() < OPPOSITE_OVERTAKING_MAX_LOOKAHEAD) {
return true;
}
}
return false;
}
bool
MSLaneChanger::checkOppositeStop(MSVehicle* vehicle, const MSLane* oncomingLane, const MSLane* opposite, std::pair<MSVehicle*, double> leader) {
const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
std::pair<MSVehicle*, double> neighLead(nullptr, -1);
std::pair<MSVehicle*, double> oncoming(nullptr, -1);
const std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, vehicle->getNextStop().lane, -1);
const int laneIndex = vehicle->getLaneChangeModel().getNormalizedLaneIndex();
const int bestOffset = preb[laneIndex].bestLaneOffset;
const double spaceToStop = vehicle->nextStopDist();
const double timeToStopForward = spaceToStop / MAX2(vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxAccel());
const double timeToStopLateral = (MSGlobals::gLaneChangeDuration > 0
? STEPS2TIME(MSGlobals::gLaneChangeDuration) * bestOffset
: (MSGlobals::gLateralResolution > 0
? bestOffset * SUMO_const_laneWidth / vehicle->getVehicleType().getMaxSpeedLat()
: 0.));
const double timeToStop = MAX2(timeToStopForward, timeToStopLateral);
if (!isOpposite) {
const double searchDist = timeToStop * oncomingLane->getSpeedLimit() * 2 + spaceToStop;
neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax);
} else {
double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax);
}
double oncomingSpeed;
const double surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
if (!isOpposite && surplusGap < 0) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
<< " timeToStopForward=" << timeToStopForward << " timeToStopLateral=" << timeToStopLateral << " surplusGap=" << surplusGap << "\n";
}
#endif
return false;
}
if (bestOffset > 0) {
MSLane* const target = preb[laneIndex + 1].lane;
neighLead = target->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_MAX_LOOKAHEAD, true);
std::pair<MSVehicle* const, double> neighFollow = target->getOppositeFollower(vehicle);
return checkChangeOpposite(vehicle, 1, target, leader, neighLead, neighFollow, preb);
} else {
return false;
}
}
std::vector<MSVehicle::LaneQ>
MSLaneChanger::getBestLanesOpposite(MSVehicle* vehicle, const MSLane* stopLane, double oppositeLength) {
const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
const MSEdge* forward = isOpposite ? vehicle->getLane()->getEdge().getOppositeEdge()->getNormalSuccessor() : vehicle->getLane()->getEdge().getNormalSuccessor();
const MSEdge* opposite = forward->getOppositeEdge();
const int numForward = forward->getNumLanes();
const int numOpposite = opposite->getNumLanes();
const std::vector<MSLane*>& oLanes = opposite->getLanes();
std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
for (int i = 0; i < numOpposite; i++) {
preb.push_back(preb.back());
preb.back().lane = oLanes[numOpposite - 1 - i];
preb.back().length = oppositeLength;
if (isOpposite) {
preb.back().bestLaneOffset = -1 - i;
}
}
if (stopLane != nullptr) {
const int stopIndex = numForward + numOpposite - stopLane->getIndex() - 1;
for (int i = 0; i < (int)preb.size(); i++) {
preb[i].bestLaneOffset = stopIndex - i;
preb[i].length = vehicle->getLaneChangeModel().getForwardPos() + vehicle->nextStopDist();
}
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " getBestLanesOpposite " << vehicle->getID() << " isOpposite=" << isOpposite << "\n";
for (int i = 0; i < (int)preb.size(); i++) {
std::cout << " i=" << i << " lane=" << preb[i].lane->getID() << " bestOffset=" << preb[i].bestLaneOffset << " length=" << preb[i].length << "\n";
}
}
#endif
return preb;
}
bool
MSLaneChanger::changeOpposite(MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, MSVehicle* lastStopped) {
if (!myChangeToOpposite) {
return false;
}
const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
MSLane* source = vehicle->getMutableLane();
MSLane* opposite = isOpposite ? source->getParallelLane(1) : source->getOpposite();
#ifdef DEBUG_CHANGE_OPPOSITE
gDebugFlag5 = DEBUG_COND;
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " considerChangeOpposite source=" << source->getID()
<< " opposite=" << Named::getIDSecure(opposite) << " lead=" << Named::getIDSecure(leader.first) << " isOpposite=" << isOpposite << "\n";
}
#endif
if (opposite == nullptr) {
return false;
}
if (vehicle->isStopped()) {
return false;
}
int ret = 0;
ret = vehicle->influenceChangeDecision(ret);
bool oppositeChangeByTraci = false;
if ((ret & (LCA_TRACI)) != 0) {
if (isOpposite && (ret & LCA_LEFT) != 0) {
return false;
}
oppositeChangeByTraci = true;
}
if (!isOpposite && !oppositeChangeByTraci && !source->allowsChangingLeft(vehicle->getVClass())) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " not overtaking due to changeLeft restriction\n";
}
#endif
return false;
}
if (!opposite->allowsVehicleClass(vehicle->getVClass())) {
return false;
}
const MSLane* oncomingLane = isOpposite ? source : opposite;
int direction = isOpposite ? -1 : 1;
std::pair<MSVehicle*, double> neighLead(nullptr, -1);
double surplusGap = std::numeric_limits<double>::max();
std::pair<MSVehicle*, double> overtaken(nullptr, -1);
std::pair<MSVehicle*, double> oncoming(nullptr, -1);
std::pair<MSVehicle*, double> oncomingOpposite(nullptr, -1);
double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
double oncomingSpeed = oncomingLane->getSpeedLimit();
const bool isEmergency = vehicle->getVClass() == SVC_EMERGENCY;
if (!oppositeChangeByTraci && hasOppositeStop(vehicle)) {
return checkOppositeStop(vehicle, oncomingLane, opposite, leader);
}
if (!isOpposite && leader.first == nullptr && !oppositeChangeByTraci) {
return false;
}
if (!isOpposite && !oppositeChangeByTraci
&& !isEmergency
&& leader.first != nullptr) {
if (leader.first->signalSet(MSGlobals::gLefthand
? MSVehicle::VEH_SIGNAL_BLINKER_RIGHT : MSVehicle::VEH_SIGNAL_BLINKER_LEFT)) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " not overtaking leader " << leader.first->getID() << " that has blinker set\n";
}
#endif
if (lastStopped != nullptr && vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT) {
neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
}
return false;
} else if (leader.second < 0) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " not overtaking leader " << leader.first->getID() << " with gap " << leader.second << "\n";
}
#endif
return false;
}
}
double timeToOvertake = std::numeric_limits<double>::max();
double spaceToOvertake = std::numeric_limits<double>::max();
double maxSpaceToOvertake = 0;
if (oppositeChangeByTraci) {
timeToOvertake = STEPS2TIME(vehicle->getInfluencer().getLaneTimeLineDuration());
spaceToOvertake = timeToOvertake * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
} else {
if (isOpposite) {
neighLead = opposite->getOppositeLeader(vehicle, -1, false);
overtaken = opposite->getLeader(vehicle, opposite->getOppositePos(vehicle->getBackPositionOnLane()), vehicle->getBestLanesContinuation(opposite));
overtaken.second -= vehicle->getVehicleType().getLength();
if (overtaken.first == nullptr && neighLead.first != nullptr) {
overtaken = neighLead;
}
if (overtaken.first != nullptr) {
overtaken = getColumnleader(maxSpaceToOvertake, vehicle, overtaken);
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " leaderOnSource=" << Named::getIDSecure(oncoming.first) << " gap=" << oncoming.second << "\n";
std::cout << " leaderOnTarget=" << Named::getIDSecure(neighLead.first) << " gap=" << neighLead.second << "\n";
std::cout << " overtaken=" << Named::getIDSecure(overtaken.first) << " gap=" << overtaken.second << "\n";
}
#endif
} else {
overtaken = getColumnleader(maxSpaceToOvertake, vehicle, leader);
}
if (overtaken.first == 0) {
if (!isOpposite) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " no leader found\n";
}
#endif
if (vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT) {
neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
resolveDeadlock(vehicle, leader, neighLead, std::make_pair(nullptr, leader.second));
}
return false;
}
} else {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " compute time/space to overtake for columnLeader=" << overtaken.first->getID() << " egoGap=" << overtaken.second << "\n";
}
#endif
vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, maxSpaceToOvertake));
computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " veh=" << vehicle->getID()
<< " changeOpposite opposite=" << opposite->getID()
<< " lead=" << Named::getIDSecure(leader.first)
<< " maxSpaceToOvertake=" << maxSpaceToOvertake
<< " vMax=" << vMax
<< " timeToOvertake=" << timeToOvertake
<< " spaceToOvertake=" << spaceToOvertake
<< "\n";
}
#endif
if (!isOpposite && spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOpposite (cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
}
#endif
neighLead = oncomingLane->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
bool wait = false;
if (vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT) {
wait = resolveDeadlock(vehicle, leader, neighLead, overtaken);
}
if (!wait && lastStopped != nullptr) {
const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " lastStopped=" << Named::getIDSecure(lastStopped) << " gap=" << lastStoppedGap << "\n";
}
#endif
avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
}
return false;
}
}
if (!isOpposite) {
assert(timeToOvertake != std::numeric_limits<double>::max());
assert(spaceToOvertake != std::numeric_limits<double>::max());
double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 2 + spaceToOvertake;
neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
} else {
double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
}
if (oncoming.first != nullptr && (oncoming.first->isStopped()
|| oncoming.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT)) {
const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
if (oncomingGap > 0) {
vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, oncomingGap));
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " oncoming=" << oncoming.first->getID() << " stopped=" << oncoming.first->isStopped()
<< " halting=" << oncoming.first->getWaitingSeconds()
<< " oncomingGap=" << oncomingGap
<< " vMaxGap=" << getMaxOvertakingSpeed(vehicle, oncomingGap)
<< " vMax=" << vMax << "\n";
}
#endif
}
if (overtaken.first != nullptr && vMax != vehicle->getLane()->getVehicleMaxSpeed(vehicle)) {
computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " recomputed overtaking time with vMax=" << vMax
<< " timeToOvertake=" << timeToOvertake
<< " spaceToOvertake=" << spaceToOvertake
<< "\n";
}
#endif
}
if (!isOpposite) {
if (spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOpposite (check2: cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
}
#endif
resolveDeadlock(vehicle, leader, neighLead, overtaken);
return false;
}
if (vehicle->nextStopDist() < spaceToOvertake) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
}
#endif
return false;
}
assert(timeToOvertake != std::numeric_limits<double>::max());
assert(spaceToOvertake != std::numeric_limits<double>::max());
}
surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
if (oncomingOpposite.first != nullptr) {
double oncomingSpeed2;
const double conservativeTime = ceil(timeToOvertake / TS) * TS;
const double conservativeSpace = conservativeTime * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
const double surplusGap2 = computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2, true);
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " oncomingOpposite=" << oncomingOpposite.first->getID() << " speed=" << oncomingSpeed2 << " gap=" << oncomingOpposite.second << " surplusGap2=" << surplusGap2 << "\n";
}
#endif
surplusGap = MIN2(surplusGap, surplusGap2);
oncomingSpeed = MAX2(oncomingSpeed, oncomingSpeed2);
if (!isOpposite && surplusGap >= 0 && oncoming.first != nullptr && oncoming.first->isStopped()
&& oncomingOpposite.second > oncoming.second) {
const double oSpeed = MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
const double closingSpeed = (vehicle->getLane()->getVehicleMaxSpeed(vehicle)
+ oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
double ooTTO = ooSTO / oSpeed;
ooTTO = ceil(ooTTO / TS) * TS;
const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " oSpeed=" << oSpeed << " ooSTO=" << ooSTO << " ooTTO=" << ooTTO << " surplusGap3=" << surplusGap3 << "\n";
}
#endif
surplusGap = MIN2(surplusGap, surplusGap3);
}
}
if (!isOpposite && surplusGap < 0) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap << ")\n";
}
#endif
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
if (oncoming.first->getLaneChangeModel().isOpposite()) {
std::cout << SIMTIME << " ego=" << vehicle->getID() << " does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() << " (but the leader is also opposite)\n";
}
}
#endif
avoidDeadlock(vehicle, neighLead, overtaken, leader);
return false;
}
}
double usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane();
if (usableDist < spaceToOvertake) {
const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
assert(bestLaneConts.size() >= 1);
std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n";
}
#endif
const MSLane* oppLane = (*it)->getOpposite();
if ((oppLane == nullptr && !isEmergency) || (oppLane != nullptr && !oppLane->allowsVehicleClass(vehicle->getVClass()))) {
break;
}
const MSLane* const prev = *(it - 1);
if (prev != nullptr) {
const MSLink* link = prev->getLinkTo(*it);
if (link == nullptr || link->getState() == LINKSTATE_ZIPPER
|| (link->getDirection() != LinkDirection::STRAIGHT && !isEmergency)
|| (!link->havePriority()
&& (!vehicle->hasInfluencer() || vehicle->getInfluencer().getRespectJunctionPriority())
&& ((!link->haveRed() && !link->haveYellow()) || !vehicle->ignoreRed(link, true)))) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " stop lookahead at link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID()) << " state=" << (link == 0 ? "?" : toString(link->getState())) << " ignoreRed=" << vehicle->ignoreRed(link, true) << "\n";
}
#endif
break;
}
}
usableDist += (*it)->getLength();
++it;
}
}
if (!isOpposite && usableDist < spaceToOvertake) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n";
}
#endif
return false;
}
if (!isOpposite && MSNet::getInstance()->hasElevation() && !overtaken.first->isStopped()) {
double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 1.5 * vehicle->getLaneChangeModel().getOppositeSafetyFactor() + spaceToOvertake;
int view = vehicle->getLane()->isInternal() ? 1 : 0;
bool foundHill = vehicle->getSlope() > 0;
if (foundHilltop(vehicle, foundHill, searchDist, vehicle->getBestLanesContinuation(), view, vehicle->getPositionOnLane(), vehicle->getPosition().z(), OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD)) {
return false;
}
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
}
#endif
std::pair<MSVehicle* const, double> neighFollow = opposite->getOppositeFollower(vehicle);
double oppositeLength = vehicle->getBestLanes().back().length;
if (isOpposite) {
const bool canOvertake = spaceToOvertake <= OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE;
oppositeLength = computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
leader.first = nullptr;
if (neighLead.first != nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
neighLead.first = nullptr;
}
} else {
if (leader.first != nullptr && neighLead.first != nullptr && leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT && !isEmergency) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " not changing to avoid deadlock\n";
}
#endif
return false;
}
if (neighLead.first != nullptr && neighLead.first->isStopped()) {
if (yieldToOppositeWaiting(vehicle, neighLead.first, 10)) {
return false;
}
}
if (oncoming.first != nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
if (yieldToOppositeWaiting(vehicle, oncoming.first, 10, TIME2STEPS(60))) {
return false;
}
}
}
std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, nullptr, oppositeLength);
return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
}
bool
MSLaneChanger::avoidDeadlock(MSVehicle* vehicle,
std::pair<MSVehicle*, double> neighLead,
std::pair<MSVehicle*, double> overtaken,
std::pair<MSVehicle*, double> leader) {
assert(!vehicle->getLaneChangeModel().isOpposite());
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
<< " neighLead=" << Named::getIDSecure(neighLead.first)
<< " overtaken=" << Named::getIDSecure(overtaken.first)
<< " leader=" << Named::getIDSecure(leader.first)
<< "\n";
}
#endif
if (leader.first == nullptr || neighLead.first == nullptr || overtaken.first == nullptr) {
return false;
} else if (!neighLead.first->isStopped()
&& vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT) {
auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
}
#endif
if (neighLead.first == nullptr) {
return false;
}
}
const bool yield = (yieldToDeadlockOncoming(vehicle, neighLead.first, overtaken.second)
|| leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT);
if (neighLead.first->isStopped()
&& (overtaken.first->isStopped()
|| leader.first->getLaneChangeModel().isOpposite()
|| yield)) {
double requiredGap = MAX2(vehicle->getVehicleType().getLengthWithGap(), neighLead.first->getVehicleType().getLengthWithGap());
requiredGap = MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
requiredGap = MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
requiredGap += 1;
const double distToStop = neighLead.second - requiredGap;
double neighStoppedBack = vehicle->getVehicleType().getMinGap();
while (neighLead.first != nullptr && neighLead.first->isStopped()) {
const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
if (neighStoppedBack + nextGap > overtaken.second) {
break;
}
neighStoppedBack += nextGap;
auto neighLeadFollow = neighLead.first->getFollower();
neighLead.second = neighLeadFollow.second;
neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << " neighLeadFollower=" << Named::getIDSecure(neighLead.first) << "\n";
}
#endif
if (neighStoppedBack > overtaken.second) {
break;
}
}
const double leaderBGap = leader.first->getBrakeGap();
const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->getBestLanesContinuation(), overtaken.second, true).second;
const double extraGap = MAX2(leaderBGap, leaderFGap);
const double gapWithEgo = leader.second + extraGap - neighStoppedBack - vehicle->getVehicleType().getLengthWithGap();
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
<< " neighLeadGap=" << neighLead.second
<< " leaderGap=" << leader.second
<< " bGap=" << leaderBGap
<< " fGap=" << leaderFGap
<< " eGap=" << extraGap
<< " neighStoppedBack=" << neighStoppedBack
<< " neighStoppedBackPos=" << vehicle->getPositionOnLane() + neighStoppedBack
<< " requiredGap=" << requiredGap
<< " gapWithEgo=" << gapWithEgo
<< " yield=" << yield
<< "\n";
}
#endif
if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
const double currentDist = preb[vehicle->getLane()->getIndex()].length;
const double stopPos = vehicle->getPositionOnLane() + distToStop;
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << " currentDist=" << currentDist << " stopPos=" << stopPos << " lGap+eGap=" << leader.second + extraGap << " distToStop=" << distToStop << "\n";
}
#endif
if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
const double blockerLength = currentDist - stopPos + vehicle->getVehicleType().getMinGap();
const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
<< " blockerLength=" << blockerLength
<< " reserved=" << reserved
<< "\n";
}
#endif
return reserved;
}
}
}
return false;
}
bool
MSLaneChanger::yieldToDeadlockOncoming(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist) {
if (vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT && stoppedNeigh != nullptr) {
std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
double followerGap = stoppedNeigh->getVehicleType().getLengthWithGap();
while (follower.first != nullptr && followerGap < dist && follower.first->isStopped()) {
followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
follower = follower.first->getFollower(dist);
};
if (follower.first != nullptr) {
followerGap += follower.second;
}
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " yieldToDeadlockOncoming"
<< " dist=" << dist << " follower=" << Named::getIDSecure(follower.first) << " fGap=" << followerGap
<< "\n";
}
#endif
return follower.first != nullptr && followerGap < dist && !follower.first->isStopped();
}
return false;
}
bool
MSLaneChanger::yieldToOppositeWaiting(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist, SUMOTime deltaWait) {
std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
while (follower.first != nullptr && follower.second < dist && follower.first->isStopped()) {
follower = follower.first->getFollower(dist);
};
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND && follower.first != nullptr) {
std::cout << SIMTIME << " yieldToOppositeWaiting veh=" << vehicle->getID() << " stoppedNeigh=" << stoppedNeigh->getID()
<< " oncoming=" << follower.first->getID()
<< " wait=" << follower.first->getWaitingSeconds()
<< " vehWait=" << vehicle->getWaitingSeconds()
<< " deltaWait=" << STEPS2TIME(deltaWait)
<< "\n";
}
#endif
if (follower.first != nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->getWaitingTime() + deltaWait) {
return true;
}
return false;
}
bool
MSLaneChanger::resolveDeadlock(MSVehicle* vehicle,
std::pair<MSVehicle* const, double> leader,
std::pair<MSVehicle*, double> neighLead,
std::pair<MSVehicle*, double> overtaken) {
const double deadLockZone = overtaken.second;
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock waiting=" << vehicle->getWaitingSeconds()
<< " leader=" << Named::getIDSecure(leader.first)
<< " gap=" << leader.second
<< "\n";
}
#endif
if (vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT
&& leader.first != nullptr && leader.second > vehicle->getVehicleType().getLengthWithGap()) {
std::pair<MSVehicle* const, double> oncomingOpposite = getOncomingOppositeVehicle(vehicle, std::make_pair(nullptr, -1), leader.second);
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
<< " leader=" << leader.first->getID()
<< " leaderGap=" << leader.second
<< " neighLead=" << Named::getIDSecure(neighLead.first)
<< " deadLockZone=" << deadLockZone
<< "\n";
}
#endif
if (neighLead.first != nullptr && !neighLead.first->isStopped()) {
auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
}
#endif
}
if (oncomingOpposite.first != nullptr ||
(neighLead.first != nullptr && neighLead.first->isStopped()
&& yieldToDeadlockOncoming(vehicle, neighLead.first, deadLockZone))) {
const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
const double currentDist = preb[vehicle->getLane()->getIndex()].length;
const double blockerLength = currentDist - vehicle->getPositionOnLane() - POSITION_EPS - NUMERICAL_EPS;
const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
<< " leader=" << leader.first->getID()
<< " leaderGap=" << leader.second
<< " oncoming=" << Named::getIDSecure(oncomingOpposite.first)
<< " currentDist=" << currentDist
<< " blockerLength=" << blockerLength
<< " reserved=" << reserved
<< "\n";
}
#else
UNUSED_PARAMETER(reserved);
#endif
return true;
}
}
return false;
}
double
MSLaneChanger::computeSafeOppositeLength(MSVehicle* vehicle, double oppositeLength, const MSLane* source, double usableDist,
std::pair<MSVehicle*, double> oncoming, double vMax, double oncomingSpeed,
std::pair<MSVehicle*, double> neighLead,
std::pair<MSVehicle*, double> overtaken,
std::pair<MSVehicle*, double> neighFollow,
double surplusGap, const MSLane* opposite,
bool canOvertake) {
const double forwardPos = source->getOppositePos(vehicle->getPositionOnLane());
oppositeLength = MIN2(oppositeLength, usableDist + forwardPos);
oppositeLength = MIN2(oppositeLength, vehicle->nextStopDist() + forwardPos);
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " laneQLength=" << oppositeLength << " usableDist=" << usableDist << " forwardPos=" << forwardPos << " stopDist=" << vehicle->nextStopDist() << "\n";
}
#endif
const MSVehicle* oncomingVeh = oncoming.first;
if (oncomingVeh != 0) {
if (!oncomingVeh->getLaneChangeModel().isOpposite() && oncomingVeh->getLaneChangeModel().getShadowLane() != source) {
double egoSpeedFraction = 0.5;
if (oncomingSpeed > 0) {
egoSpeedFraction = MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
}
oppositeLength = MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " found oncoming leader=" << oncomingVeh->getID() << " gap=" << oncoming.second
<< " egoSpeedFraction=" << egoSpeedFraction << " newDist=" << oppositeLength << "\n";
}
#endif
} else {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " opposite leader=" << oncomingVeh->getID() << " gap=" << oncoming.second << " is driving against the flow\n";
}
#endif
}
if (neighLead.first != nullptr) {
if (overtaken.first == nullptr) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " ego=" << vehicle->getID() << " did not find columnleader to overtake\n";
}
#endif
} else if (oncomingVeh != nullptr && oncomingVeh->isStopped()
&& neighLead.second > 0
&& neighFollow.second > 0
&& yieldToOppositeWaiting(vehicle, oncomingVeh, 10, TIME2STEPS(60))) {
oppositeLength = forwardPos + neighLead.second;
} else {
if (surplusGap > 0) {
oppositeLength += 1000;
} else {
if (overtaken.second > 0) {
oppositeLength = MIN2(oppositeLength, forwardPos + overtaken.second);
}
oppositeLength = MAX2(oppositeLength, forwardPos + vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed()));
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " ego=" << vehicle->getID() << " is overtaking " << overtaken.first->getID()
<< " surplusGap=" << surplusGap
<< " final laneQLength=" << oppositeLength
<< "\n";
}
#endif
}
}
} else {
if (overtaken.first == nullptr || !canOvertake) {
std::pair<MSVehicle* const, double> oppFollow = opposite->getOppositeFollower(vehicle);
if (oppFollow.first == nullptr) {
oppositeLength = forwardPos;
} else {
const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
oppFollow.first, vehicle, oppFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel());
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " ego=" << vehicle->getID() << " neighFollow=" << oppFollow.first->getID() << " gap=" << oppFollow.second << " secureGap=" << secureGap << "\n";
}
#endif
if (oppFollow.second > secureGap) {
oppositeLength = forwardPos;
}
}
}
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << oppositeLength - forwardPos << " forwardPos=" << forwardPos << " oppositeLength=" << oppositeLength << "\n";
}
#endif
return oppositeLength;
}
std::pair<MSVehicle* const, double>
MSLaneChanger::getOncomingVehicle(const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
double searchDist, double& vMax, const MSVehicle* overtaken, MSLane::MinorLinkMode mLinkMode) {
double gap = oncoming.second;
while (oncoming.first != nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() + MAX2(0.0, oncoming.second));
gap += oncoming.first->getVehicleType().getLengthWithGap();
if (oncoming.first != overtaken) {
vMax = MIN2(vMax, oncoming.first->getSpeed());
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (gDebugFlag5) {
std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " isOpposite gap=" << oncoming.second
<< " totalGap=" << gap << " searchDist=" << searchDist << " vMax=" << vMax << "\n";
}
#endif
if (searchDist < 0) {
break;
}
if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
opposite = oncoming.first->getLane();
}
oncoming = opposite->getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
if (oncoming.first != nullptr) {
gap += oncoming.second + oncoming.first->getVehicleType().getLength();
#ifdef DEBUG_CHANGE_OPPOSITE
if (gDebugFlag5) {
std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " gap=" << oncoming.second << " totalGap=" << gap << "\n";
}
#endif
}
}
oncoming.second = gap;
return oncoming;
}
std::pair<MSVehicle* const, double>
MSLaneChanger::getOncomingOppositeVehicle(const MSVehicle* vehicle, std::pair<MSVehicle*, double> overtaken, double searchDist) {
double gap = 0;
const MSVehicle* front = nullptr;
if (overtaken.first != nullptr) {
gap += overtaken.second + overtaken.first->getVehicleType().getLengthWithGap();
front = overtaken.first;
} else {
front = vehicle;
}
const bool checkTmpVehicles = front->getLane() == vehicle->getLane();
std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
while (conts.size() > 0 && conts.front() != front->getLane()) {
conts.erase(conts.begin());
}
std::pair<MSVehicle* const, double> oncoming = front->getLane()->getLeader(front, front->getPositionOnLane(), conts, searchDist, checkTmpVehicles);
if (oncoming.first != nullptr) {
const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
#ifdef DEBUG_CHANGE_OPPOSITE
if (gDebugFlag5) {
std::cout << SIMTIME
<< " front=" << front->getID() << " searchDist=" << searchDist
<< " oncomingOpposite=" << oncoming.first->getID()
<< " gap=" << oncoming.second
<< " isOpposite=" << isOpposite
<< " shadowLane=" << Named::getIDSecure(shadowLane)
<< "\n";
}
#endif
if (isOpposite && shadowLane != front->getLane()) {
oncoming.second -= oncoming.first->getVehicleType().getLength();
oncoming.second += gap;
return oncoming;
}
}
return std::make_pair(nullptr, -1);
}
double
MSLaneChanger::computeSurplusGap(const MSVehicle* vehicle, const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
double timeToOvertake, double spaceToOvertake, double& oncomingSpeed, bool oncomingOpposite) {
double surplusGap = std::numeric_limits<double>::max();
const MSVehicle* oncomingVeh = oncoming.first;
if (oncomingVeh != 0 && (oncomingOpposite
|| (!oncomingVeh->getLaneChangeModel().isOpposite()
&& oncomingVeh->getLaneChangeModel().getShadowLane() != opposite))) {
oncomingSpeed = (oncomingVeh->isStopped() || oncomingVeh->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT
? 0 : oncomingVeh->getLane()->getVehicleMaxSpeed(oncomingVeh));
const double safetyGap = ((oncomingSpeed + vehicle->getLane()->getVehicleMaxSpeed(vehicle))
* vehicle->getCarFollowModel().getHeadwayTime()
* OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR);
surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME
<< " oncoming=" << oncomingVeh->getID()
<< " oGap=" << oncoming.second
<< " oSpeed=" << oncomingSpeed
<< " sto=" << spaceToOvertake
<< " tto=" << timeToOvertake
<< " safetyGap=" << safetyGap
<< " surplusGap=" << surplusGap
<< "\n";
}
#endif
}
return surplusGap;
}
bool
MSLaneChanger::foundHilltop(MSVehicle* vehicle, bool foundHill, double searchDist, const std::vector<MSLane*>& bestLanes, int view, double pos, double lastMax, double hilltopThreshold) {
if (view >= (int)bestLanes.size()) {
return false;
}
MSLane* lane = bestLanes[view];
double laneDist = 0;
const PositionVector& shape = lane->getShape();
double lastZ = lastMax;
for (int i = 1; i < (int)shape.size(); i++) {
const double dist = lane->interpolateGeometryPosToLanePos(shape[i - 1].distanceTo(shape[i]));
laneDist += dist;
if (laneDist > pos) {
const double z = shape[i].z();
if (z > lastMax) {
lastMax = z;
}
if (z > lastZ) {
foundHill = true;
}
lastZ = z;
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " foundHill=" << foundHill << " searchDist=" << searchDist << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
}
#endif
if (foundHill && z < lastMax) {
const double drop = lastMax - z;
if (drop > hilltopThreshold) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOpposite before the top of a hill searchDist=" << searchDist << " hillDrop=" << drop
<< " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
}
#endif
return true;
}
}
if (pos == 0) {
searchDist -= dist;
} else {
searchDist -= laneDist - pos;
pos = 0;
}
if (searchDist <= 0) {
return false;
}
}
}
return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
}
bool
MSLaneChanger::checkChangeOpposite(
MSVehicle* vehicle,
int laneOffset,
MSLane* targetLane,
const std::pair<MSVehicle* const, double>& leader,
const std::pair<MSVehicle* const, double>& neighLead,
const std::pair<MSVehicle* const, double>& neighFollow,
const std::vector<MSVehicle::LaneQ>& preb) {
const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
MSLane* source = vehicle->getMutableLane();
const std::pair<MSVehicle* const, double> follower(nullptr, -1);
int state = checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
vehicle->getLaneChangeModel().setOwnState(state);
bool changingAllowed = (state & LCA_BLOCKED) == 0;
if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed
&& (isOpposite || (state & LCA_COOPERATIVE) == 0)) {
const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(source, targetLane, laneOffset);
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset << " opposite=" << Named::getIDSecure(targetLane)
<< " state=" << toString((LaneChangeAction)state) << "\n";
}
#endif
if (continuous) {
continueChange(vehicle, myCandi);
}
return true;
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset
<< " opposite=" << Named::getIDSecure(targetLane) << " state=" << toString((LaneChangeAction)state) << "\n";
}
#endif
return false;
}
void
MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, double vMax, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake) {
const double v = vehicle->getSpeed();
const double u = leader->getAcceleration() > 0 ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
const double a = vehicle->getCarFollowModel().getMaxAccel();
const double d = vehicle->getCarFollowModel().getMaxDecel();
const double g = MAX2(0.0, (
gap + vehicle->getVehicleType().getMinGap()
+ leader->getVehicleType().getLengthWithGap()
+ vehicle->getVehicleType().getLength()
+ leader->getCarFollowModel().getSecureGap(leader, vehicle, u, vMax, d))
+ (MSGlobals::gSublane ? vMax * vehicle->getLane()->getWidth() / vehicle->getVehicleType().getMaxSpeedLat() : 0));
const double sign = -1;
double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
if (DEBUG_COND) {
std::cout << " computeOvertakingTime v=" << v << " vMax=" << vMax << " u=" << u << " a=" << a << " d=" << d << " gap=" << gap << " g=" << g << " t=" << t
<< " distEgo=" << v* t + t* t* a * 0.5 << " distLead=" << g + u* t
<< "\n";
}
#endif
assert(t >= 0);
if (vMax <= u) {
timeToOvertake = std::numeric_limits<double>::max();
spaceToOvertake = std::numeric_limits<double>::max();
return;
}
t += OPPOSITE_OVERTAKING_SAFE_TIMEGAP;
if (u > 0) {
t = ceil(t / TS) * TS;
}
const double timeToMaxSpeed = (vMax - v) / a;
#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
if (DEBUG_COND) {
std::cout << " t=" << t << " tvMax=" << timeToMaxSpeed << "\n";
}
#endif
if (t <= timeToMaxSpeed) {
timeToOvertake = t;
spaceToOvertake = v * t + t * t * a * 0.5;
#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
if (DEBUG_COND) {
std::cout << " sto=" << spaceToOvertake << "\n";
}
#endif
} else {
const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
const double m = timeToMaxSpeed;
t = (g - s + m * vMax) / (vMax - u);
if (t < 0) {
#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
if (DEBUG_COND) {
std::cout << " t2=" << t << "\n";
}
#endif
timeToOvertake = std::numeric_limits<double>::max();
spaceToOvertake = std::numeric_limits<double>::max();
return;
} else {
t += OPPOSITE_OVERTAKING_SAFE_TIMEGAP;
if (u > 0) {
t = ceil(t / TS) * TS;
}
timeToOvertake = t;
spaceToOvertake = s + (t - m) * vMax;
#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
if (DEBUG_COND) {
std::cout << " t2=" << t << " s=" << s << " sto=" << spaceToOvertake << " m=" << m << "\n";
}
#endif
}
}
const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
timeToOvertake *= safetyFactor;
if (STEPS2TIME(leader->getStopDuration()) < timeToOvertake) {
spaceToOvertake *= safetyFactor;
}
double frac = fmod(timeToOvertake, TS);
if (frac > 0) {
timeToOvertake += TS - frac;
}
#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
if (DEBUG_COND) {
if (safetyFactor != 1) {
std::cout << " applying safetyFactor=" << safetyFactor
<< " leaderStopTime=" << STEPS2TIME(leader->getStopDuration())
<< " tto=" << timeToOvertake << " sto=" << spaceToOvertake << "\n";
}
}
#endif
}
std::pair<MSVehicle*, double>
MSLaneChanger::getColumnleader(double& maxSpace, MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, double maxLookAhead) {
assert(leader.first != 0);
const bool isEmergency = vehicle->getVClass() == SVC_EMERGENCY;
const MSLane* source = vehicle->getLane();
const double overtakingSpeed = source->getVehicleMaxSpeed(vehicle);
const double mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
std::pair<MSVehicle*, double> columnLeader = leader;
double egoGap = leader.second;
bool foundSpaceAhead = false;
double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
if (maxLookAhead == std::numeric_limits<double>::max()) {
maxLookAhead = (isEmergency
? OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY
: OPPOSITE_OVERTAKING_MAX_LOOKAHEAD);
maxLookAhead = MAX2(maxLookAhead, mergeBrakeGap + 10
+ vehicle->getVehicleType().getLengthWithGap()
+ leader.first->getVehicleType().getLengthWithGap());
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " getColumnleader vehicle=" << vehicle->getID() << " leader=" << leader.first->getID() << " gap=" << leader.second << " maxLookAhead=" << maxLookAhead << "\n";
}
#endif
const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
while (!foundSpaceAhead) {
const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
columnLeader.first, vehicle,
columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
+ columnLeader.first->getVehicleType().getMinGap()
+ vehicle->getVehicleType().getLengthWithGap());
const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge());
double searchStart = columnLeader.first->getPositionOnLane();
std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
checkTmpVehicles);
std::set<MSVehicle*> seenLeaders;
while (leadLead.first != nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " skipping opposite leadLead=" << leadLead.first->getID() << " gap=" << leadLead.second << "\n";
}
#endif
if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
leadLead.first = nullptr;
break;
}
seenLeaders.insert(leadLead.first);
const double searchStart2 = searchStart + MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
leadLead = columnLeader.first->getLane()->getLeader(
columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
checkTmpVehicles);
leadLead.second += (searchStart2 - searchStart);
}
if (leadLead.first == nullptr) {
double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
if (!columnLeader.first->isStopped()) {
requiredSpace += safetyFactor * mergeBrakeGap;
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " no direct leader found after columnLeader " << columnLeader.first->getID()
<< " availableSpace=" << availableSpace
<< " reqAfterLeader=" << requiredSpaceAfterLeader
<< " ovSpeed=" << overtakingSpeed
<< " reqBGap=" << mergeBrakeGap
<< " reqMin=" << requiredSpace / safetyFactor
<< " req=" << requiredSpace
<< "\n";
}
#endif
if (availableSpace > requiredSpace) {
foundSpaceAhead = true;
} else {
bool contsEnd = false;
const MSLane* next = getLaneAfter(columnLeader.first->getLane(), conts, isEmergency, contsEnd);
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " look for another leader on lane " << Named::getIDSecure(next) << "\n";
}
#endif
while (next != nullptr && seen < maxLookAhead) {
seen += next->getLength();
MSVehicle* cand = next->getLastAnyVehicle();
if (cand == nullptr) {
availableSpace += next->getLength();
if (availableSpace > requiredSpace) {
foundSpaceAhead = true;
break;
}
next = getLaneAfter(next, conts, isEmergency, contsEnd);
} else {
availableSpace += cand->getBackPositionOnLane();
if (availableSpace > requiredSpace) {
foundSpaceAhead = true;
break;
} else {
return getColumnleader(maxSpace, vehicle, std::make_pair(cand, availableSpace + cand->getPositionOnLane()), maxLookAhead - seen);
}
}
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " foundSpaceAhead=" << foundSpaceAhead << " availableSpace=" << availableSpace << " next=" << Named::getIDSecure(next) << " contsEnd=" << contsEnd << " conts=" << toString(conts) << "\n";
}
#endif
if (!foundSpaceAhead && contsEnd) {
foundSpaceAhead = true;
availableSpace = requiredSpace;
}
if (!foundSpaceAhead) {
return std::make_pair(nullptr, -1);
}
}
maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
} else {
const double sGap = vehicle->getCarFollowModel().getSecureGap(vehicle, leadLead.first,
overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
if (!columnLeader.first->isStopped()) {
requiredSpace += safetyFactor * sGap;
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " leader's leader " << leadLead.first->getID() << " space=" << leadLead.second
<< " reqAfterLeader=" << requiredSpaceAfterLeader
<< " ovSpeed=" << overtakingSpeed
<< " reqSGap=" << sGap
<< " reqMin=" << requiredSpace / safetyFactor
<< " req=" << requiredSpace
<< "\n";
}
#endif
if (leadLead.second > requiredSpace) {
foundSpaceAhead = true;
maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
} else {
if (leadLead.second < 0) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " leader's leader " << leadLead.first->getID() << " gap=" << leadLead.second << " is junction leader (aborting)\n";
}
#endif
return std::make_pair(nullptr, -1);
}
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n";
}
#endif
seen += MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
if (seen > maxLookAhead) {
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n";
}
#endif
return std::make_pair(nullptr, -1);
}
egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
columnLeader = leadLead;
#ifdef DEBUG_CHANGE_OPPOSITE
if (DEBUG_COND) {
std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
}
#endif
}
}
}
columnLeader.second = egoGap;
return columnLeader;
}
const MSLane*
MSLaneChanger::getLaneAfter(const MSLane* lane, const std::vector<MSLane*>& conts, bool allowMinor, bool& contsEnd) {
for (auto it = conts.begin(); it != conts.end(); ++it) {
if (*it == lane) {
if (it + 1 != conts.end()) {
const MSLane* next = *(it + 1);
const MSLink* link = lane->getLinkTo(next);
if (link == nullptr || (!allowMinor && !link->havePriority())) {
return nullptr;
}
return next;
} else {
contsEnd = true;
return nullptr;
}
}
}
return nullptr;
}
double
MSLaneChanger::getMaxOvertakingSpeed(const MSVehicle* vehicle, double maxSpaceToOvertake) {
const double a = vehicle->getCarFollowModel().getMaxAccel();
const double d = vehicle->getCarFollowModel().getMaxDecel();
const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
return v;
}
std::pair<double, SUMOTime>
MSLaneChanger::getLastBlocked(int index) const {
assert(index >= 0 && index < (int)myChanger.size());
return std::make_pair(
myChanger[index].lastBlockedBackPos,
myChanger[index].lastBlockedWaitingTime);
}