LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSDriveWay.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 9 9
Test Date: 2025-11-13 15:38:19 Functions: - 0 0

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2002-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    MSDriveWay.h
      15              : /// @author  Jakob Erdmann
      16              : /// @date    December 2021
      17              : ///
      18              : // A sequende of rail tracks (lanes) that may be used as a "set route" (Fahrstraße)
      19              : /****************************************************************************/
      20              : #pragma once
      21              : #include <config.h>
      22              : 
      23              : #include <utils/common/Named.h>
      24              : #include <microsim/MSMoveReminder.h>
      25              : #include <microsim/MSRoute.h>
      26              : 
      27              : // ===========================================================================
      28              : // class declarations
      29              : // ===========================================================================
      30              : class SUMOVehicle;
      31              : class MSLane;
      32              : class MSLink;
      33              : class MSRailSignal;
      34              : 
      35              : // ===========================================================================
      36              : // class definitions
      37              : // ===========================================================================
      38              : /**
      39              :  * @class MSDriveWay
      40              :  */
      41              : class MSDriveWay : public MSMoveReminder, public Named {
      42              : public:
      43              :     typedef std::pair<const SUMOVehicle* const, const MSLink::ApproachingVehicleInformation> Approaching;
      44              :     typedef std::set<const MSLane*, ComparatorNumericalIdLess> LaneSet;
      45              :     typedef std::map<const MSLane*, int, ComparatorNumericalIdLess> LaneVisitedMap;
      46              : 
      47         4754 :     struct VehicleEvent {
      48         1776 :         VehicleEvent(SUMOTime _time, bool _isEntry, const std::string& _id, Notification _reason):
      49         1776 :             time(_time), isEntry(_isEntry), id(_id), reason(_reason) {}
      50              :         SUMOTime time;
      51              :         bool isEntry;
      52              :         std::string id;
      53              :         Notification reason;
      54              :     };
      55              : 
      56              :     /*  The driveways (Fahrstrassen) for each link index of MSRailSignal
      57              :      *  Each link index has at least one driveway
      58              :      *  A driveway describes one possible route that passes the signal up to
      59              :      *  the next secure point
      60              :      *  When a signal guards a switch (indirect guard) that signal stores two
      61              :      *  or more driveways
      62              :      */
      63              :     MSDriveWay(const MSLink* origin, const std::string& id, bool temporary = false);
      64              : 
      65              :     /// @brief Destructor
      66              :     virtual ~MSDriveWay();
      67              : 
      68              :     static void cleanup();
      69              : 
      70              :     static void clearState();
      71              : 
      72              :     static bool haveDriveWays() {
      73          491 :         return myGlobalDriveWayIndex > 0;
      74              :     }
      75              : 
      76              :     static const MSDriveWay* retrieveDepartDriveWay(const MSEdge* edge, const std::string& id);
      77              : 
      78              :     bool notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* enteredLane);
      79              :     bool notifyLeave(SUMOTrafficObject& veh, double lastPos, Notification reason, const MSLane* enteredLane = 0);
      80              :     bool notifyLeaveBack(SUMOTrafficObject& veh, Notification reason, const MSLane* leftLane);
      81              :     bool notifyReroute(SUMOTrafficObject& veh);
      82              : 
      83              :     /// @brief Wether there is a flank conflict with the given driveway
      84              :     bool flankConflict(const MSDriveWay& other) const;
      85              : 
      86              :     /// @brief Wether there is a crossing conflict with the given driveway
      87              :     bool crossingConflict(const MSDriveWay& other) const;
      88              : 
      89              :     /// @brief Wether there is a bidi conflict with the given driveway
      90              :     bool bidiBlockedBy(const MSDriveWay& other) const;
      91              : 
      92              :     /// @brief Wether there is a bidi conflict with the end of the given driveway
      93              :     bool bidiBlockedByEnd(const MSDriveWay& other) const;
      94              : 
      95              :     /// @brief Wether the route of other passes into the forward section of this driveway
      96              :     bool forwardRouteConflict(std::set<const MSEdge*> forward, const MSDriveWay& other, bool secondCheck = false);
      97              : 
      98              :     /// @brief whether any of myConflictLanes is occupied (vehicles that are the target of a join must be ignored)
      99              :     bool conflictLaneOccupied(bool store = true, const SUMOVehicle* ego = nullptr) const;
     100              : 
     101              :     /// @brief whether any of myFoes is occupied (vehicles that are the target of a join must be ignored)
     102              :     bool foeDriveWayOccupied(bool store, const SUMOVehicle* ego, MSEdgeVector& occupied) const;
     103              : 
     104              :     /// @brief whether any of my Foes is being approached
     105              :     bool foeDriveWayApproached() const;
     106              : 
     107              :     /// @brief attempt reserve this driveway for the given vehicle
     108              :     bool reserve(const Approaching& closest, MSEdgeVector& occupied);
     109              : 
     110              :     /// @brief Write block items for this driveway
     111              :     void writeBlocks(OutputDevice& od) const;
     112              :     void writeBlockVehicles(OutputDevice& od) const;
     113              : 
     114              :     const std::vector<const MSEdge*>& getRoute() const {
     115              :         return myRoute;
     116              :     }
     117              : 
     118              :     const std::vector<const MSLane*>& getFlank() const {
     119              :         return myFlank;
     120              :     }
     121              : 
     122              :     const std::vector<const MSLane*>& getBidi() const {
     123              :         return myBidi;
     124              :     }
     125              : 
     126              :     const std::vector<MSLink*>& getConflictLinks() const {
     127              :         return myConflictLinks;
     128              :     }
     129              : 
     130              :     int getNumericalID() const {
     131        22574 :         return myNumericalID;
     132              :     }
     133              : 
     134              :     const std::vector<VehicleEvent>& getEvents() const {
     135              :         return myVehicleEvents;
     136              :     }
     137              : 
     138              :     void setEvents(const std::vector<VehicleEvent>& events) {
     139              :         myVehicleEvents = events;
     140              :     }
     141              : 
     142              :     void setVehicle(const std::string& vehID) {
     143         7206 :         myFirstVehicle = vehID;
     144         2876 :     }
     145              : 
     146              :     const std::vector<MSDriveWay*>& getFoes() const {
     147              :         return myFoes;
     148              :     }
     149              : 
     150              :     const std::vector<const MSLane*>& getForward() const {
     151              :         return myForward;
     152              :     }
     153              : 
     154              :     /// @brief whether the give route matches this driveway
     155              :     bool match(MSRouteIterator firstIt, MSRouteIterator endIt) const;
     156              : 
     157              :     void addDWDeadlock(const std::vector<const MSDriveWay*>& deadlockFoes);
     158              : 
     159              :     bool isDepartDriveway() const {
     160      3991444 :         return myOrigin == nullptr;
     161              :     };
     162              : 
     163              :     const MSLink* getOrigin() const {
     164              :         return myOrigin;
     165              :     }
     166              : 
     167              :     /// @brief whether the given train is on this driveway
     168              :     bool hasTrain(SUMOVehicle* veh) const;
     169              : 
     170              :     const std::vector<MSDriveWay*>& getSubDriveWays() const {
     171              :         return mySubDriveWays;
     172              :     }
     173              : 
     174              :     static void init();
     175              : 
     176              :     static bool hasRS(const MSEdge* cur, const MSEdge* next);
     177              : 
     178              :     /// @brief Whether veh must yield to the foe train
     179              :     static bool mustYield(const Approaching& veh, const Approaching& foe);
     180              : 
     181              :     /// @brief construct a new driveway by searching along the given route until all block structures are found
     182              :     static MSDriveWay* buildDriveWay(const std::string& id, const MSLink* link, MSRouteIterator first, MSRouteIterator end);
     183              : 
     184              :     /// @brief return logicID_linkIndex in a way that allows clicking in sumo-gui
     185              :     static std::string getClickableTLLinkID(const MSLink* link);
     186              : 
     187              :     static const MSDriveWay* getDepartureDriveway(const SUMOVehicle* veh, bool init = false);
     188              : 
     189              :     static void writeDepatureBlocks(OutputDevice& od, bool writeVehicles);
     190              : 
     191              :     /** @brief Save driveway occupancy into the given stream */
     192              :     static void saveState(OutputDevice& out);
     193              :     static void loadState(const SUMOSAXAttributes& attrs, int tag);
     194              : 
     195              : protected:
     196              : 
     197              :     /// @brief global driveway index
     198              :     int myNumericalID;
     199              : 
     200              :     /// @brief the link that enters this driveway or nullptr for a departure driveWay
     201              :     const MSLink* myOrigin;
     202              : 
     203              :     /// @brief whether the current signal is switched green for a train approaching this block
     204              :     const SUMOVehicle* myActive;
     205              : 
     206              :     /// @brief list of edges for matching against train routes
     207              :     std::vector<const MSEdge*> myRoute;
     208              : 
     209              :     /// @brief number of edges in myRoute where overlap with other driveways is forbidden
     210              :     int myCoreSize;
     211              : 
     212              :     /// @brief number of normal edges in myForward
     213              :     int myForwardEdgeCount;
     214              : 
     215              :     /// @brief whether this driveway ends its forward section with a rail signal (and thus comprises a full block)
     216              :     bool myFoundSignal;
     217              :     bool myFoundJump;
     218              :     bool myTerminateRoute;
     219              :     /// @brief whether driveway building was aborted due to MAX_BLOCK_LENGTH
     220              :     bool myAbortedBuild;
     221              :     /// @brief whether driveway building was aborted when no further bidi edge was found
     222              :     bool myBidiEnded;
     223              :     bool myIsSubDriveway;
     224              : 
     225              :     /* @brief the actual driveway part up to the next railsignal (halting position)
     226              :      * This must be free of other trains */
     227              :     std::vector<const MSLane*> myForward;
     228              : 
     229              :     /* @brief the list of bidirectional edges that can enter the forward
     230              :      * section and which must also be free of traffic
     231              :      * (up to the first element that could give protection) */
     232              :     std::vector<const MSLane*> myBidi;
     233              : 
     234              :     /* @brief the list of bidirectional edges that can enter the forward
     235              :      * section and which might contain deadlock-relevant traffic */
     236              :     std::vector<const MSLane*> myBidiExtended;
     237              : 
     238              :     /* @brief the list of edges that merge with the forward section
     239              :      * (found via backward search, up to the first element that could give protection) */
     240              :     std::vector<const MSLane*> myFlank;
     241              : 
     242              :     /// @brief the lanes that must be clear of trains before this signal can switch to green
     243              :     std::vector<const MSLane*> myConflictLanes;
     244              : 
     245              :     /* The conflict links for this block
     246              :      * Conflict resolution must be performed if vehicles are approaching the
     247              :      * current link and any of the conflict links */
     248              :     std::vector<MSLink*> myConflictLinks;
     249              : 
     250              :     /// @brief Whether the approaching vehicle is prevent from driving by another vehicle approaching the given link
     251              :     bool hasLinkConflict(const Approaching& closest, const MSLink* foeLink) const;
     252              : 
     253              :     /// @brief Wether this driveway (route) overlaps with the given one
     254              :     bool overlap(const MSDriveWay& other) const;
     255              : 
     256              :     /* @brief determine route that identifies this driveway (a subset of the
     257              :      * vehicle route)
     258              :      * collects:
     259              :      *   myRoute
     260              :      *   myForward
     261              :      *   myBidi
     262              :      *   myProtectedBidi
     263              :      *
     264              :      * returns edge that is assumed to safe from oncoming-deadlock or nullptr
     265              :      */
     266              :     void buildRoute(const MSLink* origin, MSRouteIterator next, MSRouteIterator end, LaneVisitedMap& visited, std::set<MSLink*>&);
     267              : 
     268              :     /* @brief find switches that threaten this driveway
     269              :      * @param[out] flankSwitches collect the switches
     270              :      */
     271              :     void checkFlanks(const MSLink* originLink, const std::vector<const MSLane*>& lanes, const LaneVisitedMap& visited, bool allFoes, std::set<MSLink*>& flankSwitches) const;
     272              : 
     273              :     /* @brief find links that cross the driveway without entering it
     274              :      * @param[out] flankSwitches collect the switches
     275              :      */
     276              :     void checkCrossingFlanks(MSLink* dwLink, const LaneVisitedMap& visited, std::set<MSLink*>& flankSwitches) const;
     277              : 
     278              :     /* @brief find upstream protection from the given link
     279              :      * @param[out] flank: the stored flank lanes
     280              :      */
     281              :     void findFlankProtection(MSLink* link, MSLink* origLink, std::vector<const MSLane*>& flank);
     282              : 
     283              :     /// @brief add all driveWays that start at the given link as foes
     284              :     void addFoes(const MSLink* link);
     285              : 
     286              :     /// @brief add sidings for the given foe
     287              :     void addSidings(MSDriveWay* foe, bool addToFoe = false);
     288              : 
     289              :     /// @brief derive foe driveways based on myBidi or myBidiExtended
     290              :     void addBidiFoes(const MSRailSignal* ownSignal, bool extended);
     291              : 
     292              :     /// @brief derive foe driveways that start at the same signal
     293              :     void addParallelFoes(const MSLink* link, const MSEdge* first);
     294              : 
     295              :     /// @brief derive foe driveways that enter the bidi section by reversing
     296              :     void addReversalFoes(bool movingBlock);
     297              : 
     298              :     /* @brief build shortened driveway that ends where the foe train leaves the conflict zone of this driveway
     299              :      * @return whether the foe has received a new entry in myFoes
     300              :      */
     301              :     bool buildSubFoe(MSDriveWay* foe, bool movingBlock);
     302              : 
     303              :     /// @brief add symmetical conflict link for foes when building a new driveway
     304              :     void addConflictLink(const MSLink* link);
     305              : 
     306              :     /// @brief return whether a siding can be used. If a siding exist but is occupied, also return the occupied driveway in the siding
     307              :     std::pair<bool, const MSDriveWay*> canUseSiding(const SUMOVehicle* ego, const MSDriveWay* foe, bool recurse = true) const;
     308              : 
     309              :     bool isFoeOrSubFoe(const MSDriveWay* foe) const;
     310              : 
     311              :     bool forwardEndOnRoute(const MSDriveWay* foe) const;
     312              : 
     313              :     void addSwitchFoes(MSLink* link);
     314              : 
     315              :     bool haveSubTrains() const;
     316              : 
     317              :     /* @brief whether the train would have matched this driveway in it's past
     318              :      * @return If matching, returns the number of edges the vehicle has gone past the start of the driveway,
     319              :      *         Indicate no-match by returning a negative value */
     320              :     int matchesPastRoute(SUMOVehicle& sveh) const;
     321              : 
     322              :     /// @brief helper method for notifyEnter
     323              :     void enterDriveWay(SUMOVehicle& sveh, Notification reason);
     324              : 
     325              :     static bool hasJoin(const SUMOVehicle* ego, const SUMOVehicle* foe);
     326              : 
     327              :     static bool isSwitch(const MSLink* link);
     328              : 
     329              :     void _saveState(OutputDevice& out) const;
     330              : 
     331              :     /// @brief return logicID_linkIndex
     332              :     static std::string getTLLinkID(const MSLink* link);
     333              : 
     334              :     /// @brief return junctionID_junctionLinkIndex
     335              :     static std::string getJunctionLinkID(const MSLink* link);
     336              : 
     337              :     /// @brief print link descriptions
     338              :     static std::string formatVisitedMap(const LaneVisitedMap& visited);
     339              : 
     340              :     /// @brief append to map by map index and avoid undefined behavior
     341              :     static void appendMapIndex(LaneVisitedMap& map, const MSLane* lane);
     342              : 
     343              : private:
     344              : 
     345              :     struct Siding {
     346          544 :         Siding(int s, int e, double l) : start(s), end(e), length(l) {}
     347              :         // indices along route
     348              :         int start;
     349              :         int end;
     350              :         double length;
     351              :     };
     352              : 
     353              :     std::set<SUMOVehicle*> myTrains;
     354              : 
     355              :     std::vector<VehicleEvent> myVehicleEvents;
     356              :     std::vector<MSDriveWay*> myFoes;
     357              :     std::map<const MSDriveWay*, std::vector<Siding>, ComparatorIdLess> mySidings;
     358              :     std::vector<std::set <const MSDriveWay*> > myDeadlocks;
     359              : 
     360              :     /* @brief shortened versions of this driveway to be used as foes instead of the long original
     361              :      * (ends as soon as the train has left a particular conflict section)
     362              :      * they are never attached to a LinkInfo and thus never the target of the match() function */
     363              :     std::vector<MSDriveWay*> mySubDriveWays;
     364              : 
     365              :     /// @brief track own occurences in myReversalDriveWays for cleanup in destructor
     366              :     std::vector<const MSEdge*> myReversals;
     367              : 
     368              :     /// @brief the first vehicle using this driveway
     369              :     std::string myFirstVehicle;
     370              : 
     371              :     static int myGlobalDriveWayIndex;
     372              :     static bool myWriteVehicles;
     373              :     static std::set<const MSEdge*> myBlockLengthWarnings;
     374              : 
     375              :     /// @brief all driveways passing the given switch (used to look up flank foes)
     376              :     static std::map<const MSLink*, std::vector<MSDriveWay*> > mySwitchDriveWays;
     377              : 
     378              :     /// @brief all driveways reversing on the given switch (used to look up flank foes)
     379              :     static std::map<const MSEdge*, std::vector<MSDriveWay*> > myReversalDriveWays;
     380              : 
     381              :     /// @brief all driveways that do not start at a rail signal (and are only used at departure)
     382              :     static std::map<const MSEdge*, std::vector<MSDriveWay*>, ComparatorNumericalIdLess > myDepartureDriveways;
     383              :     static std::map<const MSJunction*, int> myDepartDrivewayIndex;
     384              :     /// @brief all driveways that do not start at a rail signal (and are only used at departure) by end edge
     385              :     static std::map<const MSEdge*, std::vector<MSDriveWay*> > myDepartureDrivewaysEnds;
     386              : 
     387              :     /// @brief all driveways that end on the given edge
     388              :     static std::map<const MSEdge*, std::vector<MSDriveWay*>, ComparatorNumericalIdLess> myEndingDriveways;
     389              : 
     390              :     /// @brief lookup table for state loading
     391              :     static std::map<ConstMSEdgeVector, MSDriveWay*> myDriveWayRouteLookup;
     392              :     static std::map<std::string, MSDriveWay*> myDriveWayLookup;
     393              : 
     394              : };
        

Generated by: LCOV version 2.0-1