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: 2024-10-24 15:46:30 Functions: - 0 0

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

Generated by: LCOV version 2.0-1