LCOV - code coverage report
Current view: top level - src/microsim/output - MSInductLoop.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 10 10
Test Date: 2026-07-25 16:16:11 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2004-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    MSInductLoop.h
      15              : /// @author  Christian Roessel
      16              : /// @author  Daniel Krajzewicz
      17              : /// @author  Sascha Krieg
      18              : /// @author  Michael Behrisch
      19              : /// @author  Jakob Erdmann
      20              : /// @author  Mirko Barthauer
      21              : /// @date    2004-11-23
      22              : ///
      23              : // An unextended detector measuring at a fixed position on a fixed lane.
      24              : /****************************************************************************/
      25              : #pragma once
      26              : #include <config.h>
      27              : 
      28              : #include <string>
      29              : #include <deque>
      30              : #include <map>
      31              : #include <queue>
      32              : #include <functional>
      33              : #include <microsim/MSMoveReminder.h>
      34              : #include <microsim/output/MSDetectorFileOutput.h>
      35              : 
      36              : 
      37              : // ===========================================================================
      38              : // class declarations
      39              : // ===========================================================================
      40              : class MSLane;
      41              : class MESegment;
      42              : class MSVehicle;
      43              : class OutputDevice;
      44              : 
      45              : 
      46              : // ===========================================================================
      47              : // class definitions
      48              : // ===========================================================================
      49              : /**
      50              :  * @class MSInductLoop
      51              :  * @brief An unextended detector measuring at a fixed position on a fixed lane.
      52              :  *
      53              :  * Only vehicles that passed the entire detector are counted. We
      54              :  *  ignore vehicles that are emitted onto the detector and vehicles
      55              :  *  that change their lane while they are on the detector, because we
      56              :  *  cannot determine a meaningful enter/leave-times.
      57              :  *
      58              :  * This detector uses the MSMoveReminder mechanism, i.e. the vehicles
      59              :  *  call the detector if they pass it.
      60              :  *
      61              :  * @see MSMoveReminder
      62              :  * @see MSDetectorFileOutput
      63              :  */
      64              : class MSInductLoop
      65              :     : public MSMoveReminder, public MSDetectorFileOutput {
      66              : public:
      67              :     /**
      68              :      * @brief Constructor.
      69              :      *
      70              :      * Adds reminder to MSLane.
      71              :      *
      72              :      * @param[in] id Unique id
      73              :      * @param[in] lane Lane where detector works on
      74              :      * @param[in] position Position of the detector within the lane
      75              :      * @param[in] vTypes which vehicle types are considered
      76              :      * @param[in] needLocking whether internals need to be guarded against concurrent access (GUI)
      77              :      */
      78              :     MSInductLoop(const std::string& id, MSLane* const lane,
      79              :                  double positionInMeters,
      80              :                  double length, std::string name,
      81              :                  const std::string& vTypes,
      82              :                  const std::string& nextEdges,
      83              :                  int detectPersons,
      84              :                  const bool needLocking);
      85              : 
      86              : 
      87              :     /// @brief Destructor
      88              :     ~MSInductLoop();
      89              : 
      90              : 
      91              :     /// @brief Resets all generated values to allow computation of next interval
      92              :     virtual void reset();
      93              : 
      94              :     /// @brief get name
      95              :     std::string getName() const {
      96              :         return myName;
      97              :     }
      98              : 
      99              :     /** @brief Returns the position of the detector on the lane
     100              :      * @return The detector's position in meters
     101              :      */
     102              :     double getPosition() const {
     103          536 :         return myPosition;
     104              :     }
     105              : 
     106              :     /** @brief Returns the end position of the detector on the lane
     107              :      * @return The detector's end position in meters
     108              :      */
     109              :     double getEndPosition() const {
     110         2171 :         return myEndPosition;
     111              :     }
     112              : 
     113              : 
     114              :     /// @name Methods inherited from MSMoveReminder
     115              :     /// @{
     116              :     /** @brief Checks whether the reminder is activated by a vehicle entering the lane
     117              :      *
     118              :      * Lane change means in this case that the vehicle changes to the lane
     119              :      *  the reminder is placed at.
     120              :      *
     121              :      * @param[in] veh The entering vehicle.
     122              :      * @param[in] reason how the vehicle enters the lane
     123              :      * @return True if vehicle enters the induction loop
     124              :      * @see Notification
     125              :      */
     126              :     bool notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* enteredLane = 0);
     127              : 
     128              :     /** @brief Checks whether the vehicle shall be counted and/or shall still touch this MSMoveReminder
     129              :      *
     130              :      * As soon a vehicle enters the detector, its entry time is computed and stored
     131              :      *  in myVehiclesOnDet via enterDetectorByMove. If it passes the detector, the
     132              :      *  according leaving time is computed and stored, too, using leaveDetectorByMove.
     133              :      *
     134              :      * @param[in] veh Vehicle that asks this remider.
     135              :      * @param[in] oldPos Position before move.
     136              :      * @param[in] newPos Position after move with newSpeed.
     137              :      * @param[in] newSpeed Moving speed.
     138              :      * @return True if vehicle hasn't passed the detector completely.
     139              :      * @see MSMoveReminder
     140              :      * @see MSMoveReminder::notifyMove
     141              :      * @see enterDetectorByMove
     142              :      * @see leaveDetectorByMove
     143              :      */
     144              :     bool notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed);
     145              : 
     146              : 
     147              :     /** @brief Dismisses the vehicle if it is on the detector due to a lane change
     148              :      *
     149              :      * If the vehicle is on the detector, it will be dismissed by incrementing
     150              :      *  myDismissedVehicleNumber and removing this vehicle's entering time from
     151              :      *  myVehiclesOnDet.
     152              :      *
     153              :      * @param[in] veh The leaving vehicle.
     154              :      * @param[in] lastPos Position on the lane when leaving.
     155              :      * @param[in] isArrival whether the vehicle arrived at its destination
     156              :      * @param[in] isLaneChange whether the vehicle changed from the lane
     157              :      * @see discardVehicle
     158              :      * @see MSMoveReminder
     159              :      * @see MSMoveReminder::notifyLeave
     160              :      */
     161              :     bool notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
     162              : 
     163              : 
     164              :     //@}
     165              : 
     166              : 
     167              : 
     168              :     /// @name Methods returning current values
     169              :     /// @{
     170              : 
     171              :     /** @brief Returns the speed of the vehicle on the detector
     172              :      *
     173              :      * If no vehicle is on the detector, -1 is returned, otherwise
     174              :      *  this vehicle's current speed.
     175              :      *
     176              :      * @return The speed [m/s] of the vehicle if one is on the detector, -1 otherwise
     177              :      */
     178              :     double getSpeed(const int offset) const;
     179              : 
     180              : 
     181              :     /** @brief Returns the length of the vehicle on the detector
     182              :      *
     183              :      * If no vehicle is on the detector, -1 is returned, otherwise
     184              :      *  this vehicle's length.
     185              :      *
     186              :      * @return The length [m] of the vehicle if one is on the detector, -1 otherwise
     187              :      */
     188              :     double getVehicleLength(const int offset) const;
     189              : 
     190              : 
     191              :     /** @brief Returns the current occupancy
     192              :      *
     193              :      * If a vehicle is on the detector, 1 is returned. If a vehicle has passed the detector
     194              :      *  in this timestep, its occupancy value is returned. If no vehicle has passed,
     195              :      *  0 is returned.
     196              :      *
     197              :      * @return This detector's current occupancy
     198              :      * @todo recheck (especially if more than one vehicle has passed)
     199              :      */
     200              :     double getOccupancy() const;
     201              : 
     202              :     /** @brief Returns the number of vehicles that have passed the detector
     203              :      *
     204              :      * If a vehicle is on the detector, 1 is returned. If a vehicle has passed the detector
     205              :      *  in this timestep, 1 is returned. If no vehicle has passed,
     206              :      *  0 is returned.
     207              :      *
     208              :      * @return The number of vehicles that have passed the detector
     209              :      * @todo recheck (especially if more than one vehicle has passed)
     210              :      */
     211              :     double getEnteredNumber(const int offset) const;
     212              : 
     213              : 
     214              :     /** @brief Returns the ids of vehicles that have passed the detector
     215              :      *
     216              :      * @return The ids of vehicles that have passed the detector
     217              :      * @todo recheck (especially if more than one vehicle has passed)
     218              :      */
     219              :     std::vector<std::string> getVehicleIDs(const int offset) const;
     220              : 
     221              :     double getIntervalOccupancy(bool lastInterval = false) const;
     222              :     double getIntervalMeanSpeed(bool lastInterval = false) const;
     223              :     int getIntervalVehicleNumber(bool lastInterval = false) const;
     224              :     std::vector<std::string> getIntervalVehicleIDs(bool lastInterval = false) const;
     225              : 
     226              :     /** @brief Returns the time since the last vehicle left the detector
     227              :      *
     228              :      * @return seconds from last leaving (detection) of the detector
     229              :      */
     230              :     double getTimeSinceLastDetection() const;
     231              : 
     232              :     /** @brief Returns the time of continous occupation by the same vehicle in seconds
     233              :      * or 0 if there is no vehicle on the detector
     234              :      */
     235              :     double getOccupancyTime() const;
     236              : 
     237              :     /** @brief Returns the maximum stop arrival delay of public transport vehicles that are on the detector
     238              :      * or passed the detector in the last step or -INVALID_DOUBLE
     239              :      */
     240              :     double getArrivalDelay() const;
     241              : 
     242              :     ///@brief return last time a vehicle was on the detector
     243              :     SUMOTime getLastDetectionTime() const;
     244              : 
     245              :     double getOverrideTime() const {
     246       203403 :         return myOverrideTime;
     247              :     }
     248              :     //@}
     249              : 
     250              : 
     251              :     /* @brief Persistently overrides the measured time since detection with the given value.
     252              :      * Setting a negative value resets the override
     253              :      */
     254              :     void overrideTimeSinceDetection(double time);
     255              : 
     256              :     /* @brief loads the time since detetion (from state)
     257              :      */
     258              :     void loadTimeSinceLastDetection(double time);
     259              : 
     260              :     /// @name Methods inherited from MSDetectorFileOutput.
     261              :     /// @{
     262              : 
     263              :     /** @brief Writes collected values into the given stream
     264              :      *
     265              :      * @param[in] dev The output device to write the data into
     266              :      * @param[in] startTime First time step the data were gathered
     267              :      * @param[in] stopTime Last time step the data were gathered
     268              :      * @see MSDetectorFileOutput::writeXMLOutput
     269              :      * @exception IOError If an error on writing occurs (!!! not yet implemented)
     270              :      */
     271              :     void writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime);
     272              : 
     273              : 
     274              :     /** @brief Opens the XML-output using "detector" as root element
     275              :      *
     276              :      * @param[in] dev The output device to write the root into
     277              :      * @see MSDetectorFileOutput::writeXMLDetectorProlog
     278              :      * @exception IOError If an error on writing occurs (!!! not yet implemented)
     279              :      */
     280              :     void writeXMLDetectorProlog(OutputDevice& dev) const;
     281              : 
     282              :     /** @brief Updates the detector (computes values)
     283              :      * only used when detecting persons
     284              :      *
     285              :      * @param[in] step The current time step
     286              :      */
     287              :     void detectorUpdate(const SUMOTime step);
     288              :     /// @}
     289              : 
     290              : 
     291              :     /** @brief Struct to store the data of the counted vehicle internally.
     292              :      *
     293              :      * These data is fed into a container.
     294              :      *
     295              :      * @see myVehicleDataCont
     296              :      */
     297      1413679 :     struct VehicleData {
     298              :         /** @brief Constructor
     299              :          *
     300              :          * Used if the vehicle has left the induction loop completely
     301              :          *
     302              :          * @param[in] vehLength The length of the vehicle
     303              :          * @param[in] entryTimestep The time at which the vehicle entered the detector
     304              :          * @param[in] leaveTimestep The time at which the vehicle left the detector
     305              :          * @param[in] leftEarly Whether the vehicle left the detector with a lane change / teleport etc.
     306              :          * @param[in] detLength The length of the detector in meters
     307              :          */
     308              :         VehicleData(const SUMOTrafficObject& v, double entryTimestep,
     309              :                     double leaveTimestep, const bool leftEarly, const double detLength = 0);
     310              : 
     311              :         /// @brief The id of the vehicle
     312              :         std::string idM;
     313              :         /// @brief Length of the vehicle
     314              :         double lengthM;
     315              :         /// @brief Entry-time of the vehicle in [s]
     316              :         double entryTimeM;
     317              :         /// @brief Leave-time of the vehicle in [s]
     318              :         double leaveTimeM;
     319              :         /// @brief Speed of the vehicle in [m/s]
     320              :         double speedM;
     321              :         /// @brief Type of the vehicle
     322              :         std::string typeIDM;
     323              :         /// @brief whether the vehicle left the detector with a lane change / teleport etc.
     324              :         bool leftEarlyM;
     325              :     };
     326              : 
     327              : 
     328              :     /** @brief Returns vehicle data for vehicles that have been on the detector starting at the given time
     329              :      *
     330              :      * @param[in] t The time from which vehicles shall be counted
     331              :      * @param[in] leaveTime Whether entryTime or leaveTime shall be compared against t
     332              :      *            (the latter gives a more complete picture but may include vehicles in multiple steps even if they did not stay on the detector)
     333              :      * @return The list of vehicles
     334              :      */
     335              :     std::vector<VehicleData> collectVehiclesOnDet(SUMOTime t, bool includeEarly = false, bool leaveTime = false, bool forOccupancy = false, bool lastInterval = false) const;
     336              : 
     337              :     /// @brief allows for special color in the gui version
     338       886854 :     virtual void setSpecialColor(const RGBColor* /*color*/) {};
     339              : 
     340           40 :     virtual void setVisible(bool /*show*/) {};
     341              : 
     342              :     /** @brief Remove all vehicles before quick-loading state */
     343              :     virtual void clearState(SUMOTime time);
     344              : 
     345              : protected:
     346              :     /// @name Function for summing up values
     347              :     ///@{
     348              : 
     349              :     /// @brief Adds up VehicleData::speedM
     350         3101 :     static inline double speedSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
     351         3101 :         return sumSoFar + data.speedM;
     352              :     }
     353              : 
     354              :     /// @brief Adds up VehicleData::lengthM
     355           29 :     static inline double lengthSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
     356           29 :         return sumSoFar + data.lengthM;
     357              :     }
     358              :     ///@}
     359              : 
     360              :     /// @brief helper function for mapping person movement
     361              :     void notifyMovePerson(MSTransportable* p, int dir, double pos);
     362              : 
     363              : protected:
     364              :     /// @brief detecto name
     365              :     std::string myName;
     366              : 
     367              :     /// @brief Detector's position on lane [m]
     368              :     const double myPosition;
     369              : 
     370              :     /// @brief Detector's end position (defaults to myPosition)
     371              :     const double myEndPosition;
     372              : 
     373              :     /// @brief whether internals need to be guarded against concurrent access (GUI or multi threading)
     374              :     const bool myNeedLock;
     375              : 
     376              :     /// @brief Leave-time of the last vehicle detected [s]
     377              :     double myLastLeaveTime;
     378              : 
     379              :     /// @brief extrapolated leave times for meso vehicle
     380              :     mutable std::priority_queue<SUMOTime, std::vector<SUMOTime>, std::greater<SUMOTime>> myNextMesoLeaveTimes;
     381              : 
     382              :     /// @brief overrides the time since last detection
     383              :     double myOverrideTime;
     384              : 
     385              :     /// @brief records the time at which overrideTimeSinceDetection was activated
     386              :     double myOverrideEntryTime;
     387              : 
     388              :     /// @brief The number of entered vehicles
     389              :     int myEnteredVehicleNumber;
     390              : 
     391              :     /// @brief Type of myVehicleDataCont.
     392              :     typedef std::deque< VehicleData > VehicleDataCont;
     393              : 
     394              :     /// @brief Data of vehicles that have completely passed the detector
     395              :     VehicleDataCont myVehicleDataCont;
     396              : 
     397              :     /// @brief Data of vehicles that have completely passed the detector in the last time interval
     398              :     VehicleDataCont myLastVehicleDataCont;
     399              : 
     400              :     /// @brief Data for vehicles that have entered the detector (vehicle -> enter time)
     401              :     std::map<SUMOTrafficObject*, double> myVehiclesOnDet;
     402              : 
     403              :     SUMOTime myLastIntervalEnd;
     404              :     SUMOTime myLastIntervalBegin;
     405              : 
     406              :     /// @brief current segment (for actuated tls in meso)
     407              :     MESegment* mySegment;
     408              : 
     409              :     /// @brief position relative to the current segment
     410              :     double mySegmentPos;
     411              : 
     412              : private:
     413              :     /// @brief Invalidated copy constructor.
     414              :     MSInductLoop(const MSInductLoop&);
     415              : 
     416              :     /// @brief Invalidated assignment operator.
     417              :     MSInductLoop& operator=(const MSInductLoop&);
     418              : 
     419              : 
     420              : };
        

Generated by: LCOV version 2.0-1