LCOV - code coverage report
Current view: top level - src/microsim/output - MSFCDExport.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 135 139 97.1 %
Date: 2024-05-06 15:32:35 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2012-2024 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    MSFCDExport.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Mario Krumnow
      18             : /// @author  Michael Behrisch
      19             : /// @date    2012-04-26
      20             : ///
      21             : // Realises dumping Floating Car Data (FCD) Data
      22             : /****************************************************************************/
      23             : #include <config.h>
      24             : 
      25             : #include <utils/iodevices/OutputDevice.h>
      26             : #include <utils/options/OptionsCont.h>
      27             : #include <utils/geom/GeoConvHelper.h>
      28             : #include <utils/geom/GeomHelper.h>
      29             : #include <utils/shapes/SUMOPolygon.h>
      30             : #include <libsumo/Helper.h>
      31             : #include <microsim/devices/MSDevice_FCD.h>
      32             : #include <microsim/devices/MSTransportableDevice_FCD.h>
      33             : #include <microsim/MSEdgeControl.h>
      34             : #include <microsim/MSEdge.h>
      35             : #include <microsim/MSLane.h>
      36             : #include <microsim/MSGlobals.h>
      37             : #include <microsim/MSNet.h>
      38             : #include <microsim/MSVehicle.h>
      39             : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
      40             : #include <microsim/transportables/MSPerson.h>
      41             : #include <microsim/transportables/MSTransportableControl.h>
      42             : #include <microsim/MSVehicleControl.h>
      43             : #include "MSFCDExport.h"
      44             : 
      45             : 
      46             : // ===========================================================================
      47             : // method definitions
      48             : // ===========================================================================
      49             : void
      50      737908 : MSFCDExport::write(OutputDevice& of, SUMOTime timestep, bool elevation) {
      51      737908 :     const OptionsCont& oc = OptionsCont::getOptions();
      52     1475816 :     const SUMOTime period = string2time(oc.getString("device.fcd.period"));
      53     1475816 :     const SUMOTime begin = string2time(oc.getString("device.fcd.begin"));
      54      737908 :     if ((period > 0 && (timestep - begin) % period != 0) || timestep < begin) {
      55       14108 :         return;
      56             :     }
      57             :     const SumoXMLAttrMask mask = MSDevice_FCD::getWrittenAttributes();
      58      723800 :     const bool maskSet = oc.isSet("fcd-output.attributes");
      59      723800 :     const bool useGeo = oc.getBool("fcd-output.geo");
      60      809211 :     const bool signals = oc.getBool("fcd-output.signals") || (maskSet && of.useAttribute(SUMO_ATTR_SIGNALS, mask));
      61      808381 :     const bool writeAccel = oc.getBool("fcd-output.acceleration") || (maskSet && of.useAttribute(SUMO_ATTR_ACCELERATION, mask));
      62      809379 :     const bool writeDistance = oc.getBool("fcd-output.distance") || (maskSet && of.useAttribute(SUMO_ATTR_DISTANCE, mask));
      63      723800 :     const double maxLeaderDistance = oc.getFloat("fcd-output.max-leader-distance");
      64      723800 :     std::vector<std::string> params = oc.getStringVector("fcd-output.params");
      65      723800 :     MSNet* net = MSNet::getInstance();
      66             :     MSVehicleControl& vc = net->getVehicleControl();
      67     1447600 :     const double radius = oc.getFloat("device.fcd.radius");
      68      723800 :     const bool filter = MSDevice_FCD::getEdgeFilter().size() > 0;
      69             :     const bool shapeFilter = MSDevice_FCD::hasShapeFilter();
      70             :     std::set<const Named*> inRadius;
      71      723800 :     if (radius > 0) {
      72             :         // collect all vehicles in radius around equipped vehicles
      73        4152 :         for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
      74        2738 :             const SUMOVehicle* veh = it->second;
      75        2738 :             if (isVisible(veh) && hasOwnOutput(veh, filter, shapeFilter)) {
      76        1342 :                 PositionVector shape;
      77        1342 :                 shape.push_back(veh->getPosition());
      78        1342 :                 libsumo::Helper::collectObjectsInRange(libsumo::CMD_GET_VEHICLE_VARIABLE, shape, radius, inRadius);
      79        1342 :                 libsumo::Helper::collectObjectsInRange(libsumo::CMD_GET_PERSON_VARIABLE, shape, radius, inRadius);
      80        1342 :             }
      81             :         }
      82             :     }
      83             : 
      84     1447600 :     of.openTag("timestep").writeAttr(SUMO_ATTR_TIME, time2string(timestep));
      85     3084535 :     for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
      86     2360735 :         const SUMOVehicle* veh = it->second;
      87     2360735 :         const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(veh);
      88     2360735 :         const MSBaseVehicle* baseVeh = dynamic_cast<const MSBaseVehicle*>(veh);
      89     2360735 :         if (isVisible(veh)) {
      90     1528479 :             const bool hasOutput = hasOwnOutput(veh, filter, shapeFilter, (radius > 0 && inRadius.count(veh) > 0));
      91     1525771 :             if (hasOutput) {
      92      963455 :                 Position pos = veh->getPosition();
      93      963455 :                 if (useGeo) {
      94        2696 :                     of.setPrecision(gPrecisionGeo);
      95        2696 :                     GeoConvHelper::getFinal().cartesian2geo(pos);
      96             :                 }
      97      963455 :                 of.openTag(SUMO_TAG_VEHICLE);
      98             :                 of.writeAttr(SUMO_ATTR_ID, veh->getID());
      99      963455 :                 of.writeOptionalAttr(SUMO_ATTR_X, pos.x(), mask);
     100      963455 :                 of.writeOptionalAttr(SUMO_ATTR_Y, pos.y(), mask);
     101      963455 :                 of.setPrecision(gPrecision);
     102      963455 :                 if (elevation) {
     103       62077 :                     of.writeOptionalAttr(SUMO_ATTR_Z, pos.z(), mask);
     104             :                 }
     105      963455 :                 of.writeOptionalAttr(SUMO_ATTR_ANGLE, GeomHelper::naviDegree(veh->getAngle()), mask);
     106      963455 :                 of.writeOptionalAttr(SUMO_ATTR_TYPE, veh->getVehicleType().getID(), mask);
     107      963455 :                 of.writeOptionalAttr(SUMO_ATTR_SPEED, veh->getSpeed(), mask);
     108      963455 :                 of.writeOptionalAttr(SUMO_ATTR_POSITION, veh->getPositionOnLane(), mask);
     109      963455 :                 if (microVeh != nullptr) {
     110      914041 :                     of.writeOptionalAttr(SUMO_ATTR_LANE, microVeh->getLane()->getID(), mask);
     111             :                 } else {
     112       49414 :                     of.writeOptionalAttr(SUMO_ATTR_EDGE, veh->getEdge()->getID(), mask);
     113             :                 }
     114      963455 :                 of.writeOptionalAttr(SUMO_ATTR_SLOPE, veh->getSlope(), mask);
     115      963455 :                 if (microVeh != nullptr) {
     116      914041 :                     if (signals) {
     117       28864 :                         of.writeOptionalAttr(SUMO_ATTR_SIGNALS, toString(microVeh->getSignals()), mask);
     118             :                     }
     119      914041 :                     if (writeAccel) {
     120      139303 :                         of.writeOptionalAttr(SUMO_ATTR_ACCELERATION, toString(microVeh->getAcceleration()), mask);
     121      139303 :                         if (MSGlobals::gSublane) {
     122       43154 :                             of.writeOptionalAttr(SUMO_ATTR_ACCELERATION_LAT, microVeh->getLaneChangeModel().getAccelerationLat(), mask);
     123             :                         }
     124             :                     }
     125             :                 }
     126      963455 :                 if (writeDistance) {
     127        2134 :                     double lanePos = veh->getPositionOnLane();
     128        2134 :                     if (microVeh != nullptr && microVeh->getLane()->isInternal()) {
     129           4 :                         lanePos = microVeh->getRoute().getDistanceBetween(0., lanePos, microVeh->getEdge()->getLanes()[0], microVeh->getLane(),
     130           2 :                                   microVeh->getRoutePosition());
     131             :                     }
     132        2134 :                     of.writeOptionalAttr(SUMO_ATTR_DISTANCE, veh->getEdge()->getDistanceAt(lanePos), mask);
     133             :                 }
     134      963455 :                 of.writeOptionalAttr(SUMO_ATTR_ODOMETER, veh->getOdometer(), mask);
     135      963455 :                 of.writeOptionalAttr(SUMO_ATTR_POSITION_LAT, veh->getLateralPositionOnLane(), mask);
     136      963455 :                 if (microVeh != nullptr) {
     137      914041 :                     of.writeOptionalAttr(SUMO_ATTR_SPEED_LAT, microVeh->getLaneChangeModel().getSpeedLat(), mask);
     138             :                 }
     139      963455 :                 if (maxLeaderDistance >= 0 && microVeh != nullptr) {
     140       25434 :                     std::pair<const MSVehicle* const, double> leader = microVeh->getLeader(maxLeaderDistance);
     141       25434 :                     if (leader.first != nullptr) {
     142       18650 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_ID, toString(leader.first->getID()), mask);
     143       18650 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_SPEED, toString(leader.first->getSpeed()), mask);
     144       37300 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_GAP, toString(leader.second + microVeh->getVehicleType().getMinGap()), mask);
     145             :                     } else {
     146        6784 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_ID, "", mask);
     147        6784 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_SPEED, -1, mask);
     148        6784 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_GAP, -1, mask);
     149             :                     }
     150             :                 }
     151      974700 :                 for (const std::string& key : params) {
     152             :                     std::string error;
     153       11245 :                     const std::string value = baseVeh->getPrefixedParameter(key, error);
     154       11245 :                     if (value != "") {
     155       12876 :                         of.writeAttr(StringUtils::escapeXML(key), StringUtils::escapeXML(value));
     156             :                     }
     157             :                 }
     158      963455 :                 if (of.useAttribute(SUMO_ATTR_ARRIVALDELAY, mask)) {
     159        5258 :                     double arrivalDelay = baseVeh->getStopArrivalDelay();
     160        5258 :                     if (arrivalDelay == INVALID_DOUBLE) {
     161             :                         // no upcoming stop also means that there is no delay
     162        2378 :                         arrivalDelay = 0;
     163             :                     }
     164        5258 :                     of.writeOptionalAttr(SUMO_ATTR_ARRIVALDELAY, arrivalDelay, mask);
     165             :                 }
     166     1926910 :                 of.closeTag();
     167             :             }
     168             :             // write persons and containers
     169     1525771 :             const MSEdge* edge = microVeh == nullptr ? veh->getEdge() : &veh->getLane()->getEdge();
     170             : 
     171     1525771 :             const std::vector<MSTransportable*>& persons = veh->getPersons();
     172     1567004 :             for (MSTransportable* person : persons) {
     173       82466 :                 writeTransportable(of, edge, person, veh, filter, shapeFilter, inRadius.count(person) > 0, SUMO_TAG_PERSON, useGeo, elevation, mask);
     174             :             }
     175     1525771 :             const std::vector<MSTransportable*>& containers = veh->getContainers();
     176     1528341 :             for (MSTransportable* container : containers) {
     177        5140 :                 writeTransportable(of, edge, container, veh, filter, shapeFilter, inRadius.count(container) > 0, SUMO_TAG_CONTAINER, useGeo, elevation, mask);
     178             :             }
     179             :         }
     180             :     }
     181      723800 :     if (net->hasPersons() && net->getPersonControl().hasTransportables()) {
     182             :         // write persons
     183             :         MSEdgeControl& ec = net->getEdgeControl();
     184             :         const MSEdgeVector& edges = ec.getEdges();
     185     2045880 :         for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
     186     1999204 :             if (filter && MSDevice_FCD::getEdgeFilter().count(*e) == 0) {
     187         104 :                 continue;
     188             :             }
     189     1999100 :             const std::vector<MSTransportable*>& persons = (*e)->getSortedPersons(timestep);
     190     2201374 :             for (MSTransportable* person : persons) {
     191      404548 :                 writeTransportable(of, *e, person, nullptr, filter, shapeFilter, inRadius.count(person) > 0, SUMO_TAG_PERSON, useGeo, elevation, mask);
     192             :             }
     193             :         }
     194             :     }
     195      723800 :     if (net->hasContainers() && net->getContainerControl().hasTransportables()) {
     196             :         // write containers
     197             :         MSEdgeControl& ec = net->getEdgeControl();
     198             :         const std::vector<MSEdge*>& edges = ec.getEdges();
     199       30800 :         for (std::vector<MSEdge*>::const_iterator e = edges.begin(); e != edges.end(); ++e) {
     200       28000 :             if (filter && MSDevice_FCD::getEdgeFilter().count(*e) == 0) {
     201           0 :                 continue;
     202             :             }
     203       28000 :             const std::vector<MSTransportable*>& containers = (*e)->getSortedContainers(timestep);
     204       31416 :             for (MSTransportable* container : containers) {
     205        6832 :                 writeTransportable(of, *e, container, nullptr, filter, shapeFilter, inRadius.count(container) > 0, SUMO_TAG_CONTAINER, useGeo, elevation, mask);
     206             :             }
     207             :         }
     208             :     }
     209     1447600 :     of.closeTag();
     210      723800 : }
     211             : 
     212             : bool
     213     2363473 : MSFCDExport::isVisible(const SUMOVehicle* veh) {
     214     2363473 :     return veh->isOnRoad() || veh->isParking() || veh->isRemoteControlled();
     215             : }
     216             : 
     217             : bool
     218     1528479 : MSFCDExport::hasOwnOutput(const SUMOVehicle* veh, bool filter, bool shapeFilter, bool isInRadius) {
     219          52 :     return ((!filter || MSDevice_FCD::getEdgeFilter().count(veh->getEdge()) > 0)
     220     1528455 :             && (!shapeFilter || MSDevice_FCD::shapeFilter(veh))
     221     3054748 :             && ((veh->getDevice(typeid(MSDevice_FCD)) != nullptr) || isInRadius));
     222             : }
     223             : 
     224             : bool
     225      249493 : MSFCDExport::hasOwnOutput(const MSTransportable* p, bool filter, bool shapeFilter, bool isInRadius) {
     226          52 :     return ((!filter || MSDevice_FCD::getEdgeFilter().count(p->getEdge()) > 0)
     227      249465 :             && (!shapeFilter || MSDevice_FCD::shapeFilter(p))
     228      498958 :             && ((p->getDevice(typeid(MSTransportableDevice_FCD)) != nullptr) || isInRadius));
     229             : }
     230             : 
     231             : void
     232      249493 : MSFCDExport::writeTransportable(OutputDevice& of, const MSEdge* e, MSTransportable* p, const SUMOVehicle* v,
     233             :                                 bool filter, bool shapeFilter, bool inRadius,
     234             :                                 SumoXMLTag tag, bool useGeo, bool elevation, SumoXMLAttrMask mask) {
     235      249493 :     if (!hasOwnOutput(p, filter, shapeFilter, inRadius)) {
     236         128 :         return;
     237             :     }
     238      249365 :     Position pos = p->getPosition();
     239      249365 :     if (useGeo) {
     240           0 :         of.setPrecision(gPrecisionGeo);
     241           0 :         GeoConvHelper::getFinal().cartesian2geo(pos);
     242             :     }
     243      249365 :     of.openTag(tag);
     244             :     of.writeAttr(SUMO_ATTR_ID, p->getID());
     245      249365 :     of.writeOptionalAttr(SUMO_ATTR_X, pos.x(), mask);
     246      249365 :     of.writeOptionalAttr(SUMO_ATTR_Y, pos.y(), mask);
     247      249365 :     if (elevation) {
     248           0 :         of.writeOptionalAttr(SUMO_ATTR_Z, pos.z(), mask);
     249             :     }
     250      249365 :     of.writeOptionalAttr(SUMO_ATTR_ANGLE, GeomHelper::naviDegree(p->getAngle()), mask);
     251      249365 :     of.writeOptionalAttr(SUMO_ATTR_SPEED, p->getSpeed(), mask);
     252      249365 :     of.writeOptionalAttr(SUMO_ATTR_POSITION, p->getEdgePos(), mask);
     253      249365 :     of.writeOptionalAttr(SUMO_ATTR_EDGE, e->getID(), mask);
     254      249365 :     of.writeOptionalAttr(SUMO_ATTR_SLOPE, e->getLanes()[0]->getShape().slopeDegreeAtOffset(p->getEdgePos()), mask);
     255      293124 :     of.writeOptionalAttr(SUMO_ATTR_VEHICLE, v == nullptr ? "" : v->getID(), mask);
     256      498730 :     of.closeTag();
     257             : }
     258             : 
     259             : 
     260             : /****************************************************************************/

Generated by: LCOV version 1.14