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: 2026-03-02 16:00:03 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-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    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         1408 : 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         1408 :         int detectPersons, bool openEntry, bool expectArrival) :
      70         1408 :     myID(id), myDevice(device),
      71         1408 :     myHaltingSpeedThreshold(haltingSpeedThreshold),
      72         1408 :     myHaltingTimeThreshold(haltingTimeThreshold),
      73         1408 :     mySampleInterval(splInterval),
      74         1408 :     myName(name),
      75         1408 :     myVehicleTypes(vTypes),
      76         1408 :     myNextEdges(nextEdges),
      77         1408 :     myDetectPersons(detectPersons),
      78         1408 :     myOpenEntry(openEntry),
      79         1408 :     myExpectArrival(expectArrival) {
      80         1408 : }
      81              : 
      82              : 
      83         2816 : NLDetectorBuilder::E3DetectorDefinition::~E3DetectorDefinition() {}
      84              : 
      85              : 
      86              : /* -------------------------------------------------------------------------
      87              :  * NLDetectorBuilder-methods
      88              :  * ----------------------------------------------------------------------- */
      89        41274 : NLDetectorBuilder::NLDetectorBuilder(MSNet& net)
      90        41274 :     : myNet(net), myE3Definition(nullptr) {}
      91              : 
      92              : 
      93        41274 : NLDetectorBuilder::~NLDetectorBuilder() {
      94        41274 :     delete myE3Definition;
      95        41274 : }
      96              : 
      97              : 
      98              : Parameterised*
      99        24571 : 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        24571 :     checkSampleInterval(splInterval, SUMO_TAG_E1DETECTOR, id);
     107              :     // get and check the lane
     108        24565 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E1DETECTOR, id);
     109              :     // get and check the position
     110        24546 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_E1DETECTOR, id);
     111        24540 :     if (length < 0) {
     112            0 :         throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' cannot be negative");
     113        24540 :     } 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        24540 :     MSDetectorFileOutput* loop = createInductLoop(id, clane, pos, length, name, vTypes, nextEdges, detectPersons, true);
     123              :     // add the file output
     124        24534 :     myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
     125        24528 :     return loop;
     126              : }
     127              : 
     128              : 
     129              : Parameterised*
     130         1039 : 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              :         int detectPersons) {
     137              :     // get and check the lane
     138         1039 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
     139              :     // get and check the position
     140         1035 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
     141              :     // build the loop
     142         1031 :     MSDetectorFileOutput* loop = createInstantInductLoop(id, clane, pos, device, name, vTypes, nextEdges, detectPersons);
     143              :     // add the file output
     144         1027 :     myNet.getDetectorControl().add(SUMO_TAG_INSTANT_INDUCTION_LOOP, loop);
     145         1027 :     return loop;
     146              : }
     147              : 
     148              : 
     149              : Parameterised*
     150         3816 : NLDetectorBuilder::buildE2Detector(const std::string& id, MSLane* lane, double pos, double endPos, double length,
     151              :                                    const std::string& device, SUMOTime frequency,
     152              :                                    SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     153              :                                    const std::string name, const std::string& vTypes,
     154              :                                    const std::string& nextEdges,
     155              :                                    int detectPersons, bool friendlyPos, bool showDetector,
     156              :                                    MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
     157              : 
     158              :     bool tlsGiven = tlls != nullptr;
     159              :     bool toLaneGiven = toLane != nullptr;
     160              :     bool posGiven = pos != std::numeric_limits<double>::max();
     161              :     bool endPosGiven = endPos != std::numeric_limits<double>::max();
     162              : 
     163              :     assert(posGiven || endPosGiven);
     164              : 
     165              :     // Check positioning
     166         3816 :     if (posGiven) {
     167         2710 :         if (pos >= lane->getLength() || (pos < 0 && -pos > lane->getLength())) {
     168            5 :             std::stringstream ss;
     169              :             ss << "The given position (=" << pos << ") for detector '" << id
     170              :                << "' does not lie on the given lane '" << lane->getID()
     171              :                << "' with length " << lane->getLength();
     172            5 :             if (friendlyPos) {
     173            1 :                 double newPos = pos > 0 ? lane->getLength() - POSITION_EPS : 0.;
     174              :                 ss << " (adjusting to new position " << newPos;
     175            1 :                 WRITE_WARNING(ss.str());
     176              :                 pos = newPos;
     177              :             } else {
     178            4 :                 ss << " (0 <= pos < lane->getLength() is required)";
     179           12 :                 throw InvalidArgument(ss.str());
     180              :             }
     181            5 :         }
     182              :     }
     183         3812 :     if (endPosGiven) {
     184         1135 :         if (endPos > lane->getLength() || (endPos <= 0 && -endPos >= lane->getLength())) {
     185            0 :             std::stringstream ss;
     186              :             ss << "The given end position (=" << endPos << ") for detector '" << id
     187              :                << "' does not lie on the given lane '" << lane->getID()
     188              :                << "' with length " << lane->getLength();
     189            0 :             if (friendlyPos) {
     190            0 :                 double newEndPos = endPos > 0 ? lane->getLength() : POSITION_EPS;
     191              :                 ss << " (adjusting to new position " << newEndPos;
     192            0 :                 WRITE_WARNING(ss.str());
     193              :                 pos = newEndPos;
     194              :             } else {
     195            0 :                 ss << " (0 <= pos < lane->getLength() is required)";
     196            0 :                 throw InvalidArgument(ss.str());
     197              :             }
     198            0 :         }
     199              :     }
     200              : 
     201              :     MSE2Collector* det = nullptr;
     202         3812 :     if (tlsGiven) {
     203              :         // Detector connected to TLS
     204          554 :         det =  createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     205          554 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
     206              :         // add the file output (XXX: Where's the corresponding delete?)
     207          554 :         if (toLaneGiven) {
     208              :             // Detector also associated to specific link
     209              :             const MSLane* const lastLane = det->getLastLane();
     210            8 :             const MSLink* const link = lastLane->getLinkTo(toLane);
     211            8 :             if (link == nullptr) {
     212              :                 throw InvalidArgument(
     213            0 :                     "The detector '" + id + "' cannot be build as no connection between lanes '"
     214            0 :                     + lastLane->getID() + "' and '" + toLane->getID() + "' exists.");
     215              :             }
     216            8 :             new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
     217              :         } else {
     218              :             // detector for tls but without specific link
     219          546 :             new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
     220              :         }
     221              :     } else {
     222              :         // User specified detector for xml-output
     223         3258 :         checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
     224         3254 :         det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     225         3254 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
     226              :     }
     227         3804 :     return det;
     228              : }
     229              : 
     230              : 
     231              : Parameterised*
     232          252 : NLDetectorBuilder::buildE2Detector(const std::string& id, std::vector<MSLane*> lanes, double pos, double endPos,
     233              :                                    const std::string& device, SUMOTime frequency,
     234              :                                    SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     235              :                                    const std::string name, const std::string& vTypes,
     236              :                                    const std::string& nextEdges,
     237              :                                    int detectPersons, bool friendlyPos, bool showDetector,
     238              :                                    MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
     239              : 
     240              :     bool tlsGiven = tlls != nullptr;
     241              :     bool toLaneGiven = toLane != nullptr;
     242              :     assert(pos != std::numeric_limits<double>::max());
     243              :     assert(endPos != std::numeric_limits<double>::max());
     244              :     assert(lanes.size() != 0);
     245              : 
     246          252 :     const MSLane* const firstLane = lanes[0];
     247          252 :     const MSLane* const lastLane = lanes.back();
     248              : 
     249              :     // Check positioning
     250          252 :     if (pos >= firstLane->getLength() || (pos < 0 && -pos > firstLane->getLength())) {
     251            1 :         std::stringstream ss;
     252              :         ss << "The given position (=" << pos << ") for detector '" << id
     253              :            << "' does not lie on the given lane '" << firstLane->getID()
     254              :            << "' with length " << firstLane->getLength();
     255            1 :         if (friendlyPos) {
     256            1 :             double newPos = pos > 0 ? firstLane->getLength() - POSITION_EPS : 0.;
     257              :             ss << " (adjusting to new position " << newPos;
     258            1 :             WRITE_WARNING(ss.str());
     259              :             pos = newPos;
     260              :         } else {
     261            0 :             ss << " (0 <= pos < lane->getLength() is required)";
     262            0 :             throw InvalidArgument(ss.str());
     263              :         }
     264            1 :     }
     265          252 :     if (endPos > lastLane->getLength() || (endPos <= 0 && -endPos >= lastLane->getLength())) {
     266            1 :         std::stringstream ss;
     267              :         ss << "The given end position (=" << endPos << ") for detector '" << id
     268              :            << "' does not lie on the given lane '" << lastLane->getID()
     269              :            << "' with length " << lastLane->getLength();
     270            1 :         if (friendlyPos) {
     271            1 :             double newEndPos = endPos > 0 ? lastLane->getLength() : POSITION_EPS;
     272              :             ss << " (adjusting to new position " << newEndPos;
     273            1 :             WRITE_WARNING(ss.str());
     274              :             pos = newEndPos;
     275              :         } else {
     276            0 :             ss << " (0 <= pos < lane->getLength() is required)";
     277            0 :             throw InvalidArgument(ss.str());
     278              :         }
     279            1 :     }
     280              : 
     281              :     MSE2Collector* det = nullptr;
     282          252 :     if (tlsGiven) {
     283              :         // Detector connected to TLS
     284            3 :         det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     285            3 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
     286              :         // add the file output (XXX: Where's the corresponding delete?)
     287            3 :         if (toLaneGiven) {
     288              :             // Detector also associated to specific link
     289              :             const MSLane* const lastDetLane = det->getLastLane();
     290            0 :             const MSLink* const link = lastDetLane->getLinkTo(toLane);
     291            0 :             if (link == nullptr) {
     292              :                 throw InvalidArgument(
     293            0 :                     "The detector '" + id + "' cannot be build as no connection between lanes '"
     294            0 :                     + lastDetLane->getID() + "' and '" + toLane->getID() + "' exists.");
     295              :             }
     296            0 :             new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
     297              :         } else {
     298              :             // detector for tls but without specific link
     299            3 :             new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
     300              :         }
     301              :     } else {
     302              :         // User specified detector for xml-output
     303          249 :         checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
     304              : 
     305          255 :         det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     306          243 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
     307              :     }
     308          246 :     return det;
     309              : }
     310              : 
     311              : 
     312              : 
     313              : Parameterised*
     314         1412 : NLDetectorBuilder::beginE3Detector(const std::string& id,
     315              :                                    const std::string& device, SUMOTime splInterval,
     316              :                                    double haltingSpeedThreshold,
     317              :                                    SUMOTime haltingTimeThreshold,
     318              :                                    const std::string name,
     319              :                                    const std::string& vTypes,
     320              :                                    const std::string& nextEdges,
     321              :                                    int detectPersons, bool openEntry, bool expectArrival) {
     322         1412 :     checkSampleInterval(splInterval, SUMO_TAG_E3DETECTOR, id);
     323         2816 :     myE3Definition = new E3DetectorDefinition(id, device, haltingSpeedThreshold, haltingTimeThreshold, splInterval, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
     324         1408 :     return myE3Definition;
     325              : }
     326              : 
     327              : 
     328              : void
     329         1738 : NLDetectorBuilder::addE3Entry(const std::string& lane,
     330              :                               double pos, bool friendlyPos) {
     331         1738 :     if (myE3Definition == nullptr) {
     332              :         return;
     333              :     }
     334         1710 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
     335              :     // get and check the position
     336         1706 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_ENTRY, myE3Definition->myID);
     337              :     // build and save the entry
     338         1702 :     myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
     339              : }
     340              : 
     341              : 
     342              : void
     343         1702 : NLDetectorBuilder::addE3Exit(const std::string& lane,
     344              :                              double pos, bool friendlyPos) {
     345         1702 :     if (myE3Definition == nullptr) {
     346              :         return;
     347              :     }
     348         1674 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
     349              :     // get and check the position
     350         1670 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_EXIT, myE3Definition->myID);
     351              :     // build and save the exit
     352         1666 :     myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
     353              : }
     354              : 
     355              : 
     356              : std::string
     357        10440 : NLDetectorBuilder::getCurrentE3ID() const {
     358        10440 :     if (myE3Definition == nullptr) {
     359          168 :         return "<unknown>";
     360              :     }
     361              :     return myE3Definition->myID;
     362              : }
     363              : 
     364              : 
     365              : void
     366         1436 : NLDetectorBuilder::endE3Detector() {
     367         1436 :     if (myE3Definition == nullptr) {
     368              :         return;
     369              :     }
     370              :     // If E3 own entry or exit detectors
     371         1408 :     if (myE3Definition->myEntries.size() > 0 || myE3Definition->myExits.size() > 0) {
     372              :         // create E3 detector
     373         4200 :         MSDetectorFileOutput* det = createE3Detector(myE3Definition->myID,
     374         1400 :                                     myE3Definition->myEntries, myE3Definition->myExits,
     375         1400 :                                     myE3Definition->myHaltingSpeedThreshold, myE3Definition->myHaltingTimeThreshold,
     376              :                                     myE3Definition->myName,
     377         1400 :                                     myE3Definition->myVehicleTypes,
     378         1400 :                                     myE3Definition->myNextEdges,
     379              :                                     myE3Definition->myDetectPersons,
     380         1400 :                                     myE3Definition->myOpenEntry,
     381         1400 :                                     myE3Definition->myExpectArrival);
     382         1400 :         det->updateParameters(myE3Definition->getParametersMap());
     383              :         // add to net
     384         1400 :         myNet.getDetectorControl().add(SUMO_TAG_ENTRY_EXIT_DETECTOR, det, myE3Definition->myDevice, myE3Definition->mySampleInterval);
     385              :     } else {
     386           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)")
     387              :     }
     388              :     // clean up
     389         1400 :     delete myE3Definition;
     390         1400 :     myE3Definition = nullptr;
     391              : }
     392              : 
     393              : 
     394              : void
     395          108 : NLDetectorBuilder::buildVTypeProbe(const std::string& id,
     396              :                                    const std::string& vtype, SUMOTime frequency,
     397              :                                    const std::string& device) {
     398          108 :     checkSampleInterval(frequency, SUMO_TAG_VTYPEPROBE, id);
     399           96 :     new MSVTypeProbe(id, vtype, OutputDevice::getDevice(device), frequency);
     400           90 : }
     401              : 
     402              : 
     403              : void
     404          479 : NLDetectorBuilder::buildRouteProbe(const std::string& id, const std::string& edge,
     405              :                                    SUMOTime frequency, SUMOTime begin,
     406              :                                    const std::string& device,
     407              :                                    const std::string& vTypes) {
     408          479 :     checkSampleInterval(frequency, SUMO_TAG_ROUTEPROBE, id);
     409          479 :     MSEdge* e = getEdgeChecking(edge, SUMO_TAG_ROUTEPROBE, id);
     410         1437 :     MSRouteProbe* probe = new MSRouteProbe(id, e, id + "_" + toString(begin), id + "_" + toString(begin - frequency), vTypes);
     411              :     // add the file output
     412          479 :     myNet.getDetectorControl().add(SUMO_TAG_ROUTEPROBE, probe, device, frequency, begin);
     413          479 : }
     414              : 
     415              : 
     416              : MSDetectorFileOutput*
     417        27011 : NLDetectorBuilder::createInductLoop(const std::string& id,
     418              :                                     MSLane* lane, double pos,
     419              :                                     double length,
     420              :                                     const std::string name,
     421              :                                     const std::string& vTypes,
     422              :                                     const std::string& nextEdges,
     423              :                                     int detectPersons,
     424              :                                     bool /*show*/) {
     425        27011 :     if (MSGlobals::gUseMesoSim) {
     426          567 :         return new MEInductLoop(id, MSGlobals::gMesoNet->getSegmentForEdge(lane->getEdge(), pos), pos, name, vTypes, nextEdges, detectPersons);
     427              :     }
     428        53647 :     return new MSInductLoop(id, lane, pos, length, name, vTypes, nextEdges, detectPersons, false);
     429              : }
     430              : 
     431              : 
     432              : MSDetectorFileOutput*
     433          908 : NLDetectorBuilder::createInstantInductLoop(const std::string& id,
     434              :         MSLane* lane, double pos, const std::string& od,
     435              :         const std::string name, const std::string& vTypes,
     436              :         const std::string& nextEdges,
     437              :         int detectPersons) {
     438         1819 :     return new MSInstantInductLoop(id, OutputDevice::getDevice(od), lane, pos, name, vTypes, nextEdges, detectPersons);
     439              : }
     440              : 
     441              : 
     442              : MSE2Collector*
     443         5669 : NLDetectorBuilder::createE2Detector(const std::string& id,
     444              :                                     DetectorUsage usage, MSLane* lane, double pos, double endPos, double length,
     445              :                                     SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     446              :                                     const std::string name, const std::string& vTypes,
     447              :                                     const std::string& nextEdges,
     448              :                                     int detectPersons, bool /* showDetector */) {
     449        17007 :     return new MSE2Collector(id, usage, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
     450              : }
     451              : 
     452              : MSE2Collector*
     453          246 : NLDetectorBuilder::createE2Detector(const std::string& id,
     454              :                                     DetectorUsage usage, std::vector<MSLane*> lanes, double pos, double endPos,
     455              :                                     SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     456              :                                     const std::string name, const std::string& vTypes,
     457              :                                     const std::string& nextEdges,
     458              :                                     int detectPersons, bool /* showDetector */) {
     459          502 :     return new MSE2Collector(id, usage, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
     460              : }
     461              : 
     462              : MSDetectorFileOutput*
     463         1233 : NLDetectorBuilder::createE3Detector(const std::string& id,
     464              :                                     const CrossSectionVector& entries,
     465              :                                     const CrossSectionVector& exits,
     466              :                                     double haltingSpeedThreshold,
     467              :                                     SUMOTime haltingTimeThreshold,
     468              :                                     const std::string name, const std::string& vTypes,
     469              :                                     const std::string& nextEdges,
     470              :                                     int detectPersons,
     471              :                                     bool openEntry,
     472              :                                     bool expectArrival) {
     473         3699 :     return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
     474              : }
     475              : 
     476              : 
     477              : double
     478        28957 : NLDetectorBuilder::getPositionChecking(double pos, MSLane* lane, bool friendlyPos,
     479              :                                        SumoXMLTag tag,
     480              :                                        const std::string& detid) {
     481              :     // check whether it is given from the end
     482        28957 :     if (pos < 0) {
     483         2324 :         pos += lane->getLength();
     484              :     }
     485              :     // check whether it is on the lane
     486        28957 :     if (pos > lane->getLength()) {
     487          525 :         if (friendlyPos) {
     488              :             pos = lane->getLength();
     489              :         } else {
     490           54 :             throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies beyond the lane's '" + lane->getID() + "' end.");
     491              :         }
     492              :     }
     493        28939 :     if (pos < 0) {
     494          178 :         if (friendlyPos) {
     495              :             pos = 0.;
     496              :         } else {
     497            0 :             throw InvalidArgument("The position of " + toString(tag) + "  '" + detid + "' lies before the lane's '" + lane->getID() + "' begin.");
     498              :         }
     499              :     }
     500        28939 :     return pos;
     501              : }
     502              : 
     503              : 
     504              : void
     505        23326 : NLDetectorBuilder::createEdgeLaneMeanData(const std::string& id, SUMOTime frequency,
     506              :         SUMOTime begin, SUMOTime end, const std::string& type,
     507              :         const bool useLanes, const std::string& excludeEmpty,
     508              :         const bool withInternal, const bool trackVehicles, const int detectPersons,
     509              :         const double maxTravelTime, const double minSamples,
     510              :         const double haltSpeed, const std::string& vTypes,
     511              :         const std::string& writeAttributes,
     512              :         std::vector<MSEdge*> edges,
     513              :         AggregateType aggregate,
     514              :         const std::string& device) {
     515        23326 :     if (begin < 0) {
     516          108 :         throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
     517              :     }
     518        23290 :     if (end < 0) {
     519              :         end = SUMOTime_MAX;
     520              :     }
     521        23290 :     if (end <= begin) {
     522          108 :         throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
     523              :     }
     524        46508 :     checkStepLengthMultiple(begin, " for meandata dump '" + id + "'");
     525              :     MSMeanData* det = nullptr;
     526        23254 :     if ((type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::DEFAULT)) ||
     527        23254 :             (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::TRAFFIC)) ||
     528        23185 :             (type == "performance")) {
     529              :         det = new MSMeanData_Net(id, begin, end, useLanes, excludeEmpty,
     530        21927 :                                  withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
     531         1327 :     } else if ((type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::EMISSIONS)) || (type == "hbefa")) {
     532          891 :         if (type == "hbefa") {
     533           24 :             WRITE_WARNING(TL("The netstate type 'hbefa' is deprecated. Please use the type 'emissions' instead."));
     534              :         }
     535              :         det = new MSMeanData_Emissions(id, begin, end, useLanes, excludeEmpty,
     536          891 :                                        withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
     537          436 :     } else if (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::HARMONOISE)) {
     538              :         det = new MSMeanData_Harmonoise(id, begin, end, useLanes, excludeEmpty,
     539          410 :                                         withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
     540           26 :     } else if (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::AMITRAN)) {
     541              :         det = new MSMeanData_Amitran(id, begin, end, useLanes, excludeEmpty,
     542           26 :                                      withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
     543              :     } else {
     544            0 :         throw InvalidArgument("Invalid type '" + type + "' for meandata dump '" + id + "'.");
     545              :     }
     546              :     if (det != nullptr) {
     547        23254 :         if (frequency < 0) {
     548        19548 :             frequency = end - begin;
     549              :         } else {
     550        11118 :             checkStepLengthMultiple(frequency, " for meandata dump '" + id + "'");
     551              :         }
     552        23254 :         MSNet::getInstance()->getDetectorControl().add(det, device, frequency, begin);
     553              :     }
     554        23254 : }
     555              : 
     556              : 
     557              : 
     558              : 
     559              : // ------ Value checking/adapting methods ------
     560              : MSEdge*
     561          479 : NLDetectorBuilder::getEdgeChecking(const std::string& edgeID, SumoXMLTag type,
     562              :                                    const std::string& detid) {
     563              :     // get and check the lane
     564          479 :     MSEdge* edge = MSEdge::dictionary(edgeID);
     565          479 :     if (edge == nullptr) {
     566            0 :         throw InvalidArgument("The lane with the id '" + edgeID + "' is not known (while building " + toString(type) + " '" + detid + "').");
     567              :     }
     568          479 :     return edge;
     569              : }
     570              : 
     571              : 
     572              : MSLane*
     573        32439 : NLDetectorBuilder::getLaneChecking(const std::string& laneID, SumoXMLTag type,
     574              :                                    const std::string& detid) {
     575              :     // get and check the lane
     576        32439 :     MSLane* lane = MSLane::dictionary(laneID);
     577        32439 :     if (lane == nullptr) {
     578          156 :         throw InvalidArgument("The lane with the id '" + laneID + "' is not known (while building " + toString(type) + " '" + detid + "').");
     579              :     }
     580        32400 :     return lane;
     581              : }
     582              : 
     583              : 
     584              : void
     585        30077 : NLDetectorBuilder::checkSampleInterval(SUMOTime splInterval, SumoXMLTag type, const std::string& id) {
     586        30077 :     if (splInterval < 0) {
     587           60 :         throw InvalidArgument("Negative sampling frequency (in " + toString(type) + " '" + id + "').");
     588              :     }
     589        30057 :     if (splInterval == 0) {
     590           18 :         throw InvalidArgument("Sampling frequency must not be zero (in " + toString(type) + " '" + id + "').");
     591              :     }
     592        60102 :     checkStepLengthMultiple(splInterval, " (in " + toString(type) + " '" + id + "')");
     593        30051 : }
     594              : 
     595              : 
     596              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1