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.),
113 lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
128 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
130 myChanger.back().mayChangeRight = lane != lanes->begin();
131 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
132 if ((*lane)->isInternal()) {
134 if (
myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
137 if (
myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
141 if (
myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
145 if (
myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
167 const bool haveChanged =
change();
174 ce->lane->releaseVehicles();
186 ce->hoppedVeh =
nullptr;
187 ce->lastBlocked =
nullptr;
188 ce->firstBlocked =
nullptr;
189 ce->lastStopped =
nullptr;
191 ce->lane->getVehiclesSecure();
205 if (!vehHasChanged) {
228 ce->lane->swapAfterLaneChange(t);
229 ce->lane->releaseVehicles();
239#ifdef DEBUG_CANDIDATE
240 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
244 if (
veh(ce) ==
nullptr) {
247#ifdef DEBUG_CANDIDATE
248 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
252#ifdef DEBUG_CANDIDATE
258 assert(
veh(ce) != 0);
259 assert(
veh(max) != 0);
260 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
261#ifdef DEBUG_CANDIDATE
268 assert(
veh(max) != 0);
275 if (direction == 0) {
282 if (direction == -1) {
283 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingRight(svc);
284 }
else if (direction == 1) {
285 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingLeft(svc);
302#ifdef DEBUG_ACTIONSTEPS
317 myCandi->lastStopped = vehicle;
323#ifdef DEBUG_ACTIONSTEPS
325 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
328 bool changed =
false;
352 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
356 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
367 (
myCandi - 1)->lastBlocked = vehicle;
368 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
369 (
myCandi - 1)->firstBlocked = vehicle;
384 (
myCandi + 1)->lastBlocked = vehicle;
385 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
386 (
myCandi + 1)->firstBlocked = vehicle;
431 <<
" veh=" << vehicle->
getID()
434 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
445 bool changed =
false;
447 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
448 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
456 to->registerHop(vehicle);
478 to->registerHop(vehicle);
479 to->lane->requireCollisionCheck();
500 to->registerHop(vehicle);
504 from->registerHop(vehicle);
505 from->lane->requireCollisionCheck();
522#ifdef DEBUG_CONTINUE_CHANGE
525 <<
" continueChange veh=" << vehicle->
getID()
527 <<
" dir=" << direction
528 <<
" speedLat=" << speedLat
529 <<
" pastMidpoint=" << pastMidpoint
541std::pair<MSVehicle* const, double>
545#ifdef DEBUG_SURROUNDING_VEHICLES
547 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
553#ifdef DEBUG_SURROUNDING_VEHICLES
555 if (neighLead != 0) {
556 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
562 if (target->hoppedVeh !=
nullptr) {
563 double hoppedPos = target->hoppedVeh->getPositionOnLane();
564#ifdef DEBUG_SURROUNDING_VEHICLES
566 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
570 neighLead = target->hoppedVeh;
575 const bool checkBidi = target->lane->getBidiLane() !=
nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
576 if (neighLead ==
nullptr || checkBidi) {
577#ifdef DEBUG_SURROUNDING_VEHICLES
579 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
584 MSLane* targetLane = target->lane;
586 double leaderBack = targetLane->
getLength();
587 if (neighLead !=
nullptr) {
591 double plBack = pl->getBackPositionOnLane(targetLane);
592 if (pl->isBidiOn(targetLane)) {
593 plBack -= pl->getVehicleType().getLengthWithGap();
595 const double plPos = plBack + pl->getVehicleType().getLength();
596#ifdef DEBUG_SURROUNDING_VEHICLES
598 std::cout <<
" partial=" << pl->getID() <<
" plBack=" << plBack <<
" plPos=" << plPos <<
" leaderBack=" << leaderBack <<
" egoBack=" << egoBack <<
"\n";
601 if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
606 if (neighLead !=
nullptr) {
607#ifdef DEBUG_SURROUNDING_VEHICLES
609 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
613 return std::pair<MSVehicle*, double>(neighLead, gap);
618 if (target->lane->getBidiLane() !=
nullptr) {
619 dist += target->lane->getBidiLane()->getMaximumBrakeDist();
622 if (seen > dist && !
myCandi->lane->isInternal()) {
623#ifdef DEBUG_SURROUNDING_VEHICLES
625 std::cout <<
" found no leader within dist=" << dist <<
"\n";
628 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
632 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
633#ifdef DEBUG_SURROUNDING_VEHICLES
640#ifdef DEBUG_SURROUNDING_VEHICLES
642 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
650std::pair<MSVehicle* const, double>
654#ifdef DEBUG_SURROUNDING_VEHICLES
656 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
662 neighFollow =
veh(target);
665 if (target->lane->myVehicles.size() > 1) {
666 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
670#ifdef DEBUG_SURROUNDING_VEHICLES
672 if (neighFollow != 0) {
673 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
675 std::cout <<
"veh(target) returns none." << std::endl;
681#ifdef DEBUG_SURROUNDING_VEHICLES
683 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
684 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
693#ifdef DEBUG_SURROUNDING_VEHICLES
696 if (partialBehind != 0 && partialBehind != neighFollow) {
697 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
702 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
704 if (neighFollow ==
nullptr) {
706#ifdef DEBUG_SURROUNDING_VEHICLES
708 if (consecutiveFollower.first == 0) {
709 std::cout <<
"no follower found." << std::endl;
711 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
715 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
717#ifdef DEBUG_SURROUNDING_VEHICLES
719 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
722 return std::pair<MSVehicle* const, double>(neighFollow,
746 const std::pair<MSVehicle* const, double>& leader,
747 const std::vector<MSVehicle::LaneQ>& preb)
const {
752 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
755 neighFollow.first = 0;
758 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
765 const std::pair<MSVehicle* const, double>& leader,
766 const std::pair<MSVehicle* const, double>& follower,
767 const std::pair<MSVehicle* const, double>& neighLead,
768 const std::pair<MSVehicle* const, double>& neighFollow,
769 const std::vector<MSVehicle::LaneQ>& preb)
const {
773#ifdef DEBUG_CHECK_CHANGE
776 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
785 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
789#ifdef DEBUG_CHECK_CHANGE
792 <<
" overlapping with follower..."
798 if (neighLead.first !=
nullptr && neighLead.second < 0) {
801#ifdef DEBUG_CHECK_CHANGE
804 <<
" overlapping with leader..."
816 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
824 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
827 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
829#ifdef DEBUG_CHECK_CHANGE
832 <<
" follower=" << neighFollow.first->getID()
833 <<
" backGap=" << neighFollow.second
834 <<
" vNextFollower=" << vNextFollower
835 <<
" vNextEgo=" << vNextLeader
836 <<
" secureGap=" << secureBackGap
844 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
849#ifdef DEBUG_CHECK_CHANGE
851 std::cout <<
" ignoring opposite follower who changed in this step\n";
855 blocked |= blockedByFollower;
861 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
870 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
874#ifdef DEBUG_CHECK_CHANGE
877 <<
" leader=" << neighLead.first->getID()
878 <<
" frontGap=" << neighLead.second
879 <<
" vNextEgo=" << vNextFollower
880 <<
" vNextLeader=" << vNextLeader
881 <<
" secureGap=" << secureFrontGap
888 blocked |= blockedByLeader;
895 if (nextLeader.first != 0) {
899#ifdef DEBUG_CHECK_CHANGE
901 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
904 if (brakeGap > gap) {
905 blocked |= blockedByLeader;
906#ifdef DEBUG_CHECK_CHANGE
908 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
915 if (leader.first !=
nullptr) {
916 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
921 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
930 const double speed = vehicle->
getSpeed();
932 if (seen < dist || myCandi->lane->isInternal()) {
933 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
934 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
936 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
938#ifdef DEBUG_SURROUNDING_VEHICLES
940 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
941 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
944 if (neighLead2.second < secureGap2) {
945 state |= blockedByLeader;
952 double targetZipperDist = 0;
953 if (laneOffset == 0) {
954 targetZipperDist =
myCandi->zipperDist;
955 }
else if (laneOffset == 1) {
957 targetZipperDist = (
myCandi + 1)->zipperDist;
959 }
else if (laneOffset == -1) {
961 targetZipperDist = (
myCandi - 1)->zipperDist;
965 state |= blockedByLeader;
977 if (estimatedLCDuration == -1) {
979#ifdef DEBUG_CHECK_CHANGE
981 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
982 <<
"\nestimatedLCDuration=" << estimatedLCDuration
983 <<
"\ndistToNeighLane=" << distToNeighLane
991 const double avgSpeed = 0.5 * (
995 const double space2change = avgSpeed * estimatedLCDuration;
998#ifdef DEBUG_CHECK_CHANGE
1000 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
1001 <<
"\ndistToNeighLane=" << distToNeighLane
1002 <<
" estimatedLCDuration=" << estimatedLCDuration
1003 <<
" space2change=" << space2change
1004 <<
" avgSpeed=" << avgSpeed
1013 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1014 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
1018 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
1023 if ((*link)->getViaLane() ==
nullptr) {
1026 nextLane = (*link)->getViaLaneOrLane();
1031#ifdef DEBUG_CHECK_CHANGE
1033 std::cout <<
" available distance=" << seen << std::endl;
1036 if (nextLane->
isLinkEnd(link) && seen < space2change) {
1037#ifdef DEBUG_CHECK_CHANGE
1039 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1048 const double speed = vehicle->
getSpeed();
1050 nextLane = vehicle->
getLane();
1053 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1054 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1055 nextLane = (*nextLink)->getViaLaneOrLane();
1057 if (parallelLane ==
nullptr) {
1061 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1062 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1064 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1065 state |= blockedByLeader;
1069 if ((*nextLink)->getViaLane() ==
nullptr) {
1079 const int oldstate = state;
1083#ifdef DEBUG_CHECK_CHANGE
1086 <<
" veh=" << vehicle->
getID()
1106 if (laneOffset != 0) {
1128 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1129 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1132 const int bestOffset = preb[laneIndex].bestLaneOffset;
1143 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1147 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1155 double oncomingSpeed;
1156 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1157 if (!isOpposite && surplusGap < 0) {
1158#ifdef DEBUG_CHANGE_OPPOSITE
1160 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1161 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1167 if (bestOffset > 0) {
1168 MSLane*
const target = preb[laneIndex + 1].lane;
1180std::vector<MSVehicle::LaneQ>
1187 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1188 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1189 for (
int i = 0; i < numOpposite; i++) {
1190 preb.push_back(preb.back());
1191 preb.back().lane = oLanes[numOpposite - 1 - i];
1192 preb.back().length = oppositeLength;
1194 preb.back().bestLaneOffset = -1 - i;
1198 if (stopLane !=
nullptr) {
1199 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1200 for (
int i = 0; i < (int)preb.size(); i++) {
1201 preb[i].bestLaneOffset = stopIndex - i;
1206#ifdef DEBUG_CHANGE_OPPOSITE
1208 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1209 for (
int i = 0; i < (int)preb.size(); i++) {
1210 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1228#ifdef DEBUG_CHANGE_OPPOSITE
1231 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1236 if (opposite ==
nullptr) {
1246 bool oppositeChangeByTraci =
false;
1249 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1253 oppositeChangeByTraci =
true;
1257#ifdef DEBUG_CHANGE_OPPOSITE
1259 std::cout <<
" not overtaking due to changeLeft restriction\n";
1270 const MSLane* oncomingLane = isOpposite ? source : opposite;
1273 int direction = isOpposite ? -1 : 1;
1274 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1277 double surplusGap = std::numeric_limits<double>::max();
1286 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1288 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1290 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1302 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1308 if (!isOpposite && !oppositeChangeByTraci
1310 && leader.first !=
nullptr) {
1315#ifdef DEBUG_CHANGE_OPPOSITE
1317 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1323 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1326 }
else if (leader.second < 0) {
1328#ifdef DEBUG_CHANGE_OPPOSITE
1330 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1338 double timeToOvertake = std::numeric_limits<double>::max();
1339 double spaceToOvertake = std::numeric_limits<double>::max();
1340 double maxSpaceToOvertake = 0;
1342 if (oppositeChangeByTraci) {
1352 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1353 overtaken = neighLead;
1355 if (overtaken.first !=
nullptr) {
1358#ifdef DEBUG_CHANGE_OPPOSITE
1360 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1361 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1362 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1369 if (overtaken.first == 0) {
1372#ifdef DEBUG_CHANGE_OPPOSITE
1374 std::cout <<
" no leader found\n";
1379 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1384#ifdef DEBUG_CHANGE_OPPOSITE
1386 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1394 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1395#ifdef DEBUG_CHANGE_OPPOSITE
1398 <<
" veh=" << vehicle->
getID()
1399 <<
" changeOpposite opposite=" << opposite->
getID()
1401 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1403 <<
" timeToOvertake=" << timeToOvertake
1404 <<
" spaceToOvertake=" << spaceToOvertake
1410#ifdef DEBUG_CHANGE_OPPOSITE
1412 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1420 if (!wait && lastStopped !=
nullptr) {
1422#ifdef DEBUG_CHANGE_OPPOSITE
1424 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1427 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1436 assert(timeToOvertake != std::numeric_limits<double>::max());
1437 assert(spaceToOvertake != std::numeric_limits<double>::max());
1440 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1447 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1450 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1453 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1454 if (oncomingGap > 0) {
1457#ifdef DEBUG_CHANGE_OPPOSITE
1459 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1460 <<
" halting=" << oncoming.first->getWaitingSeconds()
1461 <<
" oncomingGap=" << oncomingGap
1463 <<
" vMax=" << vMax <<
"\n";
1470 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1471#ifdef DEBUG_CHANGE_OPPOSITE
1473 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1474 <<
" timeToOvertake=" << timeToOvertake
1475 <<
" spaceToOvertake=" << spaceToOvertake
1482#ifdef DEBUG_CHANGE_OPPOSITE
1484 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1492#ifdef DEBUG_CHANGE_OPPOSITE
1494 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1499 assert(timeToOvertake != std::numeric_limits<double>::max());
1500 assert(spaceToOvertake != std::numeric_limits<double>::max());
1504 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1505 if (oncomingOpposite.first !=
nullptr) {
1506 double oncomingSpeed2;
1507 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1509 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1510#ifdef DEBUG_CHANGE_OPPOSITE
1512 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1515 surplusGap =
MIN2(surplusGap, surplusGap2);
1516 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1517 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1518 && oncomingOpposite.second > oncoming.second) {
1522 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1525 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1526 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1527 double ooTTO = ooSTO / oSpeed;
1529 ooTTO = ceil(ooTTO /
TS) *
TS;
1530 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1531#ifdef DEBUG_CHANGE_OPPOSITE
1533 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1536 surplusGap =
MIN2(surplusGap, surplusGap3);
1539 if (!isOpposite && surplusGap < 0) {
1540#ifdef DEBUG_CHANGE_OPPOSITE
1542 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1546#ifdef DEBUG_CHANGE_OPPOSITE
1548 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1549 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1561 if (usableDist < spaceToOvertake) {
1564 assert(bestLaneConts.size() >= 1);
1565 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1566 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1567#ifdef DEBUG_CHANGE_OPPOSITE
1569 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1578 const MSLane*
const prev = *(it - 1);
1579 if (prev !=
nullptr) {
1588#ifdef DEBUG_CHANGE_OPPOSITE
1590 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1596 usableDist += (*it)->getLength();
1600 if (!isOpposite && usableDist < spaceToOvertake) {
1601#ifdef DEBUG_CHANGE_OPPOSITE
1603 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1612 bool foundHill = vehicle->
getSlope() > 0;
1617#ifdef DEBUG_CHANGE_OPPOSITE
1619 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1624 double oppositeLength = vehicle->
getBestLanes().back().length;
1627 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1628 leader.first =
nullptr;
1629 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1631 neighLead.first =
nullptr;
1635#ifdef DEBUG_CHANGE_OPPOSITE
1637 std::cout <<
" not changing to avoid deadlock\n";
1642 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1648 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1656 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1662 std::pair<MSVehicle*, double> neighLead,
1663 std::pair<MSVehicle*, double> overtaken,
1664 std::pair<MSVehicle*, double> leader) {
1666#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1668 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1675 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1677 }
else if (!neighLead.first->isStopped()
1681 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1682 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1683 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1684#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1686 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1689 if (neighLead.first ==
nullptr) {
1696 if (neighLead.first->isStopped()
1697 && (overtaken.first->isStopped()
1698 || leader.first->getLaneChangeModel().isOpposite()
1703 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1704 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1706 const double distToStop = neighLead.second - requiredGap;
1710 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1711 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1712 if (neighStoppedBack + nextGap > overtaken.second) {
1715 neighStoppedBack += nextGap;
1716 auto neighLeadFollow = neighLead.first->getFollower();
1717 neighLead.second = neighLeadFollow.second;
1718 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1719#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1724 if (neighStoppedBack > overtaken.second) {
1729 const double leaderBGap = leader.first->
getBrakeGap();
1730 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1731 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1733#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1735 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1736 <<
" neighLeadGap=" << neighLead.second
1737 <<
" leaderGap=" << leader.second
1738 <<
" bGap=" << leaderBGap
1739 <<
" fGap=" << leaderFGap
1740 <<
" eGap=" << extraGap
1741 <<
" neighStoppedBack=" << neighStoppedBack
1743 <<
" requiredGap=" << requiredGap
1744 <<
" gapWithEgo=" << gapWithEgo
1745 <<
" yield=" << yield
1750 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1751 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1752 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1754#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1756 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1759 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1760 const double blockerLength = currentDist - stopPos;
1762#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1764 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1765 <<
" blockerLength=" << blockerLength
1766 <<
" reserved=" << reserved
1784 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1786 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1787 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1788 follower = follower.first->getFollower(dist);
1790 if (follower.first !=
nullptr) {
1791 followerGap += follower.second;
1793#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1795 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1796 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1800 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1808 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1809 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1810 follower = follower.first->getFollower(dist);
1812#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1813 if (
DEBUG_COND && follower.first !=
nullptr) {
1814 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1815 <<
" oncoming=" << follower.first->getID()
1816 <<
" wait=" << follower.first->getWaitingSeconds()
1822 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1831 std::pair<MSVehicle* const, double> leader,
1832 std::pair<MSVehicle*, double> neighLead,
1833 std::pair<MSVehicle*, double> overtaken) {
1834 const double deadLockZone = overtaken.second;
1835#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1839 <<
" gap=" << leader.second
1848 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1849#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1851 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1852 <<
" leader=" << leader.first->getID()
1853 <<
" leaderGap=" << leader.second
1855 <<
" deadLockZone=" << deadLockZone
1859 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1862 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1863 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1864 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1865#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1867 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1872 if (oncomingOpposite.first !=
nullptr ||
1873 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1875 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1876 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1880#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1882 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1883 <<
" leader=" << leader.first->getID()
1884 <<
" leaderGap=" << leader.second
1886 <<
" currentDist=" << currentDist
1887 <<
" blockerLength=" << blockerLength
1888 <<
" reserved=" << reserved
1903 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1904 std::pair<MSVehicle*, double> neighLead,
1905 std::pair<MSVehicle*, double> overtaken,
1906 std::pair<MSVehicle*, double> neighFollow,
1907 double surplusGap,
const MSLane* opposite,
1917 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1919 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1920#ifdef DEBUG_CHANGE_OPPOSITE
1922 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1926 const MSVehicle* oncomingVeh = oncoming.first;
1927 if (oncomingVeh != 0) {
1929 double egoSpeedFraction = 0.5;
1930 if (oncomingSpeed > 0) {
1931 egoSpeedFraction =
MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1933 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1934#ifdef DEBUG_CHANGE_OPPOSITE
1936 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1937 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1941#ifdef DEBUG_CHANGE_OPPOSITE
1943 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1947 if (neighLead.first !=
nullptr) {
1948 if (overtaken.first ==
nullptr) {
1949#ifdef DEBUG_CHANGE_OPPOSITE
1951 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1954 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
1955 && neighLead.second > 0
1956 && neighFollow.second > 0
1959 oppositeLength = forwardPos + neighLead.second;
1961 if (surplusGap > 0) {
1964 oppositeLength += 1000;
1967 if (overtaken.second > 0) {
1968 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1973#ifdef DEBUG_CHANGE_OPPOSITE
1975 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1976 <<
" surplusGap=" << surplusGap
1977 <<
" final laneQLength=" << oppositeLength
1984 if (overtaken.first ==
nullptr || !canOvertake) {
1987 if (oppFollow.first ==
nullptr) {
1988 oppositeLength = forwardPos;
1990 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1992#ifdef DEBUG_CHANGE_OPPOSITE
1994 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
1997 if (oppFollow.second > secureGap) {
1999 oppositeLength = forwardPos;
2004#ifdef DEBUG_CHANGE_OPPOSITE
2006 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
2009 return oppositeLength;
2013std::pair<MSVehicle* const, double>
2016 double gap = oncoming.second;
2017 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
2018 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
2020 gap += oncoming.first->getVehicleType().getLengthWithGap();
2021 if (oncoming.first != overtaken) {
2022 vMax =
MIN2(vMax, oncoming.first->getSpeed());
2024#ifdef DEBUG_CHANGE_OPPOSITE
2026 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
2027 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
2030 if (searchDist < 0) {
2034 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2035 opposite = oncoming.first->getLane();
2037 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2038 if (oncoming.first !=
nullptr) {
2039 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2040#ifdef DEBUG_CHANGE_OPPOSITE
2042 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
2047 oncoming.second = gap;
2052std::pair<MSVehicle* const, double>
2056 if (overtaken.first !=
nullptr) {
2058 front = overtaken.first;
2066 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2068 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2069 conts.erase(conts.begin());
2072 if (oncoming.first !=
nullptr) {
2073 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2074 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2075#ifdef DEBUG_CHANGE_OPPOSITE
2078 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2079 <<
" oncomingOpposite=" << oncoming.first->getID()
2080 <<
" gap=" << oncoming.second
2081 <<
" isOpposite=" << isOpposite
2086 if (isOpposite && shadowLane != front->
getLane()) {
2088 oncoming.second -= oncoming.first->getVehicleType().getLength();
2089 oncoming.second += gap;
2093 return std::make_pair(
nullptr, -1);
2099 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2100 double surplusGap = std::numeric_limits<double>::max();
2101 const MSVehicle* oncomingVeh = oncoming.first;
2102 if (oncomingVeh != 0 && (oncomingOpposite
2113 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2114#ifdef DEBUG_CHANGE_OPPOSITE
2117 <<
" oncoming=" << oncomingVeh->
getID()
2118 <<
" oGap=" << oncoming.second
2119 <<
" oSpeed=" << oncomingSpeed
2120 <<
" sto=" << spaceToOvertake
2121 <<
" tto=" << timeToOvertake
2122 <<
" safetyGap=" << safetyGap
2123 <<
" surplusGap=" << surplusGap
2133 if (view >= (
int)bestLanes.size()) {
2136 MSLane* lane = bestLanes[view];
2137 double laneDist = 0;
2139 double lastZ = lastMax;
2140 for (
int i = 1; i < (int)shape.size(); i++) {
2143 if (laneDist > pos) {
2144 const double z = shape[i].z();
2152#ifdef DEBUG_CHANGE_OPPOSITE
2154 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2157 if (foundHill && z < lastMax) {
2158 const double drop = lastMax - z;
2160 if (drop > hilltopThreshold) {
2161#ifdef DEBUG_CHANGE_OPPOSITE
2163 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2164 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2173 searchDist -= laneDist - pos;
2176 if (searchDist <= 0) {
2181 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2190 const std::pair<MSVehicle* const, double>& leader,
2191 const std::pair<MSVehicle* const, double>& neighLead,
2192 const std::pair<MSVehicle* const, double>& neighFollow,
2193 const std::vector<MSVehicle::LaneQ>& preb) {
2196 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2197 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2199 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2205#ifdef DEBUG_CHANGE_OPPOSITE
2207 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2216#ifdef DEBUG_CHANGE_OPPOSITE
2218 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2235 const double v = vehicle->
getSpeed();
2239 const double g =
MAX2(0.0, (
2250 const double sign = -1;
2254 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2255#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2257 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2258 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2265 timeToOvertake = std::numeric_limits<double>::max();
2266 spaceToOvertake = std::numeric_limits<double>::max();
2274 t = ceil(t /
TS) *
TS;
2278 const double timeToMaxSpeed = (vMax - v) / a;
2280#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2282 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2285 if (t <= timeToMaxSpeed) {
2287 spaceToOvertake = v * t + t * t * a * 0.5;
2288#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2290 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2295 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2296 const double m = timeToMaxSpeed;
2299 t = (g - s + m * vMax) / (vMax - u);
2302#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2304 std::cout <<
" t2=" << t <<
"\n";
2307 timeToOvertake = std::numeric_limits<double>::max();
2308 spaceToOvertake = std::numeric_limits<double>::max();
2315 t = ceil(t /
TS) *
TS;
2318 spaceToOvertake = s + (t - m) * vMax;
2319#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2321 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2327 timeToOvertake *= safetyFactor;
2329 spaceToOvertake *= safetyFactor;
2331 double frac = fmod(timeToOvertake,
TS);
2334 timeToOvertake +=
TS - frac;
2336#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2338 if (safetyFactor != 1) {
2339 std::cout <<
" applying safetyFactor=" << safetyFactor
2341 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2349std::pair<MSVehicle*, double>
2351 assert(leader.first != 0);
2357 std::pair<MSVehicle*, double> columnLeader = leader;
2358 double egoGap = leader.second;
2359 bool foundSpaceAhead =
false;
2360 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2362 if (maxLookAhead == std::numeric_limits<double>::max()) {
2363 maxLookAhead = (isEmergency
2366 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2368 + leader.first->getVehicleType().getLengthWithGap());
2370#ifdef DEBUG_CHANGE_OPPOSITE
2372 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2376 while (!foundSpaceAhead) {
2377 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2378 columnLeader.first, vehicle,
2380 + columnLeader.first->getVehicleType().getMinGap()
2385 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2386 double searchStart = columnLeader.first->getPositionOnLane();
2387 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2388 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2390 std::set<MSVehicle*> seenLeaders;
2391 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2392#ifdef DEBUG_CHANGE_OPPOSITE
2394 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2397 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2398 leadLead.first =
nullptr;
2401 seenLeaders.insert(leadLead.first);
2403 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2404 leadLead = columnLeader.first->getLane()->getLeader(
2405 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2407 leadLead.second += (searchStart2 - searchStart);
2409 if (leadLead.first ==
nullptr) {
2410 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2411 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2412 if (!columnLeader.first->isStopped()) {
2414 requiredSpace += safetyFactor * mergeBrakeGap;
2416#ifdef DEBUG_CHANGE_OPPOSITE
2418 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2419 <<
" availableSpace=" << availableSpace
2420 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2421 <<
" ovSpeed=" << overtakingSpeed
2422 <<
" reqBGap=" << mergeBrakeGap
2423 <<
" reqMin=" << requiredSpace / safetyFactor
2424 <<
" req=" << requiredSpace
2428 if (availableSpace > requiredSpace) {
2429 foundSpaceAhead =
true;
2433 bool contsEnd =
false;
2434 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, isEmergency, contsEnd);
2435#ifdef DEBUG_CHANGE_OPPOSITE
2437 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2440 while (next !=
nullptr && seen < maxLookAhead) {
2443 if (cand ==
nullptr) {
2445 if (availableSpace > requiredSpace) {
2446 foundSpaceAhead =
true;
2449 next =
getLaneAfter(next, conts, isEmergency, contsEnd);
2452 if (availableSpace > requiredSpace) {
2453 foundSpaceAhead =
true;
2460#ifdef DEBUG_CHANGE_OPPOSITE
2462 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2465 if (!foundSpaceAhead && contsEnd) {
2466 foundSpaceAhead =
true;
2467 availableSpace = requiredSpace;
2469 if (!foundSpaceAhead) {
2470 return std::make_pair(
nullptr, -1);
2473 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2476 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2477 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2478 if (!columnLeader.first->isStopped()) {
2480 requiredSpace += safetyFactor * sGap;
2482#ifdef DEBUG_CHANGE_OPPOSITE
2484 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2485 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2486 <<
" ovSpeed=" << overtakingSpeed
2487 <<
" reqSGap=" << sGap
2488 <<
" reqMin=" << requiredSpace / safetyFactor
2489 <<
" req=" << requiredSpace
2493 if (leadLead.second > requiredSpace) {
2494 foundSpaceAhead =
true;
2495 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2498 if (leadLead.second < 0) {
2500#ifdef DEBUG_CHANGE_OPPOSITE
2502 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2505 return std::make_pair(
nullptr, -1);
2508#ifdef DEBUG_CHANGE_OPPOSITE
2510 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2513 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2514 if (seen > maxLookAhead) {
2515#ifdef DEBUG_CHANGE_OPPOSITE
2517 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2520 return std::make_pair(
nullptr, -1);
2523 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2524 columnLeader = leadLead;
2525#ifdef DEBUG_CHANGE_OPPOSITE
2527 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2533 columnLeader.second = egoGap;
2534 return columnLeader;
2540 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2542 if (it + 1 != conts.end()) {
2544 const MSLane* next = *(it + 1);
2546 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2564 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
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class responsible for exchanging messages between cars involved in lane-change interaction.
Interface for lane-change models.
double getLaneChangeCompletion() const
Get the current lane change completion ratio.
double getForwardPos() const
get vehicle position relative to the forward direction lane
void setFollowerGaps(CLeaderDist follower, double secGap)
virtual void setOwnState(const int state)
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change.
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
static const double NO_NEIGHBOR
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
virtual bool saveBlockerLength(double, double)
reserve space at the end of the lane to avoid dead locks
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
virtual double getOppositeSafetyFactor() const
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
void setLeaderGaps(CLeaderDist, double secGap)
void setOrigLeaderGaps(CLeaderDist, double secGap)
int getNormalizedLaneIndex()
brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
virtual int checkChangeBeforeCommitting(const MSVehicle *veh, int state) const
Informs the vehicle that it is about to be moved on an adjacent lane. The method can be used to re-ev...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
void clearNeighbors()
Clear info on neighboring vehicle from previous step.
void saveNeighbors(const int dir, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &leaders)
Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direct...
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
const MSStop & getNextStop() const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
A road/street connecting two junctions.
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
bool isInternal() const
return whether this edge is an internal edge
static double gLateralResolution
static bool gLefthand
Whether lefthand-drive is being simulated.
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
static SUMOTime gLaneChangeDuration
virtual ~MSLaneChanger()
Destructor.
bool applyTraCICommands(MSVehicle *vehicle)
Execute TraCI LC-commands.
bool continueChange(MSVehicle *vehicle, ChangerIt &from)
continue a lane change maneuver and return whether the vehicle has completely moved onto the new lane...
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
bool checkOppositeStop(MSVehicle *vehicle, const MSLane *oncomingLane, const MSLane *opposite, std::pair< MSVehicle *, double > leader)
decide whether to change (back or forth) for an opposite stop
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, MSVehicle *lastStopped)
MSLaneChanger()
Default constructor.
static bool hasOppositeStop(MSVehicle *vehicle)
whether vehicle has an opposite-direction stop within relevant range
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
virtual void initChanger()
Initialize the changer before looping over all vehicles.
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one.
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
static const MSLane * getLaneAfter(const MSLane *lane, const std::vector< MSLane * > &conts, bool allowMinor, bool &contsEnd)
return the next lane in conts beyond lane or nullptr
std::pair< MSVehicle *const, double > getOncomingOppositeVehicle(const MSVehicle *vehicle, std::pair< MSVehicle *, double > overtaken, double searchDist)
MSVehicle * veh(ConstChangerIt ce) const
std::pair< MSVehicle *const, double > getOncomingVehicle(const MSLane *opposite, std::pair< MSVehicle *, double > neighOncoming, double searchDist, double &vMax, const MSVehicle *overtaken=nullptr, MSLane::MinorLinkMode mLinkMode=MSLane::MinorLinkMode::FOLLOW_NEVER)
bool startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
const bool myAllowsChanging
double computeSafeOppositeLength(MSVehicle *vehicle, double oppositeLength, const MSLane *source, double usableDist, std::pair< MSVehicle *, double > oncoming, double vMax, double oncomingSpeed, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > neighFollow, double surplusGap, const MSLane *opposite, bool canOvertake)
determine for how long the vehicle can drive safely on the opposite side
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
static bool foundHilltop(MSVehicle *vehicle, bool foundHill, double searchDist, const std::vector< MSLane * > &bestLanes, int view, double pos, double lastMax, double hilltopThreshold)
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
static double computeSurplusGap(const MSVehicle *vehicle, const MSLane *opposite, std::pair< MSVehicle *, double > oncoming, double timeToOvertake, double spaceToOvertake, double &oncomingSpeed, bool oncomingOpposite=false)
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
bool yieldToOppositeWaiting(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist, SUMOTime deltaWait=0)
check whether to yield for oncoming vehicles that have waited longer for opposite overtaking
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
void registerUnchanged(MSVehicle *vehicle)
void updateLanes(SUMOTime t)
bool avoidDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > leader)
avoid opposite-diretion deadlock when vehicles are stopped on both sides of the road The method may c...
static std::pair< MSVehicle *, double > getColumnleader(double &maxSpace, MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
return leader vehicle that is to be overtaken
static double getMaxOvertakingSpeed(const MSVehicle *vehicle, double maxSpaceToOvertake)
compute maximum maneuver speed
bool resolveDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *const, double > leader, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken)
keep stopping to resolve opposite-diretion deadlock while there is oncoming traffic The method may ca...
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
bool yieldToDeadlockOncoming(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist)
check whether to keep stopping for oncoming vehicles in the deadlock zone
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
int checkChange(int laneOffset, const MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &follower, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb) const
virtual bool checkChangeOpposite(MSVehicle *vehicle, int laneOffset, MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb)
static void computeOvertakingTime(const MSVehicle *vehicle, double vMax, const MSVehicle *leader, double gap, double &timeToOvertake, double &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
static std::vector< MSVehicle::LaneQ > getBestLanesOpposite(MSVehicle *vehicle, const MSLane *stopLane, double oppositeLength)
add LaneQ for opposite lanes
virtual void updateChanger(bool vehHasChanged)
Representation of a lane in the micro simulation.
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, MinorLinkMode mLinkMode) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
std::vector< MSVehicle * > VehCont
Container for vehicles.
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode=MinorLinkMode::FOLLOW_NEVER) const
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
double getLength() const
Returns the lane's length.
bool allowsChangingLeft(SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
std::pair< MSVehicle *const, double > getCriticalLeader(double dist, double seen, double speed, const MSVehicle &veh) const
Returns the most dangerous leader and the distance to him.
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
bool allowsVehicleClass(SUMOVehicleClass vclass) const
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
bool hasPedestrians() const
whether the lane has pedestrians on it
int getIndex() const
Returns the lane's index.
void requireCollisionCheck()
require another collision check due to relevant changes in the simulation
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
double interpolateGeometryPosToLanePos(double geometryPos) const
std::pair< MSVehicle *const, double > getLeader(const MSVehicle *veh, const double vehPos, const std::vector< MSLane * > &bestLaneConts, double dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
virtual const PositionVector & getShape(bool) const
MSEdge & getEdge() const
Returns the lane's edge.
double getWidth() const
Returns the lane's width.
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
LinkState getState() const
Returns the current state of the link.
bool havePriority() const
Returns whether this link is a major link.
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
LinkDirection getDirection() const
Returns the direction the vehicle passing this link take.
bool haveRed() const
Returns whether this link is blocked by a red (or redyellow) traffic light.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
bool hasElevation() const
return whether the network contains elevation data
const MSLane * lane
The lane to stop at (microsim only)
bool isOpposite
whether this an opposite-direction stop
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected (concerns approaching vehicles outside the...
SUMOTime getLaneTimeLineDuration()
double myPosLat
the stored lateral position
Representation of a vehicle in the micro simulation.
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
double computeAngle() const
compute the current vehicle angle
bool isStoppedOnLane() const
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
SUMOTime getWaitingTime(const bool accumulated=false) const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
MSAbstractLaneChangeModel & getLaneChangeModel()
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
bool unsafeLinkAhead(const MSLane *lane, double zipperDist) const
whether the vehicle may safely move to the given lane with regard to upcoming links
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
const MSLane * getLane() const
Returns the lane the vehicle is on.
std::pair< const MSVehicle *const, double > getFollower(double dist=0) const
Returns the follower of the vehicle looking for a fixed distance.
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
double getSpeed() const
Returns the vehicle's current speed.
Position myCachedPosition
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
double myAngle
the angle in radians (
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignored
double getPositionOnLane() const
Get the vehicle's position along the lane.
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
double getBrakeGap(bool delayed=false) const
get distance for coming to a stop (used for rerouting checks)
State myState
This Vehicles driving state (pos and speed)
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
static const Position INVALID
used to indicate that a position is valid
double z() const
Returns the z-position.
#define UNUSED_PARAMETER(x)
ChangeElem(MSLane *_lane)
double zipperDist
visibility distance to the closest zipper link that may be encountered when driving on this lane
MSLane * lane
the lane corresponding to this ChangeElem (the current change candidate is on this lane)
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.