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;
557 const bool checkBidi = target->lane->getBidiLane() !=
nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
558 if (neighLead ==
nullptr || checkBidi) {
559#ifdef DEBUG_SURROUNDING_VEHICLES
561 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
566 MSLane* targetLane = target->lane;
568 double leaderBack = targetLane->
getLength();
569 if (neighLead !=
nullptr) {
573 double plBack = pl->getBackPositionOnLane(targetLane);
574 if (pl->isBidiOn(targetLane)) {
575 plBack -= pl->getVehicleType().getLengthWithGap();
577 const double plPos = plBack + pl->getVehicleType().getLength();
578#ifdef DEBUG_SURROUNDING_VEHICLES
580 std::cout <<
" partial=" << pl->getID() <<
" plBack=" << plBack <<
" plPos=" << plPos <<
" leaderBack=" << leaderBack <<
" egoBack=" << egoBack <<
"\n";
583 if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
588 if (neighLead !=
nullptr) {
589#ifdef DEBUG_SURROUNDING_VEHICLES
591 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
595 return std::pair<MSVehicle*, double>(neighLead, gap);
601 if (seen > dist && !
myCandi->lane->isInternal()) {
602#ifdef DEBUG_SURROUNDING_VEHICLES
604 std::cout <<
" found no leader within dist=" << dist <<
"\n";
607 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
611 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
612#ifdef DEBUG_SURROUNDING_VEHICLES
619#ifdef DEBUG_SURROUNDING_VEHICLES
621 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
629std::pair<MSVehicle* const, double>
633#ifdef DEBUG_SURROUNDING_VEHICLES
635 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
641 neighFollow =
veh(target);
644 if (target->lane->myVehicles.size() > 1) {
645 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
649#ifdef DEBUG_SURROUNDING_VEHICLES
651 if (neighFollow != 0) {
652 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
654 std::cout <<
"veh(target) returns none." << std::endl;
660#ifdef DEBUG_SURROUNDING_VEHICLES
662 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
663 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
672#ifdef DEBUG_SURROUNDING_VEHICLES
675 if (partialBehind != 0 && partialBehind != neighFollow) {
676 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
681 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
683 if (neighFollow ==
nullptr) {
685#ifdef DEBUG_SURROUNDING_VEHICLES
687 if (consecutiveFollower.first == 0) {
688 std::cout <<
"no follower found." << std::endl;
690 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
694 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
696#ifdef DEBUG_SURROUNDING_VEHICLES
698 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
701 return std::pair<MSVehicle* const, double>(neighFollow,
725 const std::pair<MSVehicle* const, double>& leader,
726 const std::vector<MSVehicle::LaneQ>& preb)
const {
731 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
734 neighFollow.first = 0;
737 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
744 const std::pair<MSVehicle* const, double>& leader,
745 const std::pair<MSVehicle* const, double>& follower,
746 const std::pair<MSVehicle* const, double>& neighLead,
747 const std::pair<MSVehicle* const, double>& neighFollow,
748 const std::vector<MSVehicle::LaneQ>& preb)
const {
752#ifdef DEBUG_CHECK_CHANGE
755 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
764 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
768#ifdef DEBUG_CHECK_CHANGE
771 <<
" overlapping with follower..."
777 if (neighLead.first !=
nullptr && neighLead.second < 0) {
780#ifdef DEBUG_CHECK_CHANGE
783 <<
" overlapping with leader..."
795 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
803 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
806 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
808#ifdef DEBUG_CHECK_CHANGE
811 <<
" follower=" << neighFollow.first->getID()
812 <<
" backGap=" << neighFollow.second
813 <<
" vNextFollower=" << vNextFollower
814 <<
" vNextEgo=" << vNextLeader
815 <<
" secureGap=" << secureBackGap
823 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
828#ifdef DEBUG_CHECK_CHANGE
830 std::cout <<
" ignoring opposite follower who changed in this step\n";
834 blocked |= blockedByFollower;
840 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
849 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
853#ifdef DEBUG_CHECK_CHANGE
856 <<
" leader=" << neighLead.first->getID()
857 <<
" frontGap=" << neighLead.second
858 <<
" vNextEgo=" << vNextFollower
859 <<
" vNextLeader=" << vNextLeader
860 <<
" secureGap=" << secureFrontGap
867 blocked |= blockedByLeader;
874 if (nextLeader.first != 0) {
878#ifdef DEBUG_CHECK_CHANGE
880 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
883 if (brakeGap > gap) {
884 blocked |= blockedByLeader;
885#ifdef DEBUG_CHECK_CHANGE
887 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
894 if (leader.first !=
nullptr) {
895 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
900 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
909 const double speed = vehicle->
getSpeed();
911 if (seen < dist || myCandi->lane->isInternal()) {
912 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
913 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
915 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
917#ifdef DEBUG_SURROUNDING_VEHICLES
919 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
920 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
923 if (neighLead2.second < secureGap2) {
924 state |= blockedByLeader;
932 state |= blockedByLeader;
944 if (estimatedLCDuration == -1) {
946#ifdef DEBUG_CHECK_CHANGE
948 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
949 <<
"\nestimatedLCDuration=" << estimatedLCDuration
950 <<
"\ndistToNeighLane=" << distToNeighLane
958 const double avgSpeed = 0.5 * (
962 const double space2change = avgSpeed * estimatedLCDuration;
965#ifdef DEBUG_CHECK_CHANGE
967 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
968 <<
"\ndistToNeighLane=" << distToNeighLane
969 <<
" estimatedLCDuration=" << estimatedLCDuration
970 <<
" space2change=" << space2change
971 <<
" avgSpeed=" << avgSpeed
980 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
981 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
985 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
990 if ((*link)->getViaLane() ==
nullptr) {
993 nextLane = (*link)->getViaLaneOrLane();
998#ifdef DEBUG_CHECK_CHANGE
1000 std::cout <<
" available distance=" << seen << std::endl;
1003 if (nextLane->
isLinkEnd(link) && seen < space2change) {
1004#ifdef DEBUG_CHECK_CHANGE
1006 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1015 const double speed = vehicle->
getSpeed();
1017 nextLane = vehicle->
getLane();
1020 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1021 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1022 nextLane = (*nextLink)->getViaLaneOrLane();
1024 if (parallelLane ==
nullptr) {
1028 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1029 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1031 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1032 state |= blockedByLeader;
1036 if ((*nextLink)->getViaLane() ==
nullptr) {
1046 const int oldstate = state;
1049#ifdef DEBUG_CHECK_CHANGE
1052 <<
" veh=" << vehicle->
getID()
1067 if (laneOffset != 0) {
1089 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1090 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1093 const int bestOffset = preb[laneIndex].bestLaneOffset;
1104 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1108 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1116 double oncomingSpeed;
1117 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1118 if (!isOpposite && surplusGap < 0) {
1119#ifdef DEBUG_CHANGE_OPPOSITE
1121 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1122 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1128 if (bestOffset > 0) {
1129 MSLane*
const target = preb[laneIndex + 1].lane;
1141std::vector<MSVehicle::LaneQ>
1148 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1149 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1150 for (
int i = 0; i < numOpposite; i++) {
1151 preb.push_back(preb.back());
1152 preb.back().lane = oLanes[numOpposite - 1 - i];
1153 preb.back().length = oppositeLength;
1155 preb.back().bestLaneOffset = -1 - i;
1159 if (stopLane !=
nullptr) {
1160 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1161 for (
int i = 0; i < (int)preb.size(); i++) {
1162 preb[i].bestLaneOffset = stopIndex - i;
1167#ifdef DEBUG_CHANGE_OPPOSITE
1169 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1170 for (
int i = 0; i < (int)preb.size(); i++) {
1171 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1189#ifdef DEBUG_CHANGE_OPPOSITE
1192 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1197 if (opposite ==
nullptr) {
1207 bool oppositeChangeByTraci =
false;
1210 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1214 oppositeChangeByTraci =
true;
1218#ifdef DEBUG_CHANGE_OPPOSITE
1220 std::cout <<
" not overtaking due to changeLeft restriction\n";
1231 const MSLane* oncomingLane = isOpposite ? source : opposite;
1234 int direction = isOpposite ? -1 : 1;
1235 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1238 double surplusGap = std::numeric_limits<double>::max();
1247 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1249 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1251 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1262 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1268 if (!isOpposite && !oppositeChangeByTraci
1270 && leader.first !=
nullptr) {
1275#ifdef DEBUG_CHANGE_OPPOSITE
1277 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1283 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1286 }
else if (leader.second < 0) {
1288#ifdef DEBUG_CHANGE_OPPOSITE
1290 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1298 double timeToOvertake = std::numeric_limits<double>::max();
1299 double spaceToOvertake = std::numeric_limits<double>::max();
1300 double maxSpaceToOvertake = 0;
1302 if (oppositeChangeByTraci) {
1312 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1313 overtaken = neighLead;
1315 if (overtaken.first !=
nullptr) {
1318#ifdef DEBUG_CHANGE_OPPOSITE
1320 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1321 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1322 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1329 if (overtaken.first == 0) {
1332#ifdef DEBUG_CHANGE_OPPOSITE
1334 std::cout <<
" no leader found\n";
1339 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1344#ifdef DEBUG_CHANGE_OPPOSITE
1346 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1354 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1355#ifdef DEBUG_CHANGE_OPPOSITE
1358 <<
" veh=" << vehicle->
getID()
1359 <<
" changeOpposite opposite=" << opposite->
getID()
1361 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1363 <<
" timeToOvertake=" << timeToOvertake
1364 <<
" spaceToOvertake=" << spaceToOvertake
1370#ifdef DEBUG_CHANGE_OPPOSITE
1372 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1380 if (!wait && lastStopped !=
nullptr) {
1382#ifdef DEBUG_CHANGE_OPPOSITE
1384 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1387 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1396 assert(timeToOvertake != std::numeric_limits<double>::max());
1397 assert(spaceToOvertake != std::numeric_limits<double>::max());
1400 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1407 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1410 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1413 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1414 if (oncomingGap > 0) {
1417#ifdef DEBUG_CHANGE_OPPOSITE
1419 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1420 <<
" halting=" << oncoming.first->getWaitingSeconds()
1421 <<
" oncomingGap=" << oncomingGap
1423 <<
" vMax=" << vMax <<
"\n";
1430 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1431#ifdef DEBUG_CHANGE_OPPOSITE
1433 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1434 <<
" timeToOvertake=" << timeToOvertake
1435 <<
" spaceToOvertake=" << spaceToOvertake
1442#ifdef DEBUG_CHANGE_OPPOSITE
1444 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1452#ifdef DEBUG_CHANGE_OPPOSITE
1454 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1459 assert(timeToOvertake != std::numeric_limits<double>::max());
1460 assert(spaceToOvertake != std::numeric_limits<double>::max());
1464 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1465 if (oncomingOpposite.first !=
nullptr) {
1466 double oncomingSpeed2;
1467 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1469 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1470#ifdef DEBUG_CHANGE_OPPOSITE
1472 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1475 surplusGap =
MIN2(surplusGap, surplusGap2);
1476 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1477 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1478 && oncomingOpposite.second > oncoming.second) {
1482 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1485 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1486 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1487 double ooTTO = ooSTO / oSpeed;
1489 ooTTO = ceil(ooTTO /
TS) *
TS;
1490 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1491#ifdef DEBUG_CHANGE_OPPOSITE
1493 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1496 surplusGap =
MIN2(surplusGap, surplusGap3);
1499 if (!isOpposite && surplusGap < 0) {
1500#ifdef DEBUG_CHANGE_OPPOSITE
1502 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1506#ifdef DEBUG_CHANGE_OPPOSITE
1508 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1509 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1521 if (usableDist < spaceToOvertake) {
1524 assert(bestLaneConts.size() >= 1);
1525 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1526 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1527#ifdef DEBUG_CHANGE_OPPOSITE
1529 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1532 if ((*it)->getOpposite() ==
nullptr || !(*it)->getOpposite()->allowsVehicleClass(vehicle->
getVClass())) {
1537 const MSLane*
const prev = *(it - 1);
1538 if (prev !=
nullptr) {
1547#ifdef DEBUG_CHANGE_OPPOSITE
1549 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1555 usableDist += (*it)->getLength();
1559 if (!isOpposite && usableDist < spaceToOvertake) {
1560#ifdef DEBUG_CHANGE_OPPOSITE
1562 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1571 bool foundHill = vehicle->
getSlope() > 0;
1576#ifdef DEBUG_CHANGE_OPPOSITE
1578 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1583 double oppositeLength = vehicle->
getBestLanes().back().length;
1586 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1587 leader.first =
nullptr;
1588 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1590 neighLead.first =
nullptr;
1595#ifdef DEBUG_CHANGE_OPPOSITE
1597 std::cout <<
" not changing to avoid deadlock\n";
1602 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1608 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1616 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1622 std::pair<MSVehicle*, double> neighLead,
1623 std::pair<MSVehicle*, double> overtaken,
1624 std::pair<MSVehicle*, double> leader) {
1626#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1628 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1635 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1637 }
else if (!neighLead.first->isStopped()
1641 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1642 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1643 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1644#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1646 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1649 if (neighLead.first ==
nullptr) {
1656 if (neighLead.first->isStopped()
1657 && (overtaken.first->isStopped()
1658 || leader.first->getLaneChangeModel().isOpposite()
1663 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1664 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1666 const double distToStop = neighLead.second - requiredGap;
1670 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1671 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1672 if (neighStoppedBack + nextGap > overtaken.second) {
1675 neighStoppedBack += nextGap;
1676 auto neighLeadFollow = neighLead.first->getFollower();
1677 neighLead.second = neighLeadFollow.second;
1678 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1679#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1684 if (neighStoppedBack > overtaken.second) {
1689 const double leaderBGap = leader.first->
getBrakeGap();
1690 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1691 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1693#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1695 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1696 <<
" neighLeadGap=" << neighLead.second
1697 <<
" leaderGap=" << leader.second
1698 <<
" bGap=" << leaderBGap
1699 <<
" fGap=" << leaderFGap
1700 <<
" eGap=" << extraGap
1701 <<
" neighStoppedBack=" << neighStoppedBack
1703 <<
" requiredGap=" << requiredGap
1704 <<
" gapWithEgo=" << gapWithEgo
1705 <<
" yield=" << yield
1710 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1711 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1712 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1714#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1716 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1719 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1720 const double blockerLength = currentDist - stopPos;
1722#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1724 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1725 <<
" blockerLength=" << blockerLength
1726 <<
" reserved=" << reserved
1744 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1746 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1747 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1748 follower = follower.first->getFollower(dist);
1750 if (follower.first !=
nullptr) {
1751 followerGap += follower.second;
1753#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1755 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1756 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1760 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1768 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1769 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1770 follower = follower.first->getFollower(dist);
1772#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1773 if (
DEBUG_COND && follower.first !=
nullptr) {
1774 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1775 <<
" oncoming=" << follower.first->getID()
1776 <<
" wait=" << follower.first->getWaitingSeconds()
1782 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1791 std::pair<MSVehicle* const, double> leader,
1792 std::pair<MSVehicle*, double> neighLead,
1793 std::pair<MSVehicle*, double> overtaken) {
1794 const double deadLockZone = overtaken.second;
1795#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1799 <<
" gap=" << leader.second
1808 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1809#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1811 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1812 <<
" leader=" << leader.first->getID()
1813 <<
" leaderGap=" << leader.second
1815 <<
" deadLockZone=" << deadLockZone
1819 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1822 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1823 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1824 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1825#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1827 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1832 if (oncomingOpposite.first !=
nullptr ||
1833 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1835 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1836 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1840#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1842 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1843 <<
" leader=" << leader.first->getID()
1844 <<
" leaderGap=" << leader.second
1845 <<
" oncoming=" << oncomingOpposite.first->getID()
1846 <<
" currentDist=" << currentDist
1847 <<
" blockerLength=" << blockerLength
1848 <<
" reserved=" << reserved
1863 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1864 std::pair<MSVehicle*, double> neighLead,
1865 std::pair<MSVehicle*, double> overtaken,
1866 std::pair<MSVehicle*, double> neighFollow,
1867 double surplusGap,
const MSLane* opposite,
1877 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1879 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1880#ifdef DEBUG_CHANGE_OPPOSITE
1882 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1886 const MSVehicle* oncomingVeh = oncoming.first;
1887 if (oncomingVeh != 0) {
1889 const double egoSpeedFraction =
MIN2(0.5, vMax / (vMax + oncomingSpeed));
1890 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1891#ifdef DEBUG_CHANGE_OPPOSITE
1893 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1894 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1898#ifdef DEBUG_CHANGE_OPPOSITE
1900 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1904 if (neighLead.first !=
nullptr) {
1905 if (overtaken.first ==
nullptr) {
1906#ifdef DEBUG_CHANGE_OPPOSITE
1908 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1911 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
1912 && neighLead.second > 0
1913 && neighFollow.second > 0
1916 oppositeLength = forwardPos + neighLead.second;
1918 if (surplusGap > 0) {
1921 oppositeLength += 1000;
1924 if (overtaken.second > 0) {
1925 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1930#ifdef DEBUG_CHANGE_OPPOSITE
1932 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1933 <<
" surplusGap=" << surplusGap
1934 <<
" final laneQLength=" << oppositeLength
1941 if (overtaken.first ==
nullptr || !canOvertake) {
1944 if (oppFollow.first ==
nullptr) {
1945 oppositeLength = forwardPos;
1947 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1949#ifdef DEBUG_CHANGE_OPPOSITE
1951 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
1954 if (oppFollow.second > secureGap) {
1956 oppositeLength = forwardPos;
1961#ifdef DEBUG_CHANGE_OPPOSITE
1963 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
1966 return oppositeLength;
1970std::pair<MSVehicle* const, double>
1973 double gap = oncoming.second;
1974 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
1975 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
1977 gap += oncoming.first->getVehicleType().getLengthWithGap();
1978 if (oncoming.first != overtaken) {
1979 vMax =
MIN2(vMax, oncoming.first->getSpeed());
1981#ifdef DEBUG_CHANGE_OPPOSITE
1983 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
1984 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
1987 if (searchDist < 0) {
1991 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
1992 opposite = oncoming.first->getLane();
1994 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
1995 if (oncoming.first !=
nullptr) {
1996 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
1997#ifdef DEBUG_CHANGE_OPPOSITE
1999 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
2004 oncoming.second = gap;
2009std::pair<MSVehicle* const, double>
2013 if (overtaken.first !=
nullptr) {
2015 front = overtaken.first;
2023 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2025 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2026 conts.erase(conts.begin());
2029 if (oncoming.first !=
nullptr) {
2030 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2031 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2032#ifdef DEBUG_CHANGE_OPPOSITE
2035 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2036 <<
" oncomingOpposite=" << oncoming.first->getID()
2037 <<
" gap=" << oncoming.second
2038 <<
" isOpposite=" << isOpposite
2043 if (isOpposite && shadowLane != front->
getLane()) {
2045 oncoming.second -= oncoming.first->getVehicleType().getLength();
2046 oncoming.second += gap;
2050 return std::make_pair(
nullptr, -1);
2056 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2057 double surplusGap = std::numeric_limits<double>::max();
2058 const MSVehicle* oncomingVeh = oncoming.first;
2059 if (oncomingVeh != 0 && (oncomingOpposite
2070 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2071#ifdef DEBUG_CHANGE_OPPOSITE
2074 <<
" oncoming=" << oncomingVeh->
getID()
2075 <<
" oGap=" << oncoming.second
2076 <<
" oSpeed=" << oncomingSpeed
2077 <<
" sto=" << spaceToOvertake
2078 <<
" tto=" << timeToOvertake
2079 <<
" safetyGap=" << safetyGap
2080 <<
" surplusGap=" << surplusGap
2090 if (view >= (
int)bestLanes.size()) {
2093 MSLane* lane = bestLanes[view];
2094 double laneDist = 0;
2096 double lastZ = lastMax;
2097 for (
int i = 1; i < (int)shape.size(); i++) {
2100 if (laneDist > pos) {
2101 const double z = shape[i].z();
2109#ifdef DEBUG_CHANGE_OPPOSITE
2111 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2114 if (foundHill && z < lastMax) {
2115 const double drop = lastMax - z;
2117 if (drop > hilltopThreshold) {
2118#ifdef DEBUG_CHANGE_OPPOSITE
2120 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2121 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2130 searchDist -= laneDist - pos;
2133 if (searchDist <= 0) {
2138 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2147 const std::pair<MSVehicle* const, double>& leader,
2148 const std::pair<MSVehicle* const, double>& neighLead,
2149 const std::pair<MSVehicle* const, double>& neighFollow,
2150 const std::vector<MSVehicle::LaneQ>& preb) {
2153 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2154 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2156 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2162#ifdef DEBUG_CHANGE_OPPOSITE
2164 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2173#ifdef DEBUG_CHANGE_OPPOSITE
2175 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2192 const double v = vehicle->
getSpeed();
2196 const double g =
MAX2(0.0, (
2207 const double sign = -1;
2211 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2212#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2214 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2215 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2222 timeToOvertake = std::numeric_limits<double>::max();
2223 spaceToOvertake = std::numeric_limits<double>::max();
2231 t = ceil(t /
TS) *
TS;
2235 const double timeToMaxSpeed = (vMax - v) / a;
2237#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2239 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2242 if (t <= timeToMaxSpeed) {
2244 spaceToOvertake = v * t + t * t * a * 0.5;
2245#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2247 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2252 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2253 const double m = timeToMaxSpeed;
2256 t = (g - s + m * vMax) / (vMax - u);
2259#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2261 std::cout <<
" t2=" << t <<
"\n";
2264 timeToOvertake = std::numeric_limits<double>::max();
2265 spaceToOvertake = std::numeric_limits<double>::max();
2272 t = ceil(t /
TS) *
TS;
2275 spaceToOvertake = s + (t - m) * vMax;
2276#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2278 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2284 timeToOvertake *= safetyFactor;
2286 spaceToOvertake *= safetyFactor;
2288 double frac = fmod(timeToOvertake,
TS);
2291 timeToOvertake +=
TS - frac;
2293#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2295 if (safetyFactor != 1) {
2296 std::cout <<
" applying safetyFactor=" << safetyFactor
2298 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2306std::pair<MSVehicle*, double>
2308 assert(leader.first != 0);
2313 std::pair<MSVehicle*, double> columnLeader = leader;
2314 double egoGap = leader.second;
2315 bool foundSpaceAhead =
false;
2316 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2318 if (maxLookAhead == std::numeric_limits<double>::max()) {
2322 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2324 + leader.first->getVehicleType().getLengthWithGap());
2326#ifdef DEBUG_CHANGE_OPPOSITE
2328 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2332 while (!foundSpaceAhead) {
2333 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2334 columnLeader.first, vehicle,
2336 + columnLeader.first->getVehicleType().getMinGap()
2341 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2342 double searchStart = columnLeader.first->getPositionOnLane();
2343 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2344 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2346 std::set<MSVehicle*> seenLeaders;
2347 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2348#ifdef DEBUG_CHANGE_OPPOSITE
2350 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2353 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2354 leadLead.first =
nullptr;
2357 seenLeaders.insert(leadLead.first);
2359 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2360 leadLead = columnLeader.first->getLane()->getLeader(
2361 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2363 leadLead.second += (searchStart2 - searchStart);
2365 if (leadLead.first ==
nullptr) {
2366 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2367 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2368 if (!columnLeader.first->isStopped()) {
2370 requiredSpace += safetyFactor * mergeBrakeGap;
2372#ifdef DEBUG_CHANGE_OPPOSITE
2374 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2375 <<
" availableSpace=" << availableSpace
2376 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2377 <<
" ovSpeed=" << overtakingSpeed
2378 <<
" reqBGap=" << mergeBrakeGap
2379 <<
" reqMin=" << requiredSpace / safetyFactor
2380 <<
" req=" << requiredSpace
2384 if (availableSpace > requiredSpace) {
2385 foundSpaceAhead =
true;
2390 bool contsEnd =
false;
2391 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, allowMinor, contsEnd);
2392#ifdef DEBUG_CHANGE_OPPOSITE
2394 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2397 while (next !=
nullptr && seen < maxLookAhead) {
2400 if (cand ==
nullptr) {
2402 if (availableSpace > requiredSpace) {
2403 foundSpaceAhead =
true;
2406 next =
getLaneAfter(next, conts, allowMinor, contsEnd);
2409 if (availableSpace > requiredSpace) {
2410 foundSpaceAhead =
true;
2417#ifdef DEBUG_CHANGE_OPPOSITE
2419 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2422 if (!foundSpaceAhead && contsEnd) {
2423 foundSpaceAhead =
true;
2424 availableSpace = requiredSpace;
2426 if (!foundSpaceAhead) {
2427 return std::make_pair(
nullptr, -1);
2430 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2433 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2434 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2435 if (!columnLeader.first->isStopped()) {
2437 requiredSpace += safetyFactor * sGap;
2439#ifdef DEBUG_CHANGE_OPPOSITE
2441 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2442 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2443 <<
" ovSpeed=" << overtakingSpeed
2444 <<
" reqSGap=" << sGap
2445 <<
" reqMin=" << requiredSpace / safetyFactor
2446 <<
" req=" << requiredSpace
2450 if (leadLead.second > requiredSpace) {
2451 foundSpaceAhead =
true;
2452 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2455 if (leadLead.second < 0) {
2457#ifdef DEBUG_CHANGE_OPPOSITE
2459 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2462 return std::make_pair(
nullptr, -1);
2465#ifdef DEBUG_CHANGE_OPPOSITE
2467 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2470 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2471 if (seen > maxLookAhead) {
2472#ifdef DEBUG_CHANGE_OPPOSITE
2474 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2477 return std::make_pair(
nullptr, -1);
2480 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2481 columnLeader = leadLead;
2482#ifdef DEBUG_CHANGE_OPPOSITE
2484 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2490 columnLeader.second = egoGap;
2491 return columnLeader;
2497 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2499 if (it + 1 != conts.end()) {
2501 const MSLane* next = *(it + 1);
2503 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2521 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 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.
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.