37 #define MAGIC_OFFSET 1. 38 #define LOOK_FORWARD (double)10. 40 #define JAM_FACTOR (double)1. 43 #define LCA_RIGHT_IMPATIENCE (double)-1. 44 #define CUT_IN_LEFT_SPEED_THRESHOLD (double)27. 45 #define MAX_ONRAMP_LENGTH (double)200. 47 #define LOOK_AHEAD_MIN_SPEED 0.0 48 #define LOOK_AHEAD_SPEED_MEMORY 0.9 50 #define HELP_DECEL_FACTOR (double)1.0 52 #define HELP_OVERTAKE (double)(10.0 / 3.6) 53 #define MIN_FALLBEHIND (double)(7.0 / 3.6) 55 #define KEEP_RIGHT_HEADWAY (double)2.0 57 #define URGENCY (double)2.0 59 #define ROUNDABOUT_DIST_BONUS (double)100.0 61 #define KEEP_RIGHT_TIME (double)5.0 // the number of seconds after which a vehicle should move to the right lane 62 #define KEEP_RIGHT_ACCEPTANCE (double)7.0 // calibration factor for determining the desire to keep right 64 #define RELGAIN_NORMALIZATION_MIN_SPEED (double)10.0 66 #define TURN_LANE_DIST (double)200.0 // the distance at which a lane leading elsewhere is considered to be a turn-lane that must be avoided 67 #define GAIN_PERCEPTION_THRESHOLD 0.05 // the minimum relative speed gain which affects the behavior 69 #define SPEED_GAIN_MIN_SECONDS 20.0 71 #define ARRIVALPOS_LAT_THRESHOLD 100.0 74 #define LATGAP_SPEED_THRESHOLD (50 / 3.6) 77 #define LATGAP_SPEED_THRESHOLD2 (50 / 3.6) 80 #define SPEEDGAIN_DECAY_FACTOR 0.5 82 #define SPEEDGAIN_MEMORY_FACTOR 0.5 107 #define DEBUG_COND (myVehicle.isSelected()) 119 mySpeedGainProbabilityRight(0),
120 mySpeedGainProbabilityLeft(0),
121 myKeepRightProbability(0),
122 myLeadingBlockerLength(0),
126 myCanChangeFully(true),
127 mySafeLatDistRight(0),
128 mySafeLatDistLeft(0),
137 v.getVehicleType().getMinGapLat()) /
138 v.getVehicleType().getMinGapLat()))),
141 myMinImpatience(myImpatience),
180 const std::vector<MSVehicle::LaneQ>& preb,
183 double& latDist,
double& maneuverDist,
int& blocked) {
186 const std::string changeType = laneOffset == -1 ?
"right" : (laneOffset == 1 ?
"left" :
"current");
188 #ifdef DEBUG_MANEUVER 197 <<
" considerChangeTo=" << changeType
204 leaders, followers, blockers,
205 neighLeaders, neighFollowers, neighBlockers,
207 lastBlocked, firstBlocked, latDist, maneuverDist, blocked);
209 result =
keepLatGap(result, leaders, followers, blockers,
210 neighLeaders, neighFollowers, neighBlockers,
211 neighLane, laneOffset, latDist, maneuverDist, blocked);
213 result |=
getLCA(result, latDist);
215 #if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE) 216 double latDistTmp = latDist;
219 #if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE) 221 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" maneuverDist=" << maneuverDist <<
" latDist=" << latDistTmp <<
" mySpeedPrev=" <<
mySpeedLat <<
" speedLat=" <<
DIST2SPEED(latDist) <<
" latDist2=" << latDist <<
"\n";
228 <<
" wantsChangeTo=" << changeType
229 <<
" latDist=" << latDist
230 <<
" maneuverDist=" << maneuverDist
238 <<
" wantsNoChangeTo=" << changeType
296 const double newSpeed =
_patchSpeed(
MAX2(min, 0.0), wanted, max, cfModel);
297 #ifdef DEBUG_PATCHSPEED 299 const std::string patched = (wanted != newSpeed ?
" patched=" +
toString(newSpeed) :
"");
306 <<
" wanted=" << wanted
329 #ifdef DEBUG_PATCHSPEED 339 #ifdef DEBUG_PATCHSPEED 341 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" slowing down for leading blocker, safe=" << safe << (safe +
NUMERICAL_EPS < min ?
" (not enough)" :
"") <<
"\n";
344 return MAX2(min, safe);
348 double nVSafe = wanted;
352 if (v >= min && v <= max) {
353 nVSafe =
MIN2(v, nVSafe);
355 #ifdef DEBUG_PATCHSPEED 357 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" got accel=" << (*i) <<
" nVSafe=" << nVSafe <<
"\n";
361 #ifdef DEBUG_PATCHSPEED 364 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring low nVSafe=" << v <<
" min=" << min <<
"\n";
368 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" ignoring high nVSafe=" << v <<
" max=" << max <<
"\n";
376 #ifdef DEBUG_PATCHSPEED 389 #if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE) 394 return (max + wanted) / (double) 2.0;
398 #if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE) 403 return (min + wanted) / (double) 2.0;
406 #if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE) 411 return (max + wanted) / (double) 2.0;
452 #if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE) 457 return (max + wanted) / (double) 2.0;
461 #if defined(DEBUG_PATCHSPEED) || defined(DEBUG_STATE) 481 if (pinfo->first >= 0) {
490 <<
" informedBy=" << sender->
getID()
491 <<
" info=" << pinfo->second
492 <<
" vSafe=" << pinfo->first
505 assert(cld.first != 0);
514 double remainingSeconds) {
520 plannedSpeed =
MIN2(plannedSpeed, v);
525 std::cout <<
" informLeader speed=" <<
myVehicle.
getSpeed() <<
" planned=" << plannedSpeed <<
"\n";
532 if (
gDebugFlag2) std::cout <<
" blocked by leader nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap=" 536 const double dv = plannedSpeed - nv->
getSpeed();
537 const double overtakeDist = (neighLead.second
549 || dv * remainingSeconds < overtakeDist) {
564 <<
" cannot overtake leader nv=" << nv->
getID()
566 <<
" remainingSeconds=" << remainingSeconds
567 <<
" targetSpeed=" << targetSpeed
568 <<
" nextSpeed=" << nextSpeed
579 <<
" cannot overtake fast leader nv=" << nv->
getID()
581 <<
" remainingSeconds=" << remainingSeconds
582 <<
" targetSpeed=" << targetSpeed
593 <<
" wants to overtake leader nv=" << nv->
getID()
595 <<
" remainingSeconds=" << remainingSeconds
596 <<
" currentGap=" << neighLead.second
598 <<
" overtakeDist=" << overtakeDist
608 }
else if (neighLead.first != 0) {
611 double dv, nextNVSpeed;
631 std::cout <<
" not blocked by leader nv=" << nv->
getID()
633 <<
" gap=" << neighLead.second
634 <<
" nextGap=" << neighLead.second - dv
636 <<
" targetSpeed=" << targetSpeed
640 return MIN2(targetSpeed, plannedSpeed);
652 double remainingSeconds,
653 double plannedSpeed) {
657 if (
gDebugFlag2) std::cout <<
" blocked by follower nv=" << nv->
getID() <<
" nvSpeed=" << nv->
getSpeed() <<
" needGap=" 664 if ((neededGap - neighFollow.second) / remainingSeconds < (plannedSpeed - nv->
getSpeed())) {
667 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" without any help neededGap=" << neededGap <<
"\n";
686 const double neighNewSpeed1s =
MAX2(0., nv->
getSpeed() - helpDecel);
687 const double dv = plannedSpeed - neighNewSpeed1s;
689 const double decelGap = neighFollow.second + dv;
695 <<
" egoNV=" << plannedSpeed
696 <<
" nvNewSpeed=" << neighNewSpeed
697 <<
" nvNewSpeed1s=" << neighNewSpeed1s
698 <<
" deltaGap=" << dv
699 <<
" decelGap=" << decelGap
700 <<
" secGap=" << secureGap
704 if (decelGap > 0 && decelGap >= secureGap) {
719 std::cout <<
" wants to cut in before nv=" << nv->
getID()
720 <<
" vsafe1=" << vsafe1
721 <<
" vsafe=" << vsafe
726 }
else if (dv > 0 && dv * remainingSeconds > (secureGap - decelGap +
POSITION_EPS)) {
731 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (eventually)\n";
739 std::cout <<
" wants to cut in before nv=" << nv->
getID() <<
" (nv cannot overtake right)\n";
755 std::cout <<
" wants right follower to slow down a bit\n";
761 std::cout <<
" wants to cut in before right follower nv=" << nv->
getID() <<
" (eventually)\n";
770 const double overtakeDist = (neighFollow.second
776 const double needDV = overtakeDist / remainingSeconds;
784 <<
" wants to be overtaken by=" << nv->
getID()
785 <<
" overtakeDist=" << overtakeDist
787 <<
" vhelp=" << vhelp
788 <<
" needDV=" << needDV
794 }
else if (neighFollow.first != 0) {
804 std::cout <<
" wants to cut in before non-blocking follower nv=" << nv->
getID() <<
"\n";
812 const std::vector<CLeaderDist>& blockers,
813 double remainingSeconds) {
820 plannedSpeed =
MIN2(plannedSpeed, safe);
823 for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
824 plannedSpeed =
MIN2(plannedSpeed,
informLeader(blocked, dir, *it, remainingSeconds));
832 const std::vector<CLeaderDist>& blockers,
833 double remainingSeconds,
834 double plannedSpeed) {
836 for (std::vector<CLeaderDist>::const_iterator it = blockers.begin(); it != blockers.end(); ++it) {
837 informFollower(blocked, dir, *it, remainingSeconds, plannedSpeed);
865 const double halfWidth =
getWidth() * 0.5;
875 std::vector<double> newExpectedSpeeds;
884 const std::vector<MSLane*>& lanes = currEdge->
getLanes();
885 for (std::vector<MSLane*>::const_iterator it_lane = lanes.begin(); it_lane != lanes.end(); ++it_lane) {
887 for (
int i = 0; i < subLanes; ++i) {
888 newExpectedSpeeds.push_back((*it_lane)->getVehicleMaxSpeed(&
myVehicle));
896 if (subLaneShift < std::numeric_limits<int>::max()) {
898 const int newI = i + subLaneShift;
899 if (newI > 0 && newI < (
int)newExpectedSpeeds.size()) {
917 const std::vector<MSLane*>& lanes = prevEdge->
getLanes();
918 for (std::vector<MSLane*>::const_iterator it_lane = lanes.begin(); it_lane != lanes.end(); ++it_lane) {
919 const MSLane* lane = *it_lane;
920 for (MSLinkCont::const_iterator it_link = lane->
getLinkCont().begin(); it_link != lane->
getLinkCont().end(); ++it_link) {
921 if (&((*it_link)->getLane()->getEdge()) == curEdge) {
923 const MSLane* target = (*it_link)->getLane();
924 const std::vector<MSLane*>& lanes2 = curEdge->
getLanes();
925 for (std::vector<MSLane*>::const_iterator it_lane2 = lanes2.begin(); it_lane2 != lanes2.end(); ++it_lane2) {
926 const MSLane* lane2 = *it_lane2;
927 if (lane2 == target) {
928 return prevShift + curShift;
939 return std::numeric_limits<int>::max();
969 #if defined(DEBUG_MANEUVER) || defined(DEBUG_STATE) 988 const std::vector<MSVehicle::LaneQ>& preb,
991 double& latDist,
double& maneuverDist,
int& blocked) {
996 int bestLaneOffset = 0;
997 double currentDist = 0;
998 double neighDist = 0;
1005 for (
int p = 0; p < (int) preb.size(); ++p) {
1006 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1007 assert(p + laneOffset < (
int)preb.size());
1009 neigh = preb[p + laneOffset];
1010 currentDist = curr.
length;
1011 neighDist = neigh.
length;
1012 bestLaneOffset = curr.bestLaneOffset;
1014 if (bestLaneOffset == 0 && preb[p + laneOffset].bestLaneOffset == 0) {
1015 #ifdef DEBUG_WANTSCHANGE 1019 <<
" bestLaneOffsetOld=" << bestLaneOffset
1020 <<
" bestLaneOffsetNew=" << laneOffset
1024 bestLaneOffset = laneOffset;
1031 const bool right = (laneOffset == -1);
1032 const bool left = (laneOffset == 1);
1035 const bool changeToBest = (right && bestLaneOffset < 0) || (left && bestLaneOffset > 0) || (laneOffset == 0 && bestLaneOffset == 0);
1061 #ifdef DEBUG_WANTSCHANGE 1068 <<
"\n leaders=" << leaders.
toString()
1069 <<
"\n followers=" << followers.
toString()
1070 <<
"\n blockers=" << blockers.
toString()
1071 <<
"\n neighLeaders=" << neighLeaders.
toString()
1072 <<
"\n neighFollowers=" << neighFollowers.
toString()
1073 <<
"\n neighBlockers=" << neighBlockers.
toString()
1074 <<
"\n changeToBest=" << changeToBest
1075 <<
" latLaneDist=" << latLaneDist
1083 if (lastBlocked != firstBlocked) {
1143 int roundaboutEdgesAhead = 0;
1145 if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
1146 roundaboutEdgesAhead += 1;
1147 }
else if (roundaboutEdgesAhead > 0) {
1152 int roundaboutEdgesAheadNeigh = 0;
1154 if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
1155 roundaboutEdgesAheadNeigh += 1;
1156 }
else if (roundaboutEdgesAheadNeigh > 0) {
1161 if (roundaboutEdgesAhead > 1) {
1165 if (roundaboutEdgesAhead > 0) {
1166 #ifdef DEBUG_ROUNDABOUTS 1168 std::cout <<
" roundaboutEdgesAhead=" << roundaboutEdgesAhead <<
" roundaboutEdgesAheadNeigh=" << roundaboutEdgesAheadNeigh <<
"\n";
1173 if (laneOffset != 0) {
1185 roundaboutEdgesAhead,
1190 if ((ret &
LCA_STAY) != 0 && latDist == 0) {
1200 if (changeToBest && abs(bestLaneOffset) > 1
1205 #ifdef DEBUG_WANTSCHANGE 1207 std::cout <<
" reserving space for unseen blockers myLeadingBlockerLength=" <<
myLeadingBlockerLength <<
"\n";
1216 if (*firstBlocked != neighLeadLongest) {
1219 std::vector<CLeaderDist> collectLeadBlockers;
1220 std::vector<CLeaderDist> collectFollowBlockers;
1221 int blockedFully = 0;
1224 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1225 leaders, followers, blockers,
1226 neighLeaders, neighFollowers, neighBlockers, &collectLeadBlockers, &collectFollowBlockers,
1227 false, gapFactor, &blockedFully);
1229 const double absLaneOffset = fabs(bestLaneOffset != 0 ? bestLaneOffset : latDist /
SUMO_const_laneWidth);
1230 const double remainingSeconds = ((ret &
LCA_TRACI) == 0 ?
1233 const double plannedSpeed =
informLeaders(blocked, myLca, collectLeadBlockers, remainingSeconds);
1235 if (plannedSpeed >= 0) {
1237 informFollowers(blocked, myLca, collectFollowBlockers, remainingSeconds, plannedSpeed);
1239 if (plannedSpeed > 0) {
1240 commitManoeuvre(blocked, blockedFully, leaders, neighLeaders, neighLane, maneuverDist);
1242 #if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE) 1249 <<
" remainingSeconds=" << remainingSeconds
1250 <<
" plannedSpeed=" << plannedSpeed
1260 if (roundaboutEdgesAhead > 1) {
1269 if ((ret & LCA_STAY) == 0) {
1270 latDist = latLaneDist;
1271 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1272 leaders, followers, blockers,
1273 neighLeaders, neighFollowers, neighBlockers);
1288 const double inconvenience = (latLaneDist < 0
1300 && (changeToBest ||
currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1303 #ifdef DEBUG_COOPERATE 1310 <<
" wantsChangeToHelp=" << (right ?
"right" :
"left")
1320 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1321 leaders, followers, blockers,
1322 neighLeaders, neighFollowers, neighBlockers);
1346 const double vehWidth =
getWidth();
1348 const double leftVehSide = rightVehSide + vehWidth;
1350 double defaultNextSpeed = std::numeric_limits<double>::max();
1352 int leftmostOnEdge = (int)sublaneSides.size() - 1;
1353 while (leftmostOnEdge > 0 && sublaneSides[leftmostOnEdge] > leftVehSide) {
1356 int rightmostOnEdge = leftmostOnEdge;
1357 while (rightmostOnEdge > 0 && sublaneSides[rightmostOnEdge] > rightVehSide +
NUMERICAL_EPS) {
1359 #ifdef DEBUG_WANTSCHANGE 1361 std::cout <<
" adapted to current sublane=" << rightmostOnEdge <<
" defaultNextSpeed=" << defaultNextSpeed <<
"\n";
1362 std::cout <<
" sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] <<
" rightVehSide=" << rightVehSide <<
"\n";
1368 #ifdef DEBUG_WANTSCHANGE 1370 std::cout <<
" adapted to current sublane=" << rightmostOnEdge <<
" defaultNextSpeed=" << defaultNextSpeed <<
"\n";
1371 std::cout <<
" sublaneSides[rightmostOnEdge]=" << sublaneSides[rightmostOnEdge] <<
" rightVehSide=" << rightVehSide <<
"\n";
1374 double maxGain = -std::numeric_limits<double>::max();
1375 double maxGainRight = -std::numeric_limits<double>::max();
1376 double maxGainLeft = -std::numeric_limits<double>::max();
1377 double latDistNice = std::numeric_limits<double>::max();
1380 const double leftMax =
MAX2(
1383 assert(leftMax <= edge.
getWidth());
1384 int sublaneCompact =
MAX2(iMin, rightmostOnEdge - 1);
1386 #ifdef DEBUG_WANTSCHANGE 1388 <<
" checking sublanes rightmostOnEdge=" << rightmostOnEdge
1389 <<
" leftmostOnEdge=" << leftmostOnEdge
1391 <<
" leftMax=" << leftMax
1392 <<
" sublaneCompact=" << sublaneCompact
1395 for (
int i = iMin; i < (int)sublaneSides.size(); ++i) {
1396 if (sublaneSides[i] + vehWidth < leftMax) {
1402 while (vMin > 0 && j < (
int)sublaneSides.size() && sublaneSides[j] < sublaneSides[i] + vehWidth) {
1408 const double currentLatDist = sublaneSides[i] - rightVehSide;
1410 if (relativeGain > maxGain) {
1411 maxGain = relativeGain;
1414 latDist = currentLatDist;
1415 #ifdef DEBUG_WANTSCHANGE 1417 std::cout <<
" i=" << i <<
" newLatDist=" << latDist <<
" relGain=" << relativeGain <<
"\n";
1423 if (currentLatDist > 0
1428 latDist = currentLatDist;
1431 #ifdef DEBUG_WANTSCHANGE 1433 std::cout <<
" i=" << i <<
" rightmostOnEdge=" << rightmostOnEdge <<
" vMin=" << vMin <<
" relGain=" << relativeGain <<
" sublaneCompact=" << sublaneCompact <<
" curLatDist=" << currentLatDist <<
"\n";
1437 maxGainRight =
MAX2(maxGainRight, relativeGain);
1439 maxGainLeft =
MAX2(maxGainLeft, relativeGain);
1441 const double subAlignDist = sublaneSides[i] - rightVehSide;
1442 if (fabs(subAlignDist) < fabs(latDistNice)) {
1443 latDistNice = subAlignDist;
1444 #ifdef DEBUG_WANTSCHANGE 1446 <<
" nicest sublane=" << i
1447 <<
" side=" << sublaneSides[i]
1448 <<
" rightSide=" << rightVehSide
1449 <<
" latDistNice=" << latDistNice
1450 <<
" maxGainR=" << maxGainRight
1451 <<
" maxGainL=" << maxGainLeft
1458 if (maxGainRight != -std::numeric_limits<double>::max()) {
1459 #ifdef DEBUG_WANTSCHANGE 1465 #ifdef DEBUG_WANTSCHANGE 1471 if (maxGainLeft != -std::numeric_limits<double>::max()) {
1472 #ifdef DEBUG_WANTSCHANGE 1478 #ifdef DEBUG_WANTSCHANGE 1485 if ((fabs(maxGainRight) <
NUMERICAL_EPS || maxGainRight == -std::numeric_limits<double>::max())
1486 && (right || (alternatives &
LCA_RIGHT) == 0)) {
1489 if ((fabs(maxGainLeft) <
NUMERICAL_EPS || maxGainLeft == -std::numeric_limits<double>::max())
1490 && (left || (alternatives &
LCA_LEFT) == 0)) {
1495 #ifdef DEBUG_WANTSCHANGE 1498 <<
" defaultNextSpeed=" << defaultNextSpeed
1499 <<
" maxGain=" << maxGain
1500 <<
" maxGainRight=" << maxGainRight
1501 <<
" maxGainLeft=" << maxGainLeft
1502 <<
" latDist=" << latDist
1503 <<
" latDistNice=" << latDistNice
1504 <<
" sublaneCompact=" << sublaneCompact
1510 if (right && maxGain >= 0 && latDist <= 0) {
1517 double fullSpeedDrivingSeconds =
MIN2(acceptanceTime, fullSpeedGap / vMax);
1519 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1520 fullSpeedGap =
MAX2(0.,
MIN2(fullSpeedGap,
1522 vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1523 fullSpeedDrivingSeconds =
MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1528 #ifdef DEBUG_WANTSCHANGE 1531 <<
" considering keepRight:" 1533 <<
" neighDist=" << neighDist
1535 <<
" leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1537 myVehicle.
getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1538 <<
" acceptanceTime=" << acceptanceTime
1539 <<
" fullSpeedGap=" << fullSpeedGap
1540 <<
" fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1541 <<
" dProb=" << deltaProb
1552 latDist = latLaneDist;
1553 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1554 leaders, followers, blockers,
1555 neighLeaders, neighFollowers, neighBlockers);
1561 #ifdef DEBUG_WANTSCHANGE 1566 <<
" neighDist=" << neighDist
1569 <<
" latDist=" << latDist
1578 int blockedFully = 0;
1579 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1580 leaders, followers, blockers,
1581 neighLeaders, neighFollowers, neighBlockers,
1582 0, 0,
false, 0, &blockedFully);
1591 #ifdef DEBUG_WANTSCHANGE 1596 <<
" latDist=" << latDist
1597 <<
" neighDist=" << neighDist
1600 <<
" stayInLane=" << stayInLane
1611 int blockedFully = 0;
1612 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1613 leaders, followers, blockers,
1614 neighLeaders, neighFollowers, neighBlockers,
1615 0, 0,
false, 0, &blockedFully);
1624 double latDistSublane = 0.;
1626 const double halfVehWidth =
getWidth() * 0.5;
1629 && bestLaneOffset == 0
1649 #ifdef DEBUG_WANTSCHANGE 1663 switch (turnInfo.second) {
1692 latDistSublane = latDistNice;
1695 latDistSublane = sublaneSides[sublaneCompact] - rightVehSide;
1703 #if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE) || defined(DEBUG_MANEUVER) 1708 <<
" latDist=" << latDist
1709 <<
" latDistSublane=" << latDistSublane
1710 <<
" relGainSublane=" <<
computeSpeedGain(latDistSublane, defaultNextSpeed)
1711 <<
" maneuverDist=" << maneuverDist
1726 && ((myManeuverDist < 0 && latDistSublane > 0) || (
myManeuverDist > 0 && latDistSublane < 0))) {
1729 latDist = latDistSublane;
1734 #ifdef DEBUG_WANTSCHANGE 1737 <<
" latDist=" << latDist
1742 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset,
1743 leaders, followers, blockers,
1744 neighLeaders, neighFollowers, neighBlockers);
1771 #ifdef DEBUG_WANTSCHANGE 1788 if ((*blocked) != 0) {
1790 #ifdef DEBUG_SLOWDOWN 1814 (*blocked)->getCarFollowModel().getMaxDecel()));
1825 #ifdef DEBUG_SAVE_BLOCKER_LENGTH 1841 #ifdef DEBUG_SAVE_BLOCKER_LENGTH 1853 #ifdef DEBUG_SAVE_BLOCKER_LENGTH 1859 <<
" potential=" << potential
1875 <<
"vSafe=" << vSafe <<
" -> accel=" << accel <<
"\n";
1885 const MSLane* lane = lanes[laneIndex];
1887 assert(preb.size() == lanes.size());
1890 for (
int sublane = 0; sublane < (int)ahead.
numSublanes(); ++sublane) {
1891 const int edgeSublane = sublane + sublaneOffset;
1895 const MSVehicle* leader = ahead[sublane].first;
1896 const double gap = ahead[sublane].second;
1907 #ifdef DEBUG_EXPECTED_SLSPEED 1909 std::cout <<
SIMTIME <<
" veh=" <<
myVehicle.
getID() <<
" updateExpectedSublaneSpeeds edgeSublane=" << edgeSublane <<
" leader=" << leader->
getID() <<
" gap=" << gap <<
" vSafe=" << vSafe <<
"\n";
1912 const double deltaV = vMax - leader->
getSpeed();
1913 if (deltaV > 0 && gap / deltaV < 5) {
1922 double foeRight, foeLeft;
1926 if (leader.first != 0) {
1929 vSafe =
MIN2(vSafe, vSafePed);
1932 vSafe =
MIN2(vMax, vSafe);
1934 myExpectedSublaneSpeeds[edgeSublane] = memoryFactor * myExpectedSublaneSpeeds[edgeSublane] + (1 - memoryFactor) * vSafe;
1946 double result = std::numeric_limits<double>::max();
1949 const double vehWidth =
getWidth();
1951 const double leftVehSide = rightVehSide + vehWidth;
1952 for (
int i = 0; i < (int)sublaneSides.size(); ++i) {
1953 if (
overlap(rightVehSide, leftVehSide, sublaneSides[i], sublaneSides[i] + res)) {
1959 return result - defaultNextSpeed;
1966 double maxLength = -1;
1968 if (ldi[i].first != 0) {
1969 const double length = ldi[i].first->getVehicleType().getLength();
1970 if (length > maxLength) {
1983 double minSpeed = std::numeric_limits<double>::max();
1985 if (ldi[i].first != 0) {
1986 const double speed = ldi[i].first->getSpeed();
1987 if (speed < minSpeed) {
2005 std::vector<CLeaderDist>* collectLeadBlockers,
2006 std::vector<CLeaderDist>* collectFollowBlockers,
2007 bool keepLatGapManeuver,
2009 int* retBlockedFully) {
2011 if (!keepLatGapManeuver) {
2013 maneuverDist = latDist;
2016 latDist =
MAX2(
MIN2(latDist, maxDist), -maxDist);
2021 if (laneOffset != 0) {
2032 if (laneOffset != 0) {
2036 #ifdef DEBUG_BLOCKING 2038 std::cout <<
" checkBlocking latDist=" << latDist <<
" mySafeLatDistRight=" << mySafeLatDistRight <<
" mySafeLatDistLeft=" << mySafeLatDistLeft <<
"\n";
2046 latDist =
MAX2(latDist, -mySafeLatDistRight);
2052 latDist =
MIN2(latDist, mySafeLatDistLeft);
2057 #ifdef DEBUG_BLOCKING 2073 if (laneOffset != 0) {
2076 mySafeLatDistRight, mySafeLatDistLeft, collectLeadBlockers);
2079 mySafeLatDistRight, mySafeLatDistLeft, collectFollowBlockers);
2082 int blockedFully = 0;
2087 if (laneOffset != 0) {
2090 mySafeLatDistRight, mySafeLatDistLeft, collectLeadBlockers);
2093 mySafeLatDistRight, mySafeLatDistLeft, collectFollowBlockers);
2095 if (retBlockedFully != 0) {
2096 *retBlockedFully = blockedFully;
2103 blocked |= blockedFully;
2108 if (collectFollowBlockers != 0 && collectLeadBlockers != 0) {
2110 for (std::vector<CLeaderDist>::const_iterator it2 = collectLeadBlockers->begin(); it2 != collectLeadBlockers->end(); ++it2) {
2111 for (std::vector<CLeaderDist>::iterator it = collectFollowBlockers->begin(); it != collectFollowBlockers->end();) {
2112 if ((*it2).first == (*it).first) {
2113 #ifdef DEBUG_BLOCKING 2115 std::cout <<
" removed follower " << (*it).first->getID() <<
" because it is already a leader\n";
2118 it = collectFollowBlockers->erase(it);
2132 double latDist,
double foeOffset,
bool leaders,
LaneChangeAction blockType,
2133 double& safeLatGapRight,
double& safeLatGapLeft,
2134 std::vector<CLeaderDist>* collectBlockers)
const {
2136 const double vehWidth =
getWidth();
2138 const double leftVehSide = rightVehSide + vehWidth;
2139 const double rightVehSideDest = rightVehSide + latDist;
2140 const double leftVehSideDest = leftVehSide + latDist;
2141 const double rightNoOverlap =
MIN2(rightVehSideDest, rightVehSide);
2142 const double leftNoOverlap =
MAX2(leftVehSideDest, leftVehSide);
2143 #ifdef DEBUG_BLOCKING 2145 std::cout <<
" checkBlockingVehicles" 2146 <<
" latDist=" << latDist
2147 <<
" foeOffset=" << foeOffset
2148 <<
" vehRight=" << rightVehSide
2149 <<
" vehLeft=" << leftVehSide
2150 <<
" rightNoOverlap=" << rightNoOverlap
2151 <<
" leftNoOverlap=" << leftNoOverlap
2152 <<
" destRight=" << rightVehSideDest
2153 <<
" destLeft=" << leftVehSideDest
2154 <<
" leaders=" << leaders
2160 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2162 if (vehDist.first != 0 &&
myCFRelated.count(vehDist.first) == 0) {
2163 const MSVehicle* leader = vehDist.first;
2166 std::swap(leader, follower);
2169 double foeRight, foeLeft;
2171 const bool overlapBefore =
overlap(rightVehSide, leftVehSide, foeRight, foeLeft);
2172 const bool overlapDest =
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft);
2173 const bool overlapAny =
overlap(rightNoOverlap, leftNoOverlap, foeRight, foeLeft);
2174 #ifdef DEBUG_BLOCKING 2176 std::cout <<
" foe=" << vehDist.first->getID()
2177 <<
" gap=" << vehDist.second
2179 <<
" foeRight=" << foeRight
2180 <<
" foeLeft=" << foeLeft
2181 <<
" overlapBefore=" << overlapBefore
2182 <<
" overlap=" << overlapAny
2183 <<
" overlapDest=" << overlapDest
2188 if (vehDist.second < 0) {
2189 if (overlapBefore && !overlapDest) {
2190 #ifdef DEBUG_BLOCKING 2192 std::cout <<
" ignoring current overlap to come clear\n";
2196 #ifdef DEBUG_BLOCKING 2202 if (collectBlockers == 0) {
2205 collectBlockers->push_back(vehDist);
2221 const double expectedGap =
MSCFModel::gapExtrapolation(timeTillAction, vehDist.second, leader->
getSpeed(), follower->
getSpeed(), leaderAccel, followerAccel, std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
2224 const double followerExpectedSpeed = follower->
getSpeed() + timeTillAction * followerAccel;
2225 const double leaderExpectedSpeed =
MAX2(0., leader->
getSpeed() + timeTillAction * leaderAccel);
2228 #if defined(DEBUG_ACTIONSTEPS) && defined(DEBUG_BLOCKING) 2230 std::cout <<
" timeTillAction=" << timeTillAction
2231 <<
" followerAccel=" << followerAccel
2232 <<
" followerExpectedSpeed=" << followerExpectedSpeed
2233 <<
" leaderAccel=" << leaderAccel
2234 <<
" leaderExpectedSpeed=" << leaderExpectedSpeed
2235 <<
"\n gap=" << vehDist.second
2236 <<
" gapChange=" << (expectedGap - vehDist.second)
2237 <<
" expectedGap=" << expectedGap
2238 <<
" expectedSecureGap=" << expectedSecureGap
2239 <<
" safeLatGapLeft=" << safeLatGapLeft
2240 <<
" safeLatGapRight=" << safeLatGapRight
2247 if (expectedGap < secureGap2) {
2249 if (foeRight > leftVehSide) {
2250 safeLatGapLeft =
MIN2(safeLatGapLeft, foeRight - leftVehSide);
2251 }
else if (foeLeft < rightVehSide) {
2252 safeLatGapRight =
MIN2(safeLatGapRight, rightVehSide - foeLeft);
2255 #ifdef DEBUG_BLOCKING 2257 std::cout <<
" blocked by " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2258 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor()
2259 <<
" safeLatGapLeft=" << safeLatGapLeft <<
" safeLatGapRight=" << safeLatGapRight
2263 result |= blockType;
2264 if (collectBlockers == 0) {
2267 collectBlockers->push_back(vehDist);
2269 #ifdef DEBUG_BLOCKING 2270 }
else if (
gDebugFlag2 && expectedGap < expectedSecureGap) {
2271 std::cout <<
" ignore blocker " << vehDist.first->getID() <<
" gap=" << vehDist.second <<
" expectedGap=" << expectedGap
2272 <<
" expectedSecureGap=" << expectedSecureGap <<
" secGap2=" << secureGap2 <<
" safetyFactor=" <<
getSafetyFactor() <<
"\n";
2290 const double leftVehSide = rightVehSide + vehWidth;
2291 #ifdef DEBUG_BLOCKING 2293 std::cout <<
" updateCFRelated foeOffset=" << foeOffset <<
" vehicles=" << vehicles.
toString() <<
"\n";
2296 for (
int i = 0; i < vehicles.
numSublanes(); ++i) {
2298 if (vehDist.first != 0 &&
myCFRelated.count(vehDist.first) == 0) {
2299 double foeRight, foeLeft;
2301 if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft) && (vehDist.second >= 0
2307 && -vehDist.second < vehDist.first->getVehicleType().getMinGap()
2310 #ifdef DEBUG_BLOCKING 2312 std::cout <<
" ignoring cfrelated foe=" << vehDist.first->getID() <<
" gap=" << vehDist.second
2314 <<
" foeOffset=" << foeOffset
2315 <<
" egoR=" << rightVehSide <<
" egoL=" << leftVehSide
2316 <<
" iR=" << foeRight <<
" iL=" << foeLeft
2331 assert(right <= left);
2332 assert(right2 <= left2);
2340 if (sd1.
state == 0) {
2342 }
else if (sd2.
state == 0) {
2350 #ifdef DEBUG_WANTSCHANGE 2356 <<
" dir1=" << sd1.
dir 2360 <<
" dir2=" << sd2.
dir 2368 return (!can1 && can2 && sd1.
sameDirection(sd2)) ? sd2 : sd1;
2372 return (!can2 && can1 && sd1.
sameDirection(sd2)) ? sd1 : sd2;
2380 }
else if (sd2.
dir == 0) {
2385 assert(sd1.
dir == -1);
2386 assert(sd2.
dir == 1);
2389 }
else if (sd2.
latDist >= 0) {
2397 return can1 ? sd1 : sd2;
2420 const std::vector<MSVehicle::LaneQ>& preb,
2429 int roundaboutEdgesAhead,
2433 const bool right = (laneOffset == -1);
2434 const bool left = (laneOffset == 1);
2446 #ifdef DEBUG_STRATEGIC_CHANGE 2451 <<
" laDist=" << laDist
2452 <<
" currentDist=" << currentDist
2453 <<
" usableDist=" << usableDist
2454 <<
" bestLaneOffset=" << bestLaneOffset
2455 <<
" best.length=" << best.
length 2456 <<
" maxJam=" << maxJam
2457 <<
" neighLeftPlace=" << neighLeftPlace
2462 if (laneOffset != 0 && changeToBest && bestLaneOffset == curr.
bestLaneOffset 2465 latDist = latLaneDist;
2482 #ifdef DEBUG_STRATEGIC_CHANGE 2485 <<
" avoid overtaking on the right nv=" << nv->
getID()
2495 if (!changeToBest && (
currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
2502 #ifdef DEBUG_STRATEGIC_CHANGE 2504 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace <<
"\n";
2510 && bestLaneOffset == 0
2513 && roundaboutEdgesAhead == 0
2518 #ifdef DEBUG_STRATEGIC_CHANGE 2520 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to leave the bestLane (neighDist=" << neighDist <<
")\n";
2525 && bestLaneOffset == 0
2531 #ifdef DEBUG_STRATEGIC_CHANGE 2533 std::cout <<
" veh=" <<
myVehicle.
getID() <<
" does not want to get stranded on the on-ramp of a highway\n";
2552 if (shadow == 0 || currentShadowDist >= requiredDist) {
2555 currentShadowDist += shadow->
getLength();
2557 #ifdef DEBUG_STRATEGIC_CHANGE 2562 if (currentShadowDist < requiredDist && currentShadowDist < usableDist) {
2565 #ifdef DEBUG_STRATEGIC_CHANGE 2567 std::cout <<
" must change for shadowLane end latDist=" << latDist <<
" myLeftSpace=" <<
myLeftSpace <<
"\n";
2575 #if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI) 2587 }
else if (((retTraCI &
LCA_RIGHT) != 0 && laneOffset < 0)
2588 || ((retTraCI &
LCA_LEFT) != 0 && laneOffset > 0)) {
2590 latDist = latLaneDist;
2593 #if defined(DEBUG_STRATEGIC_CHANGE) || defined(DEBUG_TRACI) 2595 std::cout <<
" reqAfterInfluence=" << ret <<
" ret=" << ret <<
"\n";
2619 double& maneuverDist,
2655 const bool stayInLane = laneOffset == 0 || ((state &
LCA_STRATEGIC) != 0 && (state &
LCA_STAY) != 0);
2656 const double oldLatDist = latDist;
2659 const double halfWidth =
getWidth() * 0.5;
2665 double surplusGapRight = oldCenter - halfWidth;
2667 #ifdef DEBUG_KEEP_LATGAP 2669 std::cout <<
"\n " <<
SIMTIME <<
" keepLatGap() laneOffset=" << laneOffset
2670 <<
" latDist=" << latDist
2673 <<
" gapFactor=" << gapFactor
2674 <<
" stayInLane=" << stayInLane <<
"\n" 2675 <<
" stayInEdge: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
2679 if (surplusGapLeft < 0 || surplusGapRight < 0) {
2689 if (laneOffset != 0) {
2694 #ifdef DEBUG_KEEP_LATGAP 2696 std::cout <<
" minGapLat: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n" 2705 if (stayInLane || laneOffset == 1) {
2711 if (stayInLane || laneOffset == -1) {
2717 #ifdef DEBUG_KEEP_LATGAP 2719 std::cout <<
" stayInLane: surplusGapRight=" << surplusGapRight <<
" surplusGapLeft=" << surplusGapLeft <<
"\n";
2723 if (surplusGapRight + surplusGapLeft < 0) {
2728 const double equalDeficit = 0.5 * (surplusGapLeft + surplusGapRight);
2729 if (surplusGapRight < surplusGapLeft) {
2731 const double delta =
MIN2(equalDeficit - surplusGapRight, physicalGapLeft);
2733 maneuverDist = delta;
2734 #ifdef DEBUG_KEEP_LATGAP 2736 std::cout <<
" insufficient latSpace, move left: delta=" << delta <<
"\n";
2741 const double delta =
MIN2(equalDeficit - surplusGapLeft, physicalGapRight);
2743 maneuverDist = -delta;
2744 #ifdef DEBUG_KEEP_LATGAP 2746 std::cout <<
" insufficient latSpace, move right: delta=" << delta <<
"\n";
2752 latDist =
MAX2(
MIN2(latDist, surplusGapLeft), -surplusGapRight);
2753 maneuverDist =
MAX2(
MIN2(maneuverDist, surplusGapLeft), -surplusGapRight);
2754 #ifdef DEBUG_KEEP_LATGAP 2756 std::cout <<
" adapted latDist=" << latDist <<
" maneuverDist=" << maneuverDist <<
" (old=" << oldLatDist <<
")\n";
2766 #ifdef DEBUG_KEEP_LATGAP 2768 std::cout <<
" traci influenced latDist=" << latDist <<
"\n";
2774 if (nonSublaneChange) {
2776 #ifdef DEBUG_KEEP_LATGAP 2778 std::cout <<
" wanted changeToLeft oldLatDist=" << oldLatDist <<
", blocked latGap changeToRight\n";
2781 latDist = oldLatDist;
2784 #ifdef DEBUG_KEEP_LATGAP 2786 std::cout <<
" wanted changeToRight oldLatDist=" << oldLatDist <<
", blocked latGap changeToLeft\n";
2789 latDist = oldLatDist;
2799 #ifdef DEBUG_KEEP_LATGAP 2801 std::cout <<
" latDistUpdated=" << latDist <<
" oldLatDist=" << oldLatDist <<
"\n";
2804 blocked =
checkBlocking(neighLane, latDist, maneuverDist, laneOffset, leaders, followers, blockers, neighLeaders, neighFollowers, neighBlockers, 0, 0, nonSublaneChange);
2807 state = (state & ~LCA_STAY);
2818 #if defined(DEBUG_KEEP_LATGAP) || defined(DEBUG_STATE) 2820 std::cout <<
" latDist2=" << latDist
2834 double& surplusGapRight,
double& surplusGapLeft,
2835 bool saveMinGap,
double netOverlap,
2837 std::vector<CLeaderDist>* collectBlockers) {
2842 if (others[i].first != 0 && others[i].second <= 0
2844 && (netOverlap == 0 || others[i].second + others[i].first->getVehicleType().getMinGap() < netOverlap)) {
2848 double foeRight, foeLeft;
2850 const double foeCenter = foeRight + 0.5 * res;
2851 const double gap =
MIN2(fabs(foeRight - oldCenter), fabs(foeLeft - oldCenter)) - halfWidth;
2854 const double currentMinGap = desiredMinGap * gapFactor;
2865 #if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP) 2867 std::cout <<
" updateGaps" 2869 <<
" foe=" << foe->
getID()
2870 <<
" foeRight=" << foeRight
2871 <<
" foeLeft=" << foeLeft
2872 <<
" oldCenter=" << oldCenter
2873 <<
" gap=" << others[i].second
2874 <<
" latgap=" << gap
2875 <<
" currentMinGap=" << currentMinGap
2876 <<
" surplusGapRight=" << surplusGapRight
2877 <<
" surplusGapLeft=" << surplusGapLeft
2885 if (foeCenter < oldCenter) {
2887 surplusGapRight =
MIN3(surplusGapRight, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
2890 surplusGapLeft =
MIN3(surplusGapLeft, gap - currentMinGap,
MAX2(currentMinGap, gap - foeManeuverDist));
2893 if (foeCenter < oldCenter) {
2894 #if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP) 2896 std::cout <<
" new minimum rightGap=" << gap <<
"\n";
2901 #if defined(DEBUG_BLOCKING) || defined(DEBUG_KEEP_LATGAP) 2903 std::cout <<
" new minimum leftGap=" << gap <<
"\n";
2909 if (collectBlockers != 0) {
2911 if ((foeCenter < oldCenter && latDist < 0 && gap < (desiredMinGap - latDist))
2912 || (foeCenter > oldCenter && latDist > 0 && gap < (desiredMinGap + latDist))) {
2913 collectBlockers->push_back(others[i]);
2930 int currentDirection =
mySpeedLat >= 0 ? 1 : -1;
2931 int directionWish = latDist >= 0 ? 1 : -1;
2935 #ifdef DEBUG_MANEUVER 2939 <<
" computeSpeedLat()" 2940 <<
" currentDirection=" << currentDirection
2941 <<
" directionWish=" << directionWish
2947 if (directionWish == 1) {
2958 double speedAccelSafe = latDist * speedAccel >= 0 ? speedAccel : 0;
2966 if (maneuverDist * latDist > 0) {
2967 maneuverDist = fullLatDist;
2970 #ifdef DEBUG_MANEUVER 2975 <<
" latDist=" << latDist
2976 <<
" maneuverDist=" << maneuverDist
2979 <<
" fullLatDist=" << fullLatDist
2980 <<
" speedAccel=" << speedAccel
2981 <<
" speedDecel=" << speedDecel
2982 <<
" speedBound=" << speedBound
2986 if (speedDecel * speedAccel <= 0 && (
2988 (latDist >= 0 && speedAccel >= speedBound && speedBound >= speedDecel)
2989 || (latDist <= 0 && speedAccel <= speedBound && speedBound <= speedDecel))) {
2991 #ifdef DEBUG_MANEUVER 2993 std::cout <<
" computeSpeedLat a)\n";
3000 #ifdef DEBUG_MANEUVER 3002 std::cout <<
" computeSpeedLat b)\n";
3005 return speedAccelSafe;
3009 if ((fabs(minDistAccel) < fabs(fullLatDist)) || (fabs(minDistAccel - fullLatDist) <
NUMERICAL_EPS)) {
3010 #ifdef DEBUG_MANEUVER 3012 std::cout <<
" computeSpeedLat c)\n";
3017 #ifdef DEBUG_MANEUVER 3019 std::cout <<
" minDistAccel=" << minDistAccel <<
"\n";
3024 if ((fabs(minDistCurrent) < fabs(fullLatDist)) || (fabs(minDistCurrent - fullLatDist) <
NUMERICAL_EPS)) {
3025 #ifdef DEBUG_MANEUVER 3027 std::cout <<
" computeSpeedLat d)\n";
3034 #ifdef DEBUG_MANEUVER 3036 std::cout <<
" computeSpeedLat e)\n";
3039 return speedDecelSafe;
3048 double maneuverDist) {
3051 double secondsToLeaveLane;
3072 double nextLeftSpace;
3073 if (nextActionStepSpeed > 0.) {
3081 const double avoidArrivalSpeed = nextActionStepSpeed +
TS *
MSCFModel::avoidArrivalAccel(nextLeftSpace, secondsToLeaveLane - timeTillActionStep, nextActionStepSpeed);
3087 #ifdef DEBUG_MANEUVER 3091 <<
" avoidArrivalSpeed=" << avoidArrivalSpeed
3094 <<
"\n nextLeftSpace=" << nextLeftSpace
3095 <<
" nextLeftSpace=" << nextActionStepSpeed
3096 <<
" nextActionStepRemainingSeconds=" << secondsToLeaveLane - timeTillActionStep
3104 myCommittedSpeed = 0;
3106 #ifdef DEBUG_MANEUVER 3110 <<
" secondsToLeave=" << secondsToLeaveLane
3112 <<
" committed=" << myCommittedSpeed
3132 const double vehWidth =
getWidth();
3134 const double leftVehSide = rightVehSide + vehWidth;
3135 const double rightVehSideDest = rightVehSide + latDist;
3136 const double leftVehSideDest = leftVehSide + latDist;
3137 #ifdef DEBUG_MANEUVER 3139 std::cout <<
" commitFollowSpeed" 3140 <<
" latDist=" << latDist
3141 <<
" foeOffset=" << foeOffset
3142 <<
" vehRight=" << rightVehSide
3143 <<
" vehLeft=" << leftVehSide
3144 <<
" destRight=" << rightVehSideDest
3145 <<
" destLeft=" << leftVehSideDest
3151 if (vehDist.first != 0) {
3152 const MSVehicle* leader = vehDist.first;
3154 double foeRight, foeLeft;
3156 #ifdef DEBUG_MANEUVER 3158 std::cout <<
" foe=" << vehDist.first->getID()
3159 <<
" gap=" << vehDist.second
3161 <<
" foeRight=" << foeRight
3162 <<
" foeLeft=" << foeLeft
3163 <<
" overlapBefore=" <<
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)
3164 <<
" overlapDest=" <<
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)
3168 if (
overlap(rightVehSideDest, leftVehSideDest, foeRight, foeLeft)) {
3170 assert(vehDist.second >= 0);
3173 speed =
MIN2(speed, vSafe);
3174 #ifdef DEBUG_MANEUVER 3176 std::cout <<
" case1 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3179 }
else if (
overlap(rightVehSide, leftVehSide, foeRight, foeLeft)) {
3184 speed =
MIN2(speed, vSafe);
3185 #ifdef DEBUG_MANEUVER 3187 std::cout <<
" case2 vsafe=" << vSafe <<
" speed=" << speed <<
"\n";
3283 const std::pair<MSVehicle*, double>& leader,
3284 const std::pair<MSVehicle*, double>& neighLead,
3285 const std::pair<MSVehicle*, double>& neighFollow,
3287 const std::vector<MSVehicle::LaneQ>& preb,
3293 #ifdef DEBUG_WANTSCHANGE 3295 std::cout <<
"\nWANTS_CHANGE\n" <<
SIMTIME 3302 <<
" considerChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
3316 double maneuverDist;
3319 leaders, followers, blockers,
3320 neighLeaders, neighFollowers, neighBlockers,
3322 lastBlocked, firstBlocked, latDist, maneuverDist, blocked);
3328 result |=
getLCA(result, latDist);
3330 #if defined(DEBUG_WANTSCHANGE) || defined(DEBUG_STATE) 3335 <<
" wantsChangeTo=" << (laneOffset == -1 ?
"right" :
"left")
3336 << ((result &
LCA_URGENT) ?
" (urgent)" :
"")
3342 << ((result &
LCA_TRACI) ?
" (traci)" :
"")
void * inform(void *info, MSVehicle *sender)
The link is a partial left direction.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
static double gLateralResolution
void initDerivedParameters()
init cached parameters derived directly from model parameters
const std::vector< double > getSubLaneSides() const
Returns the right side offsets of this edge's sublanes.
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i...
saves leader/follower vehicles and their distances relative to an ego vehicle
double myChangeProbThresholdLeft
MSEdge & getEdge() const
Returns the lane's edge.
Representation of a vehicle in the micro simulation.
void msg(const CLeaderDist &cld, double speed, int state)
send a speed recommendation to the given vehicle
void setParameter(const std::string &key, const std::string &value)
try to set the given parameter for this laneChangeModel. Throw exception for unsupported key ...
double mySpeedGainProbabilityLeft
a value for tracking the probability that a change to the left is beneficial
The action is due to the default of keeping right "Rechtsfahrgebot".
double myLastLateralGapRight
The action is done to help someone else.
#define RELGAIN_NORMALIZATION_MIN_SPEED
std::set< const MSVehicle * > myCFRelated
set of vehicles that are in a car-following relationship with ego (leader of followers) ...
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
virtual bool hasPedestrians(const MSLane *lane)
whether the given lane has pedestrians on it
double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
virtual std::string toString() const
print a debugging representation
#define ROUNDABOUT_DIST_BONUS
int myPreviousState
lane changing state from the previous simulation step
double informLeaders(int blocked, int dir, const std::vector< CLeaderDist > &blockers, double remainingSeconds)
MSLane * getLane() const
Returns the lane the vehicle is on.
bool myCanChangeFully
whether the current lane changing maneuver can be finished in a single step
double computeGapFactor(int state) const
compute the gap factor for the given state
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...
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive...
The vehicle is blocked by left follower.
At the leftmost side of the lane.
int gPrecision
the precision for floating point outputs
LateralAlignment getPreferredLateralAlignment() const
Get vehicle's preferred lateral alignment.
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model) ...
int checkBlockingVehicles(const MSVehicle *ego, const MSLeaderDistanceInfo &vehicles, double latDist, double foeOffset, bool leaders, LaneChangeAction blockType, double &safeLatGapRight, double &safeLatGapLeft, std::vector< CLeaderDist > *collectBlockers=0) const
check whether any of the vehicles overlaps with ego
const double SUMO_const_laneWidth
The car-following model abstraction.
double computeSpeedLat(double latDist, double &maneuverDist)
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
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 getPositionOnLane() const
Get the vehicle's position along the lane.
double mySpeedLossProbThreshold
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
void setOwnState(const int state)
static CLeaderDist getSlowest(const MSLeaderDistanceInfo &ldi)
get the slowest vehicle in the given info
int getBestLaneOffset() const
The link is a 180 degree turn.
ArrivalPosLatDefinition arrivalPosLatProcedure
Information how the vehicle shall choose the lateral arrival position.
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
double arrivalPosLat
(optional) The lateral position the vehicle shall arrive on
std::vector< double > myExpectedSublaneSpeeds
expected travel speeds on all sublanes on the current edge(!)
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
double myTimeToImpatience
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
double getLength() const
Returns the lane's length.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const MSRoute & getRoute() const
Returns the current route.
double getMinGapLat() const
Get the minimum lateral gap that vehicles of this type maintain.
double myMaxSpeedLatStanding
const MSEdge * getLastEdge() const
returns the destination edge
static const double NO_NEIGHBOR
const std::string & getID() const
Returns the id.
bool sameDirection(const StateAndDist &other) const
align with the closest sublane border
static double avoidArrivalAccel(double dist, double time, double speed)
Computes the acceleration needed to arrive not before the given time.
double length
The overall length which may be driven when using this lane without a lane change.
bool debugVehicle() const
whether the current vehicles shall be debugged
The action is due to the wish to be faster (tactical lc)
double getWidth() const
Returns the lane's width.
#define UNUSED_PARAMETER(x)
MSLCM_SL2015(MSVehicle &v)
used by the sublane model
#define LCA_RIGHT_IMPATIENCE
The link is a (hard) left direction.
double myTurnAlignmentDist
LateralAlignment
Numbers representing special SUMO-XML-attribute values Information how vehicles align themselves with...
double myChangeProbThresholdRight
MSAbstractLaneChangeModel & getLaneChangeModel()
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 ...
#define MAX_ONRAMP_LENGTH
#define GAIN_PERCEPTION_THRESHOLD
#define ARRIVALPOS_LAT_THRESHOLD
The link is a straight direction.
double mySafeLatDistRight
the lateral distance the vehicle can safely move in the currently considered direction ...
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Needs to stay on the current lane.
void saveBlockerLength(const MSVehicle *blocker, int lcaCounter)
save space for vehicles which need to counter-lane-change
const LaneChangeModel myModel
the type of this model
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
double getWidth() const
return the widht of this vehicle (padded for numerical stability)
static bool overlap(double right, double left, double right2, double left2)
return whether the given intervals overlap
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
A class responsible for exchanging messages between cars involved in lane-change interaction.
StateAndDist decideDirection(StateAndDist sd1, StateAndDist sd2) const
decide in which direction to move in case both directions are desirable
A road/street connecting two junctions.
void commitManoeuvre(int blocked, int blockedFully, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &neighLeaders, const MSLane &neighLane, double maneuverDist)
commit to lane change maneuvre potentially overriding safe speed
double myLeadingBlockerLength
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
int getIndex() const
Returns the lane's index.
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points...
double myManeuverDist
The complete lateral distance the vehicle wants to travel to finish its maneuver Only used by sublane...
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 ...
blocked in all directions
void updateCFRelated(const MSLeaderDistanceInfo &vehicles, double foeOffset, bool leaders)
find leaders/followers that are already in a car-following relationship with ego
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane ...
The action is urgent (to be defined by lc-model)
static double brakeGapEuler(const double speed, const double decel, const double headwayTime)
At the center of the lane.
static MSPModel * getModel()
void addLCSpeedAdvice(const double vSafe)
Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration ...
const MSEdge * myLastEdge
expected travel speeds on all sublanes on the current edge(!)
double informLeader(int blocked, int dir, const CLeaderDist &neighLead, double remainingSeconds)
static LaneChangeAction getLCA(int state, double latDist)
compute lane change action from desired lateral distance
void informFollowers(int blocked, int dir, const std::vector< CLeaderDist > &blockers, double remainingSeconds, double plannedSpeed)
call informFollower for multiple followers
double myMaxSpeedLatFactor
const std::set< MSTransportable * > & getPersons() const
Returns this edge's persons set.
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) ...
const std::pair< double, LinkDirection > & getNextTurn()
Get the distance and direction of the next upcoming turn for the vehicle (within its look-ahead range...
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)
Called to examine whether the vehicle wants to change with the given laneOffset (using the sublane mo...
At the rightmost side of the lane.
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
#define KEEP_RIGHT_ACCEPTANCE
The link is a (hard) right direction.
The action is needed to follow the route (navigational lc)
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
A structure representing the best lanes for continuing the current route starting at 'lane'...
virtual PersonDist nextBlocking(const MSLane *lane, double minPos, double minRight, double maxLeft, double stopTime=0)
returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or 0 ...
bool hasInfluencer() const
virtual void updateSafeLatDist(const double travelledLatDist)
Updates the value of safe lateral distances (mySafeLatDistLeft and mySafeLatDistRight) during maneuve...
double getMinGap() const
Get the free space in front of vehicles of this class.
double _patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel)
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
int myOwnState
The current state of the vehicle.
maintain the current alignment
bool isInternal() const
return whether this edge is an internal edge
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
#define LOOK_AHEAD_SPEED_MEMORY
#define LOOK_AHEAD_MIN_SPEED
static CLeaderDist getLongest(const MSLeaderDistanceInfo &ldi)
get the longest vehicle in the given info
The link is a partial right direction.
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
double myCooperativeParam
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
double getRightSideOnEdge() const
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...
std::pair< double, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
double computeSpeedGain(double latDistSublane, double defaultNextSpeed) const
compute speedGain when moving by the given amount
int getRightmostSublane() const
std::pair< const MSPerson *, double > PersonDist
int checkStrategicChange(int ret, int laneOffset, const std::vector< MSVehicle::LaneQ > &preb, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &neighLeaders, int currIdx, int bestLaneOffset, bool changeToBest, double currentDist, double neighDist, double laDist, int roundaboutEdgesAhead, double latLaneDist, double &latDist)
compute strategic lane change actions TODO: Better documentation, refs #2
bool hasStoppedVehicle() const
whether a stopped vehicle is leader
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
std::pair< const MSVehicle *, double > CLeaderDist
Influencer & getInfluencer()
Returns the velocity/lane influencer.
LaneChangeAction
The state of a vehicle's lane-change behavior.
virtual void setOwnState(const int state)
virtual void setMaxDecel(double decel)
Sets a new value for maximal comfortable deceleration [m/s^2].
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel)
Called to adapt the speed in order to allow a lane change. It uses information on LC-related desired ...
#define SPEEDGAIN_MEMORY_FACTOR
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
double myKeepRightProbability
The vehicle is blocked being overlapping.
int slowDownForBlocked(MSVehicle **blocked, int state)
compute useful slowdowns for blocked vehicles
std::vector< MSLane * > bestContinuations
void getSublaneBorders(int sublane, double latOffset, double &rightSide, double &leftSide) const
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...
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
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
double mySpeedLat
the current lateral speed
static double _2double(const E *const data)
converts a char-type array into the double value described by it
No information given; use default.
double getLength() const
Get vehicle's length [m].
#define SPEEDGAIN_DECAY_FACTOR
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
align with the rightmost sublane that allows keeping the current speed
virtual void prepareStep()
bool allowsVehicleClass(SUMOVehicleClass vclass) const
std::vector< double > myLCAccelerationAdvices
vector of LC-related acceleration recommendations Filled in wantsChange() and applied in patchSpeed()...
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
#define CUT_IN_LEFT_SPEED_THRESHOLD
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key ...
The action is due to a TraCI request.
The link is a 180 degree turn (left-hand network)
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...
#define HELP_DECEL_FACTOR
double mySpeedGainProbabilityRight
a value for tracking the probability that a change to the right is beneficial
#define LATGAP_SPEED_THRESHOLD2
static bool gSemiImplicitEulerUpdate
double myCommittedSpeed
the speed when committing to a change maneuver
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
double getSecureGap(const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
bool myDontBrake
flag to prevent speed adaptation by slowing down
#define LATGAP_SPEED_THRESHOLD
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
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) ...
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute) ...
double getSpeed() const
Returns the vehicle's current speed.
The vehicle is blocked by right leader.
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
double myLastLateralGapLeft
the minimum lateral gaps to other vehicles that were found when last changing to the left and right ...
std::map< int, int > myCanceledStates
double getLatDist() const
public emergency vehicles
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset (this is a wrapper a...
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const =0
Computes the vehicle's follow speed (no dawdling)
const std::string & getID() const
Returns the name of the vehicle.
Representation of a lane in the micro simulation.
const MSCFModel & myCarFollowModel
The vehicle's car following model.
The vehicle is blocked by right follower.
int computeSublaneShift(const MSEdge *prevEdge, const MSEdge *curEdge)
compute shift so that prevSublane + shift = newSublane
Interface for lane-change models.
virtual double stopSpeed(const MSVehicle *const veh, const double speed, double gap) const =0
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling) ...
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
void updateExpectedSublaneSpeeds(const MSLeaderDistanceInfo &ahead, int sublaneOffset, int laneIndex)
update expected speeds for each sublane of the current edge
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 ...
The link has no direction (is a dead end link)
#define SPEED_GAIN_MIN_SECONDS
bool amBlockingFollowerPlusNB()
double getWidth() const
Returns the edges's width (sum over all lanes)