LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSRailSignal.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 72.6 % 340 247
Test Date: 2025-11-13 15:38:19 Functions: 59.3 % 54 32

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MSRailSignal.cpp
      15              : /// @author  Melanie Weber
      16              : /// @author  Andreas Kendziorra
      17              : /// @author  Jakob Erdmann
      18              : /// @date    Jan 2015
      19              : ///
      20              : // A rail signal logic
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <cassert>
      25              : #include <utility>
      26              : #include <vector>
      27              : #include <bitset>
      28              : #ifdef HAVE_FOX
      29              : #include <utils/foxtools/MFXWorkerThread.h>
      30              : #endif
      31              : #include <utils/iodevices/OutputDevice_COUT.h>
      32              : #include <microsim/MSEventControl.h>
      33              : #include <microsim/MSNet.h>
      34              : #include <microsim/MSEdge.h>
      35              : #include <microsim/MSEdgeControl.h>
      36              : #include <microsim/MSLane.h>
      37              : #include <microsim/MSLink.h>
      38              : #include <microsim/MSVehicle.h>
      39              : #include <microsim/devices/MSDevice_Routing.h>
      40              : #include <microsim/devices/MSRoutingEngine.h>
      41              : #include <microsim/MSLane.h>
      42              : 
      43              : #include "MSTLLogicControl.h"
      44              : #include "MSTrafficLightLogic.h"
      45              : #include "MSPhaseDefinition.h"
      46              : #include "MSTLLogicControl.h"
      47              : #include "MSRailSignalConstraint.h"
      48              : #include "MSRailSignalControl.h"
      49              : #include "MSDriveWay.h"
      50              : #include "MSRailSignal.h"
      51              : 
      52              : //#define DEBUG_SELECT_DRIVEWAY
      53              : //#define DEBUG_DRIVEWAY_UPDATE
      54              : //#define DEBUG_SIGNALSTATE
      55              : //#define DEBUG_REROUTE
      56              : 
      57              : #define DEBUG_COND DEBUG_HELPER(this)
      58              : #define DEBUG_COND_LINKINFO DEBUG_HELPER(myLink->getTLLogic())
      59              : #define DEBUG_HELPER(obj) ((obj)->isSelected())
      60              : //#define DEBUG_HELPER(obj) ((obj)->getID() == "")
      61              : //#define DEBUG_HELPER(obj) (true)
      62              : 
      63              : // ===========================================================================
      64              : // static value definitions
      65              : // ===========================================================================
      66              : 
      67              : bool MSRailSignal::myStoreVehicles(false);
      68              : MSRailSignal::VehicleVector MSRailSignal::myBlockingVehicles;
      69              : MSRailSignal::VehicleVector MSRailSignal::myRivalVehicles;
      70              : MSRailSignal::VehicleVector MSRailSignal::myPriorityVehicles;
      71              : std::string MSRailSignal::myConstraintInfo;
      72              : int MSRailSignal::myRSIndex(0);
      73              : std::vector<const MSDriveWay*> MSRailSignal::myBlockingDriveWays;
      74              : std::string MSRailSignal::myRequestedDriveWay;
      75              : 
      76              : // ===========================================================================
      77              : // method definitions
      78              : // ===========================================================================
      79         4601 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
      80              :                            const std::string& id, const std::string& programID, SUMOTime delay,
      81         4601 :                            const Parameterised::Map& parameters) :
      82              :     MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
      83         4601 :     myNumericalID(myRSIndex++),
      84        13803 :     myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
      85         4601 :     myPhaseIndex(0),
      86         4601 :     myDriveWayIndex(0) {
      87         4601 :     myDefaultCycleTime = DELTA_T;
      88         4601 :     myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
      89         4601 :     mySwitchCommand->deschedule(this);
      90         4601 : }
      91              : 
      92              : void
      93         4601 : MSRailSignal::init(NLDetectorBuilder&) {
      94         4601 :     if (myLanes.size() == 0) {
      95            9 :         WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
      96              :     }
      97        10424 :     for (LinkVector& links : myLinks) { //for every link index
      98         5823 :         if (links.size() != 1) {
      99            0 :             throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size())
     100            0 :                                + " links controlled by index " + toString(links[0]->getTLIndex()));
     101              :         }
     102        11646 :         myLinkInfos.push_back(LinkInfo(links[0]));
     103              :     }
     104         4601 :     updateCurrentPhase();
     105         4601 :     setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     106         4601 :     myNumLinks = (int)myLinks.size();
     107         4601 :     MSRailSignalControl::getInstance().addSignal(this);
     108         4601 : }
     109              : 
     110              : 
     111         9202 : MSRailSignal::~MSRailSignal() {
     112         4601 :     removeConstraints();
     113         9202 : }
     114              : 
     115              : 
     116              : // ----------- Handling of controlled links
     117              : void
     118            0 : MSRailSignal::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
     119            0 :     MSTrafficLightLogic::adaptLinkInformationFrom(logic);
     120            0 :     updateCurrentPhase();
     121            0 : }
     122              : 
     123              : 
     124              : // ------------ Switching and setting current rows
     125              : SUMOTime
     126            0 : MSRailSignal::trySwitch() {
     127              :     // deschedule regular traffic light event,
     128              :     // updateCurrentPhase is instead called from MSRailSignalControl::updateSignals
     129            0 :     return SUMOTime_MAX;
     130              : }
     131              : 
     132              : 
     133              : 
     134              : bool
     135      7636718 : MSRailSignal::updateCurrentPhase() {
     136              : #ifdef DEBUG_SIGNALSTATE
     137              :     gDebugFlag4 = DEBUG_COND;
     138              : #endif
     139              :     bool keepActive = false;
     140              :     // green by default so vehicles can be inserted at the borders of the network
     141              :     std::string state(myLinks.size(), 'G');
     142     21772586 :     for (LinkInfo& li : myLinkInfos) {
     143     14135868 :         if (li.myLink->getApproaching().size() > 0 && li.myControlled) {
     144              :             keepActive = true;
     145      3815404 :             Approaching closest = li.myLink->getClosest();
     146      3815404 :             MSDriveWay& driveway = li.getDriveWay(closest.first);
     147              :             //std::cout << SIMTIME << " signal=" << getTLLinkID(li.myLink) << " veh=" << closest.first->getID() << " dw:\n";
     148              :             //driveway.writeBlocks(*OutputDevice_COUT::getDevice());
     149      3815404 :             const bool mustWait = !constraintsAllow(closest.first, true);
     150              :             MSEdgeVector occupied;
     151      3815404 :             if (mustWait || !driveway.reserve(closest, occupied)) {
     152      3462900 :                 state[li.myLink->getTLIndex()] = 'r';
     153      3462900 :                 if (occupied.size() > 0) {
     154       232694 :                     li.reroute(const_cast<SUMOVehicle*>(closest.first), occupied);
     155              :                 }
     156              : #ifdef DEBUG_SIGNALSTATE
     157              :                 if (gDebugFlag4) {
     158              :                     std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " notReserved\n";
     159              :                 }
     160              : #endif
     161              :             } else {
     162       352504 :                 state[li.myLink->getTLIndex()] = 'G';
     163              : #ifdef DEBUG_SIGNALSTATE
     164              :                 if (gDebugFlag4) {
     165              :                     std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " reserved\n";
     166              :                 }
     167              : #endif
     168              :             }
     169     14135868 :         } else if (li.myControlled) {
     170     10320102 :             if (li.myDriveways.empty()) {
     171              : #ifdef DEBUG_SIGNALSTATE
     172              :                 if (gDebugFlag4) {
     173              :                     std::cout << SIMTIME << " rsl=" << li.getID() << " red for unitialized signal (no driveways yet)\n";
     174              :                 }
     175              : #endif
     176      6450772 :                 state[li.myLink->getTLIndex()] = 'r';
     177              :             } else {
     178      3869330 :                 const MSDriveWay& driveway = *li.myDriveways.front();
     179              :                 MSEdgeVector occupied;
     180      3869330 :                 if (driveway.foeDriveWayOccupied(true, nullptr, occupied) || driveway.foeDriveWayApproached()) {
     181              :                     keepActive = true;
     182              : #ifdef DEBUG_SIGNALSTATE
     183              :                     if (gDebugFlag4) {
     184              :                         std::cout << SIMTIME << " rsl=" << li.getID() << " red for default driveway " << driveway.getID() << "\n";
     185              :                     }
     186              : #endif
     187      3820910 :                     state[li.myLink->getTLIndex()] = 'r';
     188              :                 } else {
     189              : #ifdef DEBUG_SIGNALSTATE
     190              :                     if (gDebugFlag4) {
     191              :                         std::cout << SIMTIME << " rsl=" << li.getID() << " green for default driveway " << driveway.getID() << "\n";
     192              :                     }
     193              : #endif
     194              :                 }
     195      3869330 :             }
     196              :         } else {
     197          362 :             state[li.myLink->getTLIndex()] = 'O';
     198              :         }
     199              :     }
     200      7636718 :     if (myCurrentPhase.getState() != state) {
     201              :         myCurrentPhase.setState(state);
     202        31932 :         myPhaseIndex = 1 - myPhaseIndex;
     203              :         // set link priorities
     204        31932 :         setTrafficLightSignals(SIMSTEP);
     205              :         // execute switch actions (3D-gui)
     206              :         //const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
     207              :         //vars.executeOnSwitchActions();
     208              :     }
     209              : #ifdef DEBUG_SIGNALSTATE
     210              :     gDebugFlag4 = false;
     211              : #endif
     212      7636718 :     return keepActive;
     213              : }
     214              : 
     215              : 
     216              : bool
     217      3840988 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
     218      3840988 :     if (myConstraints.size() == 0) {
     219              :         return true;
     220              :     } else {
     221      6516582 :         const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
     222              :         auto it = myConstraints.find(tripID);
     223      3258291 :         if (it != myConstraints.end()) {
     224      3273901 :             for (MSRailSignalConstraint* c : it->second) {
     225              :                 // ignore insertion constraints here
     226      3252393 :                 if (!c->isInsertionConstraint() && !c->cleared()) {
     227              : #ifdef DEBUG_SIGNALSTATE
     228              :                     if (gDebugFlag4) {
     229              :                         std::cout << "  constraint '" << c->getDescription() << "' not cleared\n";
     230              :                     }
     231              : #endif
     232      3222967 :                     if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
     233      3248647 :                             && veh->getWaitingTime() > veh->getVehicleType().getCarFollowModel().getStartupDelay()) {
     234        13929 :                         const SUMOVehicle* foe = c->getFoe();
     235        13929 :                         if (foe != nullptr) {
     236        11889 :                             MSRailSignalControl::getInstance().addWaitRelation(veh, this, foe, c);
     237              :                         }
     238              :                     }
     239      3231330 :                     if (myStoreVehicles) {
     240            0 :                         myConstraintInfo = c->getDescription();
     241              :                     }
     242              :                     return false;
     243              :                 }
     244              :             }
     245              :         }
     246        26961 :         return true;
     247              :     }
     248              : }
     249              : 
     250              : 
     251              : void
     252          939 : MSRailSignal::addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
     253          939 :     myConstraints[tripId].push_back(constraint);
     254          939 : }
     255              : 
     256              : 
     257              : bool
     258          218 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
     259              :     if (myConstraints.count(tripId) != 0) {
     260          218 :         auto& constraints = myConstraints[tripId];
     261          218 :         auto it = std::find(constraints.begin(), constraints.end(), constraint);
     262          218 :         if (it != constraints.end()) {
     263          218 :             delete *it;
     264              :             constraints.erase(it);
     265              :             return true;
     266              :         }
     267              :     }
     268              :     return false;
     269              : }
     270              : 
     271              : void
     272         4625 : MSRailSignal::removeConstraints() {
     273         5419 :     for (auto item : myConstraints) {
     274         1515 :         for (MSRailSignalConstraint* c : item.second) {
     275          721 :             delete c;
     276              :         }
     277              :     }
     278              :     myConstraints.clear();
     279         4625 : }
     280              : 
     281              : 
     282              : // ------------ Static Information Retrieval
     283              : int
     284            0 : MSRailSignal::getPhaseNumber() const {
     285            0 :     return 0;
     286              : }
     287              : 
     288              : const MSTrafficLightLogic::Phases&
     289         4601 : MSRailSignal::getPhases() const {
     290         4601 :     return myPhases;
     291              : }
     292              : 
     293              : const MSPhaseDefinition&
     294            0 : MSRailSignal::getPhase(int) const {
     295            0 :     return myCurrentPhase;
     296              : }
     297              : 
     298              : // ------------ Dynamic Information Retrieval
     299              : int
     300        29614 : MSRailSignal::getCurrentPhaseIndex() const {
     301        29614 :     return myPhaseIndex;
     302              : }
     303              : 
     304              : const MSPhaseDefinition&
     305      7744798 : MSRailSignal::getCurrentPhaseDef() const {
     306      7744798 :     return myCurrentPhase;
     307              : }
     308              : 
     309              : // ------------ Conversion between time and phase
     310              : SUMOTime
     311            0 : MSRailSignal::getPhaseIndexAtTime(SUMOTime) const {
     312            0 :     return 0;
     313              : }
     314              : 
     315              : SUMOTime
     316            0 : MSRailSignal::getOffsetFromIndex(int) const {
     317            0 :     return 0;
     318              : }
     319              : 
     320              : int
     321            0 : MSRailSignal::getIndexFromOffset(SUMOTime) const {
     322            0 :     return 0;
     323              : }
     324              : 
     325              : 
     326              : void
     327         5823 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
     328         5823 :     if (pos >= 0) {
     329         5823 :         MSTrafficLightLogic::addLink(link, lane, pos);
     330              :     } // ignore uncontrolled link
     331         5823 : }
     332              : 
     333              : 
     334              : std::string
     335            0 : MSRailSignal::describeLinks(std::vector<MSLink*> links) {
     336              :     std::string result;
     337            0 :     for (MSLink* link : links) {
     338            0 :         result += link->getDescription() + " ";
     339              :     }
     340            0 :     return result;
     341              : }
     342              : 
     343              : 
     344              : void
     345         3890 : MSRailSignal::writeBlocks(OutputDevice& od, bool writeVehicles) const {
     346         7780 :     od.openTag("railSignal");
     347         3890 :     od.writeAttr(SUMO_ATTR_ID, getID());
     348         8322 :     for (const LinkInfo& li : myLinkInfos) {
     349         4432 :         MSLink* link = li.myLink;
     350         8864 :         od.openTag("link");
     351         4432 :         od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex());
     352         4432 :         od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID());
     353         4432 :         od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
     354         8290 :         for (const MSDriveWay* dw : li.myDriveways) {
     355         3858 :             if (writeVehicles) {
     356          368 :                 dw->writeBlockVehicles(od);
     357              :             } else {
     358         3490 :                 dw->writeBlocks(od);
     359              :             }
     360              :         }
     361         8864 :         od.closeTag(); // link
     362              :     }
     363         3890 :     od.closeTag(); // railSignal
     364         3890 : }
     365              : 
     366              : 
     367              : void
     368         3536 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
     369         3536 :     const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
     370         3536 :     int endIndex = ego->getParameter().arrivalEdge;
     371         3536 :     if (endIndex < 0) {
     372         3533 :         endIndex = (int)edges.size() - 1;
     373              :     }
     374         3536 :     const int departIndex = ego->getParameter().departEdge;
     375         3536 :     MSDriveWay* prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego, true));
     376         3536 :     if (update && ego->hasDeparted()) {
     377          782 :         MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
     378          782 :         if (!prev->hasTrain(veh) && prev->notifyEnter(*veh, prev->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(prev)) {
     379           40 :             veh->addReminder(prev, 1);
     380              :         }
     381              :     }
     382        83265 :     for (int i = departIndex; i <= endIndex - 1; i++) {
     383        79729 :         const MSEdge* e = edges[i];
     384        79729 :         if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     385        54553 :             const MSEdge* e2 = edges[i + 1];
     386       109106 :             for (MSLane* lane : e->getLanes()) {
     387       110056 :                 for (MSLink* link : lane->getLinkCont()) {
     388        55503 :                     if (&link->getLane()->getEdge() == e2) {
     389        54532 :                         MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
     390        51969 :                         if (rs != nullptr) {
     391        51969 :                             LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
     392              :                             // init driveway
     393        51969 :                             MSDriveWay* dw = &li.getDriveWay(ego, i);
     394        51969 :                             MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
     395        51969 :                             MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
     396        51969 :                             MSRailSignalControl::getInstance().notifyApproach(link);
     397              :                             prev = dw;
     398        51969 :                             if (update && rs->isActive()) {
     399              :                                 // vehicle may have rerouted its intial trip
     400              :                                 // after the states have been set
     401              :                                 // @note: This is a hack because it could lead to invalid tls-output
     402              :                                 // (it's still an improvement over switching based on default driveways)
     403        49688 :                                 if (!ego->hasDeparted()) {
     404         8316 :                                     rs->updateCurrentPhase();
     405         8316 :                                     rs->setTrafficLightSignals(SIMSTEP);
     406        41372 :                                 } else if (ego->hasDeparted() && i <= ego->getRoutePosition()) {
     407        17435 :                                     MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
     408        17435 :                                     if (!dw->hasTrain(veh) && dw->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(dw)) {
     409           39 :                                         veh->addReminder(dw, 1);
     410           57 :                                         for (MSDriveWay* sub : dw->getSubDriveWays()) {
     411           18 :                                             if (!sub->hasTrain(veh) && sub->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(sub)) {
     412            0 :                                                 veh->addReminder(sub, 1);
     413              :                                             }
     414              :                                         }
     415              :                                     }
     416              :                                 }
     417              :                             }
     418              :                         }
     419              :                     }
     420              :                 }
     421              :             }
     422              :         }
     423              :     }
     424         3536 :     MSDriveWay::getDepartureDriveway(ego, true);
     425         3536 : }
     426              : 
     427              : 
     428              : bool
     429        16371 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
     430        16371 :     if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     431         5081 :         const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
     432         4881 :         if (rs != nullptr && rs->myConstraints.size() > 0) {
     433         6910 :             const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
     434              :             auto it = rs->myConstraints.find(tripID);
     435         3455 :             if (it != rs->myConstraints.end()) {
     436         3671 :                 for (MSRailSignalConstraint* c : it->second) {
     437         3375 :                     if (c->isInsertionConstraint() && !c->cleared()) {
     438              : #ifdef DEBUG_SIGNALSTATE
     439              :                         if (DEBUG_HELPER(rs)) {
     440              :                             std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
     441              :                         }
     442              : #endif
     443         6216 :                         info = c->getDescription();
     444         3108 :                         isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
     445         3108 :                         if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
     446         3108 :                             const SUMOVehicle* foe = c->getFoe();
     447         3108 :                             if (foe != nullptr) {
     448         3108 :                                 MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
     449              :                             }
     450              :                         }
     451              :                         return true;
     452              :                     }
     453              :                 }
     454              :             }
     455              :         }
     456              :     }
     457              :     return false;
     458              : }
     459              : 
     460              : // ===========================================================================
     461              : // LinkInfo method definitions
     462              : // ===========================================================================
     463              : 
     464         5823 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
     465         5823 :     myLink(link) {
     466         5823 :     reset();
     467         5823 : }
     468              : 
     469        13144 : MSRailSignal::LinkInfo::~LinkInfo() {
     470        17474 :     for (MSDriveWay* dw : myDriveways) {
     471         4330 :         delete dw;
     472              :     }
     473              :     myDriveways.clear();
     474        13144 : }
     475              : 
     476              : void
     477         5828 : MSRailSignal::LinkInfo::reset() {
     478         5828 :     myLastRerouteTime = -1;
     479         5828 :     myLastRerouteVehicle = nullptr;
     480              :     myDriveways.clear();
     481         8535 :     myControlled = isRailwayOrShared(myLink->getViaLaneOrLane()->getPermissions())
     482         5828 :         && isRailwayOrShared(myLink->getLane()->getPermissions());
     483         5828 : }
     484              : 
     485              : 
     486              : std::string
     487            6 : MSRailSignal::LinkInfo::getID() const {
     488           12 :     return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
     489              : }
     490              : 
     491              : 
     492              : MSDriveWay&
     493      3909946 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh, int searchStart) {
     494      3909946 :     MSEdge* first = &myLink->getLane()->getEdge();
     495      3909946 :     auto searchStartIt = searchStart < 0 ? veh->getCurrentRouteEdge() : veh->getRoute().begin() + searchStart;
     496      3909946 :     MSRouteIterator firstIt = std::find(searchStartIt, veh->getRoute().end(), first);
     497      3909946 :     if (firstIt == veh->getRoute().end()) {
     498              :         // possibly the vehicle has already gone past the first edge (i.e.
     499              :         // because first is short or the step-length is high)
     500              :         // lets look backward along the route
     501              :         // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
     502          121 :         double lookBack = SPEED2DIST(veh->getSpeed() + 10);
     503          121 :         int routeIndex = veh->getRoutePosition() - 1;
     504          139 :         while (lookBack > 0 && routeIndex > 0) {
     505          127 :             const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
     506          127 :             if (prevEdge == first) {
     507          109 :                 firstIt = veh->getRoute().begin() + routeIndex;
     508          109 :                 break;
     509              :             }
     510           18 :             lookBack -= prevEdge->getLength();
     511           18 :             routeIndex--;
     512              :         }
     513              :     }
     514      3909946 :     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
     515      3909946 :     if (firstIt == veh->getRoute().end()) {
     516           48 :         WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
     517              :                       + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
     518           12 :         if (myDriveways.empty()) {
     519              :             ConstMSEdgeVector dummyRoute;
     520            0 :             dummyRoute.push_back(&myLink->getLane()->getEdge());
     521            0 :             MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
     522            0 :             myDriveways.push_back(dw);
     523            0 :         }
     524           12 :         return *myDriveways.front();
     525              :     }
     526              :     //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
     527      3909934 :     return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
     528              : }
     529              : 
     530              : 
     531              : MSDriveWay&
     532      3909934 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
     533      3946979 :     for (MSDriveWay* dw : myDriveways) {
     534      3942649 :         if (dw->match(firstIt, endIt)) {
     535              :             return *dw;
     536              :         }
     537              : #ifdef DEBUG_SELECT_DRIVEWAY
     538              :         std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
     539              : #else
     540              :         UNUSED_PARAMETER(info);
     541              : #endif
     542              :     }
     543         4330 :     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
     544         4330 :     MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
     545              :     dw->setVehicle(info);
     546              : #ifdef DEBUG_SELECT_DRIVEWAY
     547              :     std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
     548              : #endif
     549         4330 :     myDriveways.push_back(dw);
     550         4330 :     return *myDriveways.back();
     551              : }
     552              : 
     553              : 
     554              : void
     555       232694 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
     556       232694 :     MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
     557       232694 :     const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
     558              :     if (rDev != nullptr
     559       141365 :             && rDev->mayRerouteRailSignal()
     560       232853 :             && (myLastRerouteVehicle != veh
     561              :                 // reroute each vehicle only once if no periodic routing is allowed,
     562              :                 // otherwise with the specified period
     563          153 :                 || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
     564            6 :         myLastRerouteVehicle = veh;
     565            6 :         myLastRerouteTime = now;
     566              : 
     567              : #ifdef DEBUG_REROUTE
     568              :         ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
     569              :         if (DEBUG_COND_LINKINFO) {
     570              :             std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
     571              :         }
     572              : #endif
     573              :         std::map<const MSEdge*, double> prohibited;
     574           18 :         for (MSEdge* e : occupied) {
     575              :             // indefinite occupation because vehicles might be in deadlock on their current routes
     576           12 :             prohibited[e] = -1;
     577              :         }
     578           18 :         MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, prohibited);
     579              : #ifdef DEBUG_REROUTE
     580              :         // attention this works only if we are not parallel!
     581              :         if (DEBUG_COND_LINKINFO) {
     582              :             if (veh->getRoute().getEdges() != oldRoute) {
     583              :                 std::cout << "    rerouting successful\n";
     584              :             }
     585              :         }
     586              : #endif
     587              :     }
     588       232694 : }
     589              : 
     590              : void
     591        18352 : MSRailSignal::resetStored() {
     592              :     myBlockingVehicles.clear();
     593              :     myRivalVehicles.clear();
     594              :     myPriorityVehicles.clear();
     595              :     myConstraintInfo = "";
     596              :     myBlockingDriveWays.clear();
     597              :     myRequestedDriveWay = "";
     598        18352 : }
     599              : 
     600              : 
     601              : void
     602            0 : MSRailSignal::storeTraCIVehicles(const MSDriveWay* dw) {
     603            0 :     resetStored();
     604            0 :     myStoreVehicles = true;
     605              :     MSEdgeVector occupied;
     606              :     // call for side effects
     607            0 :     dw->foeDriveWayOccupied(true, nullptr, occupied);
     608            0 :     myStoreVehicles = false;
     609            0 : }
     610              : 
     611              : void
     612        18352 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
     613        18352 :     resetStored();
     614        18352 :     myStoreVehicles = true;
     615        18352 :     LinkInfo& li = myLinkInfos[linkIndex];
     616        18352 :     if (li.myLink->getApproaching().size() > 0) {
     617         1825 :         Approaching closest = li.myLink->getClosest();
     618         1825 :         MSDriveWay& driveway = li.getDriveWay(closest.first);
     619              :         MSEdgeVector occupied;
     620              :         myRequestedDriveWay = driveway.getID();
     621              :         // call for side effects
     622         1825 :         driveway.reserve(closest, occupied);
     623         1825 :         constraintsAllow(closest.first);
     624        18352 :     } else if (li.myDriveways.size() > 0) {
     625        16035 :         li.myDriveways.front()->conflictLaneOccupied();
     626        16035 :         li.myDriveways.front()->foeDriveWayApproached();
     627              :     }
     628        18352 :     myStoreVehicles = false;
     629        18352 : }
     630              : 
     631              : MSRailSignal::VehicleVector
     632         6124 : MSRailSignal::getBlockingVehicles(int linkIndex) {
     633         6124 :     storeTraCIVehicles(linkIndex);
     634         6124 :     return myBlockingVehicles;
     635              : }
     636              : 
     637              : MSRailSignal::VehicleVector
     638         6114 : MSRailSignal::getRivalVehicles(int linkIndex) {
     639         6114 :     storeTraCIVehicles(linkIndex);
     640         6114 :     return myRivalVehicles;
     641              : }
     642              : 
     643              : MSRailSignal::VehicleVector
     644         6114 : MSRailSignal::getPriorityVehicles(int linkIndex) {
     645         6114 :     storeTraCIVehicles(linkIndex);
     646         6114 :     return myPriorityVehicles;
     647              : }
     648              : 
     649              : std::string
     650            0 : MSRailSignal::getConstraintInfo(int linkIndex) {
     651            0 :     storeTraCIVehicles(linkIndex);
     652            0 :     return myConstraintInfo;
     653              : }
     654              : 
     655              : 
     656              : std::string
     657            0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
     658            0 :     storeTraCIVehicles(linkIndex);
     659            0 :     return myRequestedDriveWay;
     660              : }
     661              : 
     662              : 
     663              : std::vector<const MSDriveWay*>
     664            0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
     665            0 :     storeTraCIVehicles(linkIndex);
     666            0 :     return myBlockingDriveWays;
     667              : }
     668              : 
     669              : 
     670              : MSRailSignal::VehicleVector
     671            0 : MSRailSignal::getBlockingVehicles(const MSDriveWay* dw) {
     672            0 :     storeTraCIVehicles(dw);
     673            0 :     return myBlockingVehicles;
     674              : }
     675              : 
     676              : 
     677              : std::vector<const MSDriveWay*>
     678            0 : MSRailSignal::getBlockingDriveWays(const MSDriveWay* dw) {
     679            0 :     storeTraCIVehicles(dw);
     680            0 :     return myBlockingDriveWays;
     681              : }
     682              : 
     683              : const MSDriveWay&
     684            0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
     685            0 :     for (const LinkInfo& li : myLinkInfos) {
     686            0 :         for (const MSDriveWay* dw : li.myDriveways) {
     687            0 :             if (dw->getNumericalID() == numericalID) {
     688            0 :                 return *dw;
     689              :             }
     690              :         }
     691              :     }
     692            0 :     throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
     693              : }
     694              : 
     695              : const MSDriveWay&
     696        40748 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
     697        40748 :     return myLinkInfos[tlIndex].getDriveWay(veh);
     698              : }
     699              : 
     700              : const MSDriveWay&
     701            0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
     702            0 :     return myLinkInfos[tlIndex].getDriveWay(first, end);
     703              : }
     704              : 
     705              : 
     706              : const std::vector<MSDriveWay*>
     707        10186 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
     708        10186 :     return myLinkInfos[tlIndex].myDriveways;
     709              : }
     710              : 
     711              : 
     712              : std::string
     713            0 : MSRailSignal::getBlockingVehicleIDs() const {
     714              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     715            0 :     if (myLinkInfos.size() == 1) {
     716            0 :         return toString(rs->getBlockingVehicles(0));
     717              :     } else {
     718              :         std::string result;
     719            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     720            0 :             result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
     721              :         }
     722            0 :         return result;
     723              :     }
     724              : }
     725              : std::string
     726            0 : MSRailSignal::getRivalVehicleIDs() const {
     727              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     728            0 :     if (myLinkInfos.size() == 1) {
     729            0 :         return toString(rs->getRivalVehicles(0));
     730              :     } else {
     731              :         std::string result;
     732            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     733            0 :             result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
     734              :         }
     735            0 :         return result;
     736              :     }
     737              : }
     738              : std::string
     739            0 : MSRailSignal::getPriorityVehicleIDs() const {
     740              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     741            0 :     if (myLinkInfos.size() == 1) {
     742            0 :         return toString(rs->getPriorityVehicles(0));
     743              :     } else {
     744              :         std::string result;
     745            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     746            0 :             result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
     747              :         }
     748            0 :         return result;
     749              :     }
     750              : }
     751              : std::string
     752            0 : MSRailSignal::getConstraintInfo() const {
     753              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     754            0 :     if (myLinkInfos.size() == 1) {
     755            0 :         return rs->getConstraintInfo(0);
     756              :     } else {
     757              :         std::string result;
     758            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     759            0 :             result += toString(i) + ": " + rs->getConstraintInfo(i);
     760              :         }
     761            0 :         return result;
     762              :     }
     763              : }
     764              : std::string
     765            0 : MSRailSignal::getRequestedDriveWay() const {
     766              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     767            0 :     if (myLinkInfos.size() == 1) {
     768            0 :         return toString(rs->getRequestedDriveWay(0));
     769              :     } else {
     770              :         std::string result;
     771            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     772            0 :             result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
     773              :         }
     774            0 :         return result;
     775              :     }
     776              : }
     777              : std::string
     778            0 : MSRailSignal::getBlockingDriveWayIDs() const {
     779              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     780            0 :     if (myLinkInfos.size() == 1) {
     781            0 :         return toString(rs->getBlockingDriveWays(0));
     782              :     } else {
     783              :         std::string result;
     784            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     785            0 :             result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
     786              :         }
     787            0 :         return result;
     788              :     }
     789              : }
     790              : 
     791              : void
     792            5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
     793              :     // some pre-defined parameters can be updated at runtime
     794            5 :     if (key == "moving-block") {
     795            5 :         bool movingBlock = StringUtils::toBool(value);
     796            5 :         if (movingBlock != myMovingBlock) {
     797              :             // recompute driveways
     798            5 :             myMovingBlock = movingBlock;
     799           10 :             for (LinkInfo& li : myLinkInfos) {
     800            5 :                 li.reset();
     801              :             }
     802            5 :             updateCurrentPhase();
     803            5 :             setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     804              :         }
     805              :     }
     806            5 :     Parameterised::setParameter(key, value);
     807            5 : }
     808              : 
     809              : 
     810              : std::string
     811         4330 : MSRailSignal::getNewDrivewayID() {
     812         8660 :     return getID() + "." + toString(myDriveWayIndex++);
     813              : }
     814              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1