LCOV - code coverage report
Current view: top level - src/microsim/output - MSInstantInductLoop.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 59 59
Test Date: 2026-03-02 16:00:03 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2011-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    MSInstantInductLoop.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    2011-09.08
      19              : ///
      20              : // An instantaneous induction loop
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include "MSInstantInductLoop.h"
      25              : #include <cassert>
      26              : #include <numeric>
      27              : #include <utility>
      28              : #ifdef HAVE_FOX
      29              : #include <utils/common/ScopedLocker.h>
      30              : #endif
      31              : #include <utils/common/WrappingCommand.h>
      32              : #include <utils/common/ToString.h>
      33              : #include <microsim/MSEventControl.h>
      34              : #include <microsim/MSLane.h>
      35              : #include <microsim/MSVehicle.h>
      36              : #include <microsim/MSNet.h>
      37              : #include <utils/common/MsgHandler.h>
      38              : #include <utils/common/UtilExceptions.h>
      39              : #include <utils/common/StringUtils.h>
      40              : #include <utils/iodevices/OutputDevice.h>
      41              : 
      42              : 
      43              : // ===========================================================================
      44              : // method definitions
      45              : // ===========================================================================
      46         1027 : MSInstantInductLoop::MSInstantInductLoop(const std::string& id,
      47              :         OutputDevice& od, MSLane* const lane, double positionInMeters,
      48              :         const std::string name, const std::string& vTypes,
      49              :         const std::string& nextEdges,
      50         1027 :         int detectPersons) :
      51              :     MSMoveReminder(id, lane),
      52              :     MSDetectorFileOutput(id, vTypes, nextEdges, detectPersons),
      53         1027 :     myName(name),
      54         1027 :     myOutputDevice(od),
      55         2054 :     myPosition(positionInMeters), myLastExitTime(-1) {
      56              :     assert(myPosition >= 0 && myPosition <= myLane->getLength());
      57         1027 :     writeXMLDetectorProlog(od);
      58         1027 : }
      59              : 
      60              : 
      61         1932 : MSInstantInductLoop::~MSInstantInductLoop() {
      62         1932 : }
      63              : 
      64              : bool
      65        20832 : MSInstantInductLoop::notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* /*enteredLane*/) {
      66              :     // vehicles must be kept if the "inductionloop" wants to detect passeengers
      67        20832 :     if (!vehicleApplies(veh)) {
      68              :         return false;
      69              :     }
      70        19828 :     if (reason != NOTIFICATION_JUNCTION) { // the junction case is handled in notifyMove
      71         1788 :         if (veh.getBackPositionOnLane(myLane) >= myPosition) {
      72              :             return false;
      73              :         }
      74         1775 :         if (veh.getPositionOnLane() >= myPosition) {
      75           11 :             double entryTime = SIMTIME;
      76           11 :             if (myLastExitTime >= 0) {
      77            4 :                 write("enter", entryTime, veh, veh.getSpeed(), "gap", entryTime - myLastExitTime);
      78              :             } else {
      79            7 :                 write("enter", entryTime, veh, veh.getSpeed());
      80              :             }
      81           11 :             myEntryTimes[&veh] = entryTime;
      82              :         }
      83              :     }
      84              :     return true;
      85              : }
      86              : 
      87              : 
      88              : bool
      89        95615 : MSInstantInductLoop::notifyMove(SUMOTrafficObject& veh, double oldPos,
      90              :                                 double newPos, double newSpeed) {
      91        95615 :     if (!vehicleApplies(veh)) {
      92              :         return false;
      93              :     }
      94        95579 :     if (newPos < myPosition) {
      95              :         // detector not reached yet
      96              :         return true;
      97              :     }
      98              : #ifdef HAVE_FOX
      99        26571 :     ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
     100              : #endif
     101              : 
     102        26571 :     const double oldSpeed = veh.getPreviousSpeed();
     103              :     double enterSpeed = MSGlobals::gSemiImplicitEulerUpdate ? newSpeed : oldSpeed; // NOTE: For the euler update, the vehicle is assumed to travel at constant speed for the whole time step
     104              : 
     105        26571 :     if (newPos >= myPosition && oldPos < myPosition/* && static_cast<MSVehicle&>(veh).getLane() == myLane*/) {
     106        17466 :         const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
     107        17466 :         const double entryTime = SIMTIME - TS + timeBeforeEnter;
     108        17466 :         enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
     109        17466 :         if (myLastExitTime >= 0) {
     110        17122 :             write("enter", entryTime, veh, enterSpeed, "gap", entryTime - myLastExitTime);
     111              :         } else {
     112          344 :             write("enter", entryTime, veh, enterSpeed);
     113              :         }
     114        17466 :         myEntryTimes[&veh] = entryTime;
     115              :     }
     116        26571 :     const double newBackPos = newPos - veh.getVehicleType().getLength();
     117        26571 :     const double oldBackPos = oldPos - veh.getVehicleType().getLength();
     118        26571 :     if (newBackPos > myPosition) {
     119              :         std::map<SUMOTrafficObject*, double>::iterator i = myEntryTimes.find(&veh);
     120        17474 :         if (i != myEntryTimes.end()) {
     121              :             // vehicle passed the detector
     122        17474 :             const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, newBackPos, oldSpeed, newSpeed);
     123        17474 :             const double leaveTime = SIMTIME - TS + timeBeforeLeave;
     124        17474 :             write("leave", leaveTime, veh, newSpeed, "occupancy", leaveTime - (*i).second);
     125              :             myEntryTimes.erase(i);
     126        17474 :             myLastExitTime = leaveTime;
     127              :         }
     128              :         return false;
     129              :     }
     130              :     // vehicle stays on the detector
     131         9097 :     write("stay", SIMTIME, veh, newSpeed);
     132              :     return true;
     133              : }
     134              : 
     135              : 
     136              : void
     137        44051 : MSInstantInductLoop::write(const char* state, double t, SUMOTrafficObject& veh, double speed, const char* add, double addValue) {
     138        44051 :     if (!myOutputDevice.isNull()) {
     139        87982 :         myOutputDevice.openTag("instantOut").writeAttr(
     140        87982 :             "id", getID()).writeAttr("time", toString(t)).writeAttr("state", state).writeAttr(
     141       175964 :                 "vehID", veh.getID()).writeAttr("speed", toString(speed)).writeAttr(
     142       175964 :                     "length", toString(veh.getVehicleType().getLength())).writeAttr(
     143        43991 :                         "type", veh.getVehicleType().getID());
     144        43991 :         if (add != nullptr) {
     145        69128 :             myOutputDevice.writeAttr(add, toString(addValue));
     146              :         }
     147        87982 :         myOutputDevice.closeTag();
     148              :     }
     149        44051 : }
     150              : 
     151              : 
     152              : bool
     153         5597 : MSInstantInductLoop::notifyLeave(SUMOTrafficObject& veh, double /* lastPos */, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     154         5597 :     if (reason == MSMoveReminder::NOTIFICATION_JUNCTION) {
     155              :         // vehicle might have jumped over detector at the end of the lane. we need
     156              :         // one more notifyMove to register it
     157              :         return true;
     158              :     }
     159              :     std::map<SUMOTrafficObject*, double>::iterator i = myEntryTimes.find(&veh);
     160         1305 :     if (i != myEntryTimes.end()) {
     161            3 :         write("leave", SIMTIME, veh, veh.getSpeed());
     162              :         myEntryTimes.erase(i);
     163              :     }
     164              :     return false;
     165              : }
     166              : 
     167              : 
     168              : void
     169         1027 : MSInstantInductLoop::writeXMLDetectorProlog(OutputDevice& dev) const {
     170         2054 :     dev.writeXMLHeader("instantE1", "instant_e1_file.xsd");
     171         1027 : }
     172              : 
     173              : 
     174              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1