38#define DRIVEWAY_SANITY_CHECK
52#define DEBUG_HELPER(obj) ((obj) != nullptr && (obj)->isSelected())
57#define DEBUG_COND_DW(obj) (obj->getID() == DEBUG_DW_ID || DEBUG_DW_ID == std::string("ALL"))
58#define DEBUG_COND_DW2 (getID() == DEBUG_DW_ID || DEBUG_DW_ID == std::string("ALL"))
96 myNumericalID(temporary ? -1 : myGlobalDriveWayIndex++),
100 myForwardEdgeCount(0),
101 myFoundSignal(false),
103 myTerminateRoute(false),
104 myAbortedBuild(false),
141 dw->myTrains.clear();
149#ifdef DEBUG_MOVEREMINDER
182#ifdef DEBUG_MOVEREMINDER
195 const MSLane* leftLane = (*(
dynamic_cast<SUMOVehicle&
>(veh).getCurrentRouteEdge()))->getLanes().front();
208#ifdef DEBUG_MOVEREMINDER
229#ifdef DEBUG_MOVEREMINDER
277 if (foe->myOrigin !=
nullptr) {
293#ifdef DEBUG_SIGNALSTATE
295 std::cout <<
getID() <<
" linkConflict with " <<
getTLLinkID(foeLink) <<
"\n";
308#ifdef DEBUG_SIGNALSTATE_PRIORITY
315#ifdef DEBUG_SIGNALSTATE_PRIORITY
317 std::cout <<
" approaching foe=" << foe.first->getID() <<
"\n";
320 if (foe.first == veh.first) {
324 assert(foeTLL !=
nullptr);
327 if (foeRS !=
nullptr) {
335#ifdef DEBUG_SIGNALSTATE_PRIORITY
338 std::cout <<
" foe blocked\n";
340 std::cout <<
" foe constrained\n";
341 }
else if (!
overlap(foeDriveWay)) {
342 std::cout <<
" no overlap with foeDW=" << foeDriveWay.
getID() <<
"\n";
344 std::cout <<
" foeDW=" << foeDriveWay.
getID() <<
" is not a foe to " <<
getID() <<
"\n";
345 }
else if (
canUseSiding(veh.first, &foeDriveWay).first) {
346 std::cout <<
" use siding\n";
352#ifdef DEBUG_SIGNALSTATE_PRIORITY
355 <<
" aSB=" << veh.second.arrivalSpeedBraking <<
" foeASB=" << foe.second.arrivalSpeedBraking
356 <<
" aT=" << veh.second.arrivalTime <<
" foeAT=" << foe.second.arrivalTime
357 <<
" aS=" << veh.first->getSpeed() <<
" foeS=" << foe.first->getSpeed()
358 <<
" aD=" << veh.second.dist <<
" foeD=" << foe.second.dist
359 <<
" aW=" << veh.first->getWaitingTime() <<
" foeW=" << foe.first->getWaitingTime()
360 <<
" aN=" << veh.first->getNumericalID() <<
" foeN=" << foe.first->getNumericalID()
385 if (foe !=
nullptr) {
395 if (foe.second.arrivalSpeedBraking == veh.second.arrivalSpeedBraking) {
396 if (foe.second.arrivalTime == veh.second.arrivalTime) {
397 if (foe.first->getSpeed() == veh.first->getSpeed()) {
398 if (foe.second.dist == veh.second.dist) {
399 if (foe.first->getWaitingTime() == veh.first->getWaitingTime()) {
402 return foe.first->getWaitingTime() > veh.first->getWaitingTime();
405 return foe.second.dist < veh.second.dist;
408 return foe.first->getSpeed() > veh.first->getSpeed();
411 return foe.second.arrivalTime < veh.second.arrivalTime;
414 return foe.second.arrivalSpeedBraking > veh.second.arrivalSpeedBraking;
422 if (!lane->isEmpty()) {
423 std::string joinVehicle =
"";
426 if (stop !=
nullptr) {
427 joinVehicle = stop->
join;
430#ifdef DEBUG_SIGNALSTATE
432 std::cout <<
SIMTIME <<
" conflictLane " << lane->getID() <<
" occupied ego=" <<
Named::getIDSecure(ego) <<
" vehNumber=" << lane->getVehicleNumber() <<
"\n";
433 if (joinVehicle !=
"") {
434 std::cout <<
" joinVehicle=" << joinVehicle <<
" occupant=" <<
toString(lane->getVehiclesSecure()) <<
"\n";
435 lane->releaseVehicles();
439 if (lane->getVehicleNumberWithPartials() == 1) {
440 MSVehicle* foe = lane->getLastAnyVehicle();
441 if (joinVehicle !=
"") {
443#ifdef DEBUG_SIGNALSTATE
445 std::cout <<
" ignore join-target '" << joinVehicle <<
"\n";
451 if (ego !=
nullptr) {
453#ifdef DEBUG_SIGNALSTATE
455 std::cout <<
" ignore ego as oncoming '" << ego->
getID() <<
"\n";
461#ifdef DEBUG_SIGNALSTATE
463 std::cout <<
" ignore " << foe->
getID() <<
" for which ego is join-target\n";
483 if (foeDW->myOrigin !=
nullptr && foeDW->myOrigin->getApproaching().size() > 0) {
484#ifdef DEBUG_SIGNALSTATE
486 std::cout <<
SIMTIME <<
" foeLink=" << foeDW->myOrigin->getDescription() <<
" approachedBy=" << foeDW->myOrigin->getApproaching().begin()->first->getID() <<
"\n";
499 if (!foeDW->myTrains.empty()) {
500#ifdef DEBUG_SIGNALSTATE
505 if (foeDW->myTrains.size() == 1) {
508#ifdef DEBUG_SIGNALSTATE
519 std::pair<bool, const MSDriveWay*> useSiding =
canUseSiding(ego, foeDW);
520#ifdef DEBUG_SIGNALSTATE
525 numSidings = it->second.size();
527 std::cout <<
" ego=" <<
Named::getIDSecure(ego) <<
" useSiding=" << useSiding.first <<
" sidingFoe=" <<
Named::getIDSecure(useSiding.second) <<
" numSidings=" << numSidings <<
"\n";
530 if (useSiding.first) {
540 occupied.push_back(
const_cast<MSEdge*
>(foe->getEdge()));
541 MSEdge* bidi =
const_cast<MSEdge*
>(foe->getEdge()->getBidiEdge());
542 if (bidi !=
nullptr) {
543 occupied.push_back(bidi);
550 SUMOVehicle* foe = *(useSiding.second ==
nullptr ? foeDW : useSiding.second)->
myTrains.begin();
556 }
else if (foeDW !=
this &&
isDepartDriveway() && !foeDW->isDepartDriveway()) {
557 if (foeDW->myOrigin->getApproaching().size() > 0) {
563 if (foeDW->match(firstIt, foe->
getRoute().
end())) {
565#ifdef DEBUG_SIGNALSTATE
567 std::cout <<
SIMTIME <<
" " <<
getID() <<
" blocked by " << foeDW->getID() <<
" (approached by " << foe->
getID() <<
") useSiding=" << useSiding <<
"\n";
582 for (
const std::set<const MSDriveWay*>& dlFoes :
myDeadlocks) {
583 bool allOccupied =
true;
585 if (dlFoe->myTrains.empty()) {
592#ifdef DEBUG_SIGNALSTATE
603 bool foundFoe =
false;
604 while (start < (
int)
myRoute.size() && !foundFoe) {
640 std::string joinVehicle =
"";
642 if (stop !=
nullptr) {
643 joinVehicle = stop->
join;
649 joinVehicle = it->pars.join;
651 if (joinVehicle !=
"") {
652#ifdef DEBUG_SIGNALSTATE
654 std::cout <<
" joinVehicle=" << joinVehicle <<
"\n";
658#ifdef DEBUG_SIGNALSTATE
660 std::cout <<
" ignore join-target '" << joinVehicle <<
"\n";
668#ifdef DEBUG_SIGNALSTATE
670 std::cout <<
" ignore " << foe->
getID() <<
" for which ego is join-target\n";
680std::pair<bool, const MSDriveWay*>
684 for (
auto siding : it->second) {
686 if (ego ==
nullptr || siding.length >= ego->
getLength()) {
689 bool checkNext =
false;
691 if (!sidingApproach->myTrains.empty() && *sidingApproach->myTrains.begin() == ego && sidingEnd == recurseSidingEnd) {
694#ifdef DEBUG_SIGNALSTATE
696 std::cout <<
" checkNext\n";
701 if ((!sidingApproach->myTrains.empty() && *sidingApproach->myTrains.begin() != ego)
704 if (recurseSidingEnd ==
nullptr) {
711 if (foeVeh ==
nullptr) {
717#ifdef DEBUG_SIGNALSTATE
719 std::cout <<
" foe2=" << foe2->
getID() <<
" this2=" << this2->
getID() <<
"\n";
722 if (this2 !=
nullptr && foe2->
canUseSiding(foeVeh, this2, sidingEnd).first) {
727#ifdef DEBUG_SIGNALSTATE
731 <<
" sidingEnd=" << sidingEnd->getID() <<
" sidingApproach=" << sidingApproach->getID() <<
" approaching=" <<
toString(sidingApproach->myTrains) <<
"\n";
734 return std::make_pair(
false, sidingApproach);
738 for (
int i : siding.intermediateEnds) {
741 if (!intermediateApproach->myTrains.empty()
742 && (*intermediateApproach->myTrains.begin() != ego || intermediateEnd == recurseSidingEnd)) {
743 SUMOVehicle* onApproach = *intermediateApproach->myTrains.begin();
749 if (recurseSidingEnd ==
nullptr) {
756 if (foeVeh ==
nullptr) {
762 if (this2 !=
nullptr && foe2->
canUseSiding(foeVeh, this2, intermediateEnd).first) {
767#ifdef DEBUG_SIGNALSTATE
771 <<
" sidingEnd=" << sidingEnd->
getID() <<
" intermediateApproach=" << intermediateApproach->getID() <<
" approaching=" <<
toString(intermediateApproach->myTrains) <<
"\n";
774 return std::make_pair(
false, intermediateApproach);
781#ifdef DEBUG_SIGNALSTATE
785 <<
" sidingEnd=" << sidingEnd->
getID() <<
" usable\n";
788 return std::make_pair(
true,
nullptr);
792#ifdef DEBUG_SIGNALSTATE
797 return std::make_pair(
false,
nullptr);
806 for (
const auto& item : it->second) {
807 if (!item.first->myTrains.empty() && !item.second->myTrains.empty()
811#ifdef DEBUG_SIGNALSTATE
813 std::cout <<
SIMTIME <<
" sidingDeadlock insertionDw=" <<
getID() <<
" approachingDW=" << item.first->
getID() <<
" foeDW=" << item.second->getID() <<
"\n";
821 while (backDist > 0 && prev !=
nullptr) {
833 const bool requiredSiding = !item.first->canUseSiding(*item.first->myTrains.begin(), item.second).first;
835 if (requiredSiding) {
895 if (lane->isNormal() && lane2->isNormal() && lane->getEdge().getToJunction() == lane2->getEdge().getToJunction()) {
898 && &lane->getEdge() !=
myRoute.back()) {
920 for (
int i = 0; i < (int)
myForward.size() - 1; i++) {
988 if (edge2 ==
myForward.front()->getNextNormal() && !secondCheck) {
992 if (
forward.count(edge2->getBidiEdge()) != 0) {
1026 std::vector<std::string> signals;
1033 std::vector<std::string> foes;
1035 foes.push_back(dw->myID);
1037 if (foes.size() > 0) {
1044 od.
writeAttr(
"foe", item.first->getID());
1045 for (
auto siding : item.second) {
1050 if (siding.intermediateEnds.size() > 0) {
1051 std::vector<std::string> endEdges;
1052 for (
int i : siding.intermediateEnds) {
1055 od.
writeAttr(
"intermediateEnds", endEdges);
1070 sub->writeBlocks(od);
1072#ifdef DRIVEWAY_SANITY_CHECK
1073 std::set<MSDriveWay*> uFoes(
myFoes.begin(),
myFoes.end());
1074 if (uFoes.size() !=
myFoes.size()) {
1087 od.
openTag(ve.isEntry ?
"entry" :
"exit");
1096 sub->writeBlockVehicles(od);
1105 std::set<MSLink*, MSLink::ComparatorNumericalLaneIdLess>& flankSwitches) {
1107 bool seekForwardSignal =
true;
1108 bool seekBidiSwitch =
true;
1109 bool foundUnsafeSwitch =
false;
1111 const std::string warnID = origin ?
"rail signal " +
getClickableTLLinkID(origin) :
"insertion lane '" + toLane->
getID() +
"'";
1112#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1123 WRITE_WARNINGF(
"Block after % exceeds maximum length (stopped searching after edge '%' (length=%m).",
1129#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1131 std::cout <<
" abort: length=" << length <<
"\n";
1136#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1151 if (seekForwardSignal) {
1152 if (!foundUnsafeSwitch) {
1167 }
else if (bidi ==
nullptr) {
1169#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1171 std::cout <<
" continue bidiSearch beyond turnaround\n";
1175 seekBidiSwitch =
false;
1176#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1178 std::cout <<
" noBidi, abort search for bidiSwitch\n";
1183 if (bidi !=
nullptr) {
1184 if (!seekForwardSignal && !foundUnsafeSwitch && bidi->
isNormal()) {
1190 if (!
myBidi.empty() && link->getViaLaneOrLane() !=
myBidi.back()) {
1193#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1195 std::cout <<
" found unsafe switch " << link->
getDescription() <<
" (used=" << (used ==
nullptr ?
"NULL" : used->
getDescription()) <<
")\n";
1199 foundUnsafeSwitch =
true;
1201 if (used !=
nullptr) {
1203 flankSwitches.insert(used);
1209 if (foundUnsafeSwitch) {
1215 const std::vector<MSLink*>& links = toLane->
getLinkCont();
1217 for (
const MSLink*
const link : links) {
1218 if ((next != end && &link->getLane()->getEdge() == *next)) {
1219 toLane = link->getViaLaneOrLane();
1221 if (link == origin) {
1222 if (seekForwardSignal) {
1227#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1229 std::cout <<
" abort: found circle\n";
1234 seekForwardSignal =
false;
1236 seekBidiSwitch = bidi !=
nullptr;
1237#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1239 std::cout <<
" found forwardSignal " << link->getTLLogic()->
getID() <<
" seekBidiSwitch=" << seekBidiSwitch <<
"\n";
1249 if (link->getLane()->getBidiLane() !=
nullptr && &link->getLane()->getEdge() == current->
getBidiEdge()) {
1257 if (toLane ==
nullptr) {
1260 toLane = (*next)->getLanes()[0];
1261#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1263 std::cout <<
" abort: turn-around or jump\n";
1269#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1271 std::cout <<
" abort: no next lane available\n";
1280#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1282 std::cout <<
" normalEnd myBidiEnded=" <<
myBidiEnded <<
"\n";
1291 if (other->getLane() != link->
getLane() && !other->isTurnaround()) {
1296 if (ili.viaLink != link && !ili.viaLink->
isTurnaround()) {
1301 if (bidi !=
nullptr) {
1314 bool allFoes,
bool movingBlock, std::set<MSLink*, MSLink::ComparatorNumericalLaneIdLess>& flankSwitches)
const {
1315#ifdef DEBUG_CHECK_FLANKS
1317 std::cout <<
" checkFlanks lanes=" <<
toString(lanes) <<
" allFoes=" << allFoes <<
"\n";
1324 if (reverseOriginLink !=
nullptr) {
1328 for (
int i = 0; i < (int)lanes.size(); i++) {
1329 const MSLane* lane = lanes[i];
1330 const MSLane* prev = i > 0 ? lanes[i - 1] :
nullptr;
1331 const MSLane* next = i + 1 < (int)lanes.size() ? lanes[i + 1] :
nullptr;
1336 if (ili.viaLink == originLink
1337 || ili.viaLink == reverseOriginLink
1340 || (originLink ==
nullptr && i == 0 && movingBlock)) {
1343 if (ili.lane != prev && ili.lane != next) {
1344#ifdef DEBUG_CHECK_FLANKS
1346 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";
1349 flankSwitches.insert(ili.viaLink);
1350 }
else if (allFoes) {
1361#ifdef DEBUG_CHECK_FLANKS
1367 if (junction ==
nullptr) {
1371 if (logic ==
nullptr) {
1375 if (in->isInternal()) {
1378 for (
MSLane* inLane : in->getLanes()) {
1380 if (
isRailwayOrShared(inLane->getPermissions()) && visited.count(inLane) == 0 && (inBidi ==
nullptr || visited.count(inBidi) == 0)) {
1381 for (
MSLink* link : inLane->getLinkCont()) {
1382 if (link->getIndex() >= 0 && logic->
getFoesFor(dwLink->
getIndex()).test(link->getIndex())
1383 && visited.count(link->getLane()) == 0) {
1384#ifdef DEBUG_CHECK_FLANKS
1386 std::cout <<
" add crossing flankSwitch junction=" << junction->
getID() <<
" index=" << link->getIndex() <<
"\n";
1389 if (link->getViaLane() ==
nullptr) {
1390 flankSwitches.insert(link);
1392 flankSwitches.insert(link->getViaLane()->getLinkCont().front());
1403#ifdef DEBUG_CHECK_FLANKS
1411#ifdef DEBUG_CHECK_FLANKS
1413 std::cout <<
" flank guarded by " << entry->
getTLLogic()->
getID() <<
"\n";
1422 std::vector<MSLink*> predLinks;
1424 if (!ili.viaLink->isTurnaround()) {
1425 predLinks.push_back(ili.viaLink);
1428 if (predLinks.size() > 1) {
1430#ifdef DEBUG_ADD_FOES
1432 std::cout <<
" predecessors of " << link->
getDescription() <<
" isSwitch\n";
1436 for (
MSLink* pred : predLinks) {
1439 }
else if (predLinks.size() == 1) {
1451#ifdef DEBUG_ADD_FOES
1453 std::cout <<
" foe " << foe->getID() <<
" departs on flank=" << lane->
getID() <<
"\n";
1458#ifdef DEBUG_ADD_FOES
1460 std::cout <<
" cand foe " << foe->getID() <<
" departs on flank=" << lane->
getID() <<
" rejected\n";
1474#ifdef DEBUG_ADD_FOES
1476 std::cout <<
" driveway " <<
myID <<
" addSwitchFoes for link " << link->
getDescription() <<
"\n";
1481#ifdef DEBUG_ADD_FOES
1482 if (
gDebugFlag4) std::cout <<
" foe=" << foe->myID
1483 <<
" fc1=" <<
flankConflict(*foe) <<
" fc2=" << foe->flankConflict(*
this)
1484 <<
" cc1=" <<
crossingConflict(*foe) <<
" cc2=" << foe->crossingConflict(*
this) <<
"\n";
1488#ifdef DEBUG_ADD_FOES
1490 std::cout <<
" cand=" << foe->myID <<
"\n";
1525 std::vector<const MSLane*> before;
1526 MSLane* fromBidi =
nullptr;
1527 if (link !=
nullptr) {
1531 std::set<MSLink*, MSLink::ComparatorNumericalLaneIdLess> flankSwitches;
1533 if (fromBidi !=
nullptr) {
1534 before.push_back(fromBidi);
1536#ifdef DEBUG_BUILD_DRIVEWAY
1539 dw->
buildRoute(link, first, end, visited, flankSwitches);
1545 const bool movingBlock = (rs && rs->
isMovingBlock()) || (!rs &&
1551 dw->
checkFlanks(link, before, visited,
true, movingBlock, flankSwitches);
1552 for (
MSLink* fsLink : flankSwitches) {
1553#ifdef DEBUG_ADD_FOES
1555 std::cout <<
" fsLink=" << fsLink->getDescription() <<
"\n";
1560 std::set<MSLink*, MSLink::ComparatorNumericalLaneIdLess> flankSwitchesBidiExtended;
1562 for (
MSLink*
const flink : flankSwitchesBidiExtended) {
1563#ifdef DEBUG_ADD_FOES
1565 std::cout <<
" fsLinkExtended=" << flink->getDescription() <<
"\n";
1570#ifdef DEBUG_BUILD_DRIVEWAY
1572 std::cout <<
SIMTIME <<
" buildDriveWay " << dw->
myID <<
" link=" << (link ==
nullptr ?
"NULL" : link->
getDescription())
1597 std::set<MSDriveWay*, ComparatorNumericalIdLess> uniqueFoes(dw->
myFoes.begin(), dw->
myFoes.end());
1600 if (movingBlock && uniqueFoes.count(dw) == 0) {
1601 std::map<const MSJunction*, std::vector<const MSLink*> > forwardJunctions;
1602 int iLast = (int)dw->
myForward.size() - 1;
1603 bool selfIntersect =
false;
1604 for (
int i = 0; i < iLast && !selfIntersect; i++) {
1609 if (fwLink !=
nullptr) {
1610 for (
const MSLink* link2 : forwardJunctions[fwTo]) {
1611 const std::vector<MSLink*>& foeLinks = fwLink->
getFoeLinks();
1612 const std::vector<MSLink*>& foeLinks2 = link2->getFoeLinks();
1613 if (std::find(foeLinks.begin(), foeLinks.end(), link2) != foeLinks.end()
1614 || std::find(foeLinks2.begin(), foeLinks2.end(), fwLink) != foeLinks2.end()
1617 dw->
myFoes.push_back(dw);
1618 selfIntersect =
true;
1619#ifdef DEBUG_ADD_FOES
1621 std::cout <<
" self-intersecting movingBlock for dw=" << dw->
getID() <<
" at junction " << fwTo->
getID() <<
" fwLink=" << fwLink->
getDescription() <<
" link2=" << link2->getDescription() <<
"\n";
1627 forwardJunctions[fwTo].push_back(fwLink);
1635 const MSEdge* foeLastEdge = &foe->myForward.back()->getEdge();
1636 const bool sameLast = foeLastEdge == lastEdge;
1637 if (sameLast && !movingBlock) {
1638 dw->
myFoes.push_back(foe);
1640 foe->myFoes.push_back(dw);
1643 if (foe->bidiBlockedByEnd(*dw)) {
1644#ifdef DEBUG_ADD_FOES
1646 std::cout <<
" setting " << dw->
getID() <<
" as foe of " << foe->getID() <<
"\n";
1649 foe->myFoes.push_back(dw);
1650 foe->addSidings(dw);
1656#ifdef DEBUG_ADD_FOES
1658 std::cout <<
" addFoeCheckSiding " << foe->getID() <<
"\n";
1661 dw->
myFoes.push_back(foe);
1664 foe->buildSubFoe(dw, movingBlock);
1669 foe->addConflictLink(link);
1672 if (foe->myRoute.front()->getFromJunction() != dw->
myRoute.front()->getFromJunction()) {
1673 for (
auto ili : foe->myForward.front()->getIncomingLanes()) {
1674 if (ili.viaLink->getTLLogic() !=
nullptr) {
1676 const MSLane* origin = ili.viaLink->getLaneBefore();
1678 uniqueCLink.insert(ili.viaLink);
1690 if (uniqueFoes.count(sameEnd) == 0) {
1691 dw->
myFoes.push_back(sameEnd);
1692 if (sameEnd != dw) {
1693 sameEnd->myFoes.push_back(dw);
1698#ifdef DEBUG_BUILD_DRIVEWAY
1700 std::cout << dw->
myID <<
" mb=" << movingBlock <<
" finalFoes " <<
toString(dw->
myFoes) <<
"\n";
1746 const int tmp = (int)map.size();
1753 auto itRoute = firstIt;
1754 auto itDwRoute =
myRoute.begin();
1756 while (itRoute != endIt && itDwRoute !=
myRoute.end()) {
1757 if (*itRoute != *itDwRoute) {
1760 std::cout <<
" check dw=" <<
getID() <<
" match failed at vehEdge=" << (*itRoute)->getID() <<
" dwEdge=" << (*itDwRoute)->getID() <<
"\n";
1772 if (itRoute != endIt) {
1774 const MSEdge* next = *itRoute;
1779 std::cout <<
" check dw=" <<
getID() <<
" prev=" << prev->
getID() <<
" next=" << next->
getID() <<
"\n";
1791 if (
myForward.back()->isInternal() &&
myForward.back()->getNextNormal() != (*itRoute)) {
1806#ifdef DEBUG_ADD_FOES
1808 std::cout <<
"driveway " <<
myID <<
" addFoes for link " << link->
getDescription() <<
"\n";
1812 if (rs !=
nullptr) {
1814#ifdef DEBUG_ADD_FOES
1816 std::cout <<
" cand foe=" << foe->
myID <<
" fc1=" <<
flankConflict(*foe) <<
" fc2=" << foe->flankConflict(*
this) <<
" cc1=" <<
crossingConflict(*foe) <<
" cc2=" << foe->crossingConflict(*
this) <<
"\n";
1820#ifdef DEBUG_ADD_FOES
1822 std::cout <<
" foe=" << foe->myID <<
"\n";
1834#ifdef DEBUG_ADD_FOES
1836 std::cout <<
"driveway " <<
myID <<
" addBidiFoes extended=" << extended <<
"\n";
1840 for (
const MSLane* bidi : bidiLanes) {
1841 for (
auto ili : bidi->getIncomingLanes()) {
1843 if (rs !=
nullptr && rs != ownSignal &&
1844 std::find(bidiLanes.begin(), bidiLanes.end(), ili.lane) != bidiLanes.end()) {
1848 const MSEdge* bidiEdge = &bidi->getEdge();
1852#ifdef DEBUG_ADD_FOES
1854 std::cout <<
" foe " << foe->
getID() <<
" departs on bidi=" << bidiEdge->
getID() <<
"\n";
1859#ifdef DEBUG_ADD_FOES
1861 std::cout <<
" cand foe " << foe->getID() <<
" departs on bidi=" << bidiEdge->
getID() <<
" rejected\n";
1870#ifdef DEBUG_ADD_FOES
1872 std::cout <<
" foe " << foe->getID() <<
" ends on bidi=" << bidiEdge->
getID() <<
"\n";
1877#ifdef DEBUG_ADD_FOES
1879 std::cout <<
" cand foe " << foe->getID() <<
" ends on bidi=" << bidiEdge->
getID() <<
" rejected\n";
1891#ifdef DEBUG_ADD_FOES
1893 std::cout <<
"driveway " <<
myID <<
" addParallelFoes\n";
1902#ifdef DEBUG_ADD_FOES
1904 std::cout <<
" foe " << foe->getID() <<
" departs on first=" << first->
getID() <<
"\n";
1916#ifdef DEBUG_ADD_FOES
1918 std::cout <<
"driveway " <<
myID <<
" addReversalFoes\n";
1921 std::set<const MSEdge*>
forward;
1923 if (lane->isNormal()) {
1924 forward.insert(&lane->getEdge());
1929 if (
forward.count(e) != 0 && !movingBlock) {
1943#ifdef DEBUG_ADD_FOES
1947 std::set<const MSEdge*> foeForward;
1948 for (
const MSLane* lane : foe->myForward) {
1949 if (lane->isNormal()) {
1950 foeForward.insert(&lane->getEdge());
1951 if (lane->getBidiLane() !=
nullptr) {
1952 foeForward.insert(lane->getEdge().getBidiEdge());
1956#ifdef DEBUG_ADD_FOES
1958 std::cout <<
" reversal cand=" << foe->getID() <<
" foeForward " <<
toString(foeForward) <<
"\n";
1961 if (foe->forwardRouteConflict(foeForward, *
this,
true)) {
1962#ifdef DEBUG_ADD_FOES
1964 std::cout <<
" foe " << foe->getID() <<
" reverses on edge=" << e->getID() <<
"\n";
1969 }
else if (movingBlock && foe ==
this) {
1970#ifdef DEBUG_ADD_FOES
1972 std::cout <<
" dw " <<
getID() <<
" reverses on forward edge=" << e->getID() <<
" (movingBlock)\n";
1996#ifdef DEBUG_BUILD_SUBDRIVEWAY
1998 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" is subpart of foe=" << foe->
getID() <<
"\n";
2001 foe->
myFoes.push_back(
this);
2004 int subLast = (int)
myForward.size() - 2;
2008#ifdef DEBUG_BUILD_SUBDRIVEWAY
2011 std::cout <<
" " <<
getID() <<
" cannot build subDriveWay for foe " << foe->
getID() <<
" because myForward has only a single lane\n";
2015 bool foundConflict =
false;
2016 bool flankC =
false;
2017 bool zipperC =
false;
2018 bool crossC =
false;
2019 while (subLast >= 0) {
2030 const bool bidiConflict = std::find(foe->
myBidi.begin(), foe->
myBidi.end(), lane) != foe->
myBidi.end();
2032#ifdef DEBUG_BUILD_SUBDRIVEWAY
2034 std::cout <<
" subLast=" << subLast <<
" lane=" << lane->
getID() <<
" fc=" << flankC <<
" cc=" << crossC <<
" bc=" << bidiConflict <<
"\n";
2037 if (flankC || crossC || bidiConflict) {
2038 foundConflict =
true;
2039 if (!movingBlock || bidiConflict) {
2047 foundConflict =
false;
2048#ifdef DEBUG_BUILD_SUBDRIVEWAY
2050 std::cout <<
" ignored movingBlock zipperConflict\n";
2053 if (!flankC && crossC) {
2054#ifdef DEBUG_BUILD_SUBDRIVEWAY
2056 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" movingBlock-save\n";
2062 if (!flankC && crossC) {
2065 }
else if (foundConflict) {
2070#ifdef DEBUG_BUILD_SUBDRIVEWAY
2072 std::cout <<
" subLastFinal=" << subLast <<
" movingBlock=" << movingBlock <<
" zipperC=" << zipperC <<
"\n";
2085 if (
forward == foeAfterForward ) {
2086 foe->
myFoes.push_back(
this);
2089#ifdef DEBUG_BUILD_SUBDRIVEWAY
2091 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" special case 1\n";
2098 if (movingBlock && zipperC) {
2099#ifdef DEBUG_BUILD_SUBDRIVEWAY
2101 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" movingBlock-save\n";
2107 foe->
myFoes.push_back(
this);
2108#ifdef DEBUG_BUILD_SUBDRIVEWAY
2110 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" foe endsOnForward\n";
2115 foe->
myFoes.push_back(
this);
2119#ifdef DEBUG_BUILD_SUBDRIVEWAY
2121 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" terminates\n";
2125 foe->
myFoes.push_back(
this);
2126#ifdef DEBUG_BUILD_SUBDRIVEWAY
2128 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" terminates, foe=" << foe->
getID() <<
"\n";
2133#ifdef DEBUG_BUILD_SUBDRIVEWAY
2135 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" has " << foe->
myReversals.size() <<
" reversals\n";
2139#ifdef DEBUG_BUILD_SUBDRIVEWAY
2141 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" failed\n";
2144#ifdef SUBDRIVEWAY_WARN_NOCONFLICT
2145 WRITE_WARNINGF(
"No point of conflict found between driveway '%' and driveway '%' when creating sub-driveway",
getID(), foe->
getID());
2150 int subSize = subLast + 1;
2152 if ((
int)cand->myForward.size() == subSize) {
2154 foe->
myFoes.push_back(cand);
2158 cand->myFoes.push_back(foe);
2159#ifdef DEBUG_BUILD_SUBDRIVEWAY
2161 std::cout <<
SIMTIME <<
" buildSubFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" useExisting=" << cand->getID() <<
"\n";
2168 std::vector<const MSEdge*> route;
2170 if (lane->isNormal()) {
2171 route.push_back(&lane->getEdge());
2174 if (route.empty()) {
2175 if (subSize == 1 && crossC
2176 &&
forward.front()->getFromJunction() == foe->
myForward.front()->getFromJunction()
2178 assert(
myForward.front()->isInternal());
2180 route.push_back(foe->
myForward.front()->getEdge().getNormalSuccessor());
2182#ifdef DEBUG_BUILD_SUBDRIVEWAY
2184 std::cout <<
SIMTIME <<
" abort subFoe dw=" <<
getID() <<
" foe=" << foe->
getID() <<
" empty subRoute\n";
2190 if (
myRoute.size() > route.size()) {
2192 const MSEdge* lastNormal = route.back();
2195#ifdef DEBUG_BUILD_SUBDRIVEWAY
2197 <<
" lastNormal=" << lastNormal->
getID() <<
" nextNormal=" << nextNormal->
getID() <<
" endWithReversal\n";
2212 auto itOnSub = std::find(sub->
myRoute.begin(), sub->
myRoute.end(), veh->getEdge());
2213 if (itOnSub != sub->
myRoute.end()) {
2216 const double pos = sub->
myRoute.front()->getLength();
2219 if (ve.id == veh->getID()) {
2226 foe->
myFoes.push_back(sub);
2230 sub->
myFoes.push_back(foe);
2232#ifdef DEBUG_BUILD_SUBDRIVEWAY
2243 assert(lastIndex < (
int)
myForward.size());
2245 for (
int i = 0; i <= lastIndex; i++) {
2255 const MSEdge* foeEndBidi = foe->
myForward.back()->getEdge().getBidiEdge();
2256 int foeForwardNormals = 0;
2258 if (lane->isNormal()) {
2259 foeForwardNormals++;
2262 if (foeForwardNormals == (
int)foeRoute.size()) {
2263#ifdef DEBUG_BUILD_SIDINGS
2265 std::cout <<
"checkSiding " <<
getID() <<
" foe=" << foe->
getID() <<
" foeForwardNormals=" << foeForwardNormals <<
" frSize=" << foeRoute.size() <<
" aborted\n";
2270 auto foeSearchBeg = foeRoute.begin() + foeForwardNormals;
2271 auto foeSearchEnd = foeRoute.end();
2272 if (foeEndBidi ==
nullptr) {
2277 std::set<const MSEdge*> foeForwardEdges(foeRoute.begin(), foeRoute.begin() + foeForwardNormals);
2278 int forwardNormals = 0;
2280 if (lane->isNormal()) {
2282 if (foeForwardEdges.count(&lane->getEdge()) != 0) {
2283#ifdef DEBUG_BUILD_SIDINGS
2285 std::cout <<
"checkSiding " <<
getID() <<
" foe=" << foe->
getID() <<
" forwardEdge=" << lane->getEdge().getID() <<
" on foeForward (sidings unsafe)\n";
2293 std::vector<int> start;
2294 std::vector<double> length;
2295 std::vector<std::vector<int> > intermediateRS;
2296 for (i = 0; i < (int)
myRoute.size(); i++) {
2297 if (
myRoute[i] == foeEndBidi) {
2301 if (i == (
int)
myRoute.size()) {
2305#ifdef DEBUG_BUILD_SIDINGS
2307 std::cout <<
"checkSiding " <<
getID() <<
" foe=" << foe->
getID() <<
" i=" << i <<
" next=" << next->
getID() <<
" foeForwardNormals=" << foeForwardNormals <<
" frSize=" << foeRoute.size() <<
" foeSearchBeg=" << (*foeSearchBeg)->getID() <<
" addToFoe=" << addToFoe <<
"\n";
2312 for (; i >= 0; i--) {
2314 const bool curHasRS =
hasRS(cur, next);
2316 if (std::find(foeSearchBeg, foeSearchEnd, cur->
getBidiEdge()) == foeSearchEnd) {
2319 length.push_back(0);
2320 intermediateRS.push_back({});
2323 if (!start.empty()) {
2325 auto itFind = std::find(foeSearchBeg, foeSearchEnd, cur->
getBidiEdge());
2326 if (itFind != foeSearchEnd) {
2327#ifdef DEBUG_BUILD_SIDINGS
2332 const int firstIndex = i + 1;
2334 auto& foeSidings = foe->
mySidings[
this];
2337 auto itFirst = std::find(foeRoute.begin(), foeRoute.end(), first);
2338 if (itFirst != foeRoute.end()) {
2339 for (
int j = 0; j < (int)length.size(); j++) {
2341 auto itLast = std::find(itFirst, foeRoute.end(), last);
2342 if (itLast != foeRoute.end()) {
2344 foeSidings.insert(foeSidings.begin(),
Siding((
int)(itFirst - foeRoute.begin()), (
int)(itLast - foeRoute.begin()), length[j], {}));
2345#ifdef DEBUG_BUILD_SIDINGS
2347 std::cout <<
" found endSiding start=" << foeSidings.front().start <<
" end=" << foeSidings.front().end <<
" length=" << foeSidings.front().length <<
"\n";
2350 if (foeSidings.size() > 2) {
2351 foeSidings.pop_back();
2358 std::vector<int> furtherRS;
2360 furtherRS.push_back(i);
2362 const MSEdge* next2 = cur;
2363 for (
int i2 = i - 1; i2 >= forwardNormals; i2--) {
2365 if (
hasRS(cur2, next2)) {
2366 furtherRS.push_back(i2);
2371 for (
int j = 0; j < (int)length.size(); j++) {
2372 intermediateRS[j].insert(intermediateRS[j].end(), furtherRS.begin(), furtherRS.end());
2373 foeSidings.insert(foeSidings.begin(),
Siding(firstIndex, start[j], length[j], intermediateRS[j]));
2374#ifdef DEBUG_BUILD_SIDINGS
2376 std::cout <<
" found endSiding start=" << foeSidings.front().start <<
" end=" << foeSidings.front().end <<
" length=" << foeSidings.front().length <<
"\n";
2379 if (foeSidings.size() > 2) {
2380 foeSidings.pop_back();
2386 intermediateRS.clear();
2387 foeSearchBeg = itFind;
2389 for (
int j = 0; j < (int)length.size(); j++) {
2391 if (curHasRS && i != start[j]) {
2392 intermediateRS[j].push_back(i);
2404 for (
const auto& siding : it->second) {
2415 for (
auto lane : cur->
getLanes()) {
2416 for (
const MSLink* link : lane->getLinkCont()) {
2417 if (&link->getLane()->getEdge() == next && link->getTLLogic() !=
nullptr) {
2429 const MSEdge* foeForwardEnd = &foe->
myForward.back()->getNormalPredecessorLane()->getEdge();
2451 std::set<const MSDriveWay*> filtered;
2456 filtered.insert(foe);
2470 for (
auto ili : lane->getIncomingLanes()) {
2473 if (rs !=
nullptr) {
2475 if (&dw->
myForward.front()->getEdge() == edge) {
2484 if (dw->match(matchStart, veh->
getRoute().
end())) {
2497const std::vector<MSDriveWay*>&
2511 const MSEdge* edge = item.first;
2512 if (item.second.size() > 0) {
2516 if (writeVehicles) {
2517 dw->writeBlockVehicles(od);
2519 dw->writeBlocks(od);
2532 dw->_saveState(out);
2534 sub->_saveState(out);
2547 std::vector<std::string> trainIDs;
2549 trainIDs.push_back(veh->getID());
2561 if (!sub->myTrains.empty()) {
2579 const std::string
id = attrs.
get<std::string>(
SUMO_ATTR_ID,
nullptr, ok);
2597 std::string parentID =
id.substr(0,
id.rfind(
'.'));
2605 if (sub->myRoute == route) {
2610 if (dw ==
nullptr) {
2619 if (veh ==
nullptr) {
2620 throw ProcessError(
TLF(
"Unknown vehicle '%' in driveway '%'", vehID,
id));
2632 if (dw->getID() == id) {
2653 result += (*it)->getLength();
#define DEBUG_HELPER(obj)
#define DEBUG_COND_DW(obj)
std::vector< const MSEdge * > ConstMSEdgeVector
std::vector< MSEdge * > MSEdgeVector
ConstMSEdgeVector::const_iterator MSRouteIterator
#define WRITE_WARNINGF(...)
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
bool isRailwayOrShared(SVCPermissions permissions)
Returns whether an edge with the given permissions is a railway edge or a shared road/rail 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
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.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
void addReminder(MSMoveReminder *rem, double pos=0)
Adds a MoveReminder dynamically.
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
Whether 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
bool myAbortedBuild
whether driveway building was aborted due to MAX_BLOCK_LENGTH
bool buildSubFoe(MSDriveWay *foe, bool movingBlock)
std::set< SUMOVehicle *, ComparatorNumericalIdLess > myTrains
static std::map< const MSJunction *, int > myDepartDrivewayIndex
std::vector< const MSLane * > myBidiExtendedSorted
static const std::vector< MSDriveWay * > EMPTY_DRIVEWAY_VECTOR
void buildRoute(const MSLink *origin, MSRouteIterator next, MSRouteIterator end, LaneVisitedMap &visited, std::set< MSLink *, MSLink::ComparatorNumericalLaneIdLess > &)
const MSDriveWay * getFoeOrSubFoe(const MSDriveWay *dw) const
return dw if it is a foe or a subDrivway of dw if it is a foe
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
static double myMovingBlockMaxDist
std::vector< const MSLane * > myBidi
static std::vector< const MSEdge * > myCurrentSidingCheck
static bool myWriteVehicles
bool notifyReroute(SUMOTrafficObject &veh)
Called if the vehicle change it's route.
bool hasLinkConflict(const Approaching &closest, const MSLink *foeLink) const
Whether the approaching vehicle is prevent from driving by another vehicle approaching the given link...
std::vector< const MSLane * > myBidiExtended
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
static const MSDriveWay * retrieveDepartDriveWay(const MSEdge *edge, const std::string &id)
static std::map< const MSEdge *, std::vector< std::pair< MSDriveWay *, MSDriveWay * > >, ComparatorNumericalIdLess > mySidingDriveways
all driveways that use a siding which ends on this edge as pair (dw, foe)
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.
bool sidingDeadlock(const SUMOVehicle *veh) const
whether insertion on this driveway would cause deadlock in an approached siding
std::vector< const MSLane * > myForward
std::vector< const MSEdge * > myReversals
track own occurences in myReversalDriveWays for cleanup in destructor
static const std::vector< MSDriveWay * > & getEndingDriveWays(const MSEdge *edge)
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
Whether 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
int getNumericalID() const
static std::set< const MSEdge * > myBlockLengthWarnings
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
void checkFlanks(const MSLink *originLink, const std::vector< const MSLane * > &lanes, const LaneVisitedMap &visited, bool allFoes, bool movingBlock, std::set< MSLink *, MSLink::ComparatorNumericalLaneIdLess > &flankSwitches) const
static std::map< std::string, MSDriveWay * > myDriveWayLookup
int matchesPastRoute(SUMOVehicle &sveh) const
void checkCrossingFlanks(MSLink *dwLink, const LaneVisitedMap &visited, std::set< MSLink *, MSLink::ComparatorNumericalLaneIdLess > &flankSwitches) const
bool flankConflict(const MSDriveWay &other) const
Whether 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)
bool hasTrain(SUMOVehicle *veh) const
whether the given train is on this driveway
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
double getForwardDistance(int lastIndex) const
compute distance along the forward section up to lastIndex
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.
MSDriveWay * myParent
set to parent driveway if this is a subDriveway, nullptr otherwise
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.
void findFlankProtection(MSLink *link, MSLink *origLink, const std::vector< const MSLane * > &flank)
void addSidings(MSDriveWay *foe, bool addToFoe=false)
add sidings for the given foe
void enterDriveWay(SUMOVehicle &sveh, Notification reason)
helper method for notifyEnter
bool bidiBlockedByEnd(const MSDriveWay &other) const
Whether there is a bidi conflict with the end of the given driveway.
static int myGlobalDriveWayIndex
bool isSubDriveWay() const
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)
void addReversalFoes(bool movingBlock)
derive foe driveways that enter the bidi section by reversing
int myForwardEdgeCount
number of normal edges in myForward
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)
Whether the route of other passes into the forward section of this driveway.
std::vector< const MSLane * > myConflictLanes
the lanes that must be clear of trains before this signal can switch to green
static const MSDriveWay * getDepartureDriveway(const SUMOVehicle *veh, bool init=false)
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
Whether 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::pair< bool, const MSDriveWay * > canUseSiding(const SUMOVehicle *ego, const MSDriveWay *foe, const MSEdge *recurseSidingEnd=nullptr) const
return whether a siding can be used. If a siding exist but is occupied, also return the occupied driv...
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)
double getParentRemainingLength() const
return for how much longer the parent driveway continues after the end of this subdriveway
A road/street connecting two junctions.
static void clear()
Clears the dictionary.
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 * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
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
bool isConnectedTo(const MSEdge &destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions=false) const
static MELoop * gMesoNet
mesoscopic simulation infrastructure
static SUMOTime gTimeToTeleportRSDeadlock
static double gMaxRailSignalBlockLength
The maximum length of a rail signal block.
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.
static void clear()
Clears the dictionary.
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
virtual void addMoveReminder(MSMoveReminder *rem, bool addToVehicles=true)
Add a move-reminder to move-reminder container.
const MSJunction * getToJunction() const
double getLength() const
Returns the lane's length.
const MSJunction * getFromJunction() const
int getIndex() const
Returns the lane's index.
MSLane * getLogicalPredecessorLane() const
get the most likely predecessor lane (sorted using by_connections_to_sorter). The result is cached in...
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 !!!
bool isTLSControlled() const
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
const std::vector< MSLink * > & getFoeLinks() 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_REROUTE
The vehicle changed it's route.
@ 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.
static StringBijection< Notification > Notifications
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()
static bool isUsingDriveWays(SVCPermissions svc)
static bool isMovingBlock(SVCPermissions svc)
bool isMovingBlock() const
const MSDriveWay & getExistingDriveWay(const MSLink *link, MSRouteIterator firstIt, MSRouteIterator endIt)
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()
const ConstMSEdgeVector & getEdges() const
MSRouteIterator end() const
Returns the end of the list of edges to pass.
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
The parent class for traffic light logics.
TrafficLightType getLogicType() const
Returns the type of the logic.
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.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
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 & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
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 MSEdge * getCurrentEdge() const =0
Returns the edge (normal or internal) the object is currently at.
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 SUMOVehicleClass getVClass() const =0
Returns the object's access class.
virtual const MSEdge * getEdge() const =0
Returns the (normal) route 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 int getDepartEdge() const =0
Returns the edge on which this vehicle shall depart.
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 int getRoutePosition() const =0
return index of edge within route
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
const std::string & getString(const T key) const
get string
std::vector< std::string > getVector()
return vector of strings
#define UNUSED_PARAMETER(x)
Function-object for stable sorting of objects with numerical ids.