42 #define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0 43 #define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR 0.0 44 #define OPPOSITE_OVERTAKING_SAFETY_FACTOR 1.2 46 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0 // just a guess 47 #define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0 // just a guess 49 #define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 200.0 // just a guess 64 #define DEBUG_COND (vehicle->isSelected()) 78 aheadNext(lane, 0, 0) {
98 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
100 myChanger.back().mayChangeRight = lane != lanes->begin();
101 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
103 if ((*lane)->isInternal()) {
104 if (
myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
107 if (
myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
128 const bool haveChanged =
change();
135 ce->lane->releaseVehicles();
149 ce->firstBlocked = 0;
151 ce->lane->getVehiclesSecure();
188 ce->lane->swapAfterLaneChange(t);
189 ce->lane->releaseVehicles();
199 #ifdef DEBUG_CANDIDATE 200 std::cout <<
SIMTIME <<
" findCandidate() on edge " <<
myChanger.begin()->lane->getEdge().getID() << std::endl;
207 #ifdef DEBUG_CANDIDATE 208 std::cout <<
" lane = " << ce->lane->getID() <<
"\n";
212 #ifdef DEBUG_CANDIDATE 218 assert(
veh(ce) != 0);
219 assert(
veh(max) != 0);
220 if (
veh(max)->getPositionOnLane() <
veh(ce)->getPositionOnLane()) {
221 #ifdef DEBUG_CANDIDATE 228 assert(
veh(max) != 0);
235 if (direction == 0) {
241 if (direction == -1) {
242 return myCandi->mayChangeRight && (
myCandi - 1)->lane->allowsVehicleClass(
veh(
myCandi)->getVehicleType().getVehicleClass());
243 }
else if (direction == 1) {
244 return myCandi->mayChangeLeft && (
myCandi + 1)->lane->allowsVehicleClass(
veh(
myCandi)->getVehicleType().getVehicleClass());
261 #ifdef DEBUG_ACTIONSTEPS 284 #ifdef DEBUG_ACTIONSTEPS 286 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' skips regular change checks." << std::endl;
289 bool changed =
false;
313 for (
int i = 0; i < (int)
myChanger.size(); ++i) {
317 const std::vector<MSVehicle::LaneQ>& preb = vehicle->
getBestLanes();
328 if ((stateRight & LCA_RIGHT) != 0 && (stateRight &
LCA_URGENT) != 0) {
329 (
myCandi - 1)->lastBlocked = vehicle;
330 if ((
myCandi - 1)->firstBlocked == 0) {
331 (
myCandi - 1)->firstBlocked = vehicle;
346 if ((stateLeft & LCA_LEFT) != 0 && (stateLeft &
LCA_URGENT) != 0) {
347 (
myCandi + 1)->lastBlocked = vehicle;
348 if ((
myCandi + 1)->firstBlocked == 0) {
349 (
myCandi + 1)->firstBlocked = vehicle;
392 <<
" veh=" << vehicle->
getID()
395 << ((newstate &
LCA_BLOCKED) != 0 ?
" (blocked)" :
"")
406 bool changed =
false;
408 const int dir = (state &
LCA_RIGHT) != 0 ? -1 : ((state &
LCA_LEFT) != 0 ? 1 : 0);
409 const bool execute = dir != 0 && ((state &
LCA_BLOCKED) == 0);
417 to->registerHop(vehicle);
435 to->registerHop(vehicle);
449 MSLane* target = to->lane;
452 to->registerHop(vehicle);
454 from->registerHop(vehicle);
464 shadow->hoppedVeh = vehicle;
468 #ifdef DEBUG_CONTINUE_CHANGE 471 <<
" continueChange veh=" << vehicle->
getID()
473 <<
" dir=" << direction
474 <<
" pastMidpoint=" << pastMidpoint
486 std::pair<MSVehicle* const, double>
490 #ifdef DEBUG_SURROUNDING_VEHICLES 492 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for leader on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
498 #ifdef DEBUG_SURROUNDING_VEHICLES 500 if (neighLead != 0) {
501 std::cout <<
"Considering '" << neighLead->
getID() <<
"' at position " << neighLead->
getPositionOnLane() << std::endl;
512 if (target->hoppedVeh != 0) {
513 double hoppedPos = target->hoppedVeh->getPositionOnLane();
514 #ifdef DEBUG_SURROUNDING_VEHICLES 516 std::cout <<
"Considering hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << hoppedPos << std::endl;
520 neighLead = target->hoppedVeh;
524 if (neighLead == 0) {
525 #ifdef DEBUG_SURROUNDING_VEHICLES 527 std::cout <<
"Looking for leader on consecutive lanes." << std::endl;
532 MSLane* targetLane = target->lane;
534 double leaderBack = targetLane->
getLength();
537 if (plBack < leaderBack &&
543 if (neighLead != 0) {
544 #ifdef DEBUG_SURROUNDING_VEHICLES 546 std::cout <<
" found leader=" << neighLead->
getID() <<
" (partial)\n";
555 if (seen > dist && !
myCandi->lane->isInternal()) {
556 #ifdef DEBUG_SURROUNDING_VEHICLES 558 std::cout <<
" found no leader within dist=" << dist <<
"\n";
561 return std::pair<MSVehicle* const, double>(
static_cast<MSVehicle*
>(0), -1);
565 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *
veh(
myCandi), bestLaneConts);
566 #ifdef DEBUG_SURROUNDING_VEHICLES 574 #ifdef DEBUG_SURROUNDING_VEHICLES 576 std::cout <<
" found leader=" << neighLead->
getID() <<
"\n";
584 std::pair<MSVehicle* const, double>
588 #ifdef DEBUG_SURROUNDING_VEHICLES 591 std::cout <<
SIMTIME <<
" veh '" << vehicle->
getID() <<
"' looks for follower on lc-target lane '" << target->lane->getID() <<
"'." << std::endl;
598 #ifdef DEBUG_SURROUNDING_VEHICLES 600 if (neighFollow != 0) {
601 std::cout <<
"veh(target) returns '" << neighFollow->
getID() <<
"' at position " << neighFollow->
getPositionOnLane() << std::endl;
603 std::cout <<
"veh(target) returns none." << std::endl;
609 #ifdef DEBUG_SURROUNDING_VEHICLES 611 if (
getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
612 std::cout <<
"Hopped vehicle '" << target->hoppedVeh->getID() <<
"' at position " << target->hoppedVeh->getPositionOnLane() <<
" is closer." << std::endl;
621 #ifdef DEBUG_SURROUNDING_VEHICLES 624 if (partialBehind != 0 && partialBehind != neighFollow) {
625 std::cout <<
"'Partial behind'-vehicle '" << target->lane->getPartialBehind(candi)->
getID() <<
"' at position " << partialBehind->
getPositionOnLane() <<
" is closer." << std::endl;
630 neighFollow =
getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi));
632 if (neighFollow == 0) {
634 #ifdef DEBUG_SURROUNDING_VEHICLES 636 if (consecutiveFollower.first == 0) {
637 std::cout <<
"no follower found." << std::endl;
639 std::cout <<
"found follower '" << consecutiveFollower.first->
getID() <<
"' on consecutive lanes." << std::endl;
643 return std::make_pair(const_cast<MSVehicle*>(consecutiveFollower.first), consecutiveFollower.second);
645 #ifdef DEBUG_SURROUNDING_VEHICLES 647 std::cout <<
"found follower '" << neighFollow->
getID() <<
"'." << std::endl;
651 return std::pair<MSVehicle* const, double>(neighFollow,
675 const std::pair<MSVehicle* const, double>& leader,
676 const std::vector<MSVehicle::LaneQ>& preb)
const {
680 if (neighLead.first != 0 && neighLead.first == neighFollow.first) {
683 neighFollow.first = 0;
686 return checkChange(laneOffset, target->lane, leader, neighLead, neighFollow, preb);
693 const std::pair<MSVehicle* const, double>& leader,
694 const std::pair<MSVehicle* const, double>& neighLead,
695 const std::pair<MSVehicle* const, double>& neighFollow,
696 const std::vector<MSVehicle::LaneQ>& preb)
const {
700 #ifdef DEBUG_CHECK_CHANGE 703 <<
"\n" <<
SIMTIME <<
" checkChange() for vehicle '" << vehicle->
getID() <<
"'" 712 if (neighFollow.first != 0 && neighFollow.second < 0) {
716 #ifdef DEBUG_CHECK_CHANGE 719 <<
" overlapping with follower..." 725 if (neighLead.first != 0 && neighLead.second < 0) {
728 #ifdef DEBUG_CHECK_CHANGE 731 <<
" overlapping with leader..." 743 if ((blocked & blockedByFollower) == 0 && neighFollow.first != 0) {
751 const double vNextFollower = neighFollow.first->getSpeed() +
MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
754 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(vNextFollower,
757 blocked |= blockedByFollower;
760 #ifdef DEBUG_CHECK_CHANGE 763 <<
" back gap unsafe: " 764 <<
"gap = " << neighFollow.second
765 <<
" vNextFollower=" << vNextFollower
766 <<
" vNextEgo=" << vNextLeader
768 << neighFollow.first->getCarFollowModel().getSecureGap(vNextFollower,
778 if ((blocked & blockedByLeader) == 0 && neighLead.first != 0) {
787 const double vNextLeader = neighLead.first->getSpeed() +
MIN2(0., tauRemainder * neighLead.first->getAcceleration());
790 vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel());
792 blocked |= blockedByLeader;
795 #ifdef DEBUG_CHECK_CHANGE 798 <<
" front gap unsafe: " 799 <<
"gap = " << neighLead.second
800 <<
" vNextLeader=" << vNextLeader
801 <<
" vNextEgo=" << vNextFollower
804 vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel())
815 if (leader.first != 0) {
819 #ifdef DEBUG_CHECK_CHANGE 821 std::cout <<
SIMTIME <<
" pedestrian on road " + leader.first->getID() <<
" gap=" << gap <<
" brakeGap=" << brakeGap <<
"\n";
824 if (brakeGap > gap) {
825 blocked |= blockedByLeader;
826 #ifdef DEBUG_CHECK_CHANGE 828 std::cout <<
SIMTIME <<
" blocked by pedestrian " + leader.first->getID() <<
"\n";
835 if (leader.first != 0) {
841 laneOffset, msg, blocked, leader, neighLead, neighFollow, *targetLane, preb, &(
myCandi->lastBlocked), &(
myCandi->firstBlocked));
850 const double speed = vehicle->
getSpeed();
852 if (seen < dist || myCandi->lane->isInternal()) {
853 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getCriticalLeader(dist, seen, speed, *vehicle);
854 if (neighLead2.first != 0 && neighLead2.first != neighLead.first) {
856 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
858 #ifdef DEBUG_SURROUNDING_VEHICLES 860 std::cout <<
SIMTIME <<
" found critical leader=" << neighLead2.first->getID()
861 <<
" gap=" << neighLead2.second <<
" secGap=" << secureGap <<
" secGap2=" << secureGap2 <<
"\n";
864 if (neighLead2.second < secureGap2) {
865 state |= blockedByLeader;
870 if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
873 state |= blockedByLeader;
885 if (estimatedLCDuration == -1) {
887 #ifdef DEBUG_CHECK_CHANGE 889 std::cout <<
SIMTIME <<
" checkChange() too slow to guarantee completion of continuous lane change." 890 <<
"\nestimatedLCDuration=" << estimatedLCDuration
891 <<
"\ndistToNeighLane=" << distToNeighLane
899 const double avgSpeed = 0.5 * (
903 const double space2change = avgSpeed * estimatedLCDuration;
906 #ifdef DEBUG_CHECK_CHANGE 908 std::cout <<
SIMTIME <<
" checkChange() checking continuous lane change..." 909 <<
"\ndistToNeighLane=" << distToNeighLane
910 <<
" estimatedLCDuration=" << estimatedLCDuration
911 <<
" space2change=" << space2change
912 <<
" avgSpeed=" << avgSpeed
921 MSLinkCont::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
922 while (!nextLane->
isLinkEnd(link) && seen <= space2change) {
926 || (nextLane->
getEdge().
isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
931 if ((*link)->getViaLane() == 0) {
934 nextLane = (*link)->getViaLaneOrLane();
939 #ifdef DEBUG_CHECK_CHANGE 941 std::cout <<
" available distance=" << seen << std::endl;
944 if (nextLane->
isLinkEnd(link) && seen < space2change) {
945 #ifdef DEBUG_CHECK_CHANGE 947 std::cout <<
SIMTIME <<
" checkChange insufficientSpace: seen=" << seen <<
" space2change=" << space2change <<
"\n";
953 if ((state & LCA_BLOCKED) == 0) {
956 const double speed = vehicle->
getSpeed();
961 MSLinkCont::const_iterator link =
MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
962 while (!nextLane->
isLinkEnd(link) && seen <= space2change && seen <= dist) {
963 nextLane = (*link)->getViaLaneOrLane();
965 if (targetLane == 0) {
969 std::pair<MSVehicle* const, double> neighLead2 = targetLane->
getLeader(vehicle, -seen, std::vector<MSLane*>());
970 if (neighLead2.first != 0 && neighLead2.first != neighLead.first
972 vehicle->
getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
973 state |= blockedByLeader;
977 if ((*link)->getViaLane() == 0) {
987 const int oldstate = state;
990 #ifdef DEBUG_CHECK_CHANGE 993 <<
" veh=" << vehicle->
getID()
1002 if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
1027 bool oppositeChangeByTraci =
false;
1030 oppositeChangeByTraci =
true;
1033 if (!isOpposite && leader.first == 0 && !oppositeChangeByTraci) {
1039 if (!isOpposite && !oppositeChangeByTraci
1041 && leader.first != 0
1046 #ifdef DEBUG_CHANGE_OPPOSITE 1048 std::cout <<
" not overtaking leader " << leader.first->getID() <<
" that has blinker set\n";
1060 int direction = isOpposite ? -1 : 1;
1061 std::pair<MSVehicle*, double> neighLead((
MSVehicle*)0, -1);
1064 double timeToOvertake;
1065 double spaceToOvertake;
1074 std::pair<MSVehicle*, double> overtaken;
1075 std::pair<MSVehicle*, double> oncoming;
1078 if (!isOpposite && !oppositeChangeByTraci) {
1080 if (overtaken.first == 0) {
1083 #ifdef DEBUG_CHANGE_OPPOSITE 1085 std::cout <<
" compute time/space to overtake for columnLeader=" << overtaken.first->getID() <<
" egoGap=" << overtaken.second <<
"\n";
1091 #ifdef DEBUG_CHANGE_OPPOSITE 1093 std::cout <<
" cannot changeOpposite due to upcoming stop (dist=" << vehicle->
nextStopDist() <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1100 #ifdef DEBUG_CHANGE_OPPOSITE 1103 <<
" veh=" << vehicle->
getID()
1104 <<
" changeOpposite opposite=" << opposite->
getID()
1106 <<
" timeToOvertake=" << timeToOvertake
1107 <<
" spaceToOvertake=" << spaceToOvertake
1112 if (neighLead.first != 0) {
1113 const MSVehicle* oncoming = neighLead.first;
1119 const double surplusGap = neighLead.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
1120 #ifdef DEBUG_CHANGE_OPPOSITE 1123 <<
" oncoming=" << oncoming->
getID()
1124 <<
" oncomingGap=" << neighLead.second
1125 <<
" leaderGap=" << leader.second
1126 <<
" safetyGap=" << safetyGap
1127 <<
" surplusGap=" << surplusGap
1131 if (surplusGap < 0) {
1133 #ifdef DEBUG_CHANGE_OPPOSITE 1135 std::cout <<
" cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap <<
")\n";
1139 #ifdef DEBUG_CHANGE_OPPOSITE 1142 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" does not changeOpposite due to dangerous oncoming " << oncoming->
getID() <<
" (but the leader is also opposite)\n";
1150 }
else if (!oppositeChangeByTraci) {
1151 timeToOvertake = -1;
1153 spaceToOvertake = std::numeric_limits<double>::max();
1156 double gap = leader.second;
1157 while (leader.first !=
nullptr && leader.first->getLaneChangeModel().isOpposite() && dist > 0) {
1159 #ifdef DEBUG_CHANGE_OPPOSITE 1161 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" opposite leader=" << leader.first->getID() <<
" gap=" << gap <<
" is driving against the flow\n";
1164 const double gapToLeaderFront = leader.second + leader.first->getVehicleType().getLengthWithGap();
1165 dist -= gapToLeaderFront;
1167 if (leader.first != 0) {
1168 gap += gapToLeaderFront;
1171 leader.second = gap;
1182 if (usableDist < spaceToOvertake) {
1185 assert(bestLaneConts.size() >= 1);
1186 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1187 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1188 #ifdef DEBUG_CHANGE_OPPOSITE 1190 std::cout <<
" usableDist=" << usableDist <<
" opposite=" <<
Named::getIDSecure((*it)->getOpposite()) <<
"\n";
1193 if ((*it)->getOpposite() == 0 || !(*it)->getOpposite()->allowsVehicleClass(vehicle->
getVClass())) {
1198 if (*(it - 1) != 0) {
1207 #ifdef DEBUG_CHANGE_OPPOSITE 1209 std::cout <<
" stop lookahead at link=" << (link == 0 ?
"NULL" : link->
getViaLaneOrLane()->
getID()) <<
" state=" << (link == 0 ?
"?" :
toString(link->getState())) <<
" ignoreRed=" << vehicle->
ignoreRed(link,
true) <<
"\n";
1215 usableDist += (*it)->getLength();
1219 if (!isOpposite && usableDist < spaceToOvertake) {
1220 #ifdef DEBUG_CHANGE_OPPOSITE 1222 std::cout <<
" cannot changeOpposite due to insufficient space (seen=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
")\n";
1227 #ifdef DEBUG_CHANGE_OPPOSITE 1229 std::cout <<
" usableDist=" << usableDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1234 std::vector<MSVehicle::LaneQ> preb = vehicle->
getBestLanes();
1249 if (leader.first != 0) {
1250 if (!leader.first->getLaneChangeModel().isOpposite()) {
1256 laneQ.
length =
MIN2(laneQ.
length, leader.second / 2 + forwardPos - safetyGap);
1257 #ifdef DEBUG_CHANGE_OPPOSITE 1259 std::cout <<
SIMTIME <<
" found oncoming leader=" << oncoming->
getID() <<
" gap=" << leader.second <<
"\n";
1263 #ifdef DEBUG_CHANGE_OPPOSITE 1265 std::cout <<
SIMTIME <<
" opposite leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" is driving against the flow\n";
1269 if (neighLead.first != 0) {
1271 if (overtaken.first == 0) {
1272 #ifdef DEBUG_CHANGE_OPPOSITE 1274 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" did not find columnleader to overtake\n";
1278 const double remainingDist = laneQ.
length - forwardPos;
1280 #ifdef DEBUG_CHANGE_OPPOSITE 1282 std::cout <<
SIMTIME <<
" ego=" << vehicle->
getID() <<
" is overtaking " << overtaken.first->getID()
1283 <<
" remainingDist=" << remainingDist <<
" spaceToOvertake=" << spaceToOvertake <<
" timeToOvertake=" << timeToOvertake <<
"\n";
1286 if (remainingDist > spaceToOvertake) {
1295 #ifdef DEBUG_CHANGE_OPPOSITE 1297 std::cout <<
SIMTIME <<
" veh=" << vehicle->
getID() <<
" remaining dist=" << laneQ.
length - forwardPos <<
" forwardPos=" << forwardPos <<
" laneQ.length=" << laneQ.
length <<
"\n";
1302 int state =
checkChange(direction, opposite, leader, neighLead, neighFollow, preb);
1305 bool changingAllowed = (state &
LCA_BLOCKED) == 0;
1318 #ifdef DEBUG_CHANGE_OPPOSITE 1320 std::cout <<
SIMTIME <<
" changing to opposite veh=" << vehicle->
getID() <<
" dir=" << direction <<
" opposite=" <<
Named::getIDSecure(opposite) <<
" state=" << state <<
"\n";
1325 #ifdef DEBUG_CHANGE_OPPOSITE 1327 std::cout <<
SIMTIME <<
" not changing to opposite veh=" << vehicle->
getID() <<
" dir=" << direction
1345 const double v = vehicle->
getSpeed();
1358 const double sign = -1;
1362 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
1363 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME 1365 std::cout <<
" computeOvertakingTime v=" << v <<
" vMax=" << vMax <<
" u=" << u <<
" a=" << a <<
" d=" << d <<
" gap=" << gap <<
" g=" << g <<
" t=" << t
1366 <<
" distEgo=" << v* t + t* t* a * 0.5 <<
" distLead=" << g + u* t
1375 t = ceil(t /
TS) *
TS;
1378 const double timeToMaxSpeed = (vMax - v) / a;
1380 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME 1382 std::cout <<
" t=" << t <<
" tvMax=" << timeToMaxSpeed <<
"\n";
1385 if (t <= timeToMaxSpeed) {
1387 spaceToOvertake = v * t + t * t * a * 0.5;
1388 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME 1390 std::cout <<
" sto=" << spaceToOvertake <<
"\n";
1395 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
1396 const double m = timeToMaxSpeed;
1399 t = (g - s + m * vMax) / (vMax - u);
1402 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME 1404 std::cout <<
" t2=" << t <<
"\n";
1407 timeToOvertake = std::numeric_limits<double>::max();
1408 spaceToOvertake = std::numeric_limits<double>::max();
1413 t = ceil(t /
TS) *
TS;
1416 spaceToOvertake = s + (t - m) * vMax;
1417 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME 1419 std::cout <<
" t2=" << t <<
" s=" << s <<
" sto=" << spaceToOvertake <<
" m=" << m <<
"\n";
1425 timeToOvertake *= safetyFactor;
1426 spaceToOvertake *= safetyFactor;
1427 #ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME 1429 if (safetyFactor != 1) {
1430 std::cout <<
" applying safetyFactor=" << safetyFactor
1431 <<
" tto=" << timeToOvertake <<
" sto=" << spaceToOvertake <<
"\n";
1440 std::pair<MSVehicle*, double>
1442 assert(leader.first != 0);
1447 std::pair<MSVehicle*, double> columnLeader = leader;
1448 double egoGap = leader.second;
1449 bool foundSpaceAhead =
false;
1450 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
1452 if (maxLookAhead == std::numeric_limits<double>::max()) {
1457 #ifdef DEBUG_CHANGE_OPPOSITE 1459 std::cout <<
" getColumnleader vehicle=" << vehicle->
getID() <<
" leader=" << leader.first->getID() <<
" gap=" << leader.second <<
" maxLookAhead=" << maxLookAhead <<
"\n";
1463 while (!foundSpaceAhead) {
1464 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
1466 + columnLeader.first->getVehicleType().getMinGap()
1471 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->
getEdge());
1472 std::pair<MSVehicle* const, double> leadLead = columnLeader.first->getLane()->getLeader(
1473 columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap,
1476 #ifdef DEBUG_CHANGE_OPPOSITE 1478 std::cout <<
" leadLead=" <<
Named::getIDSecure(leadLead.first) <<
" gap=" << leadLead.second <<
"\n";
1481 if (leadLead.first == 0) {
1482 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
1483 const double requiredSpace = safetyFactor * (requiredSpaceAfterLeader
1485 #ifdef DEBUG_CHANGE_OPPOSITE 1487 std::cout <<
" no direct leader found after columnLeader " << columnLeader.first->getID()
1488 <<
" availableSpace=" << availableSpace
1489 <<
" req1=" << requiredSpaceAfterLeader
1490 <<
" req2=" << requiredSpace / safetyFactor
1491 <<
" req3=" << requiredSpace
1495 if (availableSpace > requiredSpace) {
1496 foundSpaceAhead =
true;
1501 #ifdef DEBUG_CHANGE_OPPOSITE 1503 std::cout <<
" look for another leader on lane " <<
Named::getIDSecure(next) <<
"\n";
1506 while (next !=
nullptr) {
1509 if (cand ==
nullptr) {
1511 if (availableSpace > requiredSpace) {
1512 foundSpaceAhead =
true;
1517 if (availableSpace > requiredSpace) {
1518 foundSpaceAhead =
true;
1525 if (!foundSpaceAhead) {
1526 return std::make_pair(
nullptr, -1);
1530 const double requiredSpace = safetyFactor * (requiredSpaceAfterLeader
1531 + vehicle->
getCarFollowModel().
getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel()));
1532 #ifdef DEBUG_CHANGE_OPPOSITE 1534 std::cout <<
" leader's leader " << leadLead.first->getID() <<
" space=" << leadLead.second
1535 <<
" req1=" << requiredSpaceAfterLeader
1536 <<
" req2=" << requiredSpace / safetyFactor
1537 <<
" req3=" << requiredSpace
1541 if (leadLead.second > requiredSpace) {
1542 foundSpaceAhead =
true;
1544 #ifdef DEBUG_CHANGE_OPPOSITE 1546 std::cout <<
" not enough space after columnLeader=" << columnLeader.first->getID() <<
" required=" << requiredSpace <<
"\n";
1549 seen +=
MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
1550 if (seen > maxLookAhead) {
1551 #ifdef DEBUG_CHANGE_OPPOSITE 1553 std::cout <<
" cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen <<
" columnLeader=" << columnLeader.first->getID() <<
")\n";
1556 return std::make_pair(
nullptr, -1);
1559 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
1560 columnLeader = leadLead;
1561 #ifdef DEBUG_CHANGE_OPPOSITE 1563 std::cout <<
" new columnLeader=" << columnLeader.first->getID() <<
"\n";
1569 columnLeader.second = egoGap;
1570 return columnLeader;
1576 for (
auto it = conts.begin(); it != conts.end(); ++it) {
1578 if (it + 1 != conts.end()) {
double myPos
the stored position
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected.
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double computeAngle() const
compute the current vehicle angle
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i...
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignore
MSEdge & getEdge() const
Returns the lane's edge.
double myAngle
the angle in radians (
Representation of a vehicle in the micro simulation.
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
MSLane * lane
the lane corresponding to this ChangeElem (the current change candidate is on this lane) ...
The action is done to help someone else.
static std::pair< MSVehicle *, double > getColumnleader(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
LinkDirection getDirection() const
Returns the direction the vehicle passing this link take.
virtual bool hasPedestrians(const MSLane *lane)
whether the given lane has pedestrians on it
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir) const
State myState
This Vehicles driving state (pos and speed)
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change...
MSLane * getLane() const
Returns the lane the vehicle is on.
void setLeaderGaps(CLeaderDist, double secGap)
The vehicle is blocked by left follower.
int checkChange(int laneOffset, const 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) const
bool continueChange(MSVehicle *vehicle, ChangerIt &from)
continue a lane change maneuver and return whether the midpoint was passed in this step (used if gLan...
virtual void initChanger()
Initialize the changer before looping over all vehicles.
int getShadowDirection() const
return the direction in which the current shadow lane lies
virtual bool changeOpposite(std::pair< MSVehicle *, double > leader)
const bool myAllowsChanging
double getPositionOnLane() const
Get the vehicle's position along the lane.
double myPosLat
the stored lateral position
MSVehicle * veh(ConstChangerIt ce) const
static MSLane * getLaneAfter(MSLane *lane, const std::vector< MSLane *> &conts)
return the next lane in conts beyond lane or nullptr
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
Vehicle is too slow to guarantee success of lane change (used for continuous lane changing in case th...
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD
double getLength() const
Returns the lane's length.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
bool isLinkEnd(MSLinkCont::const_iterator &i) const
bool isStoppedOnLane() const
double getRightSideOnLane() const
Get the vehicle's lateral position on the lane:
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
static const double NO_NEIGHBOR
void startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
start the lane change maneuver (and finish it instantly if gLaneChangeDuration == 0) ...
const std::string & getID() const
Returns the id.
ChangeElem(MSLane *_lane)
double length
The overall length which may be driven when using this lane without a lane change.
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
double getWidth() const
Returns the lane's width.
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
This is an uncontrolled, zipper-merge link.
The link is a (hard) left direction.
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
MSAbstractLaneChangeModel & getLaneChangeModel()
SUMOTime getLaneTimeLineDuration()
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one...
LinkState getState() const
Returns the current state of the link.
Right blinker lights are switched on.
bool applyTraCICommands(MSVehicle *vehicle)
Execute TraCI LC-commands.
The link is a straight direction.
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
void setFollowerGaps(CLeaderDist follower, double secGap)
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
A class responsible for exchanging messages between cars involved in lane-change interaction.
double getLCParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
The vehicle changes lanes (micro only)
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Left blinker lights are switched on.
virtual void updateChanger(bool vehHasChanged)
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
blocked in all directions
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
The action is urgent (to be defined by lc-model)
virtual double getSecureGap(const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
static MSPModel * getModel()
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points...
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, 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...
Position myCachedPosition
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.
bool havePriority() const
Returns whether this link is a major link.
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
The link is a (hard) right direction.
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.
static void computeOvertakingTime(const MSVehicle *vehicle, const MSVehicle *leader, double gap, double &timeToOvertake, double &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
A structure representing the best lanes for continuing the current route starting at 'lane'...
virtual PersonDist nextBlocking(const MSLane *lane, double minPos, double minRight, double maxLeft, double stopTime=0)
returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or 0 ...
bool hasInfluencer() const
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
MSLaneChanger()
Default constructor.
MSLane * getOpposite() const
return the opposite direction lane for lane changing or 0
bool isInternal() const
return whether this edge is an internal edge
void updateLanes(SUMOTime t)
const SUMOVTypeParameter & getParameter() const
std::vector< MSVehicle * > VehCont
Container for vehicles.
static MSLinkCont::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane *> &conts)
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
void setOrigLeaderGaps(CLeaderDist, double secGap)
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD
std::pair< const MSPerson *, double > PersonDist
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP
std::pair< const MSVehicle *, double > CLeaderDist
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
Influencer & getInfluencer()
Returns the velocity/lane influencer.
virtual double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
LaneChangeAction
The state of a vehicle's lane-change behavior.
virtual void setOwnState(const int state)
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
static MSLink * getConnectingLink(const MSLane &from, const MSLane &to)
Returns the link connecting both lanes Both lanes have to be non-internal; 0 may be returned if no co...
virtual ~MSLaneChanger()
Destructor.
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
The vehicle is blocked being overlapping.
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
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.
double getLength() const
Get vehicle's length [m].
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
The action is due to a TraCI request.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
#define OPPOSITE_OVERTAKING_SAFETY_FACTOR
void registerUnchanged(MSVehicle *vehicle)
The vehicle does not have enough space to complete a continuous lane and change before the next turni...
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links ...
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool isStopped() const
Returns whether the vehicle is at a stop.
MSVehicle * hoppedVeh
last vehicle that changed into this lane
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
double getSpeed() const
Returns the vehicle's current speed.
The vehicle is blocked by right leader.
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
public emergency vehicles
static SUMOTime gLaneChangeDuration
const std::string & getID() const
Returns the name of the vehicle.
Representation of a lane in the micro simulation.
double myBackPos
the stored back position
The vehicle is blocked by right follower.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
void saveLCState(const int dir, const int stateWithoutTraCI, const int state)
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
bool haveRed() const
Returns whether this link is blocked by a red (or redyellow) traffic light.
Interface for lane-change models.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR
static const Position INVALID
used to indicate that a position is valid
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)