LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSRailSignal.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 72.7 % 352 256
Test Date: 2025-12-06 15:35:27 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         4597 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
      80              :                            const std::string& id, const std::string& programID, SUMOTime delay,
      81         4597 :                            const Parameterised::Map& parameters) :
      82              :     MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
      83         4597 :     myNumericalID(myRSIndex++),
      84        13791 :     myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
      85         4597 :     myPhaseIndex(0),
      86         4597 :     myDriveWayIndex(0) {
      87         4597 :     myDefaultCycleTime = DELTA_T;
      88         4597 :     myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
      89         4597 :     mySwitchCommand->deschedule(this);
      90         4597 : }
      91              : 
      92              : void
      93         4597 : MSRailSignal::init(NLDetectorBuilder&) {
      94         4597 :     if (myLanes.size() == 0) {
      95            9 :         WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
      96              :     }
      97        10416 :     for (LinkVector& links : myLinks) { //for every link index
      98         5819 :         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        11638 :         myLinkInfos.push_back(LinkInfo(links[0]));
     103              :     }
     104         4597 :     updateCurrentPhase();
     105         4597 :     setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     106         4597 :     myNumLinks = (int)myLinks.size();
     107         4597 :     MSRailSignalControl::getInstance().addSignal(this);
     108         4597 : }
     109              : 
     110              : 
     111         9182 : MSRailSignal::~MSRailSignal() {
     112         4591 :     removeConstraints();
     113         9182 : }
     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     16200332 : 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     47468154 :     for (LinkInfo& li : myLinkInfos) {
     143     31267822 :         if (li.myLink->getApproaching().size() > 0 && li.myControlled) {
     144              :             keepActive = true;
     145      8098059 :             Approaching closest = li.myLink->getClosest();
     146      8098059 :             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      8098059 :             const bool mustWait = !constraintsAllow(closest.first, true);
     150              :             MSEdgeVector occupied;
     151      8098059 :             if (mustWait || !driveway.reserve(closest, occupied)) {
     152      7746570 :                 state[li.myLink->getTLIndex()] = 'r';
     153      7746570 :                 if (occupied.size() > 0) {
     154       232457 :                     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       351489 :                 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     31267822 :         } else if (li.myControlled) {
     170     23169401 :             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     15019112 :                 state[li.myLink->getTLIndex()] = 'r';
     177              :             } else {
     178      8150289 :                 const MSDriveWay& driveway = *li.myDriveways.front();
     179              :                 MSEdgeVector occupied;
     180      8150289 :                 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      8102118 :                     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      8150289 :             }
     196              :         } else {
     197          362 :             state[li.myLink->getTLIndex()] = 'O';
     198              :         }
     199              :     }
     200     16200332 :     if (myCurrentPhase.getState() != state) {
     201              :         myCurrentPhase.setState(state);
     202        31876 :         myPhaseIndex = 1 - myPhaseIndex;
     203              :         // set link priorities
     204        31876 :         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     16200332 :     return keepActive;
     213              : }
     214              : 
     215              : 
     216              : bool
     217      8123411 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
     218      8123411 :     if (myConstraints.size() == 0) {
     219              :         return true;
     220              :     } else {
     221     15082482 :         const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
     222              :         auto it = myConstraints.find(tripID);
     223      7541241 :         if (it != myConstraints.end()) {
     224      7556984 :             for (MSRailSignalConstraint* c : it->second) {
     225              :                 // ignore insertion constraints here
     226      7535869 :                 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      7506874 :                     if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
     233      7532322 :                             && 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      7515005 :                     if (myStoreVehicles) {
     240            0 :                         myConstraintInfo = c->getDescription();
     241              :                     }
     242              :                     return false;
     243              :                 }
     244              :             }
     245              :         }
     246        26236 :         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          216 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
     259              :     if (myConstraints.count(tripId) != 0) {
     260          216 :         auto& constraints = myConstraints[tripId];
     261          216 :         auto it = std::find(constraints.begin(), constraints.end(), constraint);
     262          216 :         if (it != constraints.end()) {
     263          216 :             delete *it;
     264              :             constraints.erase(it);
     265              :             return true;
     266              :         }
     267              :     }
     268              :     return false;
     269              : }
     270              : 
     271              : void
     272         4615 : MSRailSignal::removeConstraints() {
     273         5405 :     for (auto item : myConstraints) {
     274         1509 :         for (MSRailSignalConstraint* c : item.second) {
     275          719 :             delete c;
     276              :         }
     277              :     }
     278              :     myConstraints.clear();
     279         4615 : }
     280              : 
     281              : 
     282              : // ------------ Static Information Retrieval
     283              : int
     284            0 : MSRailSignal::getPhaseNumber() const {
     285            0 :     return 0;
     286              : }
     287              : 
     288              : const MSTrafficLightLogic::Phases&
     289         4597 : MSRailSignal::getPhases() const {
     290         4597 :     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     16308344 : MSRailSignal::getCurrentPhaseDef() const {
     306     16308344 :     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         5819 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
     328         5819 :     if (pos >= 0) {
     329         5819 :         MSTrafficLightLogic::addLink(link, lane, pos);
     330              :     } // ignore uncontrolled link
     331         5819 : }
     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         3529 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
     369         3529 :     const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
     370         3529 :     int endIndex = ego->getParameter().arrivalEdge;
     371         3529 :     if (endIndex < 0) {
     372         3526 :         endIndex = (int)edges.size() - 1;
     373              :     }
     374         3529 :     int departIndex = ego->getParameter().departEdge;
     375              :     MSDriveWay* prev = nullptr;
     376         3529 :     if (update && ego->hasDeparted()) {
     377              :         // find last rail signal on the route and obtain the driveway
     378          780 :         const MSEdge* next = ego->getEdge();
     379          953 :         for (int i = ego->getRoutePosition() - 1; i > departIndex; i--) {
     380          817 :             const MSEdge* e = ego->getRoute().getEdges()[i];
     381          817 :             if (e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     382          646 :                 const MSLink* link = e->getLanes().front()->getLinkTo(next->getLanes().front());
     383              :                 //std::cout << SIMTIME << " veh=" << ego->getID() << " rp=" << ego->getRoutePosition()
     384              :                 //    << " i=" << i << " e=" << e->getID() << " next=" << next->getID() << " link=" << (link == nullptr ? "NUL" : link->getDescription()) << "\n";
     385          646 :                 if (link != nullptr && link->isTLSControlled()) {
     386          644 :                     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
     387          644 :                     LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
     388          644 :                     prev = &li.getDriveWay(ego, i);
     389          644 :                     departIndex = ego->getRoutePosition();
     390          644 :                     break;
     391              :                 }
     392              :             }
     393              :             next = e;
     394              :         }
     395              :     }
     396          780 :     if (prev == nullptr) {
     397         2885 :         prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego, true));
     398              :     }
     399         3529 :     if (update && ego->hasDeparted()) {
     400          780 :         MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
     401          780 :         if (!prev->hasTrain(veh) && prev->notifyEnter(*veh, prev->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(prev)) {
     402           57 :             veh->addReminder(prev, 1);
     403              :         }
     404              :     }
     405        60608 :     for (int i = departIndex; i <= endIndex - 1; i++) {
     406        57079 :         const MSEdge* e = edges[i];
     407        57079 :         if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     408        37870 :             const MSEdge* e2 = edges[i + 1];
     409        75740 :             for (MSLane* lane : e->getLanes()) {
     410        76686 :                 for (MSLink* link : lane->getLinkCont()) {
     411        38816 :                     if (&link->getLane()->getEdge() == e2) {
     412        37849 :                         MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
     413        35287 :                         if (rs != nullptr) {
     414        35287 :                             LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
     415              :                             // init driveway
     416        35287 :                             MSDriveWay* dw = &li.getDriveWay(ego, i);
     417        35287 :                             MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
     418        35287 :                             MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
     419        35287 :                             MSRailSignalControl::getInstance().notifyApproach(link);
     420              :                             prev = dw;
     421        35287 :                             if (update && rs->isActive()) {
     422              :                                 // vehicle may have rerouted its intial trip
     423              :                                 // after the states have been set
     424              :                                 // @note: This is a hack because it could lead to invalid tls-output
     425              :                                 // (it's still an improvement over switching based on default driveways)
     426        33014 :                                 if (!ego->hasDeparted()) {
     427         8306 :                                     rs->updateCurrentPhase();
     428         8306 :                                     rs->setTrafficLightSignals(SIMSTEP);
     429        24708 :                                 } else if (ego->hasDeparted() && i <= ego->getRoutePosition()) {
     430          775 :                                     MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
     431          775 :                                     if (!dw->hasTrain(veh) && dw->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(dw)) {
     432           20 :                                         veh->addReminder(dw, 1);
     433           30 :                                         for (MSDriveWay* sub : dw->getSubDriveWays()) {
     434           10 :                                             if (!sub->hasTrain(veh) && sub->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(sub)) {
     435            0 :                                                 veh->addReminder(sub, 1);
     436              :                                             }
     437              :                                         }
     438              :                                     }
     439              :                                 }
     440              :                             }
     441              :                         }
     442              :                     }
     443              :                 }
     444              :             }
     445              :         }
     446              :     }
     447         3529 : }
     448              : 
     449              : 
     450              : bool
     451        16365 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
     452        16365 :     if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     453         5075 :         const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
     454         4876 :         if (rs != nullptr && rs->myConstraints.size() > 0) {
     455         6906 :             const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
     456              :             auto it = rs->myConstraints.find(tripID);
     457         3453 :             if (it != rs->myConstraints.end()) {
     458         3670 :                 for (MSRailSignalConstraint* c : it->second) {
     459         3375 :                     if (c->isInsertionConstraint() && !c->cleared()) {
     460              : #ifdef DEBUG_SIGNALSTATE
     461              :                         if (DEBUG_HELPER(rs)) {
     462              :                             std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
     463              :                         }
     464              : #endif
     465         6216 :                         info = c->getDescription();
     466         3108 :                         isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
     467         3108 :                         if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
     468         3108 :                             const SUMOVehicle* foe = c->getFoe();
     469         3108 :                             if (foe != nullptr) {
     470         3108 :                                 MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
     471              :                             }
     472              :                         }
     473              :                         return true;
     474              :                     }
     475              :                 }
     476              :             }
     477              :         }
     478              :     }
     479              :     return false;
     480              : }
     481              : 
     482              : // ===========================================================================
     483              : // LinkInfo method definitions
     484              : // ===========================================================================
     485              : 
     486         5819 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
     487         5819 :     myLink(link) {
     488         5819 :     reset();
     489         5819 : }
     490              : 
     491        13130 : MSRailSignal::LinkInfo::~LinkInfo() {
     492        17450 :     for (MSDriveWay* dw : myDriveways) {
     493         4320 :         delete dw;
     494              :     }
     495              :     myDriveways.clear();
     496        13130 : }
     497              : 
     498              : void
     499         5824 : MSRailSignal::LinkInfo::reset() {
     500         5824 :     myLastRerouteTime = -1;
     501         5824 :     myLastRerouteVehicle = nullptr;
     502              :     myDriveways.clear();
     503         8531 :     myControlled = isRailwayOrShared(myLink->getViaLaneOrLane()->getPermissions())
     504         5824 :         && isRailwayOrShared(myLink->getLane()->getPermissions());
     505         5824 : }
     506              : 
     507              : 
     508              : std::string
     509            6 : MSRailSignal::LinkInfo::getID() const {
     510           12 :     return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
     511              : }
     512              : 
     513              : 
     514              : MSDriveWay&
     515      8176042 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh, int searchStart) {
     516      8176042 :     MSEdge* first = &myLink->getLane()->getEdge();
     517      8176042 :     auto searchStartIt = searchStart < 0 ? veh->getCurrentRouteEdge() : veh->getRoute().begin() + searchStart;
     518      8176042 :     MSRouteIterator firstIt = std::find(searchStartIt, veh->getRoute().end(), first);
     519      8176042 :     if (firstIt == veh->getRoute().end()) {
     520              :         // possibly the vehicle has already gone past the first edge (i.e.
     521              :         // because first is short or the step-length is high)
     522              :         // lets look backward along the route
     523              :         // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
     524           79 :         double lookBack = SPEED2DIST(veh->getSpeed() + 10);
     525           79 :         int routeIndex = veh->getRoutePosition() - 1;
     526           85 :         while (lookBack > 0 && routeIndex > 0) {
     527           85 :             const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
     528           85 :             if (prevEdge == first) {
     529           79 :                 firstIt = veh->getRoute().begin() + routeIndex;
     530           79 :                 break;
     531              :             }
     532            6 :             lookBack -= prevEdge->getLength();
     533            6 :             routeIndex--;
     534              :         }
     535              :     }
     536      8176042 :     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
     537      8176042 :     if (firstIt == veh->getRoute().end()) {
     538            0 :         WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
     539              :                       + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
     540            0 :         if (myDriveways.empty()) {
     541              :             ConstMSEdgeVector dummyRoute;
     542            0 :             dummyRoute.push_back(&myLink->getLane()->getEdge());
     543            0 :             MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
     544            0 :             myDriveways.push_back(dw);
     545            0 :         }
     546            0 :         return *myDriveways.front();
     547              :     }
     548              :     //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
     549      8176042 :     return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
     550              : }
     551              : 
     552              : 
     553              : MSDriveWay&
     554      8176042 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
     555      8212952 :     for (MSDriveWay* dw : myDriveways) {
     556      8208627 :         if (dw->match(firstIt, endIt)) {
     557              :             return *dw;
     558              :         }
     559              : #ifdef DEBUG_SELECT_DRIVEWAY
     560              :         std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
     561              : #else
     562              :         UNUSED_PARAMETER(info);
     563              : #endif
     564              :     }
     565         4325 :     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
     566         4325 :     MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
     567              :     dw->setVehicle(info);
     568              : #ifdef DEBUG_SELECT_DRIVEWAY
     569              :     std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
     570              : #endif
     571         4325 :     myDriveways.push_back(dw);
     572         4325 :     return *myDriveways.back();
     573              : }
     574              : 
     575              : 
     576              : void
     577       232457 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
     578       232457 :     MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
     579       232457 :     const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
     580              :     if (rDev != nullptr
     581       141304 :             && rDev->mayRerouteRailSignal()
     582       232616 :             && (myLastRerouteVehicle != veh
     583              :                 // reroute each vehicle only once if no periodic routing is allowed,
     584              :                 // otherwise with the specified period
     585          153 :                 || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
     586            6 :         myLastRerouteVehicle = veh;
     587            6 :         myLastRerouteTime = now;
     588              : 
     589              : #ifdef DEBUG_REROUTE
     590              :         ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
     591              :         if (DEBUG_COND_LINKINFO) {
     592              :             std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
     593              :         }
     594              : #endif
     595              :         std::map<const MSEdge*, double> prohibited;
     596           18 :         for (MSEdge* e : occupied) {
     597              :             // indefinite occupation because vehicles might be in deadlock on their current routes
     598           12 :             prohibited[e] = -1;
     599              :         }
     600           18 :         MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, prohibited);
     601              : #ifdef DEBUG_REROUTE
     602              :         // attention this works only if we are not parallel!
     603              :         if (DEBUG_COND_LINKINFO) {
     604              :             if (veh->getRoute().getEdges() != oldRoute) {
     605              :                 std::cout << "    rerouting successful\n";
     606              :             }
     607              :         }
     608              : #endif
     609              :     }
     610       232457 : }
     611              : 
     612              : void
     613        18352 : MSRailSignal::resetStored() {
     614              :     myBlockingVehicles.clear();
     615              :     myRivalVehicles.clear();
     616              :     myPriorityVehicles.clear();
     617              :     myConstraintInfo = "";
     618              :     myBlockingDriveWays.clear();
     619              :     myRequestedDriveWay = "";
     620        18352 : }
     621              : 
     622              : 
     623              : void
     624            0 : MSRailSignal::storeTraCIVehicles(const MSDriveWay* dw) {
     625            0 :     resetStored();
     626            0 :     myStoreVehicles = true;
     627              :     MSEdgeVector occupied;
     628              :     // call for side effects
     629            0 :     dw->foeDriveWayOccupied(true, nullptr, occupied);
     630            0 :     myStoreVehicles = false;
     631            0 : }
     632              : 
     633              : void
     634        18352 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
     635        18352 :     resetStored();
     636        18352 :     myStoreVehicles = true;
     637        18352 :     LinkInfo& li = myLinkInfos[linkIndex];
     638        18352 :     if (li.myLink->getApproaching().size() > 0) {
     639         1825 :         Approaching closest = li.myLink->getClosest();
     640         1825 :         MSDriveWay& driveway = li.getDriveWay(closest.first);
     641              :         MSEdgeVector occupied;
     642              :         myRequestedDriveWay = driveway.getID();
     643              :         // call for side effects
     644         1825 :         driveway.reserve(closest, occupied);
     645         1825 :         constraintsAllow(closest.first);
     646        18352 :     } else if (li.myDriveways.size() > 0) {
     647        16035 :         li.myDriveways.front()->conflictLaneOccupied();
     648        16035 :         li.myDriveways.front()->foeDriveWayApproached();
     649              :     }
     650        18352 :     myStoreVehicles = false;
     651        18352 : }
     652              : 
     653              : MSRailSignal::VehicleVector
     654         6124 : MSRailSignal::getBlockingVehicles(int linkIndex) {
     655         6124 :     storeTraCIVehicles(linkIndex);
     656         6124 :     return myBlockingVehicles;
     657              : }
     658              : 
     659              : MSRailSignal::VehicleVector
     660         6114 : MSRailSignal::getRivalVehicles(int linkIndex) {
     661         6114 :     storeTraCIVehicles(linkIndex);
     662         6114 :     return myRivalVehicles;
     663              : }
     664              : 
     665              : MSRailSignal::VehicleVector
     666         6114 : MSRailSignal::getPriorityVehicles(int linkIndex) {
     667         6114 :     storeTraCIVehicles(linkIndex);
     668         6114 :     return myPriorityVehicles;
     669              : }
     670              : 
     671              : std::string
     672            0 : MSRailSignal::getConstraintInfo(int linkIndex) {
     673            0 :     storeTraCIVehicles(linkIndex);
     674            0 :     return myConstraintInfo;
     675              : }
     676              : 
     677              : 
     678              : std::string
     679            0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
     680            0 :     storeTraCIVehicles(linkIndex);
     681            0 :     return myRequestedDriveWay;
     682              : }
     683              : 
     684              : 
     685              : std::vector<const MSDriveWay*>
     686            0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
     687            0 :     storeTraCIVehicles(linkIndex);
     688            0 :     return myBlockingDriveWays;
     689              : }
     690              : 
     691              : 
     692              : MSRailSignal::VehicleVector
     693            0 : MSRailSignal::getBlockingVehicles(const MSDriveWay* dw) {
     694            0 :     storeTraCIVehicles(dw);
     695            0 :     return myBlockingVehicles;
     696              : }
     697              : 
     698              : 
     699              : std::vector<const MSDriveWay*>
     700            0 : MSRailSignal::getBlockingDriveWays(const MSDriveWay* dw) {
     701            0 :     storeTraCIVehicles(dw);
     702            0 :     return myBlockingDriveWays;
     703              : }
     704              : 
     705              : const MSDriveWay&
     706            0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
     707            0 :     for (const LinkInfo& li : myLinkInfos) {
     708            0 :         for (const MSDriveWay* dw : li.myDriveways) {
     709            0 :             if (dw->getNumericalID() == numericalID) {
     710            0 :                 return *dw;
     711              :             }
     712              :         }
     713              :     }
     714            0 :     throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
     715              : }
     716              : 
     717              : const MSDriveWay&
     718        40227 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
     719        40227 :     return myLinkInfos[tlIndex].getDriveWay(veh);
     720              : }
     721              : 
     722              : const MSDriveWay&
     723            0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
     724            0 :     return myLinkInfos[tlIndex].getDriveWay(first, end);
     725              : }
     726              : 
     727              : 
     728              : const std::vector<MSDriveWay*>
     729        10181 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
     730        10181 :     return myLinkInfos[tlIndex].myDriveways;
     731              : }
     732              : 
     733              : 
     734              : std::string
     735            0 : MSRailSignal::getBlockingVehicleIDs() const {
     736              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     737            0 :     if (myLinkInfos.size() == 1) {
     738            0 :         return toString(rs->getBlockingVehicles(0));
     739              :     } else {
     740              :         std::string result;
     741            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     742            0 :             result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
     743              :         }
     744            0 :         return result;
     745              :     }
     746              : }
     747              : std::string
     748            0 : MSRailSignal::getRivalVehicleIDs() const {
     749              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     750            0 :     if (myLinkInfos.size() == 1) {
     751            0 :         return toString(rs->getRivalVehicles(0));
     752              :     } else {
     753              :         std::string result;
     754            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     755            0 :             result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
     756              :         }
     757            0 :         return result;
     758              :     }
     759              : }
     760              : std::string
     761            0 : MSRailSignal::getPriorityVehicleIDs() const {
     762              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     763            0 :     if (myLinkInfos.size() == 1) {
     764            0 :         return toString(rs->getPriorityVehicles(0));
     765              :     } else {
     766              :         std::string result;
     767            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     768            0 :             result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
     769              :         }
     770            0 :         return result;
     771              :     }
     772              : }
     773              : std::string
     774            0 : MSRailSignal::getConstraintInfo() const {
     775              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     776            0 :     if (myLinkInfos.size() == 1) {
     777            0 :         return rs->getConstraintInfo(0);
     778              :     } else {
     779              :         std::string result;
     780            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     781            0 :             result += toString(i) + ": " + rs->getConstraintInfo(i);
     782              :         }
     783            0 :         return result;
     784              :     }
     785              : }
     786              : std::string
     787            0 : MSRailSignal::getRequestedDriveWay() const {
     788              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     789            0 :     if (myLinkInfos.size() == 1) {
     790            0 :         return toString(rs->getRequestedDriveWay(0));
     791              :     } else {
     792              :         std::string result;
     793            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     794            0 :             result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
     795              :         }
     796            0 :         return result;
     797              :     }
     798              : }
     799              : std::string
     800            0 : MSRailSignal::getBlockingDriveWayIDs() const {
     801              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     802            0 :     if (myLinkInfos.size() == 1) {
     803            0 :         return toString(rs->getBlockingDriveWays(0));
     804              :     } else {
     805              :         std::string result;
     806            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     807            0 :             result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
     808              :         }
     809            0 :         return result;
     810              :     }
     811              : }
     812              : 
     813              : void
     814            5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
     815              :     // some pre-defined parameters can be updated at runtime
     816            5 :     if (key == "moving-block") {
     817            5 :         bool movingBlock = StringUtils::toBool(value);
     818            5 :         if (movingBlock != myMovingBlock) {
     819              :             // recompute driveways
     820            5 :             myMovingBlock = movingBlock;
     821           10 :             for (LinkInfo& li : myLinkInfos) {
     822            5 :                 li.reset();
     823              :             }
     824            5 :             updateCurrentPhase();
     825            5 :             setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     826              :         }
     827              :     }
     828            5 :     Parameterised::setParameter(key, value);
     829            5 : }
     830              : 
     831              : 
     832              : std::string
     833         4325 : MSRailSignal::getNewDrivewayID() {
     834         8650 :     return getID() + "." + toString(myDriveWayIndex++);
     835              : }
     836              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1