LCOV - code coverage report
Current view: top level - src/netload - NLDetectorBuilder.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.0 % 210 187
Test Date: 2025-11-13 15:38:19 Functions: 96.3 % 27 26

            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    NLDetectorBuilder.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Laura Bieker
      17              : /// @author  Clemens Honomichl
      18              : /// @author  Michael Behrisch
      19              : /// @author  Christian Roessel
      20              : /// @author  Jakob Erdmann
      21              : /// @date    Mon, 15 Apr 2002
      22              : ///
      23              : // Builds detectors for microsim
      24              : /****************************************************************************/
      25              : #include <config.h>
      26              : 
      27              : #include <string>
      28              : #include <iostream>
      29              : #include <microsim/MSNet.h>
      30              : #include <microsim/MSLane.h>
      31              : #include <microsim/MSEdge.h>
      32              : #include <microsim/output/MSInductLoop.h>
      33              : #include <microsim/output/MSE2Collector.h>
      34              : // #include <microsim/output/MSMultiLaneE2Collector.h>
      35              : #include <microsim/output/MSVTypeProbe.h>
      36              : #include <microsim/output/MSRouteProbe.h>
      37              : #include <microsim/output/MSMeanData_Net.h>
      38              : #include <microsim/output/MSMeanData_Emissions.h>
      39              : #include <microsim/output/MSMeanData_Harmonoise.h>
      40              : #include <microsim/output/MSMeanData_Amitran.h>
      41              : #include <microsim/output/MSInstantInductLoop.h>
      42              : #include <microsim/MSGlobals.h>
      43              : #include <microsim/actions/Command_SaveTLCoupledDet.h>
      44              : #include <microsim/actions/Command_SaveTLCoupledLaneDet.h>
      45              : #include <utils/common/UtilExceptions.h>
      46              : #include <utils/common/FileHelpers.h>
      47              : #include <utils/common/StringUtils.h>
      48              : #include <utils/common/StringTokenizer.h>
      49              : #include <utils/common/StringUtils.h>
      50              : #include "NLDetectorBuilder.h"
      51              : #include <microsim/output/MSDetectorControl.h>
      52              : 
      53              : #include <mesosim/MEInductLoop.h>
      54              : #include <mesosim/MELoop.h>
      55              : #include <mesosim/MESegment.h>
      56              : 
      57              : 
      58              : // ===========================================================================
      59              : // method definitions
      60              : // ===========================================================================
      61              : /* -------------------------------------------------------------------------
      62              :  * NLDetectorBuilder::E3DetectorDefinition-methods
      63              :  * ----------------------------------------------------------------------- */
      64         1553 : NLDetectorBuilder::E3DetectorDefinition::E3DetectorDefinition(const std::string& id,
      65              :         const std::string& device, double haltingSpeedThreshold,
      66              :         SUMOTime haltingTimeThreshold, SUMOTime splInterval,
      67              :         const std::string name, const std::string& vTypes,
      68              :         const std::string& nextEdges,
      69         1553 :         int detectPersons, bool openEntry, bool expectArrival) :
      70         1553 :     myID(id), myDevice(device),
      71         1553 :     myHaltingSpeedThreshold(haltingSpeedThreshold),
      72         1553 :     myHaltingTimeThreshold(haltingTimeThreshold),
      73         1553 :     mySampleInterval(splInterval),
      74         1553 :     myName(name),
      75         1553 :     myVehicleTypes(vTypes),
      76         1553 :     myNextEdges(nextEdges),
      77         1553 :     myDetectPersons(detectPersons),
      78         1553 :     myOpenEntry(openEntry),
      79         1553 :     myExpectArrival(expectArrival) {
      80         1553 : }
      81              : 
      82              : 
      83         3106 : NLDetectorBuilder::E3DetectorDefinition::~E3DetectorDefinition() {}
      84              : 
      85              : 
      86              : /* -------------------------------------------------------------------------
      87              :  * NLDetectorBuilder-methods
      88              :  * ----------------------------------------------------------------------- */
      89        39058 : NLDetectorBuilder::NLDetectorBuilder(MSNet& net)
      90        39058 :     : myNet(net), myE3Definition(nullptr) {}
      91              : 
      92              : 
      93        39058 : NLDetectorBuilder::~NLDetectorBuilder() {
      94        39058 :     delete myE3Definition;
      95        39058 : }
      96              : 
      97              : 
      98              : Parameterised*
      99        21550 : NLDetectorBuilder::buildInductLoop(const std::string& id,
     100              :                                    const std::string& lane, double pos, double length, SUMOTime splInterval,
     101              :                                    const std::string& device, bool friendlyPos,
     102              :                                    const std::string name,
     103              :                                    const std::string& vTypes,
     104              :                                    const std::string& nextEdges,
     105              :                                    int detectPersons) {
     106        21550 :     checkSampleInterval(splInterval, SUMO_TAG_E1DETECTOR, id);
     107              :     // get and check the lane
     108        21544 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E1DETECTOR, id);
     109              :     // get and check the position
     110        21525 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_E1DETECTOR, id);
     111        21519 :     if (length < 0) {
     112            0 :         throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' cannot be negative");
     113        21519 :     } else if (length > 0 && pos + length > clane->getLength()) {
     114            6 :         if (friendlyPos) {
     115              :             length = MIN2(length, clane->getLength());
     116            6 :             pos = clane->getLength() - length;
     117              :         } else {
     118            0 :             throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' puts it beyond the lane's '" + clane->getID() + "' end.");
     119              :         }
     120              :     }
     121              :     // build the loop
     122        21519 :     MSDetectorFileOutput* loop = createInductLoop(id, clane, pos, length, name, vTypes, nextEdges, detectPersons, true);
     123              :     // add the file output
     124        21513 :     myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
     125        21507 :     return loop;
     126              : }
     127              : 
     128              : 
     129              : Parameterised*
     130         1169 : NLDetectorBuilder::buildInstantInductLoop(const std::string& id,
     131              :         const std::string& lane, double pos,
     132              :         const std::string& device, bool friendlyPos,
     133              :         const std::string name,
     134              :         const std::string& vTypes,
     135              :         const std::string& nextEdges) {
     136              :     // get and check the lane
     137         1169 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
     138              :     // get and check the position
     139         1165 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
     140              :     // build the loop
     141         1161 :     MSDetectorFileOutput* loop = createInstantInductLoop(id, clane, pos, device, name, vTypes, nextEdges);
     142              :     // add the file output
     143         1157 :     myNet.getDetectorControl().add(SUMO_TAG_INSTANT_INDUCTION_LOOP, loop);
     144         1157 :     return loop;
     145              : }
     146              : 
     147              : 
     148              : Parameterised*
     149         3745 : NLDetectorBuilder::buildE2Detector(const std::string& id, MSLane* lane, double pos, double endPos, double length,
     150              :                                    const std::string& device, SUMOTime frequency,
     151              :                                    SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     152              :                                    const std::string name, const std::string& vTypes,
     153              :                                    const std::string& nextEdges,
     154              :                                    int detectPersons, bool friendlyPos, bool showDetector,
     155              :                                    MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
     156              : 
     157              :     bool tlsGiven = tlls != nullptr;
     158              :     bool toLaneGiven = toLane != nullptr;
     159              :     bool posGiven = pos != std::numeric_limits<double>::max();
     160              :     bool endPosGiven = endPos != std::numeric_limits<double>::max();
     161              : 
     162              :     assert(posGiven || endPosGiven);
     163              : 
     164              :     // Check positioning
     165         3745 :     if (posGiven) {
     166         2769 :         if (pos >= lane->getLength() || (pos < 0 && -pos > lane->getLength())) {
     167            8 :             std::stringstream ss;
     168              :             ss << "The given position (=" << pos << ") for detector '" << id
     169              :                << "' does not lie on the given lane '" << lane->getID()
     170              :                << "' with length " << lane->getLength();
     171            8 :             if (friendlyPos) {
     172            4 :                 double newPos = pos > 0 ? lane->getLength() - POSITION_EPS : 0.;
     173              :                 ss << " (adjusting to new position " << newPos;
     174            4 :                 WRITE_WARNING(ss.str());
     175              :                 pos = newPos;
     176              :             } else {
     177            4 :                 ss << " (0 <= pos < lane->getLength() is required)";
     178           12 :                 throw InvalidArgument(ss.str());
     179              :             }
     180            8 :         }
     181              :     }
     182         3741 :     if (endPosGiven) {
     183          998 :         if (endPos > lane->getLength() || (endPos <= 0 && -endPos >= lane->getLength())) {
     184            0 :             std::stringstream ss;
     185              :             ss << "The given end position (=" << endPos << ") for detector '" << id
     186              :                << "' does not lie on the given lane '" << lane->getID()
     187              :                << "' with length " << lane->getLength();
     188            0 :             if (friendlyPos) {
     189            0 :                 double newEndPos = endPos > 0 ? lane->getLength() : POSITION_EPS;
     190              :                 ss << " (adjusting to new position " << newEndPos;
     191            0 :                 WRITE_WARNING(ss.str());
     192              :                 pos = newEndPos;
     193              :             } else {
     194            0 :                 ss << " (0 <= pos < lane->getLength() is required)";
     195            0 :                 throw InvalidArgument(ss.str());
     196              :             }
     197            0 :         }
     198              :     }
     199              : 
     200              :     MSE2Collector* det = nullptr;
     201         3741 :     if (tlsGiven) {
     202              :         // Detector connected to TLS
     203          554 :         det =  createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     204          554 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
     205              :         // add the file output (XXX: Where's the corresponding delete?)
     206          554 :         if (toLaneGiven) {
     207              :             // Detector also associated to specific link
     208              :             const MSLane* const lastLane = det->getLastLane();
     209            8 :             const MSLink* const link = lastLane->getLinkTo(toLane);
     210            8 :             if (link == nullptr) {
     211              :                 throw InvalidArgument(
     212            0 :                     "The detector '" + id + "' cannot be build as no connection between lanes '"
     213            0 :                     + lastLane->getID() + "' and '" + toLane->getID() + "' exists.");
     214              :             }
     215            8 :             new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
     216              :         } else {
     217              :             // detector for tls but without specific link
     218          546 :             new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
     219              :         }
     220              :     } else {
     221              :         // User specified detector for xml-output
     222         3187 :         checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
     223         3183 :         det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     224         3183 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
     225              :     }
     226         3733 :     return det;
     227              : }
     228              : 
     229              : 
     230              : Parameterised*
     231          331 : NLDetectorBuilder::buildE2Detector(const std::string& id, std::vector<MSLane*> lanes, double pos, double endPos,
     232              :                                    const std::string& device, SUMOTime frequency,
     233              :                                    SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     234              :                                    const std::string name, const std::string& vTypes,
     235              :                                    const std::string& nextEdges,
     236              :                                    int detectPersons, bool friendlyPos, bool showDetector,
     237              :                                    MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
     238              : 
     239              :     bool tlsGiven = tlls != nullptr;
     240              :     bool toLaneGiven = toLane != nullptr;
     241              :     assert(pos != std::numeric_limits<double>::max());
     242              :     assert(endPos != std::numeric_limits<double>::max());
     243              :     assert(lanes.size() != 0);
     244              : 
     245          331 :     const MSLane* const firstLane = lanes[0];
     246          331 :     const MSLane* const lastLane = lanes.back();
     247              : 
     248              :     // Check positioning
     249          331 :     if (pos >= firstLane->getLength() || (pos < 0 && -pos > firstLane->getLength())) {
     250            1 :         std::stringstream ss;
     251              :         ss << "The given position (=" << pos << ") for detector '" << id
     252              :            << "' does not lie on the given lane '" << firstLane->getID()
     253              :            << "' with length " << firstLane->getLength();
     254            1 :         if (friendlyPos) {
     255            1 :             double newPos = pos > 0 ? firstLane->getLength() - POSITION_EPS : 0.;
     256              :             ss << " (adjusting to new position " << newPos;
     257            1 :             WRITE_WARNING(ss.str());
     258              :             pos = newPos;
     259              :         } else {
     260            0 :             ss << " (0 <= pos < lane->getLength() is required)";
     261            0 :             throw InvalidArgument(ss.str());
     262              :         }
     263            1 :     }
     264          331 :     if (endPos > lastLane->getLength() || (endPos <= 0 && -endPos >= lastLane->getLength())) {
     265            1 :         std::stringstream ss;
     266              :         ss << "The given end position (=" << endPos << ") for detector '" << id
     267              :            << "' does not lie on the given lane '" << lastLane->getID()
     268              :            << "' with length " << lastLane->getLength();
     269            1 :         if (friendlyPos) {
     270            1 :             double newEndPos = endPos > 0 ? lastLane->getLength() : POSITION_EPS;
     271              :             ss << " (adjusting to new position " << newEndPos;
     272            1 :             WRITE_WARNING(ss.str());
     273              :             pos = newEndPos;
     274              :         } else {
     275            0 :             ss << " (0 <= pos < lane->getLength() is required)";
     276            0 :             throw InvalidArgument(ss.str());
     277              :         }
     278            1 :     }
     279              : 
     280              :     MSE2Collector* det = nullptr;
     281          331 :     if (tlsGiven) {
     282              :         // Detector connected to TLS
     283            5 :         det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     284            5 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
     285              :         // add the file output (XXX: Where's the corresponding delete?)
     286            5 :         if (toLaneGiven) {
     287              :             // Detector also associated to specific link
     288              :             const MSLane* const lastDetLane = det->getLastLane();
     289            0 :             const MSLink* const link = lastDetLane->getLinkTo(toLane);
     290            0 :             if (link == nullptr) {
     291              :                 throw InvalidArgument(
     292            0 :                     "The detector '" + id + "' cannot be build as no connection between lanes '"
     293            0 :                     + lastDetLane->getID() + "' and '" + toLane->getID() + "' exists.");
     294              :             }
     295            0 :             new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
     296              :         } else {
     297              :             // detector for tls but without specific link
     298            5 :             new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
     299              :         }
     300              :     } else {
     301              :         // User specified detector for xml-output
     302          326 :         checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
     303              : 
     304          332 :         det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     305          320 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
     306              :     }
     307          325 :     return det;
     308              : }
     309              : 
     310              : 
     311              : 
     312              : Parameterised*
     313         1557 : NLDetectorBuilder::beginE3Detector(const std::string& id,
     314              :                                    const std::string& device, SUMOTime splInterval,
     315              :                                    double haltingSpeedThreshold,
     316              :                                    SUMOTime haltingTimeThreshold,
     317              :                                    const std::string name,
     318              :                                    const std::string& vTypes,
     319              :                                    const std::string& nextEdges,
     320              :                                    int detectPersons, bool openEntry, bool expectArrival) {
     321         1557 :     checkSampleInterval(splInterval, SUMO_TAG_E3DETECTOR, id);
     322         3106 :     myE3Definition = new E3DetectorDefinition(id, device, haltingSpeedThreshold, haltingTimeThreshold, splInterval, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
     323         1553 :     return myE3Definition;
     324              : }
     325              : 
     326              : 
     327              : void
     328         1883 : NLDetectorBuilder::addE3Entry(const std::string& lane,
     329              :                               double pos, bool friendlyPos) {
     330         1883 :     if (myE3Definition == nullptr) {
     331              :         return;
     332              :     }
     333         1855 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
     334              :     // get and check the position
     335         1851 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_ENTRY, myE3Definition->myID);
     336              :     // build and save the entry
     337         1847 :     myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
     338              : }
     339              : 
     340              : 
     341              : void
     342         1847 : NLDetectorBuilder::addE3Exit(const std::string& lane,
     343              :                              double pos, bool friendlyPos) {
     344         1847 :     if (myE3Definition == nullptr) {
     345              :         return;
     346              :     }
     347         1819 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
     348              :     // get and check the position
     349         1815 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_EXIT, myE3Definition->myID);
     350              :     // build and save the exit
     351         1811 :     myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
     352              : }
     353              : 
     354              : 
     355              : std::string
     356        11310 : NLDetectorBuilder::getCurrentE3ID() const {
     357        11310 :     if (myE3Definition == nullptr) {
     358          168 :         return "<unknown>";
     359              :     }
     360              :     return myE3Definition->myID;
     361              : }
     362              : 
     363              : 
     364              : void
     365         1581 : NLDetectorBuilder::endE3Detector() {
     366         1581 :     if (myE3Definition == nullptr) {
     367              :         return;
     368              :     }
     369              :     // If E3 own entry or exit detectors
     370         1553 :     if (myE3Definition->myEntries.size() > 0 || myE3Definition->myExits.size() > 0) {
     371              :         // create E3 detector
     372         4635 :         MSDetectorFileOutput* det = createE3Detector(myE3Definition->myID,
     373         1545 :                                     myE3Definition->myEntries, myE3Definition->myExits,
     374         1545 :                                     myE3Definition->myHaltingSpeedThreshold, myE3Definition->myHaltingTimeThreshold,
     375              :                                     myE3Definition->myName,
     376         1545 :                                     myE3Definition->myVehicleTypes,
     377         1545 :                                     myE3Definition->myNextEdges,
     378              :                                     myE3Definition->myDetectPersons,
     379         1545 :                                     myE3Definition->myOpenEntry,
     380         1545 :                                     myE3Definition->myExpectArrival);
     381         1545 :         det->updateParameters(myE3Definition->getParametersMap());
     382              :         // add to net
     383         1545 :         myNet.getDetectorControl().add(SUMO_TAG_ENTRY_EXIT_DETECTOR, det, myE3Definition->myDevice, myE3Definition->mySampleInterval);
     384              :     } else {
     385           40 :         WRITE_WARNING(toString(SUMO_TAG_E3DETECTOR) + " with id = '" + myE3Definition->myID + "' will not be created because is empty (no " + toString(SUMO_TAG_DET_ENTRY) + " or " + toString(SUMO_TAG_DET_EXIT) + " was defined)")
     386              :     }
     387              :     // clean up
     388         1545 :     delete myE3Definition;
     389         1545 :     myE3Definition = nullptr;
     390              : }
     391              : 
     392              : 
     393              : void
     394          108 : NLDetectorBuilder::buildVTypeProbe(const std::string& id,
     395              :                                    const std::string& vtype, SUMOTime frequency,
     396              :                                    const std::string& device) {
     397          108 :     checkSampleInterval(frequency, SUMO_TAG_VTYPEPROBE, id);
     398           96 :     new MSVTypeProbe(id, vtype, OutputDevice::getDevice(device), frequency);
     399           90 : }
     400              : 
     401              : 
     402              : void
     403          643 : NLDetectorBuilder::buildRouteProbe(const std::string& id, const std::string& edge,
     404              :                                    SUMOTime frequency, SUMOTime begin,
     405              :                                    const std::string& device,
     406              :                                    const std::string& vTypes) {
     407          643 :     checkSampleInterval(frequency, SUMO_TAG_ROUTEPROBE, id);
     408          643 :     MSEdge* e = getEdgeChecking(edge, SUMO_TAG_ROUTEPROBE, id);
     409         1929 :     MSRouteProbe* probe = new MSRouteProbe(id, e, id + "_" + toString(begin), id + "_" + toString(begin - frequency), vTypes);
     410              :     // add the file output
     411          643 :     myNet.getDetectorControl().add(SUMO_TAG_ROUTEPROBE, probe, device, frequency, begin);
     412          643 : }
     413              : 
     414              : 
     415              : MSDetectorFileOutput*
     416        24147 : NLDetectorBuilder::createInductLoop(const std::string& id,
     417              :                                     MSLane* lane, double pos,
     418              :                                     double length,
     419              :                                     const std::string name,
     420              :                                     const std::string& vTypes,
     421              :                                     const std::string& nextEdges,
     422              :                                     int detectPersons,
     423              :                                     bool /*show*/) {
     424        24147 :     if (MSGlobals::gUseMesoSim) {
     425          567 :         return new MEInductLoop(id, MSGlobals::gMesoNet->getSegmentForEdge(lane->getEdge(), pos), pos, name, vTypes, nextEdges, detectPersons);
     426              :     }
     427        47919 :     return new MSInductLoop(id, lane, pos, length, name, vTypes, nextEdges, detectPersons, false);
     428              : }
     429              : 
     430              : 
     431              : MSDetectorFileOutput*
     432         1039 : NLDetectorBuilder::createInstantInductLoop(const std::string& id,
     433              :         MSLane* lane, double pos, const std::string& od,
     434              :         const std::string name, const std::string& vTypes,
     435              :         const std::string& nextEdges) {
     436         2081 :     return new MSInstantInductLoop(id, OutputDevice::getDevice(od), lane, pos, name, vTypes, nextEdges);
     437              : }
     438              : 
     439              : 
     440              : MSE2Collector*
     441         5800 : NLDetectorBuilder::createE2Detector(const std::string& id,
     442              :                                     DetectorUsage usage, MSLane* lane, double pos, double endPos, double length,
     443              :                                     SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     444              :                                     const std::string name, const std::string& vTypes,
     445              :                                     const std::string& nextEdges,
     446              :                                     int detectPersons, bool /* showDetector */) {
     447        17400 :     return new MSE2Collector(id, usage, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
     448              : }
     449              : 
     450              : MSE2Collector*
     451          325 : NLDetectorBuilder::createE2Detector(const std::string& id,
     452              :                                     DetectorUsage usage, std::vector<MSLane*> lanes, double pos, double endPos,
     453              :                                     SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     454              :                                     const std::string name, const std::string& vTypes,
     455              :                                     const std::string& nextEdges,
     456              :                                     int detectPersons, bool /* showDetector */) {
     457          660 :     return new MSE2Collector(id, usage, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
     458              : }
     459              : 
     460              : MSDetectorFileOutput*
     461         1378 : NLDetectorBuilder::createE3Detector(const std::string& id,
     462              :                                     const CrossSectionVector& entries,
     463              :                                     const CrossSectionVector& exits,
     464              :                                     double haltingSpeedThreshold,
     465              :                                     SUMOTime haltingTimeThreshold,
     466              :                                     const std::string name, const std::string& vTypes,
     467              :                                     const std::string& nextEdges,
     468              :                                     int detectPersons,
     469              :                                     bool openEntry,
     470              :                                     bool expectArrival) {
     471         4134 :     return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
     472              : }
     473              : 
     474              : 
     475              : double
     476        26356 : NLDetectorBuilder::getPositionChecking(double pos, MSLane* lane, bool friendlyPos,
     477              :                                        SumoXMLTag tag,
     478              :                                        const std::string& detid) {
     479              :     // check whether it is given from the end
     480        26356 :     if (pos < 0) {
     481         2227 :         pos += lane->getLength();
     482              :     }
     483              :     // check whether it is on the lane
     484        26356 :     if (pos > lane->getLength()) {
     485          540 :         if (friendlyPos) {
     486              :             pos = lane->getLength();
     487              :         } else {
     488           54 :             throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies beyond the lane's '" + lane->getID() + "' end.");
     489              :         }
     490              :     }
     491        26338 :     if (pos < 0) {
     492          178 :         if (friendlyPos) {
     493              :             pos = 0.;
     494              :         } else {
     495            0 :             throw InvalidArgument("The position of " + toString(tag) + "  '" + detid + "' lies before the lane's '" + lane->getID() + "' begin.");
     496              :         }
     497              :     }
     498        26338 :     return pos;
     499              : }
     500              : 
     501              : 
     502              : void
     503        20305 : NLDetectorBuilder::createEdgeLaneMeanData(const std::string& id, SUMOTime frequency,
     504              :         SUMOTime begin, SUMOTime end, const std::string& type,
     505              :         const bool useLanes, const bool withEmpty, const bool printDefaults,
     506              :         const bool withInternal, const bool trackVehicles, const int detectPersons,
     507              :         const double maxTravelTime, const double minSamples,
     508              :         const double haltSpeed, const std::string& vTypes,
     509              :         const std::string& writeAttributes,
     510              :         std::vector<MSEdge*> edges,
     511              :         bool aggregate,
     512              :         const std::string& device) {
     513        20305 :     if (begin < 0) {
     514          108 :         throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
     515              :     }
     516        20269 :     if (end < 0) {
     517              :         end = SUMOTime_MAX;
     518              :     }
     519        20269 :     if (end <= begin) {
     520          108 :         throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
     521              :     }
     522        40466 :     checkStepLengthMultiple(begin, " for meandata dump '" + id + "'");
     523              :     MSMeanData* det = nullptr;
     524        20233 :     if ((type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::DEFAULT)) ||
     525        20233 :             (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::TRAFFIC)) ||
     526        20164 :             (type == "performance")) {
     527              :         det = new MSMeanData_Net(id, begin, end, useLanes, withEmpty,
     528        18913 :                                  printDefaults, withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
     529         1320 :     } else if ((type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::EMISSIONS)) || (type == "hbefa")) {
     530          888 :         if (type == "hbefa") {
     531           24 :             WRITE_WARNING(TL("The netstate type 'hbefa' is deprecated. Please use the type 'emissions' instead."));
     532              :         }
     533              :         det = new MSMeanData_Emissions(id, begin, end, useLanes, withEmpty,
     534          888 :                                        printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
     535          432 :     } else if (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::HARMONOISE)) {
     536              :         det = new MSMeanData_Harmonoise(id, begin, end, useLanes, withEmpty,
     537          408 :                                         printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
     538           24 :     } else if (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::AMITRAN)) {
     539              :         det = new MSMeanData_Amitran(id, begin, end, useLanes, withEmpty,
     540           24 :                                      printDefaults, withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
     541              :     } else {
     542            0 :         throw InvalidArgument("Invalid type '" + type + "' for meandata dump '" + id + "'.");
     543              :     }
     544              :     if (det != nullptr) {
     545        20233 :         if (frequency < 0) {
     546        16561 :             frequency = end - begin;
     547              :         } else {
     548        11016 :             checkStepLengthMultiple(frequency, " for meandata dump '" + id + "'");
     549              :         }
     550        20233 :         MSNet::getInstance()->getDetectorControl().add(det, device, frequency, begin);
     551              :     }
     552        20233 : }
     553              : 
     554              : 
     555              : 
     556              : 
     557              : // ------ Value checking/adapting methods ------
     558              : MSEdge*
     559          643 : NLDetectorBuilder::getEdgeChecking(const std::string& edgeID, SumoXMLTag type,
     560              :                                    const std::string& detid) {
     561              :     // get and check the lane
     562          643 :     MSEdge* edge = MSEdge::dictionary(edgeID);
     563          643 :     if (edge == nullptr) {
     564            0 :         throw InvalidArgument("The lane with the id '" + edgeID + "' is not known (while building " + toString(type) + " '" + detid + "').");
     565              :     }
     566          643 :     return edge;
     567              : }
     568              : 
     569              : 
     570              : MSLane*
     571        30049 : NLDetectorBuilder::getLaneChecking(const std::string& laneID, SumoXMLTag type,
     572              :                                    const std::string& detid) {
     573              :     // get and check the lane
     574        30049 :     MSLane* lane = MSLane::dictionary(laneID);
     575        30049 :     if (lane == nullptr) {
     576          160 :         throw InvalidArgument("The lane with the id '" + laneID + "' is not known (while building " + toString(type) + " '" + detid + "').");
     577              :     }
     578        30009 :     return lane;
     579              : }
     580              : 
     581              : 
     582              : void
     583        27371 : NLDetectorBuilder::checkSampleInterval(SUMOTime splInterval, SumoXMLTag type, const std::string& id) {
     584        27371 :     if (splInterval < 0) {
     585           60 :         throw InvalidArgument("Negative sampling frequency (in " + toString(type) + " '" + id + "').");
     586              :     }
     587        27351 :     if (splInterval == 0) {
     588           18 :         throw InvalidArgument("Sampling frequency must not be zero (in " + toString(type) + " '" + id + "').");
     589              :     }
     590        54690 :     checkStepLengthMultiple(splInterval, " (in " + toString(type) + " '" + id + "')");
     591        27345 : }
     592              : 
     593              : 
     594              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1