40#define MAGIC_OFFSET 1.
41#define LOOK_FORWARD 10.
45#define LCA_RIGHT_IMPATIENCE -1.
46#define CUT_IN_LEFT_SPEED_THRESHOLD 27.
47#define MAX_ONRAMP_LENGTH 200.
49#define LOOK_AHEAD_MIN_SPEED 0.0
50#define LOOK_AHEAD_SPEED_MEMORY 0.9
52#define HELP_DECEL_FACTOR 1.0
54#define HELP_OVERTAKE (10.0 / 3.6)
55#define MIN_FALLBEHIND (7.0 / 3.6)
59#define KEEP_RIGHT_TIME 5.0
61#define RELGAIN_NORMALIZATION_MIN_SPEED 10.0
63#define TURN_LANE_DIST 200.0
64#define GAIN_PERCEPTION_THRESHOLD 0.05
66#define ARRIVALPOS_LAT_THRESHOLD 100.0
69#define LATGAP_SPEED_THRESHOLD (50 / 3.6)
72#define LATGAP_SPEED_THRESHOLD2 (50 / 3.6)
75#define SPEEDGAIN_DECAY_FACTOR 0.5
77#define SPEEDGAIN_MEMORY_FACTOR 0.5
79#define REACT_TO_STOPPED_DISTANCE 100
104#define DEBUG_COND (myVehicle.isSelected())
116 mySpeedGainProbabilityRight(0),
117 mySpeedGainProbabilityLeft(0),
118 myKeepRightProbability(0),
119 myLeadingBlockerLength(0),
123 myCanChangeFully(true),
124 mySafeLatDistRight(0),
125 mySafeLatDistLeft(0),
133 myMinGapLat(v.getVehicleType().getMinGapLat()),
136 MAX2(NUMERICAL_EPS, myMinGapLat)) /
137 MAX2(NUMERICAL_EPS, myMinGapLat)))),
139 myMinImpatience(myImpatience),
191 const std::vector<MSVehicle::LaneQ>& preb,
194 double& latDist,
double& maneuverDist,
int& blocked) {
197 const std::string changeType = laneOffset == -1 ?
"right" : (laneOffset == 1 ?
"left" :
"current");
205 <<
" neigh=" << neighLane.
getID()
210 <<
" considerChangeTo=" << changeType
217 leaders, followers, blockers,
218 neighLeaders, neighFollowers, neighBlockers,
220 lastBlocked, firstBlocked, latDist, maneuverDist, blocked);
222 result =
keepLatGap(result, leaders, followers, blockers,
223 neighLeaders, neighFollowers, neighBlockers,
224 neighLane, laneOffset, latDist, maneuverDist, blocked);
226 result |=
getLCA(result, latDist);
228#if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE)
229 double latDistTmp = latDist;
232#if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE)
234 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" maneuverDist=" << maneuverDist <<
" latDist=" << latDistTmp <<
" mySpeedPrev=" <<
mySpeedLat <<
" speedLat=" <<
DIST2SPEED(latDist) <<
" latDist2=" << latDist <<
"\n";
241 <<
" wantsChangeTo=" << changeType
242 <<
" latDist=" << latDist
243 <<
" maneuverDist=" << maneuverDist
251 <<
" wantsNoChangeTo=" << changeType
308 const double newSpeed =
_patchSpeed(
MAX2(min, 0.0), wanted, max, cfModel);
309#ifdef DEBUG_PATCHSPEED
311 const std::string patched = (wanted != newSpeed ?
" patched=" +
toString(newSpeed) :
"");
318 <<
" wanted=" << wanted
337 double nVSafe = wanted;
343#ifdef DEBUG_PATCHSPEED
351 max =
MIN2(max, safe);
356 if (safe >= vMinEmergency) {
358 min =
MAX2(vMinEmergency, safe);
361#ifdef DEBUG_PATCHSPEED
363 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ?
" (not enough)" :
"") <<
"\n";
366 nVSafe =
MAX2(min, safe);
373 double accel = i.first;
375 if (v >= min && v <= max) {
378 nVSafe =
MIN2(v, nVSafe);
380 nVSafe =
MIN2(v * coopWeight + (1 - coopWeight) * wanted, nVSafe);
383#ifdef DEBUG_PATCHSPEED
385 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" got accel=" << accel <<
" nVSafe=" << nVSafe <<
"\n";
389#ifdef DEBUG_PATCHSPEED
392 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring low nVSafe=" << v <<
" (accel=" << accel <<
") min=" << min <<
"\n";
396 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring high nVSafe=" << v <<
" (accel=" << accel <<
") max=" << max <<
"\n";
404#ifdef DEBUG_PATCHSPEED
417#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
422 return (max + wanted) / 2.0;
426#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
431 return (min + wanted) / 2.0;
434#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
439 return (max + wanted) / 2.0;
480#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
485 return (max + wanted) / 2.0;
489#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
509 if (pinfo->first >= 0) {
518 <<
" informedBy=" << sender->
getID()
519 <<
" info=" << pinfo->second
520 <<
" vSafe=" << pinfo->first
533 assert(cld.first != 0);
542 double remainingSeconds) {
548 plannedSpeed =
MIN2(plannedSpeed, v);
553 std::cout <<
" informLeader speed=" <<
myVehicle.
getSpeed() <<
" planned=" << plannedSpeed <<
"\n";
564 if (
gDebugFlag2) std::cout <<
" blocked by leader nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap="
568 const double dv = plannedSpeed - nv->
getSpeed();
569 const double overtakeDist = (neighLead.second
581 || dv * remainingSeconds < overtakeDist)
582 && (!neighLead.first->isStopped() || (
isOpposite() && neighLead.second >= 0))) {
597 <<
" cannot overtake leader nv=" << nv->
getID()
599 <<
" remainingSeconds=" << remainingSeconds
600 <<
" targetSpeed=" << targetSpeed
601 <<
" nextSpeed=" << nextSpeed
612 <<
" cannot overtake fast leader nv=" << nv->
getID()
614 <<
" remainingSeconds=" << remainingSeconds
615 <<
" targetSpeed=" << targetSpeed
626 <<
" wants to overtake leader nv=" << nv->
getID()
628 <<
" remainingSeconds=" << remainingSeconds
629 <<
" currentGap=" << neighLead.second
631 <<
" overtakeDist=" << overtakeDist
641 }
else if (neighLead.first != 0) {
644 double dv, nextNVSpeed;
664 std::cout <<
" not blocked by leader nv=" << nv->
getID()
666 <<
" gap=" << neighLead.second
667 <<
" nextGap=" << neighLead.second - dv
669 <<
" targetSpeed=" << targetSpeed
673 return MIN2(targetSpeed, plannedSpeed);
685 double remainingSeconds,
686 double plannedSpeed) {
694 if (
gDebugFlag2) std::cout <<
" blocked by follower nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap="
701 if ((neededGap - neighFollow.second) / remainingSeconds < (plannedSpeed - nv->
getSpeed())) {
704 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" without any help neededGap=" << neededGap <<
"\n";
723 const double neighNewSpeed1s =
MAX2(0., nv->
getSpeed() - helpDecel);
724 const double dv = plannedSpeed - neighNewSpeed1s;
726 const double decelGap = neighFollow.second + dv;
732 <<
" egoNV=" << plannedSpeed
733 <<
" nvNewSpeed=" << neighNewSpeed
734 <<
" nvNewSpeed1s=" << neighNewSpeed1s
735 <<
" deltaGap=" << dv
736 <<
" decelGap=" << decelGap
737 <<
" secGap=" << secureGap
741 if (decelGap > 0 && decelGap >= secureGap) {
756 std::cout <<
" wants to cut in before nv=" << nv->
getID()
757 <<
" vsafe1=" << vsafe1
758 <<
" vsafe=" << vsafe
763 }
else if (dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS)) {
768 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (eventually)\n";
776 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (nv cannot overtake right)\n";
792 std::cout <<
" wants right follower to slow down a bit\n";
798 std::cout <<
" wants to cut in before right follower nv=" << nv->
getID() <<
" (eventually)\n";
807 const double overtakeDist = (neighFollow.second
813 const double needDV = overtakeDist / remainingSeconds;
821 <<
" wants to be overtaken by=" << nv->
getID()
822 <<
" overtakeDist=" << overtakeDist
824 <<
" vhelp=" << vhelp
825 <<
" needDV=" << needDV
831 }
else if (neighFollow.first != 0) {
836 std::cout <<
" wants to cut in before non-blocking follower nv=" << neighFollow.first->getID() <<
"\n";
844 const std::vector<CLeaderDist>& blockers,
845 double remainingSeconds) {
857 plannedSpeed =
MIN2(plannedSpeed, safe);
859 for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
860 plannedSpeed =
MIN2(plannedSpeed,
informLeader(blocked, dir, *it, remainingSeconds));
868 const std::vector<CLeaderDist>& blockers,
869 double remainingSeconds,
870 double plannedSpeed) {
872 for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
873 informFollower(blocked, dir, *it, remainingSeconds, plannedSpeed);
898 const double halfWidth =
getWidth() * 0.5;
911 std::vector<double> newExpectedSpeeds;
920 const std::vector<MSLane*>& lanes = currEdge->
getLanes();
921 for (std::vector<MSLane*>::const_iterator it_lane = lanes.begin(); it_lane != lanes.end(); ++it_lane) {
923 for (
int i = 0; i < subLanes; ++i) {
924 newExpectedSpeeds.push_back((*it_lane)->getVehicleMaxSpeed(&
myVehicle));
930 for (
int i = 0; i < subLanes; ++i) {
931 newExpectedSpeeds.push_back(lanes.back()->getVehicleMaxSpeed(&
myVehicle));
939 if (subLaneShift < std::numeric_limits<int>::max()) {
941 const int newI = i + subLaneShift;
942 if (newI > 0 && newI < (
int)newExpectedSpeeds.size()) {
978 for (
const MSLink*
const link : lane->getLinkCont()) {
979 if (&link->getLane()->getEdge() == curEdge) {
981 const MSLane* target = link->getLane();
982 const std::vector<MSLane*>& lanes2 = curEdge->
getLanes();
983 for (std::vector<MSLane*>::const_iterator it_lane2 = lanes2.begin(); it_lane2 != lanes2.end(); ++it_lane2) {
984 const MSLane* lane2 = *it_lane2;
985 if (lane2 == target) {
986 return prevShift + curShift;
997 return std::numeric_limits<int>::max();
1031#if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE)
1064 const std::vector<MSVehicle::LaneQ>& preb,
1067 double& latDist,
double& maneuverDist,
int& blocked) {
1069 if (laneOffset != 0) {
1071 const double halfWidth =
getWidth() * 0.5;
1073 if (laneOffset < 0) {
1083 int bestLaneOffset = 0;
1084 double currentDist = 0;
1085 double neighDist = 0;
1097 const int prebOffset = (checkOpposite ? 0 : laneOffset);
1098 for (
int p = 0; p < (int) preb.size(); ++p) {
1099 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1100 assert(p + prebOffset < (
int)preb.size());
1102 neigh = preb[p + prebOffset];
1103 currentDist = curr.
length;
1104 neighDist = neigh.
length;
1107 if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1108#ifdef DEBUG_WANTSCHANGE
1112 <<
" bestLaneOffsetOld=" << bestLaneOffset
1113 <<
" bestLaneOffsetNew=" << laneOffset
1117 bestLaneOffset = prebOffset;
1119 best = preb[p + bestLaneOffset];
1123 assert(curr.
lane !=
nullptr);
1124 assert(neigh.
lane !=
nullptr);
1125 assert(best.
lane !=
nullptr);
1126 double driveToNextStop = -std::numeric_limits<double>::max();
1135#ifdef DEBUG_WANTS_CHANGE
1140 <<
" stopPos=" << stopPos
1141 <<
" currentDist=" << currentDist
1142 <<
" neighDist=" << neighDist
1146 currentDist =
MAX2(currentDist, stopPos);
1147 neighDist =
MAX2(neighDist, stopPos);
1150 const bool right = (laneOffset == -1);
1151 const bool left = (laneOffset == 1);
1154 const bool changeToBest = (right && bestLaneOffset < 0) || (left && bestLaneOffset > 0) || (laneOffset == 0 && bestLaneOffset == 0);
1180#ifdef DEBUG_WANTSCHANGE
1187 <<
"\n leaders=" << leaders.
toString()
1188 <<
"\n followers=" << followers.
toString()
1189 <<
"\n blockers=" << blockers.
toString()
1190 <<
"\n neighLeaders=" << neighLeaders.
toString()
1191 <<
"\n neighFollowers=" << neighFollowers.
toString()
1192 <<
"\n neighBlockers=" << neighBlockers.
toString()
1193 <<
"\n changeToBest=" << changeToBest
1194 <<
" latLaneDist=" << latLaneDist
1203 if (lastBlocked != firstBlocked) {
1254 for (
int i = 0; i < neighLeaders.
numSublanes(); ++i) {
1256 if (vehDist.first !=
nullptr && vehDist.first->isStopped()) {
1274 currentDist += roundaboutBonus;
1275 neighDist += roundaboutBonus;
1277 if (laneOffset != 0) {
1295 if ((ret &
LCA_STAY) != 0 && latDist == 0) {
1308 if (changeToBest && abs(bestLaneOffset) > 1
1314#ifdef DEBUG_WANTSCHANGE
1316 std::cout <<
" reserving space for unseen blockers myLeadingBlockerLength=" <<
myLeadingBlockerLength <<
"\n";
1325#ifdef DEBUG_WANTSCHANGE
1331 if (*firstBlocked != neighLeadLongest &&
tieBrakeLeader(*firstBlocked)) {
1340 std::vector<CLeaderDist> collectLeadBlockers;
1341 std::vector<CLeaderDist> collectFollowBlockers;
1342 int blockedFully = 0;
1343 maneuverDist = latDist;
1345 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1346 leaders, followers, blockers,
1347 neighLeaders, neighFollowers, neighBlockers, &collectLeadBlockers, &collectFollowBlockers,
1348 false, gapFactor, &blockedFully);
1350 const double absLaneOffset = fabs(bestLaneOffset != 0 ? bestLaneOffset : latDist /
SUMO_const_laneWidth);
1351 const double remainingSeconds = ((ret &
LCA_TRACI) == 0 ?
1354 const double plannedSpeed =
informLeaders(blocked, myLca, collectLeadBlockers, remainingSeconds);
1356 if (plannedSpeed >= 0) {
1358 informFollowers(blocked, myLca, collectFollowBlockers, remainingSeconds, plannedSpeed);
1360 if (plannedSpeed > 0) {
1361 commitManoeuvre(blocked, blockedFully, leaders, neighLeaders, neighLane, maneuverDist);
1363#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE)
1370 <<
" remainingSeconds=" << remainingSeconds
1371 <<
" plannedSpeed=" << plannedSpeed
1382 if (roundaboutBonus > 0) {
1384#ifdef DEBUG_WANTS_CHANGE
1388 <<
" roundaboutBonus=" << roundaboutBonus
1399 latDist = latLaneDist;
1400 maneuverDist = latLaneDist;
1401 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1402 leaders, followers, blockers,
1403 neighLeaders, neighFollowers, neighBlockers);
1407 ret &= ~LCA_COOPERATIVE;
1423 const double inconvenience = (latLaneDist < 0
1426#ifdef DEBUG_COOPERATE
1434 <<
" inconvenience=" << inconvenience
1436 <<
" wantsChangeToHelp=" << (right ?
"right" :
"left")
1453 && (changeToBest ||
currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1456#ifdef DEBUG_COOPERATE
1458 std::cout <<
" wants cooperative change\n";
1465 maneuverDist = latDist;
1466 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1467 leaders, followers, blockers,
1468 neighLeaders, neighFollowers, neighBlockers);
1494 const double vehWidth =
getWidth();
1496 const double leftVehSide = rightVehSide + vehWidth;
1498 double defaultNextSpeed = std::numeric_limits<double>::max();
1500 int leftmostOnEdge = (int)sublaneSides.size() - 1;
1501 while (leftmostOnEdge > 0 && sublaneSides[leftmostOnEdge] > leftVehSide) {
1504 int rightmostOnEdge = leftmostOnEdge;
1505 while (rightmostOnEdge > 0 && sublaneSides[rightmostOnEdge] > rightVehSide + NUMERICAL_EPS) {
1507#ifdef DEBUG_WANTSCHANGE
1509 std::cout <<
" adapted to current sublane=" << rightmostOnEdge <<
" defaultNextSpeed=" << defaultNextSpeed <<
"\n";
1510 std::cout <<
" sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] <<
" rightVehSide=" << rightVehSide <<
"\n";
1516#ifdef DEBUG_WANTSCHANGE
1518 std::cout <<
" adapted to current sublane=" << rightmostOnEdge <<
" defaultNextSpeed=" << defaultNextSpeed <<
"\n";
1519 std::cout <<
" sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] <<
" rightVehSide=" << rightVehSide <<
"\n";
1522 double maxGain = -std::numeric_limits<double>::max();
1523 double maxGainRight = -std::numeric_limits<double>::max();
1524 double maxGainLeft = -std::numeric_limits<double>::max();
1525 double latDistNice = std::numeric_limits<double>::max();
1528 double leftMax =
MAX2(
1535 assert(leftMax <= edge.
getWidth());
1537 int sublaneCompact =
MAX2(iMin, rightmostOnEdge - 1);
1543 const double maxLatDist = leftMax - leftVehSide;
1544 const double minLatDist = rightMin - rightVehSide;
1545 const int iStart = laneOffset == 0 ? iMin : 0;
1546 const double rightEnd = laneOffset == 0 ? leftMax : (checkOpposite ?
getLeftBorder() : edge.
getWidth());
1547#ifdef DEBUG_WANTSCHANGE
1549 <<
" checking sublanes rightmostOnEdge=" << rightmostOnEdge
1550 <<
" rightEnd=" << rightEnd
1551 <<
" leftmostOnEdge=" << leftmostOnEdge
1552 <<
" iStart=" << iStart
1554 <<
" sublaneSides=" << sublaneSides.size()
1555 <<
" leftMax=" << leftMax
1556 <<
" minLatDist=" << minLatDist
1557 <<
" maxLatDist=" << maxLatDist
1558 <<
" sublaneCompact=" << sublaneCompact
1561 for (
int i = iStart; i < (int)sublaneSides.size(); ++i) {
1562 if (sublaneSides[i] + vehWidth < rightEnd) {
1568 while (vMin > 0 && j < (
int)sublaneSides.size() && sublaneSides[j] < sublaneSides[i] + vehWidth) {
1570#ifdef DEBUG_WANTSCHANGE
1578 if (laneOffset != 0 &&
overlap(sublaneSides[i], sublaneSides[i] + vehWidth, laneBoundary, laneBoundary)) {
1582 const double currentLatDist =
MIN2(
MAX2(sublaneSides[i] - rightVehSide, minLatDist), maxLatDist);
1586 relativeGain *= 0.5;
1589 if (relativeGain > maxGain) {
1590 maxGain = relativeGain;
1593 latDist = currentLatDist;
1594#ifdef DEBUG_WANTSCHANGE
1596 std::cout <<
" i=" << i <<
" vMin=" << vMin <<
" newLatDist=" << latDist <<
" relGain=" << relativeGain <<
"\n";
1602 if (currentLatDist > 0
1606 && maxGain - relativeGain < NUMERICAL_EPS) {
1607 latDist = currentLatDist;
1610#ifdef DEBUG_WANTSCHANGE
1612 std::cout <<
" i=" << i <<
" rightmostOnEdge=" << rightmostOnEdge <<
" vMin=" << vMin <<
" relGain=" << relativeGain <<
" sublaneCompact=" << sublaneCompact <<
" curLatDist=" << currentLatDist <<
"\n";
1616 maxGainRight =
MAX2(maxGainRight, relativeGain);
1618 maxGainLeft =
MAX2(maxGainLeft, relativeGain);
1620 const double subAlignDist = sublaneSides[i] - rightVehSide;
1621 if (fabs(subAlignDist) < fabs(latDistNice)) {
1622 latDistNice = subAlignDist;
1623#ifdef DEBUG_WANTSCHANGE
1625 <<
" nicest sublane=" << i
1626 <<
" side=" << sublaneSides[i]
1627 <<
" rightSide=" << rightVehSide
1628 <<
" latDistNice=" << latDistNice
1629 <<
" maxGainR=" << maxGainRight
1630 <<
" maxGainL=" << maxGainLeft
1637 if (maxGainRight != -std::numeric_limits<double>::max()) {
1638#ifdef DEBUG_WANTSCHANGE
1644#ifdef DEBUG_WANTSCHANGE
1650 if (maxGainLeft != -std::numeric_limits<double>::max()) {
1651#ifdef DEBUG_WANTSCHANGE
1657#ifdef DEBUG_WANTSCHANGE
1664 if ((fabs(maxGainRight) < NUMERICAL_EPS || maxGainRight == -std::numeric_limits<double>::max())
1665 && (right || (alternatives &
LCA_RIGHT) == 0)) {
1668 if ((fabs(maxGainLeft) < NUMERICAL_EPS || maxGainLeft == -std::numeric_limits<double>::max())
1669 && (left || (alternatives &
LCA_LEFT) == 0)) {
1674#ifdef DEBUG_WANTSCHANGE
1677 <<
" defaultNextSpeed=" << defaultNextSpeed
1678 <<
" maxGain=" << maxGain
1679 <<
" maxGainRight=" << maxGainRight
1680 <<
" maxGainLeft=" << maxGainLeft
1683 <<
" latDist=" << latDist
1684 <<
" latDistNice=" << latDistNice
1685 <<
" sublaneCompact=" << sublaneCompact
1698 double acceptanceTime;
1707 double minFactor = 1.0;
1708 for (
int i = 0; i < followers.
numSublanes(); ++i) {
1710 if (follower.first !=
nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1713 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1714 if (fRSF > roadSpeedFactor) {
1717 if (factor < minFactor) {
1723 acceptanceTime *= minFactor;
1727 double fullSpeedDrivingSeconds =
MIN2(acceptanceTime, fullSpeedGap / vMax);
1729 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1730 fullSpeedGap =
MAX2(0.,
MIN2(fullSpeedGap,
1732 vMax, neighLead.first->
getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1733 fullSpeedDrivingSeconds =
MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1742#ifdef DEBUG_WANTSCHANGE
1745 <<
" considering keepRight:"
1747 <<
" neighDist=" << neighDist
1749 <<
" leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1751 myVehicle.
getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1752 <<
" acceptanceTime=" << acceptanceTime
1753 <<
" fullSpeedGap=" << fullSpeedGap
1754 <<
" fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1755 <<
" dProb=" << deltaProb
1756 <<
" isSlide=" << isSlide
1767 latDist = latLaneDist;
1768 maneuverDist = latLaneDist;
1769 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1770 leaders, followers, blockers,
1771 neighLeaders, neighFollowers, neighBlockers);
1774 ret &= ~LCA_KEEPRIGHT;
1780#ifdef DEBUG_WANTSCHANGE
1785 <<
" neighDist=" << neighDist
1789 <<
" latDist=" << latDist
1799 int blockedFully = 0;
1800 maneuverDist = latDist;
1801 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1802 leaders, followers, blockers,
1803 neighLeaders, neighFollowers, neighBlockers,
1804 nullptr,
nullptr,
false, 0, &blockedFully);
1810 ret &= ~LCA_SPEEDGAIN;
1817#ifdef DEBUG_WANTSCHANGE
1822 <<
" latDist=" << latDist
1823 <<
" neighDist=" << neighDist
1826 <<
" stayInLane=" << stayInLane
1837 int blockedFully = 0;
1838 maneuverDist = latDist;
1839 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1840 leaders, followers, blockers,
1841 neighLeaders, neighFollowers, neighBlockers,
1842 nullptr,
nullptr,
false, 0, &blockedFully);
1847 ret &= ~LCA_SPEEDGAIN;
1852 double latDistSublane = 0.;
1854 const double halfVehWidth =
getWidth() * 0.5;
1857 && bestLaneOffset == 0
1877#ifdef DEBUG_WANTSCHANGE
1888 latDistSublane = -halfLaneWidth + halfVehWidth -
getPosLat();
1891 latDistSublane = halfLaneWidth - halfVehWidth -
getPosLat();
1898 latDistSublane = latDistNice;
1901 latDistSublane = sublaneSides[sublaneCompact] - rightVehSide;
1919 latDistSublane * latDist > 0) {
1921#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE) || defined(DEBUG_MANEUVER)
1926 <<
" latDist=" << latDist
1927 <<
" latDistSublane=" << latDistSublane
1928 <<
" relGainSublane=" <<
computeSpeedGain(latDistSublane, defaultNextSpeed)
1929 <<
" maneuverDist=" << maneuverDist
1941#if defined(DEBUG_WANTSCHANGE)
1943 <<
" speedGain=" <<
computeSpeedGain(latDistSublane, defaultNextSpeed) <<
")\n";
1951#if defined(DEBUG_WANTSCHANGE)
1953 std::cout <<
" aborting sublane change due to prior maneuver\n";
1958 latDist = latDistSublane * (
isOpposite() ? -1 : 1);
1963#ifdef DEBUG_WANTSCHANGE
1966 <<
" latDist=" << latDist
1974#ifdef DEBUG_WANTSCHANGE
1980 maneuverDist = latDist;
1981 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1982 leaders, followers, blockers,
1983 neighLeaders, neighFollowers, neighBlockers);
1986 ret &= ~LCA_SUBLANE;
2012#ifdef DEBUG_WANTSCHANGE
2029 if ((*blocked) !=
nullptr) {
2031#ifdef DEBUG_SLOWDOWN
2040 if (gap > POSITION_EPS) {
2054 (gap - POSITION_EPS), (*blocked)->getSpeed(),
2055 (*blocked)->getCarFollowModel().getMaxDecel()),
false);
2073 if (cand !=
nullptr && cand->getBidiLane() == lane) {
2087 assert(preb.size() == lanes.size() ||
isOpposite());
2088#ifdef DEBUG_EXPECTED_SLSPEED
2091 <<
" sublaneOffset=" << sublaneOffset <<
" laneIndex=" << laneIndex <<
" lane=" << lane->
getID() <<
" ahead=" << ahead.
toString() <<
"\n";
2095 for (
int sublane = 0; sublane < (int)ahead.
numSublanes(); ++sublane) {
2096 const int edgeSublane = sublane + sublaneOffset;
2104 const MSVehicle* leader = ahead[sublane].first;
2105 const double gap = ahead[sublane].second;
2107 if (leader ==
nullptr) {
2112 const int prebIndex =
isOpposite() ? (int)preb.size() - 1 : laneIndex;
2123#ifdef DEBUG_EXPECTED_SLSPEED
2125 std::cout <<
SIMTIME <<
" updateExpectedSublaneSpeeds sublane=" << sublane <<
" leader=" << leader->
getID() <<
" bidi=" << bidi->
getID() <<
" gap=" << gap <<
" vSafe=" << vSafe <<
"\n";
2135#ifdef DEBUG_EXPECTED_SLSPEED
2137 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" leader=" << leader->
getID() <<
" gap=" << gap <<
" vSafe=" << vSafe <<
"\n";
2146 double foeRight, foeLeft;
2150 if (pedLeader.first != 0) {
2155#ifdef DEBUG_EXPECTED_SLSPEED
2157 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" pedLeader=" << pedLeader.first->getID() <<
" gap=" << pedGap <<
" vSafe=" << vSafe <<
"\n";
2165 double foeRight, foeLeft;
2167 const double foeRightBidi = bidi->
getWidth() - foeLeft;
2168 const double foeLeftBidi = bidi->
getWidth() - foeRight;
2173 if (pedLeader.first != 0) {
2178#ifdef DEBUG_EXPECTED_SLSPEED
2180 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" pedLeader=" << pedLeader.first->getID() <<
" (bidi) gap=" << pedGap <<
" vSafe=" << vSafe <<
"\n";
2185 vSafe =
MIN2(vMax, vSafe);
2200 const double deltaV = vMax - vLeader;
2201 if (deltaV > 0 && gap / deltaV < mySpeedGainLookahead && mySpeedGainLookahead > 0) {
2205 const double gapClosingTime =
MAX2(0.0, gap / deltaV);
2206 const double vSafe2 = (gapClosingTime * vSafe + (foreCastTime - gapClosingTime) * vLeader) / foreCastTime;
2207#ifdef DEBUG_EXPECTED_SLSPEED
2209 std::cout <<
" foreCastTime=" << foreCastTime <<
" gapClosingTime=" << gapClosingTime <<
" extrapolated vSafe=" << vSafe2 <<
"\n";
2220 double result = std::numeric_limits<double>::max();
2222 const double vehWidth =
getWidth();
2224 const double leftVehSide = rightVehSide + vehWidth;
2225 for (
int i = 0; i < (int)sublaneSides.size(); ++i) {
2227 if (
overlap(rightVehSide, leftVehSide, sublaneSides[i], leftSide)) {
2232 return result - defaultNextSpeed;
2239 double maxLength = -1;
2250 return iMax >= 0 ? ldi[iMax] : std::make_pair(
nullptr, -1);
2267 double minSpeed = std::numeric_limits<double>::max();
2269 if (ldi[i].first != 0) {
2270 const double speed = ldi[i].first->getSpeed();
2271 if (speed < minSpeed) {
2289 std::vector<CLeaderDist>* collectLeadBlockers,
2290 std::vector<CLeaderDist>* collectFollowBlockers,
2291 bool keepLatGapManeuver,
2293 int* retBlockedFully) {
2296 latDist =
MAX2(
MIN2(latDist, maxDist), -maxDist);
2305 if (laneOffset != 0) {
2316 if (laneOffset != 0) {
2320#ifdef DEBUG_BLOCKING
2332 }
else if (!forcedTraCIChange) {
2338 }
else if (!forcedTraCIChange) {
2344#ifdef DEBUG_BLOCKING
2346 std::cout <<
" checkBlocking fully=" <<
myCanChangeFully <<
" latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
"\n";
2360 if (laneOffset != 0) {
2367 int blockedFully = 0;
2372 if (laneOffset != 0) {
2378 if (retBlockedFully !=
nullptr) {
2379 *retBlockedFully = blockedFully;
2386 blocked |= blockedFully;
2391 if (collectFollowBlockers !=
nullptr && collectLeadBlockers !=
nullptr) {
2393 for (std::vector<CLeaderDist>::const_iterator it2 = collectLeadBlockers->begin(); it2 != collectLeadBlockers->end(); ++it2) {
2394 for (std::vector<CLeaderDist>::iterator it = collectFollowBlockers->begin(); it != collectFollowBlockers->end();) {
2395 if ((*it2).first == (*it).first) {
2396#ifdef DEBUG_BLOCKING
2398 std::cout <<
" removed follower " << (*it).first->getID() <<
" because it is already a leader\n";
2401 it = collectFollowBlockers->erase(it);
2415 int laneOffset,
double latDist,
double foeOffset,
bool leaders,
2416 double& safeLatGapRight,
double& safeLatGapLeft,
2417 std::vector<CLeaderDist>* collectBlockers)
const {
2424 const double vehWidth =
getWidth();
2426 const double leftVehSide = rightVehSide + vehWidth;
2427 const double rightVehSideDest = rightVehSide + latDist;
2428 const double leftVehSideDest = leftVehSide + latDist;
2429 const double rightNoOverlap =
MIN2(rightVehSideDest, rightVehSide);
2430 const double leftNoOverlap =
MAX2(leftVehSideDest, leftVehSide);
2431#ifdef DEBUG_BLOCKING
2433 std::cout <<
" checkBlockingVehicles"
2434 <<
" laneOffset=" << laneOffset
2435 <<
" latDist=" << latDist
2436 <<
" foeOffset=" << foeOffset
2437 <<
" vehRight=" << rightVehSide
2438 <<
" vehLeft=" << leftVehSide
2439 <<
" rightNoOverlap=" << rightNoOverlap
2440 <<
" leftNoOverlap=" << leftNoOverlap
2441 <<
" destRight=" << rightVehSideDest
2442 <<
" destLeft=" << leftVehSideDest
2443 <<
" leaders=" << leaders
2449 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2451 if (vehDist.first != 0 &&
myCFRelated.count(vehDist.first) == 0) {
2452 const MSVehicle* leader = vehDist.first;
2458 double foeRight, foeLeft;
2460 const bool overlapBefore =
overlap(rightVehSide, leftVehSide, foeRight, foeLeft);
2461 const bool overlapDest =
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft);
2462 const bool overlapAny =
overlap(rightNoOverlap, leftNoOverlap, foeRight, foeLeft);
2463#ifdef DEBUG_BLOCKING
2465 std::cout <<
" foe=" << vehDist.first->getID()
2466 <<
" gap=" << vehDist.second
2468 <<
" foeRight=" << foeRight
2469 <<
" foeLeft=" << foeLeft
2470 <<
" overlapBefore=" << overlapBefore
2471 <<
" overlap=" << overlapAny
2472 <<
" overlapDest=" << overlapDest
2477 if (vehDist.second < 0) {
2478 if (overlapBefore && !overlapDest && !
outsideEdge()) {
2479#ifdef DEBUG_BLOCKING
2481 std::cout <<
" ignoring current overlap to come clear\n";
2485#ifdef DEBUG_BLOCKING
2491 if (collectBlockers ==
nullptr) {
2494 collectBlockers->push_back(vehDist);
2510 const double expectedGap =
MSCFModel::gapExtrapolation(timeTillAction, vehDist.second, leader->
getSpeed(), follower->
getSpeed(), leaderAccel, followerAccel, std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
2513 const double followerExpectedSpeed = follower->
getSpeed() + timeTillAction * followerAccel;
2514 const double leaderExpectedSpeed =
MAX2(0., leader->
getSpeed() + timeTillAction * leaderAccel);
2517#if defined(DEBUG_ACTIONSTEPS) && defined(DEBUG_BLOCKING)
2519 std::cout <<
" timeTillAction=" << timeTillAction
2520 <<
" followerAccel=" << followerAccel
2521 <<
" followerExpectedSpeed=" << followerExpectedSpeed
2522 <<
" leaderAccel=" << leaderAccel
2523 <<
" leaderExpectedSpeed=" << leaderExpectedSpeed
2524 <<
"\n gap=" << vehDist.second
2525 <<
" gapChange=" << (expectedGap - vehDist.second)
2526 <<
" expectedGap=" << expectedGap
2527 <<
" expectedSecureGap=" << expectedSecureGap
2528 <<
" safeLatGapLeft=" << safeLatGapLeft
2529 <<
" safeLatGapRight=" << safeLatGapRight
2536 if (expectedGap < secureGap2) {
2538 if (foeRight > leftVehSide) {
2539 safeLatGapLeft =
MIN2(safeLatGapLeft, foeRight - leftVehSide);
2540 }
else if (foeLeft < rightVehSide) {
2541 safeLatGapRight =
MIN2(safeLatGapRight, rightVehSide - foeLeft);
2544#ifdef DEBUG_BLOCKING
2546 std::cout <<
" blocked by " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2547 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor()
2548 <<
" safeLatGapLeft=" << safeLatGapLeft <<
" safeLatGapRight=" << safeLatGapRight
2552 result |= blockType;
2553 if (collectBlockers ==
nullptr) {
2556#ifdef DEBUG_BLOCKING
2557 }
else if (
gDebugFlag2 && expectedGap < expectedSecureGap) {
2558 std::cout <<
" ignore blocker " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2559 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor() <<
"\n";
2562 if (collectBlockers !=
nullptr) {
2565 collectBlockers->push_back(vehDist);
2582 const double leftVehSide = rightVehSide + vehWidth;
2583#ifdef DEBUG_BLOCKING
2585 std::cout <<
" updateCFRelated foeOffset=" << foeOffset <<
" vehicles=" << vehicles.
toString() <<
"\n";
2588 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2590 if (vehDist.first != 0 && (
myCFRelated.count(vehDist.first) == 0 || vehDist.second < 0)) {
2591 double foeRight, foeLeft;
2593#ifdef DEBUG_BLOCKING
2595 std::cout <<
" foe=" << vehDist.first->getID() <<
" gap=" << vehDist.second
2597 <<
" foeOffset=" << foeOffset
2598 <<
" egoR=" << rightVehSide <<
" egoL=" << leftVehSide
2599 <<
" iR=" << foeRight <<
" iL=" << foeLeft
2605 if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft) && !
outsideEdge() && (vehDist.second >= 0
2611 && -vehDist.second < vehDist.first->getVehicleType().getMinGap()
2614#ifdef DEBUG_BLOCKING
2616 std::cout <<
" ignoring cfrelated foe=" << vehDist.first->getID() <<
"\n";
2621 const int erased = (int)
myCFRelated.erase(vehDist.first);
2622#ifdef DEBUG_BLOCKING
2624 std::cout <<
" restoring cfrelated foe=" << vehDist.first->getID() <<
"\n";
2637 assert(right <= left);
2638 assert(right2 <= left2);
2639 return left2 >= right + NUMERICAL_EPS && left >= right2 + NUMERICAL_EPS;
2660 return changeReason;
2667 if (sd1.
state == 0) {
2669 }
else if (sd2.
state == 0) {
2679#ifdef DEBUG_WANTSCHANGE
2685 <<
" dir1=" << sd1.
dir
2689 <<
" dir2=" << sd2.
dir
2705 if (reason1 < reason2) {
2707 return (!can1 && can2 && sd1.
sameDirection(sd2)) ? sd2 : sd1;
2709 }
else if (reason1 > reason2) {
2711 return (!can2 && can1 && sd1.
sameDirection(sd2)) ? sd1 : sd2;
2719 }
else if (sd2.
dir == 0) {
2724 assert(sd1.
dir == -1);
2725 assert(sd2.
dir == 1);
2728 }
else if (sd2.
latDist >= 0) {
2774 double& currentDist,
2777 double roundaboutBonus,
2782 const bool right = (laneOffset == -1);
2783 const bool left = (laneOffset == 1);
2790 const double neighLeftPlace =
MAX2(0., neighDist - forwardPos - maxJam);
2793#ifdef DEBUG_STRATEGIC_CHANGE
2797 <<
" forwardPos=" << forwardPos
2799 <<
" laDist=" << laDist
2800 <<
" currentDist=" << currentDist
2801 <<
" usableDist=" << usableDist
2802 <<
" bestLaneOffset=" << bestLaneOffset
2803 <<
" best.length=" << best.
length
2804 <<
" maxJam=" << maxJam
2805 <<
" neighLeftPlace=" << neighLeftPlace
2811 if (laneOffset != 0 && changeToBest && bestLaneOffset == curr.
bestLaneOffset
2814 if (!
mustOvertakeStopped(
false, neighLane, neighLeaders, leaders, forwardPos, neighDist, right, latLaneDist, currentDist, latDist)) {
2815 latDist = latLaneDist;
2817#ifdef DEBUG_STRATEGIC_CHANGE
2819 std::cout <<
SIMTIME <<
" mustChangeToBest\n";
2823#ifdef DEBUG_STRATEGIC_CHANGE
2825 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" avoidStoppedNeigh\n";
2844#ifdef DEBUG_STRATEGIC_CHANGE
2847 <<
" avoid overtaking on the right nv=" << nv->
getID()
2859 if (laneOffset != 0 &&
myStrategicParam >= 0 && noOpposites &&
mustOvertakeStopped(
true, neighLane, leaders, neighLeaders, forwardPos, neighDist, right, latLaneDist, currentDist, latDist)) {
2860#ifdef DEBUG_STRATEGIC_CHANGE
2862 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" mustOvertakeStopped\n";
2871 }
else if (!changeToBest && (
currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
2878#ifdef DEBUG_STRATEGIC_CHANGE
2880 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace <<
"\n";
2886 && bestLaneOffset == 0
2889 && roundaboutBonus == 0
2896#ifdef DEBUG_STRATEGIC_CHANGE
2898 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to leave the bestLane (neighDist=" << neighDist <<
")\n";
2903 && bestLaneOffset == 0
2909#ifdef DEBUG_STRATEGIC_CHANGE
2911 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to get stranded on the on-ramp of a highway\n";
2925 MSLane* shadowPrev =
nullptr;
2927 if (*it ==
nullptr) {
2931 if (shadow ==
nullptr || currentShadowDist >= requiredDist) {
2934 if (shadowPrev !=
nullptr) {
2937 currentShadowDist += shadow->
getLength();
2938 shadowPrev = shadow;
2939#ifdef DEBUG_STRATEGIC_CHANGE
2941 std::cout <<
" shadow=" << shadow->
getID() <<
" currentShadowDist=" << currentShadowDist <<
"\n";
2945#ifdef DEBUG_STRATEGIC_CHANGE
2950 if (currentShadowDist < requiredDist && currentShadowDist < usableDist) {
2953#ifdef DEBUG_STRATEGIC_CHANGE
2955 std::cout <<
" must change for shadowLane end latDist=" << latDist <<
" myLeftSpace=" <<
myLeftSpace <<
"\n";
2963#if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI)
2975 }
else if (((retTraCI &
LCA_RIGHT) != 0 && laneOffset < 0)
2976 || ((retTraCI &
LCA_LEFT) != 0 && laneOffset > 0)) {
2978 latDist = latLaneDist;
2981#if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI)
2992 double posOnLane,
double neighDist,
bool right,
double latLaneDist,
double& currentDist,
double& latDist) {
2993 bool mustOvertake =
false;
2998 const int dir = latLaneDist < 0 ? -1 : 1;
3002 if (curHasStopped) {
3004 for (
int i = rightmost; i <= leftmost; i++) {
3008 const double remaining =
MIN2(neighDist, currentDist) - posOnLane;
3009#ifdef DEBUG_STRATEGIC_CHANGE
3011 std::cout <<
" overtakeDist=" << overtakeDist <<
" remaining=" << remaining
3013 <<
" hasLaneBeyond=" << hasLaneBeyond
3018 remaining > overtakeDist
3020 && (!checkCurrent || !checkOverTakeRight || !right)
3029 latDist = latLaneDist;
3030 mustOvertake =
true;
3031#ifdef DEBUG_STRATEGIC_CHANGE
3033 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" overtake stopped leader=" << leader.first->getID()
3034 <<
" newCurrentDist=" << currentDist
3035 <<
" overtakeDist=" << overtakeDist
3036 <<
" remaining=" << remaining
3052 mustOvertake =
true;
3053 if (i >= rightmost && i <= leftmost) {
3060 return mustOvertake;
3081 double& maneuverDist,
3117 const double oldLatDist = latDist;
3118 const double oldManeuverDist = maneuverDist;
3123 const double halfWidth =
getWidth() * 0.5;
3129 double surplusGapRight = oldCenter - halfWidth;
3130 double surplusGapLeft =
getLeftBorder(laneOffset != 0) - oldCenter - halfWidth;
3131 const bool stayInLane = (laneOffset == 0
3135 && (surplusGapLeft >= 0 && surplusGapRight >= 0)));
3138 std::swap(surplusGapLeft, surplusGapRight);
3140#ifdef DEBUG_KEEP_LATGAP
3142 std::cout <<
"\n " <<
SIMTIME <<
" keepLatGap() laneOffset=" << laneOffset
3143 <<
" latDist=" << latDist
3144 <<
" maneuverDist=" << maneuverDist
3148 <<
" gapFactor=" << gapFactor
3149 <<
" stayInLane=" << stayInLane <<
"\n"
3150 <<
" stayInEdge: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
3154 if (surplusGapLeft < 0 || surplusGapRight < 0) {
3164 if (laneOffset != 0) {
3167 updateGaps(neighLeaders, neighRight, oldCenter, gapFactor, surplusGapRight, surplusGapLeft,
true);
3168 updateGaps(neighFollowers, neighRight, oldCenter, gapFactor, surplusGapRight, surplusGapLeft,
true, netOverlap);
3170#ifdef DEBUG_KEEP_LATGAP
3172 std::cout <<
" minGapLat: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n"
3182 if (stayInLane || laneOffset == 1) {
3185 surplusGapRight =
MIN2(surplusGapRight,
MAX2(0.0, halfLaneWidth + posLat - halfWidth));
3186 physicalGapRight =
MIN2(physicalGapRight,
MAX2(0.0, halfLaneWidth + posLat - halfWidth));
3188 if (stayInLane || laneOffset == -1) {
3191 surplusGapLeft =
MIN2(surplusGapLeft,
MAX2(0.0, halfLaneWidth - posLat - halfWidth));
3192 physicalGapLeft =
MIN2(physicalGapLeft,
MAX2(0.0, halfLaneWidth - posLat - halfWidth));
3194#ifdef DEBUG_KEEP_LATGAP
3196 std::cout <<
" stayInLane: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
3200 if (surplusGapRight + surplusGapLeft < 0) {
3205 const double equalDeficit = 0.5 * (surplusGapLeft + surplusGapRight);
3206 if (surplusGapRight < surplusGapLeft) {
3208 const double delta =
MIN2(equalDeficit - surplusGapRight, physicalGapLeft);
3210 maneuverDist = delta;
3211#ifdef DEBUG_KEEP_LATGAP
3213 std::cout <<
" insufficient latSpace, move left: delta=" << delta <<
"\n";
3218 const double delta =
MIN2(equalDeficit - surplusGapLeft, physicalGapRight);
3220 maneuverDist = -delta;
3221#ifdef DEBUG_KEEP_LATGAP
3223 std::cout <<
" insufficient latSpace, move right: delta=" << delta <<
"\n";
3229 latDist =
MAX2(
MIN2(latDist, surplusGapLeft), -surplusGapRight);
3230 maneuverDist =
MAX2(
MIN2(maneuverDist, surplusGapLeft), -surplusGapRight);
3231 if ((state &
LCA_KEEPRIGHT) != 0 && maneuverDist != oldManeuverDist) {
3233 latDist = oldLatDist;
3234 maneuverDist = oldManeuverDist;
3236#ifdef DEBUG_KEEP_LATGAP
3238 std::cout <<
" adapted latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
" (old=" << oldLatDist <<
")\n";
3253#ifdef DEBUG_KEEP_LATGAP
3255 std::cout <<
" traci influenced latDist=" << latDist <<
"\n";
3261 const bool traciChange = ((state | traciState) &
LCA_TRACI) != 0;
3262 if (nonSublaneChange && !traciChange) {
3264#ifdef DEBUG_KEEP_LATGAP
3266 std::cout <<
" wanted changeToLeft oldLatDist=" << oldLatDist <<
", blocked latGap changeToRight\n";
3269 latDist = oldLatDist;
3272#ifdef DEBUG_KEEP_LATGAP
3274 std::cout <<
" wanted changeToRight oldLatDist=" << oldLatDist <<
", blocked latGap changeToLeft\n";
3277 latDist = oldLatDist;
3287#ifdef DEBUG_KEEP_LATGAP
3289 std::cout <<
" latDistUpdated=" << latDist <<
" oldLatDist=" << oldLatDist <<
"\n";
3292 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset, leaders, followers, blockers, neighLeaders, neighFollowers, neighBlockers,
nullptr,
nullptr, nonSublaneChange);
3295 state = (state & ~LCA_STAY);
3306#if defined(DEBUG_KEEP_LATGAP) || defined(DEBUG_STATE)
3308 std::cout <<
" latDist2=" << latDist
3322 double& surplusGapRight,
double& surplusGapLeft,
3323 bool saveMinGap,
double netOverlap,
3325 std::vector<CLeaderDist>* collectBlockers) {
3327 const double halfWidth =
getWidth() * 0.5 + NUMERICAL_EPS;
3330 if (others[i].first != 0 && others[i].second <= 0
3332 && (netOverlap == 0 || others[i].second + others[i].first->getVehicleType().getMinGap() < netOverlap)) {
3336 double foeRight, foeLeft;
3338 const double foeCenter = foeRight + 0.5 * res;
3339 const double gap =
MIN2(fabs(foeRight - oldCenter), fabs(foeLeft - oldCenter)) - halfWidth;
3342 const double currentMinGap = desiredMinGap * gapFactor;
3353#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3355 std::cout <<
" updateGaps"
3357 <<
" foe=" << foe->
getID()
3358 <<
" foeRight=" << foeRight
3359 <<
" foeLeft=" << foeLeft
3360 <<
" oldCenter=" << oldCenter
3361 <<
" gap=" << others[i].second
3362 <<
" latgap=" << gap
3363 <<
" currentMinGap=" << currentMinGap
3364 <<
" surplusGapRight=" << surplusGapRight
3365 <<
" surplusGapLeft=" << surplusGapLeft
3373 if (foeCenter < oldCenter) {
3375 surplusGapRight =
MIN3(surplusGapRight, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
3378 surplusGapLeft =
MIN3(surplusGapLeft, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
3381 if (foeCenter < oldCenter) {
3382#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3384 std::cout <<
" new minimum rightGap=" << gap <<
"\n";
3389#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3391 std::cout <<
" new minimum leftGap=" << gap <<
"\n";
3397 if (collectBlockers !=
nullptr) {
3399 if ((foeCenter < oldCenter && latDist < 0 && gap < (desiredMinGap - latDist))
3400 || (foeCenter > oldCenter && latDist > 0 && gap < (desiredMinGap + latDist))) {
3401 collectBlockers->push_back(others[i]);
3418 int currentDirection =
mySpeedLat >= 0 ? 1 : -1;
3419 int directionWish = latDist >= 0 ? 1 : -1;
3426 maxSpeedLat =
MIN2(maxSpeedLat, speedBound);
3430 maxSpeedLat =
MAX2(maxSpeedLat, speedBound);
3436#ifdef DEBUG_MANEUVER
3440 <<
" computeSpeedLat()"
3441 <<
" latDist=" << latDist
3442 <<
" maneuverDist=" << maneuverDist
3443 <<
" urgent=" << urgent
3445 <<
" currentDirection=" << currentDirection
3446 <<
" directionWish=" << directionWish
3448 <<
" maxSpeedLat=" << maxSpeedLat
3454 if (directionWish == 1) {
3468 if (maneuverDist * latDist > 0) {
3469 maneuverDist = fullLatDist;
3472#ifdef DEBUG_MANEUVER
3476 <<
" fullLatDist=" << fullLatDist
3477 <<
" speedAccel=" << speedAccel
3478 <<
" speedDecel=" << speedDecel
3479 <<
" speedBound=" << speedBound
3483 if (speedDecel * speedAccel <= 0 && (
3485 (latDist >= 0 && speedAccel >= speedBound && speedBound >= speedDecel)
3486 || (latDist <= 0 && speedAccel <= speedBound && speedBound <= speedDecel))) {
3488#ifdef DEBUG_MANEUVER
3490 std::cout <<
" computeSpeedLat a)\n";
3497#ifdef DEBUG_MANEUVER
3499 std::cout <<
" computeSpeedLat b)\n";
3506 if ((fabs(minDistAccel) < fabs(fullLatDist)) || (fabs(minDistAccel - fullLatDist) < NUMERICAL_EPS)) {
3507#ifdef DEBUG_MANEUVER
3509 std::cout <<
" computeSpeedLat c)\n";
3514#ifdef DEBUG_MANEUVER
3516 std::cout <<
" minDistAccel=" << minDistAccel <<
"\n";
3521 if ((fabs(minDistCurrent) < fabs(fullLatDist)) || (fabs(minDistCurrent - fullLatDist) < NUMERICAL_EPS)) {
3522#ifdef DEBUG_MANEUVER
3524 std::cout <<
" computeSpeedLat d)\n";
3531#ifdef DEBUG_MANEUVER
3533 std::cout <<
" computeSpeedLat e)\n";
3545#ifdef DEBUG_MANEUVER
3547 std::cout <<
" rightDanger speedLat=" << speedLat <<
"\n";
3552#ifdef DEBUG_MANEUVER
3554 std::cout <<
" leftDanger speedLat=" << speedLat <<
"\n";
3569 const bool indirect = turnInfo.second ==
nullptr ? false : turnInfo.second->isIndirect();
3602 double maneuverDist) {
3605 double secondsToLeaveLane;
3615#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3631 double nextLeftSpace;
3632 if (nextActionStepSpeed > 0.) {
3647#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3651 <<
" avoidArrivalSpeed=" << avoidArrivalSpeed
3654 <<
"\n nextLeftSpace=" << nextLeftSpace
3655 <<
" nextActionStepSpeed=" << nextActionStepSpeed
3656 <<
" nextActionStepRemainingSeconds=" << secondsToLeaveLane - timeTillActionStep
3666#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3670 <<
" secondsToLeave=" << secondsToLeaveLane
3692 const double vehWidth =
getWidth();
3694 const double leftVehSide = rightVehSide + vehWidth;
3695 const double rightVehSideDest = rightVehSide + latDist;
3696 const double leftVehSideDest = leftVehSide + latDist;
3697#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3699 std::cout <<
" commitFollowSpeed"
3700 <<
" latDist=" << latDist
3701 <<
" foeOffset=" << foeOffset
3702 <<
" vehRight=" << rightVehSide
3703 <<
" vehLeft=" << leftVehSide
3704 <<
" destRight=" << rightVehSideDest
3705 <<
" destLeft=" << leftVehSideDest
3711 if (vehDist.first != 0) {
3712 const MSVehicle* leader = vehDist.first;
3714 double foeRight, foeLeft;
3716#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3718 std::cout <<
" foe=" << vehDist.first->getID()
3719 <<
" gap=" << vehDist.second
3721 <<
" foeRight=" << foeRight
3722 <<
" foeLeft=" << foeLeft
3723 <<
" overlapBefore=" <<
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)
3724 <<
" overlapDest=" <<
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)
3728 if (
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)) {
3732 speed =
MIN2(speed, vSafe);
3733#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3735 std::cout <<
" case1 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3738 }
else if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)) {
3743 speed =
MIN2(speed, vSafe);
3744#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3746 std::cout <<
" case2 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3766 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 /
myOppositeParam;
3825 }
else if (key ==
"speedGainProbabilityRight") {
3827 }
else if (key ==
"speedGainProbabilityLeft") {
3829 }
else if (key ==
"keepRightProbability") {
3831 }
else if (key ==
"lookAheadSpeed") {
3833 }
else if (key ==
"sigmaState") {
3836 }
else if (key ==
"speedGainRP") {
3838 }
else if (key ==
"speedGainLP") {
3840 }
else if (key ==
"keepRightP") {
3910 }
else if (key ==
"speedGainProbabilityRight") {
3912 }
else if (key ==
"speedGainProbabilityLeft") {
3914 }
else if (key ==
"keepRightProbability") {
3916 }
else if (key ==
"lookAheadSpeed") {
3918 }
else if (key ==
"sigmaState") {
3932 const std::pair<MSVehicle*, double>& leader,
3933 const std::pair<MSVehicle*, double>& follower,
3934 const std::pair<MSVehicle*, double>& neighLead,
3935 const std::pair<MSVehicle*, double>& neighFollow,
3937 const std::vector<MSVehicle::LaneQ>& preb,
3943#ifdef DEBUG_WANTSCHANGE
3945 std::cout <<
"\nWANTS_CHANGE\n" <<
SIMTIME
3949 <<
" neigh=" << neighLane.
getID()
3953 <<
" considerChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
3967 double maneuverDist;
3970 leaders, followers, blockers,
3971 neighLeaders, neighFollowers, neighBlockers,
3973 lastBlocked, firstBlocked, latDist, maneuverDist, blocked);
3977 result &= ~LCA_SUBLANE;
3978 result |=
getLCA(result, latDist);
3980#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE)
3985 <<
" wantsChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
3986 << ((result &
LCA_URGENT) ?
" (urgent)" :
"")
3992 << ((result &
LCA_TRACI) ?
" (traci)" :
"")
4044 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" bgap=" << brakeGap <<
" maneuverDist=" << maneuverDist
#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 ARRIVALPOS_LAT_THRESHOLD
#define SPEEDGAIN_MEMORY_FACTOR
#define LOOK_AHEAD_MIN_SPEED
#define SPEEDGAIN_DECAY_FACTOR
#define LATGAP_SPEED_THRESHOLD
#define GAIN_PERCEPTION_THRESHOLD
#define LATGAP_SPEED_THRESHOLD2
std::pair< const MSVehicle *, double > CLeaderDist
std::pair< const MSPerson *, double > PersonDist
LatAlignmentDefinition
Possible ways to choose the lateral alignment, i.e., how vehicles align themselves within their lane.
@ RIGHT
drive on the right side
@ GIVEN
The alignment as offset is given.
@ DEFAULT
No information given; use default.
@ LEFT
drive on the left side
@ ARBITRARY
maintain the current alignment
@ NICE
align with the closest sublane border
@ COMPACT
align with the rightmost sublane that allows keeping the current speed
@ CENTER
drive in the middle
@ SVC_EMERGENCY
public emergency vehicles
@ RIGHT
At the rightmost side of the lane.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ LEFT
At the leftmost side of the lane.
@ CENTER
At the center of the lane.
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ TURN
The link is a 180 degree turn.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ TURN_LEFTHAND
The link is a 180 degree turn (left-hand network)
@ PARTRIGHT
The link is a partial right direction.
@ NODIR
The link has no direction (is a dead end link)
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_BLOCKED_LEFT
blocked left
@ 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_BLOCKED_BY_RIGHT_LEADER
The vehicle is blocked by right leader.
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_SUBLANE
used by the sublane model
@ 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_OVERLAPPING
The vehicle is blocked being overlapping.
@ LCA_LEFT
Wants go to the left.
@ LCA_BLOCKED_RIGHT
blocked right
@ LCA_BLOCKED_BY_RIGHT_FOLLOWER
The vehicle is blocked by right follower.
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_AMBACKBLOCKER_STANDING
@ LCA_CHANGE_REASONS
reasons of lane change
@ 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
@ LCA_BLOCKED_BY_LEFT_LEADER
@ SUMO_ATTR_LCA_COOPERATIVE_SPEED
@ SUMO_ATTR_LCA_ASSERTIVE
@ SUMO_ATTR_LCA_LANE_DISCIPLINE
@ SUMO_ATTR_LCA_TURN_ALIGNMENT_DISTANCE
@ SUMO_ATTR_LCA_LOOKAHEADLEFT
@ SUMO_ATTR_LCA_SPEEDGAIN_PARAM
@ SUMO_ATTR_LCA_MAXDISTLATSTANDING
@ SUMO_ATTR_LCA_IMPATIENCE
@ 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_COOPERATIVE_PARAM
@ SUMO_ATTR_LCA_OPPOSITE_PARAM
@ SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME
@ SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR
@ SUMO_ATTR_LCA_SUBLANE_PARAM
@ SUMO_ATTR_LCA_ACCEL_LAT
@ SUMO_ATTR_LCA_STRATEGIC_PARAM
@ SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME
@ SUMO_ATTR_LCA_TIME_TO_IMPATIENCE
@ SUMO_ATTR_LCA_SPEEDGAINRIGHT
int gPrecision
the precision for floating point outputs
const double SUMO_const_laneWidth
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.
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
bool hasBlueLight() const
double getPreviousManeuverDist() const
virtual void setOwnState(const int state)
int myPreviousState
lane changing state from the previous simulation step
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model)
int myOwnState
The current state of the vehicle.
virtual void prepareStep()
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
double myLastLateralGapRight
double myCommittedSpeed
the speed when committing to a change maneuver
virtual LatAlignmentDefinition getDesiredAlignment() const
static const double NO_NEIGHBOR
double myMaxDistLatStanding
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
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
double getMaxSpeedLat2() const
return the max of maxSpeedLat and lcMaxSpeedLatStanding
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
double mySpeedLat
the current lateral speed
double myMaxSpeedLatStanding
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
double myLastLateralGapLeft
the minimum lateral gaps to other vehicles that were found when last changing to the left and right
virtual bool avoidOvertakeRight() const
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getLength() const
Returns the vehicle's length.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
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 MSRoute & getRoute() const
Returns the current route.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
The car-following model abstraction.
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
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 followSpeedTransient(double duration, const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel) const
Computes the vehicle's follow speed that avoids a collision for the given amount of time.
double getEmergencyDecel() const
Get the vehicle type's maximal physically possible deceleration [m/s^2].
static double brakeGapEuler(const double speed, const double decel, const double headwayTime)
static double avoidArrivalAccel(double dist, double time, double speed, double maxDecel)
Computes the acceleration needed to arrive not before the given time.
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...
virtual void setMaxDecel(double decel)
Sets a new value for maximal comfortable deceleration [m/s^2].
@ 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 getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
static double estimateArrivalTime(double dist, double speed, double maxSpeed, double accel)
Computes the time needed to travel a distance dist given an initial speed and constant acceleration....
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)
A road/street connecting two junctions.
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
double getInternalFollowingLengthTo(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
returns the length of all internal edges on the junction until reaching the non-internal edge followe...
bool canChangeToOpposite() const
whether this edge allows changing to the opposite direction edge
bool isInternal() const
return whether this edge is an internal edge
double getWidth() const
Returns the edges's width (sum over all lanes)
const std::vector< double > getSubLaneSides() const
Returns the right side offsets of this edge's sublanes.
static double gLateralResolution
static bool gSemiImplicitEulerUpdate
static bool gLefthand
Whether lefthand-drive is being simulated.
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 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
double mySafeLatDistRight
the lateral distance the vehicle can safely move in the currently considered direction
static bool overlap(double right, double left, double right2, double left2)
return whether the given intervals overlap
double _patchSpeed(double min, const double wanted, double max, const MSCFModel &cfModel)
double informLeaders(int blocked, int dir, const std::vector< CLeaderDist > &blockers, double remainingSeconds)
void commitManoeuvre(int blocked, int blockedFully, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &neighLeaders, const MSLane &neighLane, double maneuverDist)
commit to lane change maneuver potentially overriding safe speed
std::set< const MSVehicle * > myCFRelated
set of vehicles that are in a car-following relationship with ego (leader of followers)
void prepareStep() override
double myKeepRightProbability
double commitFollowSpeed(double speed, double latDist, double secondsToLeaveLane, const MSLeaderDistanceInfo &leaders, double foeOffset) const
compute speed when committing to an urgent change that is safe in regard to leading vehicles
double getLeftBorder(bool checkOpposite=true) const
return current edge width optionally extended by opposite direction lane width
double myChangeProbThresholdRight
double informLeader(int blocked, int dir, const CLeaderDist &neighLead, double remainingSeconds)
MSLCM_SL2015(MSVehicle &v)
int computeSublaneShift(const MSEdge *prevEdge, const MSEdge *curEdge)
compute shift so that prevSublane + shift = newSublane
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 ...
double getSafetyFactor() const override
return factor for modifying the safety constraints of the car-following model
double myCooperativeSpeed
double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const override
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
std::vector< double > myExpectedSublaneSpeeds
expected travel speeds on all sublanes on the current edge(!)
double getWidth() const
return the width of this vehicle (padded for numerical stability)
bool myCanChangeFully
whether the current lane changing maneuver can be finished in a single step
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 is a wrapper a...
bool mustOvertakeStopped(bool checkCurrent, const MSLane &neighLane, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &neighLead, double posOnLane, double neighDist, bool right, double latLaneDist, double ¤tDist, double &latDist)
bool outsideEdge() const
whether the ego vehicle is driving outside edgebounds
bool myDontBrake
flag to prevent speed adaptation by slowing down
std::string getParameter(const std::string &key) const override
try to retrieve the given parameter from this device. Throw exception for unsupported key
bool wantsKeepRight(double keepRightProb) const
check against thresholds
double forecastAverageSpeed(double vSafe, double vMax, double gap, double vLeader) const
estimate average speed over mySpeedGainLookahead time
int checkStrategicChange(int ret, const MSLane &neighLane, int laneOffset, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &neighLeaders, const MSVehicle::LaneQ &curr, const MSVehicle::LaneQ &neigh, const MSVehicle::LaneQ &best, int bestLaneOffset, bool changeToBest, double ¤tDist, double neighDist, double laDist, double roundaboutBonus, double latLaneDist, bool checkOpposite, double &latDist)
compute strategic lane change actions TODO: Better documentation, refs #2
void updateCFRelated(const MSLeaderDistanceInfo &vehicles, double foeOffset, bool leaders)
find leaders/followers that are already in a car-following relationship with ego
bool debugVehicle() const override
whether the current vehicles shall be debugged
int wantsChangeSublane(int laneOffset, LaneChangeAction alternatives, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked, double &latDist, double &maneuverDist, int &blocked) override
Called to examine whether the vehicle wants to change with the given laneOffset (using the sublane mo...
LatAlignmentDefinition getDesiredAlignment() const override
double mySpeedGainProbabilityRight
a value for tracking the probability that a change to the right is beneficial
int slowDownForBlocked(MSVehicle **blocked, int state)
compute useful slowdowns for blocked vehicles
void initDerivedParameters()
init cached parameters derived directly from model parameters
int keepLatGap(int state, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, int laneOffset, double &latDist, double &maneuverDist, int &blocked)
check whether lateral gap requirements are met override the current maneuver if necessary
bool tieBrakeLeader(const MSVehicle *veh) const
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
CLeaderDist getLongest(const MSLeaderDistanceInfo &ldi) const
get the longest vehicle in the given info
double myCooperativeParam
double getNeighRight(const MSLane &neighLane) const
return the right offset of the neighboring lane relative to the current edge
double computeSpeedGain(double latDistSublane, double defaultNextSpeed) const
compute speedGain when moving by the given amount
double emergencySpeedLat(double speedLat) const
avoid unsafe lateral speed (overruling lcAccelLat)
double myKeepRightAcceptanceTime
void updateGaps(const MSLeaderDistanceInfo &others, double foeOffset, double oldCenter, double gapFactor, double &surplusGapRight, double &surplusGapLeft, bool saveMinGap=false, double netOverlap=0, double latDist=0, std::vector< CLeaderDist > *collectBlockers=0)
check remaining lateral gaps for the given foe vehicles and optionally update minimum lateral gaps
virtual void updateSafeLatDist(const double travelledLatDist) override
Updates the value of safe lateral distances (mySafeLatDistLeft and mySafeLatDistRight) during maneuve...
const MSEdge * myLastEdge
expected travel speeds on all sublanes on the current edge(!)
double getOppositeSafetyFactor() const override
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
StateAndDist decideDirection(StateAndDist sd1, StateAndDist sd2) const override
decide in which direction to move in case both directions are desirable
std::pair< double, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
void msg(const CLeaderDist &cld, double speed, int state)
send a speed recommendation to the given vehicle
double mySpeedGainRemainTime
int checkBlocking(const MSLane &neighLane, double &latDist, double maneuverDist, int laneOffset, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, std::vector< CLeaderDist > *collectLeadBlockers=0, std::vector< CLeaderDist > *collectFollowBlockers=0, bool keepLatGapManeuver=false, double gapFactor=0, int *retBlockedFully=0)
restrict latDist to permissible speed and determine blocking state depending on that distance
double getVehicleCenter() const
return vehicle position relative to the current edge (extend by another virtual lane for opposite-dir...
int _wantsChangeSublane(int laneOffset, LaneChangeAction alternatives, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked, double &latDist, double &maneuverDist, int &blocked)
helper function for doing the actual work
double getLateralDrift()
get lateral drift for the current step
double computeGapFactor(int state) const
compute the gap factor for the given state
double getPosLat()
get lateral position of this vehicle
bool preventSliding(double maneuverDist) const
bool isBidi(const MSLane *lane) const
check whether lane is an upcoming bidi lane
void * inform(void *info, MSVehicle *sender) override
void informFollower(int blocked, int dir, const CLeaderDist &neighFollow, double remainingSeconds, double plannedSpeed)
decide whether we will try cut in before the follower or allow to be overtaken
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 saveBlockerLength(double length, double foeLeftSpace) override
reserve space at the end of the lane to avoid dead locks
double myOvertakeDeltaSpeedFactor
double myTurnAlignmentDist
double myLeadingBlockerLength
void setOwnState(const int state) override
int checkBlockingVehicles(const MSVehicle *ego, const MSLeaderDistanceInfo &vehicles, int laneOffset, double latDist, double foeOffset, bool leaders, double &safeLatGapRight, double &safeLatGapLeft, std::vector< CLeaderDist > *collectBlockers=0) const
check whether any of the vehicles overlaps with ego
void informFollowers(int blocked, int dir, const std::vector< CLeaderDist > &blockers, double remainingSeconds, double plannedSpeed)
call informFollower for multiple followers
double mySpeedGainLookahead
double mySpeedLossProbThreshold
void resetState() override
double mySpeedGainProbabilityLeft
a value for tracking the probability that a change to the left is beneficial
static LaneChangeAction getLCA(int state, double latDist)
compute lane change action from desired lateral distance
double myChangeProbThresholdLeft
void updateExpectedSublaneSpeeds(const MSLeaderDistanceInfo &ahead, int sublaneOffset, int laneIndex) override
update expected speeds for each sublane of the current edge
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
double myTimeToImpatience
static int lowest_bit(int changeReason)
return the most important change reason
static CLeaderDist getSlowest(const MSLeaderDistanceInfo &ldi)
get the slowest vehicle in the given info
bool amBlockingFollowerPlusNB()
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.
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
double getLength() const
Returns the lane's length.
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.
double getRightSideOnEdge() const
bool hasPedestrians() const
whether the lane has pedestrians on it
int getIndex() const
Returns the lane's index.
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge 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
double getWidth() const
Returns the lane's width.
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
int getRightmostSublane() const
saves leader/follower vehicles and their distances relative to an ego vehicle
virtual std::string toString() const
print a debugging representation
double getMinDistToStopped() const
return minimum distance to a stopped vehicle or max double
bool hasStoppedVehicle() const
whether a stopped vehicle is leader
void getSublaneBorders(int sublane, double latOffset, double &rightSide, double &leftSide) const
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
const MSEdge * getLastEdge() const
returns the destination edge
const MSLane * lane
The lane to stop at (microsim only)
double getLatDist() const
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
bool ignoreOverlap() const
Representation of a vehicle in the micro simulation.
double getRightSideOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
double getLeftSideOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
const std::pair< double, const MSLink * > & getNextTurn()
Get the distance and direction of the next upcoming turn for the vehicle (within its look-ahead range...
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 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
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
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 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
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
double getCenterOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
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.
const LatAlignmentDefinition & getPreferredLateralAlignment() const
Get vehicle's preferred lateral alignment procedure.
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].
double getPreferredLateralAlignmentOffset() const
Get vehicle's preferred lateral alignment offset (in m from center line)
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.
double arrivalPosLat
(optional) The lateral position the vehicle shall arrive on
ArrivalPosLatDefinition arrivalPosLatProcedure
Information how the vehicle shall choose the lateral arrival position.
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)
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
bool sameDirection(const StateAndDist &other) const
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.