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()) {
168 const bool haveChanged =
change();
175 ce->lane->releaseVehicles();
187 ce->hoppedVeh =
nullptr;
188 ce->lastBlocked =
nullptr;
189 ce->firstBlocked =
nullptr;
190 ce->lastStopped =
nullptr;
192 ce->lastBlockedBackPos = -1;
193 ce->lastBlockedWaitingTime = -1;
194 ce->lane->getVehiclesSecure();
208 if (!vehHasChanged) {
231 ce->lane->swapAfterLaneChange(t);
232 ce->lane->releaseVehicles();
233 if (ce->lastBlocked !=
nullptr) {
234 ce->lastBlockedBackPos = ce->lastBlocked->getBackPositionOnLane();
235 ce->lastBlockedWaitingTime = ce->lastBlocked->getWaitingTime();
246#ifdef DEBUG_CANDIDATE
247 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
251 if (
veh(ce) ==
nullptr) {
254#ifdef DEBUG_CANDIDATE
255 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
259#ifdef DEBUG_CANDIDATE
265 assert(
veh(ce) != 0);
266 assert(
veh(max) != 0);
267 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
268#ifdef DEBUG_CANDIDATE
275 assert(
veh(max) != 0);
282 if (direction == 0) {
289 if (direction == -1) {
290 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingRight(svc);
291 }
else if (direction == 1) {
292 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingLeft(svc);
309#ifdef DEBUG_ACTIONSTEPS
324 myCandi->lastStopped = vehicle;
330#ifdef DEBUG_ACTIONSTEPS
332 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
335 bool changed =
false;
359 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
363 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
374 (
myCandi - 1)->lastBlocked = vehicle;
375 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
376 (
myCandi - 1)->firstBlocked = vehicle;
391 (
myCandi + 1)->lastBlocked = vehicle;
392 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
393 (
myCandi + 1)->firstBlocked = vehicle;
438 <<
" veh=" << vehicle->
getID()
441 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
452 bool changed =
false;
454 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
455 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
463 to->registerHop(vehicle);
485 to->registerHop(vehicle);
486 to->lane->requireCollisionCheck();
507 to->registerHop(vehicle);
511 from->registerHop(vehicle);
512 from->lane->requireCollisionCheck();
529#ifdef DEBUG_CONTINUE_CHANGE
532 <<
" continueChange veh=" << vehicle->
getID()
534 <<
" dir=" << direction
535 <<
" speedLat=" << speedLat
536 <<
" pastMidpoint=" << pastMidpoint
548std::pair<MSVehicle* const, double>
552#ifdef DEBUG_SURROUNDING_VEHICLES
554 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
560#ifdef DEBUG_SURROUNDING_VEHICLES
562 if (neighLead != 0) {
563 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
569 if (target->hoppedVeh !=
nullptr) {
570 double hoppedPos = target->hoppedVeh->getPositionOnLane();
571#ifdef DEBUG_SURROUNDING_VEHICLES
573 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
577 neighLead = target->hoppedVeh;
582 const bool checkBidi = target->lane->getBidiLane() !=
nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
583 if (neighLead ==
nullptr || checkBidi) {
584#ifdef DEBUG_SURROUNDING_VEHICLES
586 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
591 MSLane* targetLane = target->lane;
593 double leaderBack = targetLane->
getLength();
594 if (neighLead !=
nullptr) {
598 double plBack = pl->getBackPositionOnLane(targetLane);
599 if (pl->isBidiOn(targetLane)) {
600 plBack -= pl->getVehicleType().getLengthWithGap();
602 const double plPos = plBack + pl->getVehicleType().getLength();
603#ifdef DEBUG_SURROUNDING_VEHICLES
605 std::cout <<
" partial=" << pl->getID() <<
" plBack=" << plBack <<
" plPos=" << plPos <<
" leaderBack=" << leaderBack <<
" egoBack=" << egoBack <<
"\n";
608 if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
613 if (neighLead !=
nullptr) {
614#ifdef DEBUG_SURROUNDING_VEHICLES
616 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
620 return std::pair<MSVehicle*, double>(neighLead, gap);
625 if (target->lane->getBidiLane() !=
nullptr) {
626 dist += target->lane->getBidiLane()->getMaximumBrakeDist();
629 if (seen > dist && !
myCandi->lane->isInternal()) {
630#ifdef DEBUG_SURROUNDING_VEHICLES
632 std::cout <<
" found no leader within dist=" << dist <<
"\n";
635 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
639 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
640#ifdef DEBUG_SURROUNDING_VEHICLES
647#ifdef DEBUG_SURROUNDING_VEHICLES
649 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
657std::pair<MSVehicle* const, double>
661#ifdef DEBUG_SURROUNDING_VEHICLES
663 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
669 neighFollow =
veh(target);
672 if (target->lane->myVehicles.size() > 1) {
673 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
677#ifdef DEBUG_SURROUNDING_VEHICLES
679 if (neighFollow != 0) {
680 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
682 std::cout <<
"veh(target) returns none." << std::endl;
688#ifdef DEBUG_SURROUNDING_VEHICLES
690 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
691 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
700#ifdef DEBUG_SURROUNDING_VEHICLES
703 if (partialBehind != 0 && partialBehind != neighFollow) {
704 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
709 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
711 if (neighFollow ==
nullptr) {
713#ifdef DEBUG_SURROUNDING_VEHICLES
715 if (consecutiveFollower.first == 0) {
716 std::cout <<
"no follower found." << std::endl;
718 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
722 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
724#ifdef DEBUG_SURROUNDING_VEHICLES
726 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
729 return std::pair<MSVehicle* const, double>(neighFollow,
753 const std::pair<MSVehicle* const, double>& leader,
754 const std::vector<MSVehicle::LaneQ>& preb)
const {
759 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
762 neighFollow.first = 0;
765 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
772 const std::pair<MSVehicle* const, double>& leader,
773 const std::pair<MSVehicle* const, double>& follower,
774 const std::pair<MSVehicle* const, double>& neighLead,
775 const std::pair<MSVehicle* const, double>& neighFollow,
776 const std::vector<MSVehicle::LaneQ>& preb)
const {
780#ifdef DEBUG_CHECK_CHANGE
783 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
792 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
796#ifdef DEBUG_CHECK_CHANGE
799 <<
" overlapping with follower..."
805 if (neighLead.first !=
nullptr && neighLead.second < 0) {
808#ifdef DEBUG_CHECK_CHANGE
811 <<
" overlapping with leader..."
823 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
831 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
834 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
836#ifdef DEBUG_CHECK_CHANGE
839 <<
" follower=" << neighFollow.first->getID()
840 <<
" backGap=" << neighFollow.second
841 <<
" vNextFollower=" << vNextFollower
842 <<
" vNextEgo=" << vNextLeader
843 <<
" secureGap=" << secureBackGap
851 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
856#ifdef DEBUG_CHECK_CHANGE
858 std::cout <<
" ignoring opposite follower who changed in this step\n";
862 blocked |= blockedByFollower;
868 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
877 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
881#ifdef DEBUG_CHECK_CHANGE
884 <<
" leader=" << neighLead.first->getID()
885 <<
" frontGap=" << neighLead.second
886 <<
" vNextEgo=" << vNextFollower
887 <<
" vNextLeader=" << vNextLeader
888 <<
" secureGap=" << secureFrontGap
895 blocked |= blockedByLeader;
902 if (nextLeader.first != 0) {
906#ifdef DEBUG_CHECK_CHANGE
908 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
911 if (brakeGap > gap) {
912 blocked |= blockedByLeader;
913#ifdef DEBUG_CHECK_CHANGE
915 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
922 if (leader.first !=
nullptr) {
923 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
928 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
937 const double speed = vehicle->
getSpeed();
939 if (seen < dist || myCandi->lane->isInternal()) {
940 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
941 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
943 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
945#ifdef DEBUG_SURROUNDING_VEHICLES
947 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
948 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
951 if (neighLead2.second < secureGap2) {
952 state |= blockedByLeader;
959 double targetZipperDist = 0;
960 if (laneOffset == 0) {
961 targetZipperDist =
myCandi->zipperDist;
962 }
else if (laneOffset == 1) {
964 targetZipperDist = (
myCandi + 1)->zipperDist;
966 }
else if (laneOffset == -1) {
968 targetZipperDist = (
myCandi - 1)->zipperDist;
972 state |= blockedByLeader;
984 if (estimatedLCDuration == -1) {
986#ifdef DEBUG_CHECK_CHANGE
988 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
989 <<
"\nestimatedLCDuration=" << estimatedLCDuration
990 <<
"\ndistToNeighLane=" << distToNeighLane
998 const double avgSpeed = 0.5 * (
1002 const double space2change = avgSpeed * estimatedLCDuration;
1005#ifdef DEBUG_CHECK_CHANGE
1007 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
1008 <<
"\ndistToNeighLane=" << distToNeighLane
1009 <<
" estimatedLCDuration=" << estimatedLCDuration
1010 <<
" space2change=" << space2change
1011 <<
" avgSpeed=" << avgSpeed
1020 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1021 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
1025 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
1030 if ((*link)->getViaLane() ==
nullptr) {
1033 nextLane = (*link)->getViaLaneOrLane();
1038#ifdef DEBUG_CHECK_CHANGE
1040 std::cout <<
" available distance=" << seen << std::endl;
1043 if (nextLane->
isLinkEnd(link) && seen < space2change) {
1044#ifdef DEBUG_CHECK_CHANGE
1046 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1055 const double speed = vehicle->
getSpeed();
1057 nextLane = vehicle->
getLane();
1060 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1061 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1062 nextLane = (*nextLink)->getViaLaneOrLane();
1064 if (parallelLane ==
nullptr) {
1068 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1069 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1071 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1072 state |= blockedByLeader;
1076 if ((*nextLink)->getViaLane() ==
nullptr) {
1086 const int oldstate = state;
1090#ifdef DEBUG_CHECK_CHANGE
1093 <<
" veh=" << vehicle->
getID()
1113 if (laneOffset != 0) {
1135 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1136 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1139 const int bestOffset = preb[laneIndex].bestLaneOffset;
1150 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1154 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1162 double oncomingSpeed;
1163 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1164 if (!isOpposite && surplusGap < 0) {
1165#ifdef DEBUG_CHANGE_OPPOSITE
1167 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1168 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1174 if (bestOffset > 0) {
1175 MSLane*
const target = preb[laneIndex + 1].lane;
1187std::vector<MSVehicle::LaneQ>
1194 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1195 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1196 for (
int i = 0; i < numOpposite; i++) {
1197 preb.push_back(preb.back());
1198 preb.back().lane = oLanes[numOpposite - 1 - i];
1199 preb.back().length = oppositeLength;
1201 preb.back().bestLaneOffset = -1 - i;
1205 if (stopLane !=
nullptr) {
1206 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1207 for (
int i = 0; i < (int)preb.size(); i++) {
1208 preb[i].bestLaneOffset = stopIndex - i;
1213#ifdef DEBUG_CHANGE_OPPOSITE
1215 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1216 for (
int i = 0; i < (int)preb.size(); i++) {
1217 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1235#ifdef DEBUG_CHANGE_OPPOSITE
1238 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1243 if (opposite ==
nullptr) {
1253 bool oppositeChangeByTraci =
false;
1256 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1260 oppositeChangeByTraci =
true;
1264#ifdef DEBUG_CHANGE_OPPOSITE
1266 std::cout <<
" not overtaking due to changeLeft restriction\n";
1277 const MSLane* oncomingLane = isOpposite ? source : opposite;
1280 int direction = isOpposite ? -1 : 1;
1281 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1284 double surplusGap = std::numeric_limits<double>::max();
1293 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1295 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1297 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1309 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1315 if (!isOpposite && !oppositeChangeByTraci
1317 && leader.first !=
nullptr) {
1322#ifdef DEBUG_CHANGE_OPPOSITE
1324 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1330 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1333 }
else if (leader.second < 0) {
1335#ifdef DEBUG_CHANGE_OPPOSITE
1337 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1345 double timeToOvertake = std::numeric_limits<double>::max();
1346 double spaceToOvertake = std::numeric_limits<double>::max();
1347 double maxSpaceToOvertake = 0;
1349 if (oppositeChangeByTraci) {
1359 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1360 overtaken = neighLead;
1362 if (overtaken.first !=
nullptr) {
1365#ifdef DEBUG_CHANGE_OPPOSITE
1367 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1368 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1369 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1376 if (overtaken.first == 0) {
1379#ifdef DEBUG_CHANGE_OPPOSITE
1381 std::cout <<
" no leader found\n";
1386 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1391#ifdef DEBUG_CHANGE_OPPOSITE
1393 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1401 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1402#ifdef DEBUG_CHANGE_OPPOSITE
1405 <<
" veh=" << vehicle->
getID()
1406 <<
" changeOpposite opposite=" << opposite->
getID()
1408 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1410 <<
" timeToOvertake=" << timeToOvertake
1411 <<
" spaceToOvertake=" << spaceToOvertake
1417#ifdef DEBUG_CHANGE_OPPOSITE
1419 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1427 if (!wait && lastStopped !=
nullptr) {
1429#ifdef DEBUG_CHANGE_OPPOSITE
1431 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1434 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1443 assert(timeToOvertake != std::numeric_limits<double>::max());
1444 assert(spaceToOvertake != std::numeric_limits<double>::max());
1447 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1454 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1457 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1460 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1461 if (oncomingGap > 0) {
1464#ifdef DEBUG_CHANGE_OPPOSITE
1466 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1467 <<
" halting=" << oncoming.first->getWaitingSeconds()
1468 <<
" oncomingGap=" << oncomingGap
1470 <<
" vMax=" << vMax <<
"\n";
1477 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1478#ifdef DEBUG_CHANGE_OPPOSITE
1480 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1481 <<
" timeToOvertake=" << timeToOvertake
1482 <<
" spaceToOvertake=" << spaceToOvertake
1489#ifdef DEBUG_CHANGE_OPPOSITE
1491 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1499#ifdef DEBUG_CHANGE_OPPOSITE
1501 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1506 assert(timeToOvertake != std::numeric_limits<double>::max());
1507 assert(spaceToOvertake != std::numeric_limits<double>::max());
1511 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1512 if (oncomingOpposite.first !=
nullptr) {
1513 double oncomingSpeed2;
1514 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1516 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1517#ifdef DEBUG_CHANGE_OPPOSITE
1519 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1522 surplusGap =
MIN2(surplusGap, surplusGap2);
1523 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1524 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1525 && oncomingOpposite.second > oncoming.second) {
1529 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1532 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1533 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1534 double ooTTO = ooSTO / oSpeed;
1536 ooTTO = ceil(ooTTO /
TS) *
TS;
1537 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1538#ifdef DEBUG_CHANGE_OPPOSITE
1540 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1543 surplusGap =
MIN2(surplusGap, surplusGap3);
1546 if (!isOpposite && surplusGap < 0) {
1547#ifdef DEBUG_CHANGE_OPPOSITE
1549 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1553#ifdef DEBUG_CHANGE_OPPOSITE
1555 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1556 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1568 if (usableDist < spaceToOvertake) {
1571 assert(bestLaneConts.size() >= 1);
1572 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1573 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1574#ifdef DEBUG_CHANGE_OPPOSITE
1576 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1585 const MSLane*
const prev = *(it - 1);
1586 if (prev !=
nullptr) {
1595#ifdef DEBUG_CHANGE_OPPOSITE
1597 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1603 usableDist += (*it)->getLength();
1607 if (!isOpposite && usableDist < spaceToOvertake) {
1608#ifdef DEBUG_CHANGE_OPPOSITE
1610 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1619 bool foundHill = vehicle->
getSlope() > 0;
1624#ifdef DEBUG_CHANGE_OPPOSITE
1626 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1631 double oppositeLength = vehicle->
getBestLanes().back().length;
1634 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1635 leader.first =
nullptr;
1636 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1638 neighLead.first =
nullptr;
1642#ifdef DEBUG_CHANGE_OPPOSITE
1644 std::cout <<
" not changing to avoid deadlock\n";
1649 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1655 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1663 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1669 std::pair<MSVehicle*, double> neighLead,
1670 std::pair<MSVehicle*, double> overtaken,
1671 std::pair<MSVehicle*, double> leader) {
1673#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1675 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1682 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1684 }
else if (!neighLead.first->isStopped()
1688 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1689 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1690 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1691#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1693 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1696 if (neighLead.first ==
nullptr) {
1703 if (neighLead.first->isStopped()
1704 && (overtaken.first->isStopped()
1705 || leader.first->getLaneChangeModel().isOpposite()
1710 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1711 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1713 const double distToStop = neighLead.second - requiredGap;
1717 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1718 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1719 if (neighStoppedBack + nextGap > overtaken.second) {
1722 neighStoppedBack += nextGap;
1723 auto neighLeadFollow = neighLead.first->getFollower();
1724 neighLead.second = neighLeadFollow.second;
1725 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1726#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1731 if (neighStoppedBack > overtaken.second) {
1736 const double leaderBGap = leader.first->
getBrakeGap();
1737 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1738 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1740#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1742 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1743 <<
" neighLeadGap=" << neighLead.second
1744 <<
" leaderGap=" << leader.second
1745 <<
" bGap=" << leaderBGap
1746 <<
" fGap=" << leaderFGap
1747 <<
" eGap=" << extraGap
1748 <<
" neighStoppedBack=" << neighStoppedBack
1750 <<
" requiredGap=" << requiredGap
1751 <<
" gapWithEgo=" << gapWithEgo
1752 <<
" yield=" << yield
1757 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1758 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1759 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1761#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1763 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1766 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1767 const double blockerLength = currentDist - stopPos;
1769#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1771 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1772 <<
" blockerLength=" << blockerLength
1773 <<
" reserved=" << reserved
1791 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1793 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1794 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1795 follower = follower.first->getFollower(dist);
1797 if (follower.first !=
nullptr) {
1798 followerGap += follower.second;
1800#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1802 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1803 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1807 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1815 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1816 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1817 follower = follower.first->getFollower(dist);
1819#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1820 if (
DEBUG_COND && follower.first !=
nullptr) {
1821 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1822 <<
" oncoming=" << follower.first->getID()
1823 <<
" wait=" << follower.first->getWaitingSeconds()
1829 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1838 std::pair<MSVehicle* const, double> leader,
1839 std::pair<MSVehicle*, double> neighLead,
1840 std::pair<MSVehicle*, double> overtaken) {
1841 const double deadLockZone = overtaken.second;
1842#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1846 <<
" gap=" << leader.second
1855 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1856#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1858 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1859 <<
" leader=" << leader.first->getID()
1860 <<
" leaderGap=" << leader.second
1862 <<
" deadLockZone=" << deadLockZone
1866 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1869 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1870 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1871 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1872#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1874 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1879 if (oncomingOpposite.first !=
nullptr ||
1880 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1882 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1883 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1887#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1889 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1890 <<
" leader=" << leader.first->getID()
1891 <<
" leaderGap=" << leader.second
1893 <<
" currentDist=" << currentDist
1894 <<
" blockerLength=" << blockerLength
1895 <<
" reserved=" << reserved
1910 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1911 std::pair<MSVehicle*, double> neighLead,
1912 std::pair<MSVehicle*, double> overtaken,
1913 std::pair<MSVehicle*, double> neighFollow,
1914 double surplusGap,
const MSLane* opposite,
1924 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1926 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1927#ifdef DEBUG_CHANGE_OPPOSITE
1929 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1933 const MSVehicle* oncomingVeh = oncoming.first;
1934 if (oncomingVeh != 0) {
1936 double egoSpeedFraction = 0.5;
1937 if (oncomingSpeed > 0) {
1938 egoSpeedFraction =
MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1940 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1941#ifdef DEBUG_CHANGE_OPPOSITE
1943 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1944 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1948#ifdef DEBUG_CHANGE_OPPOSITE
1950 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1954 if (neighLead.first !=
nullptr) {
1955 if (overtaken.first ==
nullptr) {
1956#ifdef DEBUG_CHANGE_OPPOSITE
1958 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1961 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
1962 && neighLead.second > 0
1963 && neighFollow.second > 0
1966 oppositeLength = forwardPos + neighLead.second;
1968 if (surplusGap > 0) {
1971 oppositeLength += 1000;
1974 if (overtaken.second > 0) {
1975 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1980#ifdef DEBUG_CHANGE_OPPOSITE
1982 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1983 <<
" surplusGap=" << surplusGap
1984 <<
" final laneQLength=" << oppositeLength
1991 if (overtaken.first ==
nullptr || !canOvertake) {
1994 if (oppFollow.first ==
nullptr) {
1995 oppositeLength = forwardPos;
1997 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1999#ifdef DEBUG_CHANGE_OPPOSITE
2001 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
2004 if (oppFollow.second > secureGap) {
2006 oppositeLength = forwardPos;
2011#ifdef DEBUG_CHANGE_OPPOSITE
2013 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
2016 return oppositeLength;
2020std::pair<MSVehicle* const, double>
2023 double gap = oncoming.second;
2024 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
2025 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
2027 gap += oncoming.first->getVehicleType().getLengthWithGap();
2028 if (oncoming.first != overtaken) {
2029 vMax =
MIN2(vMax, oncoming.first->getSpeed());
2031#ifdef DEBUG_CHANGE_OPPOSITE
2033 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
2034 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
2037 if (searchDist < 0) {
2041 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2042 opposite = oncoming.first->getLane();
2044 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2045 if (oncoming.first !=
nullptr) {
2046 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2047#ifdef DEBUG_CHANGE_OPPOSITE
2049 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
2054 oncoming.second = gap;
2059std::pair<MSVehicle* const, double>
2063 if (overtaken.first !=
nullptr) {
2065 front = overtaken.first;
2073 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2075 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2076 conts.erase(conts.begin());
2079 if (oncoming.first !=
nullptr) {
2080 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2081 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2082#ifdef DEBUG_CHANGE_OPPOSITE
2085 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2086 <<
" oncomingOpposite=" << oncoming.first->getID()
2087 <<
" gap=" << oncoming.second
2088 <<
" isOpposite=" << isOpposite
2093 if (isOpposite && shadowLane != front->
getLane()) {
2095 oncoming.second -= oncoming.first->getVehicleType().getLength();
2096 oncoming.second += gap;
2100 return std::make_pair(
nullptr, -1);
2106 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2107 double surplusGap = std::numeric_limits<double>::max();
2108 const MSVehicle* oncomingVeh = oncoming.first;
2109 if (oncomingVeh != 0 && (oncomingOpposite
2120 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2121#ifdef DEBUG_CHANGE_OPPOSITE
2124 <<
" oncoming=" << oncomingVeh->
getID()
2125 <<
" oGap=" << oncoming.second
2126 <<
" oSpeed=" << oncomingSpeed
2127 <<
" sto=" << spaceToOvertake
2128 <<
" tto=" << timeToOvertake
2129 <<
" safetyGap=" << safetyGap
2130 <<
" surplusGap=" << surplusGap
2140 if (view >= (
int)bestLanes.size()) {
2143 MSLane* lane = bestLanes[view];
2144 double laneDist = 0;
2146 double lastZ = lastMax;
2147 for (
int i = 1; i < (int)shape.size(); i++) {
2150 if (laneDist > pos) {
2151 const double z = shape[i].z();
2159#ifdef DEBUG_CHANGE_OPPOSITE
2161 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2164 if (foundHill && z < lastMax) {
2165 const double drop = lastMax - z;
2167 if (drop > hilltopThreshold) {
2168#ifdef DEBUG_CHANGE_OPPOSITE
2170 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2171 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2180 searchDist -= laneDist - pos;
2183 if (searchDist <= 0) {
2188 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2197 const std::pair<MSVehicle* const, double>& leader,
2198 const std::pair<MSVehicle* const, double>& neighLead,
2199 const std::pair<MSVehicle* const, double>& neighFollow,
2200 const std::vector<MSVehicle::LaneQ>& preb) {
2203 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2204 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2206 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2212#ifdef DEBUG_CHANGE_OPPOSITE
2214 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2223#ifdef DEBUG_CHANGE_OPPOSITE
2225 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2242 const double v = vehicle->
getSpeed();
2246 const double g =
MAX2(0.0, (
2257 const double sign = -1;
2261 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2262#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2264 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2265 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2272 timeToOvertake = std::numeric_limits<double>::max();
2273 spaceToOvertake = std::numeric_limits<double>::max();
2281 t = ceil(t /
TS) *
TS;
2285 const double timeToMaxSpeed = (vMax - v) / a;
2287#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2289 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2292 if (t <= timeToMaxSpeed) {
2294 spaceToOvertake = v * t + t * t * a * 0.5;
2295#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2297 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2302 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2303 const double m = timeToMaxSpeed;
2306 t = (g - s + m * vMax) / (vMax - u);
2309#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2311 std::cout <<
" t2=" << t <<
"\n";
2314 timeToOvertake = std::numeric_limits<double>::max();
2315 spaceToOvertake = std::numeric_limits<double>::max();
2322 t = ceil(t /
TS) *
TS;
2325 spaceToOvertake = s + (t - m) * vMax;
2326#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2328 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2334 timeToOvertake *= safetyFactor;
2336 spaceToOvertake *= safetyFactor;
2338 double frac = fmod(timeToOvertake,
TS);
2341 timeToOvertake +=
TS - frac;
2343#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2345 if (safetyFactor != 1) {
2346 std::cout <<
" applying safetyFactor=" << safetyFactor
2348 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2356std::pair<MSVehicle*, double>
2358 assert(leader.first != 0);
2364 std::pair<MSVehicle*, double> columnLeader = leader;
2365 double egoGap = leader.second;
2366 bool foundSpaceAhead =
false;
2367 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2369 if (maxLookAhead == std::numeric_limits<double>::max()) {
2370 maxLookAhead = (isEmergency
2373 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2375 + leader.first->getVehicleType().getLengthWithGap());
2377#ifdef DEBUG_CHANGE_OPPOSITE
2379 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2383 while (!foundSpaceAhead) {
2384 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2385 columnLeader.first, vehicle,
2387 + columnLeader.first->getVehicleType().getMinGap()
2392 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2393 double searchStart = columnLeader.first->getPositionOnLane();
2394 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2395 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2397 std::set<MSVehicle*> seenLeaders;
2398 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2399#ifdef DEBUG_CHANGE_OPPOSITE
2401 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2404 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2405 leadLead.first =
nullptr;
2408 seenLeaders.insert(leadLead.first);
2410 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2411 leadLead = columnLeader.first->getLane()->getLeader(
2412 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2414 leadLead.second += (searchStart2 - searchStart);
2416 if (leadLead.first ==
nullptr) {
2417 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2418 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2419 if (!columnLeader.first->isStopped()) {
2421 requiredSpace += safetyFactor * mergeBrakeGap;
2423#ifdef DEBUG_CHANGE_OPPOSITE
2425 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2426 <<
" availableSpace=" << availableSpace
2427 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2428 <<
" ovSpeed=" << overtakingSpeed
2429 <<
" reqBGap=" << mergeBrakeGap
2430 <<
" reqMin=" << requiredSpace / safetyFactor
2431 <<
" req=" << requiredSpace
2435 if (availableSpace > requiredSpace) {
2436 foundSpaceAhead =
true;
2440 bool contsEnd =
false;
2441 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, isEmergency, contsEnd);
2442#ifdef DEBUG_CHANGE_OPPOSITE
2444 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2447 while (next !=
nullptr && seen < maxLookAhead) {
2450 if (cand ==
nullptr) {
2452 if (availableSpace > requiredSpace) {
2453 foundSpaceAhead =
true;
2456 next =
getLaneAfter(next, conts, isEmergency, contsEnd);
2459 if (availableSpace > requiredSpace) {
2460 foundSpaceAhead =
true;
2467#ifdef DEBUG_CHANGE_OPPOSITE
2469 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2472 if (!foundSpaceAhead && contsEnd) {
2473 foundSpaceAhead =
true;
2474 availableSpace = requiredSpace;
2476 if (!foundSpaceAhead) {
2477 return std::make_pair(
nullptr, -1);
2480 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2483 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2484 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2485 if (!columnLeader.first->isStopped()) {
2487 requiredSpace += safetyFactor * sGap;
2489#ifdef DEBUG_CHANGE_OPPOSITE
2491 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2492 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2493 <<
" ovSpeed=" << overtakingSpeed
2494 <<
" reqSGap=" << sGap
2495 <<
" reqMin=" << requiredSpace / safetyFactor
2496 <<
" req=" << requiredSpace
2500 if (leadLead.second > requiredSpace) {
2501 foundSpaceAhead =
true;
2502 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2505 if (leadLead.second < 0) {
2507#ifdef DEBUG_CHANGE_OPPOSITE
2509 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2512 return std::make_pair(
nullptr, -1);
2515#ifdef DEBUG_CHANGE_OPPOSITE
2517 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2520 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2521 if (seen > maxLookAhead) {
2522#ifdef DEBUG_CHANGE_OPPOSITE
2524 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2527 return std::make_pair(
nullptr, -1);
2530 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2531 columnLeader = leadLead;
2532#ifdef DEBUG_CHANGE_OPPOSITE
2534 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2540 columnLeader.second = egoGap;
2541 return columnLeader;
2547 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2549 if (it + 1 != conts.end()) {
2551 const MSLane* next = *(it + 1);
2553 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2571 const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
2576std::pair<double, SUMOTime>
2578 assert(index >= 0 && index < (
int)
myChanger.size());
2579 return std::make_pair(
2581 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_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
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)
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
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.
bool havePriority() const
Returns whether this link is a major link.
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.