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
69 #define DEBUG_COND (vehicle->isSelected())
82 firstBlocked(nullptr),
84 aheadNext(lane, nullptr, 0) {
90 lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
105 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
107 myChanger.back().mayChangeRight = lane != lanes->begin();
108 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
109 if ((*lane)->isInternal()) {
111 if (
myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
114 if (
myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
118 if (
myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
122 if (
myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
144 const bool haveChanged =
change();
151 ce->lane->releaseVehicles();
163 ce->hoppedVeh =
nullptr;
164 ce->lastBlocked =
nullptr;
165 ce->firstBlocked =
nullptr;
167 ce->lane->getVehiclesSecure();
181 if (!vehHasChanged) {
204 ce->lane->swapAfterLaneChange(t);
205 ce->lane->releaseVehicles();
215 #ifdef DEBUG_CANDIDATE
216 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
220 if (
veh(ce) ==
nullptr) {
223 #ifdef DEBUG_CANDIDATE
224 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
228 #ifdef DEBUG_CANDIDATE
234 assert(
veh(ce) != 0);
235 assert(
veh(max) != 0);
236 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
237 #ifdef DEBUG_CANDIDATE
244 assert(
veh(max) != 0);
251 if (direction == 0) {
258 if (direction == -1) {
259 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingRight(svc);
260 }
else if (direction == 1) {
261 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(svc) &&
myCandi->lane->allowsChangingLeft(svc);
278 #ifdef DEBUG_ACTIONSTEPS
297 #ifdef DEBUG_ACTIONSTEPS
299 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
302 bool changed =
false;
326 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
330 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
341 (
myCandi - 1)->lastBlocked = vehicle;
342 if ((
myCandi - 1)->firstBlocked ==
nullptr) {
343 (
myCandi - 1)->firstBlocked = vehicle;
358 (
myCandi + 1)->lastBlocked = vehicle;
359 if ((
myCandi + 1)->firstBlocked ==
nullptr) {
360 (
myCandi + 1)->firstBlocked = vehicle;
405 <<
" veh=" << vehicle->
getID()
408 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
419 bool changed =
false;
421 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
422 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
430 to->registerHop(vehicle);
452 to->registerHop(vehicle);
453 to->lane->requireCollisionCheck();
474 to->registerHop(vehicle);
478 from->registerHop(vehicle);
479 from->lane->requireCollisionCheck();
496 #ifdef DEBUG_CONTINUE_CHANGE
499 <<
" continueChange veh=" << vehicle->
getID()
501 <<
" dir=" << direction
502 <<
" speedLat=" << speedLat
503 <<
" pastMidpoint=" << pastMidpoint
515 std::pair<MSVehicle* const, double>
519 #ifdef DEBUG_SURROUNDING_VEHICLES
521 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
527 #ifdef DEBUG_SURROUNDING_VEHICLES
529 if (neighLead != 0) {
530 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
536 if (target->hoppedVeh !=
nullptr) {
537 double hoppedPos = target->hoppedVeh->getPositionOnLane();
538 #ifdef DEBUG_SURROUNDING_VEHICLES
540 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
544 neighLead = target->hoppedVeh;
548 if (neighLead ==
nullptr) {
549 #ifdef DEBUG_SURROUNDING_VEHICLES
551 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
556 MSLane* targetLane = target->lane;
558 double leaderBack = targetLane->
getLength();
561 if (plBack < leaderBack &&
567 if (neighLead !=
nullptr) {
568 #ifdef DEBUG_SURROUNDING_VEHICLES
570 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
579 if (seen > dist && !
myCandi->lane->isInternal()) {
580 #ifdef DEBUG_SURROUNDING_VEHICLES
582 std::cout <<
" found no leader within dist=" << dist <<
"\n";
585 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(
nullptr), -1);
589 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
590 #ifdef DEBUG_SURROUNDING_VEHICLES
597 #ifdef DEBUG_SURROUNDING_VEHICLES
599 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
607 std::pair<MSVehicle* const, double>
611 #ifdef DEBUG_SURROUNDING_VEHICLES
613 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
619 #ifdef DEBUG_SURROUNDING_VEHICLES
621 if (neighFollow != 0) {
622 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
624 std::cout <<
"veh(target) returns none." << std::endl;
630 #ifdef DEBUG_SURROUNDING_VEHICLES
632 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
633 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
642 #ifdef DEBUG_SURROUNDING_VEHICLES
645 if (partialBehind != 0 && partialBehind != neighFollow) {
646 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
651 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
653 if (neighFollow ==
nullptr || neighFollow == vehicle) {
655 #ifdef DEBUG_SURROUNDING_VEHICLES
657 if (consecutiveFollower.first == 0) {
658 std::cout <<
"no follower found." << std::endl;
660 std::cout <<
"found follower '" << consecutiveFollower.first->getID() <<
"' on consecutive lanes." << std::endl;
664 return std::make_pair(
const_cast<MSVehicle*
>(consecutiveFollower.first), consecutiveFollower.second);
666 #ifdef DEBUG_SURROUNDING_VEHICLES
668 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
671 return std::pair<MSVehicle* const, double>(neighFollow,
695 const std::pair<MSVehicle* const, double>& leader,
696 const std::vector<MSVehicle::LaneQ>& preb)
const {
701 if (neighLead.first !=
nullptr && neighLead.first == neighFollow.first) {
704 neighFollow.first = 0;
707 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
714 const std::pair<MSVehicle* const, double>& leader,
715 const std::pair<MSVehicle* const, double>& follower,
716 const std::pair<MSVehicle* const, double>& neighLead,
717 const std::pair<MSVehicle* const, double>& neighFollow,
718 const std::vector<MSVehicle::LaneQ>& preb)
const {
722 #ifdef DEBUG_CHECK_CHANGE
725 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'"
734 if (neighFollow.first !=
nullptr && neighFollow.second < 0) {
738 #ifdef DEBUG_CHECK_CHANGE
741 <<
" overlapping with follower..."
747 if (neighLead.first !=
nullptr && neighLead.second < 0) {
750 #ifdef DEBUG_CHECK_CHANGE
753 <<
" overlapping with leader..."
765 if ((blocked & blockedByFollower) == 0 && neighFollow.first !=
nullptr) {
773 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
776 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
778 #ifdef DEBUG_CHECK_CHANGE
781 <<
" backGap=" << neighFollow.second
782 <<
" vNextFollower=" << vNextFollower
783 <<
" vNextEgo=" << vNextLeader
784 <<
" secureGap=" << secureBackGap
791 blocked |= blockedByFollower;
796 if ((blocked & blockedByLeader) == 0 && neighLead.first !=
nullptr) {
805 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
809 #ifdef DEBUG_CHECK_CHANGE
812 <<
" frontGap=" << neighFollow.second
813 <<
" vNextEgo=" << vNextFollower
814 <<
" vNextLeader=" << vNextLeader
815 <<
" secureGap=" << secureFrontGap
822 blocked |= blockedByLeader;
829 if (nextLeader.first != 0) {
833 #ifdef DEBUG_CHECK_CHANGE
835 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
838 if (brakeGap > gap) {
839 blocked |= blockedByLeader;
840 #ifdef DEBUG_CHECK_CHANGE
842 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
849 if (leader.first !=
nullptr) {
850 secureOrigFrontGap = vehicle->
getCarFollowModel().
getSecureGap(vehicle, leader.first, vehicle->
getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
855 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
864 const double speed = vehicle->
getSpeed();
866 if (seen < dist || myCandi->lane->isInternal()) {
867 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
868 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first) {
870 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
872 #ifdef DEBUG_SURROUNDING_VEHICLES
874 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
875 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
878 if (neighLead2.second < secureGap2) {
879 state |= blockedByLeader;
887 state |= blockedByLeader;
899 if (estimatedLCDuration == -1) {
901 #ifdef DEBUG_CHECK_CHANGE
903 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change."
904 <<
"\nestimatedLCDuration=" << estimatedLCDuration
905 <<
"\ndistToNeighLane=" << distToNeighLane
913 const double avgSpeed = 0.5 * (
917 const double space2change = avgSpeed * estimatedLCDuration;
920 #ifdef DEBUG_CHECK_CHANGE
922 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..."
923 <<
"\ndistToNeighLane=" << distToNeighLane
924 <<
" estimatedLCDuration=" << estimatedLCDuration
925 <<
" space2change=" << space2change
926 <<
" avgSpeed=" << avgSpeed
935 std::vector<MSLink*>::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
936 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
940 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
945 if ((*link)->getViaLane() ==
nullptr) {
948 nextLane = (*link)->getViaLaneOrLane();
953 #ifdef DEBUG_CHECK_CHANGE
955 std::cout <<
" available distance=" << seen << std::endl;
958 if (nextLane->
isLinkEnd(link) && seen < space2change) {
959 #ifdef DEBUG_CHECK_CHANGE
961 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
970 const double speed = vehicle->
getSpeed();
975 std::vector<MSLink*>::const_iterator nextLink =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
976 while (!nextLane->
isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
977 nextLane = (*nextLink)->getViaLaneOrLane();
979 if (parallelLane ==
nullptr) {
983 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
984 if (neighLead2.first !=
nullptr && neighLead2.first != neighLead.first
986 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
987 state |= blockedByLeader;
991 if ((*nextLink)->getViaLane() ==
nullptr) {
1001 const int oldstate = state;
1004 #ifdef DEBUG_CHECK_CHANGE
1007 <<
" veh=" << vehicle->
getID()
1022 if (laneOffset != 0) {
1041 std::vector<MSVehicle::LaneQ>
1048 const std::vector<MSLane*>& oLanes = opposite->
getLanes();
1049 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1050 for (
int i = 0; i < numOpposite; i++) {
1051 preb.push_back(preb.back());
1052 preb.back().lane = oLanes[numOpposite - 1 - i];
1053 preb.back().length = oppositeLength;
1055 preb.back().bestLaneOffset = -1 - i;
1059 if (stopLane !=
nullptr) {
1060 const int stopIndex = numForward + numOpposite - stopLane->
getIndex() - 1;
1061 for (
int i = 0; i < (int)preb.size(); i++) {
1062 preb[i].bestLaneOffset = stopIndex - i;
1067 #ifdef DEBUG_CHANGE_OPPOSITE
1069 std::cout <<
SIMTIME <<
" getBestLanesOpposite " << vehicle->
getID() <<
" isOpposite=" << isOpposite <<
"\n";
1070 for (
int i = 0; i < (int)preb.size(); i++) {
1071 std::cout <<
" i=" << i <<
" lane=" << preb[i].lane->getID() <<
" bestOffset=" << preb[i].bestLaneOffset <<
" length=" << preb[i].length <<
"\n";
1089 #ifdef DEBUG_CHANGE_OPPOSITE
1096 if (opposite ==
nullptr) {
1106 bool oppositeChangeByTraci =
false;
1109 if (isOpposite && (ret &
LCA_LEFT) != 0) {
1113 oppositeChangeByTraci =
true;
1117 #ifdef DEBUG_CHANGE_OPPOSITE
1119 std::cout <<
" not overtaking due to changeLeft restriction\n";
1130 const MSLane* oncomingLane = isOpposite ? source : opposite;
1132 int direction = isOpposite ? -1 : 1;
1133 std::pair<MSVehicle*, double> neighLead(
nullptr, -1);
1136 double surplusGap = std::numeric_limits<double>::max();
1145 std::pair<MSVehicle*, double> overtaken(
nullptr, -1);
1146 std::pair<MSVehicle*, double> oncoming(
nullptr, -1);
1156 const int bestOffset = preb[laneIndex].bestLaneOffset;
1167 const double timeToStop =
MAX2(timeToStopForward, timeToStopLateral);
1171 const double searchDist = timeToStop * oncomingLane->
getSpeedLimit() * 2 + spaceToStop;
1179 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1180 if (!isOpposite && surplusGap < 0) {
1181 #ifdef DEBUG_CHANGE_OPPOSITE
1183 std::cout <<
" cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1184 <<
" timeToStopForward=" << timeToStopForward <<
" timeToStopLateral=" << timeToStopLateral <<
" surplusGap=" << surplusGap <<
"\n";
1190 if (bestOffset > 0) {
1191 MSLane*
const target = preb[laneIndex + 1].lane;
1202 if (!isOpposite && leader.first ==
nullptr && !oppositeChangeByTraci) {
1208 if (!isOpposite && !oppositeChangeByTraci
1210 && leader.first !=
nullptr) {
1215 #ifdef DEBUG_CHANGE_OPPOSITE
1217 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1221 }
else if (leader.second < 0) {
1223 #ifdef DEBUG_CHANGE_OPPOSITE
1225 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" with gap " << leader.second <<
"\n";
1233 double timeToOvertake = std::numeric_limits<double>::max();
1234 double spaceToOvertake = std::numeric_limits<double>::max();
1236 if (oppositeChangeByTraci) {
1246 if (overtaken.first ==
nullptr && neighLead.first !=
nullptr) {
1247 overtaken = neighLead;
1249 if (overtaken.first !=
nullptr) {
1252 #ifdef DEBUG_CHANGE_OPPOSITE
1254 std::cout <<
" leaderOnSource=" <<
Named::getIDSecure(oncoming.first) <<
" gap=" << oncoming.second <<
"\n";
1255 std::cout <<
" leaderOnTarget=" <<
Named::getIDSecure(neighLead.first) <<
" gap=" << neighLead.second <<
"\n";
1256 std::cout <<
" overtaken=" <<
Named::getIDSecure(overtaken.first) <<
" gap=" << overtaken.second <<
"\n";
1263 if (overtaken.first == 0) {
1269 #ifdef DEBUG_CHANGE_OPPOSITE
1271 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1277 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1278 #ifdef DEBUG_CHANGE_OPPOSITE
1281 <<
" veh=" << vehicle->
getID()
1282 <<
" changeOpposite opposite=" << opposite->
getID()
1284 <<
" timeToOvertake=" << timeToOvertake
1285 <<
" spaceToOvertake=" << spaceToOvertake
1291 #ifdef DEBUG_CHANGE_OPPOSITE
1293 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1303 assert(timeToOvertake != std::numeric_limits<double>::max());
1304 assert(spaceToOvertake != std::numeric_limits<double>::max());
1307 double searchDist = timeToOvertake * oncomingLane->
getSpeedLimit() * 2 + spaceToOvertake;
1309 oncoming =
getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first);
1313 oncoming =
getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1317 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1318 #ifdef DEBUG_CHANGE_OPPOSITE
1320 std::cout <<
" recomputed overtaking time with vMax=" << vMax
1321 <<
" timeToOvertake=" << timeToOvertake
1322 <<
" spaceToOvertake=" << spaceToOvertake
1329 #ifdef DEBUG_CHANGE_OPPOSITE
1331 std::cout <<
" cannot changeOpposite (cannot overtake fast leader " <<
Named::getIDSecure(overtaken.first) <<
" v=" << overtaken.first->getSpeed() <<
")\n";
1338 #ifdef DEBUG_CHANGE_OPPOSITE
1340 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1345 assert(timeToOvertake != std::numeric_limits<double>::max());
1346 assert(spaceToOvertake != std::numeric_limits<double>::max());
1350 surplusGap =
computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1351 if (!isOpposite && surplusGap < 0) {
1352 #ifdef DEBUG_CHANGE_OPPOSITE
1354 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1358 #ifdef DEBUG_CHANGE_OPPOSITE
1360 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1361 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() <<
" (but the leader is also opposite)\n";
1372 if (usableDist < spaceToOvertake) {
1375 assert(bestLaneConts.size() >= 1);
1376 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1377 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1378 #ifdef DEBUG_CHANGE_OPPOSITE
1380 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1383 if ((*it)->getOpposite() ==
nullptr || !(*it)->getOpposite()->allowsVehicleClass(vehicle->
getVClass())) {
1388 const MSLane*
const prev = *(it - 1);
1389 if (prev !=
nullptr) {
1398 #ifdef DEBUG_CHANGE_OPPOSITE
1400 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1406 usableDist += (*it)->getLength();
1410 if (!isOpposite && usableDist < spaceToOvertake) {
1411 #ifdef DEBUG_CHANGE_OPPOSITE
1413 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1422 bool foundHill = vehicle->
getSlope() > 0;
1427 #ifdef DEBUG_CHANGE_OPPOSITE
1429 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1433 double oppositeLength = vehicle->
getBestLanes().back().length;
1443 oppositeLength =
MIN2(oppositeLength, usableDist + forwardPos);
1445 oppositeLength =
MIN2(oppositeLength, vehicle->
nextStopDist() + forwardPos);
1446 #ifdef DEBUG_CHANGE_OPPOSITE
1448 std::cout <<
" laneQLength=" << oppositeLength <<
" usableDist=" << usableDist <<
" forwardPos=" << forwardPos <<
" stopDist=" << vehicle->
nextStopDist() <<
"\n";
1452 const MSVehicle* oncomingVeh = oncoming.first;
1453 if (oncomingVeh != 0) {
1455 const double egoSpeedFraction =
MIN2(0.5, vMax / (vMax + oncomingSpeed));
1456 oppositeLength =
MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1457 #ifdef DEBUG_CHANGE_OPPOSITE
1459 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second
1460 <<
" egoSpeedFraction=" << egoSpeedFraction <<
" newDist=" << oppositeLength <<
"\n";
1464 #ifdef DEBUG_CHANGE_OPPOSITE
1466 std::cout <<
SIMTIME <<
" opposite leader=" << oncomingVeh->
getID() <<
" gap=" << oncoming.second <<
" is driving against the flow\n";
1470 if (neighLead.first !=
nullptr) {
1471 if (overtaken.first ==
nullptr) {
1472 #ifdef DEBUG_CHANGE_OPPOSITE
1474 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1478 if (surplusGap > 0) {
1481 oppositeLength += 1000;
1484 if (overtaken.second > 0) {
1485 oppositeLength =
MIN2(oppositeLength, forwardPos + overtaken.second);
1490 #ifdef DEBUG_CHANGE_OPPOSITE
1492 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1493 <<
" surplusGap=" << surplusGap
1494 <<
" spaceToOvertake=" << spaceToOvertake
1495 <<
" timeToOvertake=" << timeToOvertake
1496 <<
" timeToOvertake=" << timeToOvertake
1497 <<
" final laneQLength=" << oppositeLength
1504 if (overtaken.first ==
nullptr) {
1507 if (neighFollow.first ==
nullptr) {
1508 oppositeLength = forwardPos;
1510 const double secureGap = neighFollow.first->getCarFollowModel().getSecureGap(
1512 #ifdef DEBUG_CHANGE_OPPOSITE
1514 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" neighFollow=" << neighFollow.first->getID() <<
" gap=" << neighFollow.second <<
" secureGap=" << secureGap <<
"\n";
1517 if (neighFollow.second > secureGap) {
1519 oppositeLength = forwardPos;
1525 #ifdef DEBUG_CHANGE_OPPOSITE
1527 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << oppositeLength - forwardPos <<
" forwardPos=" << forwardPos <<
" oppositeLength=" << oppositeLength <<
"\n";
1533 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1537 std::pair<MSVehicle* const, double>
1539 double gap = oncoming.second;
1540 while (oncoming.first !=
nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
1541 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() +
MAX2(0.0, oncoming.second));
1543 gap += oncoming.first->getVehicleType().getLengthWithGap();
1544 if (oncoming.first != overtaken) {
1545 vMax =
MIN2(vMax, oncoming.first->getSpeed());
1547 #ifdef DEBUG_CHANGE_OPPOSITE
1549 std::cout <<
SIMTIME <<
" oncoming=" << oncoming.first->getID() <<
" isOpposite gap=" << oncoming.second
1550 <<
" totalGap=" << gap <<
" searchDist=" << searchDist <<
" vMax=" << vMax <<
"\n";
1553 if (searchDist < 0) {
1557 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
1558 opposite = oncoming.first->getLane();
1560 oncoming = opposite->
getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist,
true);
1561 if (oncoming.first !=
nullptr) {
1562 gap += oncoming.second;
1565 oncoming.second = gap;
1572 double surplusGap = std::numeric_limits<double>::max();
1573 const MSVehicle* oncomingVeh = oncoming.first;
1580 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
1581 #ifdef DEBUG_CHANGE_OPPOSITE
1584 <<
" oncoming=" << oncomingVeh->
getID()
1585 <<
" oncomingGap=" << oncoming.second
1586 <<
" safetyGap=" << safetyGap
1587 <<
" surplusGap=" << surplusGap
1597 if (view >= (
int)bestLanes.size()) {
1600 MSLane* lane = bestLanes[view];
1601 double laneDist = 0;
1603 double lastZ = lastMax;
1604 for (
int i = 1; i < (int)shape.size(); i++) {
1607 if (laneDist > pos) {
1608 const double z = shape[i].z();
1616 #ifdef DEBUG_CHANGE_OPPOSITE
1618 std::cout <<
SIMTIME <<
" foundHill=" << foundHill <<
" searchDist=" << searchDist <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
1621 if (foundHill && z < lastMax) {
1622 const double drop = lastMax - z;
1624 if (drop > hilltopThreshold) {
1625 #ifdef DEBUG_CHANGE_OPPOSITE
1627 std::cout <<
" cannot changeOpposite before the top of a hill searchDist=" << searchDist <<
" hillDrop=" << drop
1628 <<
" lastMax=" << lastMax <<
" lane=" << lane->
getID() <<
" laneDist=" << laneDist <<
" z=" << z <<
"\n";
1637 searchDist -= laneDist - pos;
1640 if (searchDist <= 0) {
1645 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
1654 const std::pair<MSVehicle* const, double>& leader,
1655 const std::pair<MSVehicle* const, double>& neighLead,
1656 const std::pair<MSVehicle* const, double>& neighFollow,
1657 const std::vector<MSVehicle::LaneQ>& preb) {
1660 const std::pair<MSVehicle* const, double> follower(
nullptr, -1);
1661 int state =
checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
1663 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
1669 #ifdef DEBUG_CHANGE_OPPOSITE
1671 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset <<
" opposite=" <<
Named::getIDSecure(targetLane)
1680 #ifdef DEBUG_CHANGE_OPPOSITE
1682 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << laneOffset
1699 const double v = vehicle->
getSpeed();
1703 const double g =
MAX2(0.0, (
1714 const double sign = -1;
1718 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
1719 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1721 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
1722 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
1729 timeToOvertake = std::numeric_limits<double>::max();
1730 spaceToOvertake = std::numeric_limits<double>::max();
1737 t = ceil(t /
TS) *
TS;
1740 const double timeToMaxSpeed = (vMax - v) / a;
1742 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1744 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
1747 if (t <= timeToMaxSpeed) {
1749 spaceToOvertake = v * t + t * t * a * 0.5;
1750 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1752 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
1757 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
1758 const double m = timeToMaxSpeed;
1761 t = (g - s + m * vMax) / (vMax - u);
1764 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1766 std::cout <<
" t2=" << t <<
"\n";
1769 timeToOvertake = std::numeric_limits<double>::max();
1770 spaceToOvertake = std::numeric_limits<double>::max();
1776 t = ceil(t /
TS) *
TS;
1779 spaceToOvertake = s + (t - m) * vMax;
1780 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1782 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
1788 timeToOvertake *= safetyFactor;
1789 spaceToOvertake *= safetyFactor;
1790 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
1792 if (safetyFactor != 1) {
1793 std::cout <<
" applying safetyFactor=" << safetyFactor
1794 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
1802 std::pair<MSVehicle*, double>
1804 assert(leader.first != 0);
1809 std::pair<MSVehicle*, double> columnLeader = leader;
1810 double egoGap = leader.second;
1811 bool foundSpaceAhead =
false;
1812 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
1814 if (maxLookAhead == std::numeric_limits<double>::max()) {
1819 #ifdef DEBUG_CHANGE_OPPOSITE
1821 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
1825 while (!foundSpaceAhead) {
1826 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
1827 columnLeader.first, vehicle,
1829 + columnLeader.first->getVehicleType().getMinGap()
1834 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
1835 double searchStart = columnLeader.first->getPositionOnLane();
1836 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
1837 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
1839 std::set<MSVehicle*> seenLeaders;
1840 while (leadLead.first !=
nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
1841 #ifdef DEBUG_CHANGE_OPPOSITE
1843 std::cout <<
" skipping opposite leadLead=" << leadLead.first->getID() <<
" gap=" << leadLead.second <<
"\n";
1846 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
1847 leadLead.first =
nullptr;
1850 seenLeaders.insert(leadLead.first);
1852 const double searchStart2 = searchStart +
MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
1853 leadLead = columnLeader.first->getLane()->getLeader(
1854 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
1856 leadLead.second += (searchStart2 - searchStart);
1858 if (leadLead.first ==
nullptr) {
1859 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
1860 const double requiredSpace = safetyFactor * (requiredSpaceAfterLeader
1862 #ifdef DEBUG_CHANGE_OPPOSITE
1864 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
1865 <<
" availableSpace=" << availableSpace
1866 <<
" req1=" << requiredSpaceAfterLeader
1867 <<
" req2=" << requiredSpace / safetyFactor
1868 <<
" req3=" << requiredSpace
1872 if (availableSpace > requiredSpace) {
1873 foundSpaceAhead =
true;
1879 #ifdef DEBUG_CHANGE_OPPOSITE
1881 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
1884 while (next !=
nullptr && seen < maxLookAhead) {
1887 if (cand ==
nullptr) {
1889 if (availableSpace > requiredSpace) {
1890 foundSpaceAhead =
true;
1896 if (availableSpace > requiredSpace) {
1897 foundSpaceAhead =
true;
1904 if (!foundSpaceAhead) {
1905 return std::make_pair(
nullptr, -1);
1909 const double requiredSpace = safetyFactor * (requiredSpaceAfterLeader
1911 overtakingSpeed, leadLead.first->
getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel()));
1912 #ifdef DEBUG_CHANGE_OPPOSITE
1914 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
1915 <<
" req1=" << requiredSpaceAfterLeader
1916 <<
" req2=" << requiredSpace / safetyFactor
1917 <<
" req3=" << requiredSpace
1921 if (leadLead.second > requiredSpace) {
1922 foundSpaceAhead =
true;
1925 if (leadLead.second < 0) {
1927 #ifdef DEBUG_CHANGE_OPPOSITE
1929 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" gap=" << leadLead.second <<
" is junction leader (aborting)\n";
1932 return std::make_pair(
nullptr, -1);
1935 #ifdef DEBUG_CHANGE_OPPOSITE
1937 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
1940 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
1941 if (seen > maxLookAhead) {
1942 #ifdef DEBUG_CHANGE_OPPOSITE
1944 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
1947 return std::make_pair(
nullptr, -1);
1950 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
1951 columnLeader = leadLead;
1952 #ifdef DEBUG_CHANGE_OPPOSITE
1954 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
1960 columnLeader.second = egoGap;
1961 return columnLeader;
1967 for (
auto it = conts.begin(); it != conts.end(); ++it) {
1969 if (it + 1 != conts.end()) {
1971 const MSLane* next = *(it + 1);
1973 if (link ==
nullptr || (!allowMinor && !link->
havePriority())) {
#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_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 saveLCState(const int dir, const int stateWithoutTraCI, const int state)
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
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...
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
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)
virtual double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
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 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
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
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
static std::pair< MSVehicle *, double > getColumnleader(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
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
bool startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
const bool myAllowsChanging
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
MSVehicle * veh(ConstChangerIt ce) 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)
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
std::pair< MSVehicle *const, double > getOncomingVehicle(const MSLane *opposite, std::pair< MSVehicle *, double > neighOncoming, double searchDist, double &vMax, const MSVehicle *overtaken=nullptr)
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
void registerUnchanged(MSVehicle *vehicle)
void updateLanes(SUMOTime t)
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
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
static const MSLane * getLaneAfter(const MSLane *lane, const std::vector< MSLane * > &conts, bool allowMinor)
return the next lane in conts beyond lane or nullptr
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.
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > 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.
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)
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
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 > getFollower(const MSVehicle *ego, double egoPos, double dist, bool ignoreMinorLinks) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
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...
MSEdge & getEdge() const
Returns the lane's edge.
const PositionVector & getShape() const
Returns this lane's shape.
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
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir) const
double getWidth() const
Returns the lane's width.
LinkState getState() const
Returns the current state of the link.
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
bool havePriority() const
Returns whether this link is a major link.
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.
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
MSAbstractLaneChangeModel & getLaneChangeModel()
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
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.
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the vehicle's lateral position 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.
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.
const MSLane * getLane() const
Returns the lane the vehicle is on.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
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.