LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSRailSignal.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 73.1 % 357 261
Test Date: 2026-03-02 16:00:03 Functions: 60.0 % 55 33

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 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         4697 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
      80              :                            const std::string& id, const std::string& programID, SUMOTime delay,
      81         4697 :                            const Parameterised::Map& parameters) :
      82              :     MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
      83         4697 :     myNumericalID(myRSIndex++),
      84        14091 :     myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
      85         4697 :     myPhaseIndex(0),
      86         4697 :     myDriveWayIndex(0) {
      87         4697 :     myDefaultCycleTime = DELTA_T;
      88         4697 :     myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
      89         4697 :     mySwitchCommand->deschedule(this);
      90         4697 : }
      91              : 
      92              : void
      93         4697 : MSRailSignal::init(NLDetectorBuilder&) {
      94         4697 :     if (myLanes.size() == 0) {
      95            9 :         WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
      96              :     }
      97              :     SVCPermissions outgoingPermissions = 0;
      98        10671 :     for (LinkVector& links : myLinks) { //for every link index
      99         5974 :         if (links.size() != 1) {
     100            0 :             throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size())
     101            0 :                                + " links controlled by index " + toString(links[0]->getTLIndex()));
     102              :         }
     103        11948 :         myLinkInfos.push_back(LinkInfo(links[0]));
     104         5974 :         outgoingPermissions |= links[0]->getPermissions();
     105              :     }
     106         4697 :     updateCurrentPhase();
     107         4697 :     setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     108         4697 :     myNumLinks = (int)myLinks.size();
     109         4697 :     MSRailSignalControl::getInstance().addSignal(this);
     110         4697 :     myMovingBlock |= MSRailSignalControl::isMovingBlock(outgoingPermissions);
     111         4697 : }
     112              : 
     113              : 
     114         9394 : MSRailSignal::~MSRailSignal() {
     115         4697 :     removeConstraints();
     116         9394 : }
     117              : 
     118              : 
     119              : // ----------- Handling of controlled links
     120              : void
     121            0 : MSRailSignal::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
     122            0 :     MSTrafficLightLogic::adaptLinkInformationFrom(logic);
     123            0 :     updateCurrentPhase();
     124            0 : }
     125              : 
     126              : 
     127              : // ------------ Switching and setting current rows
     128              : SUMOTime
     129            0 : MSRailSignal::trySwitch() {
     130              :     // deschedule regular traffic light event,
     131              :     // updateCurrentPhase is instead called from MSRailSignalControl::updateSignals
     132            0 :     return SUMOTime_MAX;
     133              : }
     134              : 
     135              : 
     136              : 
     137              : bool
     138     18091955 : MSRailSignal::updateCurrentPhase() {
     139              : #ifdef DEBUG_SIGNALSTATE
     140              :     gDebugFlag4 = DEBUG_COND;
     141              : #endif
     142              :     bool keepActive = false;
     143              :     // green by default so vehicles can be inserted at the borders of the network
     144              :     std::string state(myLinks.size(), 'G');
     145     53127667 :     for (LinkInfo& li : myLinkInfos) {
     146     35035712 :         if (li.myLink->getApproaching().size() > 0 && li.myControlled) {
     147              :             keepActive = true;
     148      9042109 :             Approaching closest = li.myLink->getClosest();
     149      9042109 :             MSDriveWay& driveway = li.getDriveWay(closest.first);
     150              :             //std::cout << SIMTIME << " signal=" << getTLLinkID(li.myLink) << " veh=" << closest.first->getID() << " dw:\n";
     151              :             //driveway.writeBlocks(*OutputDevice_COUT::getDevice());
     152      9042109 :             const bool mustWait = !constraintsAllow(closest.first, true);
     153              :             MSEdgeVector occupied;
     154      9042109 :             if (mustWait || !driveway.reserve(closest, occupied)) {
     155      8683962 :                 state[li.myLink->getTLIndex()] = 'r';
     156      8683962 :                 if (occupied.size() > 0) {
     157       232696 :                     li.reroute(const_cast<SUMOVehicle*>(closest.first), occupied);
     158              :                 }
     159              : #ifdef DEBUG_SIGNALSTATE
     160              :                 if (gDebugFlag4) {
     161              :                     std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " notReserved\n";
     162              :                 }
     163              : #endif
     164              :             } else {
     165       358147 :                 state[li.myLink->getTLIndex()] = 'G';
     166              : #ifdef DEBUG_SIGNALSTATE
     167              :                 if (gDebugFlag4) {
     168              :                     std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " reserved\n";
     169              :                 }
     170              : #endif
     171              :             }
     172     35035712 :         } else if (li.myControlled) {
     173     25993241 :             if (li.myDriveways.empty()) {
     174              : #ifdef DEBUG_SIGNALSTATE
     175              :                 if (gDebugFlag4) {
     176              :                     std::cout << SIMTIME << " rsl=" << li.getID() << " red for unitialized signal (no driveways yet)\n";
     177              :                 }
     178              : #endif
     179     16895363 :                 state[li.myLink->getTLIndex()] = 'r';
     180              :             } else {
     181      9097878 :                 const MSDriveWay& driveway = *li.myDriveways.front();
     182              :                 MSEdgeVector occupied;
     183      9097878 :                 if (driveway.foeDriveWayOccupied(true, nullptr, occupied) || driveway.foeDriveWayApproached()) {
     184              :                     keepActive = true;
     185              : #ifdef DEBUG_SIGNALSTATE
     186              :                     if (gDebugFlag4) {
     187              :                         std::cout << SIMTIME << " rsl=" << li.getID() << " red for default driveway " << driveway.getID() << "\n";
     188              :                     }
     189              : #endif
     190      9050475 :                     state[li.myLink->getTLIndex()] = 'r';
     191              :                 } else {
     192              : #ifdef DEBUG_SIGNALSTATE
     193              :                     if (gDebugFlag4) {
     194              :                         std::cout << SIMTIME << " rsl=" << li.getID() << " green for default driveway " << driveway.getID() << "\n";
     195              :                     }
     196              : #endif
     197              :                 }
     198      9097878 :             }
     199              :         } else {
     200          362 :             state[li.myLink->getTLIndex()] = 'O';
     201              :         }
     202              :     }
     203     18091955 :     if (myCurrentPhase.getState() != state) {
     204              :         myCurrentPhase.setState(state);
     205        32284 :         myPhaseIndex = 1 - myPhaseIndex;
     206              :         // set link priorities
     207        32284 :         setTrafficLightSignals(SIMSTEP);
     208              :         // execute switch actions (3D-gui)
     209              :         //const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
     210              :         //vars.executeOnSwitchActions();
     211              :     }
     212              : #ifdef DEBUG_SIGNALSTATE
     213              :     gDebugFlag4 = false;
     214              : #endif
     215     18091955 :     return keepActive;
     216              : }
     217              : 
     218              : 
     219              : bool
     220      9068752 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
     221      9068752 :     if (myConstraints.size() == 0) {
     222              :         return true;
     223              :     } else {
     224     16959126 :         const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
     225              :         auto it = myConstraints.find(tripID);
     226      8479563 :         if (it != myConstraints.end()) {
     227      8495579 :             for (MSRailSignalConstraint* c : it->second) {
     228              :                 // ignore insertion constraints here
     229      8473783 :                 if (!c->isInsertionConstraint() && !c->cleared()) {
     230              : #ifdef DEBUG_SIGNALSTATE
     231              :                     if (gDebugFlag4) {
     232              :                         std::cout << "  constraint '" << c->getDescription() << "' not cleared\n";
     233              :                     }
     234              : #endif
     235      8443959 :                     if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
     236      8469693 :                             && veh->getWaitingTime() > veh->getVehicleType().getCarFollowModel().getStartupDelay()) {
     237        13929 :                         const SUMOVehicle* foe = c->getFoe();
     238        13929 :                         if (foe != nullptr) {
     239        11889 :                             MSRailSignalControl::getInstance().addWaitRelation(veh, this, foe, c);
     240              :                         }
     241              :                     }
     242      8452376 :                     if (myStoreVehicles) {
     243            0 :                         myConstraintInfo = c->getDescription();
     244              :                     }
     245              :                     return false;
     246              :                 }
     247              :             }
     248              :         }
     249        27187 :         return true;
     250              :     }
     251              : }
     252              : 
     253              : 
     254              : void
     255          934 : MSRailSignal::addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
     256          934 :     myConstraints[tripId].push_back(constraint);
     257          934 : }
     258              : 
     259              : 
     260              : bool
     261          216 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
     262              :     if (myConstraints.count(tripId) != 0) {
     263          216 :         auto& constraints = myConstraints[tripId];
     264          216 :         auto it = std::find(constraints.begin(), constraints.end(), constraint);
     265          216 :         if (it != constraints.end()) {
     266          216 :             delete *it;
     267              :             constraints.erase(it);
     268              :             return true;
     269              :         }
     270              :     }
     271              :     return false;
     272              : }
     273              : 
     274              : void
     275         4721 : MSRailSignal::removeConstraints() {
     276         5510 :     for (auto item : myConstraints) {
     277         1507 :         for (MSRailSignalConstraint* c : item.second) {
     278          718 :             delete c;
     279              :         }
     280              :     }
     281              :     myConstraints.clear();
     282         4721 : }
     283              : 
     284              : 
     285              : // ------------ Static Information Retrieval
     286              : int
     287            0 : MSRailSignal::getPhaseNumber() const {
     288            0 :     return 0;
     289              : }
     290              : 
     291              : const MSTrafficLightLogic::Phases&
     292         4697 : MSRailSignal::getPhases() const {
     293         4697 :     return myPhases;
     294              : }
     295              : 
     296              : const MSPhaseDefinition&
     297            0 : MSRailSignal::getPhase(int) const {
     298            0 :     return myCurrentPhase;
     299              : }
     300              : 
     301              : // ------------ Dynamic Information Retrieval
     302              : int
     303        29614 : MSRailSignal::getCurrentPhaseIndex() const {
     304        29614 :     return myPhaseIndex;
     305              : }
     306              : 
     307              : const MSPhaseDefinition&
     308     18200789 : MSRailSignal::getCurrentPhaseDef() const {
     309     18200789 :     return myCurrentPhase;
     310              : }
     311              : 
     312              : 
     313              : void
     314            1 : MSRailSignal::resetLastSwitch(SUMOTime t) {
     315            1 :     myCurrentPhase.myLastSwitch = t;
     316            1 : }
     317              : 
     318              : 
     319              : // ------------ Conversion between time and phase
     320              : SUMOTime
     321            0 : MSRailSignal::getPhaseIndexAtTime(SUMOTime) const {
     322            0 :     return 0;
     323              : }
     324              : 
     325              : SUMOTime
     326            0 : MSRailSignal::getOffsetFromIndex(int) const {
     327            0 :     return 0;
     328              : }
     329              : 
     330              : int
     331            0 : MSRailSignal::getIndexFromOffset(SUMOTime) const {
     332            0 :     return 0;
     333              : }
     334              : 
     335              : 
     336              : void
     337         5974 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
     338         5974 :     if (pos >= 0) {
     339         5974 :         MSTrafficLightLogic::addLink(link, lane, pos);
     340              :     } // ignore uncontrolled link
     341         5974 : }
     342              : 
     343              : 
     344              : std::string
     345            0 : MSRailSignal::describeLinks(std::vector<MSLink*> links) {
     346              :     std::string result;
     347            0 :     for (MSLink* link : links) {
     348            0 :         result += link->getDescription() + " ";
     349              :     }
     350            0 :     return result;
     351              : }
     352              : 
     353              : 
     354              : void
     355         3990 : MSRailSignal::writeBlocks(OutputDevice& od, bool writeVehicles) const {
     356         7980 :     od.openTag("railSignal");
     357         3990 :     od.writeAttr(SUMO_ATTR_ID, getID());
     358         8577 :     for (const LinkInfo& li : myLinkInfos) {
     359         4587 :         MSLink* link = li.myLink;
     360         9174 :         od.openTag("link");
     361         4587 :         od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex());
     362         4587 :         od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID());
     363         4587 :         od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
     364         9150 :         for (const MSDriveWay* dw : li.myDriveways) {
     365         4563 :             if (writeVehicles) {
     366          371 :                 dw->writeBlockVehicles(od);
     367              :             } else {
     368         4192 :                 dw->writeBlocks(od);
     369              :             }
     370              :         }
     371         9174 :         od.closeTag(); // link
     372              :     }
     373         3990 :     od.closeTag(); // railSignal
     374         3990 : }
     375              : 
     376              : 
     377              : void
     378         3568 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
     379         3568 :     const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
     380         3568 :     int endIndex = ego->getParameter().arrivalEdge;
     381         3568 :     if (endIndex < 0) {
     382         3565 :         endIndex = (int)edges.size() - 1;
     383              :     }
     384         3568 :     int departIndex = ego->getParameter().departEdge;
     385              :     MSDriveWay* prev = nullptr;
     386         3568 :     if (update && ego->hasDeparted()) {
     387              :         // find last rail signal on the route and obtain the driveway
     388          722 :         const MSEdge* next = ego->getEdge();
     389          880 :         for (int i = ego->getRoutePosition() - 1; i > departIndex; i--) {
     390          743 :             const MSEdge* e = ego->getRoute().getEdges()[i];
     391          743 :             if (e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     392          587 :                 const MSLink* link = e->getLanes().front()->getLinkTo(next->getLanes().front());
     393              :                 //std::cout << SIMTIME << " veh=" << ego->getID() << " rp=" << ego->getRoutePosition()
     394              :                 //    << " i=" << i << " e=" << e->getID() << " next=" << next->getID() << " link=" << (link == nullptr ? "NUL" : link->getDescription()) << "\n";
     395          587 :                 if (link != nullptr && link->isTLSControlled()) {
     396          585 :                     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
     397          585 :                     LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
     398          585 :                     prev = &li.getDriveWay(ego, i);
     399          585 :                     departIndex = ego->getRoutePosition();
     400          585 :                     break;
     401              :                 }
     402              :             }
     403              :             next = e;
     404              :         }
     405              :     }
     406          722 :     if (prev == nullptr) {
     407         2983 :         prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego, true));
     408              :     }
     409         3568 :     if (update && ego->hasDeparted()) {
     410          722 :         MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
     411          722 :         if (!prev->hasTrain(veh) && prev->notifyEnter(*veh, prev->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(prev)) {
     412          644 :             veh->addReminder(prev, 1);
     413              :         }
     414              :     }
     415        57877 :     for (int i = departIndex; i <= endIndex - 1; i++) {
     416        54309 :         const MSEdge* e = edges[i];
     417        54309 :         if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     418        35670 :             const MSEdge* e2 = edges[i + 1];
     419        71340 :             for (MSLane* lane : e->getLanes()) {
     420        72287 :                 for (MSLink* link : lane->getLinkCont()) {
     421        36617 :                     if (&link->getLane()->getEdge() == e2) {
     422        35649 :                         MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
     423        33173 :                         if (rs != nullptr) {
     424        33173 :                             LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
     425              :                             // init driveway
     426        33173 :                             MSDriveWay* dw = &li.getDriveWay(ego, i);
     427        33173 :                             MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
     428        33173 :                             MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
     429        33173 :                             MSRailSignalControl::getInstance().notifyApproach(link);
     430              :                             prev = dw;
     431        33173 :                             if (update && rs->isActive()) {
     432              :                                 // vehicle may have rerouted its intial trip
     433              :                                 // after the states have been set
     434              :                                 // @note: This is a hack because it could lead to invalid tls-output
     435              :                                 // (it's still an improvement over switching based on default driveways)
     436        30847 :                                 if (!ego->hasDeparted()) {
     437         8364 :                                     rs->updateCurrentPhase();
     438         8364 :                                     rs->setTrafficLightSignals(SIMSTEP);
     439        22483 :                                 } else if (ego->hasDeparted() && i <= ego->getRoutePosition()) {
     440          723 :                                     MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
     441          723 :                                     if (!dw->hasTrain(veh) && dw->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(dw)) {
     442           47 :                                         veh->addReminder(dw, 1);
     443           63 :                                         for (MSDriveWay* sub : dw->getSubDriveWays()) {
     444           16 :                                             if (!sub->hasTrain(veh) && sub->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(sub)) {
     445            0 :                                                 veh->addReminder(sub, 1);
     446              :                                             }
     447              :                                         }
     448              :                                     }
     449              :                                 }
     450              :                             }
     451              :                         }
     452              :                     }
     453              :                 }
     454              :             }
     455              :         }
     456              :     }
     457         3568 : }
     458              : 
     459              : 
     460              : bool
     461        16761 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
     462        16761 :     if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
     463         5125 :         const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
     464         4925 :         if (rs != nullptr && rs->myConstraints.size() > 0) {
     465         6912 :             const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
     466              :             auto it = rs->myConstraints.find(tripID);
     467         3456 :             if (it != rs->myConstraints.end()) {
     468         3673 :                 for (MSRailSignalConstraint* c : it->second) {
     469         3376 :                     if (c->isInsertionConstraint() && !c->cleared()) {
     470              : #ifdef DEBUG_SIGNALSTATE
     471              :                         if (DEBUG_HELPER(rs)) {
     472              :                             std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
     473              :                         }
     474              : #endif
     475         6216 :                         info = c->getDescription();
     476         3108 :                         isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
     477         3108 :                         if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
     478         3108 :                             const SUMOVehicle* foe = c->getFoe();
     479         3108 :                             if (foe != nullptr) {
     480         3108 :                                 MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
     481              :                             }
     482              :                         }
     483              :                         return true;
     484              :                     }
     485              :                 }
     486              :             }
     487              :         }
     488              :     }
     489              :     return false;
     490              : }
     491              : 
     492              : // ===========================================================================
     493              : // LinkInfo method definitions
     494              : // ===========================================================================
     495              : 
     496         5974 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
     497         5974 :     myLink(link) {
     498         5974 :     reset();
     499         5974 : }
     500              : 
     501        13501 : MSRailSignal::LinkInfo::~LinkInfo() {
     502        18545 :     for (MSDriveWay* dw : myDriveways) {
     503         5044 :         delete dw;
     504              :     }
     505              :     myDriveways.clear();
     506        13501 : }
     507              : 
     508              : void
     509         5979 : MSRailSignal::LinkInfo::reset() {
     510         5979 :     myLastRerouteTime = -1;
     511         5979 :     myLastRerouteVehicle = nullptr;
     512              :     myDriveways.clear();
     513         8742 :     myControlled = isRailwayOrShared(myLink->getViaLaneOrLane()->getPermissions())
     514         5979 :                    && isRailwayOrShared(myLink->getLane()->getPermissions());
     515         5979 : }
     516              : 
     517              : 
     518              : std::string
     519            6 : MSRailSignal::LinkInfo::getID() const {
     520           12 :     return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
     521              : }
     522              : 
     523              : 
     524              : MSDriveWay&
     525      9119846 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh, int searchStart) {
     526      9119846 :     MSEdge* first = &myLink->getLane()->getEdge();
     527      9119846 :     auto searchStartIt = searchStart < 0 ? veh->getCurrentRouteEdge() : veh->getRoute().begin() + searchStart;
     528      9119846 :     MSRouteIterator firstIt = std::find(searchStartIt, veh->getRoute().end(), first);
     529      9119846 :     if (firstIt == veh->getRoute().end()) {
     530              :         // possibly the vehicle has already gone past the first edge (i.e.
     531              :         // because first is short or the step-length is high)
     532              :         // lets look backward along the route
     533              :         // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
     534           79 :         double lookBack = SPEED2DIST(veh->getSpeed() + 10);
     535           79 :         int routeIndex = veh->getRoutePosition() - 1;
     536           85 :         while (lookBack > 0 && routeIndex > 0) {
     537           85 :             const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
     538           85 :             if (prevEdge == first) {
     539           79 :                 firstIt = veh->getRoute().begin() + routeIndex;
     540           79 :                 break;
     541              :             }
     542            6 :             lookBack -= prevEdge->getLength();
     543            6 :             routeIndex--;
     544              :         }
     545              :     }
     546      9119846 :     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
     547      9119846 :     if (firstIt == veh->getRoute().end()) {
     548            0 :         WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
     549              :                       + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
     550            0 :         if (myDriveways.empty()) {
     551              :             ConstMSEdgeVector dummyRoute;
     552            0 :             dummyRoute.push_back(&myLink->getLane()->getEdge());
     553            0 :             MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
     554            0 :             myDriveways.push_back(dw);
     555            0 :         }
     556            0 :         return *myDriveways.front();
     557              :     }
     558              :     //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
     559      9119846 :     return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
     560              : }
     561              : 
     562              : 
     563              : MSDriveWay&
     564      9119846 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
     565      9333496 :     for (MSDriveWay* dw : myDriveways) {
     566      9328452 :         if (dw->match(firstIt, endIt)) {
     567              :             return *dw;
     568              :         }
     569              : #ifdef DEBUG_SELECT_DRIVEWAY
     570              :         std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
     571              : #else
     572              :         UNUSED_PARAMETER(info);
     573              : #endif
     574              :     }
     575         5044 :     MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
     576         5044 :     MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
     577              :     dw->setVehicle(info);
     578              : #ifdef DEBUG_SELECT_DRIVEWAY
     579              :     std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
     580              : #endif
     581         5044 :     myDriveways.push_back(dw);
     582         5044 :     return *myDriveways.back();
     583              : }
     584              : 
     585              : 
     586              : void
     587       232696 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
     588       232696 :     MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
     589       232696 :     const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
     590              :     if (rDev != nullptr
     591       140130 :             && rDev->mayRerouteRailSignal()
     592       232855 :             && (myLastRerouteVehicle != veh
     593              :                 // reroute each vehicle only once if no periodic routing is allowed,
     594              :                 // otherwise with the specified period
     595          153 :                 || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
     596            6 :         myLastRerouteVehicle = veh;
     597            6 :         myLastRerouteTime = now;
     598              : 
     599              : #ifdef DEBUG_REROUTE
     600              :         ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
     601              :         if (DEBUG_COND_LINKINFO) {
     602              :             std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
     603              :         }
     604              : #endif
     605              :         MSRoutingEngine::Prohibitions prohibited;
     606           18 :         for (MSEdge* e : occupied) {
     607              :             // indefinite occupation because vehicles might be in deadlock on their current routes
     608           12 :             prohibited[e].end = std::numeric_limits<double>::max();
     609              :         }
     610           18 :         MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, prohibited);
     611              : #ifdef DEBUG_REROUTE
     612              :         // attention this works only if we are not parallel!
     613              :         if (DEBUG_COND_LINKINFO) {
     614              :             if (veh->getRoute().getEdges() != oldRoute) {
     615              :                 std::cout << "    rerouting successful\n";
     616              :             }
     617              :         }
     618              : #endif
     619              :     }
     620       232696 : }
     621              : 
     622              : void
     623        18352 : MSRailSignal::resetStored() {
     624              :     myBlockingVehicles.clear();
     625              :     myRivalVehicles.clear();
     626              :     myPriorityVehicles.clear();
     627              :     myConstraintInfo = "";
     628              :     myBlockingDriveWays.clear();
     629              :     myRequestedDriveWay = "";
     630        18352 : }
     631              : 
     632              : 
     633              : void
     634            0 : MSRailSignal::storeTraCIVehicles(const MSDriveWay* dw) {
     635            0 :     resetStored();
     636            0 :     myStoreVehicles = true;
     637              :     MSEdgeVector occupied;
     638              :     // call for side effects
     639            0 :     dw->foeDriveWayOccupied(true, nullptr, occupied);
     640            0 :     myStoreVehicles = false;
     641            0 : }
     642              : 
     643              : void
     644        18352 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
     645        18352 :     resetStored();
     646        18352 :     myStoreVehicles = true;
     647        18352 :     LinkInfo& li = myLinkInfos[linkIndex];
     648        18352 :     if (li.myLink->getApproaching().size() > 0) {
     649         1825 :         Approaching closest = li.myLink->getClosest();
     650         1825 :         MSDriveWay& driveway = li.getDriveWay(closest.first);
     651              :         MSEdgeVector occupied;
     652              :         myRequestedDriveWay = driveway.getID();
     653              :         // call for side effects
     654         1825 :         driveway.reserve(closest, occupied);
     655         1825 :         constraintsAllow(closest.first);
     656        18352 :     } else if (li.myDriveways.size() > 0) {
     657        16035 :         li.myDriveways.front()->conflictLaneOccupied();
     658        16035 :         li.myDriveways.front()->foeDriveWayApproached();
     659              :     }
     660        18352 :     myStoreVehicles = false;
     661        18352 : }
     662              : 
     663              : MSRailSignal::VehicleVector
     664         6124 : MSRailSignal::getBlockingVehicles(int linkIndex) {
     665         6124 :     storeTraCIVehicles(linkIndex);
     666         6124 :     return myBlockingVehicles;
     667              : }
     668              : 
     669              : MSRailSignal::VehicleVector
     670         6114 : MSRailSignal::getRivalVehicles(int linkIndex) {
     671         6114 :     storeTraCIVehicles(linkIndex);
     672         6114 :     return myRivalVehicles;
     673              : }
     674              : 
     675              : MSRailSignal::VehicleVector
     676         6114 : MSRailSignal::getPriorityVehicles(int linkIndex) {
     677         6114 :     storeTraCIVehicles(linkIndex);
     678         6114 :     return myPriorityVehicles;
     679              : }
     680              : 
     681              : std::string
     682            0 : MSRailSignal::getConstraintInfo(int linkIndex) {
     683            0 :     storeTraCIVehicles(linkIndex);
     684            0 :     return myConstraintInfo;
     685              : }
     686              : 
     687              : 
     688              : std::string
     689            0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
     690            0 :     storeTraCIVehicles(linkIndex);
     691            0 :     return myRequestedDriveWay;
     692              : }
     693              : 
     694              : 
     695              : std::vector<const MSDriveWay*>
     696            0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
     697            0 :     storeTraCIVehicles(linkIndex);
     698            0 :     return myBlockingDriveWays;
     699              : }
     700              : 
     701              : 
     702              : MSRailSignal::VehicleVector
     703            0 : MSRailSignal::getBlockingVehicles(const MSDriveWay* dw) {
     704            0 :     storeTraCIVehicles(dw);
     705            0 :     return myBlockingVehicles;
     706              : }
     707              : 
     708              : 
     709              : std::vector<const MSDriveWay*>
     710            0 : MSRailSignal::getBlockingDriveWays(const MSDriveWay* dw) {
     711            0 :     storeTraCIVehicles(dw);
     712            0 :     return myBlockingDriveWays;
     713              : }
     714              : 
     715              : const MSDriveWay&
     716            0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
     717            0 :     for (const LinkInfo& li : myLinkInfos) {
     718            0 :         for (const MSDriveWay* dw : li.myDriveways) {
     719            0 :             if (dw->getNumericalID() == numericalID) {
     720            0 :                 return *dw;
     721              :             }
     722              :         }
     723              :     }
     724            0 :     throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
     725              : }
     726              : 
     727              : const MSDriveWay&
     728        42154 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
     729        42154 :     return myLinkInfos[tlIndex].getDriveWay(veh);
     730              : }
     731              : 
     732              : const MSDriveWay&
     733            0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
     734            0 :     return myLinkInfos[tlIndex].getDriveWay(first, end);
     735              : }
     736              : 
     737              : 
     738              : const std::vector<MSDriveWay*>
     739        11523 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
     740        11523 :     return myLinkInfos[tlIndex].myDriveways;
     741              : }
     742              : 
     743              : 
     744              : std::string
     745            0 : MSRailSignal::getBlockingVehicleIDs() const {
     746              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     747            0 :     if (myLinkInfos.size() == 1) {
     748            0 :         return toString(rs->getBlockingVehicles(0));
     749              :     } else {
     750              :         std::string result;
     751            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     752            0 :             result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
     753              :         }
     754            0 :         return result;
     755              :     }
     756              : }
     757              : std::string
     758            0 : MSRailSignal::getRivalVehicleIDs() const {
     759              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     760            0 :     if (myLinkInfos.size() == 1) {
     761            0 :         return toString(rs->getRivalVehicles(0));
     762              :     } else {
     763              :         std::string result;
     764            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     765            0 :             result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
     766              :         }
     767            0 :         return result;
     768              :     }
     769              : }
     770              : std::string
     771            0 : MSRailSignal::getPriorityVehicleIDs() const {
     772              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     773            0 :     if (myLinkInfos.size() == 1) {
     774            0 :         return toString(rs->getPriorityVehicles(0));
     775              :     } else {
     776              :         std::string result;
     777            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     778            0 :             result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
     779              :         }
     780            0 :         return result;
     781              :     }
     782              : }
     783              : std::string
     784            0 : MSRailSignal::getConstraintInfo() const {
     785              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     786            0 :     if (myLinkInfos.size() == 1) {
     787            0 :         return rs->getConstraintInfo(0);
     788              :     } else {
     789              :         std::string result;
     790            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     791            0 :             result += toString(i) + ": " + rs->getConstraintInfo(i);
     792              :         }
     793            0 :         return result;
     794              :     }
     795              : }
     796              : std::string
     797            0 : MSRailSignal::getRequestedDriveWay() const {
     798              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     799            0 :     if (myLinkInfos.size() == 1) {
     800            0 :         return toString(rs->getRequestedDriveWay(0));
     801              :     } else {
     802              :         std::string result;
     803            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     804            0 :             result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
     805              :         }
     806            0 :         return result;
     807              :     }
     808              : }
     809              : std::string
     810            0 : MSRailSignal::getBlockingDriveWayIDs() const {
     811              :     MSRailSignal* rs = const_cast<MSRailSignal*>(this);
     812            0 :     if (myLinkInfos.size() == 1) {
     813            0 :         return toString(rs->getBlockingDriveWays(0));
     814              :     } else {
     815              :         std::string result;
     816            0 :         for (int i = 0; i < (int)myLinkInfos.size(); i++) {
     817            0 :             result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
     818              :         }
     819            0 :         return result;
     820              :     }
     821              : }
     822              : 
     823              : void
     824            5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
     825              :     // some pre-defined parameters can be updated at runtime
     826            5 :     if (key == "moving-block") {
     827            5 :         bool movingBlock = StringUtils::toBool(value);
     828            5 :         if (movingBlock != myMovingBlock) {
     829              :             // recompute driveways
     830            5 :             myMovingBlock = movingBlock;
     831           10 :             for (LinkInfo& li : myLinkInfos) {
     832            5 :                 li.reset();
     833              :             }
     834            5 :             updateCurrentPhase();
     835            5 :             setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     836              :         }
     837              :     }
     838            5 :     Parameterised::setParameter(key, value);
     839            5 : }
     840              : 
     841              : 
     842              : std::string
     843         5044 : MSRailSignal::getNewDrivewayID() {
     844        10088 :     return getID() + "." + toString(myDriveWayIndex++);
     845              : }
     846              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1