44#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0
45#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR 0.0
46#define OPPOSITE_OVERTAKING_SAFETY_FACTOR 1.2
48#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0
49#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0
51#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 1000.0
53#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE 1000.0
54#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD 5
57#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT 1
73#define DEBUG_COND (vehicle->isSelected())
86 firstBlocked(nullptr),
88 ahead(_lane->getWidth()),
89 aheadNext(_lane->getWidth(), nullptr, 0.) {
95 lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
110 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
112 myChanger.back().mayChangeRight = lane != lanes->begin();
113 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
114 if ((*lane)->isInternal()) {
116 if (
myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
119 if (
myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
123 if (
myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
127 if (
myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
149 const bool haveChanged =
change();
156 ce->lane->releaseVehicles();
168 ce->hoppedVeh =
nullptr;
169 ce->lastBlocked =
nullptr;
170 ce->firstBlocked =
nullptr;
171 ce->lastStopped =
nullptr;
173 ce->lane->getVehiclesSecure();
187 if (!vehHasChanged) {
210 ce->lane->swapAfterLaneChange(t);
211 ce->lane->releaseVehicles();
221#ifdef DEBUG_CANDIDATE
222 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
226 if (
veh(ce) ==
nullptr) {
229#ifdef DEBUG_CANDIDATE
230 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
234#ifdef DEBUG_CANDIDATE
240 assert(
veh(ce) != 0);
241 assert(
veh(max) != 0);
242 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
243#ifdef DEBUG_CANDIDATE
250 assert(
veh(max) != 0);
257 if (direction == 0) {
264 if (direction == -1) {
265 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingRight(svc);
266 }
else if (direction == 1) {
267 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingLeft(svc);
284#ifdef DEBUG_ACTIONSTEPS
299 myCandi->lastStopped = vehicle;
305#ifdef DEBUG_ACTIONSTEPS
307 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
310 bool changed =
false;
334 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
338 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
349 (
myCandi - 1)->lastBlocked = vehicle;
350 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
351 (
myCandi - 1)->firstBlocked = vehicle;
366 (
myCandi + 1)->lastBlocked = vehicle;
367 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
368 (
myCandi + 1)->firstBlocked = vehicle;
413 <<
" veh=" << vehicle->
getID()
416 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
427 bool changed =
false;
429 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
430 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
438 to->registerHop(vehicle);
460 to->registerHop(vehicle);
461 to->lane->requireCollisionCheck();
482 to->registerHop(vehicle);
486 from->registerHop(vehicle);
487 from->lane->requireCollisionCheck();
504#ifdef DEBUG_CONTINUE_CHANGE
507 <<
" continueChange veh=" << vehicle->
getID()
509 <<
" dir=" << direction
510 <<
" speedLat=" << speedLat
511 <<
" pastMidpoint=" << pastMidpoint
523std::pair<MSVehicle* const, double>
527#ifdef DEBUG_SURROUNDING_VEHICLES
529 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
535#ifdef DEBUG_SURROUNDING_VEHICLES
537 if (neighLead != 0) {
538 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
544 if (target->hoppedVeh !=
nullptr) {
545 double hoppedPos = target->hoppedVeh->getPositionOnLane();
546#ifdef DEBUG_SURROUNDING_VEHICLES
548 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
552 neighLead = target->hoppedVeh;
556 if (neighLead ==
nullptr) {
557#ifdef DEBUG_SURROUNDING_VEHICLES
559 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
564 MSLane* targetLane = target->lane;
566 double leaderBack = targetLane->
getLength();
569 if (plBack < leaderBack &&
575 if (neighLead !=
nullptr) {
576#ifdef DEBUG_SURROUNDING_VEHICLES
578 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
587 if (seen > dist && !
myCandi->lane->isInternal()) {
588#ifdef DEBUG_SURROUNDING_VEHICLES
590 std::cout <<
" found no leader within dist=" << dist <<
"\n";
593 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
597 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
598#ifdef DEBUG_SURROUNDING_VEHICLES
605#ifdef DEBUG_SURROUNDING_VEHICLES
607 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
615std::pair<MSVehicle* const, double>
619#ifdef DEBUG_SURROUNDING_VEHICLES
621 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
627 neighFollow =
veh(target);
630 if (target->lane->myVehicles.size() > 1) {
631 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
635#ifdef DEBUG_SURROUNDING_VEHICLES
637 if (neighFollow != 0) {
638 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
640 std::cout <<
"veh(target) returns none." << std::endl;
646#ifdef DEBUG_SURROUNDING_VEHICLES
648 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
649 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
658#ifdef DEBUG_SURROUNDING_VEHICLES
661 if (partialBehind != 0 && partialBehind != neighFollow) {
662 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
667 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
669 if (neighFollow ==
nullptr) {
671#ifdef DEBUG_SURROUNDING_VEHICLES
673 if (consecutiveFollower.first == 0) {
674 std::cout <<
"no follower found." << std::endl;
676 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
680 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
682#ifdef DEBUG_SURROUNDING_VEHICLES
684 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
687 return std::pair<MSVehicle* const, double>(neighFollow,
711 const std::pair<MSVehicle* const, double>& leader,
712 const std::vector<MSVehicle::LaneQ>& preb)
const {
717 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
720 neighFollow.first = 0;
723 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
730 const std::pair<MSVehicle* const, double>& leader,
731 const std::pair<MSVehicle* const, double>& follower,
732 const std::pair<MSVehicle* const, double>& neighLead,
733 const std::pair<MSVehicle* const, double>& neighFollow,
734 const std::vector<MSVehicle::LaneQ>& preb)
const {
738#ifdef DEBUG_CHECK_CHANGE
741 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
750 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
754#ifdef DEBUG_CHECK_CHANGE
757 <<
" overlapping with follower..."
763 if (neighLead.first !=
nullptr && neighLead.second < 0) {
766#ifdef DEBUG_CHECK_CHANGE
769 <<
" overlapping with leader..."
781 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
789 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
792 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
794#ifdef DEBUG_CHECK_CHANGE
797 <<
" follower=" << neighFollow.first->getID()
798 <<
" backGap=" << neighFollow.second
799 <<
" vNextFollower=" << vNextFollower
800 <<
" vNextEgo=" << vNextLeader
801 <<
" secureGap=" << secureBackGap
809 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
814#ifdef DEBUG_CHECK_CHANGE
816 std::cout <<
" ignoring opposite follower who changed in this step\n";
820 blocked |= blockedByFollower;
826 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
835 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
839#ifdef DEBUG_CHECK_CHANGE
842 <<
" leader=" << neighLead.first->getID()
843 <<
" frontGap=" << neighLead.second
844 <<
" vNextEgo=" << vNextFollower
845 <<
" vNextLeader=" << vNextLeader
846 <<
" secureGap=" << secureFrontGap
853 blocked |= blockedByLeader;
860 if (nextLeader.first != 0) {
864#ifdef DEBUG_CHECK_CHANGE
866 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
869 if (brakeGap > gap) {
870 blocked |= blockedByLeader;
871#ifdef DEBUG_CHECK_CHANGE
873 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
880 if (leader.first !=
nullptr) {
881 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
886 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
895 const double speed = vehicle->
getSpeed();
897 if (seen < dist || myCandi->lane->isInternal()) {
898 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
899 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
901 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
903#ifdef DEBUG_SURROUNDING_VEHICLES
905 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
906 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
909 if (neighLead2.second < secureGap2) {
910 state |= blockedByLeader;
918 state |= blockedByLeader;
930 if (estimatedLCDuration == -1) {
932#ifdef DEBUG_CHECK_CHANGE
934 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
935 <<
"\nestimatedLCDuration=" << estimatedLCDuration
936 <<
"\ndistToNeighLane=" << distToNeighLane
944 const double avgSpeed = 0.5 * (
948 const double space2change = avgSpeed * estimatedLCDuration;
951#ifdef DEBUG_CHECK_CHANGE
953 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
954 <<
"\ndistToNeighLane=" << distToNeighLane
955 <<
" estimatedLCDuration=" << estimatedLCDuration
956 <<
" space2change=" << space2change
957 <<
" avgSpeed=" << avgSpeed
966 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
967 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
971 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
976 if ((*link)->getViaLane() ==
nullptr) {
979 nextLane = (*link)->getViaLaneOrLane();
984#ifdef DEBUG_CHECK_CHANGE
986 std::cout <<
" available distance=" << seen << std::endl;
989 if (nextLane->
isLinkEnd(link) && seen < space2change) {
990#ifdef DEBUG_CHECK_CHANGE
992 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1001 const double speed = vehicle->
getSpeed();
1003 nextLane = vehicle->
getLane();
1006 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1007 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1008 nextLane = (*nextLink)->getViaLaneOrLane();
1010 if (parallelLane ==
nullptr) {
1014 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1015 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1017 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1018 state |= blockedByLeader;
1022 if ((*nextLink)->getViaLane() ==
nullptr) {
1032 const int oldstate = state;
1035#ifdef DEBUG_CHECK_CHANGE
1038 <<
" veh=" << vehicle->
getID()
1053 if (laneOffset != 0) {
1075 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1076 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1079 const int bestOffset = preb[laneIndex].bestLaneOffset;
1090 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1094 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1102 double oncomingSpeed;
1103 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1104 if (!isOpposite && surplusGap < 0) {
1105#ifdef DEBUG_CHANGE_OPPOSITE
1107 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1108 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1114 if (bestOffset > 0) {
1115 MSLane*
const target = preb[laneIndex + 1].lane;
1127std::vector<MSVehicle::LaneQ>
1134 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1135 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1136 for (
int i = 0; i < numOpposite; i++) {
1137 preb.push_back(preb.back());
1138 preb.back().lane = oLanes[numOpposite - 1 - i];
1139 preb.back().length = oppositeLength;
1141 preb.back().bestLaneOffset = -1 - i;
1145 if (stopLane !=
nullptr) {
1146 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1147 for (
int i = 0; i < (int)preb.size(); i++) {
1148 preb[i].bestLaneOffset = stopIndex - i;
1153#ifdef DEBUG_CHANGE_OPPOSITE
1155 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1156 for (
int i = 0; i < (int)preb.size(); i++) {
1157 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1175#ifdef DEBUG_CHANGE_OPPOSITE
1178 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1183 if (opposite ==
nullptr) {
1193 bool oppositeChangeByTraci =
false;
1196 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1200 oppositeChangeByTraci =
true;
1204#ifdef DEBUG_CHANGE_OPPOSITE
1206 std::cout <<
" not overtaking due to changeLeft restriction\n";
1217 const MSLane* oncomingLane = isOpposite ? source : opposite;
1220 int direction = isOpposite ? -1 : 1;
1221 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1224 double surplusGap = std::numeric_limits<double>::max();
1233 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1235 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1237 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1248 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1254 if (!isOpposite && !oppositeChangeByTraci
1256 && leader.first !=
nullptr) {
1261#ifdef DEBUG_CHANGE_OPPOSITE
1263 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1269 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1272 }
else if (leader.second < 0) {
1274#ifdef DEBUG_CHANGE_OPPOSITE
1276 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1284 double timeToOvertake = std::numeric_limits<double>::max();
1285 double spaceToOvertake = std::numeric_limits<double>::max();
1286 double maxSpaceToOvertake = 0;
1288 if (oppositeChangeByTraci) {
1298 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1299 overtaken = neighLead;
1301 if (overtaken.first !=
nullptr) {
1304#ifdef DEBUG_CHANGE_OPPOSITE
1306 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1307 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1308 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1315 if (overtaken.first == 0) {
1318#ifdef DEBUG_CHANGE_OPPOSITE
1320 std::cout <<
" no leader found\n";
1325 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1330#ifdef DEBUG_CHANGE_OPPOSITE
1332 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1340 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1341#ifdef DEBUG_CHANGE_OPPOSITE
1344 <<
" veh=" << vehicle->
getID()
1345 <<
" changeOpposite opposite=" << opposite->
getID()
1347 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1349 <<
" timeToOvertake=" << timeToOvertake
1350 <<
" spaceToOvertake=" << spaceToOvertake
1356#ifdef DEBUG_CHANGE_OPPOSITE
1358 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1366 if (!wait && lastStopped !=
nullptr) {
1368#ifdef DEBUG_CHANGE_OPPOSITE
1370 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1373 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1382 assert(timeToOvertake != std::numeric_limits<double>::max());
1383 assert(spaceToOvertake != std::numeric_limits<double>::max());
1386 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1387 neighLead = oncomingLane->
getOppositeLeader(vehicle, searchDist,
true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1388 oncoming =
getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1393 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1396 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1399 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1400 if (oncomingGap > 0) {
1403#ifdef DEBUG_CHANGE_OPPOSITE
1405 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1406 <<
" halting=" << oncoming.first->getWaitingSeconds()
1407 <<
" oncomingGap=" << oncomingGap
1409 <<
" vMax=" << vMax <<
"\n";
1416 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1417#ifdef DEBUG_CHANGE_OPPOSITE
1419 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1420 <<
" timeToOvertake=" << timeToOvertake
1421 <<
" spaceToOvertake=" << spaceToOvertake
1428#ifdef DEBUG_CHANGE_OPPOSITE
1430 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1438#ifdef DEBUG_CHANGE_OPPOSITE
1440 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1445 assert(timeToOvertake != std::numeric_limits<double>::max());
1446 assert(spaceToOvertake != std::numeric_limits<double>::max());
1450 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1451 if (oncomingOpposite.first !=
nullptr) {
1452 double oncomingSpeed2;
1453 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1455 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1456#ifdef DEBUG_CHANGE_OPPOSITE
1458 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1461 surplusGap =
MIN2(surplusGap, surplusGap2);
1462 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1463 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1464 && oncomingOpposite.second > oncoming.second) {
1468 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1471 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1472 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1473 double ooTTO = ooSTO / oSpeed;
1475 ooTTO = ceil(ooTTO /
TS) *
TS;
1476 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1477#ifdef DEBUG_CHANGE_OPPOSITE
1479 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1482 surplusGap =
MIN2(surplusGap, surplusGap3);
1485 if (!isOpposite && surplusGap < 0) {
1486#ifdef DEBUG_CHANGE_OPPOSITE
1488 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1492#ifdef DEBUG_CHANGE_OPPOSITE
1494 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1495 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1507 if (usableDist < spaceToOvertake) {
1510 assert(bestLaneConts.size() >= 1);
1511 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1512 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1513#ifdef DEBUG_CHANGE_OPPOSITE
1515 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1518 if ((*it)->getOpposite() ==
nullptr || !(*it)->getOpposite()->allowsVehicleClass(vehicle->
getVClass())) {
1523 const MSLane*
const prev = *(it - 1);
1524 if (prev !=
nullptr) {
1533#ifdef DEBUG_CHANGE_OPPOSITE
1535 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1541 usableDist += (*it)->getLength();
1545 if (!isOpposite && usableDist < spaceToOvertake) {
1546#ifdef DEBUG_CHANGE_OPPOSITE
1548 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1557 bool foundHill = vehicle->
getSlope() > 0;
1562#ifdef DEBUG_CHANGE_OPPOSITE
1564 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1569 double oppositeLength = vehicle->
getBestLanes().back().length;
1572 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1573 leader.first =
nullptr;
1574 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1576 neighLead.first =
nullptr;
1581#ifdef DEBUG_CHANGE_OPPOSITE
1583 std::cout <<
" not changing to avoid deadlock\n";
1588 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1594 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1602 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1608 std::pair<MSVehicle*, double> neighLead,
1609 std::pair<MSVehicle*, double> overtaken,
1610 std::pair<MSVehicle*, double> leader) {
1612#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1614 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1621 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1623 }
else if (!neighLead.first->isStopped()
1627 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1628 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1629 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1630#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1632 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1635 if (neighLead.first ==
nullptr) {
1642 if (neighLead.first->isStopped()
1643 && (overtaken.first->isStopped()
1644 || leader.first->getLaneChangeModel().isOpposite()
1649 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1650 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1652 const double distToStop = neighLead.second - requiredGap;
1656 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1657 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1658 if (neighStoppedBack + nextGap > overtaken.second) {
1661 neighStoppedBack += nextGap;
1662 auto neighLeadFollow = neighLead.first->getFollower();
1663 neighLead.second = neighLeadFollow.second;
1664 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1665#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1670 if (neighStoppedBack > overtaken.second) {
1675 const double leaderBGap = leader.first->getBrakeGap();
1676 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1677 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1679#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1681 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1682 <<
" neighLeadGap=" << neighLead.second
1683 <<
" leaderGap=" << leader.second
1684 <<
" bGap=" << leaderBGap
1685 <<
" fGap=" << leaderFGap
1686 <<
" eGap=" << extraGap
1687 <<
" neighStoppedBack=" << neighStoppedBack
1689 <<
" requiredGap=" << requiredGap
1690 <<
" gapWithEgo=" << gapWithEgo
1691 <<
" yield=" << yield
1696 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1697 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1698 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1700#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1702 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1705 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1706 const double blockerLength = currentDist - stopPos;
1708#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1710 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1711 <<
" blockerLength=" << blockerLength
1712 <<
" reserved=" << reserved
1730 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1732 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1733 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1734 follower = follower.first->getFollower(dist);
1736 if (follower.first !=
nullptr) {
1737 followerGap += follower.second;
1739#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1741 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1742 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1746 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1754 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1755 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1756 follower = follower.first->getFollower(dist);
1758#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1759 if (
DEBUG_COND && follower.first !=
nullptr) {
1760 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1761 <<
" oncoming=" << follower.first->getID()
1762 <<
" wait=" << follower.first->getWaitingSeconds()
1768 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1777 std::pair<MSVehicle* const, double> leader,
1778 std::pair<MSVehicle*, double> neighLead,
1779 std::pair<MSVehicle*, double> overtaken) {
1780 const double deadLockZone = overtaken.second;
1781#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1785 <<
" gap=" << leader.second
1794 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1795#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1797 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1798 <<
" leader=" << leader.first->getID()
1799 <<
" leaderGap=" << leader.second
1801 <<
" deadLockZone=" << deadLockZone
1805 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1808 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1809 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1810 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1811#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1813 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1818 if (oncomingOpposite.first !=
nullptr ||
1819 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1821 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1822 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1826#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1828 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1829 <<
" leader=" << leader.first->getID()
1830 <<
" leaderGap=" << leader.second
1831 <<
" oncoming=" << oncomingOpposite.first->getID()
1832 <<
" currentDist=" << currentDist
1833 <<
" blockerLength=" << blockerLength
1834 <<
" reserved=" << reserved
1849 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1850 std::pair<MSVehicle*, double> neighLead,
1851 std::pair<MSVehicle*, double> overtaken,
1852 std::pair<MSVehicle*, double> neighFollow,
1853 double surplusGap,
const MSLane* opposite,
1863 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1865 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1866#ifdef DEBUG_CHANGE_OPPOSITE
1868 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1872 const MSVehicle* oncomingVeh = oncoming.first;
1873 if (oncomingVeh != 0) {
1875 const double egoSpeedFraction =
MIN2(0.5, vMax / (vMax + oncomingSpeed));
1876 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1877#ifdef DEBUG_CHANGE_OPPOSITE
1879 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1880 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1884#ifdef DEBUG_CHANGE_OPPOSITE
1886 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1890 if (neighLead.first !=
nullptr) {
1891 if (overtaken.first ==
nullptr) {
1892#ifdef DEBUG_CHANGE_OPPOSITE
1894 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1897 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
1898 && neighLead.second > 0
1899 && neighFollow.second > 0
1902 oppositeLength = forwardPos + neighLead.second;
1904 if (surplusGap > 0) {
1907 oppositeLength += 1000;
1910 if (overtaken.second > 0) {
1911 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1916#ifdef DEBUG_CHANGE_OPPOSITE
1918 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1919 <<
" surplusGap=" << surplusGap
1920 <<
" final laneQLength=" << oppositeLength
1927 if (overtaken.first ==
nullptr || !canOvertake) {
1930 if (oppFollow.first ==
nullptr) {
1931 oppositeLength = forwardPos;
1933 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1935#ifdef DEBUG_CHANGE_OPPOSITE
1937 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
1940 if (oppFollow.second > secureGap) {
1942 oppositeLength = forwardPos;
1947#ifdef DEBUG_CHANGE_OPPOSITE
1949 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
1952 return oppositeLength;
1956std::pair<MSVehicle* const, double>
1959 double gap = oncoming.second;
1960 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
1961 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
1963 gap += oncoming.first->getVehicleType().getLengthWithGap();
1964 if (oncoming.first != overtaken) {
1965 vMax =
MIN2(vMax, oncoming.first->getSpeed());
1967#ifdef DEBUG_CHANGE_OPPOSITE
1969 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
1970 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
1973 if (searchDist < 0) {
1977 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
1978 opposite = oncoming.first->getLane();
1980 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
1981 if (oncoming.first !=
nullptr) {
1982 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
1983#ifdef DEBUG_CHANGE_OPPOSITE
1985 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
1990 oncoming.second = gap;
1995std::pair<MSVehicle* const, double>
1999 if (overtaken.first !=
nullptr) {
2001 front = overtaken.first;
2009 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2011 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2012 conts.erase(conts.begin());
2015 if (oncoming.first !=
nullptr) {
2016 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2017 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2018#ifdef DEBUG_CHANGE_OPPOSITE
2021 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2022 <<
" oncomingOpposite=" << oncoming.first->getID()
2023 <<
" gap=" << oncoming.second
2024 <<
" isOpposite=" << isOpposite
2029 if (isOpposite && shadowLane != front->
getLane()) {
2031 oncoming.second -= oncoming.first->getVehicleType().getLength();
2032 oncoming.second += gap;
2036 return std::make_pair(
nullptr, -1);
2042 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2043 double surplusGap = std::numeric_limits<double>::max();
2044 const MSVehicle* oncomingVeh = oncoming.first;
2045 if (oncomingVeh != 0 && (oncomingOpposite
2056 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2057#ifdef DEBUG_CHANGE_OPPOSITE
2060 <<
" oncoming=" << oncomingVeh->
getID()
2061 <<
" oGap=" << oncoming.second
2062 <<
" oSpeed=" << oncomingSpeed
2063 <<
" sto=" << spaceToOvertake
2064 <<
" tto=" << timeToOvertake
2065 <<
" safetyGap=" << safetyGap
2066 <<
" surplusGap=" << surplusGap
2076 if (view >= (
int)bestLanes.size()) {
2079 MSLane* lane = bestLanes[view];
2080 double laneDist = 0;
2082 double lastZ = lastMax;
2083 for (
int i = 1; i < (int)shape.size(); i++) {
2086 if (laneDist > pos) {
2087 const double z = shape[i].z();
2095#ifdef DEBUG_CHANGE_OPPOSITE
2097 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2100 if (foundHill && z < lastMax) {
2101 const double drop = lastMax - z;
2103 if (drop > hilltopThreshold) {
2104#ifdef DEBUG_CHANGE_OPPOSITE
2106 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2107 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2116 searchDist -= laneDist - pos;
2119 if (searchDist <= 0) {
2124 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2133 const std::pair<MSVehicle* const, double>& leader,
2134 const std::pair<MSVehicle* const, double>& neighLead,
2135 const std::pair<MSVehicle* const, double>& neighFollow,
2136 const std::vector<MSVehicle::LaneQ>& preb) {
2139 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2140 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2142 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2148#ifdef DEBUG_CHANGE_OPPOSITE
2150 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2159#ifdef DEBUG_CHANGE_OPPOSITE
2161 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2178 const double v = vehicle->
getSpeed();
2182 const double g =
MAX2(0.0, (
2193 const double sign = -1;
2197 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2198#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2200 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2201 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2208 timeToOvertake = std::numeric_limits<double>::max();
2209 spaceToOvertake = std::numeric_limits<double>::max();
2217 t = ceil(t /
TS) *
TS;
2221 const double timeToMaxSpeed = (vMax - v) / a;
2223#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2225 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2228 if (t <= timeToMaxSpeed) {
2230 spaceToOvertake = v * t + t * t * a * 0.5;
2231#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2233 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2238 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2239 const double m = timeToMaxSpeed;
2242 t = (g - s + m * vMax) / (vMax - u);
2245#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2247 std::cout <<
" t2=" << t <<
"\n";
2250 timeToOvertake = std::numeric_limits<double>::max();
2251 spaceToOvertake = std::numeric_limits<double>::max();
2258 t = ceil(t /
TS) *
TS;
2261 spaceToOvertake = s + (t - m) * vMax;
2262#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2264 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2270 timeToOvertake *= safetyFactor;
2272 spaceToOvertake *= safetyFactor;
2274 double frac = fmod(timeToOvertake,
TS);
2277 timeToOvertake +=
TS - frac;
2279#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2281 if (safetyFactor != 1) {
2282 std::cout <<
" applying safetyFactor=" << safetyFactor
2284 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2292std::pair<MSVehicle*, double>
2294 assert(leader.first != 0);
2299 std::pair<MSVehicle*, double> columnLeader = leader;
2300 double egoGap = leader.second;
2301 bool foundSpaceAhead =
false;
2302 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2304 if (maxLookAhead == std::numeric_limits<double>::max()) {
2308 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2310 + leader.first->getVehicleType().getLengthWithGap());
2312#ifdef DEBUG_CHANGE_OPPOSITE
2314 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2318 while (!foundSpaceAhead) {
2319 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2320 columnLeader.first, vehicle,
2322 + columnLeader.first->getVehicleType().getMinGap()
2327 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2328 double searchStart = columnLeader.first->getPositionOnLane();
2329 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2330 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2332 std::set<MSVehicle*> seenLeaders;
2333 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2334#ifdef DEBUG_CHANGE_OPPOSITE
2336 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2339 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2340 leadLead.first =
nullptr;
2343 seenLeaders.insert(leadLead.first);
2345 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2346 leadLead = columnLeader.first->getLane()->getLeader(
2347 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2349 leadLead.second += (searchStart2 - searchStart);
2351 if (leadLead.first ==
nullptr) {
2352 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2353 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2354 if (!columnLeader.first->isStopped()) {
2356 requiredSpace += safetyFactor * mergeBrakeGap;
2358#ifdef DEBUG_CHANGE_OPPOSITE
2360 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2361 <<
" availableSpace=" << availableSpace
2362 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2363 <<
" ovSpeed=" << overtakingSpeed
2364 <<
" reqBGap=" << mergeBrakeGap
2365 <<
" reqMin=" << requiredSpace / safetyFactor
2366 <<
" req=" << requiredSpace
2370 if (availableSpace > requiredSpace) {
2371 foundSpaceAhead =
true;
2376 bool contsEnd =
false;
2377 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, allowMinor, contsEnd);
2378#ifdef DEBUG_CHANGE_OPPOSITE
2380 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2383 while (next !=
nullptr && seen < maxLookAhead) {
2386 if (cand ==
nullptr) {
2388 if (availableSpace > requiredSpace) {
2389 foundSpaceAhead =
true;
2392 next =
getLaneAfter(next, conts, allowMinor, contsEnd);
2395 if (availableSpace > requiredSpace) {
2396 foundSpaceAhead =
true;
2403#ifdef DEBUG_CHANGE_OPPOSITE
2405 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2408 if (!foundSpaceAhead && contsEnd) {
2409 foundSpaceAhead =
true;
2410 availableSpace = requiredSpace;
2412 if (!foundSpaceAhead) {
2413 return std::make_pair(
nullptr, -1);
2416 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2419 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2420 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2421 if (!columnLeader.first->isStopped()) {
2423 requiredSpace += safetyFactor * sGap;
2425#ifdef DEBUG_CHANGE_OPPOSITE
2427 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2428 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2429 <<
" ovSpeed=" << overtakingSpeed
2430 <<
" reqSGap=" << sGap
2431 <<
" reqMin=" << requiredSpace / safetyFactor
2432 <<
" req=" << requiredSpace
2436 if (leadLead.second > requiredSpace) {
2437 foundSpaceAhead =
true;
2438 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2441 if (leadLead.second < 0) {
2443#ifdef DEBUG_CHANGE_OPPOSITE
2445 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2448 return std::make_pair(
nullptr, -1);
2451#ifdef DEBUG_CHANGE_OPPOSITE
2453 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2456 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2457 if (seen > maxLookAhead) {
2458#ifdef DEBUG_CHANGE_OPPOSITE
2460 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2463 return std::make_pair(
nullptr, -1);
2466 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2467 columnLeader = leadLead;
2468#ifdef DEBUG_CHANGE_OPPOSITE
2470 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2476 columnLeader.second = egoGap;
2477 return columnLeader;
2483 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2485 if (it + 1 != conts.end()) {
2487 const MSLane* next = *(it + 1);
2489 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2507 const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY
#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETY_FACTOR
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP
#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE
std::pair< const MSVehicle *, double > CLeaderDist
std::pair< const MSPerson *, double > PersonDist
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_EMERGENCY
public emergency vehicles
@ RIGHT
The link is a (hard) right direction.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_BLOCKED_BY_RIGHT_LEADER
The vehicle is blocked by right leader.
@ LCA_INSUFFICIENT_SPACE
The vehicle does not have enough space to complete a continuous change before the next turn.
@ LCA_BLOCKED_BY_LEFT_FOLLOWER
The vehicle is blocked by left follower.
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_INSUFFICIENT_SPEED
Vehicle is too slow to complete a continuous lane change (in case that maxSpeedLatStanding==0)
@ LCA_OVERLAPPING
The vehicle is blocked being overlapping.
@ LCA_LEFT
Wants go to the left.
@ LCA_BLOCKED_BY_RIGHT_FOLLOWER
The vehicle is blocked by right follower.
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_LEFT_LEADER
const double SUMO_const_laneWidth
#define UNUSED_PARAMETER(x)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class responsible for exchanging messages between cars involved in lane-change interaction.
Interface for lane-change models.
double getLaneChangeCompletion() const
Get the current lane change completion ratio.
double getForwardPos() const
get vehicle position relative to the forward direction lane
void setFollowerGaps(CLeaderDist follower, double secGap)
virtual void setOwnState(const int state)
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change.
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
static const double NO_NEIGHBOR
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
virtual bool saveBlockerLength(double, double)
reserve space at the end of the lane to avoid dead locks
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
virtual double getOppositeSafetyFactor() const
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
void setLeaderGaps(CLeaderDist, double secGap)
void setOrigLeaderGaps(CLeaderDist, double secGap)
int getNormalizedLaneIndex()
brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
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.
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.
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
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.
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
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
bool isStoppedOnLane() const
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
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.
@ 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:
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
double getSpeed() const
Returns the vehicle's current speed.
Position myCachedPosition
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
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 ignore
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)
State myState
This Vehicles driving state (pos and speed)
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
static const Position INVALID
used to indicate that a position is valid
double z() const
Returns the z-position.
ChangeElem(MSLane *_lane)
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.