44#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0
45#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR 0.0
46#define OPPOSITE_OVERTAKING_SAFETY_FACTOR 1.2
48#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0
49#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0
51#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 1000.0
53#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE 1000.0
54#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD 5
57#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT 1
73#define DEBUG_COND (vehicle->isSelected())
86 firstBlocked(nullptr),
88 ahead(_lane->getWidth()),
89 aheadNext(_lane->getWidth(), nullptr, 0.),
91 lastBlockedBackPos(-1),
92 lastBlockedWaitingTime(-1) {
114 lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
129 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
131 myChanger.back().mayChangeRight = lane != lanes->begin();
132 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
133 if ((*lane)->isInternal()) {
135 if (
myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
138 if (
myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
142 if (
myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
146 if (
myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
163 const MSLane* lane = ce.lane;
165 if (link->getTLLogic() !=
nullptr || link->havePriority()) {
169 const MSLane* lane2 = ce2.lane;
174 if (&link->getLane()->getEdge() == &link2->getLane()->getEdge()
175 && link->getLane() != link2->getLane()
177 & link->getViaLaneOrLane()->getPermissions() & link2->getViaLaneOrLane()->getPermissions() & ~(
SVC_PEDESTRIAN |
SVC_BICYCLE)) != 0
178 && link->getFoeLinks() != link2->getFoeLinks()) {
198 const bool haveChanged =
change();
205 ce->lane->releaseVehicles();
217 ce->hoppedVeh =
nullptr;
218 ce->lastBlocked =
nullptr;
219 ce->firstBlocked =
nullptr;
220 ce->lastStopped =
nullptr;
222 ce->lastBlockedBackPos = -1;
223 ce->lastBlockedWaitingTime = -1;
224 ce->lane->getVehiclesSecure();
238 if (!vehHasChanged) {
261 ce->lane->swapAfterLaneChange(t);
262 ce->lane->releaseVehicles();
263 if (ce->lastBlocked !=
nullptr) {
264 ce->lastBlockedBackPos = ce->lastBlocked->getBackPositionOnLane();
265 ce->lastBlockedWaitingTime = ce->lastBlocked->getWaitingTime();
276#ifdef DEBUG_CANDIDATE
277 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
281 if (
veh(ce) ==
nullptr) {
284#ifdef DEBUG_CANDIDATE
285 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
289#ifdef DEBUG_CANDIDATE
295 assert(
veh(ce) != 0);
296 assert(
veh(max) != 0);
297 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
298#ifdef DEBUG_CANDIDATE
305 assert(
veh(max) != 0);
312 if (direction == 0) {
319 if (direction == -1) {
320 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingRight(svc);
321 }
else if (direction == 1) {
322 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingLeft(svc);
339#ifdef DEBUG_ACTIONSTEPS
354 myCandi->lastStopped = vehicle;
360#ifdef DEBUG_ACTIONSTEPS
362 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
365 bool changed =
false;
389 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
393 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
404 (
myCandi - 1)->lastBlocked = vehicle;
405 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
406 (
myCandi - 1)->firstBlocked = vehicle;
421 (
myCandi + 1)->lastBlocked = vehicle;
422 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
423 (
myCandi + 1)->firstBlocked = vehicle;
468 <<
" veh=" << vehicle->
getID()
471 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
482 bool changed =
false;
484 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
485 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
493 to->registerHop(vehicle);
515 to->registerHop(vehicle);
516 to->lane->requireCollisionCheck();
537 to->registerHop(vehicle);
541 from->registerHop(vehicle);
542 from->lane->requireCollisionCheck();
559#ifdef DEBUG_CONTINUE_CHANGE
562 <<
" continueChange veh=" << vehicle->
getID()
564 <<
" dir=" << direction
565 <<
" speedLat=" << speedLat
566 <<
" pastMidpoint=" << pastMidpoint
578std::pair<MSVehicle* const, double>
582#ifdef DEBUG_SURROUNDING_VEHICLES
584 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
590#ifdef DEBUG_SURROUNDING_VEHICLES
592 if (neighLead != 0) {
593 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
599 if (target->hoppedVeh !=
nullptr) {
600 double hoppedPos = target->hoppedVeh->getPositionOnLane();
601#ifdef DEBUG_SURROUNDING_VEHICLES
603 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
607 neighLead = target->hoppedVeh;
612 const bool checkBidi = target->lane->getBidiLane() !=
nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
613 if (neighLead ==
nullptr || checkBidi) {
614#ifdef DEBUG_SURROUNDING_VEHICLES
616 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
621 MSLane* targetLane = target->lane;
623 double leaderBack = targetLane->
getLength();
624 if (neighLead !=
nullptr) {
628 double plBack = pl->getBackPositionOnLane(targetLane);
629 if (pl->isBidiOn(targetLane)) {
630 plBack -= pl->getVehicleType().getLengthWithGap();
632 const double plPos = plBack + pl->getVehicleType().getLength();
633#ifdef DEBUG_SURROUNDING_VEHICLES
635 std::cout <<
" partial=" << pl->getID() <<
" plBack=" << plBack <<
" plPos=" << plPos <<
" leaderBack=" << leaderBack <<
" egoBack=" << egoBack <<
"\n";
638 if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
643 if (neighLead !=
nullptr) {
644#ifdef DEBUG_SURROUNDING_VEHICLES
646 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
650 return std::pair<MSVehicle*, double>(neighLead, gap);
655 if (target->lane->getBidiLane() !=
nullptr) {
656 dist += target->lane->getBidiLane()->getMaximumBrakeDist();
659 if (seen > dist && !
myCandi->lane->isInternal()) {
660#ifdef DEBUG_SURROUNDING_VEHICLES
662 std::cout <<
" found no leader within dist=" << dist <<
"\n";
665 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
669 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
670#ifdef DEBUG_SURROUNDING_VEHICLES
677#ifdef DEBUG_SURROUNDING_VEHICLES
679 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
687std::pair<MSVehicle* const, double>
691#ifdef DEBUG_SURROUNDING_VEHICLES
693 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
699 neighFollow =
veh(target);
702 if (target->lane->myVehicles.size() > 1) {
703 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
707#ifdef DEBUG_SURROUNDING_VEHICLES
709 if (neighFollow != 0) {
710 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
712 std::cout <<
"veh(target) returns none." << std::endl;
718#ifdef DEBUG_SURROUNDING_VEHICLES
720 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
721 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
730#ifdef DEBUG_SURROUNDING_VEHICLES
733 if (partialBehind != 0 && partialBehind != neighFollow) {
734 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
739 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
741 if (neighFollow ==
nullptr) {
743#ifdef DEBUG_SURROUNDING_VEHICLES
745 if (consecutiveFollower.first == 0) {
746 std::cout <<
"no follower found." << std::endl;
748 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
752 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
754#ifdef DEBUG_SURROUNDING_VEHICLES
756 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
759 return std::pair<MSVehicle* const, double>(neighFollow,
783 const std::pair<MSVehicle* const, double>& leader,
784 const std::vector<MSVehicle::LaneQ>& preb)
const {
789 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
792 neighFollow.first = 0;
795 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
802 const std::pair<MSVehicle* const, double>& leader,
803 const std::pair<MSVehicle* const, double>& follower,
804 const std::pair<MSVehicle* const, double>& neighLead,
805 const std::pair<MSVehicle* const, double>& neighFollow,
806 const std::vector<MSVehicle::LaneQ>& preb)
const {
810#ifdef DEBUG_CHECK_CHANGE
813 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
822 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
826#ifdef DEBUG_CHECK_CHANGE
829 <<
" overlapping with follower..."
835 if (neighLead.first !=
nullptr && neighLead.second < 0) {
838#ifdef DEBUG_CHECK_CHANGE
841 <<
" overlapping with leader..."
853 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
861 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
864 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
866#ifdef DEBUG_CHECK_CHANGE
869 <<
" follower=" << neighFollow.first->getID()
870 <<
" backGap=" << neighFollow.second
871 <<
" vNextFollower=" << vNextFollower
872 <<
" vNextEgo=" << vNextLeader
873 <<
" secureGap=" << secureBackGap
881 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
886#ifdef DEBUG_CHECK_CHANGE
888 std::cout <<
" ignoring opposite follower who changed in this step\n";
892 blocked |= blockedByFollower;
898 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
907 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
911#ifdef DEBUG_CHECK_CHANGE
914 <<
" leader=" << neighLead.first->getID()
915 <<
" frontGap=" << neighLead.second
916 <<
" vNextEgo=" << vNextFollower
917 <<
" vNextLeader=" << vNextLeader
918 <<
" secureGap=" << secureFrontGap
925 blocked |= blockedByLeader;
932 if (nextLeader.first != 0) {
936#ifdef DEBUG_CHECK_CHANGE
938 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
941 if (brakeGap > gap) {
942 blocked |= blockedByLeader;
943#ifdef DEBUG_CHECK_CHANGE
945 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
952 if (leader.first !=
nullptr) {
953 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
958 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
967 const double speed = vehicle->
getSpeed();
969 if (seen < dist || myCandi->lane->isInternal()) {
970 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
971 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
973 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
975#ifdef DEBUG_SURROUNDING_VEHICLES
977 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
978 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
981 if (neighLead2.second < secureGap2) {
982 state |= blockedByLeader;
989 double targetZipperDist = 0;
990 if (laneOffset == 0) {
991 targetZipperDist =
myCandi->zipperDist;
992 }
else if (laneOffset == 1) {
994 targetZipperDist = (
myCandi + 1)->zipperDist;
996 }
else if (laneOffset == -1) {
998 targetZipperDist = (
myCandi - 1)->zipperDist;
1002 state |= blockedByLeader;
1014 if (estimatedLCDuration == -1) {
1016#ifdef DEBUG_CHECK_CHANGE
1018 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
1019 <<
"\nestimatedLCDuration=" << estimatedLCDuration
1020 <<
"\ndistToNeighLane=" << distToNeighLane
1028 const double avgSpeed = 0.5 * (
1032 const double space2change = avgSpeed * estimatedLCDuration;
1035#ifdef DEBUG_CHECK_CHANGE
1037 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
1038 <<
"\ndistToNeighLane=" << distToNeighLane
1039 <<
" estimatedLCDuration=" << estimatedLCDuration
1040 <<
" space2change=" << space2change
1041 <<
" avgSpeed=" << avgSpeed
1050 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1051 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
1055 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
1060 if ((*link)->getViaLane() ==
nullptr) {
1063 nextLane = (*link)->getViaLaneOrLane();
1068#ifdef DEBUG_CHECK_CHANGE
1070 std::cout <<
" available distance=" << seen << std::endl;
1073 if (nextLane->
isLinkEnd(link) && seen < space2change) {
1074#ifdef DEBUG_CHECK_CHANGE
1076 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1085 const double speed = vehicle->
getSpeed();
1087 nextLane = vehicle->
getLane();
1090 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1091 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1092 nextLane = (*nextLink)->getViaLaneOrLane();
1094 if (parallelLane ==
nullptr) {
1098 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1099 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1101 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1102 state |= blockedByLeader;
1106 if ((*nextLink)->getViaLane() ==
nullptr) {
1123 if (link2 !=
nullptr) {
1125 if (api !=
nullptr) {
1126 if (!link2->
opened(api->arrivalTime, api->arrivalSpeed, api->leaveSpeed, vehicle->
getLength(),
1128 nullptr,
false, vehicle, api->dist)) {
1137 const int oldstate = state;
1141#ifdef DEBUG_CHECK_CHANGE
1144 <<
" veh=" << vehicle->
getID()
1164 if (laneOffset != 0) {
1186 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1187 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1190 const int bestOffset = preb[laneIndex].bestLaneOffset;
1201 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1205 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1213 double oncomingSpeed;
1214 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1215 if (!isOpposite && surplusGap < 0) {
1216#ifdef DEBUG_CHANGE_OPPOSITE
1218 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1219 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1225 if (bestOffset > 0) {
1226 MSLane*
const target = preb[laneIndex + 1].lane;
1238std::vector<MSVehicle::LaneQ>
1245 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1246 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1247 for (
int i = 0; i < numOpposite; i++) {
1248 preb.push_back(preb.back());
1249 preb.back().lane = oLanes[numOpposite - 1 - i];
1250 preb.back().length = oppositeLength;
1252 preb.back().bestLaneOffset = -1 - i;
1256 if (stopLane !=
nullptr) {
1257 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1258 for (
int i = 0; i < (int)preb.size(); i++) {
1259 preb[i].bestLaneOffset = stopIndex - i;
1264#ifdef DEBUG_CHANGE_OPPOSITE
1266 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1267 for (
int i = 0; i < (int)preb.size(); i++) {
1268 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1286#ifdef DEBUG_CHANGE_OPPOSITE
1289 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1294 if (opposite ==
nullptr) {
1304 bool oppositeChangeByTraci =
false;
1307 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1311 oppositeChangeByTraci =
true;
1315#ifdef DEBUG_CHANGE_OPPOSITE
1317 std::cout <<
" not overtaking due to changeLeft restriction\n";
1328 const MSLane* oncomingLane = isOpposite ? source : opposite;
1331 int direction = isOpposite ? -1 : 1;
1332 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1335 double surplusGap = std::numeric_limits<double>::max();
1344 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1346 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1348 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1360 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1366 if (!isOpposite && !oppositeChangeByTraci
1368 && leader.first !=
nullptr) {
1373#ifdef DEBUG_CHANGE_OPPOSITE
1375 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1381 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1384 }
else if (leader.second < 0) {
1386#ifdef DEBUG_CHANGE_OPPOSITE
1388 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1396 double timeToOvertake = std::numeric_limits<double>::max();
1397 double spaceToOvertake = std::numeric_limits<double>::max();
1398 double maxSpaceToOvertake = 0;
1400 if (oppositeChangeByTraci) {
1410 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1411 overtaken = neighLead;
1413 if (overtaken.first !=
nullptr) {
1416#ifdef DEBUG_CHANGE_OPPOSITE
1418 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1419 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1420 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1427 if (overtaken.first == 0) {
1430#ifdef DEBUG_CHANGE_OPPOSITE
1432 std::cout <<
" no leader found\n";
1437 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1442#ifdef DEBUG_CHANGE_OPPOSITE
1444 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1452 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1453#ifdef DEBUG_CHANGE_OPPOSITE
1456 <<
" veh=" << vehicle->
getID()
1457 <<
" changeOpposite opposite=" << opposite->
getID()
1459 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1461 <<
" timeToOvertake=" << timeToOvertake
1462 <<
" spaceToOvertake=" << spaceToOvertake
1468#ifdef DEBUG_CHANGE_OPPOSITE
1470 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1478 if (!wait && lastStopped !=
nullptr) {
1480#ifdef DEBUG_CHANGE_OPPOSITE
1482 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1485 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1494 assert(timeToOvertake != std::numeric_limits<double>::max());
1495 assert(spaceToOvertake != std::numeric_limits<double>::max());
1498 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1505 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1508 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1511 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1512 if (oncomingGap > 0) {
1515#ifdef DEBUG_CHANGE_OPPOSITE
1517 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1518 <<
" halting=" << oncoming.first->getWaitingSeconds()
1519 <<
" oncomingGap=" << oncomingGap
1521 <<
" vMax=" << vMax <<
"\n";
1528 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1529#ifdef DEBUG_CHANGE_OPPOSITE
1531 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1532 <<
" timeToOvertake=" << timeToOvertake
1533 <<
" spaceToOvertake=" << spaceToOvertake
1540#ifdef DEBUG_CHANGE_OPPOSITE
1542 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1550#ifdef DEBUG_CHANGE_OPPOSITE
1552 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1557 assert(timeToOvertake != std::numeric_limits<double>::max());
1558 assert(spaceToOvertake != std::numeric_limits<double>::max());
1562 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1563 if (oncomingOpposite.first !=
nullptr) {
1564 double oncomingSpeed2;
1565 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1567 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1568#ifdef DEBUG_CHANGE_OPPOSITE
1570 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1573 surplusGap =
MIN2(surplusGap, surplusGap2);
1574 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1575 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1576 && oncomingOpposite.second > oncoming.second) {
1580 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1583 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1584 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1585 double ooTTO = ooSTO / oSpeed;
1587 ooTTO = ceil(ooTTO /
TS) *
TS;
1588 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1589#ifdef DEBUG_CHANGE_OPPOSITE
1591 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1594 surplusGap =
MIN2(surplusGap, surplusGap3);
1597 if (!isOpposite && surplusGap < 0) {
1598#ifdef DEBUG_CHANGE_OPPOSITE
1600 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1604#ifdef DEBUG_CHANGE_OPPOSITE
1606 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1607 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1619 if (usableDist < spaceToOvertake) {
1622 assert(bestLaneConts.size() >= 1);
1623 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1624 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1625#ifdef DEBUG_CHANGE_OPPOSITE
1627 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1636 const MSLane*
const prev = *(it - 1);
1637 if (prev !=
nullptr) {
1646#ifdef DEBUG_CHANGE_OPPOSITE
1648 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1654 usableDist += (*it)->getLength();
1658 if (!isOpposite && usableDist < spaceToOvertake) {
1659#ifdef DEBUG_CHANGE_OPPOSITE
1661 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1670 bool foundHill = vehicle->
getSlope() > 0;
1675#ifdef DEBUG_CHANGE_OPPOSITE
1677 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1682 double oppositeLength = vehicle->
getBestLanes().back().length;
1685 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1686 leader.first =
nullptr;
1687 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1689 neighLead.first =
nullptr;
1693#ifdef DEBUG_CHANGE_OPPOSITE
1695 std::cout <<
" not changing to avoid deadlock\n";
1700 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1706 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1714 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1720 std::pair<MSVehicle*, double> neighLead,
1721 std::pair<MSVehicle*, double> overtaken,
1722 std::pair<MSVehicle*, double> leader) {
1724#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1726 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1733 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1735 }
else if (!neighLead.first->isStopped()
1739 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1740 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1741 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1742#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1744 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1747 if (neighLead.first ==
nullptr) {
1754 if (neighLead.first->isStopped()
1755 && (overtaken.first->isStopped()
1756 || leader.first->getLaneChangeModel().isOpposite()
1761 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1762 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1764 const double distToStop = neighLead.second - requiredGap;
1768 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1769 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1770 if (neighStoppedBack + nextGap > overtaken.second) {
1773 neighStoppedBack += nextGap;
1774 auto neighLeadFollow = neighLead.first->getFollower();
1775 neighLead.second = neighLeadFollow.second;
1776 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1777#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1782 if (neighStoppedBack > overtaken.second) {
1787 const double leaderBGap = leader.first->
getBrakeGap();
1788 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1789 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1791#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1793 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1794 <<
" neighLeadGap=" << neighLead.second
1795 <<
" leaderGap=" << leader.second
1796 <<
" bGap=" << leaderBGap
1797 <<
" fGap=" << leaderFGap
1798 <<
" eGap=" << extraGap
1799 <<
" neighStoppedBack=" << neighStoppedBack
1801 <<
" requiredGap=" << requiredGap
1802 <<
" gapWithEgo=" << gapWithEgo
1803 <<
" yield=" << yield
1808 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1809 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1810 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1812#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1814 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1817 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1820#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1822 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1823 <<
" blockerLength=" << blockerLength
1824 <<
" reserved=" << reserved
1842 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1844 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1845 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1846 follower = follower.first->getFollower(dist);
1848 if (follower.first !=
nullptr) {
1849 followerGap += follower.second;
1851#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1853 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1854 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1858 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1866 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1867 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1868 follower = follower.first->getFollower(dist);
1870#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1871 if (
DEBUG_COND && follower.first !=
nullptr) {
1872 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1873 <<
" oncoming=" << follower.first->getID()
1874 <<
" wait=" << follower.first->getWaitingSeconds()
1880 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1889 std::pair<MSVehicle* const, double> leader,
1890 std::pair<MSVehicle*, double> neighLead,
1891 std::pair<MSVehicle*, double> overtaken) {
1892 const double deadLockZone = overtaken.second;
1893#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1897 <<
" gap=" << leader.second
1906 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1907#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1909 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1910 <<
" leader=" << leader.first->getID()
1911 <<
" leaderGap=" << leader.second
1913 <<
" deadLockZone=" << deadLockZone
1917 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1920 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1921 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1922 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1923#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1925 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1930 if (oncomingOpposite.first !=
nullptr ||
1931 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1933 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1934 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1936 const double blockerLength = currentDist - vehicle->
getPositionOnLane() - POSITION_EPS - NUMERICAL_EPS;
1938#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1940 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1941 <<
" leader=" << leader.first->getID()
1942 <<
" leaderGap=" << leader.second
1944 <<
" currentDist=" << currentDist
1945 <<
" blockerLength=" << blockerLength
1946 <<
" reserved=" << reserved
1961 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1962 std::pair<MSVehicle*, double> neighLead,
1963 std::pair<MSVehicle*, double> overtaken,
1964 std::pair<MSVehicle*, double> neighFollow,
1965 double surplusGap,
const MSLane* opposite,
1975 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1977 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1978#ifdef DEBUG_CHANGE_OPPOSITE
1980 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1984 const MSVehicle* oncomingVeh = oncoming.first;
1985 if (oncomingVeh != 0) {
1987 double egoSpeedFraction = 0.5;
1988 if (oncomingSpeed > 0) {
1989 egoSpeedFraction =
MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1991 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1992#ifdef DEBUG_CHANGE_OPPOSITE
1994 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1995 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1999#ifdef DEBUG_CHANGE_OPPOSITE
2001 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
2005 if (neighLead.first !=
nullptr) {
2006 if (overtaken.first ==
nullptr) {
2007#ifdef DEBUG_CHANGE_OPPOSITE
2009 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
2012 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
2013 && neighLead.second > 0
2014 && neighFollow.second > 0
2017 oppositeLength = forwardPos + neighLead.second;
2019 if (surplusGap > 0) {
2022 oppositeLength += 1000;
2025 if (overtaken.second > 0) {
2026 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
2031#ifdef DEBUG_CHANGE_OPPOSITE
2033 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
2034 <<
" surplusGap=" << surplusGap
2035 <<
" final laneQLength=" << oppositeLength
2042 if (overtaken.first ==
nullptr || !canOvertake) {
2045 if (oppFollow.first ==
nullptr) {
2046 oppositeLength = forwardPos;
2048 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
2050#ifdef DEBUG_CHANGE_OPPOSITE
2052 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
2055 if (oppFollow.second > secureGap) {
2057 oppositeLength = forwardPos;
2062#ifdef DEBUG_CHANGE_OPPOSITE
2064 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
2067 return oppositeLength;
2071std::pair<MSVehicle* const, double>
2074 double gap = oncoming.second;
2075 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
2076 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
2078 gap += oncoming.first->getVehicleType().getLengthWithGap();
2079 if (oncoming.first != overtaken) {
2080 vMax =
MIN2(vMax, oncoming.first->getSpeed());
2082#ifdef DEBUG_CHANGE_OPPOSITE
2084 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
2085 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
2088 if (searchDist < 0) {
2092 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2093 opposite = oncoming.first->getLane();
2095 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2096 if (oncoming.first !=
nullptr) {
2097 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2098#ifdef DEBUG_CHANGE_OPPOSITE
2100 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
2105 oncoming.second = gap;
2110std::pair<MSVehicle* const, double>
2114 if (overtaken.first !=
nullptr) {
2116 front = overtaken.first;
2124 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2126 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2127 conts.erase(conts.begin());
2130 if (oncoming.first !=
nullptr) {
2131 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2132 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2133#ifdef DEBUG_CHANGE_OPPOSITE
2136 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2137 <<
" oncomingOpposite=" << oncoming.first->getID()
2138 <<
" gap=" << oncoming.second
2139 <<
" isOpposite=" << isOpposite
2144 if (isOpposite && shadowLane != front->
getLane()) {
2146 oncoming.second -= oncoming.first->getVehicleType().getLength();
2147 oncoming.second += gap;
2151 return std::make_pair(
nullptr, -1);
2157 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2158 double surplusGap = std::numeric_limits<double>::max();
2159 const MSVehicle* oncomingVeh = oncoming.first;
2160 if (oncomingVeh != 0 && (oncomingOpposite
2171 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2172#ifdef DEBUG_CHANGE_OPPOSITE
2175 <<
" oncoming=" << oncomingVeh->
getID()
2176 <<
" oGap=" << oncoming.second
2177 <<
" oSpeed=" << oncomingSpeed
2178 <<
" sto=" << spaceToOvertake
2179 <<
" tto=" << timeToOvertake
2180 <<
" safetyGap=" << safetyGap
2181 <<
" surplusGap=" << surplusGap
2191 if (view >= (
int)bestLanes.size()) {
2194 MSLane* lane = bestLanes[view];
2195 double laneDist = 0;
2197 double lastZ = lastMax;
2198 for (
int i = 1; i < (int)shape.size(); i++) {
2201 if (laneDist > pos) {
2202 const double z = shape[i].z();
2210#ifdef DEBUG_CHANGE_OPPOSITE
2212 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2215 if (foundHill && z < lastMax) {
2216 const double drop = lastMax - z;
2218 if (drop > hilltopThreshold) {
2219#ifdef DEBUG_CHANGE_OPPOSITE
2221 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2222 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2231 searchDist -= laneDist - pos;
2234 if (searchDist <= 0) {
2239 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2248 const std::pair<MSVehicle* const, double>& leader,
2249 const std::pair<MSVehicle* const, double>& neighLead,
2250 const std::pair<MSVehicle* const, double>& neighFollow,
2251 const std::vector<MSVehicle::LaneQ>& preb) {
2254 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2255 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2257 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2263#ifdef DEBUG_CHANGE_OPPOSITE
2265 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2274#ifdef DEBUG_CHANGE_OPPOSITE
2276 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2293 const double v = vehicle->
getSpeed();
2297 const double g =
MAX2(0.0, (
2308 const double sign = -1;
2312 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2313#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2315 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2316 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2323 timeToOvertake = std::numeric_limits<double>::max();
2324 spaceToOvertake = std::numeric_limits<double>::max();
2332 t = ceil(t /
TS) *
TS;
2336 const double timeToMaxSpeed = (vMax - v) / a;
2338#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2340 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2343 if (t <= timeToMaxSpeed) {
2345 spaceToOvertake = v * t + t * t * a * 0.5;
2346#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2348 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2353 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2354 const double m = timeToMaxSpeed;
2357 t = (g - s + m * vMax) / (vMax - u);
2360#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2362 std::cout <<
" t2=" << t <<
"\n";
2365 timeToOvertake = std::numeric_limits<double>::max();
2366 spaceToOvertake = std::numeric_limits<double>::max();
2373 t = ceil(t /
TS) *
TS;
2376 spaceToOvertake = s + (t - m) * vMax;
2377#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2379 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2385 timeToOvertake *= safetyFactor;
2387 spaceToOvertake *= safetyFactor;
2389 double frac = fmod(timeToOvertake,
TS);
2392 timeToOvertake +=
TS - frac;
2394#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2396 if (safetyFactor != 1) {
2397 std::cout <<
" applying safetyFactor=" << safetyFactor
2399 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2407std::pair<MSVehicle*, double>
2409 assert(leader.first != 0);
2415 std::pair<MSVehicle*, double> columnLeader = leader;
2416 double egoGap = leader.second;
2417 bool foundSpaceAhead =
false;
2418 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2420 if (maxLookAhead == std::numeric_limits<double>::max()) {
2421 maxLookAhead = (isEmergency
2424 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2426 + leader.first->getVehicleType().getLengthWithGap());
2428#ifdef DEBUG_CHANGE_OPPOSITE
2430 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2434 while (!foundSpaceAhead) {
2435 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2436 columnLeader.first, vehicle,
2438 + columnLeader.first->getVehicleType().getMinGap()
2443 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2444 double searchStart = columnLeader.first->getPositionOnLane();
2445 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2446 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2448 std::set<MSVehicle*> seenLeaders;
2449 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2450#ifdef DEBUG_CHANGE_OPPOSITE
2452 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2455 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2456 leadLead.first =
nullptr;
2459 seenLeaders.insert(leadLead.first);
2461 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2462 leadLead = columnLeader.first->getLane()->getLeader(
2463 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2465 leadLead.second += (searchStart2 - searchStart);
2467 if (leadLead.first ==
nullptr) {
2468 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2469 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2470 if (!columnLeader.first->isStopped()) {
2472 requiredSpace += safetyFactor * mergeBrakeGap;
2474#ifdef DEBUG_CHANGE_OPPOSITE
2476 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2477 <<
" availableSpace=" << availableSpace
2478 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2479 <<
" ovSpeed=" << overtakingSpeed
2480 <<
" reqBGap=" << mergeBrakeGap
2481 <<
" reqMin=" << requiredSpace / safetyFactor
2482 <<
" req=" << requiredSpace
2486 if (availableSpace > requiredSpace) {
2487 foundSpaceAhead =
true;
2491 bool contsEnd =
false;
2492 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, isEmergency, contsEnd);
2493#ifdef DEBUG_CHANGE_OPPOSITE
2495 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2498 while (next !=
nullptr && seen < maxLookAhead) {
2501 if (cand ==
nullptr) {
2503 if (availableSpace > requiredSpace) {
2504 foundSpaceAhead =
true;
2507 next =
getLaneAfter(next, conts, isEmergency, contsEnd);
2510 if (availableSpace > requiredSpace) {
2511 foundSpaceAhead =
true;
2518#ifdef DEBUG_CHANGE_OPPOSITE
2520 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2523 if (!foundSpaceAhead && contsEnd) {
2524 foundSpaceAhead =
true;
2525 availableSpace = requiredSpace;
2527 if (!foundSpaceAhead) {
2528 return std::make_pair(
nullptr, -1);
2531 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2534 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2535 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2536 if (!columnLeader.first->isStopped()) {
2538 requiredSpace += safetyFactor * sGap;
2540#ifdef DEBUG_CHANGE_OPPOSITE
2542 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2543 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2544 <<
" ovSpeed=" << overtakingSpeed
2545 <<
" reqSGap=" << sGap
2546 <<
" reqMin=" << requiredSpace / safetyFactor
2547 <<
" req=" << requiredSpace
2551 if (leadLead.second > requiredSpace) {
2552 foundSpaceAhead =
true;
2553 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2556 if (leadLead.second < 0) {
2558#ifdef DEBUG_CHANGE_OPPOSITE
2560 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2563 return std::make_pair(
nullptr, -1);
2566#ifdef DEBUG_CHANGE_OPPOSITE
2568 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2571 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2572 if (seen > maxLookAhead) {
2573#ifdef DEBUG_CHANGE_OPPOSITE
2575 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2578 return std::make_pair(
nullptr, -1);
2581 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2582 columnLeader = leadLead;
2583#ifdef DEBUG_CHANGE_OPPOSITE
2585 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2591 columnLeader.second = egoGap;
2592 return columnLeader;
2598 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2600 if (it + 1 != conts.end()) {
2602 const MSLane* next = *(it + 1);
2604 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2622 const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
2627std::pair<double, SUMOTime>
2629 assert(index >= 0 && index < (
int)
myChanger.size());
2630 return std::make_pair(
2632 myChanger[index].lastBlockedWaitingTime);
#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY
#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETY_FACTOR
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP
#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE
std::pair< const MSVehicle *, double > CLeaderDist
std::pair< const MSPerson *, double > PersonDist
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_EMERGENCY
public emergency vehicles
@ SVC_PEDESTRIAN
pedestrian
@ RIGHT
The link is a (hard) right direction.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_BLOCKED_BY_RIGHT_LEADER
The vehicle is blocked by right leader.
@ LCA_INSUFFICIENT_SPACE
The vehicle does not have enough space to complete a continuous change before the next turn.
@ LCA_BLOCKED_BY_LEFT_FOLLOWER
The vehicle is blocked by left follower.
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_INSUFFICIENT_SPEED
Vehicle is too slow to complete a continuous lane change (in case that maxSpeedLatStanding==0)
@ LCA_OVERLAPPING
The vehicle is blocked being overlapping.
@ LCA_LEFT
Wants go to the left.
@ LCA_BLOCKED_BY_RIGHT_FOLLOWER
The vehicle is blocked by right follower.
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_LEFT_LEADER
const double SUMO_const_laneWidth
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class responsible for exchanging messages between cars involved in lane-change interaction.
Interface for lane-change models.
double getLaneChangeCompletion() const
Get the current lane change completion ratio.
double getForwardPos() const
get vehicle position relative to the forward direction lane
void setFollowerGaps(CLeaderDist follower, double secGap)
virtual void setOwnState(const int state)
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change.
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
static const double NO_NEIGHBOR
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
virtual bool saveBlockerLength(double, double)
reserve space at the end of the lane to avoid dead locks
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
virtual double getOppositeSafetyFactor() const
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
void setLeaderGaps(CLeaderDist, double secGap)
void setOrigLeaderGaps(CLeaderDist, double secGap)
int getNormalizedLaneIndex()
brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
virtual int checkChangeBeforeCommitting(const MSVehicle *veh, int state) const
Informs the vehicle that it is about to be moved on an adjacent lane. The method can be used to re-ev...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
void clearNeighbors()
Clear info on neighboring vehicle from previous step.
void saveNeighbors(const int dir, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &leaders)
Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direct...
double getImpatience() const
Returns this vehicles impatience.
double getLength() const
Returns the vehicle's length.
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
const MSStop & getNextStop() const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
A road/street connecting two junctions.
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
bool isInternal() const
return whether this edge is an internal edge
static double gLateralResolution
static bool gLefthand
Whether lefthand-drive is being simulated.
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
static SUMOTime gLaneChangeDuration
virtual ~MSLaneChanger()
Destructor.
bool applyTraCICommands(MSVehicle *vehicle)
Execute TraCI LC-commands.
bool continueChange(MSVehicle *vehicle, ChangerIt &from)
continue a lane change maneuver and return whether the vehicle has completely moved onto the new lane...
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
bool checkOppositeStop(MSVehicle *vehicle, const MSLane *oncomingLane, const MSLane *opposite, std::pair< MSVehicle *, double > leader)
decide whether to change (back or forth) for an opposite stop
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, MSVehicle *lastStopped)
MSLaneChanger()
Default constructor.
static bool hasOppositeStop(MSVehicle *vehicle)
whether vehicle has an opposite-direction stop within relevant range
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
virtual void initChanger()
Initialize the changer before looping over all vehicles.
std::pair< double, SUMOTime > getLastBlocked(int index) const
retrieve properties of a blocked vehicle that wants to chane to the lane with the given index
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one.
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
static const MSLane * getLaneAfter(const MSLane *lane, const std::vector< MSLane * > &conts, bool allowMinor, bool &contsEnd)
return the next lane in conts beyond lane or nullptr
std::pair< MSVehicle *const, double > getOncomingOppositeVehicle(const MSVehicle *vehicle, std::pair< MSVehicle *, double > overtaken, double searchDist)
MSVehicle * veh(ConstChangerIt ce) const
std::pair< MSVehicle *const, double > getOncomingVehicle(const MSLane *opposite, std::pair< MSVehicle *, double > neighOncoming, double searchDist, double &vMax, const MSVehicle *overtaken=nullptr, MSLane::MinorLinkMode mLinkMode=MSLane::MinorLinkMode::FOLLOW_NEVER)
bool startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
const bool myAllowsChanging
double 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)
determine for how long the vehicle can drive safely on the opposite side
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
static bool foundHilltop(MSVehicle *vehicle, bool foundHill, double searchDist, const std::vector< MSLane * > &bestLanes, int view, double pos, double lastMax, double hilltopThreshold)
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
static double computeSurplusGap(const MSVehicle *vehicle, const MSLane *opposite, std::pair< MSVehicle *, double > oncoming, double timeToOvertake, double spaceToOvertake, double &oncomingSpeed, bool oncomingOpposite=false)
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
bool yieldToOppositeWaiting(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist, SUMOTime deltaWait=0)
check whether to yield for oncoming vehicles that have waited longer for opposite overtaking
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
void registerUnchanged(MSVehicle *vehicle)
void updateLanes(SUMOTime t)
bool avoidDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > leader)
avoid opposite-diretion deadlock when vehicles are stopped on both sides of the road The method may c...
static std::pair< MSVehicle *, double > getColumnleader(double &maxSpace, MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
return leader vehicle that is to be overtaken
static double getMaxOvertakingSpeed(const MSVehicle *vehicle, double maxSpaceToOvertake)
compute maximum maneuver speed
bool resolveDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *const, double > leader, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken)
keep stopping to resolve opposite-diretion deadlock while there is oncoming traffic The method may ca...
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
bool yieldToDeadlockOncoming(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist)
check whether to keep stopping for oncoming vehicles in the deadlock zone
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
int 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
virtual bool 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)
static void computeOvertakingTime(const MSVehicle *vehicle, double vMax, const MSVehicle *leader, double gap, double &timeToOvertake, double &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
static std::vector< MSVehicle::LaneQ > getBestLanesOpposite(MSVehicle *vehicle, const MSLane *stopLane, double oppositeLength)
add LaneQ for opposite lanes
virtual void updateChanger(bool vehHasChanged)
Representation of a lane in the micro simulation.
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, MinorLinkMode mLinkMode) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
std::vector< MSVehicle * > VehCont
Container for vehicles.
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode=MinorLinkMode::FOLLOW_NEVER) const
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
double getLength() const
Returns the lane's length.
bool allowsChangingLeft(SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
std::pair< MSVehicle *const, double > getCriticalLeader(double dist, double seen, double speed, const MSVehicle &veh) const
Returns the most dangerous leader and the distance to him.
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
bool allowsVehicleClass(SUMOVehicleClass vclass) const
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
bool hasPedestrians() const
whether the lane has pedestrians on it
int getIndex() const
Returns the lane's index.
void requireCollisionCheck()
require another collision check due to relevant changes in the simulation
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
double interpolateGeometryPosToLanePos(double geometryPos) const
std::pair< MSVehicle *const, double > getLeader(const MSVehicle *veh, const double vehPos, const std::vector< MSLane * > &bestLaneConts, double dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
virtual const PositionVector & getShape(bool) const
MSEdge & getEdge() const
Returns the lane's edge.
double getWidth() const
Returns the lane's width.
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
LinkState getState() const
Returns the current state of the link.
const ApproachingVehicleInformation * getApproachingPtr(const SUMOVehicle *veh) const
bool opened(SUMOTime arrivalTime, double arrivalSpeed, double leaveSpeed, double vehicleLength, double impatience, double decel, SUMOTime waitingTime, double posLat=0, BlockingFoes *collectFoes=nullptr, bool ignoreRed=false, const SUMOTrafficObject *ego=nullptr, double dist=-1) const
Returns the information whether the link may be passed.
bool havePriority() const
Returns whether this link is a major link.
bool isEntryLink() const
return whether the toLane of this link is an internal lane and fromLane is a normal lane
MSLink * getParallelLink(int direction) const
return the link that is parallel to this lane or 0
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
LinkDirection getDirection() const
Returns the direction the vehicle passing this link take.
bool haveRed() const
Returns whether this link is blocked by a red (or redyellow) traffic light.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
bool hasElevation() const
return whether the network contains elevation data
const MSLane * lane
The lane to stop at (microsim only)
bool isOpposite
whether this an opposite-direction stop
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected (concerns approaching vehicles outside the...
SUMOTime getLaneTimeLineDuration()
double myPosLat
the stored lateral position
Representation of a vehicle in the micro simulation.
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
double computeAngle() const
compute the current vehicle angle
bool isStoppedOnLane() const
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
SUMOTime getWaitingTime(const bool accumulated=false) const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
MSAbstractLaneChangeModel & getLaneChangeModel()
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
bool unsafeLinkAhead(const MSLane *lane, double zipperDist) const
whether the vehicle may safely move to the given lane with regard to upcoming links
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
const MSLane * getLane() const
Returns the lane the vehicle is on.
std::pair< const MSVehicle *const, double > getFollower(double dist=0) const
Returns the follower of the vehicle looking for a fixed distance.
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
double getSpeed() const
Returns the vehicle's current speed.
Position myCachedPosition
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
double myAngle
the angle in radians (
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignored
double getPositionOnLane() const
Get the vehicle's position along the lane.
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
double getBrakeGap(bool delayed=false) const
get distance for coming to a stop (used for rerouting checks)
State myState
This Vehicles driving state (pos and speed)
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
static const Position INVALID
used to indicate that a position is valid
double z() const
Returns the z-position.
#define UNUSED_PARAMETER(x)
ChangeElem(MSLane *_lane)
double zipperDist
visibility distance to the closest zipper link that may be encountered when driving on this lane
MSLane * lane
the lane corresponding to this ChangeElem (the current change candidate is on this lane)
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.