/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file NLDetectorBuilder.h14/// @author Daniel Krajzewicz15/// @author Clemens Honomichl16/// @author Christian Roessel17/// @author Michael Behrisch18/// @date Mon, 15 Apr 200219///20// Builds detectors for microsim21/****************************************************************************/22#pragma once23#include <config.h>2425#include <string>26#include <microsim/output/MSCrossSection.h>27#include <microsim/traffic_lights/MSTLLogicControl.h>28#include <microsim/output/MSE2Collector.h>29// #include <microsim/output/MSMultiLaneE2Collector.h>3031// ===========================================================================32// class declarations33// ===========================================================================34class MSDetectorFileOutput;35class MSLane;36class MSEdge;3738class MEInductLoop;39class MESegment;404142// ===========================================================================43// class definitions44// ===========================================================================45/**46* @class NLDetectorBuilder47* @brief Builds detectors for microsim48*49* The building methods may be overridden, to build guisim-instances of the triggers,50* for example.51*/52class NLDetectorBuilder {53public:54/** @brief Constructor55*56* @param[in] net The network to which's detector control built detector shall be added57*/58NLDetectorBuilder(MSNet& net);596061/// @brief Destructor62virtual ~NLDetectorBuilder();636465/// @name Value parsing and detector building methods66/// @{6768/** @brief Builds an e1 detector and adds it to the net69*70* Checks the given values, first. If one of the values is invalid71* (lane is not known, sampling frequency<=0, position is larger72* than lane's length, the id is already in use), an InvalidArgument is thrown.73*74* Otherwise the e1 detector is built by calling "createInductLoop".75*76* Internally, there is also a distinction whether a mesosim e1 detector77* shall be built.78*79* @param[in] id The id the detector shall have80* @param[in] lane The name of the lane the detector is placed at81* @param[in] pos The definition of the position on the lane the detector shall be placed at82* @param[in] length The optional length of the detector83* @param[in] splInterval The aggregation time span the detector shall use84* @param[in] device The output device the detector shall write into85* @param[in] friendlyPos Whether the position information shall be used "friendly" (see user docs)86* @param[in] vTypes which vehicle types are considered87* @exception InvalidArgument If one of the values is invalid88* @return The created detector89*/90Parameterised* buildInductLoop(const std::string& id,91const std::string& lane, double pos, double length, SUMOTime splInterval,92const std::string& device, bool friendlyPos,93const std::string name, const std::string& vTypes, const std::string& nextEdges, int detectPersons);949596/** @brief Builds an instantenous induction and adds it to the net97*98* Checks the given values, first. If one of the values is invalid99* (lane is not known, sampling frequency<=0, position is larger100* than lane's length, the id is already in use), an InvalidArgument is thrown.101*102* Otherwise the e1 detector is built by calling "createInductLoop".103*104* @param[in] id The id the detector shall have105* @param[in] lane The name of the lane the detector is placed at106* @param[in] pos The definition of the position on the lane the detector shall be placed at107* @param[in] device The output device the detector shall write into108* @param[in] friendlyPos Whether the position information shall be used "friendly" (see user docs)109* @exception InvalidArgument If one of the values is invalid110* @return The created detector111*/112Parameterised* buildInstantInductLoop(const std::string& id,113const std::string& lane, double pos,114const std::string& device, bool friendlyPos,115const std::string name, const std::string& vTypes,116const std::string& nextEdges);117118119/** @brief Builds a new E2 detector and adds it to the net's detector control. Also performs some120* consistency checks for the detector positioning and applies "friendly positioning"121*122* @param[in] tlls Traffic light logic associated to the detector123* @param[in] toLane Lane associated to the detector (only for tlls != 0)124* @param[in] friendlyPos Whether automatic adjustments of the detector position shall be applied in case of erroneous specification125* @see For the other parameters see the MSE2Collector constructors126*127* @todo Add parameter showDetector to indicate whether the detector should be visible in the GUI128*129*/130Parameterised* buildE2Detector(const std::string& id, MSLane* lane, double pos, double endPos, double length,131const std::string& device, SUMOTime frequency,132SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,133const std::string name, const std::string& vTypes,134const std::string& nextEdges,135int detectPersons, bool friendlyPos, bool showDetector,136MSTLLogicControl::TLSLogicVariants* tlls = 0, MSLane* toLane = 0);137138Parameterised* buildE2Detector(const std::string& id, std::vector<MSLane*> lanes, double pos, double endPos,139const std::string& device, SUMOTime frequency,140SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,141const std::string name, const std::string& vTypes,142const std::string& nextEdges,143int detectPersons, bool friendlyPos, bool showDetector,144MSTLLogicControl::TLSLogicVariants* tlls = 0, MSLane* toLane = 0);145146147/** @brief Stores temporary the initial information about an e3 detector to build148*149* If the given sample interval is < 0, an InvalidArgument is thrown. Otherwise,150* the values are stored in a new instance of E3DetectorDefinition within151* "myE3Definition".152*153* @param[in] id The id the detector shall have154* @param[in] device The output device the detector shall write into155* @param[in] splInterval The aggregation time span the detector shall use156* @param[in] haltingTimeThreshold Detector parameter: the time a vehicle's speed must be below haltingSpeedThreshold to be assigned as jammed157* @param[in] haltingSpeedThreshold Detector parameter: the speed a vehicle's speed must be below to be assigned as jammed158* @exception InvalidArgument If one of the values is invalid159*/160Parameterised* beginE3Detector(const std::string& id, const std::string& device, SUMOTime splInterval,161double haltingSpeedThreshold, SUMOTime haltingTimeThreshold,162const std::string name, const std::string& vTypes,163const std::string& nextEdges,164int detectPersons, bool openEntry, bool expectArrival);165166167/** @brief Builds an entry point of an e3 detector168*169* If the lane is not known or the position information is not within the lane,170* an InvalidArgument is thrown. Otherwise a MSCrossSection is built171* using the obtained values and added to the list of entries of the e3 definition172* stored in "myE3Definition".173*174* @param[in] lane The id of the lane the entry shall be placed at175* @param[in] pos The position on the lane the entry shall be placed at176* @param[in] friendlyPos Whether the position information shall be used "friendly" (see user docs)177* @exception InvalidArgument If one of the values is invalid178*/179void addE3Entry(const std::string& lane, double pos, bool friendlyPos);180181182/** @brief Builds an exit point of an e3 detector183*184* If the lane is not known or the position information is not within the lane,185* an InvalidArgument is thrown. Otherwise a MSCrossSection is built186* using the obtained values and added to the list of exits of the e3 definition187* stored in "myE3Definition".188*189* @param[in] lane The id of the lane the exit shall be placed at190* @param[in] pos The position on the lane the exit shall be placed at191* @param[in] friendlyPos Whether the position information shall be used "friendly" (see user docs)192* @exception InvalidArgument If one of the values is invalid193*/194void addE3Exit(const std::string& lane, double pos, bool friendlyPos);195196197/** @brief Builds of an e3 detector using collected values198*199* The parameter collected are used to build an e3 detector using200* "createE3Detector". The resulting detector is added to the net.201*202* @param[in] lane The id of the lane the exit shall be placed at203* @param[in] pos The position on the lane the exit shall be placed at204* @exception InvalidArgument If one of the values is invalid205*/206void endE3Detector();207208209/** @brief Returns the id of the currently built e3 detector210*211* This is used for error-message generation only. If no id is known,212* "<unknown>" is returned.213*214* @return The id of the currently processed e3 detector215*/216std::string getCurrentE3ID() const;217218219/** @brief Builds a vTypeProbe and adds it to the net220*221* Checks the given values, first. If one of the values is invalid222* (sampling frequency<=0), an InvalidArgument is thrown.223*224* Otherwise the vTypeProbe is built (directly).225*226* @param[in] id The id the detector shall have227* @param[in] vtype The name of the vehicle type the detector shall observe228* @param[in] frequency The reporting frequency229* @param[in] device The output device the detector shall write into230* @exception InvalidArgument If one of the values is invalid231*/232void buildVTypeProbe(const std::string& id,233const std::string& vtype, SUMOTime frequency,234const std::string& device);235236237/** @brief Builds a routeProbe and adds it to the net238*239* Checks the given values, first. If one of the values is invalid240* (sampling frequency<=0), an InvalidArgument is thrown.241*242* Otherwise the routeProbe is built (directly).243*244* @param[in] id The id the detector shall have245* @param[in] edge The name of the edge the detector shall observe246* @param[in] frequency The reporting frequency247* @param[in] begin The start of the first reporting interval248* @param[in] device The output device the detector shall write into249* @exception InvalidArgument If one of the values is invalid250*/251void buildRouteProbe(const std::string& id, const std::string& edge,252SUMOTime frequency, SUMOTime begin,253const std::string& device,254const std::string& vTypes);255/// @}256257258259/// @name Detector creating methods260///261/// Virtual, so they may be overwritten, for generating gui-versions of the detectors, for example.262/// @{263264/** @brief Creates an instance of an e1 detector using the given values265*266* Simply calls the MSInductLoop constructor267*268* @param[in] id The id the detector shall have269* @param[in] lane The lane the detector is placed at270* @param[in] pos The position on the lane the detector is placed at271* @param[in] length The optional length of the detector272* @param[in] vTypes which vehicle types are considered273* @param[in] show Whether to show the detector in the gui if available274*/275virtual MSDetectorFileOutput* createInductLoop(const std::string& id,276MSLane* lane, double pos,277double length,278const std::string name, const std::string& vTypes,279const std::string& nextEdges,280int detectPersons,281bool show);282283284/** @brief Creates an instance of an e1 detector using the given values285*286* Simply calls the MSInductLoop constructor287*288* @param[in] id The id the detector shall have289* @param[in] lane The lane the detector is placed at290* @param[in] pos The position on the lane the detector is placed at291* @param[in] od The output device the loop shall use292*/293virtual MSDetectorFileOutput* createInstantInductLoop(const std::string& id,294MSLane* lane, double pos, const std::string& od,295const std::string name, const std::string& vTypes,296const std::string& nextEdges);297298299/** @brief Creates a MSE2Collector instance, overridden by GUIE2Collector::createE2Detector()300*301* Simply calls the MSE2Collector constructor302*303* @see MSE2Collector Constructor documentation304*/305virtual MSE2Collector* createE2Detector(const std::string& id,306DetectorUsage usage, MSLane* lane, double pos, double endPos, double length,307SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,308const std::string name, const std::string& vTypes,309const std::string& nextEdges,310int detectPersons, bool showDetector);311312virtual MSE2Collector* createE2Detector(const std::string& id,313DetectorUsage usage, std::vector<MSLane*> lanes, double pos, double endPos,314SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,315const std::string name, const std::string& vTypes,316const std::string& nextEdges,317int detectPersons, bool showDetector);318319/** @brief Creates an instance of an e3 detector using the given values320*321* Simply calls the MSE3Collector constructor.322*323* @param[in] id The id the detector shall have324* @param[in] entries The list of this detector's entries325* @param[in] exits The list of this detector's exits326* @param[in] haltingSpeedThreshold Detector parameter: the speed a vehicle's speed must be below to be assigned as jammed327* @param[in] haltingTimeThreshold Detector parameter: the time a vehicle's speed must be below haltingSpeedThreshold to be assigned as jammed328*/329virtual MSDetectorFileOutput* createE3Detector(const std::string& id,330const CrossSectionVector& entries, const CrossSectionVector& exits,331double haltingSpeedThreshold, SUMOTime haltingTimeThreshold,332const std::string name, const std::string& vTypes,333const std::string& nextEdges,334int detectPersons, bool openEntry, bool expectArrival);335336337/** @brief Creates edge based mean data collector using the given specification338*339* @param[in] id The id the detector shall have340* @param[in] frequency The aggregation interval the detector shall use341* @param[in] begin dump begin time342* @param[in] end dump end time343* @param[in] type The type of values to be generated344* @param[in] useLanes Information whether lane-based or edge-based dump shall be generated345* @param[in] withEmpty Information whether empty lanes/edges shall be written346* @param[in] withInternal Information whether internal lanes/edges shall be written347* @param[in] trackVehicles Information whether information shall be collected per vehicle348* @param[in] detectPersons Whether pedestrians shall be detected instead of vehicles349* @param[in] maxTravelTime the maximum travel time to output350* @param[in] minSamples the minimum number of sample seconds before the values are valid351* @param[in] haltSpeed the maximum speed to consider a vehicle waiting352* @param[in] vTypes the set of vehicle types to consider353* @exception InvalidArgument If one of the values is invalid354*/355void createEdgeLaneMeanData(const std::string& id, SUMOTime frequency,356SUMOTime begin, SUMOTime end, const std::string& type,357const bool useLanes, const bool withEmpty, const bool printDefaults,358const bool withInternal, const bool trackVehicles, const int detectPersons,359const double maxTravelTime, const double minSamples,360const double haltSpeed, const std::string& vTypes,361const std::string& writeAttributes,362std::vector<MSEdge*> edges,363bool aggregate,364const std::string& device);365/// @}366367368protected:369/**370* @class E3DetectorDefinition371* @brief Holds the incoming definitions of an e3 detector unless the detector is build.372*/373class E3DetectorDefinition : public Parameterised {374public:375/** @brief Constructor376* @param[in] id The id the detector shall have377* @param[in] device The output device the detector shall write into378* @param[in] haltingSpeedThreshold Detector parameter: the speed a vehicle's speed must be below to be assigned as jammed379* @param[in] haltingTimeThreshold Detector parameter: the time a vehicle's speed must be below haltingSpeedThreshold to be assigned as jammed380* @param[in] splInterval The aggregation time span the detector shall use381*/382E3DetectorDefinition(const std::string& id,383const std::string& device, double haltingSpeedThreshold,384SUMOTime haltingTimeThreshold, SUMOTime splInterval,385const std::string name, const std::string& vTypes,386const std::string& nextEdges,387int detectPersons, bool openEntry, bool expectArrival);388389/// @brief Destructor390virtual ~E3DetectorDefinition();391392/// @brief The id of the detector393const std::string myID;394/// @brief The device the detector shall use395const std::string myDevice;396/// @brief The speed a vehicle's speed must be below to be assigned as jammed397double myHaltingSpeedThreshold;398/// @brief The time a vehicle's speed must be below haltingSpeedThreshold to be assigned as jammed399SUMOTime myHaltingTimeThreshold;400/// @brief List of detector's entries401CrossSectionVector myEntries;402/// @brief List of detector's exits403CrossSectionVector myExits;404/// @brief The aggregation interval405SUMOTime mySampleInterval;406/// @brief name407std::string myName;408/// @brief The types to filter409const std::string myVehicleTypes;410/// @brief The route edges to filter by411const std::string myNextEdges;412/// @brief person detection mode413int myDetectPersons;414/// @brief Whether the detector is declared as having incomplete entry detectors415bool myOpenEntry;416/// @brief Whether the detector expects vehicles to arrive inside (and doesn't issue a warning in this case)417bool myExpectArrival;418//@}419420private:421/// @brief Invalidated copy constructor.422E3DetectorDefinition(const E3DetectorDefinition&);423424/// @brief Invalidated assignment operator.425E3DetectorDefinition& operator=(const E3DetectorDefinition&);426427};428429430protected:431/** @brief Computes the position to use432*433* At first, it is checked whether the given position is negative. If so, the434* position is added to the lane's length to obtain the position counted435* backwards.436*437* If the resulting position is beyond or in front (<0) of the lane, it is either438* set to the according lane's boundary (.1 or length-.1) if friendlyPos439* is set, or, if friendlyPos is not set, an InvalidArgument is thrown.440*441* @param[in] pos Definition of the position on the lane442* @param[in] lane The lane the position must be valid for443* @param[in] friendlyPos Whether false positions shall be made acceptable444* @param[in] detid The id of the currently built detector (for error message generation)445* @exception InvalidArgument If the defined position is invalid446*/447double getPositionChecking(double pos, MSLane* lane, bool friendlyPos,448SumoXMLTag tag,449const std::string& detid);450451452/// @name Value checking/adapting methods453/// @{454455/** @brief Returns the named edge456* @param[in] edgeID The id of the lane457* @param[in] type The type of the detector (for error message generation)458* @param[in] detid The id of the currently built detector (for error message generation)459* @exception InvalidArgument If the named edge is not known460*/461MSEdge* getEdgeChecking(const std::string& edgeID, SumoXMLTag type,462const std::string& detid);463464public:465/** @brief Returns the named lane466* @param[in] laneID The id of the lane467* @param[in] type The type of the detector (for error message generation)468* @param[in] detid The id of the currently built detector (for error message generation)469* @exception InvalidArgument If the named lane is not known470*/471MSLane* getLaneChecking(const std::string& laneID, SumoXMLTag type,472const std::string& detid);473474protected:475/** @brief Checks whether the given frequency (sample interval) is valid476* @param[in] splInterval The sample interval477* @param[in] type The type of the detector (for error message generation)478* @param[in] id The id of the detector (for error message generation)479* @exception InvalidArgument If the given sample interval is invalid (<=0)480* @todo Why is splInterval an int???481*/482void checkSampleInterval(SUMOTime splInterval, SumoXMLTag type, const std::string& id);483/// @}484485486protected:487/// @brief The net to fill488MSNet& myNet;489490491private:492/// @brief definition of the currently parsed e3 detector493E3DetectorDefinition* myE3Definition;494495496private:497/// @brief Invalidated copy constructor.498NLDetectorBuilder(const NLDetectorBuilder&);499500/// @brief Invalidated assignment operator.501NLDetectorBuilder& operator=(const NLDetectorBuilder&);502503};504505506