42#define MAX_BLOCK_LENGTH 20000
43#define MAX_SIGNAL_WARNINGS 10
45#define DRIVEWAY_SANITY_CHECK
60#define DEBUG_HELPER(obj) ((obj) != nullptr && (obj)->isSelected())
65#define DEBUG_COND_DW (false)
98 myNumericalID(temporary ? -1 : myGlobalDriveWayIndex++),
103 myFoundSignal(false),
105 myTerminateRoute(false),
106 myAbortedBuild(false),
108 myIsSubDriveway(false)
142 dw->myTrains.clear();
152#ifdef DEBUG_MOVEREMINDER
165 if (foe->myOrigin !=
nullptr) {
183#ifdef DEBUG_MOVEREMINDER
196 const MSLane* leftLane = (*(
dynamic_cast<SUMOVehicle&
>(veh).getCurrentRouteEdge()))->getLanes().front();
211#ifdef DEBUG_MOVEREMINDER
237#ifdef DEBUG_SIGNALSTATE
239 std::cout <<
getID() <<
" linkConflict with " <<
getTLLinkID(foeLink) <<
"\n";
252#ifdef DEBUG_SIGNALSTATE_PRIORITY
259#ifdef DEBUG_SIGNALSTATE_PRIORITY
261 std::cout <<
" approaching foe=" << foe.first->getID() <<
"\n";
264 if (foe.first == veh.first) {
268 assert(foeTLL !=
nullptr);
271 if (foeRS !=
nullptr) {
279#ifdef DEBUG_SIGNALSTATE_PRIORITY
282 std::cout <<
" foe blocked\n";
284 std::cout <<
" foe constrained\n";
285 }
else if (!
overlap(foeDriveWay)) {
286 std::cout <<
" no overlap\n";
288 std::cout <<
" foeDW=" << foeDriveWay.
getID() <<
" is not a foe to " <<
getID() <<
"\n";
289 }
else if (
canUseSiding(veh.first, &foeDriveWay).first) {
290 std::cout <<
" use siding\n";
296#ifdef DEBUG_SIGNALSTATE_PRIORITY
299 <<
" aSB=" << veh.second.arrivalSpeedBraking <<
" foeASB=" << foe.second.arrivalSpeedBraking
300 <<
" aT=" << veh.second.arrivalTime <<
" foeAT=" << foe.second.arrivalTime
301 <<
" aS=" << veh.first->getSpeed() <<
" foeS=" << foe.first->getSpeed()
302 <<
" aD=" << veh.second.dist <<
" foeD=" << foe.second.dist
303 <<
" aW=" << veh.first->getWaitingTime() <<
" foeW=" << foe.first->getWaitingTime()
304 <<
" aN=" << veh.first->getNumericalID() <<
" foeN=" << foe.first->getNumericalID()
338 if (foe.second.arrivalSpeedBraking == veh.second.arrivalSpeedBraking) {
339 if (foe.second.arrivalTime == veh.second.arrivalTime) {
340 if (foe.first->getSpeed() == veh.first->getSpeed()) {
341 if (foe.second.dist == veh.second.dist) {
342 if (foe.first->getWaitingTime() == veh.first->getWaitingTime()) {
343 return foe.first->getNumericalID() < veh.first->getNumericalID();
345 return foe.first->getWaitingTime() > veh.first->getWaitingTime();
348 return foe.second.dist < veh.second.dist;
351 return foe.first->getSpeed() > veh.first->getSpeed();
354 return foe.second.arrivalTime < veh.second.arrivalTime;
357 return foe.second.arrivalSpeedBraking > veh.second.arrivalSpeedBraking;
365 if (!lane->isEmpty()) {
366 std::string joinVehicle =
"";
369 if (stop !=
nullptr) {
370 joinVehicle = stop->
join;
373#ifdef DEBUG_SIGNALSTATE
375 std::cout <<
SIMTIME <<
" conflictLane " << lane->getID() <<
" occupied ego=" <<
Named::getIDSecure(ego) <<
" vehNumber=" << lane->getVehicleNumber() <<
"\n";
376 if (joinVehicle !=
"") {
377 std::cout <<
" joinVehicle=" << joinVehicle <<
" occupant=" <<
toString(lane->getVehiclesSecure()) <<
"\n";
378 lane->releaseVehicles();
382 if (lane->getVehicleNumberWithPartials() == 1) {
383 MSVehicle* foe = lane->getLastAnyVehicle();
384 if (joinVehicle !=
"") {
386#ifdef DEBUG_SIGNALSTATE
388 std::cout <<
" ignore join-target '" << joinVehicle <<
"\n";
394 if (ego !=
nullptr) {
396#ifdef DEBUG_SIGNALSTATE
398 std::cout <<
" ignore ego as oncoming '" << ego->
getID() <<
"\n";
404#ifdef DEBUG_SIGNALSTATE
406 std::cout <<
" ignore " << foe->
getID() <<
" for which ego is join-target\n";
426 if (foeDW->myOrigin !=
nullptr && foeDW->myOrigin->getApproaching().size() > 0) {
427#ifdef DEBUG_SIGNALSTATE
429 std::cout <<
SIMTIME <<
" foeLink=" << foeDW->myOrigin->getDescription() <<
" approachedBy=" << foeDW->myOrigin->getApproaching().begin()->first->getID() <<
"\n";
442 if (!foeDW->myTrains.empty()) {
443#ifdef DEBUG_SIGNALSTATE
448 if (foeDW->myTrains.size() == 1) {
451#ifdef DEBUG_SIGNALSTATE
462 std::pair<bool, const MSDriveWay*> useSiding =
canUseSiding(ego, foeDW);
463#ifdef DEBUG_SIGNALSTATE
468 numSidings = it->second.size();
470 std::cout <<
" useSiding=" << useSiding.first <<
" sidingFoe=" <<
Named::getIDSecure(useSiding.second) <<
" numSidings=" << numSidings <<
"\n";
473 if (useSiding.first) {
483 occupied.push_back(
const_cast<MSEdge*
>(foe->getEdge()));
484 MSEdge* bidi =
const_cast<MSEdge*
>(foe->getEdge()->getBidiEdge());
485 if (bidi !=
nullptr) {
486 occupied.push_back(bidi);
493 SUMOVehicle* foe = *(useSiding.second ==
nullptr ? foeDW : useSiding.second)->
myTrains.begin();
499 }
else if (foeDW !=
this &&
isDepartDriveway() && !foeDW->isDepartDriveway()) {
500 if (foeDW->myOrigin->getApproaching().size() > 0) {
506 if (foeDW->match(firstIt, foe->
getRoute().
end())) {
508#ifdef DEBUG_SIGNALSTATE
510 std::cout <<
SIMTIME <<
" " <<
getID() <<
" blocked by " << foeDW->getID() <<
" (approached by " << foe->
getID() <<
") useSiding=" << useSiding <<
"\n";
525 for (
const std::set<const MSDriveWay*>& dlFoes :
myDeadlocks) {
526 bool allOccupied =
true;
528 if (dlFoe->myTrains.empty()) {
535#ifdef DEBUG_SIGNALSTATE
553 std::string joinVehicle =
"";
555 if (stop !=
nullptr) {
556 joinVehicle = stop->
join;
562 joinVehicle = it->pars.join;
564 if (joinVehicle !=
"") {
565#ifdef DEBUG_SIGNALSTATE
567 std::cout <<
" joinVehicle=" << joinVehicle <<
"\n";
571#ifdef DEBUG_SIGNALSTATE
573 std::cout <<
" ignore join-target '" << joinVehicle <<
"\n";
581#ifdef DEBUG_SIGNALSTATE
583 std::cout <<
" ignore " << foe->
getID() <<
" for which ego is join-target\n";
593std::pair<bool, const MSDriveWay*>
597 for (
auto siding : it->second) {
599 if (ego ==
nullptr || siding.length >= ego->
getLength()) {
603 if (!sidingApproach->myTrains.empty()) {
612 if (foeVeh ==
nullptr) {
622#ifdef DEBUG_SIGNALSTATE
626 <<
" sidingEnd=" << sidingEnd->
getID() <<
" sidingApproach=" << sidingApproach->getID() <<
" approaching=" <<
toString(sidingApproach->myTrains) <<
"\n";
629 return std::make_pair(
false, sidingApproach);
635 return std::make_pair(
true,
nullptr);
639 return std::make_pair(
false,
nullptr);
692 if (lane->isNormal() && lane2->isNormal() && lane->getEdge().getToJunction() == lane2->getEdge().getToJunction()) {
749 if (edge2 ==
myForward.front()->getNextNormal() && !secondCheck) {
753 if (forward.count(edge2->getBidiEdge()) != 0) {
787 std::vector<std::string> signals;
794 std::vector<std::string> foes;
796 foes.push_back(dw->myID);
798 if (foes.size() > 0) {
805 od.
writeAttr(
"foe", item.first->getID());
806 for (
auto siding : item.second) {
824 sub->writeBlocks(od);
826#ifdef DRIVEWAY_SANITY_CHECK
827 std::set<MSDriveWay*> uFoes(
myFoes.begin(),
myFoes.end());
828 if (uFoes.size() !=
myFoes.size()) {
841 od.
openTag(ve.isEntry ?
"entry" :
"exit");
850 sub->writeBlockVehicles(od);
859 std::set<MSLink*>& flankSwitches) {
860 bool seekForwardSignal =
true;
861 bool seekBidiSwitch =
true;
862 bool foundUnsafeSwitch =
false;
864 const std::string warnID = origin ?
"rail signal " +
getClickableTLLinkID(origin) :
"insertion lane '" + toLane->
getID() +
"'";
865#ifdef DEBUG_DRIVEWAY_BUILDROUTE
870 while ((seekForwardSignal || seekBidiSwitch)) {
874 " exceeds maximum length (stopped searching after edge '" + toLane->
getEdge().
getID() +
"' (length=" +
toString(length) +
"m).");
879#ifdef DEBUG_DRIVEWAY_BUILDROUTE
881 std::cout <<
" abort: length=" << length <<
"\n";
886#ifdef DEBUG_DRIVEWAY_BUILDROUTE
901 if (seekForwardSignal) {
902 if (!foundUnsafeSwitch) {
914 }
else if (bidi ==
nullptr) {
916#ifdef DEBUG_DRIVEWAY_BUILDROUTE
918 std::cout <<
" continue bidiSearch beyond turnaround\n";
922 seekBidiSwitch =
false;
923#ifdef DEBUG_DRIVEWAY_BUILDROUTE
925 std::cout <<
" noBidi, abort search for bidiSwitch\n";
930 if (bidi !=
nullptr) {
931 if (foundUnsafeSwitch) {
936 if (!seekForwardSignal) {
942 for (
const MSLink*
const link : ili.lane->getLinkCont()) {
946 if (link->getViaLaneOrLane() != bidi) {
948#ifdef DEBUG_DRIVEWAY_BUILDROUTE
951 std::cout <<
" found unsafe switch " << ili.viaLink->getDescription() <<
" (used=" << bidiNext->
getID() <<
")\n";
955 foundUnsafeSwitch =
true;
959 flankSwitches.insert(ili.viaLink);
967 const std::vector<MSLink*>& links = toLane->
getLinkCont();
969 for (
const MSLink*
const link : links) {
970 if ((next != end && &link->getLane()->getEdge() == *next)
971 &&
isRailway(link->getViaLaneOrLane()->getPermissions())) {
972 toLane = link->getViaLaneOrLane();
973 if (link->getTLLogic() !=
nullptr && link->getTLIndex() >= 0) {
974 if (link == origin) {
978#ifdef DEBUG_DRIVEWAY_BUILDROUTE
980 std::cout <<
" abort: found circle\n";
985 seekForwardSignal =
false;
987 seekBidiSwitch = bidi !=
nullptr;
988#ifdef DEBUG_DRIVEWAY_BUILDROUTE
990 std::cout <<
" found forwardSignal " << link->getTLLogic()->
getID() <<
" seekBidiSwitch=" << seekBidiSwitch <<
"\n";
1000 if (link->getLane()->getBidiLane() !=
nullptr && &link->getLane()->getEdge() == current->
getBidiEdge()) {
1008 if (toLane ==
nullptr) {
1011 toLane = (*next)->getLanes()[0];
1012#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1014 std::cout <<
" abort: turn-around or jump\n";
1020#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1022 std::cout <<
" abort: no next lane available\n";
1031#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1033 std::cout <<
" normalEnd myBidiEnded=" <<
myBidiEnded <<
"\n";
1042 if (other->getLane() != link->
getLane() && !other->isTurnaround()) {
1047 if (ili.viaLink != link && !ili.viaLink->
isTurnaround()) {
1052 if (bidi !=
nullptr) {
1065#ifdef DEBUG_CHECK_FLANKS
1066 std::cout <<
" checkFlanks lanes=" <<
toString(lanes) <<
" allFoes=" << allFoes <<
"\n";
1072 if (reverseOriginLink !=
nullptr) {
1076 for (
int i = 0; i < (int)lanes.size(); i++) {
1077 const MSLane* lane = lanes[i];
1078 const MSLane* prev = i > 0 ? lanes[i - 1] :
nullptr;
1079 const MSLane* next = i + 1 < (int)lanes.size() ? lanes[i + 1] :
nullptr;
1084 if (ili.viaLink == originLink
1085 || ili.viaLink == reverseOriginLink
1090 if (ili.lane != prev && ili.lane != next) {
1091#ifdef DEBUG_CHECK_FLANKS
1092 std::cout <<
" add flankSwitch junction=" << ili.viaLink->getJunction()->
getID() <<
" index=" << ili.viaLink->getIndex() <<
" iLane=" << ili.lane->getID() <<
" prev=" <<
Named::getIDSecure(prev) <<
" targetLane=" << lane->
getID() <<
" next=" <<
Named::getIDSecure(next) <<
"\n";
1094 flankSwitches.insert(ili.viaLink);
1095 }
else if (allFoes) {
1106#ifdef DEBUG_CHECK_FLANKS
1110 if (junction ==
nullptr) {
1114 if (logic ==
nullptr) {
1118 if (in->isInternal()) {
1121 for (
MSLane* inLane : in->getLanes()) {
1123 if (
isRailway(inLane->getPermissions()) && visited.count(inLane) == 0 && (inBidi ==
nullptr || visited.count(inBidi) == 0)) {
1124 for (
MSLink* link : inLane->getLinkCont()) {
1125 if (link->getIndex() >= 0 && logic->
getFoesFor(dwLink->
getIndex()).test(link->getIndex())
1126 && visited.count(link->getLane()) == 0) {
1127#ifdef DEBUG_CHECK_FLANKS
1128 std::cout <<
" add crossing flankSwitch junction=" << junction->
getID() <<
" index=" << link->getIndex() <<
"\n";
1130 if (link->getViaLane() ==
nullptr) {
1131 flankSwitches.insert(link);
1133 flankSwitches.insert(link->getViaLane()->getLinkCont().front());
1144#ifdef DEBUG_CHECK_FLANKS
1150#ifdef DEBUG_CHECK_FLANKS
1151 std::cout <<
" flank guarded by " << entry->
getTLLogic()->
getID() <<
"\n";
1159 std::vector<MSLink*> predLinks;
1161 if (!ili.viaLink->isTurnaround()) {
1162 predLinks.push_back(ili.viaLink);
1165 if (predLinks.size() > 1) {
1167#ifdef DEBUG_ADD_FOES
1168 std::cout <<
" predecessors of " << link->
getDescription() <<
" isSwitch\n";
1170 for (
MSLink* pred : predLinks) {
1173 }
else if (predLinks.size() == 1) {
1189#ifdef DEBUG_ADD_FOES
1190 std::cout <<
" driveway " <<
myID <<
" addSwitchFoes for link " << link->
getDescription() <<
"\n";
1194#ifdef DEBUG_ADD_FOES
1195 std::cout <<
" foe=" << foe->myID
1196 <<
" fc1=" <<
flankConflict(*foe) <<
" fc2=" << foe->flankConflict(*
this)
1197 <<
" cc1=" <<
crossingConflict(*foe) <<
" cc2=" << foe->crossingConflict(*
this) <<
"\n";
1201#ifdef DEBUG_ADD_FOES
1202 std::cout <<
" cand=" << foe->myID <<
"\n";
1236 std::vector<const MSLane*> before;
1237 MSLane* fromBidi =
nullptr;
1238 if (link !=
nullptr) {
1242 std::set<MSLink*> flankSwitches;
1244 if (fromBidi !=
nullptr) {
1245 before.push_back(fromBidi);
1247 dw->
buildRoute(link, 0., first, end, visited, flankSwitches);
1251 dw->
checkFlanks(link, before, visited,
true, flankSwitches);
1252 for (
MSLink* fsLink : flankSwitches) {
1253#ifdef DEBUG_ADD_FOES
1255 std::cout <<
" fsLink=" << fsLink->getDescription() <<
"\n";
1260 std::set<MSLink*> flankSwitchesBidiExtended;
1262 for (
MSLink* link : flankSwitchesBidiExtended) {
1263#ifdef DEBUG_ADD_FOES
1265 std::cout <<
" fsLinkExtended=" << link->
getDescription() <<
"\n";
1272#ifdef DEBUG_BUILD_DRIVEWAY
1274 std::cout <<
SIMTIME <<
" buildDriveWay " << dw->
myID <<
" link=" << (link ==
nullptr ?
"NULL" : link->
getDescription())
1297 std::set<MSDriveWay*, ComparatorNumericalIdLess> uniqueFoes(dw->
myFoes.begin(), dw->
myFoes.end());
1302 const MSEdge* foeLastEdge = &foe->myForward.back()->getEdge();
1303 const bool sameLast = foeLastEdge == lastEdge;
1304 if (sameLast && !movingBlock) {
1305 dw->
myFoes.push_back(foe);
1307 foe->myFoes.push_back(dw);
1310 if (foe->bidiBlockedByEnd(*dw)) {
1311#ifdef DEBUG_ADD_FOES
1313 std::cout <<
" setting " << dw->
getID() <<
" as foe of " << foe->getID() <<
"\n";
1316 foe->myFoes.push_back(dw);
1317 foe->addSidings(dw);
1322#ifdef DEBUG_ADD_FOES
1324 std::cout <<
" addFoeCheckSiding " << foe->getID() <<
"\n";
1327 dw->
myFoes.push_back(foe);
1330 foe->buildSubFoe(dw, movingBlock);
1334 foe->addConflictLink(link);
1337 if (foe->myRoute.front()->getFromJunction() != dw->
myRoute.front()->getFromJunction()) {
1338 for (
auto ili : foe->myForward.front()->getIncomingLanes()) {
1339 if (ili.viaLink->getTLLogic() !=
nullptr) {
1341 const MSLane* origin = ili.viaLink->getLaneBefore();
1343 uniqueCLink.insert(ili.viaLink);
1355 if (uniqueFoes.count(sameEnd) == 0) {
1356 dw->
myFoes.push_back(sameEnd);
1357 if (sameEnd != dw) {
1358 sameEnd->myFoes.push_back(dw);
1363#ifdef DEBUG_BUILD_DRIVEWAY
1410 const int tmp = (int)map.size();
1417 auto itRoute = firstIt;
1418 auto itDwRoute =
myRoute.begin();
1420 while (itRoute != endIt && itDwRoute !=
myRoute.end()) {
1421 if (*itRoute != *itDwRoute) {
1424 std::cout <<
" check dw=" <<
getID() <<
" match failed at vehEdge=" << (*itRoute)->getID() <<
" dwEdge=" << (*itDwRoute)->getID() <<
"\n";
1436 if (itRoute != endIt) {
1438 const MSEdge* next = *itRoute;
1443 std::cout <<
" check dw=" <<
getID() <<
" prev=" << prev->
getID() <<
" next=" << next->
getID() <<
"\n";
1463#ifdef DEBUG_ADD_FOES
1464 std::cout <<
"driveway " <<
myID <<
" addFoes for link " << link->
getDescription() <<
"\n";
1467 if (rs !=
nullptr) {
1469#ifdef DEBUG_ADD_FOES
1470 std::cout <<
" cand foe=" << foe->
myID <<
" fc1=" <<
flankConflict(*foe) <<
" fc2=" << foe->flankConflict(*
this) <<
" cc1=" <<
crossingConflict(*foe) <<
" cc2=" << foe->crossingConflict(*
this) <<
"\n";
1473#ifdef DEBUG_ADD_FOES
1474 std::cout <<
" foe=" << foe->myID <<
"\n";
1485#ifdef DEBUG_ADD_FOES
1486 std::cout <<
"driveway " <<
myID <<
" addBidiFoes extended=" << extended <<
"\n";
1489 for (
const MSLane* bidi : bidiLanes) {
1490 for (
auto ili : bidi->getIncomingLanes()) {
1492 if (rs !=
nullptr && rs != ownSignal &&
1493 std::find(bidiLanes.begin(), bidiLanes.end(), ili.lane) != bidiLanes.end()) {
1497 const MSEdge* bidiEdge = &bidi->getEdge();
1501#ifdef DEBUG_ADD_FOES
1502 std::cout <<
" foe " << foe->
getID() <<
" departs on bidi=" << bidiEdge->
getID() <<
"\n";
1506#ifdef DEBUG_ADD_FOES
1507 std::cout <<
" cand foe " << foe->getID() <<
" departs on bidi=" << bidiEdge->
getID() <<
" rejected\n";
1515#ifdef DEBUG_ADD_FOES
1516 std::cout <<
" foe " << foe->getID() <<
" ends on bidi=" << bidiEdge->
getID() <<
"\n";
1520#ifdef DEBUG_ADD_FOES
1521 std::cout <<
" cand foe " << foe->getID() <<
" ends on bidi=" << bidiEdge->
getID() <<
" rejected\n";
1532#ifdef DEBUG_ADD_FOES
1533 std::cout <<
"driveway " <<
myID <<
" addParallelFoes\n";
1541#ifdef DEBUG_ADD_FOES
1542 std::cout <<
" foe " << foe->getID() <<
" departs on first=" << first->
getID() <<
"\n";
1553#ifdef DEBUG_ADD_FOES
1554 std::cout <<
"driveway " <<
myID <<
" addReversalFoes\n";
1556 std::set<const MSEdge*> forward;
1558 if (lane->isNormal()) {
1559 forward.insert(&lane->getEdge());
1564 if (forward.count(e) != 0) {
1577#ifdef DEBUG_ADD_FOES
1581 std::set<const MSEdge*> foeForward;
1582 for (
const MSLane* lane : foe->myForward) {
1583 if (lane->isNormal()) {
1584 foeForward.insert(&lane->getEdge());
1585 if (lane->getBidiLane() !=
nullptr) {
1586 foeForward.insert(lane->getEdge().getBidiEdge());
1590#ifdef DEBUG_ADD_FOES
1591 std::cout <<
" reversal cand=" << foe->getID() <<
" foeForward " <<
toString(foeForward) <<
"\n";
1593 if (foe->forwardRouteConflict(foeForward, *
this,
true)) {
1594#ifdef DEBUG_ADD_FOES
1595 std::cout <<
" foe " << foe->getID() <<
" reverses on edge=" << e->getID() <<
"\n";
1620#ifdef DEBUG_BUILD_SUBDRIVEWAY
1621 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" is subpart of foe=" << foe->
getID() <<
"\n";
1623 foe->
myFoes.push_back(
this);
1626 int subLast = (int)
myForward.size() - 2;
1627#ifdef DEBUG_BUILD_SUBDRIVEWAY
1629 std::cout <<
" " <<
getID() <<
" cannot build subDriveWay for foe " << foe->
getID() <<
" because myForward has only a single lane\n";
1632 bool foundConflict =
false;
1633 while (subLast >= 0) {
1637#ifdef DEBUG_BUILD_SUBDRIVEWAY
1639 <<
" bc=" << (std::find(foe->
myBidi.begin(), foe->
myBidi.end(), lane) != foe->
myBidi.end()) <<
"\n";
1641 const bool bidiConflict = std::find(foe->
myBidi.begin(), foe->
myBidi.end(), lane) != foe->
myBidi.end();
1643 foundConflict =
true;
1644 if (!movingBlock || bidiConflict) {
1647 }
else if (foundConflict) {
1655 foe->
myFoes.push_back(
this);
1659#ifdef DEBUG_BUILD_SUBDRIVEWAY
1660 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" terminates\n";
1663 foe->
myFoes.push_back(
this);
1664#ifdef DEBUG_BUILD_SUBDRIVEWAY
1665 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" terminates, foe=" << foe->
getID() <<
"\n";
1669#ifdef DEBUG_BUILD_SUBDRIVEWAY
1670 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" has " << foe->
myReversals.size() <<
" reversals\n";
1673#ifdef DEBUG_BUILD_SUBDRIVEWAY
1674 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" failed\n";
1676#ifdef SUBDRIVEWAY_WARN_NOCONFLICT
1677 WRITE_WARNINGF(
"No point of conflict found between driveway '%' and driveway '%' when creating sub-driveway",
getID(), foe->
getID());
1682 int subSize = subLast + 1;
1684 if ((
int)cand->myForward.size() == subSize) {
1686 foe->
myFoes.push_back(cand);
1687 cand->myFoes.push_back(foe);
1688#ifdef DEBUG_BUILD_SUBDRIVEWAY
1689 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" useExisting=" << cand->getID() <<
"\n";
1695 std::vector<const MSEdge*> route;
1696 for (
const MSLane* lane : forward) {
1697 if (lane->isNormal()) {
1698 route.push_back(&lane->getEdge());
1701 if (
myRoute.size() > route.size()) {
1703 const MSEdge* lastNormal = route.back();
1706#ifdef DEBUG_BUILD_SUBDRIVEWAY
1707 std::cout <<
SIMTIME <<
" abort subFoe dw=" <<
getID() <<
" foe=" << foe->
getID()
1708 <<
" lastNormal=" << lastNormal->
getID() <<
" nextNormal=" << nextNormal->
getID() <<
" endWithReversal\n";
1727 if (ve.id == veh->getID()) {
1734 foe->
myFoes.push_back(sub);
1735 sub->
myFoes.push_back(foe);
1737#ifdef DEBUG_BUILD_SUBDRIVEWAY
1745 const MSEdge* foeEndBidi = foe->
myForward.back()->getEdge().getBidiEdge();
1746 int forwardNormals = 0;
1748 if (lane->isNormal()) {
1752 if (forwardNormals == (
int)foe->
myRoute.size()) {
1753#ifdef DEBUG_BUILD_SIDINGS
1754 std::cout <<
"checkSiding " <<
getID() <<
" foe=" << foe->
getID() <<
" forwardNormals=" << forwardNormals <<
" frSize=" << foe->
myRoute.size() <<
" aborted\n";
1758 auto foeSearchBeg = foe->
myRoute.begin() + forwardNormals;
1759 auto foeSearchEnd = foe->
myRoute.end();
1760 if (foeEndBidi ==
nullptr) {
1764 std::vector<int> start;
1765 std::vector<double> length;
1766 for (i = 0; i < (int)
myRoute.size(); i++) {
1767 if (
myRoute[i] == foeEndBidi) {
1771 if (i == (
int)
myRoute.size()) {
1775#ifdef DEBUG_BUILD_SIDINGS
1776 std::cout <<
"checkSiding " <<
getID() <<
" foe=" << foe->
getID() <<
" i=" << i <<
" next=" << next->
getID() <<
" forwardNormals=" << forwardNormals <<
" frSize=" << foe->
myRoute.size() <<
" foeSearchBeg=" << (*foeSearchBeg)->getID() <<
"\n";
1779 for (; i >= 0; i--) {
1781 if (
hasRS(cur, next)) {
1782 if (std::find(foeSearchBeg, foeSearchEnd, cur->
getBidiEdge()) == foeSearchEnd) {
1784 length.push_back(0);
1787 if (!start.empty()) {
1788 auto itFind = std::find(foeSearchBeg, foeSearchEnd, cur->
getBidiEdge());
1789 if (itFind != foeSearchEnd) {
1790#ifdef DEBUG_BUILD_SIDINGS
1793 const int firstIndex = i + 1;
1795 auto& foeSidings = foe->
mySidings[
this];
1798 auto itFirst = std::find(foe->
myRoute.begin(), foe->
myRoute.end(), first);
1799 if (itFirst != foe->
myRoute.end()) {
1800 for (
int j = 0; j < (int)length.size(); j++) {
1802 auto itLast = std::find(itFirst, foe->
myRoute.end(), last);
1803 if (itLast != foe->
myRoute.end()) {
1804 foeSidings.insert(foeSidings.begin(),
Siding((
int)(itFirst - foe->
myRoute.begin()), (
int)(itLast - foe->
myRoute.begin()), length[j]));
1810 for (
int j = 0; j < (int)length.size(); j++) {
1811 foeSidings.insert(foeSidings.begin(),
Siding(firstIndex, start[j], length[j]));
1816 foeSearchBeg = itFind;
1818 for (
int j = 0; j < (int)length.size(); j++) {
1832 for (
auto lane : cur->
getLanes()) {
1833 for (
const MSLink* link : lane->getLinkCont()) {
1834 if (&link->getLane()->getEdge() == next && link->getTLLogic() !=
nullptr) {
1846 const MSEdge* foeForwardEnd = &foe->
myForward.back()->getNormalPredecessorLane()->getEdge();
1868 std::set<const MSDriveWay*> filtered;
1871 filtered.insert(foe);
1885 for (
auto ili : lane->getIncomingLanes()) {
1888 if (rs !=
nullptr) {
1890 if (&dw->
myForward.front()->getEdge() == edge) {
1914 const MSEdge* edge = item.first;
1915 if (item.second.size() > 0) {
1919 if (writeVehicles) {
1920 dw->writeBlockVehicles(od);
1922 dw->writeBlocks(od);
1935 dw->_saveState(out);
1937 sub->_saveState(out);
1960 if (!sub->myTrains.empty()) {
1978 const std::string
id = attrs.
get<std::string>(
SUMO_ATTR_ID,
nullptr, ok);
1990 throw ProcessError(
TLF(
"Unknown driveWay '%' with route '%'",
id, edges));
1995 std::string parentID =
id.substr(0,
id.rfind(
'.'));
2000 throw ProcessError(
TLF(
"Unknown parent driveway '%' for subDriveWay '%'", parentID,
id));
2004 if (sub->myRoute == route) {
2009 if (dw ==
nullptr) {
2018 if (veh ==
nullptr) {
2019 throw ProcessError(
TLF(
"Unknown vehicle '%' in driveway '%'", vehID,
id));
#define DEBUG_HELPER(obj)
#define MAX_SIGNAL_WARNINGS
std::vector< const MSEdge * > ConstMSEdgeVector
std::vector< MSEdge * > MSEdgeVector
ConstMSEdgeVector::const_iterator MSRouteIterator
#define WRITE_WARNINGF(...)
#define WRITE_WARNING(msg)
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a railway edge.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SUMO_TAG_DRIVEWAY
Saved driveway information.
@ TURN
The link is a 180 degree turn.
@ TURN_LEFTHAND
The link is a 180 degree turn (left-hand network)
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_TIME
trigger: the time of the step
#define UNUSED_PARAMETER(x)
std::string joinNamedToString(const std::set< T *, C > &ns, const T_BETWEEN &between)
std::string joinToStringSorting(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
std::string joinNamedToStringSorting(const std::set< T * > &ns, const T_BETWEEN &between)
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
A single mesoscopic segment (cell)
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
The base class for microscopic and mesoscopic vehicles.
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
bool isStopped() const
Returns whether the vehicle is at a stop.
SUMOTime getStartupDelay() const
Get the vehicle type's startupDelay.
void addFoes(const MSLink *link)
add all driveWays that start at the given link as foes
std::vector< MSLink * > myConflictLinks
const SUMOVehicle * myActive
whether the current signal is switched green for a train approaching this block
bool crossingConflict(const MSDriveWay &other) const
Wether there is a crossing conflict with the given driveway.
static std::string getJunctionLinkID(const MSLink *link)
return junctionID_junctionLinkIndex
bool haveSubTrains() const
std::vector< MSDriveWay * > mySubDriveWays
std::vector< std::set< const MSDriveWay * > > myDeadlocks
void checkFlanks(const MSLink *originLink, const std::vector< const MSLane * > &lanes, const LaneVisitedMap &visited, bool allFoes, std::set< MSLink * > &flankSwitches) const
bool myAbortedBuild
whether driveway building was aborted due to MAX_BLOCK_LENGTH
bool buildSubFoe(MSDriveWay *foe, bool movingBlock)
static std::map< const MSJunction *, int > myDepartDrivewayIndex
static bool hasJoin(const SUMOVehicle *ego, const SUMOVehicle *foe)
bool isDepartDriveway() const
static std::string getClickableTLLinkID(const MSLink *link)
return logicID_linkIndex in a way that allows clicking in sumo-gui
const MSLink * myOrigin
the link that enters this driveway or nullptr for a departure driveWay
std::vector< const MSLane * > myBidi
static bool myWriteVehicles
void checkCrossingFlanks(MSLink *dwLink, const LaneVisitedMap &visited, std::set< MSLink * > &flankSwitches) const
bool hasLinkConflict(const Approaching &closest, const MSLink *foeLink) const
Whether the approaching vehicle is prevent from driving by another vehicle approaching the given link...
void findFlankProtection(MSLink *link, MSLink *origLink, std::vector< const MSLane * > &flank)
std::vector< const MSLane * > myBidiExtended
void addReversalFoes()
derive foe driveways that enter the bidi section by reversing
MSDriveWay(const MSLink *origin, const std::string &id, bool temporary=false)
static bool hasRS(const MSEdge *cur, const MSEdge *next)
void addBidiFoes(const MSRailSignal *ownSignal, bool extended)
derive foe driveways based on myBidi or myBidiExtended
void writeBlocks(OutputDevice &od) const
Write block items for this driveway.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder's lane.
std::vector< const MSLane * > myForward
std::vector< const MSEdge * > myReversals
track own occurences in myReversalDriveWays for cleanup in destructor
std::map< const MSDriveWay *, std::vector< Siding >, ComparatorIdLess > mySidings
void writeBlockVehicles(OutputDevice &od) const
virtual ~MSDriveWay()
Destructor.
bool match(MSRouteIterator firstIt, MSRouteIterator endIt) const
whether the give route matches this driveway
static void appendMapIndex(LaneVisitedMap &map, const MSLane *lane)
append to map by map index and avoid undefined behavior
bool overlap(const MSDriveWay &other) const
Wether this driveway (route) overlaps with the given one.
std::vector< const MSLane * > myFlank
static std::string getTLLinkID(const MSLink *link)
return logicID_linkIndex
std::vector< const MSEdge * > myRoute
list of edges for matching against train routes
std::map< const MSLane *, int, ComparatorNumericalIdLess > LaneVisitedMap
static void writeDepatureBlocks(OutputDevice &od, bool writeVehicles)
static std::map< ConstMSEdgeVector, MSDriveWay * > myDriveWayRouteLookup
lookup table for state loading
void buildRoute(const MSLink *origin, double length, MSRouteIterator next, MSRouteIterator end, LaneVisitedMap &visited, std::set< MSLink * > &)
static std::map< const MSEdge *, std::vector< MSDriveWay * > > myReversalDriveWays
all driveways reversing on the given switch (used to look up flank foes)
void _saveState(OutputDevice &out) const
static std::string formatVisitedMap(const LaneVisitedMap &visited)
print link descriptions
static std::map< std::string, MSDriveWay * > myDriveWayLookup
bool flankConflict(const MSDriveWay &other) const
Wether there is a flank conflict with the given driveway.
bool conflictLaneOccupied(bool store=true, const SUMOVehicle *ego=nullptr) const
whether any of myConflictLanes is occupied (vehicles that are the target of a join must be ignored)
void addSwitchFoes(MSLink *link)
static std::map< const MSEdge *, std::vector< MSDriveWay * > > myDepartureDrivewaysEnds
all driveways that do not start at a rail signal (and are only used at departure) by end edge
int myCoreSize
number of edges in myRoute where overlap with other driveways is forbidden
std::pair< const SUMOVehicle *const, const MSLink::ApproachingVehicleInformation > Approaching
void addConflictLink(const MSLink *link)
add symmetical conflict link for foes when building a new driveway
bool notifyLeaveBack(SUMOTrafficObject &veh, Notification reason, const MSLane *leftLane)
Called if the vehicle's back leaves the reminder's lane.
std::string myFirstVehicle
the first vehicle using this driveway
bool forwardEndOnRoute(const MSDriveWay *foe) const
static void saveState(OutputDevice &out)
Save driveway occupancy into the given stream.
static std::map< const MSEdge *, std::vector< MSDriveWay * >, ComparatorNumericalIdLess > myDepartureDriveways
all driveways that do not start at a rail signal (and are only used at departure)
void setVehicle(const std::string &vehID)
bool myBidiEnded
whether driveway building was aborted when no further bidi edge was found
static bool mustYield(const Approaching &veh, const Approaching &foe)
Whether veh must yield to the foe train.
static const MSDriveWay * getDepartureDriveway(const SUMOVehicle *veh)
void addSidings(MSDriveWay *foe, bool addToFoe=false)
add sidings for the given foe
bool bidiBlockedByEnd(const MSDriveWay &other) const
Wether there is a bidi conflict with the end of the given driveway.
static int myGlobalDriveWayIndex
static MSDriveWay * buildDriveWay(const std::string &id, const MSLink *link, MSRouteIterator first, MSRouteIterator end)
construct a new driveway by searching along the given route until all block structures are found
bool myFoundSignal
whether this driveway ends its forward section with a rail signal (and thus comprises a full block)
static std::map< const MSLink *, std::vector< MSDriveWay * > > mySwitchDriveWays
all driveways passing the given switch (used to look up flank foes)
bool isFoeOrSubFoe(const MSDriveWay *foe) const
void addDWDeadlock(const std::vector< const MSDriveWay * > &deadlockFoes)
static std::map< const MSEdge *, std::vector< MSDriveWay * >, ComparatorNumericalIdLess > myEndingDriveways
all driveways that end on the given edge
bool foeDriveWayApproached() const
whether any of my Foes is being approached
static void loadState(const SUMOSAXAttributes &attrs, int tag)
bool forwardRouteConflict(std::set< const MSEdge * > forward, const MSDriveWay &other, bool secondCheck=false)
Wether the route of other passes into the forward section of this driveway.
std::pair< bool, const MSDriveWay * > canUseSiding(const SUMOVehicle *ego, const MSDriveWay *foe, bool recurse=true) const
return whether a siding can be used. If a siding exist but is occupied, also return the occupied driv...
std::vector< const MSLane * > myConflictLanes
the lanes that must be clear of trains before this signal can switch to green
std::vector< MSDriveWay * > myFoes
std::vector< VehicleEvent > myVehicleEvents
static bool isSwitch(const MSLink *link)
bool notifyEnter(SUMOTrafficObject &veh, Notification reason, const MSLane *enteredLane)
Checks whether the reminder is activated by a vehicle entering the lane.
bool bidiBlockedBy(const MSDriveWay &other) const
Wether there is a bidi conflict with the given driveway.
bool reserve(const Approaching &closest, MSEdgeVector &occupied)
attempt reserve this driveway for the given vehicle
std::set< SUMOVehicle * > myTrains
void addParallelFoes(const MSLink *link, const MSEdge *first)
derive foe driveways that start at the same signal
bool foeDriveWayOccupied(bool store, const SUMOVehicle *ego, MSEdgeVector &occupied) const
whether any of myFoes is occupied (vehicles that are the target of a join must be ignored)
A road/street connecting two junctions.
bool isConnectedTo(const MSEdge &destination, SUMOVehicleClass vclass) const
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
static void parseEdgesList(const std::string &desc, ConstMSEdgeVector &into, const std::string &rid)
Parses the given string assuming it contains a list of edge ids divided by spaces.
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
bool isNormal() const
return whether this edge is an internal edge
const MSJunction * getToJunction() const
double getLength() const
return the length of the edge
const MSJunction * getFromJunction() const
static MELoop * gMesoNet
mesoscopic simulation infrastructure
static SUMOTime gTimeToTeleportRSDeadlock
The base class for an intersection.
SumoXMLNodeType getType() const
return the type of this Junction
virtual const MSJunctionLogic * getLogic() const
const ConstMSEdgeVector & getIncoming() const
virtual const MSLogicJunction::LinkBits & getFoesFor(int linkIndex) const
Returns the foes for the given link.
Representation of a lane in the micro simulation.
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
double getLength() const
Returns the lane's length.
int getIndex() const
Returns the lane's index.
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
MSEdge & getEdge() const
Returns the lane's edge.
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
virtual void addMoveReminder(MSMoveReminder *rem)
Add a move-reminder to move-reminder container.
MSJunction * getJunction() const
MSLane * getLane() const
Returns the connected lane.
int getIndex() const
Returns the respond index (for visualization)
bool isTurnaround() const
int getTLIndex() const
Returns the TLS index.
const MSLane * getLaneBefore() const
return the internalLaneBefore if it exists and the laneBefore otherwise
ApproachingVehicleInformation getApproaching(const SUMOVehicle *veh) const
std::string getDescription() const
get string description for this link
std::pair< const SUMOVehicle *const, const ApproachingVehicleInformation > getClosest() const
get the closest vehicle approaching this link
const MSLink * getCorrespondingEntryLink() const
returns the corresponding entry link for exitLinks to a junction.
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
const MSTrafficLightLogic * getTLLogic() const
Returns the TLS index.
const MSLink * getCorrespondingExitLink() const
returns the corresponding exit link for entryLinks to a junction.
LinkDirection getDirection() const
Returns the direction the vehicle passing this link take.
Something on a lane to be noticed about vehicle movement.
const std::string & getDescription() const
Notification
Definition of a vehicle state.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
@ NOTIFICATION_PARKING
The vehicle starts or ends parking.
MSLane * myLane
Lane on which the reminder works.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
void notifyApproach(const MSLink *link)
switch rail signal to active
void addWaitRelation(const SUMOVehicle *waits, const MSRailSignal *rs, const SUMOVehicle *reason, MSRailSignalConstraint *constraint=nullptr)
static MSRailSignalControl & getInstance()
bool isMovingBlock() const
const MSDriveWay & retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle *veh)
static std::string describeLinks(std::vector< MSLink * > links)
print link descriptions
bool constraintsAllow(const SUMOVehicle *veh, bool storeWaitRelation=false) const
whether the given vehicle is free to drive
static VehicleVector & rivalVehicles()
static bool storeVehicles()
const std::vector< MSDriveWay * > retrieveDriveWays(int tlIndex) const
static VehicleVector & priorityVehicles()
static std::vector< const MSDriveWay * > & blockingDriveWays()
static VehicleVector & blockingVehicles()
MSRouteIterator end() const
Returns the end of the list of edges to pass.
The parent class for traffic light logics.
The class responsible for building and deletion of vehicles.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
Representation of a vehicle in the micro simulation.
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
Base class for objects which have an id.
std::string myID
The name of the object.
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.
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
void lf()
writes a line feed if applicable
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSLane * getBackLane() const =0
Returns the lane the where the rear of the object is currently at.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
Representation of a vehicle.
virtual bool isStopped() const =0
Returns whether the vehicle is at a stop and waiting for a person or container to continue.
virtual const std::list< MSStop > & getStops() const =0
virtual bool hasDeparted() const =0
Returns whether this vehicle has departed.
virtual double getLength() const =0
Returns the vehicles's length.
virtual bool isOnRoad() const =0
Returns the information whether the vehicle is on a road (is simulated)
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
virtual const SUMOVehicleParameter::Stop * getNextStopParameter() const =0
Returns parameters of the next stop or nullptr.
virtual const MSRoute & getRoute() const =0
Returns the current route.
Definition of vehicle stop (position and duration)
std::string join
the id of the vehicle (train portion) to which this vehicle shall be joined
std::vector< std::string > getVector()
return vector of strings
Function-object for stable sorting of objects with numerical ids.