LCOV - code coverage report
Current view: top level - src/netload - NLDetectorBuilder.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.0 % 228 203
Test Date: 2026-09-05 15:36:08 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         1433 : 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         1433 :         int detectPersons, bool openEntry, bool expectArrival) :
      70         1433 :     myID(id), myDevice(device),
      71         1433 :     myHaltingSpeedThreshold(haltingSpeedThreshold),
      72         1433 :     myHaltingTimeThreshold(haltingTimeThreshold),
      73         1433 :     mySampleInterval(splInterval),
      74         1433 :     myName(name),
      75         1433 :     myVehicleTypes(vTypes),
      76         1433 :     myNextEdges(nextEdges),
      77         1433 :     myDetectPersons(detectPersons),
      78         1433 :     myOpenEntry(openEntry),
      79         1433 :     myExpectArrival(expectArrival) {
      80         1433 : }
      81              : 
      82              : 
      83         2866 : NLDetectorBuilder::E3DetectorDefinition::~E3DetectorDefinition() {}
      84              : 
      85              : 
      86              : /* -------------------------------------------------------------------------
      87              :  * NLDetectorBuilder-methods
      88              :  * ----------------------------------------------------------------------- */
      89        42965 : NLDetectorBuilder::NLDetectorBuilder(MSNet& net)
      90        42965 :     : myNet(net), myE3Definition(nullptr) {}
      91              : 
      92              : 
      93        42965 : NLDetectorBuilder::~NLDetectorBuilder() {
      94        42965 :     delete myE3Definition;
      95        42965 : }
      96              : 
      97              : 
      98              : Parameterised*
      99        24631 : 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              :                                    bool mesoTLS,
     106              :                                    int detectPersons) {
     107        24631 :     checkSampleInterval(splInterval, SUMO_TAG_E1DETECTOR, id);
     108              :     // get and check the lane
     109        24625 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E1DETECTOR, id);
     110              :     // get and check the position
     111        24619 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_E1DETECTOR, id);
     112        24613 :     if (length < 0) {
     113            0 :         throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' cannot be negative");
     114        24613 :     } else if (length > 0 && pos + length > clane->getLength()) {
     115            6 :         if (friendlyPos) {
     116              :             length = MIN2(length, clane->getLength());
     117            6 :             pos = clane->getLength() - length;
     118              :         } else {
     119            0 :             throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' puts it beyond the lane's '" + clane->getID() + "' end.");
     120              :         }
     121              :     }
     122              :     // build the loop
     123        24613 :     MSDetectorFileOutput* loop = createInductLoop(id, clane, pos, length, name, vTypes, nextEdges, detectPersons, true, mesoTLS);
     124              :     // add the file output
     125        24607 :     myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
     126        24601 :     return loop;
     127              : }
     128              : 
     129              : 
     130              : Parameterised*
     131         1096 : NLDetectorBuilder::buildInstantInductLoop(const std::string& id,
     132              :         const std::string& lane, double pos,
     133              :         const std::string& device, bool friendlyPos,
     134              :         const std::string name,
     135              :         const std::string& vTypes,
     136              :         const std::string& nextEdges,
     137              :         int detectPersons) {
     138              :     // get and check the lane
     139         1096 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
     140              :     // get and check the position
     141         1092 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
     142              :     // build the loop
     143         1088 :     MSDetectorFileOutput* loop = createInstantInductLoop(id, clane, pos, device, name, vTypes, nextEdges, detectPersons);
     144              :     // add the file output
     145         1084 :     myNet.getDetectorControl().add(SUMO_TAG_INSTANT_INDUCTION_LOOP, loop);
     146         1084 :     return loop;
     147              : }
     148              : 
     149              : 
     150              : Parameterised*
     151         3865 : NLDetectorBuilder::buildE2Detector(const std::string& id, MSLane* lane, double pos, double endPos, double length,
     152              :                                    const std::string& device, SUMOTime frequency,
     153              :                                    SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     154              :                                    const std::string name, const std::string& vTypes,
     155              :                                    const std::string& nextEdges,
     156              :                                    int detectPersons, bool friendlyPos, bool showDetector,
     157              :                                    MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
     158              : 
     159              :     bool tlsGiven = tlls != nullptr;
     160              :     bool toLaneGiven = toLane != nullptr;
     161              :     bool posGiven = pos != std::numeric_limits<double>::max();
     162              :     bool endPosGiven = endPos != std::numeric_limits<double>::max();
     163              : 
     164              :     assert(posGiven || endPosGiven);
     165              : 
     166              :     // Check positioning
     167         3865 :     if (posGiven) {
     168         2759 :         if (pos >= lane->getLength() || (pos < 0 && -pos > lane->getLength())) {
     169            5 :             std::stringstream ss;
     170              :             ss << "The given position (=" << pos << ") for detector '" << id
     171              :                << "' does not lie on the given lane '" << lane->getID()
     172              :                << "' with length " << lane->getLength();
     173            5 :             if (friendlyPos) {
     174            1 :                 double newPos = pos > 0 ? lane->getLength() - POSITION_EPS : 0.;
     175              :                 ss << " (adjusting to new position " << newPos;
     176            1 :                 WRITE_WARNING(ss.str());
     177              :                 pos = newPos;
     178              :             } else {
     179            4 :                 ss << " (0 <= pos < lane->getLength() is required)";
     180           12 :                 throw InvalidArgument(ss.str());
     181              :             }
     182            5 :         }
     183              :     }
     184         3861 :     if (endPosGiven) {
     185         1141 :         if (endPos > lane->getLength() || (endPos <= 0 && -endPos >= lane->getLength())) {
     186            0 :             std::stringstream ss;
     187              :             ss << "The given end position (=" << endPos << ") for detector '" << id
     188              :                << "' does not lie on the given lane '" << lane->getID()
     189              :                << "' with length " << lane->getLength();
     190            0 :             if (friendlyPos) {
     191            0 :                 double newEndPos = endPos > 0 ? lane->getLength() : POSITION_EPS;
     192              :                 ss << " (adjusting to new position " << newEndPos;
     193            0 :                 WRITE_WARNING(ss.str());
     194              :                 pos = newEndPos;
     195              :             } else {
     196            0 :                 ss << " (0 <= pos < lane->getLength() is required)";
     197            0 :                 throw InvalidArgument(ss.str());
     198              :             }
     199            0 :         }
     200              :     }
     201              : 
     202              :     MSE2Collector* det = nullptr;
     203         3861 :     if (tlsGiven) {
     204              :         // Detector connected to TLS
     205          554 :         det =  createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     206          554 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
     207              :         // add the file output (XXX: Where's the corresponding delete?)
     208          554 :         if (toLaneGiven) {
     209              :             // Detector also associated to specific link
     210              :             const MSLane* const lastLane = det->getLastLane();
     211            8 :             const MSLink* const link = lastLane->getLinkTo(toLane);
     212            8 :             if (link == nullptr) {
     213              :                 throw InvalidArgument(
     214            0 :                     "The detector '" + id + "' cannot be build as no connection between lanes '"
     215            0 :                     + lastLane->getID() + "' and '" + toLane->getID() + "' exists.");
     216              :             }
     217            8 :             new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
     218              :         } else {
     219              :             // detector for tls but without specific link
     220          546 :             new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
     221              :         }
     222              :     } else {
     223              :         // User specified detector for xml-output
     224         3307 :         checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
     225         3303 :         det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     226         3303 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
     227              :     }
     228         3853 :     return det;
     229              : }
     230              : 
     231              : 
     232              : Parameterised*
     233          252 : NLDetectorBuilder::buildE2Detector(const std::string& id, std::vector<MSLane*> lanes, double pos, double endPos,
     234              :                                    const std::string& device, SUMOTime frequency,
     235              :                                    SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     236              :                                    const std::string name, const std::string& vTypes,
     237              :                                    const std::string& nextEdges,
     238              :                                    int detectPersons, bool friendlyPos, bool showDetector,
     239              :                                    MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
     240              : 
     241              :     bool tlsGiven = tlls != nullptr;
     242              :     bool toLaneGiven = toLane != nullptr;
     243              :     assert(pos != std::numeric_limits<double>::max());
     244              :     assert(endPos != std::numeric_limits<double>::max());
     245              :     assert(lanes.size() != 0);
     246              : 
     247          252 :     const MSLane* const firstLane = lanes[0];
     248          252 :     const MSLane* const lastLane = lanes.back();
     249              : 
     250              :     // Check positioning
     251          252 :     if (pos >= firstLane->getLength() || (pos < 0 && -pos > firstLane->getLength())) {
     252            1 :         std::stringstream ss;
     253              :         ss << "The given position (=" << pos << ") for detector '" << id
     254              :            << "' does not lie on the given lane '" << firstLane->getID()
     255              :            << "' with length " << firstLane->getLength();
     256            1 :         if (friendlyPos) {
     257            1 :             double newPos = pos > 0 ? firstLane->getLength() - POSITION_EPS : 0.;
     258              :             ss << " (adjusting to new position " << newPos;
     259            1 :             WRITE_WARNING(ss.str());
     260              :             pos = newPos;
     261              :         } else {
     262            0 :             ss << " (0 <= pos < lane->getLength() is required)";
     263            0 :             throw InvalidArgument(ss.str());
     264              :         }
     265            1 :     }
     266          252 :     if (endPos > lastLane->getLength() || (endPos <= 0 && -endPos >= lastLane->getLength())) {
     267            1 :         std::stringstream ss;
     268              :         ss << "The given end position (=" << endPos << ") for detector '" << id
     269              :            << "' does not lie on the given lane '" << lastLane->getID()
     270              :            << "' with length " << lastLane->getLength();
     271            1 :         if (friendlyPos) {
     272            1 :             double newEndPos = endPos > 0 ? lastLane->getLength() : POSITION_EPS;
     273              :             ss << " (adjusting to new position " << newEndPos;
     274            1 :             WRITE_WARNING(ss.str());
     275              :             pos = newEndPos;
     276              :         } else {
     277            0 :             ss << " (0 <= pos < lane->getLength() is required)";
     278            0 :             throw InvalidArgument(ss.str());
     279              :         }
     280            1 :     }
     281              : 
     282              :     MSE2Collector* det = nullptr;
     283          252 :     if (tlsGiven) {
     284              :         // Detector connected to TLS
     285            3 :         det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     286            3 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
     287              :         // add the file output (XXX: Where's the corresponding delete?)
     288            3 :         if (toLaneGiven) {
     289              :             // Detector also associated to specific link
     290              :             const MSLane* const lastDetLane = det->getLastLane();
     291            0 :             const MSLink* const link = lastDetLane->getLinkTo(toLane);
     292            0 :             if (link == nullptr) {
     293              :                 throw InvalidArgument(
     294            0 :                     "The detector '" + id + "' cannot be build as no connection between lanes '"
     295            0 :                     + lastDetLane->getID() + "' and '" + toLane->getID() + "' exists.");
     296              :             }
     297            0 :             new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
     298              :         } else {
     299              :             // detector for tls but without specific link
     300            3 :             new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
     301              :         }
     302              :     } else {
     303              :         // User specified detector for xml-output
     304          249 :         checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
     305              : 
     306          255 :         det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
     307          243 :         myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
     308              :     }
     309          246 :     return det;
     310              : }
     311              : 
     312              : 
     313              : 
     314              : Parameterised*
     315         1437 : NLDetectorBuilder::beginE3Detector(const std::string& id,
     316              :                                    const std::string& device, SUMOTime splInterval,
     317              :                                    double haltingSpeedThreshold,
     318              :                                    SUMOTime haltingTimeThreshold,
     319              :                                    const std::string name,
     320              :                                    const std::string& vTypes,
     321              :                                    const std::string& nextEdges,
     322              :                                    int detectPersons, bool openEntry, bool expectArrival) {
     323         1437 :     checkSampleInterval(splInterval, SUMO_TAG_E3DETECTOR, id);
     324         2866 :     myE3Definition = new E3DetectorDefinition(id, device, haltingSpeedThreshold, haltingTimeThreshold, splInterval, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
     325         1433 :     return myE3Definition;
     326              : }
     327              : 
     328              : 
     329              : void
     330         1795 : NLDetectorBuilder::addE3Entry(const std::string& lane,
     331              :                               double pos, bool friendlyPos) {
     332         1795 :     if (myE3Definition == nullptr) {
     333              :         return;
     334              :     }
     335         1767 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
     336              :     // get and check the position
     337         1763 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_ENTRY, myE3Definition->myID);
     338              :     // build and save the entry
     339         1759 :     myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
     340              : }
     341              : 
     342              : 
     343              : void
     344         1763 : NLDetectorBuilder::addE3Exit(const std::string& lane,
     345              :                              double pos, bool friendlyPos) {
     346         1763 :     if (myE3Definition == nullptr) {
     347              :         return;
     348              :     }
     349         1735 :     MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
     350              :     // get and check the position
     351         1731 :     pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_EXIT, myE3Definition->myID);
     352              :     // build and save the exit
     353         1727 :     myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
     354              : }
     355              : 
     356              : 
     357              : std::string
     358        10794 : NLDetectorBuilder::getCurrentE3ID() const {
     359        10794 :     if (myE3Definition == nullptr) {
     360          168 :         return "<unknown>";
     361              :     }
     362              :     return myE3Definition->myID;
     363              : }
     364              : 
     365              : 
     366              : void
     367         1461 : NLDetectorBuilder::endE3Detector() {
     368         1461 :     if (myE3Definition == nullptr) {
     369              :         return;
     370              :     }
     371              :     // If E3 own entry or exit detectors
     372         1433 :     if (myE3Definition->myEntries.size() > 0 || myE3Definition->myExits.size() > 0) {
     373              :         // create E3 detector
     374         4275 :         MSDetectorFileOutput* det = createE3Detector(myE3Definition->myID,
     375         1425 :                                     myE3Definition->myEntries, myE3Definition->myExits,
     376         1425 :                                     myE3Definition->myHaltingSpeedThreshold, myE3Definition->myHaltingTimeThreshold,
     377              :                                     myE3Definition->myName,
     378         1425 :                                     myE3Definition->myVehicleTypes,
     379         1425 :                                     myE3Definition->myNextEdges,
     380              :                                     myE3Definition->myDetectPersons,
     381         1425 :                                     myE3Definition->myOpenEntry,
     382         1425 :                                     myE3Definition->myExpectArrival);
     383         1425 :         det->updateParameters(myE3Definition->getParametersMap());
     384              :         // add to net
     385         1425 :         myNet.getDetectorControl().add(SUMO_TAG_ENTRY_EXIT_DETECTOR, det, myE3Definition->myDevice, myE3Definition->mySampleInterval);
     386              :     } else {
     387           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)")
     388              :     }
     389              :     // clean up
     390         1425 :     delete myE3Definition;
     391         1425 :     myE3Definition = nullptr;
     392              : }
     393              : 
     394              : 
     395              : void
     396          108 : NLDetectorBuilder::buildVTypeProbe(const std::string& id,
     397              :                                    const std::string& vtype, SUMOTime frequency,
     398              :                                    const std::string& device) {
     399          108 :     checkSampleInterval(frequency, SUMO_TAG_VTYPEPROBE, id);
     400           96 :     new MSVTypeProbe(id, vtype, OutputDevice::getDevice(device), frequency);
     401           90 : }
     402              : 
     403              : 
     404              : void
     405          478 : NLDetectorBuilder::buildRouteProbe(const std::string& id, const std::string& edge,
     406              :                                    SUMOTime frequency, SUMOTime begin,
     407              :                                    const std::string& device,
     408              :                                    const std::string& vTypes) {
     409          478 :     checkSampleInterval(frequency, SUMO_TAG_ROUTEPROBE, id);
     410          478 :     MSEdge* e = getEdgeChecking(edge, SUMO_TAG_ROUTEPROBE, id);
     411         1434 :     MSRouteProbe* probe = new MSRouteProbe(id, e, id + "_" + toString(begin), id + "_" + toString(begin - frequency), vTypes);
     412              :     // add the file output
     413          478 :     myNet.getDetectorControl().add(SUMO_TAG_ROUTEPROBE, probe, device, frequency, begin);
     414          478 : }
     415              : 
     416              : 
     417              : MSDetectorFileOutput*
     418        27931 : NLDetectorBuilder::createInductLoop(const std::string& id,
     419              :                                     MSLane* lane, double pos,
     420              :                                     double length,
     421              :                                     const std::string name,
     422              :                                     const std::string& vTypes,
     423              :                                     const std::string& nextEdges,
     424              :                                     int detectPersons,
     425              :                                     bool /*show*/,
     426              :                                     bool forceMicro) {
     427        27931 :     if (MSGlobals::gUseMesoSim && !forceMicro) {
     428          627 :         return new MEInductLoop(id, MSGlobals::gMesoNet->getSegmentForEdge(lane->getEdge(), pos), pos, name, vTypes, nextEdges, detectPersons);
     429              :     }
     430        55447 :     return new MSInductLoop(id, lane, pos, length, name, vTypes, nextEdges, detectPersons, false);
     431              : }
     432              : 
     433              : 
     434              : MSDetectorFileOutput*
     435          965 : NLDetectorBuilder::createInstantInductLoop(const std::string& id,
     436              :         MSLane* lane, double pos, const std::string& od,
     437              :         const std::string name, const std::string& vTypes,
     438              :         const std::string& nextEdges,
     439              :         int detectPersons) {
     440         1933 :     return new MSInstantInductLoop(id, OutputDevice::getDevice(od), lane, pos, name, vTypes, nextEdges, detectPersons);
     441              : }
     442              : 
     443              : 
     444              : MSE2Collector*
     445         5721 : NLDetectorBuilder::createE2Detector(const std::string& id,
     446              :                                     DetectorUsage usage, MSLane* lane, double pos, double endPos, double length,
     447              :                                     SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     448              :                                     const std::string name, const std::string& vTypes,
     449              :                                     const std::string& nextEdges,
     450              :                                     int detectPersons, bool /* showDetector */) {
     451        17163 :     return new MSE2Collector(id, usage, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
     452              : }
     453              : 
     454              : MSE2Collector*
     455          246 : NLDetectorBuilder::createE2Detector(const std::string& id,
     456              :                                     DetectorUsage usage, std::vector<MSLane*> lanes, double pos, double endPos,
     457              :                                     SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
     458              :                                     const std::string name, const std::string& vTypes,
     459              :                                     const std::string& nextEdges,
     460              :                                     int detectPersons, bool /* showDetector */) {
     461          502 :     return new MSE2Collector(id, usage, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
     462              : }
     463              : 
     464              : MSDetectorFileOutput*
     465         1254 : NLDetectorBuilder::createE3Detector(const std::string& id,
     466              :                                     const CrossSectionVector& entries,
     467              :                                     const CrossSectionVector& exits,
     468              :                                     double haltingSpeedThreshold,
     469              :                                     SUMOTime haltingTimeThreshold,
     470              :                                     const std::string name, const std::string& vTypes,
     471              :                                     const std::string& nextEdges,
     472              :                                     int detectPersons,
     473              :                                     bool openEntry,
     474              :                                     bool expectArrival) {
     475         3762 :     return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
     476              : }
     477              : 
     478              : 
     479              : double
     480        29205 : NLDetectorBuilder::getPositionChecking(double pos, MSLane* lane, bool friendlyPos,
     481              :                                        SumoXMLTag tag,
     482              :                                        const std::string& detid) {
     483              :     // check whether it is given from the end
     484        29205 :     if (pos < 0) {
     485         2382 :         pos += lane->getLength();
     486              :     }
     487              :     // check whether it is on the lane
     488        29205 :     if (pos > lane->getLength()) {
     489          525 :         if (friendlyPos) {
     490              :             pos = lane->getLength();
     491              :         } else {
     492           54 :             throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies beyond the lane's '" + lane->getID() + "' end.");
     493              :         }
     494              :     }
     495        29187 :     if (pos < 0) {
     496          178 :         if (friendlyPos) {
     497              :             pos = 0.;
     498              :         } else {
     499            0 :             throw InvalidArgument("The position of " + toString(tag) + "  '" + detid + "' lies before the lane's '" + lane->getID() + "' begin.");
     500              :         }
     501              :     }
     502        29187 :     return pos;
     503              : }
     504              : 
     505              : 
     506              : void
     507        23426 : NLDetectorBuilder::createEdgeLaneMeanData(const std::string& id, SUMOTime frequency,
     508              :         SUMOTime begin, SUMOTime end, const std::string& type,
     509              :         const bool useLanes, const std::string& excludeEmpty,
     510              :         const bool withInternal, const bool trackVehicles, const int detectPersons,
     511              :         const double maxTravelTime, const double minSamples,
     512              :         const double haltSpeed, const double haltSpeedRel, const std::string& vTypes,
     513              :         const std::string& writeAttributes,
     514              :         std::vector<MSEdge*> edges,
     515              :         AggregateType aggregate,
     516              :         const std::string& device) {
     517        23426 :     if (begin < 0) {
     518          108 :         throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
     519              :     }
     520        23390 :     if (end < 0) {
     521              :         end = SUMOTime_MAX;
     522              :     }
     523        23390 :     if (end <= begin) {
     524          108 :         throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
     525              :     }
     526        70062 :     checkStepLengthMultiple(begin, " for meandata dump '" + id + "'");
     527              :     std::vector<MeanDataType> types;
     528        23354 :     if (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::DEFAULT)) {
     529        87672 :         const SumoXMLAttrMask attrs = OutputDevice::parseWrittenAttributes(StringTokenizer(writeAttributes).getVector(), "meandata '" + id + "'");
     530        21918 :         if (attrs.none()) {
     531        21823 :             types.push_back(MeanDataType::TRAFFIC);
     532              :         } else {
     533           95 :             if (MSMeanData_Net::supports(attrs)) {
     534           85 :                 types.push_back(MeanDataType::TRAFFIC);
     535              :             }
     536           95 :             if (MSMeanData_Emissions::supports(attrs)) {
     537            6 :                 types.push_back(MeanDataType::EMISSIONS);
     538              :             }
     539           95 :             if (MSMeanData_Harmonoise::supports(attrs)) {
     540            0 :                 types.push_back(MeanDataType::HARMONOISE);
     541              :             }
     542              :         }
     543              :     } else {
     544         4308 :         for (const std::string& t : StringTokenizer(type).getVector()) {
     545              :             if (SUMOXMLDefinitions::MeanDataTypes.hasString(t)) {
     546         1424 :                 types.push_back(SUMOXMLDefinitions::MeanDataTypes.get(t));
     547           12 :             } else if (t == "performance") {
     548            0 :                 types.push_back(MeanDataType::TRAFFIC);
     549           12 :             } else if (t == "hbefa") {
     550           12 :                 WRITE_WARNING(TL("The meandata type 'hbefa' is deprecated. Please use the type 'emissions' instead."));
     551           12 :                 types.push_back(MeanDataType::EMISSIONS);
     552              :             } else {
     553            0 :                 throw InvalidArgument("Invalid type '" + t + "' for meandata dump '" + id + "'.");
     554              :             }
     555         1436 :         }
     556              :     }
     557        23354 :     if (frequency < 0) {
     558        19613 :         frequency = end - begin;
     559              :     } else {
     560        11223 :         checkStepLengthMultiple(frequency, " for meandata dump '" + id + "'");
     561              :     }
     562              :     MSMeanData* first = nullptr;
     563              :     MSMeanData* parent = nullptr;
     564        46704 :     for (const MeanDataType t : types) {
     565              :         MSMeanData* det = nullptr;
     566        23350 :         if (t == MeanDataType::TRAFFIC) {
     567              :             det = new MSMeanData_Net(id, begin, end, useLanes, excludeEmpty,
     568        22017 :                                      withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, haltSpeedRel, vTypes, writeAttributes, edges, aggregate);
     569         1333 :         } else if (t == MeanDataType::EMISSIONS) {
     570              :             det = new MSMeanData_Emissions(id, begin, end, useLanes, excludeEmpty,
     571          897 :                                            withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
     572          436 :         } else if (t == MeanDataType::HARMONOISE) {
     573              :             det = new MSMeanData_Harmonoise(id, begin, end, useLanes, excludeEmpty,
     574          410 :                                             withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
     575           26 :         } else if (t == MeanDataType::AMITRAN) {
     576              :             det = new MSMeanData_Amitran(id, begin, end, useLanes, excludeEmpty,
     577           26 :                                          withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
     578              :         }
     579              :         if (det != nullptr) {
     580        23350 :             if (first == nullptr) {
     581              :                 first = det;
     582              :             }
     583        23350 :             if (parent != nullptr) {
     584              :                 parent->setSubData(det);
     585              :             }
     586              :             parent = det;
     587              :         }
     588              :     }
     589        23354 :     if (first != nullptr) {
     590              :         // needs to be delayed because it might call init for the subdata
     591        23344 :         MSNet::getInstance()->getDetectorControl().add(first, device, frequency, begin);
     592              :     }
     593        23354 : }
     594              : 
     595              : 
     596              : 
     597              : 
     598              : // ------ Value checking/adapting methods ------
     599              : MSEdge*
     600          478 : NLDetectorBuilder::getEdgeChecking(const std::string& edgeID, SumoXMLTag type,
     601              :                                    const std::string& detid) {
     602              :     // get and check the lane
     603          478 :     MSEdge* edge = MSEdge::dictionary(edgeID);
     604          478 :     if (edge == nullptr) {
     605            0 :         throw InvalidArgument("The lane with the id '" + edgeID + "' is not known (while building " + toString(type) + " '" + detid + "').");
     606              :     }
     607          478 :     return edge;
     608              : }
     609              : 
     610              : 
     611              : MSLane*
     612        32723 : NLDetectorBuilder::getLaneChecking(const std::string& laneID, SumoXMLTag type,
     613              :                                    const std::string& detid) {
     614              :     // get and check the lane
     615        32723 :     MSLane* lane = MSLane::dictionary(laneID);
     616        32723 :     if (lane == nullptr) {
     617          104 :         throw InvalidArgument("The lane with the id '" + laneID + "' is not known (while building " + toString(type) + " '" + detid + "').");
     618              :     }
     619        32697 :     return lane;
     620              : }
     621              : 
     622              : 
     623              : void
     624        30210 : NLDetectorBuilder::checkSampleInterval(SUMOTime splInterval, SumoXMLTag type, const std::string& id) {
     625        30210 :     if (splInterval < 0) {
     626           60 :         throw InvalidArgument("Negative sampling frequency (in " + toString(type) + " '" + id + "').");
     627              :     }
     628        30190 :     if (splInterval == 0) {
     629           18 :         throw InvalidArgument("Sampling frequency must not be zero (in " + toString(type) + " '" + id + "').");
     630              :     }
     631        60368 :     checkStepLengthMultiple(splInterval, " (in " + toString(type) + " '" + id + "')");
     632        30184 : }
     633              : 
     634              : 
     635              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1