40#define LOOK_FORWARD 10.
44#define LCA_RIGHT_IMPATIENCE -1.
45#define CUT_IN_LEFT_SPEED_THRESHOLD 27.
46#define MAX_ONRAMP_LENGTH 200.
48#define LOOK_AHEAD_MIN_SPEED 0.0
49#define LOOK_AHEAD_SPEED_MEMORY 0.9
51#define HELP_DECEL_FACTOR 1.0
53#define HELP_OVERTAKE (10.0 / 3.6)
54#define MIN_FALLBEHIND (7.0 / 3.6)
58#define KEEP_RIGHT_TIME 5.0
60#define RELGAIN_NORMALIZATION_MIN_SPEED 10.0
62#define TURN_LANE_DIST 200.0
63#define GAIN_PERCEPTION_THRESHOLD 0.05
65#define ARRIVALPOS_LAT_THRESHOLD 100.0
68#define LATGAP_SPEED_THRESHOLD (50 / 3.6)
71#define LATGAP_SPEED_THRESHOLD2 (50 / 3.6)
74#define SPEEDGAIN_DECAY_FACTOR 0.5
76#define SPEEDGAIN_MEMORY_FACTOR 0.5
78#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();
1032#if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE)
1065 const std::vector<MSVehicle::LaneQ>& preb,
1068 double& latDist,
double& maneuverDist,
int& blocked) {
1070 if (laneOffset != 0) {
1072 const double halfWidth =
getWidth() * 0.5;
1074 if (laneOffset < 0) {
1084 int bestLaneOffset = 0;
1085 double currentDist = 0;
1086 double neighDist = 0;
1098 const int prebOffset = (checkOpposite ? 0 : laneOffset);
1099 for (
int p = 0; p < (int) preb.size(); ++p) {
1100 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1101 assert(p + prebOffset < (
int)preb.size());
1103 neigh = preb[p + prebOffset];
1104 currentDist = curr.
length;
1105 neighDist = neigh.
length;
1108 if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1109#ifdef DEBUG_WANTSCHANGE
1113 <<
" bestLaneOffsetOld=" << bestLaneOffset
1114 <<
" bestLaneOffsetNew=" << laneOffset
1118 bestLaneOffset = prebOffset;
1120 best = preb[p + bestLaneOffset];
1124 assert(curr.
lane !=
nullptr);
1125 assert(neigh.
lane !=
nullptr);
1126 assert(best.
lane !=
nullptr);
1127 double driveToNextStop = -std::numeric_limits<double>::max();
1136#ifdef DEBUG_WANTS_CHANGE
1141 <<
" stopPos=" << stopPos
1142 <<
" currentDist=" << currentDist
1143 <<
" neighDist=" << neighDist
1147 currentDist =
MAX2(currentDist, stopPos);
1148 neighDist =
MAX2(neighDist, stopPos);
1151 const bool right = (laneOffset == -1);
1152 const bool left = (laneOffset == 1);
1155 const bool changeToBest = (right && bestLaneOffset < 0) || (left && bestLaneOffset > 0) || (laneOffset == 0 && bestLaneOffset == 0);
1181#ifdef DEBUG_WANTSCHANGE
1188 <<
"\n leaders=" << leaders.
toString()
1189 <<
"\n followers=" << followers.
toString()
1190 <<
"\n blockers=" << blockers.
toString()
1191 <<
"\n neighLeaders=" << neighLeaders.
toString()
1192 <<
"\n neighFollowers=" << neighFollowers.
toString()
1193 <<
"\n neighBlockers=" << neighBlockers.
toString()
1194 <<
"\n changeToBest=" << changeToBest
1195 <<
" latLaneDist=" << latLaneDist
1204 if (lastBlocked != firstBlocked) {
1255 for (
int i = 0; i < neighLeaders.
numSublanes(); ++i) {
1257 if (vehDist.first !=
nullptr && vehDist.first->isStopped()) {
1275 currentDist += roundaboutBonus;
1276 neighDist += roundaboutBonus;
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 double currentLatDist = sublaneSides[i] - rightVehSide;
1583 if ((laneOffset == 0 && (currentLatDist > maxLatDist || currentLatDist < minLatDist))
1584 || (laneOffset < 0 && currentLatDist > maxLatDist)
1585 || (laneOffset > 0 && currentLatDist < minLatDist)) {
1586#ifdef DEBUG_WANTSCHANGE
1588 std::cout <<
" i=" << i <<
" currentLatDist=" << currentLatDist <<
" outOfBounds\n";
1593 currentLatDist =
MIN2(
MAX2(currentLatDist, minLatDist), maxLatDist);
1597 relativeGain *= 0.5;
1600 if (relativeGain > maxGain && currentLatDist * laneOffset >= 0) {
1601 maxGain = relativeGain;
1604 latDist = currentLatDist;
1605#ifdef DEBUG_WANTSCHANGE
1607 std::cout <<
" i=" << i <<
" vMin=" << vMin <<
" newLatDist=" << latDist <<
" relGain=" << relativeGain <<
"\n";
1613 if (currentLatDist > 0
1617 && maxGain - relativeGain < NUMERICAL_EPS) {
1618 latDist = currentLatDist;
1621#ifdef DEBUG_WANTSCHANGE
1623 std::cout <<
" i=" << i <<
" rightmostOnEdge=" << rightmostOnEdge <<
" vMin=" << vMin <<
" relGain=" << relativeGain <<
" sublaneCompact=" << sublaneCompact <<
" curLatDist=" << currentLatDist <<
"\n";
1627 maxGainRight =
MAX2(maxGainRight, relativeGain);
1629 maxGainLeft =
MAX2(maxGainLeft, relativeGain);
1631 const double subAlignDist = sublaneSides[i] - rightVehSide;
1632 if (fabs(subAlignDist) < fabs(latDistNice)) {
1633 latDistNice = subAlignDist;
1634#ifdef DEBUG_WANTSCHANGE
1636 <<
" nicest sublane=" << i
1637 <<
" side=" << sublaneSides[i]
1638 <<
" rightSide=" << rightVehSide
1639 <<
" latDistNice=" << latDistNice
1640 <<
" maxGainR=" << (maxGainRight == -std::numeric_limits<double>::max() ?
"n/a" :
toString(maxGainRight))
1641 <<
" maxGainL=" << (maxGainLeft == -std::numeric_limits<double>::max() ?
"n/a" :
toString(maxGainLeft))
1648 if (maxGainRight != -std::numeric_limits<double>::max()) {
1649#ifdef DEBUG_WANTSCHANGE
1655#ifdef DEBUG_WANTSCHANGE
1661 if (maxGainLeft != -std::numeric_limits<double>::max()) {
1662#ifdef DEBUG_WANTSCHANGE
1668#ifdef DEBUG_WANTSCHANGE
1675 if ((fabs(maxGainRight) < NUMERICAL_EPS || maxGainRight == -std::numeric_limits<double>::max())
1676 && (right || (alternatives &
LCA_RIGHT) == 0)) {
1679 if ((fabs(maxGainLeft) < NUMERICAL_EPS || maxGainLeft == -std::numeric_limits<double>::max())
1680 && (left || (alternatives &
LCA_LEFT) == 0)) {
1685#ifdef DEBUG_WANTSCHANGE
1688 <<
" defaultNextSpeed=" << defaultNextSpeed
1689 <<
" maxGain=" << maxGain
1690 <<
" maxGainRight=" << maxGainRight
1691 <<
" maxGainLeft=" << maxGainLeft
1694 <<
" latDist=" << latDist
1695 <<
" latDistNice=" << latDistNice
1696 <<
" sublaneCompact=" << sublaneCompact
1709 double acceptanceTime;
1718 double minFactor = 1.0;
1719 for (
int i = 0; i < followers.
numSublanes(); ++i) {
1721 if (follower.first !=
nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1724 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1725 if (fRSF > roadSpeedFactor) {
1728 if (factor < minFactor) {
1734 acceptanceTime *= minFactor;
1738 double fullSpeedDrivingSeconds =
MIN2(acceptanceTime, fullSpeedGap / vMax);
1740 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1741 fullSpeedGap =
MAX2(0.,
MIN2(fullSpeedGap,
1743 vMax, neighLead.first->
getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1744 fullSpeedDrivingSeconds =
MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1753#ifdef DEBUG_WANTSCHANGE
1756 <<
" considering keepRight:"
1758 <<
" neighDist=" << neighDist
1760 <<
" leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1762 myVehicle.
getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1763 <<
" acceptanceTime=" << acceptanceTime
1764 <<
" fullSpeedGap=" << fullSpeedGap
1765 <<
" fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1766 <<
" dProb=" << deltaProb
1767 <<
" isSlide=" << isSlide
1778 latDist = latLaneDist;
1779 maneuverDist = latLaneDist;
1780 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1781 leaders, followers, blockers,
1782 neighLeaders, neighFollowers, neighBlockers);
1785 ret &= ~LCA_KEEPRIGHT;
1791#ifdef DEBUG_WANTSCHANGE
1796 <<
" neighDist=" << neighDist
1800 <<
" latDist=" << latDist
1810 int blockedFully = 0;
1811 maneuverDist = latDist;
1812 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1813 leaders, followers, blockers,
1814 neighLeaders, neighFollowers, neighBlockers,
1815 nullptr,
nullptr,
false, 0, &blockedFully);
1821 ret &= ~LCA_SPEEDGAIN;
1828#ifdef DEBUG_WANTSCHANGE
1833 <<
" latDist=" << latDist
1834 <<
" neighDist=" << neighDist
1837 <<
" stayInLane=" << stayInLane
1848 int blockedFully = 0;
1849 maneuverDist = latDist;
1850 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1851 leaders, followers, blockers,
1852 neighLeaders, neighFollowers, neighBlockers,
1853 nullptr,
nullptr,
false, 0, &blockedFully);
1858 ret &= ~LCA_SPEEDGAIN;
1863 double latDistSublane = 0.;
1865 const double halfVehWidth =
getWidth() * 0.5;
1868 && bestLaneOffset == 0
1888#ifdef DEBUG_WANTSCHANGE
1899 latDistSublane = -halfLaneWidth + halfVehWidth -
getPosLat();
1902 latDistSublane = halfLaneWidth - halfVehWidth -
getPosLat();
1909 latDistSublane = latDistNice;
1912 latDistSublane = sublaneSides[sublaneCompact] - rightVehSide;
1918 if (fabs(posLat) > hLW) {
1921 latDistSublane -= (posLat - hLW);
1923 latDistSublane += (-posLat - hLW);
1928 if (rightVehSide < 0) {
1929 latDistSublane -= rightVehSide;
1930 }
else if (leftVehSide > edgeWidth) {
1931 latDistSublane -= leftVehSide - edgeWidth;
1950 latDistSublane * latDist > 0) {
1952#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE) || defined(DEBUG_MANEUVER)
1957 <<
" latDist=" << latDist
1958 <<
" latDistSublane=" << latDistSublane
1959 <<
" relGainSublane=" <<
computeSpeedGain(latDistSublane, defaultNextSpeed)
1960 <<
" maneuverDist=" << maneuverDist
1972#if defined(DEBUG_WANTSCHANGE)
1974 <<
" speedGain=" <<
computeSpeedGain(latDistSublane, defaultNextSpeed) <<
")\n";
1982#if defined(DEBUG_WANTSCHANGE)
1984 std::cout <<
" aborting sublane change due to prior maneuver\n";
1989 latDist = latDistSublane * (
isOpposite() ? -1 : 1);
1994#ifdef DEBUG_WANTSCHANGE
1997 <<
" latDist=" << latDist
2005#ifdef DEBUG_WANTSCHANGE
2011 maneuverDist = latDist;
2012 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
2013 leaders, followers, blockers,
2014 neighLeaders, neighFollowers, neighBlockers);
2017 ret &= ~LCA_SUBLANE;
2043#ifdef DEBUG_WANTSCHANGE
2060 if ((*blocked) !=
nullptr) {
2062#ifdef DEBUG_SLOWDOWN
2071 if (gap > POSITION_EPS) {
2085 (*blocked)->getSpeed(), (*blocked)->getCarFollowModel().getMaxDecel());
2088 std::cout <<
" slowing down for blocked " <<
Named::getIDSecure(*blocked) <<
" targetSpeed=" << targetSpeed <<
"\n";
2109 if (cand !=
nullptr && cand->getBidiLane() == lane) {
2122 const MSLink* link = next !=
nullptr ? lane->
getLinkTo(next) :
nullptr;
2126 assert(preb.size() == lanes.size() ||
isOpposite());
2127#ifdef DEBUG_EXPECTED_SLSPEED
2130 <<
" sublaneOffset=" << sublaneOffset <<
" laneIndex=" << laneIndex <<
" lane=" << lane->
getID() <<
" ahead=" << ahead.
toString() <<
"\n";
2134 for (
int sublane = 0; sublane < (int)ahead.
numSublanes(); ++sublane) {
2135 const int edgeSublane = sublane + sublaneOffset;
2143#ifdef DEBUG_EXPECTED_SLSPEED
2145 std::cout <<
" updateExpectedSublaneSpeeds sublane=" << sublane <<
" doesNotContinue\n";
2152 const MSVehicle* leader = ahead[sublane].first;
2153 const double gap = ahead[sublane].second;
2155 if (leader ==
nullptr) {
2160 const int prebIndex =
isOpposite() ? (int)preb.size() - 1 : laneIndex;
2171#ifdef DEBUG_EXPECTED_SLSPEED
2173 std::cout <<
SIMTIME <<
" updateExpectedSublaneSpeeds sublane=" << sublane <<
" leader=" << leader->
getID() <<
" bidi=" << bidi->
getID() <<
" gap=" << gap <<
" vSafe=" << vSafe <<
"\n";
2183#ifdef DEBUG_EXPECTED_SLSPEED
2185 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" leader=" << leader->
getID() <<
" gap=" << gap <<
" vSafe=" << vSafe <<
"\n";
2194 double foeRight, foeLeft;
2198 if (pedLeader.first != 0) {
2203#ifdef DEBUG_EXPECTED_SLSPEED
2205 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" pedLeader=" << pedLeader.first->getID() <<
" gap=" << pedGap <<
" vSafe=" << vSafe <<
"\n";
2213 double foeRight, foeLeft;
2215 const double foeRightBidi = bidi->
getWidth() - foeLeft;
2216 const double foeLeftBidi = bidi->
getWidth() - foeRight;
2221 if (pedLeader.first != 0) {
2226#ifdef DEBUG_EXPECTED_SLSPEED
2228 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" pedLeader=" << pedLeader.first->getID() <<
" (bidi) gap=" << pedGap <<
" vSafe=" << vSafe <<
"\n";
2233 vSafe =
MIN2(vMax, vSafe);
2240#ifdef DEBUG_EXPECTED_SLSPEED
2242 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" lane " << lane->
getID() <<
" forbidden\n";
2254 return ((side < -NUMERICAL_EPS
2263 const double deltaV = vMax - vLeader;
2264 if (deltaV > 0 && gap / deltaV < mySpeedGainLookahead && mySpeedGainLookahead > 0) {
2268 const double gapClosingTime =
MAX2(0.0, gap / deltaV);
2269 const double vSafe2 = (gapClosingTime * vSafe + (foreCastTime - gapClosingTime) * vLeader) / foreCastTime;
2270#ifdef DEBUG_EXPECTED_SLSPEED
2272 std::cout <<
" foreCastTime=" << foreCastTime <<
" gapClosingTime=" << gapClosingTime <<
" extrapolated vSafe=" << vSafe2 <<
"\n";
2283 double result = std::numeric_limits<double>::max();
2285 const double vehWidth =
getWidth();
2287 const double leftVehSide = rightVehSide + vehWidth;
2288 for (
int i = 0; i < (int)sublaneSides.size(); ++i) {
2290 if (
overlap(rightVehSide, leftVehSide, sublaneSides[i], leftSide)) {
2295 return result - defaultNextSpeed;
2302 double maxLength = -1;
2313 return iMax >= 0 ? ldi[iMax] : std::make_pair(
nullptr, -1);
2330 double minSpeed = std::numeric_limits<double>::max();
2332 if (ldi[i].first != 0) {
2333 const double speed = ldi[i].first->getSpeed();
2334 if (speed < minSpeed) {
2352 std::vector<CLeaderDist>* collectLeadBlockers,
2353 std::vector<CLeaderDist>* collectFollowBlockers,
2354 bool keepLatGapManeuver,
2356 int* retBlockedFully) {
2359 latDist =
MAX2(
MIN2(latDist, maxDist), -maxDist);
2368 if (laneOffset != 0) {
2379 if (laneOffset != 0) {
2383#ifdef DEBUG_BLOCKING
2395 }
else if (!forcedTraCIChange) {
2401 }
else if (!forcedTraCIChange) {
2407#ifdef DEBUG_BLOCKING
2409 std::cout <<
" checkBlocking latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
"\n";
2423 if (laneOffset != 0) {
2430 int blockedFully = 0;
2435 if (laneOffset != 0) {
2441 if (retBlockedFully !=
nullptr) {
2442 *retBlockedFully = blockedFully;
2444#ifdef DEBUG_BLOCKING
2447 <<
" canChangeFully=" <<
myCanChangeFully <<
" keepLatGapManeuver=" << keepLatGapManeuver <<
"\n";
2455 blocked |= blockedFully;
2460#ifdef DEBUG_BLOCKING
2465 if (collectFollowBlockers !=
nullptr && collectLeadBlockers !=
nullptr) {
2467 for (std::vector<CLeaderDist>::const_iterator it2 = collectLeadBlockers->begin(); it2 != collectLeadBlockers->end(); ++it2) {
2468 for (std::vector<CLeaderDist>::iterator it = collectFollowBlockers->begin(); it != collectFollowBlockers->end();) {
2469 if ((*it2).first == (*it).first) {
2470#ifdef DEBUG_BLOCKING
2472 std::cout <<
" removed follower " << (*it).first->getID() <<
" because it is already a leader\n";
2475 it = collectFollowBlockers->erase(it);
2489 int laneOffset,
double latDist,
double foeOffset,
bool leaders,
2490 double& safeLatGapRight,
double& safeLatGapLeft,
2491 std::vector<CLeaderDist>* collectBlockers)
const {
2498 const double vehWidth =
getWidth();
2500 const double leftVehSide = rightVehSide + vehWidth;
2501 const double rightVehSideDest = rightVehSide + latDist;
2502 const double leftVehSideDest = leftVehSide + latDist;
2503 const double rightNoOverlap =
MIN2(rightVehSideDest, rightVehSide);
2504 const double leftNoOverlap =
MAX2(leftVehSideDest, leftVehSide);
2505#ifdef DEBUG_BLOCKING
2507 std::cout <<
" checkBlockingVehicles"
2508 <<
" laneOffset=" << laneOffset
2509 <<
" latDist=" << latDist
2510 <<
" foeOffset=" << foeOffset
2511 <<
" vehRight=" << rightVehSide
2512 <<
" vehLeft=" << leftVehSide
2513 <<
" rightNoOverlap=" << rightNoOverlap
2514 <<
" leftNoOverlap=" << leftNoOverlap
2515 <<
" destRight=" << rightVehSideDest
2516 <<
" destLeft=" << leftVehSideDest
2517 <<
" leaders=" << leaders
2523 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2525 if (vehDist.first != 0 &&
myCFRelated.count(vehDist.first) == 0) {
2526 const MSVehicle* leader = vehDist.first;
2532 double foeRight, foeLeft;
2534 const bool overlapBefore =
overlap(rightVehSide, leftVehSide, foeRight, foeLeft);
2535 const bool overlapDest =
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft);
2536 const bool overlapAny =
overlap(rightNoOverlap, leftNoOverlap, foeRight, foeLeft);
2537#ifdef DEBUG_BLOCKING
2539 std::cout <<
" foe=" << vehDist.first->getID()
2540 <<
" gap=" << vehDist.second
2542 <<
" foeRight=" << foeRight
2543 <<
" foeLeft=" << foeLeft
2544 <<
" overlapBefore=" << overlapBefore
2545 <<
" overlap=" << overlapAny
2546 <<
" overlapDest=" << overlapDest
2551 if (vehDist.second < 0) {
2552 if (overlapBefore && !overlapDest && !
outsideEdge()) {
2553#ifdef DEBUG_BLOCKING
2555 std::cout <<
" ignoring current overlap to come clear\n";
2559#ifdef DEBUG_BLOCKING
2565 if (collectBlockers ==
nullptr) {
2568 collectBlockers->push_back(vehDist);
2584 const double expectedGap =
MSCFModel::gapExtrapolation(timeTillAction, vehDist.second, leader->
getSpeed(), follower->
getSpeed(), leaderAccel, followerAccel, std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
2587 const double followerExpectedSpeed = follower->
getSpeed() + timeTillAction * followerAccel;
2588 const double leaderExpectedSpeed =
MAX2(0., leader->
getSpeed() + timeTillAction * leaderAccel);
2591#if defined(DEBUG_ACTIONSTEPS) && defined(DEBUG_BLOCKING)
2593 std::cout <<
" timeTillAction=" << timeTillAction
2594 <<
" followerAccel=" << followerAccel
2595 <<
" followerExpectedSpeed=" << followerExpectedSpeed
2596 <<
" leaderAccel=" << leaderAccel
2597 <<
" leaderExpectedSpeed=" << leaderExpectedSpeed
2598 <<
"\n gap=" << vehDist.second
2599 <<
" gapChange=" << (expectedGap - vehDist.second)
2600 <<
" expectedGap=" << expectedGap
2601 <<
" expectedSecureGap=" << expectedSecureGap
2602 <<
" safeLatGapLeft=" << safeLatGapLeft
2603 <<
" safeLatGapRight=" << safeLatGapRight
2610 if (expectedGap < secureGap2) {
2612 if (foeRight > leftVehSide) {
2613 safeLatGapLeft =
MIN2(safeLatGapLeft, foeRight - leftVehSide);
2614 }
else if (foeLeft < rightVehSide) {
2615 safeLatGapRight =
MIN2(safeLatGapRight, rightVehSide - foeLeft);
2618#ifdef DEBUG_BLOCKING
2620 std::cout <<
" blocked by " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2621 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor()
2622 <<
" safeLatGapLeft=" << safeLatGapLeft <<
" safeLatGapRight=" << safeLatGapRight
2626 result |= blockType;
2627 if (collectBlockers ==
nullptr) {
2630#ifdef DEBUG_BLOCKING
2631 }
else if (
gDebugFlag2 && expectedGap < expectedSecureGap) {
2632 std::cout <<
" ignore blocker " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2633 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor() <<
"\n";
2636 if (collectBlockers !=
nullptr) {
2639 collectBlockers->push_back(vehDist);
2656 const double leftVehSide = rightVehSide + vehWidth;
2657#ifdef DEBUG_BLOCKING
2659 std::cout <<
" updateCFRelated foeOffset=" << foeOffset <<
" vehicles=" << vehicles.
toString() <<
"\n";
2662 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2664 if (vehDist.first != 0 && (
myCFRelated.count(vehDist.first) == 0 || vehDist.second < 0)) {
2665 double foeRight, foeLeft;
2667#ifdef DEBUG_BLOCKING
2669 std::cout <<
" foe=" << vehDist.first->getID() <<
" gap=" << vehDist.second
2671 <<
" foeOffset=" << foeOffset
2672 <<
" egoR=" << rightVehSide <<
" egoL=" << leftVehSide
2673 <<
" iR=" << foeRight <<
" iL=" << foeLeft
2679 if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft) && !
outsideEdge() && (vehDist.second >= 0
2685 && -vehDist.second < vehDist.first->getVehicleType().getMinGap()
2688#ifdef DEBUG_BLOCKING
2690 std::cout <<
" ignoring cfrelated foe=" << vehDist.first->getID() <<
"\n";
2695 const int erased = (int)
myCFRelated.erase(vehDist.first);
2696#ifdef DEBUG_BLOCKING
2698 std::cout <<
" restoring cfrelated foe=" << vehDist.first->getID() <<
"\n";
2711 assert(right <= left);
2712 assert(right2 <= left2);
2713 return left2 >= right + NUMERICAL_EPS && left >= right2 + NUMERICAL_EPS;
2734 return changeReason;
2741 if (sd1.
state == 0) {
2743 }
else if (sd2.
state == 0) {
2753#ifdef DEBUG_DECISION
2759 <<
" dir1=" << sd1.
dir
2763 <<
" dir2=" << sd2.
dir
2779 if (reason1 < reason2) {
2781 return (!can1 && can2 && sd1.
sameDirection(sd2)) ? sd2 : sd1;
2783 }
else if (reason1 > reason2) {
2785 return (!can2 && can1 && sd1.
sameDirection(sd2)) ? sd1 : sd2;
2793 }
else if (sd2.
dir == 0) {
2798 assert(sd1.
dir == -1);
2799 assert(sd2.
dir == 1);
2802 }
else if (sd2.
latDist >= 0) {
2858 double& currentDist,
2861 double roundaboutBonus,
2866 const bool right = (laneOffset == -1);
2867 const bool left = (laneOffset == 1);
2870 if (laneOffset != 0) {
2876 const double neighLeftPlace =
MAX2(0., neighDist - forwardPos - maxJam);
2880#ifdef DEBUG_STRATEGIC_CHANGE
2884 <<
" forwardPos=" << forwardPos
2886 <<
" laDist=" << laDist
2887 <<
" currentDist=" << currentDist
2888 <<
" usableDist=" << usableDist
2889 <<
" bestLaneOffset=" << bestLaneOffset
2890 <<
" best.length=" << best.
length
2891 <<
" maxJam=" << maxJam
2892 <<
" neighLeftPlace=" << neighLeftPlace
2899 if (laneOffset == 0) {
2906#ifdef DEBUG_STRATEGIC_CHANGE
2908 std::cout <<
SIMTIME <<
" returnToLaneBounds\n";
2917 if (link !=
nullptr &&
getWidth() < next->
getWidth() && distOnLane < 100) {
2923 latDist = -rightVehSide;
2926#ifdef DEBUG_STRATEGIC_CHANGE
2933 latDist = -(leftVehSide - next->
getWidth());
2936#ifdef DEBUG_STRATEGIC_CHANGE
2945 }
else if (laneOffset != 0 && changeToBest && bestLaneOffset == curr.
bestLaneOffset
2948 if (!
mustOvertakeStopped(
false, neighLane, neighLeaders, leaders, forwardPos, neighDist, right, latLaneDist, currentDist, latDist)) {
2949 latDist = latLaneDist;
2951#ifdef DEBUG_STRATEGIC_CHANGE
2953 std::cout <<
SIMTIME <<
" mustChangeToBest\n";
2957#ifdef DEBUG_STRATEGIC_CHANGE
2959 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" avoidStoppedNeigh\n";
2978#ifdef DEBUG_STRATEGIC_CHANGE
2981 <<
" avoid overtaking on the right nv=" << nv->
getID()
2993 if (laneOffset != 0 &&
myStrategicParam >= 0 && noOpposites &&
mustOvertakeStopped(
true, neighLane, leaders, neighLeaders, forwardPos, neighDist, right, latLaneDist, currentDist, latDist)) {
2994#ifdef DEBUG_STRATEGIC_CHANGE
2996 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" mustOvertakeStopped\n";
3005 }
else if (!changeToBest && (
currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
3012#ifdef DEBUG_STRATEGIC_CHANGE
3014 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace <<
"\n";
3020 && bestLaneOffset == 0
3023 && roundaboutBonus == 0
3030#ifdef DEBUG_STRATEGIC_CHANGE
3032 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to leave the bestLane (neighDist=" << neighDist <<
")\n";
3037 && bestLaneOffset == 0
3043#ifdef DEBUG_STRATEGIC_CHANGE
3045 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to get stranded on the on-ramp of a highway\n";
3059 MSLane* shadowPrev =
nullptr;
3061 if (*it ==
nullptr) {
3065 if (shadow ==
nullptr || currentShadowDist >= requiredDist) {
3068 if (shadowPrev !=
nullptr) {
3071 currentShadowDist += shadow->
getLength();
3072 shadowPrev = shadow;
3073#ifdef DEBUG_STRATEGIC_CHANGE
3075 std::cout <<
" shadow=" << shadow->
getID() <<
" currentShadowDist=" << currentShadowDist <<
"\n";
3079#ifdef DEBUG_STRATEGIC_CHANGE
3081 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" currentShadowDist=" << currentShadowDist <<
" requiredDist=" << requiredDist <<
" overlap=" <<
overlap <<
"\n";
3084 if (currentShadowDist < requiredDist && currentShadowDist < usableDist) {
3087#ifdef DEBUG_STRATEGIC_CHANGE
3089 std::cout <<
" must change for shadowLane end latDist=" << latDist <<
" myLeftSpace=" <<
myLeftSpace <<
"\n";
3097#if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI)
3109 }
else if (((retTraCI &
LCA_RIGHT) != 0 && laneOffset < 0)
3110 || ((retTraCI &
LCA_LEFT) != 0 && laneOffset > 0)) {
3112 latDist = latLaneDist;
3115#if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI)
3126 double posOnLane,
double neighDist,
bool right,
double latLaneDist,
double& currentDist,
double& latDist) {
3127 bool mustOvertake =
false;
3132 const int dir = latLaneDist < 0 ? -1 : 1;
3136 if (curHasStopped) {
3138 for (
int i = rightmost; i <= leftmost; i++) {
3142 const double remaining =
MIN2(neighDist, currentDist) - posOnLane;
3143#ifdef DEBUG_STRATEGIC_CHANGE
3145 std::cout <<
" overtakeDist=" << overtakeDist <<
" remaining=" << remaining
3147 <<
" hasLaneBeyond=" << hasLaneBeyond
3152 remaining > overtakeDist
3154 && (!checkCurrent || !checkOverTakeRight || !right)
3163 latDist = latLaneDist;
3164 mustOvertake =
true;
3165#ifdef DEBUG_STRATEGIC_CHANGE
3167 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" overtake stopped leader=" << leader.first->getID()
3168 <<
" newCurrentDist=" << currentDist
3169 <<
" overtakeDist=" << overtakeDist
3170 <<
" remaining=" << remaining
3186 mustOvertake =
true;
3187 if (i >= rightmost && i <= leftmost) {
3194 return mustOvertake;
3215 double& maneuverDist,
3251 const double oldLatDist = latDist;
3252 const double oldManeuverDist = maneuverDist;
3257 const double halfWidth =
getWidth() * 0.5;
3263 double surplusGapRight = oldCenter - halfWidth;
3264 double surplusGapLeft =
getLeftBorder(laneOffset != 0) - oldCenter - halfWidth;
3265 const bool stayInLane = (laneOffset == 0
3269 && (surplusGapLeft >= 0 && surplusGapRight >= 0)));
3272 std::swap(surplusGapLeft, surplusGapRight);
3274#ifdef DEBUG_KEEP_LATGAP
3276 std::cout <<
"\n " <<
SIMTIME <<
" keepLatGap() laneOffset=" << laneOffset
3277 <<
" latDist=" << latDist
3278 <<
" maneuverDist=" << maneuverDist
3282 <<
" gapFactor=" << gapFactor
3283 <<
" stayInLane=" << stayInLane <<
"\n"
3284 <<
" stayInEdge: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
3288 if (surplusGapLeft < 0 || surplusGapRight < 0) {
3298 if (laneOffset != 0) {
3301 updateGaps(neighLeaders, neighRight, oldCenter, gapFactor, surplusGapRight, surplusGapLeft,
true);
3302 updateGaps(neighFollowers, neighRight, oldCenter, gapFactor, surplusGapRight, surplusGapLeft,
true, netOverlap);
3304#ifdef DEBUG_KEEP_LATGAP
3306 std::cout <<
" minGapLat: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n"
3316 if (stayInLane || laneOffset == 1) {
3319 surplusGapRight =
MIN2(surplusGapRight,
MAX2(0.0, halfLaneWidth + posLat - halfWidth));
3320 physicalGapRight =
MIN2(physicalGapRight,
MAX2(0.0, halfLaneWidth + posLat - halfWidth));
3322 if (stayInLane || laneOffset == -1) {
3325 surplusGapLeft =
MIN2(surplusGapLeft,
MAX2(0.0, halfLaneWidth - posLat - halfWidth));
3326 physicalGapLeft =
MIN2(physicalGapLeft,
MAX2(0.0, halfLaneWidth - posLat - halfWidth));
3328#ifdef DEBUG_KEEP_LATGAP
3330 std::cout <<
" stayInLane: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
3334 if (surplusGapRight + surplusGapLeft < 0) {
3339 const double equalDeficit = 0.5 * (surplusGapLeft + surplusGapRight);
3340 if (surplusGapRight < surplusGapLeft) {
3342 const double delta =
MIN2(equalDeficit - surplusGapRight, physicalGapLeft);
3344 maneuverDist = delta;
3345#ifdef DEBUG_KEEP_LATGAP
3347 std::cout <<
" insufficient latSpace, move left: delta=" << delta <<
"\n";
3352 const double delta =
MIN2(equalDeficit - surplusGapLeft, physicalGapRight);
3354 maneuverDist = -delta;
3355#ifdef DEBUG_KEEP_LATGAP
3357 std::cout <<
" insufficient latSpace, move right: delta=" << delta <<
"\n";
3363 latDist =
MAX2(
MIN2(latDist, surplusGapLeft), -surplusGapRight);
3364 maneuverDist =
MAX2(
MIN2(maneuverDist, surplusGapLeft), -surplusGapRight);
3365 if ((state &
LCA_KEEPRIGHT) != 0 && maneuverDist != oldManeuverDist) {
3367 latDist = oldLatDist;
3368 maneuverDist = oldManeuverDist;
3370#ifdef DEBUG_KEEP_LATGAP
3372 std::cout <<
" adapted latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
" (old=" << oldLatDist <<
")\n";
3387#ifdef DEBUG_KEEP_LATGAP
3389 std::cout <<
" traci influenced latDist=" << latDist <<
"\n";
3395 const bool traciChange = ((state | traciState) &
LCA_TRACI) != 0;
3396 if (nonSublaneChange && !traciChange) {
3398#ifdef DEBUG_KEEP_LATGAP
3400 std::cout <<
" wanted changeToLeft oldLatDist=" << oldLatDist <<
", blocked latGap changeToRight\n";
3403 latDist = oldLatDist;
3406#ifdef DEBUG_KEEP_LATGAP
3408 std::cout <<
" wanted changeToRight oldLatDist=" << oldLatDist <<
", blocked latGap changeToLeft\n";
3411 latDist = oldLatDist;
3421#ifdef DEBUG_KEEP_LATGAP
3423 std::cout <<
" latDistUpdated=" << latDist <<
" oldLatDist=" << oldLatDist <<
"\n";
3426 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset, leaders, followers, blockers, neighLeaders, neighFollowers, neighBlockers,
nullptr,
nullptr, nonSublaneChange);
3429 state = (state & ~LCA_STAY);
3440#if defined(DEBUG_KEEP_LATGAP) || defined(DEBUG_STATE)
3442 std::cout <<
" latDist2=" << latDist
3456 double& surplusGapRight,
double& surplusGapLeft,
3457 bool saveMinGap,
double netOverlap,
3459 std::vector<CLeaderDist>* collectBlockers) {
3461 const double halfWidth =
getWidth() * 0.5 + NUMERICAL_EPS;
3464 if (others[i].first != 0 && others[i].second <= 0
3466 && (netOverlap == 0 || others[i].second + others[i].first->getVehicleType().getMinGap() < netOverlap)) {
3470 double foeRight, foeLeft;
3472 const double foeCenter = foeRight + 0.5 * res;
3473 const double gap =
MIN2(fabs(foeRight - oldCenter), fabs(foeLeft - oldCenter)) - halfWidth;
3476 const double currentMinGap = desiredMinGap * gapFactor;
3487#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3489 std::cout <<
" updateGaps"
3491 <<
" foe=" << foe->
getID()
3492 <<
" foeRight=" << foeRight
3493 <<
" foeLeft=" << foeLeft
3494 <<
" oldCenter=" << oldCenter
3495 <<
" gap=" << others[i].second
3496 <<
" latgap=" << gap
3497 <<
" currentMinGap=" << currentMinGap
3498 <<
" surplusGapRight=" << surplusGapRight
3499 <<
" surplusGapLeft=" << surplusGapLeft
3507 if (foeCenter < oldCenter) {
3509 surplusGapRight =
MIN3(surplusGapRight, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
3512 surplusGapLeft =
MIN3(surplusGapLeft, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
3515 if (foeCenter < oldCenter) {
3516#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3518 std::cout <<
" new minimum rightGap=" << gap <<
"\n";
3523#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3525 std::cout <<
" new minimum leftGap=" << gap <<
"\n";
3531 if (collectBlockers !=
nullptr) {
3533 if ((foeCenter < oldCenter && latDist < 0 && gap < (desiredMinGap - latDist))
3534 || (foeCenter > oldCenter && latDist > 0 && gap < (desiredMinGap + latDist))) {
3535 collectBlockers->push_back(others[i]);
3552 int currentDirection =
mySpeedLat >= 0 ? 1 : -1;
3553 int directionWish = latDist >= 0 ? 1 : -1;
3560 maxSpeedLat =
MIN2(maxSpeedLat, speedBound);
3564 maxSpeedLat =
MAX2(maxSpeedLat, speedBound);
3573 accelLat =
MAX2(accelLat, 2 * edgeOverlap);
3574 maxSpeedLat =
MAX2(maxSpeedLat, edgeOverlap);
3577#ifdef DEBUG_MANEUVER
3581 <<
" computeSpeedLat()"
3582 <<
" latDist=" << latDist
3583 <<
" maneuverDist=" << maneuverDist
3584 <<
" urgent=" << urgent
3586 <<
" currentDirection=" << currentDirection
3587 <<
" directionWish=" << directionWish
3589 <<
" maxSpeedLat=" << maxSpeedLat
3595 if (directionWish == 1) {
3609 if (maneuverDist * latDist > 0) {
3610 maneuverDist = fullLatDist;
3613#ifdef DEBUG_MANEUVER
3617 <<
" fullLatDist=" << fullLatDist
3618 <<
" speedAccel=" << speedAccel
3619 <<
" speedDecel=" << speedDecel
3620 <<
" speedBound=" << speedBound
3624 if (speedDecel * speedAccel <= 0 && (
3626 (latDist >= 0 && speedAccel >= speedBound && speedBound >= speedDecel)
3627 || (latDist <= 0 && speedAccel <= speedBound && speedBound <= speedDecel))) {
3629#ifdef DEBUG_MANEUVER
3631 std::cout <<
" computeSpeedLat a)\n";
3638#ifdef DEBUG_MANEUVER
3640 std::cout <<
" computeSpeedLat b)\n";
3647 if ((fabs(minDistAccel) < fabs(fullLatDist)) || (fabs(minDistAccel - fullLatDist) < NUMERICAL_EPS)) {
3648#ifdef DEBUG_MANEUVER
3650 std::cout <<
" computeSpeedLat c)\n";
3655#ifdef DEBUG_MANEUVER
3657 std::cout <<
" minDistAccel=" << minDistAccel <<
"\n";
3662 if ((fabs(minDistCurrent) < fabs(fullLatDist)) || (fabs(minDistCurrent - fullLatDist) < NUMERICAL_EPS)) {
3663#ifdef DEBUG_MANEUVER
3665 std::cout <<
" computeSpeedLat d)\n";
3672#ifdef DEBUG_MANEUVER
3674 std::cout <<
" computeSpeedLat e)\n";
3686#ifdef DEBUG_MANEUVER
3688 std::cout <<
" rightDanger speedLat=" << speedLat <<
"\n";
3693#ifdef DEBUG_MANEUVER
3695 std::cout <<
" leftDanger speedLat=" << speedLat <<
"\n";
3710 const bool indirect = turnInfo.second ==
nullptr ? false : turnInfo.second->isIndirect();
3743 double maneuverDist) {
3746 double secondsToLeaveLane;
3756#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3772 double nextLeftSpace;
3773 if (nextActionStepSpeed > 0.) {
3788#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3792 <<
" avoidArrivalSpeed=" << avoidArrivalSpeed
3795 <<
"\n nextLeftSpace=" << nextLeftSpace
3796 <<
" nextActionStepSpeed=" << nextActionStepSpeed
3797 <<
" nextActionStepRemainingSeconds=" << secondsToLeaveLane - timeTillActionStep
3807#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3811 <<
" secondsToLeave=" << secondsToLeaveLane
3833 const double vehWidth =
getWidth();
3835 const double leftVehSide = rightVehSide + vehWidth;
3836 const double rightVehSideDest = rightVehSide + latDist;
3837 const double leftVehSideDest = leftVehSide + latDist;
3838#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3840 std::cout <<
" commitFollowSpeed"
3841 <<
" latDist=" << latDist
3842 <<
" foeOffset=" << foeOffset
3843 <<
" vehRight=" << rightVehSide
3844 <<
" vehLeft=" << leftVehSide
3845 <<
" destRight=" << rightVehSideDest
3846 <<
" destLeft=" << leftVehSideDest
3852 if (vehDist.first != 0) {
3853 const MSVehicle* leader = vehDist.first;
3855 double foeRight, foeLeft;
3857#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3859 std::cout <<
" foe=" << vehDist.first->getID()
3860 <<
" gap=" << vehDist.second
3862 <<
" foeRight=" << foeRight
3863 <<
" foeLeft=" << foeLeft
3864 <<
" overlapBefore=" <<
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)
3865 <<
" overlapDest=" <<
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)
3869 if (
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)) {
3873 speed =
MIN2(speed, vSafe);
3874#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3876 std::cout <<
" case1 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3879 }
else if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)) {
3884 speed =
MIN2(speed, vSafe);
3885#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3887 std::cout <<
" case2 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3907 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 /
myOppositeParam;
3966 }
else if (key ==
"speedGainProbabilityRight") {
3968 }
else if (key ==
"speedGainProbabilityLeft") {
3970 }
else if (key ==
"keepRightProbability") {
3972 }
else if (key ==
"lookAheadSpeed") {
3974 }
else if (key ==
"sigmaState") {
3977 }
else if (key ==
"speedGainRP") {
3979 }
else if (key ==
"speedGainLP") {
3981 }
else if (key ==
"keepRightP") {
4051 }
else if (key ==
"speedGainProbabilityRight") {
4053 }
else if (key ==
"speedGainProbabilityLeft") {
4055 }
else if (key ==
"keepRightProbability") {
4057 }
else if (key ==
"lookAheadSpeed") {
4059 }
else if (key ==
"sigmaState") {
4073 const std::pair<MSVehicle*, double>& leader,
4074 const std::pair<MSVehicle*, double>& follower,
4075 const std::pair<MSVehicle*, double>& neighLead,
4076 const std::pair<MSVehicle*, double>& neighFollow,
4078 const std::vector<MSVehicle::LaneQ>& preb,
4084#ifdef DEBUG_WANTSCHANGE
4086 std::cout <<
"\nWANTS_CHANGE\n" <<
SIMTIME
4090 <<
" neigh=" << neighLane.
getID()
4094 <<
" considerChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
4108 double maneuverDist;
4111 leaders, followers, blockers,
4112 neighLeaders, neighFollowers, neighBlockers,
4114 lastBlocked, firstBlocked, latDist, maneuverDist, blocked);
4118 result &= ~LCA_SUBLANE;
4119 result |=
getLCA(result, latDist);
4121#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE)
4126 <<
" wantsChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
4127 << ((result &
LCA_URGENT) ?
" (urgent)" :
"")
4133 << ((result &
LCA_TRACI) ?
" (traci)" :
"")
4185 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 sublaneEnds(int i, const MSLane *next, double shift)
check whether the sublane continues on the next lane
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.
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
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
double getLateralShift() const
return lateral shift that must be applied when passing this link
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 getLeftSideOnLane() const
Get the lateral position of the vehicles left side on the lane:
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 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
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.