48#define LOOK_FORWARD 10.
52#define LCA_RIGHT_IMPATIENCE -1.
53#define CUT_IN_LEFT_SPEED_THRESHOLD 27.
55#define LOOK_AHEAD_MIN_SPEED 0.0
56#define LOOK_AHEAD_SPEED_MEMORY 0.9
58#define HELP_DECEL_FACTOR 1.0
60#define HELP_OVERTAKE (10.0 / 3.6)
61#define MIN_FALLBEHIND (7.0 / 3.6)
63#define RELGAIN_NORMALIZATION_MIN_SPEED 10.0
65#define OPPOSITE_URGENCY 5.0
67#define KEEP_RIGHT_TIME 5.0
69#define KEEP_RIGHT_HEADWAY 2.0
70#define MAX_ONRAMP_LENGTH 200.
71#define TURN_LANE_DIST 200.0
73#define LC_RESOLUTION_SPEED_LAT 0.5
75#define REACT_TO_STOPPED_DISTANCE 100
76#define BLOCKER_IS_BLOCKED_TIME_THRESHOLD 5
78#define HYST_PRECISION 10000000
93#define DEBUG_COND (myVehicle.isSelected())
101 mySpeedGainProbabilityLeft(0),
102 mySpeedGainProbabilityRight(0),
103 myKeepRightProbability(0),
104 myLeadingBlockerLength(0),
124#ifdef DEBUG_CONSTRUCTOR
165 const std::pair<MSVehicle*, double>& leader,
166 const std::pair<MSVehicle*, double>& follower,
167 const std::pair<MSVehicle*, double>& neighLead,
168 const std::pair<MSVehicle*, double>& neighFollow,
170 const std::vector<MSVehicle::LaneQ>& preb,
174#ifdef DEBUG_WANTS_CHANGE
176 std::cout <<
"\nWANTS_CHANGE\n" <<
SIMTIME
183 <<
" considerChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
188 const int result =
_wantsChange(laneOffset, msgPass, blocked, leader, follower, neighLead, neighFollow, neighLane, preb, *lastBlocked, *firstBlocked);
190#ifdef DEBUG_WANTS_CHANGE
203#ifdef DEBUG_PATCH_SPEED
205 std::cout <<
"\nPATCH_SPEED\n"
212 <<
" wanted=" << wanted
219 const double newSpeed =
_patchSpeed(
MAX2(min, 0.0), wanted, max, cfModel);
221#ifdef DEBUG_PATCH_SPEED
223 const std::string patched = (wanted != newSpeed ?
" patched=" +
toString(newSpeed) :
"");
236#ifdef DEBUG_PATCH_SPEED
248 double nVSafe = wanted;
253#ifdef DEBUG_PATCH_SPEED
262 max =
MIN2(max,
MAX2(safe, vMinEmergency));
267 if (safe >= vMinEmergency) {
269 min =
MAX2(vMinEmergency, safe);
272#ifdef DEBUG_PATCH_SPEED
274 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ?
" (not enough)" :
"") <<
"\n";
277 nVSafe =
MAX2(min, safe);
297 nVSafe =
MIN2(v, nVSafe);
299 nVSafe =
MIN2(v * coopWeight + (1 - coopWeight) * wanted, nVSafe);
302#ifdef DEBUG_PATCH_SPEED
304 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" got nVSafe=" << nVSafe <<
" isOwn: " << i.second <<
" rawV=" << v <<
"\n";
309#ifdef DEBUG_PATCH_SPEED
311 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring low nVSafe=" << v <<
" min=" << min <<
"\n";
315#ifdef DEBUG_PATCH_SPEED
317 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring high nVSafe=" << v <<
" max=" << max <<
"\n";
325#ifdef DEBUG_PATCH_SPEED
338#ifdef DEBUG_PATCH_SPEED
343 return (max + wanted) / 2.0;
347#ifdef DEBUG_PATCH_SPEED
353 return (
MAX2(0., min) + wanted) / 2.0;
359#ifdef DEBUG_PATCH_SPEED
364 return (max + wanted) / 2.0;
405#ifdef DEBUG_PATCH_SPEED
410 return (max + wanted) / 2.0;
414#ifdef DEBUG_PATCH_SPEED
446 <<
" informedBy=" << sender->
getID()
447 <<
" info=" << pinfo->second
448 <<
" vSafe=" << pinfo->first
460 double overtakeDist = (gap
465 return MAX2(overtakeDist, 0.);
473 const std::pair<MSVehicle*, double>& neighLead,
474 double remainingSeconds) {
477 plannedSpeed =
MIN2(plannedSpeed,
481 const double a = i.first;
488 std::cout <<
"\nINFORM_LEADER"
493 const MSVehicle*
const nv = neighLead.first;
501 neighNextGap = neighLead.second +
SPEED2DIST(neighNextSpeed - plannedSpeed);
512 std::cout <<
" blocked by leader nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap="
519 const double dv = plannedSpeed - nv->
getSpeed();
522 overtakeTime = overtakeDist / dv;
527 overtakeTime = remainingSeconds - 1;
530 overtakeTime = remainingSeconds + 1;
536 <<
"\nnv = " << nv->
getID()
537 <<
"\nplannedSpeed = " << plannedSpeed
538 <<
"\nleaderSpeed = " << nv->
getSpeed()
540 <<
"\nremainingSeconds = " << remainingSeconds
541 <<
"\novertakeDist = " << overtakeDist
542 <<
"\novertakeTime = " << overtakeTime
557 && (!neighLead.first->isStopped() || (
isOpposite() && neighLead.second >= 0))) {
575 <<
" cannot overtake leader nv=" << nv->
getID()
579 <<
" overtakeDist=" << overtakeDist
580 <<
" overtakeTime=" << overtakeTime
581 <<
" remainingSeconds=" << remainingSeconds
582 <<
" currentGap=" << neighLead.second
584 <<
" neighNextSpeed=" << neighNextSpeed
585 <<
" neighNextGap=" << neighNextGap
586 <<
" targetSpeed=" << targetSpeed
587 <<
" nextSpeed=" << nextSpeed
598 <<
" cannot overtake fast leader nv=" << nv->
getID()
602 <<
" overtakeDist=" << overtakeDist
604 <<
" overtakeTime=" << overtakeTime
605 <<
" remainingSeconds=" << remainingSeconds
606 <<
" currentGap=" << neighLead.second
607 <<
" neighNextSpeed=" << neighNextSpeed
608 <<
" neighNextGap=" << neighNextGap
609 <<
" targetSpeed=" << targetSpeed
621 <<
" wants to overtake leader nv=" << nv->
getID()
623 <<
" overtakeDist=" << overtakeDist
624 <<
" remainingSeconds=" << remainingSeconds
625 <<
" overtakeTime=" << overtakeTime
626 <<
" currentGap=" << neighLead.second
639 const double targetSpeed =
MAX2(
645 std::cout <<
" not blocked by leader nv=" << nv->
getID()
647 <<
" gap=" << neighLead.second
648 <<
" neighNextSpeed=" << neighNextSpeed
649 <<
" neighNextGap=" << neighNextGap
651 <<
" targetSpeed=" << targetSpeed
655 return MIN2(targetSpeed, plannedSpeed);
663 const std::pair<MSVehicle*, double>& neighFollow,
664 double remainingSeconds,
665 double plannedSpeed) {
672 std::cout <<
"\nINFORM_FOLLOWER"
685 std::cout <<
"\n nv=" << nv->
getID() <<
" not willing to help because ego is much slower\n";
698 std::cout <<
"\n nv=" << nv->
getID() <<
" not willing to help because it is already too slow\n";
712 std::cout <<
" blocked by follower nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap="
719 if ((neededGap - neighFollow.second) / remainingSeconds < (
MAX2(plannedSpeed, 0.) - nv->
getSpeed())) {
722 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" without any help." <<
"\nneededGap = " << neededGap <<
"\n";
740 double neighNewSpeed;
742 double neighNewSpeed1s;
752 dv = plannedSpeed - neighNewSpeed1s;
759 decelGap = neighFollow.second + dv;
766 neighNewSpeed1s = nv->
getSpeed() - helpDecel;
782 <<
" plannedSpeed=" << plannedSpeed
783 <<
" threshold=" << onRampThreshold
784 <<
" neighNewSpeed=" << neighNewSpeed
785 <<
" neighNewSpeed1s=" << neighNewSpeed1s
787 <<
" gap=" << neighFollow.second
788 <<
" decelGap=" << decelGap
789 <<
" secureGap=" << secureGap
796 && neighNewSpeed1s < onRampThreshold) {
800 if (decelGap > 0 && decelGap >= secureGap) {
808 double vsafe, vsafe1;
830 std::cout <<
"nextGap=" << nextGap <<
" (without help decel) \n";
838 MAX2(0., plannedSpeed),
846 nv->
getSpeed(), plannedAccel, -decel2,
856 MAX2(0., plannedSpeed),
859 assert(vsafe >= vsafe1 - NUMERICAL_EPS);
863 std::cout <<
"nextGap=" << nextGap
864 <<
" (with vsafe1 and help decel) \nvsafe1=" << vsafe1
865 <<
" vsafe=" << vsafe
874 if (nextGap < nextSecureGap) {
876 vsafe = neighNewSpeed;
881 std::cout <<
"nextGap=" << nextGap
882 <<
" minNextSecureGap=" << nextSecureGap
883 <<
" vsafe=" << vsafe <<
"\n";
893 std::cout <<
" wants to cut in before nv=" << nv->
getID()
894 <<
" vsafe1=" << vsafe1 <<
" vsafe=" << vsafe
922 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (eventually)\n";
931 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (nv cannot overtake right)\n";
954 std::cout <<
" wants right follower to slow down a bit\n";
964 std::cout <<
" wants to cut in before right follower nv=" << nv->
getID() <<
" (eventually)\n";
986 if (gapAfterRemainingSecs >= secureGapAfterRemainingSecs) {
989 std::cout <<
" wants to cut in before follower nv=" << nv->
getID() <<
" (eventually)\n";
1002#ifdef DEBUG_INFORMER
1006 <<
" informs follower " << nv->
getID()
1007 <<
" vhelp=" << vhelp
1016 const double needDV = overtakeDist / remainingSeconds;
1020#ifdef DEBUG_INFORMER
1024 <<
" wants to be overtaken by=" << nv->
getID()
1025 <<
" overtakeDist=" << overtakeDist
1027 <<
" vhelp=" << vhelp
1028 <<
" needDV=" << needDV
1039#ifdef DEBUG_INFORMER
1041 std::cout <<
" wants to cut in before non-blocking follower nv=" << nv->
getID() <<
"\n";
1068 scaledDelta =
MIN2(overlap, maxDist);
1077 deltaPosLat =
MAX2(
MIN2(deltaPosLat, maxDist), -maxDist);
1126 const std::pair<MSVehicle*, double>& leader,
1127 const std::pair<MSVehicle*, double>& follower,
1128 const std::pair<MSVehicle*, double>& neighLead,
1129 const std::pair<MSVehicle*, double>& neighFollow,
1131 const std::vector<MSVehicle::LaneQ>& preb,
1134 assert(laneOffset == 1 || laneOffset == -1);
1138 int bestLaneOffset = 0;
1143 double currentDist = 0;
1144 double neighDist = 0;
1157 const int prebOffset = laneOffset;
1158 for (
int p = 0; p < (int) preb.size(); ++p) {
1162 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1163 assert(p + prebOffset < (
int)preb.size());
1165 neigh = preb[p + prebOffset];
1166 currentDist = curr.
length;
1167 neighDist = neigh.
length;
1169 if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1170#ifdef DEBUG_WANTS_CHANGE
1174 <<
" bestLaneOffsetOld=" << bestLaneOffset
1175 <<
" bestLaneOffsetNew=" << laneOffset
1179 bestLaneOffset = prebOffset;
1181 best = preb[p + bestLaneOffset];
1186 assert(curr.
lane !=
nullptr);
1187 assert(neigh.
lane !=
nullptr);
1188 assert(best.
lane !=
nullptr);
1190 const bool right = (laneOffset == -1);
1192 double driveToNextStop = -std::numeric_limits<double>::max();
1200#ifdef DEBUG_WANTS_CHANGE
1205 <<
" stopPos=" << stopPos
1206 <<
" currentDist=" << currentDist
1207 <<
" neighDist=" << neighDist
1211 currentDist =
MAX2(currentDist, stopPos);
1212 neighDist =
MAX2(neighDist, stopPos);
1217 bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1223 if (lastBlocked != firstBlocked) {
1227#ifdef DEBUG_WANTS_CHANGE
1236 <<
" leaderGap=" << leader.second
1238 <<
" followerGap=" << follower.second
1240 <<
" neighLeadGap=" << neighLead.second
1242 <<
" neighFollowGap=" << neighFollow.second
1265 assert(memoryFactor > 0.);
1271 const bool hasStoppedLeader = leader.first != 0 && leader.first->isStopped() && leader.second < (currentDist - posOnLane);
1275 if (bestLaneOffset == 0 && hasBidiLeader) {
1278 }
else if (bestLaneOffset == 0 && hasStoppedLeader) {
1283 + leader.first->getVehicleType().getLengthWithGap()
1285 }
else if (bestLaneOffset == laneOffset && neighLead.first != 0 && (neighLead.first->isStopped() || hasBidiNeighLeader) && neighLead.second < (currentDist - posOnLane)) {
1290 + neighLead.first->getVehicleType().getLengthWithGap()
1291 + neighLead.second);
1292 }
else if (!hasStoppedLeader &&
1294 || hasBidiNeighLeader)) {
1297 changeToBest =
false;
1316 currentDist += roundaboutBonus;
1317 neighDist += roundaboutBonus;
1321 const double maxJam =
MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1325 double thisLaneVSafe = vMax;
1328 double neighLeftPlace =
MAX2(0.0, neighDist - posOnLane - maxJam);
1329 if (neighLead.first != 0 && neighLead.first->isStopped()) {
1330 neighLeftPlace =
MIN2(neighLeftPlace, neighLead.second);
1333#ifdef DEBUG_WANTS_CHANGE
1338 <<
" laDist=" << laDist
1339 <<
" currentDist=" << currentDist
1340 <<
" usableDist=" << usableDist
1341 <<
" bestLaneOffset=" << bestLaneOffset
1343 <<
" best.length=" << best.
length
1344 <<
"\n roundaboutBonus=" << roundaboutBonus
1345 <<
" maxJam=" << maxJam
1346 <<
" neighDist=" << neighDist
1347 <<
" neighLeftPlace=" << neighLeftPlace
1348 << (hasBidiLeader ?
" bidiLeader" :
"")
1349 << (hasBidiNeighLeader ?
" bidiNeighLeader" :
"")
1354 bool changeLeftToAvoidOvertakeRight =
false;
1361 if (neighLead.first != 0 && checkOverTakeRight && !right) {
1371 thisLaneVSafe =
MIN2(thisLaneVSafe, vSafe);
1374 const double deltaGapFuture = deltaV * 8;
1377 if (vSafeFuture < vSafe) {
1378 const double relativeGain = deltaV /
MAX2(vMax,
1381 changeLeftToAvoidOvertakeRight =
true;
1383#ifdef DEBUG_WANTS_CHANGE
1386 <<
" avoid overtaking on the right nv=" << nv->
getID()
1387 <<
" deltaV=" << deltaV
1397 const bool currFreeUntilNeighEnd = leader.first ==
nullptr || neighDist - posOnLane <= leader.second;
1398 const double overtakeDist = (leader.first == 0 || hasBidiLeader ? -1 :
1400 const double overtakeDist2 = (neighLead.first == 0 || !neighLead.first->isStopped() ? -1 :
1404 &&
MIN2(neighDist, currentDist) - posOnLane > overtakeDist
1406 && (!checkOverTakeRight || !right)
1408 && (neighLead.first == 0 || !neighLead.first->isStopped()
1410 || neighLead.second > overtakeDist
1412 || (overtakeDist2 > leader.second &&
hasFreeLane(laneOffset, neighLead)))) {
1415#ifdef DEBUG_WANTS_CHANGE
1417 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" overtake stopped leader=" << leader.first->getID()
1418 <<
" overtakeDist=" << overtakeDist
1419 <<
" overtakeDist2=" << overtakeDist
1420 <<
" hasFreeLane=" <<
hasFreeLane(laneOffset, neighLead)
1421 <<
" remaining=" <<
MIN2(neighDist, currentDist) - posOnLane
1426 }
else if (!changeToBest &&
currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist) && !hasBidiLeader) {
1433#ifdef DEBUG_WANTS_CHANGE
1435 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace <<
"\n";
1439 }
else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1444#ifdef DEBUG_WANTS_CHANGE
1446 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace <<
"\n";
1450 }
else if (bestLaneOffset == 0
1451 && (leader.first == 0 || !leader.first->isStopped())
1454 && roundaboutBonus == 0
1463#ifdef DEBUG_WANTS_CHANGE
1465 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to leave the bestLane (neighDist=" << neighDist <<
")\n";
1472#ifdef DEBUG_WANTS_CHANGE
1480 if ((ret & lcaCounter) != 0) {
1484#ifdef DEBUG_WANTS_CHANGE
1502#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1504 std::cout <<
" reserving space for unseen blockers myLeadingBlockerLength=" <<
myLeadingBlockerLength <<
"\n";
1513 if (firstBlocked != neighLead.first) {
1516#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1518 std::cout <<
SIMTIME <<
" canReserve=" << canReserve <<
" canContinue=" << canContinue <<
"\n";
1527 const int remainingLanes =
MAX2(1, abs(bestLaneOffset));
1529 const double remainingSeconds = ((ret &
LCA_TRACI) == 0 ?
1533 if (!hasBidiNeighLeader) {
1534 const double plannedSpeed =
informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1540 if (!hasBidiNeighFollower) {
1541 informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1544#ifdef DEBUG_WANTS_CHANGE
1549 <<
" remainingSeconds=" << remainingSeconds
1550 <<
" plannedSpeed=" << plannedSpeed
1555#ifdef DEBUG_WANTS_CHANGE
1560 <<
" remainingSeconds=" << remainingSeconds
1561 <<
" hasBidiNeighLeader\n";
1574 const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1575 || (leader.first != 0 && leader.first->getAcceleration() > 0);
1586 double inconvenience = laneOffset < 0
1590 const double relSpeedDiff = thisLaneVSafe == 0 ? 0 : (thisLaneVSafe - neighLaneVSafe) /
MAX2(thisLaneVSafe, neighLaneVSafe);
1591 inconvenience =
MAX2(relSpeedDiff, inconvenience);
1592 inconvenience =
MIN2(1.0, inconvenience);
1596#ifdef DEBUG_WANTS_CHANGE
1602 <<
" neighSpeedFactor=" << (thisLaneVSafe / neighLaneVSafe - 1)
1603 <<
" inconvenience=" << inconvenience
1604 <<
" speedInconv=" << speedGainInconvenient
1605 <<
" occInconv=" << neighOccupancyInconvenient
1611 if (roundaboutBonus > 0) {
1613#ifdef DEBUG_WANTS_CHANGE
1617 <<
" roundaboutBonus=" << roundaboutBonus
1647#ifdef DEBUG_WANTS_CHANGE
1649 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to get stranded on the on-ramp of a highway\n";
1669 && (!speedGainInconvenient)
1671 && (changeToBest ||
currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1674#ifdef DEBUG_COOPERATE
1678 <<
" wantsChangeToHelp=" << (right ?
"right" :
"left")
1680 << (((
myOwnState & myLca) == 0) ?
" (counter)" :
"")
1689 if (nv !=
nullptr && !hasBidiNeighFollower) {
1719 const double relativeGain = (neighLaneVSafe - thisLaneVSafe) /
MAX2(neighLaneVSafe,
1722#ifdef DEBUG_WANTS_CHANGE
1726 <<
" currentDist=" << currentDist
1727 <<
" neighDist=" << neighDist
1728 <<
" thisVSafe=" << thisLaneVSafe
1729 <<
" neighVSafe=" << neighLaneVSafe
1730 <<
" relGain=" <<
toString(relativeGain, 8)
1737 if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1747 double acceptanceTime;
1754 if (follower.first !=
nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1758 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1759 if (fRSF > roadSpeedFactor) {
1760 acceptanceTime /= fRSF;
1766 double fullSpeedDrivingSeconds =
MIN2(acceptanceTime, fullSpeedGap / vMax);
1767 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1768 fullSpeedGap =
MAX2(0.,
MIN2(fullSpeedGap,
1770 vMax, neighLead.first->
getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1771 fullSpeedDrivingSeconds =
MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1774 if (checkOverTakeRight && leader.first != 0
1775 && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1776 fullSpeedGap =
MIN2(fullSpeedGap, leader.second);
1777 fullSpeedDrivingSeconds =
MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1792#ifdef DEBUG_WANTS_CHANGE
1797 <<
" neighDist=" << neighDist
1799 <<
" leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1801 myVehicle.
getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1802 <<
" acceptanceTime=" << acceptanceTime
1803 <<
" fullSpeedGap=" << fullSpeedGap
1804 <<
" fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1818#ifdef DEBUG_WANTS_CHANGE
1825 <<
" thisLaneVSafe=" << thisLaneVSafe
1826 <<
" neighLaneVSafe=" << neighLaneVSafe
1827 <<
" relativeGain=" << relativeGain
1828 <<
" blocked=" << blocked
1845 if (thisLaneVSafe > neighLaneVSafe) {
1848 }
else if (thisLaneVSafe == neighLaneVSafe) {
1863#ifdef DEBUG_WANTS_CHANGE
1870 <<
" thisLaneVSafe=" << thisLaneVSafe
1871 <<
" neighLaneVSafe=" << neighLaneVSafe
1872 <<
" relativeGain=" << relativeGain
1873 <<
" blocked=" << blocked
1879 && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1889 if (nv !=
nullptr && !hasBidiNeighFollower) {
1901 && relativeGain >= 0
1909#ifdef DEBUG_WANTS_CHANGE
1916 <<
" thisLaneVSafe=" << thisLaneVSafe
1917 <<
" neighLaneVSafe=" << neighLaneVSafe
1928 const MSVehicle* leader = leaderDist.first;
1929 const double gap = leaderDist.second;
1931 if (acceleratingLeader) {
1935 if (leader ==
nullptr) {
1947 if (leader ==
nullptr) {
1958 futureSpeed =
MIN2(vMax, futureSpeed);
1961 const double deltaV = vMax - futureLeaderSpeed;
1962 if (deltaV > 0 && gap > 0) {
1964 const double fullSpeedGap = gap - secGap;
1968 const double gapClosingTime =
MAX2(0.0, fullSpeedGap / deltaV);
1971 futureSpeed =
MIN2(futureSpeed, (gapClosingTime * futureSpeed + (foreCastTime - gapClosingTime) * futureLeaderSpeed) / foreCastTime);
1983 if (blocked !=
nullptr) {
1985#ifdef DEBUG_SLOW_DOWN
1994 if (gap > POSITION_EPS) {
2008 gap - POSITION_EPS, blocked->
getSpeed(),
2012#ifdef DEBUG_SLOW_DOWN
2016 <<
" slowing down for"
2040#ifdef DEBUG_WANTS_CHANGE
2042 std::cout <<
SIMTIME <<
" adapt to pedestrians on lane=" << lane->
getID() <<
"\n";
2048 if (leader.first != 0) {
2050 v =
MIN2(v, stopSpeed);
2051#ifdef DEBUG_WANTS_CHANGE
2053 std::cout <<
SIMTIME <<
" pedLeader=" << leader.first->getID() <<
" dist=" << leader.second <<
" v=" << v <<
"\n";
2064#ifdef DEBUG_WANTS_CHANGE
2066 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" myLeftSpace=" <<
myLeftSpace <<
" latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
" result=" << result <<
"\n";
2074 result =
MAX2(-speedBound,
MIN2(speedBound, result));
2087 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 /
myOppositeParam;
2095#ifdef DEBUG_SAVE_BLOCKER_LENGTH
2097 std::cout <<
SIMTIME <<
" saveBlockerLength veh=" <<
myVehicle.
getID() <<
" canReserve=" << canReserve <<
" myLeftSpace=" <<
myLeftSpace <<
" foeLeftSpace=" << foeLeftSpace <<
"\n";
2113 if (neighLeadStopped.first ==
nullptr) {
2116 int dir = (laneOffset > 0 ? 1 : -1);
2123 int nextOffset = laneOffset + dir;
2128 const double overtakeDist = neighLeadStopped.second + neighLeadStopped.first->getVehicleType().getLengthWithGap() +
myVehicle.
getLength() + POSITION_EPS;
2130 return nextLead.first ==
nullptr || nextLead.second >= overtakeDist ||
hasFreeLane(nextOffset, nextLead);
2177 }
else if (key ==
"speedGainProbabilityRight") {
2179 }
else if (key ==
"speedGainProbabilityLeft") {
2181 }
else if (key ==
"keepRightProbability") {
2183 }
else if (key ==
"lookAheadSpeed") {
2186 }
else if (key ==
"speedGainRP") {
2188 }
else if (key ==
"speedGainLP") {
2190 }
else if (key ==
"keepRightP") {
2246 }
else if (key ==
"speedGainProbabilityRight") {
2248 }
else if (key ==
"speedGainProbabilityLeft") {
2250 }
else if (key ==
"keepRightProbability") {
2252 }
else if (key ==
"lookAheadSpeed") {
2264 std::vector<long long int> lcState;
#define HELP_DECEL_FACTOR
#define LOOK_AHEAD_MIN_SPEED
#define LCA_RIGHT_IMPATIENCE
#define REACT_TO_STOPPED_DISTANCE
#define RELGAIN_NORMALIZATION_MIN_SPEED
#define CUT_IN_LEFT_SPEED_THRESHOLD
#define MAX_ONRAMP_LENGTH
#define LOOK_AHEAD_SPEED_MEMORY
#define BLOCKER_IS_BLOCKED_TIME_THRESHOLD
#define LC_RESOLUTION_SPEED_LAT
std::pair< const MSPerson *, double > PersonDist
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_KEEPRIGHT
The action is due to the default of keeping right "Rechtsfahrgebot".
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_BLOCKED_BY_LEADER
blocked by leader
@ LCA_BLOCKED_BY_LEFT_FOLLOWER
The vehicle is blocked by left follower.
@ LCA_AMBLOCKINGFOLLOWER_DONTBRAKE
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_LEFT
Wants go to the left.
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_AMBACKBLOCKER_STANDING
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_SPEEDGAIN
The action is due to the wish to be faster (tactical lc)
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_FOLLOWER
blocker by follower
@ SUMO_ATTR_LCA_COOPERATIVE_SPEED
@ SUMO_ATTR_LCA_ASSERTIVE
@ SUMO_ATTR_LCA_LOOKAHEADLEFT
@ SUMO_ATTR_LCA_SPEEDGAIN_PARAM
@ SUMO_ATTR_LCA_MAXDISTLATSTANDING
@ SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT
@ SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD
@ SUMO_ATTR_LCA_MAXSPEEDLATFACTOR
@ SUMO_ATTR_LCA_MAXSPEEDLATSTANDING
@ SUMO_ATTR_LCA_KEEPRIGHT_PARAM
@ SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD
@ SUMO_ATTR_LCA_COOPERATIVE_PARAM
@ SUMO_ATTR_LCA_OPPOSITE_PARAM
@ SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME
@ SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR
@ SUMO_ATTR_LCA_OVERTAKE_RIGHT
@ SUMO_ATTR_LCA_STRATEGIC_PARAM
@ SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME
@ SUMO_ATTR_LCA_EXPERIMENTAL1
@ SUMO_ATTR_LCA_SPEEDGAIN_URGENCY
@ SUMO_ATTR_LCA_SPEEDGAINRIGHT
int gPrecision
the precision for floating point outputs
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class responsible for exchanging messages between cars involved in lane-change interaction.
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
Interface for lane-change models.
double getForwardPos() const
get vehicle position relative to the forward direction lane
virtual double getExtraReservation(int bestLaneOffset, double neighExtraDist=0) const
double getCooperativeHelpTime() const
bool hasBlueLight() const
double getCooperativeHelpThreshold() const
virtual double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
virtual void resetSpeedLat()
double getCooperativeMinSpeed() const
int myOwnState
The current state of the vehicle.
virtual void prepareStep()
virtual void saveState(OutputDevice &out) const
Save the state of the laneChangeModel.
double myMaxDistLatStanding
bool canOvertakeRight(const MSVehicle *const nv, const double dist, const double maxSpeedDiff, const double helpOvertakeSpeed, double &vSafe, double &deltaV) const
void addLCSpeedAdvice(const double vSafe, bool ownAdvice=true)
Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration ...
int & getCanceledState(const int dir)
double myMaxSpeedLatFactor
const LaneChangeModel myModel
the type of this model
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
std::vector< std::pair< double, bool > > myLCAccelerationAdvices
virtual bool avoidOvertakeRight(const MSVehicle *const neighLeader, const bool allowProb=false) const
void setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
double myOvertakeRightParam
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
double myMaxSpeedLatStanding
double myStrategicLookahead
virtual void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the laneChangeModel from the given attributes.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
virtual bool isSelected() const
whether this vehicle is selected in the GUI
double getImpatience() const
Returns this vehicles impatience.
int getNumRemainingEdges() const
return the number of edges remaining in the route (include the current)
double getLength() const
Returns the vehicle's length.
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
const MSStop & getNextStop() const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
The car-following model abstraction.
static double gapExtrapolation(const double duration, const double currentGap, double v1, double v2, double a1=0, double a2=0, const double maxV1=std::numeric_limits< double >::max(), const double maxV2=std::numeric_limits< double >::max())
return the resulting gap if, starting with gap currentGap, two vehicles continue with constant accele...
virtual double minNextSpeedEmergency(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed after emergency braking, given the current speed (depends on the numerical ...
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
double maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion=false) const
Returns the maximum safe velocity for following the given leader.
@ LANE_CHANGE
the return value is used for lane change calculations
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1, bool relaxEmergency=true) const
Returns the maximum next velocity for stopping within gap.
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const =0
Computes the vehicle's follow speed (no dawdling)
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
bool hasLaneChanger() const
bool isRoundabout() const
bool isInternal() const
return whether this edge is an internal edge
static bool gSemiImplicitEulerUpdate
static bool isBidiFollower(const MSVehicle *ego, const MSVehicle *follower)
static bool canSaveBlockerLength(const MSVehicle &veh, double requested, double leftSpace)
static double getSpeedPreservingSecureGap(const MSVehicle &leader, const MSVehicle &follower, double currentGap, double leaderPlannedSpeed)
static double getRoundaboutDistBonus(const MSVehicle &veh, double bonusParam, const MSVehicle::LaneQ &curr, const MSVehicle::LaneQ &neigh, const MSVehicle::LaneQ &best)
static bool isBidiLeader(const MSVehicle *leader, const std::vector< MSLane * > &cont)
static bool updateBlockerLength(const MSVehicle &veh, MSVehicle *blocker, int lcaCounter, double leftSpace, bool reliefConnection, double &leadingBlockerLength)
static bool divergentRoute(const MSVehicle &v1, const MSVehicle &v2)
return whether the vehicles are on the same junction but on divergent paths
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
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) override
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
void informFollower(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighFollow, double remainingSeconds, double plannedSpeed)
decide whether we will try cut in before the follower or allow to be overtaken
long long int myKeepRightProbability
double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const override
decides the next lateral speed (for continuous lane changing)
double myOvertakeDeltaSpeedFactor
bool debugVehicle() const override
whether the current vehicles shall be debugged
long long int mySpeedGainProbabilityRight
double mySpeedGainLookahead
const double myExperimentalParam1
double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel) override
Called to adapt the speed in order to allow a lane change. It uses information on LC-related desired ...
void initDerivedParameters()
init cached parameters derived directly from model parameters
double myCooperativeParam
MSLCM_LC2013(MSVehicle &v)
double anticipateFollowSpeed(const std::pair< MSVehicle *, double > &leaderDist, double dist, double vMax, bool acceleratingLeader)
anticipate future follow speed for the given leader
std::string getParameter(const std::string &key) const override
try to retrieve the given parameter from this device. Throw exception for unsupported key
void setParameter(const std::string &key, const std::string &value) override
try to set the given parameter for this laneChangeModel. Throw exception for unsupported key
bool hasFreeLane(int laneOffset, const std::pair< MSVehicle *, double > &neighLeadStopped) const
whether there is a lane beyond laneOffset that can be used to overtake the stopped leader on the neig...
double myCooperativeSpeed
double informLeader(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighLead, double remainingSeconds)
double _patchSpeed(double min, const double wanted, double max, const MSCFModel &cfModel)
double myLeadingBlockerLength
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)
helper function for doing the actual work
std::pair< double, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
void prepareStep() override
double getSafetyFactor() const override
return factor for modifying the safety constraints of the car-following model
bool amBlockingFollowerPlusNB()
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
void adaptSpeedToPedestrians(const MSLane *lane, double &v)
react to pedestrians on the given lane
virtual void saveState(OutputDevice &out) const override
Save the state of the laneChangeModel.
long long int myChangeProbThresholdRight
double getOppositeSafetyFactor() const override
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
long long int mySpeedGainProbabilityLeft
a value for tracking the probability that a change to that side is beneficial
void resetState() override
double myKeepRightAcceptanceTime
double mySpeedGainUrgency
int slowDownForBlocked(MSVehicle *blocked, int state)
compute useful slowdowns for blocked vehicles
bool saveBlockerLength(double length, double foeLeftSpace) override
reserve space at the end of the lane to avoid dead locks
double mySpeedGainRemainTime
void * inform(void *info, MSVehicle *sender) override
long long int myChangeProbThresholdLeft
virtual void loadState(const SUMOSAXAttributes &attrs) override
Loads the state of the laneChangeModel from the given attributes.
static double overtakeDistance(const MSVehicle *follower, const MSVehicle *leader, const double gap, double followerSpeed=INVALID_SPEED, double leaderSpeed=INVALID_SPEED)
Representation of a lane in the micro simulation.
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.
bool isAccelLane() const
return whether this lane is an acceleration lane
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
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.
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.
bool hasPedestrians() const
whether the lane has pedestrians on it
int getIndex() const
Returns the lane's index.
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
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 * getBidiLane() const
retrieve bidirectional lane or nullptr
MSEdge & getEdge() const
Returns the lane's edge.
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
const MSLane * lane
The lane to stop at (microsim only)
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Representation of a vehicle in the micro simulation.
MSAbstractLaneChangeModel & getLaneChangeModel()
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation,...
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
int getBestLaneOffset() const
const MSEdge * getCurrentEdge() const
Returns the edge the vehicle is currently at (possibly an internal edge or nullptr)
const MSLane * getLane() const
Returns the lane the vehicle is on.
double getLastStepDist() const
Get the distance the vehicle covered in the previous timestep.
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
double getSpeed() const
Returns the vehicle's current speed.
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 getPositionOnLane() const
Get the vehicle's position along the lane.
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
void setLateralPositionOnLane(double posLat)
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
void step(double dt)
evolve for a time step of length dt.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
#define UNUSED_PARAMETER(x)
A structure representing the best lanes for continuing the current route starting at 'lane'.
double length
The overall length which may be driven when using this lane without a lane change.
std::vector< MSLane * > bestContinuations
MSLane * lane
The described lane.
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.