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.) {
95 lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
110 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
112 myChanger.back().mayChangeRight = lane != lanes->begin();
113 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
114 if ((*lane)->isInternal()) {
116 if (
myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
119 if (
myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
123 if (
myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
127 if (
myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
149 const bool haveChanged =
change();
156 ce->lane->releaseVehicles();
168 ce->hoppedVeh =
nullptr;
169 ce->lastBlocked =
nullptr;
170 ce->firstBlocked =
nullptr;
171 ce->lastStopped =
nullptr;
173 ce->lane->getVehiclesSecure();
187 if (!vehHasChanged) {
210 ce->lane->swapAfterLaneChange(t);
211 ce->lane->releaseVehicles();
221 #ifdef DEBUG_CANDIDATE
222 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
226 if (
veh(ce) ==
nullptr) {
229 #ifdef DEBUG_CANDIDATE
230 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
234 #ifdef DEBUG_CANDIDATE
240 assert(
veh(ce) != 0);
241 assert(
veh(max) != 0);
242 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
243 #ifdef DEBUG_CANDIDATE
250 assert(
veh(max) != 0);
257 if (direction == 0) {
264 if (direction == -1) {
265 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingRight(svc);
266 }
else if (direction == 1) {
267 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingLeft(svc);
284 #ifdef DEBUG_ACTIONSTEPS
299 myCandi->lastStopped = vehicle;
305 #ifdef DEBUG_ACTIONSTEPS
307 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
310 bool changed =
false;
334 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
338 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
349 (
myCandi - 1)->lastBlocked = vehicle;
350 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
351 (
myCandi - 1)->firstBlocked = vehicle;
366 (
myCandi + 1)->lastBlocked = vehicle;
367 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
368 (
myCandi + 1)->firstBlocked = vehicle;
413 <<
" veh=" << vehicle->
getID()
416 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
427 bool changed =
false;
429 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
430 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
438 to->registerHop(vehicle);
460 to->registerHop(vehicle);
461 to->lane->requireCollisionCheck();
482 to->registerHop(vehicle);
486 from->registerHop(vehicle);
487 from->lane->requireCollisionCheck();
504 #ifdef DEBUG_CONTINUE_CHANGE
507 <<
" continueChange veh=" << vehicle->
getID()
509 <<
" dir=" << direction
510 <<
" speedLat=" << speedLat
511 <<
" pastMidpoint=" << pastMidpoint
523 std::pair<MSVehicle* const, double>
527 #ifdef DEBUG_SURROUNDING_VEHICLES
529 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
535 #ifdef DEBUG_SURROUNDING_VEHICLES
537 if (neighLead != 0) {
538 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
544 if (target->hoppedVeh !=
nullptr) {
545 double hoppedPos = target->hoppedVeh->getPositionOnLane();
546 #ifdef DEBUG_SURROUNDING_VEHICLES
548 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
552 neighLead = target->hoppedVeh;
557 const bool checkBidi = target->lane->getBidiLane() !=
nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
558 if (neighLead ==
nullptr || checkBidi) {
559 #ifdef DEBUG_SURROUNDING_VEHICLES
561 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
566 MSLane* targetLane = target->lane;
568 double leaderBack = targetLane->
getLength();
569 if (neighLead !=
nullptr) {
578 #ifdef DEBUG_SURROUNDING_VEHICLES
580 std::cout <<
" partial=" << pl->
getID() <<
" plBack=" << plBack <<
" plPos=" << plPos <<
" leaderBack=" << leaderBack <<
" egoBack=" << egoBack <<
"\n";
583 if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
588 if (neighLead !=
nullptr) {
589 #ifdef DEBUG_SURROUNDING_VEHICLES
591 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
595 return std::pair<MSVehicle*, double>(neighLead, gap);
600 if (target->lane->getBidiLane() !=
nullptr) {
601 dist += target->lane->getBidiLane()->getMaximumBrakeDist();
604 if (seen > dist && !
myCandi->lane->isInternal()) {
605 #ifdef DEBUG_SURROUNDING_VEHICLES
607 std::cout <<
" found no leader within dist=" << dist <<
"\n";
610 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
614 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
615 #ifdef DEBUG_SURROUNDING_VEHICLES
622 #ifdef DEBUG_SURROUNDING_VEHICLES
624 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
632 std::pair<MSVehicle* const, double>
636 #ifdef DEBUG_SURROUNDING_VEHICLES
638 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
644 neighFollow =
veh(target);
647 if (target->lane->myVehicles.size() > 1) {
648 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
652 #ifdef DEBUG_SURROUNDING_VEHICLES
654 if (neighFollow != 0) {
655 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
657 std::cout <<
"veh(target) returns none." << std::endl;
663 #ifdef DEBUG_SURROUNDING_VEHICLES
665 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
666 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
675 #ifdef DEBUG_SURROUNDING_VEHICLES
678 if (partialBehind != 0 && partialBehind != neighFollow) {
679 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
684 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
686 if (neighFollow ==
nullptr) {
688 #ifdef DEBUG_SURROUNDING_VEHICLES
690 if (consecutiveFollower.first == 0) {
691 std::cout <<
"no follower found." << std::endl;
693 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
697 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
699 #ifdef DEBUG_SURROUNDING_VEHICLES
701 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
704 return std::pair<MSVehicle* const, double>(neighFollow,
728 const std::pair<MSVehicle* const, double>& leader,
729 const std::vector<MSVehicle::LaneQ>& preb)
const {
734 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
737 neighFollow.first = 0;
740 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
747 const std::pair<MSVehicle* const, double>& leader,
748 const std::pair<MSVehicle* const, double>& follower,
749 const std::pair<MSVehicle* const, double>& neighLead,
750 const std::pair<MSVehicle* const, double>& neighFollow,
751 const std::vector<MSVehicle::LaneQ>& preb)
const {
755 #ifdef DEBUG_CHECK_CHANGE
758 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
767 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
771 #ifdef DEBUG_CHECK_CHANGE
774 <<
" overlapping with follower..."
780 if (neighLead.first !=
nullptr && neighLead.second < 0) {
783 #ifdef DEBUG_CHECK_CHANGE
786 <<
" overlapping with leader..."
798 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
806 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
809 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
811 #ifdef DEBUG_CHECK_CHANGE
814 <<
" follower=" << neighFollow.first->getID()
815 <<
" backGap=" << neighFollow.second
816 <<
" vNextFollower=" << vNextFollower
817 <<
" vNextEgo=" << vNextLeader
818 <<
" secureGap=" << secureBackGap
826 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
831 #ifdef DEBUG_CHECK_CHANGE
833 std::cout <<
" ignoring opposite follower who changed in this step\n";
837 blocked |= blockedByFollower;
843 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
852 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
856 #ifdef DEBUG_CHECK_CHANGE
859 <<
" leader=" << neighLead.first->getID()
860 <<
" frontGap=" << neighLead.second
861 <<
" vNextEgo=" << vNextFollower
862 <<
" vNextLeader=" << vNextLeader
863 <<
" secureGap=" << secureFrontGap
870 blocked |= blockedByLeader;
877 if (nextLeader.first != 0) {
881 #ifdef DEBUG_CHECK_CHANGE
883 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
886 if (brakeGap > gap) {
887 blocked |= blockedByLeader;
888 #ifdef DEBUG_CHECK_CHANGE
890 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
897 if (leader.first !=
nullptr) {
898 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
903 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
912 const double speed = vehicle->
getSpeed();
914 if (seen < dist || myCandi->lane->isInternal()) {
915 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
916 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
918 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
920 #ifdef DEBUG_SURROUNDING_VEHICLES
922 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
923 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
926 if (neighLead2.second < secureGap2) {
927 state |= blockedByLeader;
935 state |= blockedByLeader;
947 if (estimatedLCDuration == -1) {
949 #ifdef DEBUG_CHECK_CHANGE
951 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
952 <<
"\nestimatedLCDuration=" << estimatedLCDuration
953 <<
"\ndistToNeighLane=" << distToNeighLane
961 const double avgSpeed = 0.5 * (
965 const double space2change = avgSpeed * estimatedLCDuration;
968 #ifdef DEBUG_CHECK_CHANGE
970 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
971 <<
"\ndistToNeighLane=" << distToNeighLane
972 <<
" estimatedLCDuration=" << estimatedLCDuration
973 <<
" space2change=" << space2change
974 <<
" avgSpeed=" << avgSpeed
983 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
984 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
988 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
993 if ((*link)->getViaLane() ==
nullptr) {
996 nextLane = (*link)->getViaLaneOrLane();
1001 #ifdef DEBUG_CHECK_CHANGE
1003 std::cout <<
" available distance=" << seen << std::endl;
1006 if (nextLane->
isLinkEnd(link) && seen < space2change) {
1007 #ifdef DEBUG_CHECK_CHANGE
1009 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1018 const double speed = vehicle->
getSpeed();
1020 nextLane = vehicle->
getLane();
1023 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1024 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1025 nextLane = (*nextLink)->getViaLaneOrLane();
1027 if (parallelLane ==
nullptr) {
1031 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1032 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1034 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1035 state |= blockedByLeader;
1039 if ((*nextLink)->getViaLane() ==
nullptr) {
1049 const int oldstate = state;
1052 #ifdef DEBUG_CHECK_CHANGE
1055 <<
" veh=" << vehicle->
getID()
1075 if (laneOffset != 0) {
1097 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1098 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1101 const int bestOffset = preb[laneIndex].bestLaneOffset;
1112 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1116 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1124 double oncomingSpeed;
1125 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1126 if (!isOpposite && surplusGap < 0) {
1127 #ifdef DEBUG_CHANGE_OPPOSITE
1129 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1130 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1136 if (bestOffset > 0) {
1137 MSLane*
const target = preb[laneIndex + 1].lane;
1149 std::vector<MSVehicle::LaneQ>
1156 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1157 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1158 for (
int i = 0; i < numOpposite; i++) {
1159 preb.push_back(preb.back());
1160 preb.back().lane = oLanes[numOpposite - 1 - i];
1161 preb.back().length = oppositeLength;
1163 preb.back().bestLaneOffset = -1 - i;
1167 if (stopLane !=
nullptr) {
1168 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1169 for (
int i = 0; i < (int)preb.size(); i++) {
1170 preb[i].bestLaneOffset = stopIndex - i;
1175 #ifdef DEBUG_CHANGE_OPPOSITE
1177 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1178 for (
int i = 0; i < (int)preb.size(); i++) {
1179 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1197 #ifdef DEBUG_CHANGE_OPPOSITE
1200 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1205 if (opposite ==
nullptr) {
1215 bool oppositeChangeByTraci =
false;
1218 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1222 oppositeChangeByTraci =
true;
1226 #ifdef DEBUG_CHANGE_OPPOSITE
1228 std::cout <<
" not overtaking due to changeLeft restriction\n";
1239 const MSLane* oncomingLane = isOpposite ? source : opposite;
1242 int direction = isOpposite ? -1 : 1;
1243 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1246 double surplusGap = std::numeric_limits<double>::max();
1255 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1257 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1259 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1270 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1276 if (!isOpposite && !oppositeChangeByTraci
1278 && leader.first !=
nullptr) {
1283 #ifdef DEBUG_CHANGE_OPPOSITE
1285 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1291 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1294 }
else if (leader.second < 0) {
1296 #ifdef DEBUG_CHANGE_OPPOSITE
1298 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1306 double timeToOvertake = std::numeric_limits<double>::max();
1307 double spaceToOvertake = std::numeric_limits<double>::max();
1308 double maxSpaceToOvertake = 0;
1310 if (oppositeChangeByTraci) {
1320 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1321 overtaken = neighLead;
1323 if (overtaken.first !=
nullptr) {
1326 #ifdef DEBUG_CHANGE_OPPOSITE
1328 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1329 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1330 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1337 if (overtaken.first == 0) {
1340 #ifdef DEBUG_CHANGE_OPPOSITE
1342 std::cout <<
" no leader found\n";
1347 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1352 #ifdef DEBUG_CHANGE_OPPOSITE
1354 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1362 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1363 #ifdef DEBUG_CHANGE_OPPOSITE
1366 <<
" veh=" << vehicle->
getID()
1367 <<
" changeOpposite opposite=" << opposite->
getID()
1369 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1371 <<
" timeToOvertake=" << timeToOvertake
1372 <<
" spaceToOvertake=" << spaceToOvertake
1378 #ifdef DEBUG_CHANGE_OPPOSITE
1380 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1388 if (!wait && lastStopped !=
nullptr) {
1390 #ifdef DEBUG_CHANGE_OPPOSITE
1392 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1395 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1404 assert(timeToOvertake != std::numeric_limits<double>::max());
1405 assert(spaceToOvertake != std::numeric_limits<double>::max());
1408 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1409 neighLead = oncomingLane->
getOppositeLeader(vehicle, searchDist,
true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1410 oncoming =
getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1415 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1418 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1421 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1422 if (oncomingGap > 0) {
1425 #ifdef DEBUG_CHANGE_OPPOSITE
1427 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1428 <<
" halting=" << oncoming.first->getWaitingSeconds()
1429 <<
" oncomingGap=" << oncomingGap
1431 <<
" vMax=" << vMax <<
"\n";
1438 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1439 #ifdef DEBUG_CHANGE_OPPOSITE
1441 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1442 <<
" timeToOvertake=" << timeToOvertake
1443 <<
" spaceToOvertake=" << spaceToOvertake
1450 #ifdef DEBUG_CHANGE_OPPOSITE
1452 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1460 #ifdef DEBUG_CHANGE_OPPOSITE
1462 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1467 assert(timeToOvertake != std::numeric_limits<double>::max());
1468 assert(spaceToOvertake != std::numeric_limits<double>::max());
1472 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1473 if (oncomingOpposite.first !=
nullptr) {
1474 double oncomingSpeed2;
1475 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1477 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1478 #ifdef DEBUG_CHANGE_OPPOSITE
1480 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1483 surplusGap =
MIN2(surplusGap, surplusGap2);
1484 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1485 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1486 && oncomingOpposite.second > oncoming.second) {
1490 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1493 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1494 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1495 double ooTTO = ooSTO / oSpeed;
1497 ooTTO = ceil(ooTTO /
TS) *
TS;
1498 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1499 #ifdef DEBUG_CHANGE_OPPOSITE
1501 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1504 surplusGap =
MIN2(surplusGap, surplusGap3);
1507 if (!isOpposite && surplusGap < 0) {
1508 #ifdef DEBUG_CHANGE_OPPOSITE
1510 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1514 #ifdef DEBUG_CHANGE_OPPOSITE
1516 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1517 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1529 if (usableDist < spaceToOvertake) {
1532 assert(bestLaneConts.size() >= 1);
1533 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1534 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1535 #ifdef DEBUG_CHANGE_OPPOSITE
1537 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1540 if ((*it)->getOpposite() ==
nullptr || !(*it)->getOpposite()->allowsVehicleClass(vehicle->
getVClass())) {
1545 const MSLane*
const prev = *(it - 1);
1546 if (prev !=
nullptr) {
1555 #ifdef DEBUG_CHANGE_OPPOSITE
1557 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1563 usableDist += (*it)->getLength();
1567 if (!isOpposite && usableDist < spaceToOvertake) {
1568 #ifdef DEBUG_CHANGE_OPPOSITE
1570 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1579 bool foundHill = vehicle->
getSlope() > 0;
1584 #ifdef DEBUG_CHANGE_OPPOSITE
1586 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1591 double oppositeLength = vehicle->
getBestLanes().back().length;
1594 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1595 leader.first =
nullptr;
1596 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1598 neighLead.first =
nullptr;
1603 #ifdef DEBUG_CHANGE_OPPOSITE
1605 std::cout <<
" not changing to avoid deadlock\n";
1610 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1616 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1624 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1630 std::pair<MSVehicle*, double> neighLead,
1631 std::pair<MSVehicle*, double> overtaken,
1632 std::pair<MSVehicle*, double> leader) {
1634 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1636 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1643 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1645 }
else if (!neighLead.first->isStopped()
1649 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1650 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1651 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1652 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1654 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1657 if (neighLead.first ==
nullptr) {
1664 if (neighLead.first->isStopped()
1665 && (overtaken.first->isStopped()
1666 || leader.first->getLaneChangeModel().isOpposite()
1671 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1672 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1674 const double distToStop = neighLead.second - requiredGap;
1678 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1679 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1680 if (neighStoppedBack + nextGap > overtaken.second) {
1683 neighStoppedBack += nextGap;
1684 auto neighLeadFollow = neighLead.first->getFollower();
1685 neighLead.second = neighLeadFollow.second;
1686 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1687 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1692 if (neighStoppedBack > overtaken.second) {
1697 const double leaderBGap = leader.first->getBrakeGap();
1698 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1699 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1701 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1703 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1704 <<
" neighLeadGap=" << neighLead.second
1705 <<
" leaderGap=" << leader.second
1706 <<
" bGap=" << leaderBGap
1707 <<
" fGap=" << leaderFGap
1708 <<
" eGap=" << extraGap
1709 <<
" neighStoppedBack=" << neighStoppedBack
1711 <<
" requiredGap=" << requiredGap
1712 <<
" gapWithEgo=" << gapWithEgo
1713 <<
" yield=" << yield
1718 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1719 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1720 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1722 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1724 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1727 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1728 const double blockerLength = currentDist - stopPos;
1730 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1732 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1733 <<
" blockerLength=" << blockerLength
1734 <<
" reserved=" << reserved
1752 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1754 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1755 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1756 follower = follower.first->getFollower(dist);
1758 if (follower.first !=
nullptr) {
1759 followerGap += follower.second;
1761 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1763 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1764 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1768 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1776 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1777 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1778 follower = follower.first->getFollower(dist);
1780 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1781 if (
DEBUG_COND && follower.first !=
nullptr) {
1782 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1783 <<
" oncoming=" << follower.first->getID()
1784 <<
" wait=" << follower.first->getWaitingSeconds()
1790 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1799 std::pair<MSVehicle* const, double> leader,
1800 std::pair<MSVehicle*, double> neighLead,
1801 std::pair<MSVehicle*, double> overtaken) {
1802 const double deadLockZone = overtaken.second;
1803 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1807 <<
" gap=" << leader.second
1816 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1817 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1819 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1820 <<
" leader=" << leader.first->getID()
1821 <<
" leaderGap=" << leader.second
1823 <<
" deadLockZone=" << deadLockZone
1827 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1830 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1831 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1832 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1833 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1835 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1840 if (oncomingOpposite.first !=
nullptr ||
1841 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1843 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1844 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1848 #ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1850 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1851 <<
" leader=" << leader.first->getID()
1852 <<
" leaderGap=" << leader.second
1854 <<
" currentDist=" << currentDist
1855 <<
" blockerLength=" << blockerLength
1856 <<
" reserved=" << reserved
1871 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1872 std::pair<MSVehicle*, double> neighLead,
1873 std::pair<MSVehicle*, double> overtaken,
1874 std::pair<MSVehicle*, double> neighFollow,
1875 double surplusGap,
const MSLane* opposite,
1885 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1887 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1888 #ifdef DEBUG_CHANGE_OPPOSITE
1890 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1894 const MSVehicle* oncomingVeh = oncoming.first;
1895 if (oncomingVeh != 0) {
1897 double egoSpeedFraction = 0.5;
1898 if (oncomingSpeed > 0) {
1899 egoSpeedFraction =
MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1901 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1902 #ifdef DEBUG_CHANGE_OPPOSITE
1904 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1905 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1909 #ifdef DEBUG_CHANGE_OPPOSITE
1911 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1915 if (neighLead.first !=
nullptr) {
1916 if (overtaken.first ==
nullptr) {
1917 #ifdef DEBUG_CHANGE_OPPOSITE
1919 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1922 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
1923 && neighLead.second > 0
1924 && neighFollow.second > 0
1927 oppositeLength = forwardPos + neighLead.second;
1929 if (surplusGap > 0) {
1932 oppositeLength += 1000;
1935 if (overtaken.second > 0) {
1936 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1941 #ifdef DEBUG_CHANGE_OPPOSITE
1943 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1944 <<
" surplusGap=" << surplusGap
1945 <<
" final laneQLength=" << oppositeLength
1952 if (overtaken.first ==
nullptr || !canOvertake) {
1955 if (oppFollow.first ==
nullptr) {
1956 oppositeLength = forwardPos;
1958 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1960 #ifdef DEBUG_CHANGE_OPPOSITE
1962 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
1965 if (oppFollow.second > secureGap) {
1967 oppositeLength = forwardPos;
1972 #ifdef DEBUG_CHANGE_OPPOSITE
1974 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
1977 return oppositeLength;
1981 std::pair<MSVehicle* const, double>
1984 double gap = oncoming.second;
1985 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
1986 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
1988 gap += oncoming.first->getVehicleType().getLengthWithGap();
1989 if (oncoming.first != overtaken) {
1990 vMax =
MIN2(vMax, oncoming.first->getSpeed());
1992 #ifdef DEBUG_CHANGE_OPPOSITE
1994 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
1995 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
1998 if (searchDist < 0) {
2002 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2003 opposite = oncoming.first->getLane();
2005 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2006 if (oncoming.first !=
nullptr) {
2007 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2008 #ifdef DEBUG_CHANGE_OPPOSITE
2010 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
2015 oncoming.second = gap;
2020 std::pair<MSVehicle* const, double>
2024 if (overtaken.first !=
nullptr) {
2026 front = overtaken.first;
2034 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2036 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2037 conts.erase(conts.begin());
2040 if (oncoming.first !=
nullptr) {
2041 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2042 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2043 #ifdef DEBUG_CHANGE_OPPOSITE
2046 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2047 <<
" oncomingOpposite=" << oncoming.first->getID()
2048 <<
" gap=" << oncoming.second
2049 <<
" isOpposite=" << isOpposite
2054 if (isOpposite && shadowLane != front->
getLane()) {
2056 oncoming.second -= oncoming.first->getVehicleType().getLength();
2057 oncoming.second += gap;
2061 return std::make_pair(
nullptr, -1);
2067 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2068 double surplusGap = std::numeric_limits<double>::max();
2069 const MSVehicle* oncomingVeh = oncoming.first;
2070 if (oncomingVeh != 0 && (oncomingOpposite
2081 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2082 #ifdef DEBUG_CHANGE_OPPOSITE
2085 <<
" oncoming=" << oncomingVeh->
getID()
2086 <<
" oGap=" << oncoming.second
2087 <<
" oSpeed=" << oncomingSpeed
2088 <<
" sto=" << spaceToOvertake
2089 <<
" tto=" << timeToOvertake
2090 <<
" safetyGap=" << safetyGap
2091 <<
" surplusGap=" << surplusGap
2101 if (view >= (
int)bestLanes.size()) {
2104 MSLane* lane = bestLanes[view];
2105 double laneDist = 0;
2107 double lastZ = lastMax;
2108 for (
int i = 1; i < (int)shape.size(); i++) {
2111 if (laneDist > pos) {
2112 const double z = shape[i].z();
2120 #ifdef DEBUG_CHANGE_OPPOSITE
2122 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2125 if (foundHill && z < lastMax) {
2126 const double drop = lastMax - z;
2128 if (drop > hilltopThreshold) {
2129 #ifdef DEBUG_CHANGE_OPPOSITE
2131 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2132 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2141 searchDist -= laneDist - pos;
2144 if (searchDist <= 0) {
2149 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2158 const std::pair<MSVehicle* const, double>& leader,
2159 const std::pair<MSVehicle* const, double>& neighLead,
2160 const std::pair<MSVehicle* const, double>& neighFollow,
2161 const std::vector<MSVehicle::LaneQ>& preb) {
2164 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2165 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2167 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2173 #ifdef DEBUG_CHANGE_OPPOSITE
2175 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2184 #ifdef DEBUG_CHANGE_OPPOSITE
2186 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2203 const double v = vehicle->
getSpeed();
2207 const double g =
MAX2(0.0, (
2218 const double sign = -1;
2222 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2223 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2225 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2226 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2233 timeToOvertake = std::numeric_limits<double>::max();
2234 spaceToOvertake = std::numeric_limits<double>::max();
2242 t = ceil(t /
TS) *
TS;
2246 const double timeToMaxSpeed = (vMax - v) / a;
2248 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2250 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2253 if (t <= timeToMaxSpeed) {
2255 spaceToOvertake = v * t + t * t * a * 0.5;
2256 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2258 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2263 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2264 const double m = timeToMaxSpeed;
2267 t = (g - s + m * vMax) / (vMax - u);
2270 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2272 std::cout <<
" t2=" << t <<
"\n";
2275 timeToOvertake = std::numeric_limits<double>::max();
2276 spaceToOvertake = std::numeric_limits<double>::max();
2283 t = ceil(t /
TS) *
TS;
2286 spaceToOvertake = s + (t - m) * vMax;
2287 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2289 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2295 timeToOvertake *= safetyFactor;
2297 spaceToOvertake *= safetyFactor;
2299 double frac = fmod(timeToOvertake,
TS);
2302 timeToOvertake +=
TS - frac;
2304 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2306 if (safetyFactor != 1) {
2307 std::cout <<
" applying safetyFactor=" << safetyFactor
2309 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2317 std::pair<MSVehicle*, double>
2319 assert(leader.first != 0);
2324 std::pair<MSVehicle*, double> columnLeader = leader;
2325 double egoGap = leader.second;
2326 bool foundSpaceAhead =
false;
2327 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2329 if (maxLookAhead == std::numeric_limits<double>::max()) {
2333 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2335 + leader.first->getVehicleType().getLengthWithGap());
2337 #ifdef DEBUG_CHANGE_OPPOSITE
2339 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2343 while (!foundSpaceAhead) {
2344 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2345 columnLeader.first, vehicle,
2347 + columnLeader.first->getVehicleType().getMinGap()
2352 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2353 double searchStart = columnLeader.first->getPositionOnLane();
2354 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2355 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2357 std::set<MSVehicle*> seenLeaders;
2358 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2359 #ifdef DEBUG_CHANGE_OPPOSITE
2361 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2364 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2365 leadLead.first =
nullptr;
2368 seenLeaders.insert(leadLead.first);
2370 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2371 leadLead = columnLeader.first->getLane()->getLeader(
2372 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2374 leadLead.second += (searchStart2 - searchStart);
2376 if (leadLead.first ==
nullptr) {
2377 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2378 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2379 if (!columnLeader.first->isStopped()) {
2381 requiredSpace += safetyFactor * mergeBrakeGap;
2383 #ifdef DEBUG_CHANGE_OPPOSITE
2385 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2386 <<
" availableSpace=" << availableSpace
2387 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2388 <<
" ovSpeed=" << overtakingSpeed
2389 <<
" reqBGap=" << mergeBrakeGap
2390 <<
" reqMin=" << requiredSpace / safetyFactor
2391 <<
" req=" << requiredSpace
2395 if (availableSpace > requiredSpace) {
2396 foundSpaceAhead =
true;
2401 bool contsEnd =
false;
2402 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, allowMinor, contsEnd);
2403 #ifdef DEBUG_CHANGE_OPPOSITE
2405 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2408 while (next !=
nullptr && seen < maxLookAhead) {
2411 if (cand ==
nullptr) {
2413 if (availableSpace > requiredSpace) {
2414 foundSpaceAhead =
true;
2417 next =
getLaneAfter(next, conts, allowMinor, contsEnd);
2420 if (availableSpace > requiredSpace) {
2421 foundSpaceAhead =
true;
2428 #ifdef DEBUG_CHANGE_OPPOSITE
2430 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2433 if (!foundSpaceAhead && contsEnd) {
2434 foundSpaceAhead =
true;
2435 availableSpace = requiredSpace;
2437 if (!foundSpaceAhead) {
2438 return std::make_pair(
nullptr, -1);
2441 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2444 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2445 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2446 if (!columnLeader.first->isStopped()) {
2448 requiredSpace += safetyFactor * sGap;
2450 #ifdef DEBUG_CHANGE_OPPOSITE
2452 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2453 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2454 <<
" ovSpeed=" << overtakingSpeed
2455 <<
" reqSGap=" << sGap
2456 <<
" reqMin=" << requiredSpace / safetyFactor
2457 <<
" req=" << requiredSpace
2461 if (leadLead.second > requiredSpace) {
2462 foundSpaceAhead =
true;
2463 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2466 if (leadLead.second < 0) {
2468 #ifdef DEBUG_CHANGE_OPPOSITE
2470 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2473 return std::make_pair(
nullptr, -1);
2476 #ifdef DEBUG_CHANGE_OPPOSITE
2478 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2481 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2482 if (seen > maxLookAhead) {
2483 #ifdef DEBUG_CHANGE_OPPOSITE
2485 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2488 return std::make_pair(
nullptr, -1);
2491 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2492 columnLeader = leadLead;
2493 #ifdef DEBUG_CHANGE_OPPOSITE
2495 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2501 columnLeader.second = egoGap;
2502 return columnLeader;
2508 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2510 if (it + 1 != conts.end()) {
2512 const MSLane* next = *(it + 1);
2514 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2532 const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
#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_EMERGENCY
public emergency vehicles
@ 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
#define UNUSED_PARAMETER(x)
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 getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
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 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
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
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.
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)
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
MSVehicle * veh(ConstChangerIt ce) 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
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...
MSEdge & getEdge() const
Returns the lane's edge.
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
double getWidth() const
Returns the lane's width.
virtual const PositionVector & getShape(bool) const
LinkState getState() const
Returns the current state of the link.
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
bool havePriority() const
Returns whether this link is a major link.
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()
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
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.
@ 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.
std::pair< const MSVehicle *const, double > getFollower(double dist=0) const
Returns the follower of the vehicle looking for a fixed distance.
Influencer & getInfluencer()
bool isBidiOn(const MSLane *lane) const
whether this vehicle is driving against lane
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links
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.
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.
const MSLane * getLane() const
Returns the lane the vehicle is on.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
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.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
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.
ChangeElem(MSLane *_lane)
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.