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
105#define DEBUG_COND (myVehicle.isSelected())
117 mySpeedGainProbabilityRight(0),
118 mySpeedGainProbabilityLeft(0),
119 myKeepRightProbability(0),
120 myLeadingBlockerLength(0),
124 myCanChangeFully(true),
125 mySafeLatDistRight(0),
126 mySafeLatDistLeft(0),
134 myMinGapLat(v.getVehicleType().getMinGapLat()),
137 MAX2(NUMERICAL_EPS, myMinGapLat)) /
138 MAX2(NUMERICAL_EPS, myMinGapLat)))),
140 myMinImpatience(myImpatience),
192 const std::vector<MSVehicle::LaneQ>& preb,
195 double& latDist,
double& maneuverDist,
int& blocked) {
198 const std::string changeType = laneOffset == -1 ?
"right" : (laneOffset == 1 ?
"left" :
"current");
206 <<
" neigh=" << neighLane.
getID()
211 <<
" considerChangeTo=" << changeType
218 leaders, followers, blockers,
219 neighLeaders, neighFollowers, neighBlockers,
221 lastBlocked, firstBlocked, latDist, maneuverDist, blocked);
223 result =
keepLatGap(result, leaders, followers, blockers,
224 neighLeaders, neighFollowers, neighBlockers,
225 neighLane, laneOffset, latDist, maneuverDist, blocked);
227 result |=
getLCA(result, latDist);
229#if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE)
230 double latDistTmp = latDist;
233#if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE)
235 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" maneuverDist=" << maneuverDist <<
" latDist=" << latDistTmp <<
" mySpeedPrev=" <<
mySpeedLat <<
" speedLat=" <<
DIST2SPEED(latDist) <<
" latDist2=" << latDist <<
"\n";
242 <<
" wantsChangeTo=" << changeType
243 <<
" latDist=" << latDist
244 <<
" maneuverDist=" << maneuverDist
252 <<
" wantsNoChangeTo=" << changeType
309 const double newSpeed =
_patchSpeed(
MAX2(min, 0.0), wanted, max, cfModel);
310#ifdef DEBUG_PATCHSPEED
312 const std::string patched = (wanted != newSpeed ?
" patched=" +
toString(newSpeed) :
"");
319 <<
" wanted=" << wanted
338 double nVSafe = wanted;
344#ifdef DEBUG_PATCHSPEED
352 max =
MIN2(max, safe);
357 if (safe >= vMinEmergency) {
359 min =
MAX2(vMinEmergency, safe);
362#ifdef DEBUG_PATCHSPEED
364 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ?
" (not enough)" :
"") <<
"\n";
367 nVSafe =
MAX2(min, safe);
374 double accel = i.first;
376 if (v >= min && v <= max) {
379 nVSafe =
MIN2(v, nVSafe);
381 nVSafe =
MIN2(v * coopWeight + (1 - coopWeight) * wanted, nVSafe);
384#ifdef DEBUG_PATCHSPEED
386 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" got accel=" << accel <<
" nVSafe=" << nVSafe <<
"\n";
390#ifdef DEBUG_PATCHSPEED
393 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring low nVSafe=" << v <<
" (accel=" << accel <<
") min=" << min <<
"\n";
397 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring high nVSafe=" << v <<
" (accel=" << accel <<
") max=" << max <<
"\n";
405#ifdef DEBUG_PATCHSPEED
418#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
423 return (max + wanted) / 2.0;
427#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
432 return (min + wanted) / 2.0;
435#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
440 return (max + wanted) / 2.0;
481#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
486 return (max + wanted) / 2.0;
490#if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE)
510 if (pinfo->first >= 0) {
519 <<
" informedBy=" << sender->
getID()
520 <<
" info=" << pinfo->second
521 <<
" vSafe=" << pinfo->first
534 assert(cld.first != 0);
543 double remainingSeconds) {
549 plannedSpeed =
MIN2(plannedSpeed, v);
554 std::cout <<
" informLeader speed=" <<
myVehicle.
getSpeed() <<
" planned=" << plannedSpeed <<
"\n";
565 if (
gDebugFlag2) std::cout <<
" blocked by leader nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap="
569 const double dv = plannedSpeed - nv->
getSpeed();
570 const double overtakeDist = (neighLead.second
582 || dv * remainingSeconds < overtakeDist)
583 && (!neighLead.first->isStopped() || (
isOpposite() && neighLead.second >= 0))) {
598 <<
" cannot overtake leader nv=" << nv->
getID()
600 <<
" remainingSeconds=" << remainingSeconds
601 <<
" targetSpeed=" << targetSpeed
602 <<
" nextSpeed=" << nextSpeed
613 <<
" cannot overtake fast leader nv=" << nv->
getID()
615 <<
" remainingSeconds=" << remainingSeconds
616 <<
" targetSpeed=" << targetSpeed
627 <<
" wants to overtake leader nv=" << nv->
getID()
629 <<
" remainingSeconds=" << remainingSeconds
630 <<
" currentGap=" << neighLead.second
632 <<
" overtakeDist=" << overtakeDist
642 }
else if (neighLead.first != 0) {
645 double dv, nextNVSpeed;
665 std::cout <<
" not blocked by leader nv=" << nv->
getID()
667 <<
" gap=" << neighLead.second
668 <<
" nextGap=" << neighLead.second - dv
670 <<
" targetSpeed=" << targetSpeed
674 return MIN2(targetSpeed, plannedSpeed);
686 double remainingSeconds,
687 double plannedSpeed) {
695 if (
gDebugFlag2) std::cout <<
" blocked by follower nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap="
702 if ((neededGap - neighFollow.second) / remainingSeconds < (plannedSpeed - nv->
getSpeed())) {
705 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" without any help neededGap=" << neededGap <<
"\n";
715 const double curDV = nv->
getSpeed() - plannedSpeed;
731 const double neighNewSpeed1s =
MAX2(0., nv->
getSpeed() - helpDecel);
732 const double dv = plannedSpeed - neighNewSpeed1s;
734 const double decelGap = neighFollow.second + dv;
740 <<
" egoNV=" << plannedSpeed
741 <<
" nvNewSpeed=" << neighNewSpeed
742 <<
" nvNewSpeed1s=" << neighNewSpeed1s
743 <<
" deltaGap=" << dv
744 <<
" decelGap=" << decelGap
745 <<
" secGap=" << secureGap
749 if (decelGap > 0 && decelGap >= secureGap) {
764 std::cout <<
" wants to cut in before nv=" << nv->
getID()
765 <<
" vsafe1=" << vsafe1
766 <<
" vsafe=" << vsafe
771 }
else if (dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS)) {
776 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (eventually)\n";
784 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (nv cannot overtake right)\n";
800 std::cout <<
" wants right follower to slow down a bit\n";
806 std::cout <<
" wants to cut in before right follower nv=" << nv->
getID() <<
" (eventually)\n";
815 const double overtakeDist = (neighFollow.second
821 const double needDV = overtakeDist / remainingSeconds;
829 <<
" wants to be overtaken by=" << nv->
getID()
830 <<
" overtakeDist=" << overtakeDist
832 <<
" vhelp=" << vhelp
833 <<
" needDV=" << needDV
839 }
else if (neighFollow.first != 0) {
844 std::cout <<
" wants to cut in before non-blocking follower nv=" << neighFollow.first->getID() <<
"\n";
852 const std::vector<CLeaderDist>& blockers,
853 double remainingSeconds) {
865 plannedSpeed =
MIN2(plannedSpeed, safe);
867 for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
868 plannedSpeed =
MIN2(plannedSpeed,
informLeader(blocked, dir, *it, remainingSeconds));
876 const std::vector<CLeaderDist>& blockers,
877 double remainingSeconds,
878 double plannedSpeed) {
880 for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
881 informFollower(blocked, dir, *it, remainingSeconds, plannedSpeed);
906 const double halfWidth =
getWidth() * 0.5;
919 std::vector<double> newExpectedSpeeds;
928 const std::vector<MSLane*>& lanes = currEdge->
getLanes();
929 for (std::vector<MSLane*>::const_iterator it_lane = lanes.begin(); it_lane != lanes.end(); ++it_lane) {
931 for (
int i = 0; i < subLanes; ++i) {
932 newExpectedSpeeds.push_back((*it_lane)->getVehicleMaxSpeed(&
myVehicle));
938 for (
int i = 0; i < subLanes; ++i) {
939 newExpectedSpeeds.push_back(lanes.back()->getVehicleMaxSpeed(&
myVehicle));
947 if (subLaneShift < std::numeric_limits<int>::max()) {
949 const int newI = i + subLaneShift;
950 if (newI > 0 && newI < (
int)newExpectedSpeeds.size()) {
986 for (
const MSLink*
const link : lane->getLinkCont()) {
987 if (&link->getLane()->getEdge() == curEdge) {
989 const MSLane* target = link->getLane();
990 const std::vector<MSLane*>& lanes2 = curEdge->
getLanes();
991 for (std::vector<MSLane*>::const_iterator it_lane2 = lanes2.begin(); it_lane2 != lanes2.end(); ++it_lane2) {
992 const MSLane* lane2 = *it_lane2;
993 if (lane2 == target) {
994 return prevShift + curShift;
1005 return std::numeric_limits<int>::max();
1040#if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE)
1073 const std::vector<MSVehicle::LaneQ>& preb,
1076 double& latDist,
double& maneuverDist,
int& blocked) {
1078 if (laneOffset != 0) {
1080 const double halfWidth =
getWidth() * 0.5;
1082 if (laneOffset < 0) {
1092 int bestLaneOffset = 0;
1093 double currentDist = 0;
1094 double neighDist = 0;
1106 const int prebOffset = (checkOpposite ? 0 : laneOffset);
1107 for (
int p = 0; p < (int) preb.size(); ++p) {
1108 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1109 assert(p + prebOffset < (
int)preb.size());
1111 neigh = preb[p + prebOffset];
1112 currentDist = curr.
length;
1113 neighDist = neigh.
length;
1116 if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1117#ifdef DEBUG_WANTSCHANGE
1121 <<
" bestLaneOffsetOld=" << bestLaneOffset
1122 <<
" bestLaneOffsetNew=" << laneOffset
1126 bestLaneOffset = prebOffset;
1128 best = preb[p + bestLaneOffset];
1132 assert(curr.
lane !=
nullptr);
1133 assert(neigh.
lane !=
nullptr);
1134 assert(best.
lane !=
nullptr);
1135 double driveToNextStop = -std::numeric_limits<double>::max();
1144#ifdef DEBUG_WANTS_CHANGE
1149 <<
" stopPos=" << stopPos
1150 <<
" currentDist=" << currentDist
1151 <<
" neighDist=" << neighDist
1155 currentDist =
MAX2(currentDist, stopPos);
1156 neighDist =
MAX2(neighDist, stopPos);
1159 const bool right = (laneOffset == -1);
1160 const bool left = (laneOffset == 1);
1163 const bool changeToBest = (right && bestLaneOffset < 0) || (left && bestLaneOffset > 0) || (laneOffset == 0 && bestLaneOffset == 0);
1189#ifdef DEBUG_WANTSCHANGE
1196 <<
"\n leaders=" << leaders.
toString()
1197 <<
"\n followers=" << followers.
toString()
1198 <<
"\n blockers=" << blockers.
toString()
1199 <<
"\n neighLeaders=" << neighLeaders.
toString()
1200 <<
"\n neighFollowers=" << neighFollowers.
toString()
1201 <<
"\n neighBlockers=" << neighBlockers.
toString()
1202 <<
"\n changeToBest=" << changeToBest
1203 <<
" latLaneDist=" << latLaneDist
1212 if (lastBlocked != firstBlocked) {
1263 for (
int i = 0; i < neighLeaders.
numSublanes(); ++i) {
1265 if (vehDist.first !=
nullptr && vehDist.first->isStopped()) {
1283 currentDist += roundaboutBonus;
1284 neighDist += roundaboutBonus;
1303 if ((ret &
LCA_STAY) != 0 && latDist == 0) {
1316 if (changeToBest && abs(bestLaneOffset) > 1
1322#ifdef DEBUG_WANTSCHANGE
1324 std::cout <<
" reserving space for unseen blockers myLeadingBlockerLength=" <<
myLeadingBlockerLength <<
"\n";
1333#ifdef DEBUG_WANTSCHANGE
1339 if (*firstBlocked != neighLeadLongest &&
tieBrakeLeader(*firstBlocked)) {
1348 std::vector<CLeaderDist> collectLeadBlockers;
1349 std::vector<CLeaderDist> collectFollowBlockers;
1350 int blockedFully = 0;
1351 maneuverDist = latDist;
1353 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1354 leaders, followers, blockers,
1355 neighLeaders, neighFollowers, neighBlockers, &collectLeadBlockers, &collectFollowBlockers,
1356 false, gapFactor, &blockedFully);
1358 const double absLaneOffset = fabs(bestLaneOffset != 0 ? bestLaneOffset : latDist /
SUMO_const_laneWidth);
1359 const double remainingSeconds = ((ret &
LCA_TRACI) == 0 ?
1362 const double plannedSpeed =
informLeaders(blocked, myLca, collectLeadBlockers, remainingSeconds);
1364 if (plannedSpeed >= 0) {
1366 informFollowers(blocked, myLca, collectFollowBlockers, remainingSeconds, plannedSpeed);
1368 if (plannedSpeed > 0) {
1369 commitManoeuvre(blocked, blockedFully, leaders, neighLeaders, neighLane, maneuverDist);
1371#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE)
1378 <<
" remainingSeconds=" << remainingSeconds
1379 <<
" plannedSpeed=" << plannedSpeed
1390 if (roundaboutBonus > 0) {
1392#ifdef DEBUG_WANTS_CHANGE
1396 <<
" roundaboutBonus=" << roundaboutBonus
1407 latDist = latLaneDist;
1408 maneuverDist = latLaneDist;
1409 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1410 leaders, followers, blockers,
1411 neighLeaders, neighFollowers, neighBlockers);
1415 ret &= ~LCA_COOPERATIVE;
1431 const double inconvenience = (latLaneDist < 0
1434#ifdef DEBUG_COOPERATE
1442 <<
" inconvenience=" << inconvenience
1444 <<
" wantsChangeToHelp=" << (right ?
"right" :
"left")
1461 && (changeToBest ||
currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1464#ifdef DEBUG_COOPERATE
1466 std::cout <<
" wants cooperative change\n";
1473 maneuverDist = latDist;
1474 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1475 leaders, followers, blockers,
1476 neighLeaders, neighFollowers, neighBlockers);
1502 const double vehWidth =
getWidth();
1504 const double leftVehSide = rightVehSide + vehWidth;
1506 double defaultNextSpeed = std::numeric_limits<double>::max();
1508 int leftmostOnEdge = (int)sublaneSides.size() - 1;
1509 while (leftmostOnEdge > 0 && sublaneSides[leftmostOnEdge] > leftVehSide) {
1512 int rightmostOnEdge = leftmostOnEdge;
1513 while (rightmostOnEdge > 0 && sublaneSides[rightmostOnEdge] > rightVehSide + NUMERICAL_EPS) {
1515#ifdef DEBUG_WANTSCHANGE
1517 std::cout <<
" adapted to current sublane=" << rightmostOnEdge <<
" defaultNextSpeed=" << defaultNextSpeed <<
"\n";
1518 std::cout <<
" sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] <<
" rightVehSide=" << rightVehSide <<
"\n";
1524#ifdef DEBUG_WANTSCHANGE
1526 std::cout <<
" adapted to current sublane=" << rightmostOnEdge <<
" defaultNextSpeed=" << defaultNextSpeed <<
"\n";
1527 std::cout <<
" sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] <<
" rightVehSide=" << rightVehSide <<
"\n";
1530 double maxGain = -std::numeric_limits<double>::max();
1531 double maxGainRight = -std::numeric_limits<double>::max();
1532 double maxGainLeft = -std::numeric_limits<double>::max();
1533 double latDistNice = std::numeric_limits<double>::max();
1536 double leftMax =
MAX2(
1543 assert(leftMax <= edge.
getWidth());
1545 int sublaneCompact =
MAX2(iMin, rightmostOnEdge - 1);
1551 const double maxLatDist = leftMax - leftVehSide;
1552 const double minLatDist = rightMin - rightVehSide;
1553 const int iStart = laneOffset == 0 ? iMin : 0;
1554 const double rightEnd = laneOffset == 0 ? leftMax : (checkOpposite ?
getLeftBorder() : edge.
getWidth());
1555#ifdef DEBUG_WANTSCHANGE
1557 <<
" checking sublanes rightmostOnEdge=" << rightmostOnEdge
1558 <<
" rightEnd=" << rightEnd
1559 <<
" leftmostOnEdge=" << leftmostOnEdge
1560 <<
" iStart=" << iStart
1562 <<
" sublaneSides=" << sublaneSides.size()
1563 <<
" leftMax=" << leftMax
1564 <<
" minLatDist=" << minLatDist
1565 <<
" maxLatDist=" << maxLatDist
1566 <<
" sublaneCompact=" << sublaneCompact
1569 for (
int i = iStart; i < (int)sublaneSides.size(); ++i) {
1570 if (sublaneSides[i] + vehWidth < rightEnd) {
1576 while (vMin > 0 && j < (
int)sublaneSides.size() && sublaneSides[j] < sublaneSides[i] + vehWidth) {
1578#ifdef DEBUG_WANTSCHANGE
1586 if (laneOffset != 0 &&
overlap(sublaneSides[i], sublaneSides[i] + vehWidth, laneBoundary, laneBoundary)) {
1590 double currentLatDist = sublaneSides[i] - rightVehSide;
1591 if ((laneOffset == 0 && (currentLatDist > maxLatDist || currentLatDist < minLatDist))
1592 || (laneOffset < 0 && currentLatDist > maxLatDist)
1593 || (laneOffset > 0 && currentLatDist < minLatDist)) {
1594#ifdef DEBUG_WANTSCHANGE
1596 std::cout <<
" i=" << i <<
" currentLatDist=" << currentLatDist <<
" outOfBounds\n";
1601 currentLatDist =
MIN2(
MAX2(currentLatDist, minLatDist), maxLatDist);
1605 relativeGain *= 0.5;
1608 if (relativeGain > maxGain && currentLatDist * laneOffset >= 0) {
1609 maxGain = relativeGain;
1612 latDist = currentLatDist;
1613#ifdef DEBUG_WANTSCHANGE
1615 std::cout <<
" i=" << i <<
" vMin=" << vMin <<
" newLatDist=" << latDist <<
" relGain=" << relativeGain <<
"\n";
1621 if (currentLatDist > 0
1625 && maxGain - relativeGain < NUMERICAL_EPS) {
1626 latDist = currentLatDist;
1629#ifdef DEBUG_WANTSCHANGE
1631 std::cout <<
" i=" << i <<
" rightmostOnEdge=" << rightmostOnEdge <<
" vMin=" << vMin <<
" relGain=" << relativeGain <<
" sublaneCompact=" << sublaneCompact <<
" curLatDist=" << currentLatDist <<
"\n";
1635 maxGainRight =
MAX2(maxGainRight, relativeGain);
1637 maxGainLeft =
MAX2(maxGainLeft, relativeGain);
1639 const double subAlignDist = sublaneSides[i] - rightVehSide;
1640 if (fabs(subAlignDist) < fabs(latDistNice)) {
1641 latDistNice = subAlignDist;
1642#ifdef DEBUG_WANTSCHANGE
1644 <<
" nicest sublane=" << i
1645 <<
" side=" << sublaneSides[i]
1646 <<
" rightSide=" << rightVehSide
1647 <<
" latDistNice=" << latDistNice
1648 <<
" maxGainR=" << (maxGainRight == -std::numeric_limits<double>::max() ?
"n/a" :
toString(maxGainRight))
1649 <<
" maxGainL=" << (maxGainLeft == -std::numeric_limits<double>::max() ?
"n/a" :
toString(maxGainLeft))
1656 if (maxGainRight != -std::numeric_limits<double>::max()) {
1657#ifdef DEBUG_WANTSCHANGE
1663#ifdef DEBUG_WANTSCHANGE
1669 if (maxGainLeft != -std::numeric_limits<double>::max()) {
1670#ifdef DEBUG_WANTSCHANGE
1676#ifdef DEBUG_WANTSCHANGE
1683 if ((fabs(maxGainRight) < NUMERICAL_EPS || maxGainRight == -std::numeric_limits<double>::max())
1684 && (right || (alternatives &
LCA_RIGHT) == 0)) {
1687 if ((fabs(maxGainLeft) < NUMERICAL_EPS || maxGainLeft == -std::numeric_limits<double>::max())
1688 && (left || (alternatives &
LCA_LEFT) == 0)) {
1693#ifdef DEBUG_WANTSCHANGE
1696 <<
" defaultNextSpeed=" << defaultNextSpeed
1697 <<
" maxGain=" << maxGain
1698 <<
" maxGainRight=" << maxGainRight
1699 <<
" maxGainLeft=" << maxGainLeft
1702 <<
" latDist=" << latDist
1703 <<
" latDistNice=" << latDistNice
1704 <<
" sublaneCompact=" << sublaneCompact
1717 double acceptanceTime;
1726 double minFactor = 1.0;
1727 for (
int i = 0; i < followers.
numSublanes(); ++i) {
1729 if (follower.first !=
nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1732 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1733 if (fRSF > roadSpeedFactor) {
1736 if (factor < minFactor) {
1742 acceptanceTime *= minFactor;
1746 double fullSpeedDrivingSeconds =
MIN2(acceptanceTime, fullSpeedGap / vMax);
1748 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1749 fullSpeedGap =
MAX2(0.,
MIN2(fullSpeedGap,
1751 vMax, neighLead.first->
getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1752 fullSpeedDrivingSeconds =
MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1761#ifdef DEBUG_WANTSCHANGE
1764 <<
" considering keepRight:"
1766 <<
" neighDist=" << neighDist
1768 <<
" leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1770 myVehicle.
getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1771 <<
" acceptanceTime=" << acceptanceTime
1772 <<
" fullSpeedGap=" << fullSpeedGap
1773 <<
" fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1774 <<
" dProb=" << deltaProb
1775 <<
" isSlide=" << isSlide
1786 latDist = latLaneDist;
1787 maneuverDist = latLaneDist;
1788 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1789 leaders, followers, blockers,
1790 neighLeaders, neighFollowers, neighBlockers);
1793 ret &= ~LCA_KEEPRIGHT;
1799#ifdef DEBUG_WANTSCHANGE
1804 <<
" neighDist=" << neighDist
1808 <<
" latDist=" << latDist
1818 int blockedFully = 0;
1819 maneuverDist = latDist;
1820 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1821 leaders, followers, blockers,
1822 neighLeaders, neighFollowers, neighBlockers,
1823 nullptr,
nullptr,
false, 0, &blockedFully);
1829 ret &= ~LCA_SPEEDGAIN;
1836#ifdef DEBUG_WANTSCHANGE
1841 <<
" latDist=" << latDist
1842 <<
" neighDist=" << neighDist
1845 <<
" stayInLane=" << stayInLane
1856 int blockedFully = 0;
1857 maneuverDist = latDist;
1858 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1859 leaders, followers, blockers,
1860 neighLeaders, neighFollowers, neighBlockers,
1861 nullptr,
nullptr,
false, 0, &blockedFully);
1866 ret &= ~LCA_SPEEDGAIN;
1871 double latDistSublane = 0.;
1873 const double halfVehWidth =
getWidth() * 0.5;
1876 && bestLaneOffset == 0
1896#ifdef DEBUG_WANTSCHANGE
1907 latDistSublane = -halfLaneWidth + halfVehWidth -
getPosLat();
1910 latDistSublane = halfLaneWidth - halfVehWidth -
getPosLat();
1917 latDistSublane = latDistNice;
1920 latDistSublane = sublaneSides[sublaneCompact] - rightVehSide;
1926 if (fabs(posLat) > hLW) {
1929 latDistSublane -= (posLat - hLW);
1931 latDistSublane += (-posLat - hLW);
1936 if (rightVehSide < 0) {
1937 latDistSublane -= rightVehSide;
1938 }
else if (leftVehSide > edgeWidth) {
1939 latDistSublane -= leftVehSide - edgeWidth;
1958 latDistSublane * latDist > 0) {
1960#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE) || defined(DEBUG_MANEUVER)
1965 <<
" latDist=" << latDist
1966 <<
" latDistSublane=" << latDistSublane
1967 <<
" relGainSublane=" <<
computeSpeedGain(latDistSublane, defaultNextSpeed)
1968 <<
" maneuverDist=" << maneuverDist
1980#if defined(DEBUG_WANTSCHANGE)
1982 <<
" speedGain=" <<
computeSpeedGain(latDistSublane, defaultNextSpeed) <<
")\n";
1990#if defined(DEBUG_WANTSCHANGE)
1992 std::cout <<
" aborting sublane change due to prior maneuver\n";
1997 latDist = latDistSublane * (
isOpposite() ? -1 : 1);
2002#ifdef DEBUG_WANTSCHANGE
2005 <<
" latDist=" << latDist
2013#ifdef DEBUG_WANTSCHANGE
2019 maneuverDist = latDist;
2020 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
2021 leaders, followers, blockers,
2022 neighLeaders, neighFollowers, neighBlockers);
2025 ret &= ~LCA_SUBLANE;
2051#ifdef DEBUG_WANTSCHANGE
2068 if ((*blocked) !=
nullptr) {
2070#ifdef DEBUG_SLOWDOWN
2079 if (gap > POSITION_EPS) {
2093 (*blocked)->getSpeed(), (*blocked)->getCarFollowModel().getMaxDecel());
2096 std::cout <<
" slowing down for blocked " <<
Named::getIDSecure(*blocked) <<
" targetSpeed=" << targetSpeed <<
"\n";
2117 if (cand !=
nullptr && cand->getBidiLane() == lane) {
2130 const MSLink* link = next !=
nullptr ? lane->
getLinkTo(next) :
nullptr;
2134 assert(preb.size() == lanes.size() ||
isOpposite());
2135#ifdef DEBUG_EXPECTED_SLSPEED
2138 <<
" sublaneOffset=" << sublaneOffset <<
" laneIndex=" << laneIndex <<
" lane=" << lane->
getID() <<
" ahead=" << ahead.
toString() <<
"\n";
2142 for (
int sublane = 0; sublane < (int)ahead.
numSublanes(); ++sublane) {
2143 const int edgeSublane = sublane + sublaneOffset;
2151#ifdef DEBUG_EXPECTED_SLSPEED
2153 std::cout <<
" updateExpectedSublaneSpeeds sublane=" << sublane <<
" doesNotContinue\n";
2160 const MSVehicle* leader = ahead[sublane].first;
2161 const double gap = ahead[sublane].second;
2163 if (leader ==
nullptr) {
2168 const int prebIndex =
isOpposite() ? (int)preb.size() - 1 : laneIndex;
2179#ifdef DEBUG_EXPECTED_SLSPEED
2181 std::cout <<
SIMTIME <<
" updateExpectedSublaneSpeeds sublane=" << sublane <<
" leader=" << leader->
getID() <<
" bidi=" << bidi->
getID() <<
" gap=" << gap <<
" vSafe=" << vSafe <<
"\n";
2191#ifdef DEBUG_EXPECTED_SLSPEED
2193 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" leader=" << leader->
getID() <<
" gap=" << gap <<
" vSafe=" << vSafe <<
"\n";
2202 double foeRight, foeLeft;
2206 if (pedLeader.first != 0) {
2211#ifdef DEBUG_EXPECTED_SLSPEED
2213 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" pedLeader=" << pedLeader.first->getID() <<
" gap=" << pedGap <<
" vSafe=" << vSafe <<
"\n";
2221 double foeRight, foeLeft;
2223 const double foeRightBidi = bidi->
getWidth() - foeLeft;
2224 const double foeLeftBidi = bidi->
getWidth() - foeRight;
2229 if (pedLeader.first != 0) {
2234#ifdef DEBUG_EXPECTED_SLSPEED
2236 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" pedLeader=" << pedLeader.first->getID() <<
" (bidi) gap=" << pedGap <<
" vSafe=" << vSafe <<
"\n";
2241 vSafe =
MIN2(vMax, vSafe);
2248#ifdef DEBUG_EXPECTED_SLSPEED
2250 std::cout <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" lane " << lane->
getID() <<
" forbidden\n";
2262 return ((side < -NUMERICAL_EPS
2271 const double deltaV = vMax - vLeader;
2272 if (deltaV > 0 && gap / deltaV < mySpeedGainLookahead && mySpeedGainLookahead > 0) {
2276 const double gapClosingTime =
MAX2(0.0, gap / deltaV);
2277 const double vSafe2 = (gapClosingTime * vSafe + (foreCastTime - gapClosingTime) * vLeader) / foreCastTime;
2278#ifdef DEBUG_EXPECTED_SLSPEED
2280 std::cout <<
" foreCastTime=" << foreCastTime <<
" gapClosingTime=" << gapClosingTime <<
" extrapolated vSafe=" << vSafe2 <<
"\n";
2291 double result = std::numeric_limits<double>::max();
2293 const double vehWidth =
getWidth();
2295 const double leftVehSide = rightVehSide + vehWidth;
2296 for (
int i = 0; i < (int)sublaneSides.size(); ++i) {
2298 if (
overlap(rightVehSide, leftVehSide, sublaneSides[i], leftSide)) {
2303 return result - defaultNextSpeed;
2310 double maxLength = -1;
2321 return iMax >= 0 ? ldi[iMax] : std::make_pair(
nullptr, -1);
2338 double minSpeed = std::numeric_limits<double>::max();
2340 if (ldi[i].first != 0) {
2341 const double speed = ldi[i].first->getSpeed();
2342 if (speed < minSpeed) {
2356 if (v !=
nullptr && v->isStopped()) {
2373 std::vector<CLeaderDist>* collectLeadBlockers,
2374 std::vector<CLeaderDist>* collectFollowBlockers,
2375 bool keepLatGapManeuver,
2377 int* retBlockedFully) {
2380 latDist =
MAX2(
MIN2(latDist, maxDist), -maxDist);
2389 if (laneOffset != 0) {
2400 if (laneOffset != 0) {
2404#ifdef DEBUG_BLOCKING
2416 }
else if (!forcedTraCIChange) {
2422 }
else if (!forcedTraCIChange) {
2428#ifdef DEBUG_BLOCKING
2430 std::cout <<
" checkBlocking latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
"\n";
2444 if (laneOffset != 0) {
2451 int blockedFully = 0;
2456 if (laneOffset != 0) {
2462 if (retBlockedFully !=
nullptr) {
2463 *retBlockedFully = blockedFully;
2465#ifdef DEBUG_BLOCKING
2468 <<
" canChangeFully=" <<
myCanChangeFully <<
" keepLatGapManeuver=" << keepLatGapManeuver <<
"\n";
2476 blocked |= blockedFully;
2481#ifdef DEBUG_BLOCKING
2486 if (collectFollowBlockers !=
nullptr && collectLeadBlockers !=
nullptr) {
2488 for (std::vector<CLeaderDist>::const_iterator it2 = collectLeadBlockers->begin(); it2 != collectLeadBlockers->end(); ++it2) {
2489 for (std::vector<CLeaderDist>::iterator it = collectFollowBlockers->begin(); it != collectFollowBlockers->end();) {
2490 if ((*it2).first == (*it).first) {
2491#ifdef DEBUG_BLOCKING
2493 std::cout <<
" removed follower " << (*it).first->getID() <<
" because it is already a leader\n";
2496 it = collectFollowBlockers->erase(it);
2510 int laneOffset,
double latDist,
double foeOffset,
bool leaders,
2511 double& safeLatGapRight,
double& safeLatGapLeft,
2512 std::vector<CLeaderDist>* collectBlockers)
const {
2519 const double vehWidth =
getWidth();
2521 const double leftVehSide = rightVehSide + vehWidth;
2522 const double rightVehSideDest = rightVehSide + latDist;
2523 const double leftVehSideDest = leftVehSide + latDist;
2524 const double rightNoOverlap =
MIN2(rightVehSideDest, rightVehSide);
2525 const double leftNoOverlap =
MAX2(leftVehSideDest, leftVehSide);
2526#ifdef DEBUG_BLOCKING
2528 std::cout <<
" checkBlockingVehicles"
2529 <<
" laneOffset=" << laneOffset
2530 <<
" latDist=" << latDist
2531 <<
" foeOffset=" << foeOffset
2532 <<
" vehRight=" << rightVehSide
2533 <<
" vehLeft=" << leftVehSide
2534 <<
" rightNoOverlap=" << rightNoOverlap
2535 <<
" leftNoOverlap=" << leftNoOverlap
2536 <<
" destRight=" << rightVehSideDest
2537 <<
" destLeft=" << leftVehSideDest
2538 <<
" leaders=" << leaders
2544 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2546 if (vehDist.first != 0 &&
myCFRelated.count(vehDist.first) == 0) {
2547 const MSVehicle* leader = vehDist.first;
2553 double foeRight, foeLeft;
2555 const bool overlapBefore =
overlap(rightVehSide, leftVehSide, foeRight, foeLeft);
2556 const bool overlapDest =
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft);
2557 const bool overlapAny =
overlap(rightNoOverlap, leftNoOverlap, foeRight, foeLeft);
2558#ifdef DEBUG_BLOCKING
2560 std::cout <<
" foe=" << vehDist.first->getID()
2561 <<
" gap=" << vehDist.second
2563 <<
" foeRight=" << foeRight
2564 <<
" foeLeft=" << foeLeft
2565 <<
" overlapBefore=" << overlapBefore
2566 <<
" overlap=" << overlapAny
2567 <<
" overlapDest=" << overlapDest
2572 if (vehDist.second < 0) {
2573 if (overlapBefore && !overlapDest && !
outsideEdge()) {
2574#ifdef DEBUG_BLOCKING
2576 std::cout <<
" ignoring current overlap to come clear\n";
2580#ifdef DEBUG_BLOCKING
2586 if (collectBlockers ==
nullptr) {
2589 collectBlockers->push_back(vehDist);
2605 const double expectedGap =
MSCFModel::gapExtrapolation(timeTillAction, vehDist.second, leader->
getSpeed(), follower->
getSpeed(), leaderAccel, followerAccel, std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
2608 const double followerExpectedSpeed = follower->
getSpeed() + timeTillAction * followerAccel;
2609 const double leaderExpectedSpeed =
MAX2(0., leader->
getSpeed() + timeTillAction * leaderAccel);
2612#if defined(DEBUG_ACTIONSTEPS) && defined(DEBUG_BLOCKING)
2614 std::cout <<
" timeTillAction=" << timeTillAction
2615 <<
" followerAccel=" << followerAccel
2616 <<
" followerExpectedSpeed=" << followerExpectedSpeed
2617 <<
" leaderAccel=" << leaderAccel
2618 <<
" leaderExpectedSpeed=" << leaderExpectedSpeed
2619 <<
"\n gap=" << vehDist.second
2620 <<
" gapChange=" << (expectedGap - vehDist.second)
2621 <<
" expectedGap=" << expectedGap
2622 <<
" expectedSecureGap=" << expectedSecureGap
2623 <<
" safeLatGapLeft=" << safeLatGapLeft
2624 <<
" safeLatGapRight=" << safeLatGapRight
2631 if (expectedGap < secureGap2) {
2633 if (foeRight > leftVehSide) {
2634 safeLatGapLeft =
MIN2(safeLatGapLeft, foeRight - leftVehSide);
2635 }
else if (foeLeft < rightVehSide) {
2636 safeLatGapRight =
MIN2(safeLatGapRight, rightVehSide - foeLeft);
2639#ifdef DEBUG_BLOCKING
2641 std::cout <<
" blocked by " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2642 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor()
2643 <<
" safeLatGapLeft=" << safeLatGapLeft <<
" safeLatGapRight=" << safeLatGapRight
2647 result |= blockType;
2648 if (collectBlockers ==
nullptr) {
2651#ifdef DEBUG_BLOCKING
2652 }
else if (
gDebugFlag2 && expectedGap < expectedSecureGap) {
2653 std::cout <<
" ignore blocker " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2654 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor() <<
"\n";
2657 if (collectBlockers !=
nullptr) {
2660 collectBlockers->push_back(vehDist);
2677 const double leftVehSide = rightVehSide + vehWidth;
2678#ifdef DEBUG_BLOCKING
2680 std::cout <<
" updateCFRelated foeOffset=" << foeOffset <<
" vehicles=" << vehicles.
toString() <<
"\n";
2683 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2685 if (vehDist.first != 0 && (
myCFRelated.count(vehDist.first) == 0 || vehDist.second < 0)) {
2686 double foeRight, foeLeft;
2688#ifdef DEBUG_BLOCKING
2690 std::cout <<
" foe=" << vehDist.first->getID() <<
" gap=" << vehDist.second
2692 <<
" foeOffset=" << foeOffset
2693 <<
" egoR=" << rightVehSide <<
" egoL=" << leftVehSide
2694 <<
" iR=" << foeRight <<
" iL=" << foeLeft
2700 if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft) && !
outsideEdge() && (vehDist.second >= 0
2706 && -vehDist.second < vehDist.first->getVehicleType().getMinGap()
2709#ifdef DEBUG_BLOCKING
2711 std::cout <<
" ignoring cfrelated foe=" << vehDist.first->getID() <<
"\n";
2716 const int erased = (int)
myCFRelated.erase(vehDist.first);
2717#ifdef DEBUG_BLOCKING
2719 std::cout <<
" restoring cfrelated foe=" << vehDist.first->getID() <<
"\n";
2732 assert(right <= left);
2733 assert(right2 <= left2);
2734 return left2 >= right + NUMERICAL_EPS && left >= right2 + NUMERICAL_EPS;
2755 return changeReason;
2762 if (sd1.
state == 0) {
2764 }
else if (sd2.
state == 0) {
2774#ifdef DEBUG_DECISION
2780 <<
" dir1=" << sd1.
dir
2784 <<
" dir2=" << sd2.
dir
2800 if (reason1 < reason2) {
2802 return (!can1 && can2 && sd1.
sameDirection(sd2)) ? sd2 : sd1;
2804 }
else if (reason1 > reason2) {
2806 return (!can2 && can1 && sd1.
sameDirection(sd2)) ? sd1 : sd2;
2814 }
else if (sd2.
dir == 0) {
2819 assert(sd1.
dir == -1);
2820 assert(sd2.
dir == 1);
2823 }
else if (sd2.
latDist >= 0) {
2879 double& currentDist,
2882 double roundaboutBonus,
2887 const bool right = (laneOffset == -1);
2888 const bool left = (laneOffset == 1);
2891 if (laneOffset != 0) {
2897 const double neighLeftPlace =
MAX2(0., neighDist - forwardPos - maxJam);
2901#ifdef DEBUG_STRATEGIC_CHANGE
2905 <<
" forwardPos=" << forwardPos
2907 <<
" laDist=" << laDist
2908 <<
" currentDist=" << currentDist
2909 <<
" usableDist=" << usableDist
2910 <<
" bestLaneOffset=" << bestLaneOffset
2911 <<
" best.length=" << best.
length
2912 <<
" maxJam=" << maxJam
2913 <<
" neighLeftPlace=" << neighLeftPlace
2920 if (laneOffset == 0) {
2927#ifdef DEBUG_STRATEGIC_CHANGE
2929 std::cout <<
SIMTIME <<
" returnToLaneBounds\n";
2938 if (link !=
nullptr &&
getWidth() < next->
getWidth() && distOnLane < 100) {
2944 latDist = -rightVehSide;
2947#ifdef DEBUG_STRATEGIC_CHANGE
2954 latDist = -(leftVehSide - next->
getWidth());
2957#ifdef DEBUG_STRATEGIC_CHANGE
2966 }
else if (laneOffset != 0 && changeToBest && bestLaneOffset == curr.
bestLaneOffset
2969 if (!
mustOvertakeStopped(
false, neighLane, neighLeaders, leaders, forwardPos, neighDist, right, latLaneDist, currentDist, latDist)) {
2970 latDist = latLaneDist;
2972#ifdef DEBUG_STRATEGIC_CHANGE
2974 std::cout <<
SIMTIME <<
" mustChangeToBest\n";
2978#ifdef DEBUG_STRATEGIC_CHANGE
2980 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" avoidStoppedNeigh\n";
3000#ifdef DEBUG_STRATEGIC_CHANGE
3003 <<
" avoid overtaking on the right nv=" << nv->
getID()
3015 if (laneOffset != 0 &&
myStrategicParam >= 0 && noOpposites &&
mustOvertakeStopped(
true, neighLane, leaders, neighLeaders, forwardPos, neighDist, right, latLaneDist, currentDist, latDist)) {
3016#ifdef DEBUG_STRATEGIC_CHANGE
3018 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" mustOvertakeStopped\n";
3027 }
else if (!changeToBest && (
currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
3034#ifdef DEBUG_STRATEGIC_CHANGE
3036 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace <<
"\n";
3042 && bestLaneOffset == 0
3045 && roundaboutBonus == 0
3052#ifdef DEBUG_STRATEGIC_CHANGE
3054 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to leave the bestLane (neighDist=" << neighDist <<
")\n";
3059 && bestLaneOffset == 0
3065#ifdef DEBUG_STRATEGIC_CHANGE
3067 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to get stranded on the on-ramp of a highway\n";
3081 MSLane* shadowPrev =
nullptr;
3083 if (*it ==
nullptr) {
3087 if (shadow ==
nullptr || currentShadowDist >= requiredDist) {
3090 if (shadowPrev !=
nullptr) {
3093 currentShadowDist += shadow->
getLength();
3094 shadowPrev = shadow;
3095#ifdef DEBUG_STRATEGIC_CHANGE
3097 std::cout <<
" shadow=" << shadow->
getID() <<
" currentShadowDist=" << currentShadowDist <<
"\n";
3101#ifdef DEBUG_STRATEGIC_CHANGE
3103 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" currentShadowDist=" << currentShadowDist <<
" requiredDist=" << requiredDist <<
" overlap=" <<
overlap <<
"\n";
3106 if (currentShadowDist < requiredDist && currentShadowDist < usableDist) {
3109#ifdef DEBUG_STRATEGIC_CHANGE
3111 std::cout <<
" must change for shadowLane end latDist=" << latDist <<
" myLeftSpace=" <<
myLeftSpace <<
"\n";
3119#if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI)
3131 }
else if (((retTraCI &
LCA_RIGHT) != 0 && laneOffset < 0)
3132 || ((retTraCI &
LCA_LEFT) != 0 && laneOffset > 0)) {
3134 latDist = latLaneDist;
3137#if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI)
3148 double posOnLane,
double neighDist,
bool right,
double latLaneDist,
double& currentDist,
double& latDist) {
3149 bool mustOvertake =
false;
3154 const bool curHasStopped = stoppedLeader !=
nullptr;
3155 const int dir = latLaneDist < 0 ? -1 : 1;
3159 if (curHasStopped) {
3161 for (
int i = rightmost; i <= leftmost; i++) {
3165 const double remaining =
MIN2(neighDist, currentDist) - posOnLane;
3166#ifdef DEBUG_STRATEGIC_CHANGE
3168 std::cout <<
" overtakeDist=" << overtakeDist <<
" remaining=" << remaining
3170 <<
" hasLaneBeyond=" << hasLaneBeyond
3175 remaining > overtakeDist
3177 && (!checkCurrent || !checkOverTakeRight || !right)
3186 latDist = latLaneDist;
3187 mustOvertake =
true;
3188#ifdef DEBUG_STRATEGIC_CHANGE
3190 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" overtake stopped leader=" << leader.first->getID()
3191 <<
" newCurrentDist=" << currentDist
3192 <<
" overtakeDist=" << overtakeDist
3193 <<
" remaining=" << remaining
3209 mustOvertake =
true;
3210 if (i >= rightmost && i <= leftmost) {
3217 return mustOvertake;
3238 double& maneuverDist,
3274 const double oldLatDist = latDist;
3275 const double oldManeuverDist = maneuverDist;
3280 const double halfWidth =
getWidth() * 0.5;
3286 double surplusGapRight = oldCenter - halfWidth;
3287 double surplusGapLeft =
getLeftBorder(laneOffset != 0) - oldCenter - halfWidth;
3288 const bool stayInLane = (laneOffset == 0
3292 && (surplusGapLeft >= 0 && surplusGapRight >= 0)));
3295 std::swap(surplusGapLeft, surplusGapRight);
3297#ifdef DEBUG_KEEP_LATGAP
3299 std::cout <<
"\n " <<
SIMTIME <<
" keepLatGap() laneOffset=" << laneOffset
3300 <<
" latDist=" << latDist
3301 <<
" maneuverDist=" << maneuverDist
3305 <<
" gapFactor=" << gapFactor
3306 <<
" stayInLane=" << stayInLane <<
"\n"
3307 <<
" stayInEdge: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
3311 if (surplusGapLeft < 0 || surplusGapRight < 0) {
3321 if (laneOffset != 0) {
3324 updateGaps(neighLeaders, neighRight, oldCenter, gapFactor, surplusGapRight, surplusGapLeft,
true);
3325 updateGaps(neighFollowers, neighRight, oldCenter, gapFactor, surplusGapRight, surplusGapLeft,
true, netOverlap);
3327#ifdef DEBUG_KEEP_LATGAP
3329 std::cout <<
" minGapLat: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n"
3339 if (stayInLane || laneOffset == 1) {
3342 surplusGapRight =
MIN2(surplusGapRight,
MAX2(0.0, halfLaneWidth + posLat - halfWidth));
3343 physicalGapRight =
MIN2(physicalGapRight,
MAX2(0.0, halfLaneWidth + posLat - halfWidth));
3345 if (stayInLane || laneOffset == -1) {
3348 surplusGapLeft =
MIN2(surplusGapLeft,
MAX2(0.0, halfLaneWidth - posLat - halfWidth));
3349 physicalGapLeft =
MIN2(physicalGapLeft,
MAX2(0.0, halfLaneWidth - posLat - halfWidth));
3351#ifdef DEBUG_KEEP_LATGAP
3353 std::cout <<
" stayInLane: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
3357 if (surplusGapRight + surplusGapLeft < 0) {
3362 const double equalDeficit = 0.5 * (surplusGapLeft + surplusGapRight);
3363 if (surplusGapRight < surplusGapLeft) {
3365 const double delta =
MIN2(equalDeficit - surplusGapRight, physicalGapLeft);
3367 maneuverDist = delta;
3368#ifdef DEBUG_KEEP_LATGAP
3370 std::cout <<
" insufficient latSpace, move left: delta=" << delta <<
"\n";
3375 const double delta =
MIN2(equalDeficit - surplusGapLeft, physicalGapRight);
3377 maneuverDist = -delta;
3378#ifdef DEBUG_KEEP_LATGAP
3380 std::cout <<
" insufficient latSpace, move right: delta=" << delta <<
"\n";
3386 latDist =
MAX2(
MIN2(latDist, surplusGapLeft), -surplusGapRight);
3387 maneuverDist =
MAX2(
MIN2(maneuverDist, surplusGapLeft), -surplusGapRight);
3388 if ((state &
LCA_KEEPRIGHT) != 0 && maneuverDist != oldManeuverDist) {
3390 latDist = oldLatDist;
3391 maneuverDist = oldManeuverDist;
3393#ifdef DEBUG_KEEP_LATGAP
3395 std::cout <<
" adapted latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
" (old=" << oldLatDist <<
")\n";
3410#ifdef DEBUG_KEEP_LATGAP
3412 std::cout <<
" traci influenced latDist=" << latDist <<
"\n";
3418 const bool traciChange = ((state | traciState) &
LCA_TRACI) != 0;
3419 if (nonSublaneChange && !traciChange) {
3421#ifdef DEBUG_KEEP_LATGAP
3423 std::cout <<
" wanted changeToLeft oldLatDist=" << oldLatDist <<
", blocked latGap changeToRight\n";
3426 latDist = oldLatDist;
3429#ifdef DEBUG_KEEP_LATGAP
3431 std::cout <<
" wanted changeToRight oldLatDist=" << oldLatDist <<
", blocked latGap changeToLeft\n";
3434 latDist = oldLatDist;
3444#ifdef DEBUG_KEEP_LATGAP
3446 std::cout <<
" latDistUpdated=" << latDist <<
" oldLatDist=" << oldLatDist <<
"\n";
3449 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset, leaders, followers, blockers, neighLeaders, neighFollowers, neighBlockers,
nullptr,
nullptr, nonSublaneChange);
3452 state = (state & ~LCA_STAY);
3463#if defined(DEBUG_KEEP_LATGAP) || defined(DEBUG_STATE)
3465 std::cout <<
" latDist2=" << latDist
3479 double& surplusGapRight,
double& surplusGapLeft,
3480 bool saveMinGap,
double netOverlap,
3482 std::vector<CLeaderDist>* collectBlockers) {
3484 const double halfWidth =
getWidth() * 0.5 + NUMERICAL_EPS;
3487 if (others[i].first != 0 && others[i].second <= 0
3489 && (netOverlap == 0 || others[i].second + others[i].first->getVehicleType().getMinGap() < netOverlap)) {
3493 double foeRight, foeLeft;
3495 const double foeCenter = foeRight + 0.5 * res;
3496 const double gap =
MIN2(fabs(foeRight - oldCenter), fabs(foeLeft - oldCenter)) - halfWidth;
3499 const double currentMinGap = desiredMinGap * gapFactor;
3510#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3512 std::cout <<
" updateGaps"
3514 <<
" foe=" << foe->
getID()
3515 <<
" foeRight=" << foeRight
3516 <<
" foeLeft=" << foeLeft
3517 <<
" oldCenter=" << oldCenter
3518 <<
" gap=" << others[i].second
3519 <<
" latgap=" << gap
3520 <<
" currentMinGap=" << currentMinGap
3521 <<
" surplusGapRight=" << surplusGapRight
3522 <<
" surplusGapLeft=" << surplusGapLeft
3530 if (foeCenter < oldCenter) {
3532 surplusGapRight =
MIN3(surplusGapRight, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
3535 surplusGapLeft =
MIN3(surplusGapLeft, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
3538 if (foeCenter < oldCenter) {
3539#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3541 std::cout <<
" new minimum rightGap=" << gap <<
"\n";
3546#if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP)
3548 std::cout <<
" new minimum leftGap=" << gap <<
"\n";
3554 if (collectBlockers !=
nullptr) {
3556 if ((foeCenter < oldCenter && latDist < 0 && gap < (desiredMinGap - latDist))
3557 || (foeCenter > oldCenter && latDist > 0 && gap < (desiredMinGap + latDist))) {
3558 collectBlockers->push_back(others[i]);
3575 int currentDirection =
mySpeedLat >= 0 ? 1 : -1;
3576 int directionWish = latDist >= 0 ? 1 : -1;
3583 maxSpeedLat =
MIN2(maxSpeedLat, speedBound);
3587 maxSpeedLat =
MAX2(maxSpeedLat, speedBound);
3596 accelLat =
MAX2(accelLat, 2 * edgeOverlap);
3597 maxSpeedLat =
MAX2(maxSpeedLat, edgeOverlap);
3600#ifdef DEBUG_MANEUVER
3604 <<
" computeSpeedLat()"
3605 <<
" latDist=" << latDist
3606 <<
" maneuverDist=" << maneuverDist
3607 <<
" urgent=" << urgent
3609 <<
" currentDirection=" << currentDirection
3610 <<
" directionWish=" << directionWish
3612 <<
" maxSpeedLat=" << maxSpeedLat
3618 if (directionWish == 1) {
3632 if (maneuverDist * latDist > 0) {
3633 maneuverDist = fullLatDist;
3636#ifdef DEBUG_MANEUVER
3640 <<
" fullLatDist=" << fullLatDist
3641 <<
" speedAccel=" << speedAccel
3642 <<
" speedDecel=" << speedDecel
3643 <<
" speedBound=" << speedBound
3647 if (speedDecel * speedAccel <= 0 && (
3649 (latDist >= 0 && speedAccel >= speedBound && speedBound >= speedDecel)
3650 || (latDist <= 0 && speedAccel <= speedBound && speedBound <= speedDecel))) {
3652#ifdef DEBUG_MANEUVER
3654 std::cout <<
" computeSpeedLat a)\n";
3661#ifdef DEBUG_MANEUVER
3663 std::cout <<
" computeSpeedLat b)\n";
3670 if ((fabs(minDistAccel) < fabs(fullLatDist)) || (fabs(minDistAccel - fullLatDist) < NUMERICAL_EPS)) {
3671#ifdef DEBUG_MANEUVER
3673 std::cout <<
" computeSpeedLat c)\n";
3678#ifdef DEBUG_MANEUVER
3680 std::cout <<
" minDistAccel=" << minDistAccel <<
"\n";
3685 if ((fabs(minDistCurrent) < fabs(fullLatDist)) || (fabs(minDistCurrent - fullLatDist) < NUMERICAL_EPS)) {
3686#ifdef DEBUG_MANEUVER
3688 std::cout <<
" computeSpeedLat d)\n";
3695#ifdef DEBUG_MANEUVER
3697 std::cout <<
" computeSpeedLat e)\n";
3709#ifdef DEBUG_MANEUVER
3711 std::cout <<
" rightDanger speedLat=" << speedLat <<
"\n";
3716#ifdef DEBUG_MANEUVER
3718 std::cout <<
" leftDanger speedLat=" << speedLat <<
"\n";
3733 const bool indirect = turnInfo.second ==
nullptr ? false : turnInfo.second->isIndirect();
3766 double maneuverDist) {
3769 double secondsToLeaveLane;
3779#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3795 double nextLeftSpace;
3796 if (nextActionStepSpeed > 0.) {
3811#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3815 <<
" avoidArrivalSpeed=" << avoidArrivalSpeed
3818 <<
"\n nextLeftSpace=" << nextLeftSpace
3819 <<
" nextActionStepSpeed=" << nextActionStepSpeed
3820 <<
" nextActionStepRemainingSeconds=" << secondsToLeaveLane - timeTillActionStep
3830#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3834 <<
" secondsToLeave=" << secondsToLeaveLane
3856 const double vehWidth =
getWidth();
3858 const double leftVehSide = rightVehSide + vehWidth;
3859 const double rightVehSideDest = rightVehSide + latDist;
3860 const double leftVehSideDest = leftVehSide + latDist;
3861#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3863 std::cout <<
" commitFollowSpeed"
3864 <<
" latDist=" << latDist
3865 <<
" foeOffset=" << foeOffset
3866 <<
" vehRight=" << rightVehSide
3867 <<
" vehLeft=" << leftVehSide
3868 <<
" destRight=" << rightVehSideDest
3869 <<
" destLeft=" << leftVehSideDest
3875 if (vehDist.first != 0) {
3876 const MSVehicle* leader = vehDist.first;
3878 double foeRight, foeLeft;
3880#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3882 std::cout <<
" foe=" << vehDist.first->getID()
3883 <<
" gap=" << vehDist.second
3885 <<
" foeRight=" << foeRight
3886 <<
" foeLeft=" << foeLeft
3887 <<
" overlapBefore=" <<
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)
3888 <<
" overlapDest=" <<
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)
3892 if (
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)) {
3896 speed =
MIN2(speed, vSafe);
3897#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3899 std::cout <<
" case1 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3902 }
else if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)) {
3907 speed =
MIN2(speed, vSafe);
3908#if defined(DEBUG_MANEUVER) || defined(DEBUG_COMMITTED_SPEED)
3910 std::cout <<
" case2 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3930 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 /
myOppositeParam;
3989 }
else if (key ==
"speedGainProbabilityRight") {
3991 }
else if (key ==
"speedGainProbabilityLeft") {
3993 }
else if (key ==
"keepRightProbability") {
3995 }
else if (key ==
"lookAheadSpeed") {
3997 }
else if (key ==
"sigmaState") {
4000 }
else if (key ==
"speedGainRP") {
4002 }
else if (key ==
"speedGainLP") {
4004 }
else if (key ==
"keepRightP") {
4074 }
else if (key ==
"speedGainProbabilityRight") {
4076 }
else if (key ==
"speedGainProbabilityLeft") {
4078 }
else if (key ==
"keepRightProbability") {
4080 }
else if (key ==
"lookAheadSpeed") {
4082 }
else if (key ==
"sigmaState") {
4096 const std::pair<MSVehicle*, double>& leader,
4097 const std::pair<MSVehicle*, double>& follower,
4098 const std::pair<MSVehicle*, double>& neighLead,
4099 const std::pair<MSVehicle*, double>& neighFollow,
4101 const std::vector<MSVehicle::LaneQ>& preb,
4107#ifdef DEBUG_WANTSCHANGE
4109 std::cout <<
"\nWANTS_CHANGE\n" <<
SIMTIME
4113 <<
" neigh=" << neighLane.
getID()
4117 <<
" considerChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
4131 double maneuverDist;
4134 leaders, followers, blockers,
4135 neighLeaders, neighFollowers, neighBlockers,
4137 lastBlocked, firstBlocked, latDist, maneuverDist, blocked);
4141 result &= ~LCA_SUBLANE;
4142 result |=
getLCA(result, latDist);
4144#if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE)
4149 <<
" wantsChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
4150 << ((result &
LCA_URGENT) ?
" (urgent)" :
"")
4156 << ((result &
LCA_TRACI) ?
" (traci)" :
"")
4208 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
double getCooperativeHelpTime() const
bool hasBlueLight() const
double getPreviousManeuverDist() const
double getCooperativeHelpThreshold() 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
bool canOvertakeRight(const MSVehicle *const nv, const double dist, const double maxSpeedDiff, const double helpOvertakeSpeed, double &vSafe, double &deltaV) const
void addLCSpeedAdvice(const double vSafe, bool ownAdvice=true)
Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration ...
int & getCanceledState(const int dir)
double myMaxSpeedLatFactor
const LaneChangeModel myModel
the type of this model
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
std::vector< std::pair< double, bool > > myLCAccelerationAdvices
virtual bool avoidOvertakeRight(const MSVehicle *const neighLeader, const bool allowProb=false) const
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 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
static const MSVehicle * getStopped(const MSLeaderDistanceInfo &ldi)
get a stopped vehicle in the given info
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
const std::vector< const MSVehicle * > & getVehicles() 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.