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)
115 lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
130 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
132 myChanger.back().mayChangeRight = lane != lanes->begin();
133 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
134 if ((*lane)->isInternal()) {
136 if (
myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
139 if (
myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
143 if (
myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
147 if (
myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
169 const bool haveChanged =
change();
176 ce->lane->releaseVehicles();
188 ce->hoppedVeh =
nullptr;
189 ce->lastBlocked =
nullptr;
190 ce->firstBlocked =
nullptr;
191 ce->lastStopped =
nullptr;
193 ce->lastBlockedBackPos = -1;
194 ce->lastBlockedWaitingTime = -1;
195 ce->lane->getVehiclesSecure();
209 if (!vehHasChanged) {
232 ce->lane->swapAfterLaneChange(t);
233 ce->lane->releaseVehicles();
234 if (ce->lastBlocked !=
nullptr) {
235 ce->lastBlockedBackPos = ce->lastBlocked->getBackPositionOnLane();
236 ce->lastBlockedWaitingTime = ce->lastBlocked->getWaitingTime();
247#ifdef DEBUG_CANDIDATE
248 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
252 if (
veh(ce) ==
nullptr) {
255#ifdef DEBUG_CANDIDATE
256 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
260#ifdef DEBUG_CANDIDATE
266 assert(
veh(ce) != 0);
267 assert(
veh(max) != 0);
268 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
269#ifdef DEBUG_CANDIDATE
276 assert(
veh(max) != 0);
283 if (direction == 0) {
290 if (direction == -1) {
291 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingRight(svc);
292 }
else if (direction == 1) {
293 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingLeft(svc);
310#ifdef DEBUG_ACTIONSTEPS
325 myCandi->lastStopped = vehicle;
331#ifdef DEBUG_ACTIONSTEPS
333 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
336 bool changed =
false;
360 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
364 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
375 (
myCandi - 1)->lastBlocked = vehicle;
376 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
377 (
myCandi - 1)->firstBlocked = vehicle;
392 (
myCandi + 1)->lastBlocked = vehicle;
393 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
394 (
myCandi + 1)->firstBlocked = vehicle;
439 <<
" veh=" << vehicle->
getID()
442 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
453 bool changed =
false;
455 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
456 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
464 to->registerHop(vehicle);
486 to->registerHop(vehicle);
487 to->lane->requireCollisionCheck();
508 to->registerHop(vehicle);
512 from->registerHop(vehicle);
513 from->lane->requireCollisionCheck();
530#ifdef DEBUG_CONTINUE_CHANGE
533 <<
" continueChange veh=" << vehicle->
getID()
535 <<
" dir=" << direction
536 <<
" speedLat=" << speedLat
537 <<
" pastMidpoint=" << pastMidpoint
549std::pair<MSVehicle* const, double>
553#ifdef DEBUG_SURROUNDING_VEHICLES
555 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
561#ifdef DEBUG_SURROUNDING_VEHICLES
563 if (neighLead != 0) {
564 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
570 if (target->hoppedVeh !=
nullptr) {
571 double hoppedPos = target->hoppedVeh->getPositionOnLane();
572#ifdef DEBUG_SURROUNDING_VEHICLES
574 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
578 neighLead = target->hoppedVeh;
583 const bool checkBidi = target->lane->getBidiLane() !=
nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
584 if (neighLead ==
nullptr || checkBidi) {
585#ifdef DEBUG_SURROUNDING_VEHICLES
587 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
592 MSLane* targetLane = target->lane;
594 double leaderBack = targetLane->
getLength();
595 if (neighLead !=
nullptr) {
599 double plBack = pl->getBackPositionOnLane(targetLane);
600 if (pl->isBidiOn(targetLane)) {
601 plBack -= pl->getVehicleType().getLengthWithGap();
603 const double plPos = plBack + pl->getVehicleType().getLength();
604#ifdef DEBUG_SURROUNDING_VEHICLES
606 std::cout <<
" partial=" << pl->getID() <<
" plBack=" << plBack <<
" plPos=" << plPos <<
" leaderBack=" << leaderBack <<
" egoBack=" << egoBack <<
"\n";
609 if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
614 if (neighLead !=
nullptr) {
615#ifdef DEBUG_SURROUNDING_VEHICLES
617 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
621 return std::pair<MSVehicle*, double>(neighLead, gap);
626 if (target->lane->getBidiLane() !=
nullptr) {
627 dist += target->lane->getBidiLane()->getMaximumBrakeDist();
630 if (seen > dist && !
myCandi->lane->isInternal()) {
631#ifdef DEBUG_SURROUNDING_VEHICLES
633 std::cout <<
" found no leader within dist=" << dist <<
"\n";
636 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
640 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
641#ifdef DEBUG_SURROUNDING_VEHICLES
648#ifdef DEBUG_SURROUNDING_VEHICLES
650 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
658std::pair<MSVehicle* const, double>
662#ifdef DEBUG_SURROUNDING_VEHICLES
664 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
670 neighFollow =
veh(target);
673 if (target->lane->myVehicles.size() > 1) {
674 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
678#ifdef DEBUG_SURROUNDING_VEHICLES
680 if (neighFollow != 0) {
681 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
683 std::cout <<
"veh(target) returns none." << std::endl;
689#ifdef DEBUG_SURROUNDING_VEHICLES
691 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
692 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
701#ifdef DEBUG_SURROUNDING_VEHICLES
704 if (partialBehind != 0 && partialBehind != neighFollow) {
705 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
710 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
712 if (neighFollow ==
nullptr) {
714#ifdef DEBUG_SURROUNDING_VEHICLES
716 if (consecutiveFollower.first == 0) {
717 std::cout <<
"no follower found." << std::endl;
719 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
723 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
725#ifdef DEBUG_SURROUNDING_VEHICLES
727 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
730 return std::pair<MSVehicle* const, double>(neighFollow,
754 const std::pair<MSVehicle* const, double>& leader,
755 const std::vector<MSVehicle::LaneQ>& preb)
const {
760 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
763 neighFollow.first = 0;
766 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
773 const std::pair<MSVehicle* const, double>& leader,
774 const std::pair<MSVehicle* const, double>& follower,
775 const std::pair<MSVehicle* const, double>& neighLead,
776 const std::pair<MSVehicle* const, double>& neighFollow,
777 const std::vector<MSVehicle::LaneQ>& preb)
const {
781#ifdef DEBUG_CHECK_CHANGE
784 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
793 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
797#ifdef DEBUG_CHECK_CHANGE
800 <<
" overlapping with follower..."
806 if (neighLead.first !=
nullptr && neighLead.second < 0) {
809#ifdef DEBUG_CHECK_CHANGE
812 <<
" overlapping with leader..."
824 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
832 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
835 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
837#ifdef DEBUG_CHECK_CHANGE
840 <<
" follower=" << neighFollow.first->getID()
841 <<
" backGap=" << neighFollow.second
842 <<
" vNextFollower=" << vNextFollower
843 <<
" vNextEgo=" << vNextLeader
844 <<
" secureGap=" << secureBackGap
852 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
857#ifdef DEBUG_CHECK_CHANGE
859 std::cout <<
" ignoring opposite follower who changed in this step\n";
863 blocked |= blockedByFollower;
869 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
878 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
882#ifdef DEBUG_CHECK_CHANGE
885 <<
" leader=" << neighLead.first->getID()
886 <<
" frontGap=" << neighLead.second
887 <<
" vNextEgo=" << vNextFollower
888 <<
" vNextLeader=" << vNextLeader
889 <<
" secureGap=" << secureFrontGap
896 blocked |= blockedByLeader;
903 if (nextLeader.first != 0) {
907#ifdef DEBUG_CHECK_CHANGE
909 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
912 if (brakeGap > gap) {
913 blocked |= blockedByLeader;
914#ifdef DEBUG_CHECK_CHANGE
916 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
923 if (leader.first !=
nullptr) {
924 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
929 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
938 const double speed = vehicle->
getSpeed();
940 if (seen < dist || myCandi->lane->isInternal()) {
941 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
942 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
944 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
946#ifdef DEBUG_SURROUNDING_VEHICLES
948 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
949 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
952 if (neighLead2.second < secureGap2) {
953 state |= blockedByLeader;
960 double targetZipperDist = 0;
961 if (laneOffset == 0) {
962 targetZipperDist =
myCandi->zipperDist;
963 }
else if (laneOffset == 1) {
965 targetZipperDist = (
myCandi + 1)->zipperDist;
967 }
else if (laneOffset == -1) {
969 targetZipperDist = (
myCandi - 1)->zipperDist;
973 state |= blockedByLeader;
985 if (estimatedLCDuration == -1) {
987#ifdef DEBUG_CHECK_CHANGE
989 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
990 <<
"\nestimatedLCDuration=" << estimatedLCDuration
991 <<
"\ndistToNeighLane=" << distToNeighLane
999 const double avgSpeed = 0.5 * (
1003 const double space2change = avgSpeed * estimatedLCDuration;
1006#ifdef DEBUG_CHECK_CHANGE
1008 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
1009 <<
"\ndistToNeighLane=" << distToNeighLane
1010 <<
" estimatedLCDuration=" << estimatedLCDuration
1011 <<
" space2change=" << space2change
1012 <<
" avgSpeed=" << avgSpeed
1021 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1022 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
1026 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
1031 if ((*link)->getViaLane() ==
nullptr) {
1034 nextLane = (*link)->getViaLaneOrLane();
1039#ifdef DEBUG_CHECK_CHANGE
1041 std::cout <<
" available distance=" << seen << std::endl;
1044 if (nextLane->
isLinkEnd(link) && seen < space2change) {
1045#ifdef DEBUG_CHECK_CHANGE
1047 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1056 const double speed = vehicle->
getSpeed();
1058 nextLane = vehicle->
getLane();
1061 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1062 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1063 nextLane = (*nextLink)->getViaLaneOrLane();
1065 if (parallelLane ==
nullptr) {
1069 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1070 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1072 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1073 state |= blockedByLeader;
1077 if ((*nextLink)->getViaLane() ==
nullptr) {
1087 const int oldstate = state;
1091#ifdef DEBUG_CHECK_CHANGE
1094 <<
" veh=" << vehicle->
getID()
1114 if (laneOffset != 0) {
1136 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1137 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1140 const int bestOffset = preb[laneIndex].bestLaneOffset;
1151 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1155 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1163 double oncomingSpeed;
1164 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1165 if (!isOpposite && surplusGap < 0) {
1166#ifdef DEBUG_CHANGE_OPPOSITE
1168 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1169 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1175 if (bestOffset > 0) {
1176 MSLane*
const target = preb[laneIndex + 1].lane;
1188std::vector<MSVehicle::LaneQ>
1195 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1196 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1197 for (
int i = 0; i < numOpposite; i++) {
1198 preb.push_back(preb.back());
1199 preb.back().lane = oLanes[numOpposite - 1 - i];
1200 preb.back().length = oppositeLength;
1202 preb.back().bestLaneOffset = -1 - i;
1206 if (stopLane !=
nullptr) {
1207 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1208 for (
int i = 0; i < (int)preb.size(); i++) {
1209 preb[i].bestLaneOffset = stopIndex - i;
1214#ifdef DEBUG_CHANGE_OPPOSITE
1216 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1217 for (
int i = 0; i < (int)preb.size(); i++) {
1218 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1236#ifdef DEBUG_CHANGE_OPPOSITE
1239 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1244 if (opposite ==
nullptr) {
1254 bool oppositeChangeByTraci =
false;
1257 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1261 oppositeChangeByTraci =
true;
1265#ifdef DEBUG_CHANGE_OPPOSITE
1267 std::cout <<
" not overtaking due to changeLeft restriction\n";
1278 const MSLane* oncomingLane = isOpposite ? source : opposite;
1281 int direction = isOpposite ? -1 : 1;
1282 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1285 double surplusGap = std::numeric_limits<double>::max();
1294 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1296 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1298 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1310 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1316 if (!isOpposite && !oppositeChangeByTraci
1318 && leader.first !=
nullptr) {
1323#ifdef DEBUG_CHANGE_OPPOSITE
1325 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1331 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1334 }
else if (leader.second < 0) {
1336#ifdef DEBUG_CHANGE_OPPOSITE
1338 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1346 double timeToOvertake = std::numeric_limits<double>::max();
1347 double spaceToOvertake = std::numeric_limits<double>::max();
1348 double maxSpaceToOvertake = 0;
1350 if (oppositeChangeByTraci) {
1360 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1361 overtaken = neighLead;
1363 if (overtaken.first !=
nullptr) {
1366#ifdef DEBUG_CHANGE_OPPOSITE
1368 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1369 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1370 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1377 if (overtaken.first == 0) {
1380#ifdef DEBUG_CHANGE_OPPOSITE
1382 std::cout <<
" no leader found\n";
1387 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1392#ifdef DEBUG_CHANGE_OPPOSITE
1394 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1402 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1403#ifdef DEBUG_CHANGE_OPPOSITE
1406 <<
" veh=" << vehicle->
getID()
1407 <<
" changeOpposite opposite=" << opposite->
getID()
1409 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1411 <<
" timeToOvertake=" << timeToOvertake
1412 <<
" spaceToOvertake=" << spaceToOvertake
1418#ifdef DEBUG_CHANGE_OPPOSITE
1420 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1428 if (!wait && lastStopped !=
nullptr) {
1430#ifdef DEBUG_CHANGE_OPPOSITE
1432 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1435 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1444 assert(timeToOvertake != std::numeric_limits<double>::max());
1445 assert(spaceToOvertake != std::numeric_limits<double>::max());
1448 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1455 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1458 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1461 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1462 if (oncomingGap > 0) {
1465#ifdef DEBUG_CHANGE_OPPOSITE
1467 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1468 <<
" halting=" << oncoming.first->getWaitingSeconds()
1469 <<
" oncomingGap=" << oncomingGap
1471 <<
" vMax=" << vMax <<
"\n";
1478 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1479#ifdef DEBUG_CHANGE_OPPOSITE
1481 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1482 <<
" timeToOvertake=" << timeToOvertake
1483 <<
" spaceToOvertake=" << spaceToOvertake
1490#ifdef DEBUG_CHANGE_OPPOSITE
1492 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1500#ifdef DEBUG_CHANGE_OPPOSITE
1502 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1507 assert(timeToOvertake != std::numeric_limits<double>::max());
1508 assert(spaceToOvertake != std::numeric_limits<double>::max());
1512 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1513 if (oncomingOpposite.first !=
nullptr) {
1514 double oncomingSpeed2;
1515 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1517 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1518#ifdef DEBUG_CHANGE_OPPOSITE
1520 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1523 surplusGap =
MIN2(surplusGap, surplusGap2);
1524 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1525 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1526 && oncomingOpposite.second > oncoming.second) {
1530 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1533 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1534 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1535 double ooTTO = ooSTO / oSpeed;
1537 ooTTO = ceil(ooTTO /
TS) *
TS;
1538 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1539#ifdef DEBUG_CHANGE_OPPOSITE
1541 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1544 surplusGap =
MIN2(surplusGap, surplusGap3);
1547 if (!isOpposite && surplusGap < 0) {
1548#ifdef DEBUG_CHANGE_OPPOSITE
1550 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1554#ifdef DEBUG_CHANGE_OPPOSITE
1556 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1557 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1569 if (usableDist < spaceToOvertake) {
1572 assert(bestLaneConts.size() >= 1);
1573 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1574 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1575#ifdef DEBUG_CHANGE_OPPOSITE
1577 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1586 const MSLane*
const prev = *(it - 1);
1587 if (prev !=
nullptr) {
1596#ifdef DEBUG_CHANGE_OPPOSITE
1598 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1604 usableDist += (*it)->getLength();
1608 if (!isOpposite && usableDist < spaceToOvertake) {
1609#ifdef DEBUG_CHANGE_OPPOSITE
1611 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1620 bool foundHill = vehicle->
getSlope() > 0;
1625#ifdef DEBUG_CHANGE_OPPOSITE
1627 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1632 double oppositeLength = vehicle->
getBestLanes().back().length;
1635 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1636 leader.first =
nullptr;
1637 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1639 neighLead.first =
nullptr;
1643#ifdef DEBUG_CHANGE_OPPOSITE
1645 std::cout <<
" not changing to avoid deadlock\n";
1650 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1656 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1664 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1670 std::pair<MSVehicle*, double> neighLead,
1671 std::pair<MSVehicle*, double> overtaken,
1672 std::pair<MSVehicle*, double> leader) {
1674#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1676 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1683 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1685 }
else if (!neighLead.first->isStopped()
1689 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1690 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1691 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1692#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1694 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1697 if (neighLead.first ==
nullptr) {
1704 if (neighLead.first->isStopped()
1705 && (overtaken.first->isStopped()
1706 || leader.first->getLaneChangeModel().isOpposite()
1711 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1712 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1714 const double distToStop = neighLead.second - requiredGap;
1718 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1719 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1720 if (neighStoppedBack + nextGap > overtaken.second) {
1723 neighStoppedBack += nextGap;
1724 auto neighLeadFollow = neighLead.first->getFollower();
1725 neighLead.second = neighLeadFollow.second;
1726 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1727#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1732 if (neighStoppedBack > overtaken.second) {
1737 const double leaderBGap = leader.first->
getBrakeGap();
1738 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1739 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1741#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1743 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1744 <<
" neighLeadGap=" << neighLead.second
1745 <<
" leaderGap=" << leader.second
1746 <<
" bGap=" << leaderBGap
1747 <<
" fGap=" << leaderFGap
1748 <<
" eGap=" << extraGap
1749 <<
" neighStoppedBack=" << neighStoppedBack
1751 <<
" requiredGap=" << requiredGap
1752 <<
" gapWithEgo=" << gapWithEgo
1753 <<
" yield=" << yield
1758 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1759 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1760 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1762#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1764 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1767 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1768 const double blockerLength = currentDist - stopPos;
1770#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1772 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1773 <<
" blockerLength=" << blockerLength
1774 <<
" reserved=" << reserved
1792 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1794 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1795 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1796 follower = follower.first->getFollower(dist);
1798 if (follower.first !=
nullptr) {
1799 followerGap += follower.second;
1801#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1803 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1804 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1808 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1816 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1817 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1818 follower = follower.first->getFollower(dist);
1820#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1821 if (
DEBUG_COND && follower.first !=
nullptr) {
1822 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1823 <<
" oncoming=" << follower.first->getID()
1824 <<
" wait=" << follower.first->getWaitingSeconds()
1830 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1839 std::pair<MSVehicle* const, double> leader,
1840 std::pair<MSVehicle*, double> neighLead,
1841 std::pair<MSVehicle*, double> overtaken) {
1842 const double deadLockZone = overtaken.second;
1843#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1847 <<
" gap=" << leader.second
1856 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1857#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1859 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1860 <<
" leader=" << leader.first->getID()
1861 <<
" leaderGap=" << leader.second
1863 <<
" deadLockZone=" << deadLockZone
1867 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1870 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1871 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1872 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1873#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1875 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1880 if (oncomingOpposite.first !=
nullptr ||
1881 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1883 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1884 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1888#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1890 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1891 <<
" leader=" << leader.first->getID()
1892 <<
" leaderGap=" << leader.second
1894 <<
" currentDist=" << currentDist
1895 <<
" blockerLength=" << blockerLength
1896 <<
" reserved=" << reserved
1911 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1912 std::pair<MSVehicle*, double> neighLead,
1913 std::pair<MSVehicle*, double> overtaken,
1914 std::pair<MSVehicle*, double> neighFollow,
1915 double surplusGap,
const MSLane* opposite,
1925 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1927 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1928#ifdef DEBUG_CHANGE_OPPOSITE
1930 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1934 const MSVehicle* oncomingVeh = oncoming.first;
1935 if (oncomingVeh != 0) {
1937 double egoSpeedFraction = 0.5;
1938 if (oncomingSpeed > 0) {
1939 egoSpeedFraction =
MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1941 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1942#ifdef DEBUG_CHANGE_OPPOSITE
1944 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1945 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1949#ifdef DEBUG_CHANGE_OPPOSITE
1951 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1955 if (neighLead.first !=
nullptr) {
1956 if (overtaken.first ==
nullptr) {
1957#ifdef DEBUG_CHANGE_OPPOSITE
1959 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1962 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
1963 && neighLead.second > 0
1964 && neighFollow.second > 0
1967 oppositeLength = forwardPos + neighLead.second;
1969 if (surplusGap > 0) {
1972 oppositeLength += 1000;
1975 if (overtaken.second > 0) {
1976 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1981#ifdef DEBUG_CHANGE_OPPOSITE
1983 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1984 <<
" surplusGap=" << surplusGap
1985 <<
" final laneQLength=" << oppositeLength
1992 if (overtaken.first ==
nullptr || !canOvertake) {
1995 if (oppFollow.first ==
nullptr) {
1996 oppositeLength = forwardPos;
1998 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
2000#ifdef DEBUG_CHANGE_OPPOSITE
2002 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
2005 if (oppFollow.second > secureGap) {
2007 oppositeLength = forwardPos;
2012#ifdef DEBUG_CHANGE_OPPOSITE
2014 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
2017 return oppositeLength;
2021std::pair<MSVehicle* const, double>
2024 double gap = oncoming.second;
2025 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
2026 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
2028 gap += oncoming.first->getVehicleType().getLengthWithGap();
2029 if (oncoming.first != overtaken) {
2030 vMax =
MIN2(vMax, oncoming.first->getSpeed());
2032#ifdef DEBUG_CHANGE_OPPOSITE
2034 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
2035 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
2038 if (searchDist < 0) {
2042 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2043 opposite = oncoming.first->getLane();
2045 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2046 if (oncoming.first !=
nullptr) {
2047 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2048#ifdef DEBUG_CHANGE_OPPOSITE
2050 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
2055 oncoming.second = gap;
2060std::pair<MSVehicle* const, double>
2064 if (overtaken.first !=
nullptr) {
2066 front = overtaken.first;
2074 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2076 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2077 conts.erase(conts.begin());
2080 if (oncoming.first !=
nullptr) {
2081 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2082 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2083#ifdef DEBUG_CHANGE_OPPOSITE
2086 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2087 <<
" oncomingOpposite=" << oncoming.first->getID()
2088 <<
" gap=" << oncoming.second
2089 <<
" isOpposite=" << isOpposite
2094 if (isOpposite && shadowLane != front->
getLane()) {
2096 oncoming.second -= oncoming.first->getVehicleType().getLength();
2097 oncoming.second += gap;
2101 return std::make_pair(
nullptr, -1);
2107 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2108 double surplusGap = std::numeric_limits<double>::max();
2109 const MSVehicle* oncomingVeh = oncoming.first;
2110 if (oncomingVeh != 0 && (oncomingOpposite
2121 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2122#ifdef DEBUG_CHANGE_OPPOSITE
2125 <<
" oncoming=" << oncomingVeh->
getID()
2126 <<
" oGap=" << oncoming.second
2127 <<
" oSpeed=" << oncomingSpeed
2128 <<
" sto=" << spaceToOvertake
2129 <<
" tto=" << timeToOvertake
2130 <<
" safetyGap=" << safetyGap
2131 <<
" surplusGap=" << surplusGap
2141 if (view >= (
int)bestLanes.size()) {
2144 MSLane* lane = bestLanes[view];
2145 double laneDist = 0;
2147 double lastZ = lastMax;
2148 for (
int i = 1; i < (int)shape.size(); i++) {
2151 if (laneDist > pos) {
2152 const double z = shape[i].z();
2160#ifdef DEBUG_CHANGE_OPPOSITE
2162 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2165 if (foundHill && z < lastMax) {
2166 const double drop = lastMax - z;
2168 if (drop > hilltopThreshold) {
2169#ifdef DEBUG_CHANGE_OPPOSITE
2171 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2172 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2181 searchDist -= laneDist - pos;
2184 if (searchDist <= 0) {
2189 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2198 const std::pair<MSVehicle* const, double>& leader,
2199 const std::pair<MSVehicle* const, double>& neighLead,
2200 const std::pair<MSVehicle* const, double>& neighFollow,
2201 const std::vector<MSVehicle::LaneQ>& preb) {
2204 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2205 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2207 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2213#ifdef DEBUG_CHANGE_OPPOSITE
2215 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2224#ifdef DEBUG_CHANGE_OPPOSITE
2226 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2243 const double v = vehicle->
getSpeed();
2247 const double g =
MAX2(0.0, (
2258 const double sign = -1;
2262 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2263#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2265 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2266 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2273 timeToOvertake = std::numeric_limits<double>::max();
2274 spaceToOvertake = std::numeric_limits<double>::max();
2282 t = ceil(t /
TS) *
TS;
2286 const double timeToMaxSpeed = (vMax - v) / a;
2288#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2290 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2293 if (t <= timeToMaxSpeed) {
2295 spaceToOvertake = v * t + t * t * a * 0.5;
2296#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2298 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2303 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2304 const double m = timeToMaxSpeed;
2307 t = (g - s + m * vMax) / (vMax - u);
2310#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2312 std::cout <<
" t2=" << t <<
"\n";
2315 timeToOvertake = std::numeric_limits<double>::max();
2316 spaceToOvertake = std::numeric_limits<double>::max();
2323 t = ceil(t /
TS) *
TS;
2326 spaceToOvertake = s + (t - m) * vMax;
2327#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2329 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2335 timeToOvertake *= safetyFactor;
2337 spaceToOvertake *= safetyFactor;
2339 double frac = fmod(timeToOvertake,
TS);
2342 timeToOvertake +=
TS - frac;
2344#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2346 if (safetyFactor != 1) {
2347 std::cout <<
" applying safetyFactor=" << safetyFactor
2349 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2357std::pair<MSVehicle*, double>
2359 assert(leader.first != 0);
2365 std::pair<MSVehicle*, double> columnLeader = leader;
2366 double egoGap = leader.second;
2367 bool foundSpaceAhead =
false;
2368 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2370 if (maxLookAhead == std::numeric_limits<double>::max()) {
2371 maxLookAhead = (isEmergency
2374 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2376 + leader.first->getVehicleType().getLengthWithGap());
2378#ifdef DEBUG_CHANGE_OPPOSITE
2380 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2384 while (!foundSpaceAhead) {
2385 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2386 columnLeader.first, vehicle,
2388 + columnLeader.first->getVehicleType().getMinGap()
2393 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2394 double searchStart = columnLeader.first->getPositionOnLane();
2395 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2396 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2398 std::set<MSVehicle*> seenLeaders;
2399 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2400#ifdef DEBUG_CHANGE_OPPOSITE
2402 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2405 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2406 leadLead.first =
nullptr;
2409 seenLeaders.insert(leadLead.first);
2411 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2412 leadLead = columnLeader.first->getLane()->getLeader(
2413 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2415 leadLead.second += (searchStart2 - searchStart);
2417 if (leadLead.first ==
nullptr) {
2418 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2419 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2420 if (!columnLeader.first->isStopped()) {
2422 requiredSpace += safetyFactor * mergeBrakeGap;
2424#ifdef DEBUG_CHANGE_OPPOSITE
2426 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2427 <<
" availableSpace=" << availableSpace
2428 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2429 <<
" ovSpeed=" << overtakingSpeed
2430 <<
" reqBGap=" << mergeBrakeGap
2431 <<
" reqMin=" << requiredSpace / safetyFactor
2432 <<
" req=" << requiredSpace
2436 if (availableSpace > requiredSpace) {
2437 foundSpaceAhead =
true;
2441 bool contsEnd =
false;
2442 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, isEmergency, contsEnd);
2443#ifdef DEBUG_CHANGE_OPPOSITE
2445 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2448 while (next !=
nullptr && seen < maxLookAhead) {
2451 if (cand ==
nullptr) {
2453 if (availableSpace > requiredSpace) {
2454 foundSpaceAhead =
true;
2457 next =
getLaneAfter(next, conts, isEmergency, contsEnd);
2460 if (availableSpace > requiredSpace) {
2461 foundSpaceAhead =
true;
2468#ifdef DEBUG_CHANGE_OPPOSITE
2470 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2473 if (!foundSpaceAhead && contsEnd) {
2474 foundSpaceAhead =
true;
2475 availableSpace = requiredSpace;
2477 if (!foundSpaceAhead) {
2478 return std::make_pair(
nullptr, -1);
2481 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2484 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2485 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2486 if (!columnLeader.first->isStopped()) {
2488 requiredSpace += safetyFactor * sGap;
2490#ifdef DEBUG_CHANGE_OPPOSITE
2492 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2493 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2494 <<
" ovSpeed=" << overtakingSpeed
2495 <<
" reqSGap=" << sGap
2496 <<
" reqMin=" << requiredSpace / safetyFactor
2497 <<
" req=" << requiredSpace
2501 if (leadLead.second > requiredSpace) {
2502 foundSpaceAhead =
true;
2503 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2506 if (leadLead.second < 0) {
2508#ifdef DEBUG_CHANGE_OPPOSITE
2510 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2513 return std::make_pair(
nullptr, -1);
2516#ifdef DEBUG_CHANGE_OPPOSITE
2518 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2521 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2522 if (seen > maxLookAhead) {
2523#ifdef DEBUG_CHANGE_OPPOSITE
2525 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2528 return std::make_pair(
nullptr, -1);
2531 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2532 columnLeader = leadLead;
2533#ifdef DEBUG_CHANGE_OPPOSITE
2535 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2541 columnLeader.second = egoGap;
2542 return columnLeader;
2548 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2550 if (it + 1 != conts.end()) {
2552 const MSLane* next = *(it + 1);
2554 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2572 const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
2577std::pair<double, SUMOTime>
2579 assert(index >= 0 && index < (
int)
myChanger.size());
2580 return std::make_pair(
2582 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.