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
300 myCandi->lastStopped = vehicle;
306#ifdef DEBUG_ACTIONSTEPS
308 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
311 bool changed =
false;
335 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
339 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
350 (
myCandi - 1)->lastBlocked = vehicle;
351 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
352 (
myCandi - 1)->firstBlocked = vehicle;
367 (
myCandi + 1)->lastBlocked = vehicle;
368 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
369 (
myCandi + 1)->firstBlocked = vehicle;
414 <<
" veh=" << vehicle->
getID()
417 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
428 bool changed =
false;
430 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
431 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
439 to->registerHop(vehicle);
461 to->registerHop(vehicle);
462 to->lane->requireCollisionCheck();
483 to->registerHop(vehicle);
487 from->registerHop(vehicle);
488 from->lane->requireCollisionCheck();
505#ifdef DEBUG_CONTINUE_CHANGE
508 <<
" continueChange veh=" << vehicle->
getID()
510 <<
" dir=" << direction
511 <<
" speedLat=" << speedLat
512 <<
" pastMidpoint=" << pastMidpoint
524std::pair<MSVehicle* const, double>
528#ifdef DEBUG_SURROUNDING_VEHICLES
530 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
536#ifdef DEBUG_SURROUNDING_VEHICLES
538 if (neighLead != 0) {
539 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
545 if (target->hoppedVeh !=
nullptr) {
546 double hoppedPos = target->hoppedVeh->getPositionOnLane();
547#ifdef DEBUG_SURROUNDING_VEHICLES
549 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
553 neighLead = target->hoppedVeh;
557 if (neighLead ==
nullptr) {
558#ifdef DEBUG_SURROUNDING_VEHICLES
560 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
565 MSLane* targetLane = target->lane;
567 double leaderBack = targetLane->
getLength();
570 if (plBack < leaderBack &&
576 if (neighLead !=
nullptr) {
577#ifdef DEBUG_SURROUNDING_VEHICLES
579 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
588 if (seen > dist && !
myCandi->lane->isInternal()) {
589#ifdef DEBUG_SURROUNDING_VEHICLES
591 std::cout <<
" found no leader within dist=" << dist <<
"\n";
594 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
598 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
599#ifdef DEBUG_SURROUNDING_VEHICLES
606#ifdef DEBUG_SURROUNDING_VEHICLES
608 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
616std::pair<MSVehicle* const, double>
620#ifdef DEBUG_SURROUNDING_VEHICLES
622 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
628 neighFollow =
veh(target);
631 if (target->lane->myVehicles.size() > 1) {
632 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
636#ifdef DEBUG_SURROUNDING_VEHICLES
638 if (neighFollow != 0) {
639 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
641 std::cout <<
"veh(target) returns none." << std::endl;
647#ifdef DEBUG_SURROUNDING_VEHICLES
649 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
650 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
659#ifdef DEBUG_SURROUNDING_VEHICLES
662 if (partialBehind != 0 && partialBehind != neighFollow) {
663 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
668 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
670 if (neighFollow ==
nullptr) {
672#ifdef DEBUG_SURROUNDING_VEHICLES
674 if (consecutiveFollower.first == 0) {
675 std::cout <<
"no follower found." << std::endl;
677 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
681 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
683#ifdef DEBUG_SURROUNDING_VEHICLES
685 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
688 return std::pair<MSVehicle* const, double>(neighFollow,
712 const std::pair<MSVehicle* const, double>& leader,
713 const std::vector<MSVehicle::LaneQ>& preb)
const {
718 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
721 neighFollow.first = 0;
724 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
731 const std::pair<MSVehicle* const, double>& leader,
732 const std::pair<MSVehicle* const, double>& follower,
733 const std::pair<MSVehicle* const, double>& neighLead,
734 const std::pair<MSVehicle* const, double>& neighFollow,
735 const std::vector<MSVehicle::LaneQ>& preb)
const {
739#ifdef DEBUG_CHECK_CHANGE
742 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
751 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
755#ifdef DEBUG_CHECK_CHANGE
758 <<
" overlapping with follower..."
764 if (neighLead.first !=
nullptr && neighLead.second < 0) {
767#ifdef DEBUG_CHECK_CHANGE
770 <<
" overlapping with leader..."
782 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
790 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
793 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
795#ifdef DEBUG_CHECK_CHANGE
798 <<
" follower=" << neighFollow.first->getID()
799 <<
" backGap=" << neighFollow.second
800 <<
" vNextFollower=" << vNextFollower
801 <<
" vNextEgo=" << vNextLeader
802 <<
" secureGap=" << secureBackGap
810 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
815#ifdef DEBUG_CHECK_CHANGE
817 std::cout <<
" ignoring opposite follower who changed in this step\n";
821 blocked |= blockedByFollower;
827 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
836 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
840#ifdef DEBUG_CHECK_CHANGE
843 <<
" leader=" << neighLead.first->getID()
844 <<
" frontGap=" << neighLead.second
845 <<
" vNextEgo=" << vNextFollower
846 <<
" vNextLeader=" << vNextLeader
847 <<
" secureGap=" << secureFrontGap
854 blocked |= blockedByLeader;
861 if (nextLeader.first != 0) {
865#ifdef DEBUG_CHECK_CHANGE
867 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
870 if (brakeGap > gap) {
871 blocked |= blockedByLeader;
872#ifdef DEBUG_CHECK_CHANGE
874 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
881 if (leader.first !=
nullptr) {
882 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
887 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
896 const double speed = vehicle->
getSpeed();
898 if (seen < dist || myCandi->lane->isInternal()) {
899 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
900 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
902 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
904#ifdef DEBUG_SURROUNDING_VEHICLES
906 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
907 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
910 if (neighLead2.second < secureGap2) {
911 state |= blockedByLeader;
919 state |= blockedByLeader;
931 if (estimatedLCDuration == -1) {
933#ifdef DEBUG_CHECK_CHANGE
935 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
936 <<
"\nestimatedLCDuration=" << estimatedLCDuration
937 <<
"\ndistToNeighLane=" << distToNeighLane
945 const double avgSpeed = 0.5 * (
949 const double space2change = avgSpeed * estimatedLCDuration;
952#ifdef DEBUG_CHECK_CHANGE
954 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
955 <<
"\ndistToNeighLane=" << distToNeighLane
956 <<
" estimatedLCDuration=" << estimatedLCDuration
957 <<
" space2change=" << space2change
958 <<
" avgSpeed=" << avgSpeed
967 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
968 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
972 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
977 if ((*link)->getViaLane() ==
nullptr) {
980 nextLane = (*link)->getViaLaneOrLane();
985#ifdef DEBUG_CHECK_CHANGE
987 std::cout <<
" available distance=" << seen << std::endl;
990 if (nextLane->
isLinkEnd(link) && seen < space2change) {
991#ifdef DEBUG_CHECK_CHANGE
993 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
1002 const double speed = vehicle->
getSpeed();
1004 nextLane = vehicle->
getLane();
1007 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1008 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1009 nextLane = (*nextLink)->getViaLaneOrLane();
1011 if (parallelLane ==
nullptr) {
1015 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
1016 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
1018 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1019 state |= blockedByLeader;
1023 if ((*nextLink)->getViaLane() ==
nullptr) {
1033 const int oldstate = state;
1036#ifdef DEBUG_CHECK_CHANGE
1039 <<
" veh=" << vehicle->
getID()
1054 if (laneOffset != 0) {
1076 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1077 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1080 const int bestOffset = preb[laneIndex].bestLaneOffset;
1091 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1095 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1103 double oncomingSpeed;
1104 const double surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1105 if (!isOpposite && surplusGap < 0) {
1106#ifdef DEBUG_CHANGE_OPPOSITE
1108 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1109 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1115 if (bestOffset > 0) {
1116 MSLane*
const target = preb[laneIndex + 1].lane;
1128std::vector<MSVehicle::LaneQ>
1135 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1136 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1137 for (
int i = 0; i < numOpposite; i++) {
1138 preb.push_back(preb.back());
1139 preb.back().lane = oLanes[numOpposite - 1 - i];
1140 preb.back().length = oppositeLength;
1142 preb.back().bestLaneOffset = -1 - i;
1146 if (stopLane !=
nullptr) {
1147 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1148 for (
int i = 0; i < (int)preb.size(); i++) {
1149 preb[i].bestLaneOffset = stopIndex - i;
1154#ifdef DEBUG_CHANGE_OPPOSITE
1156 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1157 for (
int i = 0; i < (int)preb.size(); i++) {
1158 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1176#ifdef DEBUG_CHANGE_OPPOSITE
1179 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" considerChangeOpposite source=" << source->
getID()
1184 if (opposite ==
nullptr) {
1194 bool oppositeChangeByTraci =
false;
1197 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1201 oppositeChangeByTraci =
true;
1205#ifdef DEBUG_CHANGE_OPPOSITE
1207 std::cout <<
" not overtaking due to changeLeft restriction\n";
1218 const MSLane* oncomingLane = isOpposite ? source : opposite;
1221 int direction = isOpposite ? -1 : 1;
1222 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1225 double surplusGap = std::numeric_limits<double>::max();
1234 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1236 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1238 std::pair<MSVehicle*, double> oncomingOpposite(
nullptr, -1);
1249 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1255 if (!isOpposite && !oppositeChangeByTraci
1257 && leader.first !=
nullptr) {
1262#ifdef DEBUG_CHANGE_OPPOSITE
1264 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1270 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1273 }
else if (leader.second < 0) {
1275#ifdef DEBUG_CHANGE_OPPOSITE
1277 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1285 double timeToOvertake = std::numeric_limits<double>::max();
1286 double spaceToOvertake = std::numeric_limits<double>::max();
1287 double maxSpaceToOvertake = 0;
1289 if (oppositeChangeByTraci) {
1299 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1300 overtaken = neighLead;
1302 if (overtaken.first !=
nullptr) {
1305#ifdef DEBUG_CHANGE_OPPOSITE
1307 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1308 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1309 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1316 if (overtaken.first == 0) {
1319#ifdef DEBUG_CHANGE_OPPOSITE
1321 std::cout <<
" no leader found\n";
1326 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(
nullptr, leader.second));
1331#ifdef DEBUG_CHANGE_OPPOSITE
1333 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1341 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1342#ifdef DEBUG_CHANGE_OPPOSITE
1345 <<
" veh=" << vehicle->
getID()
1346 <<
" changeOpposite opposite=" << opposite->
getID()
1348 <<
" maxSpaceToOvertake=" << maxSpaceToOvertake
1350 <<
" timeToOvertake=" << timeToOvertake
1351 <<
" spaceToOvertake=" << spaceToOvertake
1357#ifdef DEBUG_CHANGE_OPPOSITE
1359 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1367 if (!wait && lastStopped !=
nullptr) {
1369#ifdef DEBUG_CHANGE_OPPOSITE
1371 std::cout <<
" lastStopped=" <<
Named::getIDSecure(lastStopped) <<
" gap=" << lastStoppedGap <<
"\n";
1374 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1383 assert(timeToOvertake != std::numeric_limits<double>::max());
1384 assert(spaceToOvertake != std::numeric_limits<double>::max());
1387 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1388 neighLead = oncomingLane->
getOppositeLeader(vehicle, searchDist,
true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1389 oncoming =
getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1394 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1397 if (oncoming.first !=
nullptr && (oncoming.first->isStopped()
1400 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1401 if (oncomingGap > 0) {
1404#ifdef DEBUG_CHANGE_OPPOSITE
1406 std::cout <<
" oncoming=" << oncoming.first->getID() <<
" stopped=" << oncoming.first->isStopped()
1407 <<
" halting=" << oncoming.first->getWaitingSeconds()
1408 <<
" oncomingGap=" << oncomingGap
1410 <<
" vMax=" << vMax <<
"\n";
1417 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1418#ifdef DEBUG_CHANGE_OPPOSITE
1420 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1421 <<
" timeToOvertake=" << timeToOvertake
1422 <<
" spaceToOvertake=" << spaceToOvertake
1429#ifdef DEBUG_CHANGE_OPPOSITE
1431 std::cout <<
" cannot changeOpposite (check2: cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1439#ifdef DEBUG_CHANGE_OPPOSITE
1441 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1446 assert(timeToOvertake != std::numeric_limits<double>::max());
1447 assert(spaceToOvertake != std::numeric_limits<double>::max());
1451 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1452 if (oncomingOpposite.first !=
nullptr) {
1453 double oncomingSpeed2;
1454 const double conservativeTime = ceil(timeToOvertake /
TS) *
TS;
1456 const double surplusGap2 =
computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2,
true);
1457#ifdef DEBUG_CHANGE_OPPOSITE
1459 std::cout <<
" oncomingOpposite=" << oncomingOpposite.first->getID() <<
" speed=" << oncomingSpeed2 <<
" gap=" << oncomingOpposite.second <<
" surplusGap2=" << surplusGap2 <<
"\n";
1462 surplusGap =
MIN2(surplusGap, surplusGap2);
1463 oncomingSpeed =
MAX2(oncomingSpeed, oncomingSpeed2);
1464 if (!isOpposite && surplusGap >= 0 && oncoming.first !=
nullptr && oncoming.first->isStopped()
1465 && oncomingOpposite.second > oncoming.second) {
1469 const double oSpeed =
MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1472 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1473 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1474 double ooTTO = ooSTO / oSpeed;
1476 ooTTO = ceil(ooTTO /
TS) *
TS;
1477 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1478#ifdef DEBUG_CHANGE_OPPOSITE
1480 std::cout <<
" oSpeed=" << oSpeed <<
" ooSTO=" << ooSTO <<
" ooTTO=" << ooTTO <<
" surplusGap3=" << surplusGap3 <<
"\n";
1483 surplusGap =
MIN2(surplusGap, surplusGap3);
1486 if (!isOpposite && surplusGap < 0) {
1487#ifdef DEBUG_CHANGE_OPPOSITE
1489 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1493#ifdef DEBUG_CHANGE_OPPOSITE
1495 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1496 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1508 if (usableDist < spaceToOvertake) {
1511 assert(bestLaneConts.size() >= 1);
1512 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1513 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1514#ifdef DEBUG_CHANGE_OPPOSITE
1516 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1519 if ((*it)->getOpposite() ==
nullptr || !(*it)->getOpposite()->allowsVehicleClass(vehicle->
getVClass())) {
1524 const MSLane*
const prev = *(it - 1);
1525 if (prev !=
nullptr) {
1534#ifdef DEBUG_CHANGE_OPPOSITE
1536 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1542 usableDist += (*it)->getLength();
1546 if (!isOpposite && usableDist < spaceToOvertake) {
1547#ifdef DEBUG_CHANGE_OPPOSITE
1549 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1558 bool foundHill = vehicle->
getSlope() > 0;
1563#ifdef DEBUG_CHANGE_OPPOSITE
1565 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1570 double oppositeLength = vehicle->
getBestLanes().back().length;
1573 oppositeLength =
computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1574 leader.first =
nullptr;
1575 if (neighLead.first !=
nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1577 neighLead.first =
nullptr;
1582#ifdef DEBUG_CHANGE_OPPOSITE
1584 std::cout <<
" not changing to avoid deadlock\n";
1589 if (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1595 if (oncoming.first !=
nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1603 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1609 std::pair<MSVehicle*, double> neighLead,
1610 std::pair<MSVehicle*, double> overtaken,
1611 std::pair<MSVehicle*, double> leader) {
1613#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1615 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1622 if (leader.first ==
nullptr || neighLead.first ==
nullptr || overtaken.first ==
nullptr) {
1624 }
else if (!neighLead.first->isStopped()
1628 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1629 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1630 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1631#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1633 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1636 if (neighLead.first ==
nullptr) {
1643 if (neighLead.first->isStopped()
1644 && (overtaken.first->isStopped()
1645 || leader.first->getLaneChangeModel().isOpposite()
1650 requiredGap =
MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1651 requiredGap =
MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1653 const double distToStop = neighLead.second - requiredGap;
1657 while (neighLead.first !=
nullptr && neighLead.first->isStopped()) {
1658 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1659 if (neighStoppedBack + nextGap > overtaken.second) {
1662 neighStoppedBack += nextGap;
1663 auto neighLeadFollow = neighLead.first->getFollower();
1664 neighLead.second = neighLeadFollow.second;
1665 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1666#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1671 if (neighStoppedBack > overtaken.second) {
1676 const double leaderBGap = leader.first->getBrakeGap();
1677 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->
getBestLanesContinuation(), overtaken.second,
true).second;
1678 const double extraGap =
MAX2(leaderBGap, leaderFGap);
1680#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1682 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1683 <<
" neighLeadGap=" << neighLead.second
1684 <<
" leaderGap=" << leader.second
1685 <<
" bGap=" << leaderBGap
1686 <<
" fGap=" << leaderFGap
1687 <<
" eGap=" << extraGap
1688 <<
" neighStoppedBack=" << neighStoppedBack
1690 <<
" requiredGap=" << requiredGap
1691 <<
" gapWithEgo=" << gapWithEgo
1692 <<
" yield=" << yield
1697 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1698 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1699 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1701#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1703 std::cout <<
" currentDist=" << currentDist <<
" stopPos=" << stopPos <<
" lGap+eGap=" << leader.second + extraGap <<
" distToStop=" << distToStop <<
"\n";
1706 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1707 const double blockerLength = currentDist - stopPos;
1709#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1711 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" avoidDeadlock"
1712 <<
" blockerLength=" << blockerLength
1713 <<
" reserved=" << reserved
1731 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1733 while (follower.first !=
nullptr && followerGap < dist && follower.first->isStopped()) {
1734 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1735 follower = follower.first->getFollower(dist);
1737 if (follower.first !=
nullptr) {
1738 followerGap += follower.second;
1740#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1742 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" yieldToDeadlockOncoming"
1743 <<
" dist=" << dist <<
" follower=" <<
Named::getIDSecure(follower.first) <<
" fGap=" << followerGap
1747 return follower.first !=
nullptr && followerGap < dist && !follower.first->isStopped();
1755 std::pair<const MSVehicle*, double> follower = stoppedNeigh->
getFollower(dist);
1756 while (follower.first !=
nullptr && follower.second < dist && follower.first->isStopped()) {
1757 follower = follower.first->getFollower(dist);
1759#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1760 if (
DEBUG_COND && follower.first !=
nullptr) {
1761 std::cout <<
SIMTIME <<
" yieldToOppositeWaiting veh=" << vehicle->
getID() <<
" stoppedNeigh=" << stoppedNeigh->
getID()
1762 <<
" oncoming=" << follower.first->getID()
1763 <<
" wait=" << follower.first->getWaitingSeconds()
1769 if (follower.first !=
nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->
getWaitingTime() + deltaWait) {
1778 std::pair<MSVehicle* const, double> leader,
1779 std::pair<MSVehicle*, double> neighLead,
1780 std::pair<MSVehicle*, double> overtaken) {
1781 const double deadLockZone = overtaken.second;
1782#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1786 <<
" gap=" << leader.second
1795 std::pair<MSVehicle* const, double> oncomingOpposite =
getOncomingOppositeVehicle(vehicle, std::make_pair(
nullptr, -1), leader.second);
1796#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1798 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1799 <<
" leader=" << leader.first->getID()
1800 <<
" leaderGap=" << leader.second
1802 <<
" deadLockZone=" << deadLockZone
1806 if (neighLead.first !=
nullptr && !neighLead.first->isStopped()) {
1809 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1810 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1811 neighLead.first =
const_cast<MSVehicle*
>(neighLeadFollow.first);
1812#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1814 std::cout <<
" neighLead follower=" <<
Named::getIDSecure(neighLeadFollow.first) <<
"\n";
1819 if (oncomingOpposite.first !=
nullptr ||
1820 (neighLead.first !=
nullptr && neighLead.first->isStopped()
1822 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
1823 const double currentDist = preb[vehicle->
getLane()->
getIndex()].length;
1827#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1829 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" resolveDeadlock"
1830 <<
" leader=" << leader.first->getID()
1831 <<
" leaderGap=" << leader.second
1832 <<
" oncoming=" << oncomingOpposite.first->getID()
1833 <<
" currentDist=" << currentDist
1834 <<
" blockerLength=" << blockerLength
1835 <<
" reserved=" << reserved
1850 std::pair<MSVehicle*, double> oncoming,
double vMax,
double oncomingSpeed,
1851 std::pair<MSVehicle*, double> neighLead,
1852 std::pair<MSVehicle*, double> overtaken,
1853 std::pair<MSVehicle*, double> neighFollow,
1854 double surplusGap,
const MSLane* opposite,
1864 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1866 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1867#ifdef DEBUG_CHANGE_OPPOSITE
1869 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1873 const MSVehicle* oncomingVeh = oncoming.first;
1874 if (oncomingVeh != 0) {
1876 const double egoSpeedFraction =
MIN2(0.5, vMax / (vMax + oncomingSpeed));
1877 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1878#ifdef DEBUG_CHANGE_OPPOSITE
1880 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1881 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1885#ifdef DEBUG_CHANGE_OPPOSITE
1887 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1891 if (neighLead.first !=
nullptr) {
1892 if (overtaken.first ==
nullptr) {
1893#ifdef DEBUG_CHANGE_OPPOSITE
1895 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1898 }
else if (oncomingVeh !=
nullptr && oncomingVeh->
isStopped()
1899 && neighLead.second > 0
1900 && neighFollow.second > 0
1903 oppositeLength = forwardPos + neighLead.second;
1905 if (surplusGap > 0) {
1908 oppositeLength += 1000;
1911 if (overtaken.second > 0) {
1912 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1917#ifdef DEBUG_CHANGE_OPPOSITE
1919 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1920 <<
" surplusGap=" << surplusGap
1921 <<
" final laneQLength=" << oppositeLength
1928 if (overtaken.first ==
nullptr || !canOvertake) {
1931 if (oppFollow.first ==
nullptr) {
1932 oppositeLength = forwardPos;
1934 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1936#ifdef DEBUG_CHANGE_OPPOSITE
1938 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << oppFollow.first->getID() <<
" gap=" << oppFollow.second <<
" secureGap=" << secureGap <<
"\n";
1941 if (oppFollow.second > secureGap) {
1943 oppositeLength = forwardPos;
1948#ifdef DEBUG_CHANGE_OPPOSITE
1950 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
1953 return oppositeLength;
1957std::pair<MSVehicle* const, double>
1960 double gap = oncoming.second;
1961 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
1962 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
1964 gap += oncoming.first->getVehicleType().getLengthWithGap();
1965 if (oncoming.first != overtaken) {
1966 vMax =
MIN2(vMax, oncoming.first->getSpeed());
1968#ifdef DEBUG_CHANGE_OPPOSITE
1970 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
1971 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
1974 if (searchDist < 0) {
1978 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
1979 opposite = oncoming.first->getLane();
1981 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
1982 if (oncoming.first !=
nullptr) {
1983 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
1984#ifdef DEBUG_CHANGE_OPPOSITE
1986 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" gap=" << oncoming.second <<
" totalGap=" << gap <<
"\n";
1991 oncoming.second = gap;
1996std::pair<MSVehicle* const, double>
2000 if (overtaken.first !=
nullptr) {
2002 front = overtaken.first;
2010 const bool checkTmpVehicles = front->
getLane() == vehicle->
getLane();
2012 while (conts.size() > 0 && conts.front() != front->
getLane()) {
2013 conts.erase(conts.begin());
2016 if (oncoming.first !=
nullptr) {
2017 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2018 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2019#ifdef DEBUG_CHANGE_OPPOSITE
2022 <<
" front=" << front->
getID() <<
" searchDist=" << searchDist
2023 <<
" oncomingOpposite=" << oncoming.first->getID()
2024 <<
" gap=" << oncoming.second
2025 <<
" isOpposite=" << isOpposite
2030 if (isOpposite && shadowLane != front->
getLane()) {
2032 oncoming.second -= oncoming.first->getVehicleType().getLength();
2033 oncoming.second += gap;
2037 return std::make_pair(
nullptr, -1);
2043 double timeToOvertake,
double spaceToOvertake,
double& oncomingSpeed,
bool oncomingOpposite) {
2044 double surplusGap = std::numeric_limits<double>::max();
2045 const MSVehicle* oncomingVeh = oncoming.first;
2046 if (oncomingVeh != 0 && (oncomingOpposite
2057 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2058#ifdef DEBUG_CHANGE_OPPOSITE
2061 <<
" oncoming=" << oncomingVeh->
getID()
2062 <<
" oGap=" << oncoming.second
2063 <<
" oSpeed=" << oncomingSpeed
2064 <<
" sto=" << spaceToOvertake
2065 <<
" tto=" << timeToOvertake
2066 <<
" safetyGap=" << safetyGap
2067 <<
" surplusGap=" << surplusGap
2077 if (view >= (
int)bestLanes.size()) {
2080 MSLane* lane = bestLanes[view];
2081 double laneDist = 0;
2083 double lastZ = lastMax;
2084 for (
int i = 1; i < (int)shape.size(); i++) {
2087 if (laneDist > pos) {
2088 const double z = shape[i].z();
2096#ifdef DEBUG_CHANGE_OPPOSITE
2098 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2101 if (foundHill && z < lastMax) {
2102 const double drop = lastMax - z;
2104 if (drop > hilltopThreshold) {
2105#ifdef DEBUG_CHANGE_OPPOSITE
2107 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
2108 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
2117 searchDist -= laneDist - pos;
2120 if (searchDist <= 0) {
2125 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2134 const std::pair<MSVehicle* const, double>& leader,
2135 const std::pair<MSVehicle* const, double>& neighLead,
2136 const std::pair<MSVehicle* const, double>& neighFollow,
2137 const std::vector<MSVehicle::LaneQ>& preb) {
2140 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
2141 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2143 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
2149#ifdef DEBUG_CHANGE_OPPOSITE
2151 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
2160#ifdef DEBUG_CHANGE_OPPOSITE
2162 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
2179 const double v = vehicle->
getSpeed();
2183 const double g =
MAX2(0.0, (
2194 const double sign = -1;
2198 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2199#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2201 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
2202 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
2209 timeToOvertake = std::numeric_limits<double>::max();
2210 spaceToOvertake = std::numeric_limits<double>::max();
2218 t = ceil(t /
TS) *
TS;
2222 const double timeToMaxSpeed = (vMax - v) / a;
2224#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2226 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
2229 if (t <= timeToMaxSpeed) {
2231 spaceToOvertake = v * t + t * t * a * 0.5;
2232#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2234 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
2239 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2240 const double m = timeToMaxSpeed;
2243 t = (g - s + m * vMax) / (vMax - u);
2246#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2248 std::cout <<
" t2=" << t <<
"\n";
2251 timeToOvertake = std::numeric_limits<double>::max();
2252 spaceToOvertake = std::numeric_limits<double>::max();
2259 t = ceil(t /
TS) *
TS;
2262 spaceToOvertake = s + (t - m) * vMax;
2263#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2265 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
2271 timeToOvertake *= safetyFactor;
2273 spaceToOvertake *= safetyFactor;
2275 double frac = fmod(timeToOvertake,
TS);
2278 timeToOvertake +=
TS - frac;
2280#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2282 if (safetyFactor != 1) {
2283 std::cout <<
" applying safetyFactor=" << safetyFactor
2285 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
2293std::pair<MSVehicle*, double>
2295 assert(leader.first != 0);
2300 std::pair<MSVehicle*, double> columnLeader = leader;
2301 double egoGap = leader.second;
2302 bool foundSpaceAhead =
false;
2303 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2305 if (maxLookAhead == std::numeric_limits<double>::max()) {
2309 maxLookAhead =
MAX2(maxLookAhead, mergeBrakeGap + 10
2311 + leader.first->getVehicleType().getLengthWithGap());
2313#ifdef DEBUG_CHANGE_OPPOSITE
2315 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
2319 while (!foundSpaceAhead) {
2320 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2321 columnLeader.first, vehicle,
2323 + columnLeader.first->getVehicleType().getMinGap()
2328 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
2329 double searchStart = columnLeader.first->getPositionOnLane();
2330 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2331 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2333 std::set<MSVehicle*> seenLeaders;
2334 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2335#ifdef DEBUG_CHANGE_OPPOSITE
2337 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
2340 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2341 leadLead.first =
nullptr;
2344 seenLeaders.insert(leadLead.first);
2346 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2347 leadLead = columnLeader.first->getLane()->getLeader(
2348 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2350 leadLead.second += (searchStart2 - searchStart);
2352 if (leadLead.first ==
nullptr) {
2353 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2354 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2355 if (!columnLeader.first->isStopped()) {
2357 requiredSpace += safetyFactor * mergeBrakeGap;
2359#ifdef DEBUG_CHANGE_OPPOSITE
2361 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
2362 <<
" availableSpace=" << availableSpace
2363 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2364 <<
" ovSpeed=" << overtakingSpeed
2365 <<
" reqBGap=" << mergeBrakeGap
2366 <<
" reqMin=" << requiredSpace / safetyFactor
2367 <<
" req=" << requiredSpace
2371 if (availableSpace > requiredSpace) {
2372 foundSpaceAhead =
true;
2377 bool contsEnd =
false;
2378 const MSLane* next =
getLaneAfter(columnLeader.first->getLane(), conts, allowMinor, contsEnd);
2379#ifdef DEBUG_CHANGE_OPPOSITE
2381 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
2384 while (next !=
nullptr && seen < maxLookAhead) {
2387 if (cand ==
nullptr) {
2389 if (availableSpace > requiredSpace) {
2390 foundSpaceAhead =
true;
2393 next =
getLaneAfter(next, conts, allowMinor, contsEnd);
2396 if (availableSpace > requiredSpace) {
2397 foundSpaceAhead =
true;
2404#ifdef DEBUG_CHANGE_OPPOSITE
2406 std::cout <<
" foundSpaceAhead=" << foundSpaceAhead <<
" availableSpace=" << availableSpace <<
" next=" <<
Named::getIDSecure(next) <<
" contsEnd=" << contsEnd <<
" conts=" <<
toString(conts) <<
"\n";
2409 if (!foundSpaceAhead && contsEnd) {
2410 foundSpaceAhead =
true;
2411 availableSpace = requiredSpace;
2413 if (!foundSpaceAhead) {
2414 return std::make_pair(
nullptr, -1);
2417 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2420 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2421 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2422 if (!columnLeader.first->isStopped()) {
2424 requiredSpace += safetyFactor * sGap;
2426#ifdef DEBUG_CHANGE_OPPOSITE
2428 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
2429 <<
" reqAfterLeader=" << requiredSpaceAfterLeader
2430 <<
" ovSpeed=" << overtakingSpeed
2431 <<
" reqSGap=" << sGap
2432 <<
" reqMin=" << requiredSpace / safetyFactor
2433 <<
" req=" << requiredSpace
2437 if (leadLead.second > requiredSpace) {
2438 foundSpaceAhead =
true;
2439 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2442 if (leadLead.second < 0) {
2444#ifdef DEBUG_CHANGE_OPPOSITE
2446 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
2449 return std::make_pair(
nullptr, -1);
2452#ifdef DEBUG_CHANGE_OPPOSITE
2454 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
2457 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2458 if (seen > maxLookAhead) {
2459#ifdef DEBUG_CHANGE_OPPOSITE
2461 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
2464 return std::make_pair(
nullptr, -1);
2467 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2468 columnLeader = leadLead;
2469#ifdef DEBUG_CHANGE_OPPOSITE
2471 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
2477 columnLeader.second = egoGap;
2478 return columnLeader;
2484 for (
auto it = conts.begin(); it != conts.end(); ++it) {
2486 if (it + 1 != conts.end()) {
2488 const MSLane* next = *(it + 1);
2490 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
2508 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 setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
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, 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.
const PositionVector & getShape() const
Returns this lane's shape.
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
MSEdge & getEdge() const
Returns the lane's edge.
double getWidth() const
Returns the lane's width.
LinkState getState() const
Returns the current state of the link.
bool havePriority() const
Returns whether this link is a major link.
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
LinkDirection getDirection() const
Returns the direction the vehicle passing this link take.
bool haveRed() const
Returns whether this link is blocked by a red (or redyellow) traffic light.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
bool hasElevation() const
return whether the network contains elevation data
const MSLane * lane
The lane to stop at (microsim only)
bool isOpposite
whether this an opposite-direction stop
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected (concerns approaching vehicles outside the...
SUMOTime getLaneTimeLineDuration()
double myPosLat
the stored lateral position
Representation of a vehicle in the micro simulation.
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
double computeAngle() const
compute the current vehicle angle
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
bool isStoppedOnLane() const
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
MSAbstractLaneChangeModel & getLaneChangeModel()
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
const MSLane * getLane() const
Returns the lane the vehicle is on.
std::pair< const MSVehicle *const, double > getFollower(double dist=0) const
Returns the follower of the vehicle looking for a fixed distance.
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
double getSpeed() const
Returns the vehicle's current speed.
Position myCachedPosition
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
double myAngle
the angle in radians (
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignore
double getPositionOnLane() const
Get the vehicle's position along the lane.
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
State myState
This Vehicles driving state (pos and speed)
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
static const Position INVALID
used to indicate that a position is valid
double z() const
Returns the z-position.
ChangeElem(MSLane *_lane)
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.