LCOV - code coverage report
Current view: top level - src/microsim/output - MSFCDExport.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 97.3 % 149 145
Test Date: 2024-11-20 15:55:46 Functions: 100.0 % 5 5

            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 <mesosim/MEVehicle.h>
      44              : #include "MSFCDExport.h"
      45              : 
      46              : 
      47              : // ===========================================================================
      48              : // method definitions
      49              : // ===========================================================================
      50              : void
      51       769585 : MSFCDExport::write(OutputDevice& of, SUMOTime timestep, bool elevation) {
      52       769585 :     const OptionsCont& oc = OptionsCont::getOptions();
      53       769585 :     const SUMOTime period = string2time(oc.getString("device.fcd.period"));
      54       769585 :     const SUMOTime begin = string2time(oc.getString("device.fcd.begin"));
      55       769585 :     if ((period > 0 && (timestep - begin) % period != 0) || timestep < begin) {
      56        56260 :         return;
      57              :     }
      58              :     const SumoXMLAttrMask mask = MSDevice_FCD::getWrittenAttributes();
      59       713325 :     const bool maskSet = oc.isSet("fcd-output.attributes");
      60       713325 :     const bool useGeo = oc.getBool("fcd-output.geo");
      61       799604 :     const bool signals = oc.getBool("fcd-output.signals") || (maskSet && of.useAttribute(SUMO_ATTR_SIGNALS, mask));
      62       798774 :     const bool writeAccel = oc.getBool("fcd-output.acceleration") || (maskSet && of.useAttribute(SUMO_ATTR_ACCELERATION, mask));
      63       799772 :     const bool writeDistance = oc.getBool("fcd-output.distance") || (maskSet && of.useAttribute(SUMO_ATTR_DISTANCE, mask));
      64       713325 :     const double maxLeaderDistance = oc.getFloat("fcd-output.max-leader-distance");
      65       713325 :     std::vector<std::string> params = oc.getStringVector("fcd-output.params");
      66       713325 :     MSNet* net = MSNet::getInstance();
      67              :     MSVehicleControl& vc = net->getVehicleControl();
      68      1426650 :     const double radius = oc.getFloat("device.fcd.radius");
      69       713325 :     const bool filter = MSDevice_FCD::getEdgeFilter().size() > 0;
      70              :     const bool shapeFilter = MSDevice_FCD::hasShapeFilter();
      71              :     std::set<const Named*> inRadius;
      72       713325 :     if (radius > 0) {
      73              :         // collect all vehicles in radius around equipped vehicles
      74         4152 :         for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
      75         2738 :             const SUMOVehicle* veh = it->second;
      76         2738 :             if (isVisible(veh) && hasOwnOutput(veh, filter, shapeFilter)) {
      77         1342 :                 PositionVector shape;
      78         1342 :                 shape.push_back(veh->getPosition());
      79         1342 :                 libsumo::Helper::collectObjectsInRange(libsumo::CMD_GET_VEHICLE_VARIABLE, shape, radius, inRadius);
      80         1342 :                 libsumo::Helper::collectObjectsInRange(libsumo::CMD_GET_PERSON_VARIABLE, shape, radius, inRadius);
      81         1342 :             }
      82              :         }
      83              :     }
      84              : 
      85      1426650 :     of.openTag("timestep").writeAttr(SUMO_ATTR_TIME, time2string(timestep));
      86      3069577 :     for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
      87      2356252 :         const SUMOVehicle* veh = it->second;
      88      2356252 :         const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(veh);
      89      2356252 :         const MSBaseVehicle* baseVeh = dynamic_cast<const MSBaseVehicle*>(veh);
      90      2356252 :         if (isVisible(veh)) {
      91      3043272 :             const bool hasOutput = hasOwnOutput(veh, filter, shapeFilter, (radius > 0 && inRadius.count(veh) > 0));
      92      1521636 :             if (hasOutput) {
      93       955610 :                 Position pos = veh->getPosition();
      94       955610 :                 if (useGeo) {
      95         2696 :                     of.setPrecision(gPrecisionGeo);
      96         2696 :                     GeoConvHelper::getFinal().cartesian2geo(pos);
      97              :                 }
      98       955610 :                 of.openTag(SUMO_TAG_VEHICLE);
      99              :                 of.writeAttr(SUMO_ATTR_ID, veh->getID());
     100       955610 :                 of.writeOptionalAttr(SUMO_ATTR_X, pos.x(), mask);
     101       955610 :                 of.writeOptionalAttr(SUMO_ATTR_Y, pos.y(), mask);
     102       955610 :                 of.setPrecision(gPrecision);
     103       955610 :                 if (elevation) {
     104        62507 :                     of.writeOptionalAttr(SUMO_ATTR_Z, pos.z(), mask);
     105              :                 }
     106       955610 :                 of.writeOptionalAttr(SUMO_ATTR_ANGLE, GeomHelper::naviDegree(veh->getAngle()), mask);
     107       955610 :                 of.writeOptionalAttr(SUMO_ATTR_TYPE, veh->getVehicleType().getID(), mask);
     108       955610 :                 of.writeOptionalAttr(SUMO_ATTR_SPEED, veh->getSpeed(), mask);
     109       955610 :                 of.writeOptionalAttr(SUMO_ATTR_POSITION, veh->getPositionOnLane(), mask);
     110       955610 :                 if (microVeh != nullptr) {
     111       899770 :                     of.writeOptionalAttr(SUMO_ATTR_LANE, microVeh->getLane()->getID(), mask);
     112              :                 } else {
     113        55840 :                     of.writeOptionalAttr(SUMO_ATTR_EDGE, veh->getEdge()->getID(), mask);
     114              :                 }
     115       955610 :                 of.writeOptionalAttr(SUMO_ATTR_SLOPE, veh->getSlope(), mask);
     116       955610 :                 if (microVeh != nullptr) {
     117       899770 :                     if (signals) {
     118        29614 :                         of.writeOptionalAttr(SUMO_ATTR_SIGNALS, toString(microVeh->getSignals()), mask);
     119              :                     }
     120       899770 :                     if (writeAccel) {
     121       137902 :                         of.writeOptionalAttr(SUMO_ATTR_ACCELERATION, toString(microVeh->getAcceleration()), mask);
     122       137902 :                         if (MSGlobals::gSublane) {
     123        43201 :                             of.writeOptionalAttr(SUMO_ATTR_ACCELERATION_LAT, microVeh->getLaneChangeModel().getAccelerationLat(), mask);
     124              :                         }
     125              :                     }
     126              :                 }
     127       955610 :                 if (writeDistance) {
     128         2134 :                     double lanePos = veh->getPositionOnLane();
     129         2134 :                     if (microVeh != nullptr && microVeh->getLane()->isInternal()) {
     130            4 :                         lanePos = microVeh->getRoute().getDistanceBetween(0., lanePos, microVeh->getEdge()->getLanes()[0], microVeh->getLane(),
     131            2 :                                   microVeh->getRoutePosition());
     132              :                     }
     133         2134 :                     of.writeOptionalAttr(SUMO_ATTR_DISTANCE, veh->getEdge()->getDistanceAt(lanePos), mask);
     134              :                 }
     135       955610 :                 of.writeOptionalAttr(SUMO_ATTR_ODOMETER, veh->getOdometer(), mask);
     136       955610 :                 of.writeOptionalAttr(SUMO_ATTR_POSITION_LAT, veh->getLateralPositionOnLane(), mask);
     137       955610 :                 if (microVeh != nullptr) {
     138       899770 :                     of.writeOptionalAttr(SUMO_ATTR_SPEED_LAT, microVeh->getLaneChangeModel().getSpeedLat(), mask);
     139              :                 }
     140       955610 :                 if (maxLeaderDistance >= 0 && microVeh != nullptr) {
     141        19203 :                     std::pair<const MSVehicle* const, double> leader = microVeh->getLeader(maxLeaderDistance);
     142        19203 :                     if (leader.first != nullptr) {
     143        13988 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_ID, toString(leader.first->getID()), mask);
     144        13988 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_SPEED, toString(leader.first->getSpeed()), mask);
     145        27976 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_GAP, toString(leader.second + microVeh->getVehicleType().getMinGap()), mask);
     146              :                     } else {
     147         5215 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_ID, "", mask);
     148         5215 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_SPEED, -1, mask);
     149         5215 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_GAP, -1, mask);
     150              :                     }
     151              :                 }
     152       974749 :                 for (const std::string& key : params) {
     153              :                     std::string error;
     154        19139 :                     const std::string value = baseVeh->getPrefixedParameter(key, error);
     155        19139 :                     if (value != "") {
     156        28656 :                         of.writeAttr(StringUtils::escapeXML(key), StringUtils::escapeXML(value));
     157              :                     }
     158              :                 }
     159       955610 :                 if (of.useAttribute(SUMO_ATTR_ARRIVALDELAY, mask)) {
     160         5258 :                     double arrivalDelay = baseVeh->getStopArrivalDelay();
     161         5258 :                     if (arrivalDelay == INVALID_DOUBLE) {
     162              :                         // no upcoming stop also means that there is no delay
     163         2378 :                         arrivalDelay = 0;
     164              :                     }
     165         5258 :                     of.writeOptionalAttr(SUMO_ATTR_ARRIVALDELAY, arrivalDelay, mask);
     166              :                 }
     167       955610 :                 if (MSGlobals::gUseMesoSim) {
     168        55840 :                     const MEVehicle* mesoVeh = dynamic_cast<const MEVehicle*>(veh);
     169        55840 :                     of.writeOptionalAttr(SUMO_ATTR_SEGMENT, mesoVeh->getSegmentIndex(), mask);
     170        55840 :                     of.writeOptionalAttr(SUMO_ATTR_QUEUE, mesoVeh->getQueIndex(), mask);
     171        55840 :                     of.writeOptionalAttr(SUMO_ATTR_ENTRYTIME, mesoVeh->getLastEntryTimeSeconds(), mask);
     172        55840 :                     of.writeOptionalAttr(SUMO_ATTR_EVENTTIME, mesoVeh->getEventTimeSeconds(), mask);
     173        58564 :                     of.writeOptionalAttr(SUMO_ATTR_BLOCKTIME, mesoVeh->getBlockTime() == SUMOTime_MAX ? -1.0 : mesoVeh->getBlockTimeSeconds(), mask);
     174              :                 }
     175      1911220 :                 of.closeTag();
     176              :             }
     177              :             // write persons and containers
     178      1521636 :             const MSEdge* edge = microVeh == nullptr ? veh->getEdge() : &veh->getLane()->getEdge();
     179              : 
     180      1521636 :             const std::vector<MSTransportable*>& persons = veh->getPersons();
     181      1566273 :             for (MSTransportable* person : persons) {
     182        89274 :                 writeTransportable(of, edge, person, veh, filter, shapeFilter, inRadius.count(person) > 0, SUMO_TAG_PERSON, useGeo, elevation, mask);
     183              :             }
     184      1521636 :             const std::vector<MSTransportable*>& containers = veh->getContainers();
     185      1524206 :             for (MSTransportable* container : containers) {
     186         5140 :                 writeTransportable(of, edge, container, veh, filter, shapeFilter, inRadius.count(container) > 0, SUMO_TAG_CONTAINER, useGeo, elevation, mask);
     187              :             }
     188              :         }
     189              :     }
     190       713325 :     if (net->hasPersons() && net->getPersonControl().hasTransportables()) {
     191              :         // write persons
     192              :         MSEdgeControl& ec = net->getEdgeControl();
     193              :         const MSEdgeVector& edges = ec.getEdges();
     194      2225058 :         for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
     195      2178037 :             if (filter && MSDevice_FCD::getEdgeFilter().count(*e) == 0) {
     196          104 :                 continue;
     197              :             }
     198      2177933 :             const std::vector<MSTransportable*>& persons = (*e)->getSortedPersons(timestep);
     199      2377198 :             for (MSTransportable* person : persons) {
     200       398530 :                 writeTransportable(of, *e, person, nullptr, filter, shapeFilter, inRadius.count(person) > 0, SUMO_TAG_PERSON, useGeo, elevation, mask);
     201              :             }
     202      2177933 :         }
     203              :     }
     204       713325 :     if (net->hasContainers() && net->getContainerControl().hasTransportables()) {
     205              :         // write containers
     206              :         MSEdgeControl& ec = net->getEdgeControl();
     207              :         const std::vector<MSEdge*>& edges = ec.getEdges();
     208        30800 :         for (std::vector<MSEdge*>::const_iterator e = edges.begin(); e != edges.end(); ++e) {
     209        28000 :             if (filter && MSDevice_FCD::getEdgeFilter().count(*e) == 0) {
     210            0 :                 continue;
     211              :             }
     212        28000 :             const std::vector<MSTransportable*>& containers = (*e)->getSortedContainers(timestep);
     213        31416 :             for (MSTransportable* container : containers) {
     214         6832 :                 writeTransportable(of, *e, container, nullptr, filter, shapeFilter, inRadius.count(container) > 0, SUMO_TAG_CONTAINER, useGeo, elevation, mask);
     215              :             }
     216        28000 :         }
     217              :     }
     218      1426650 :     of.closeTag();
     219       713325 : }
     220              : 
     221              : bool
     222      2358990 : MSFCDExport::isVisible(const SUMOVehicle* veh) {
     223      2358990 :     return veh->isOnRoad() || veh->isParking() || veh->isRemoteControlled();
     224              : }
     225              : 
     226              : bool
     227      1524344 : MSFCDExport::hasOwnOutput(const SUMOVehicle* veh, bool filter, bool shapeFilter, bool isInRadius) {
     228           52 :     return ((!filter || MSDevice_FCD::getEdgeFilter().count(veh->getEdge()) > 0)
     229      1524320 :             && (!shapeFilter || MSDevice_FCD::shapeFilter(veh))
     230      3046478 :             && ((veh->getDevice(typeid(MSDevice_FCD)) != nullptr) || isInRadius));
     231              : }
     232              : 
     233              : bool
     234       249888 : MSFCDExport::hasOwnOutput(const MSTransportable* p, bool filter, bool shapeFilter, bool isInRadius) {
     235           52 :     return ((!filter || MSDevice_FCD::getEdgeFilter().count(p->getEdge()) > 0)
     236       249860 :             && (!shapeFilter || MSDevice_FCD::shapeFilter(p))
     237       499748 :             && ((p->getDevice(typeid(MSTransportableDevice_FCD)) != nullptr) || isInRadius));
     238              : }
     239              : 
     240              : void
     241       249888 : MSFCDExport::writeTransportable(OutputDevice& of, const MSEdge* e, MSTransportable* p, const SUMOVehicle* v,
     242              :                                 bool filter, bool shapeFilter, bool inRadius,
     243              :                                 SumoXMLTag tag, bool useGeo, bool elevation, SumoXMLAttrMask mask) {
     244       249888 :     if (!hasOwnOutput(p, filter, shapeFilter, inRadius)) {
     245         1134 :         return;
     246              :     }
     247       248754 :     Position pos = p->getPosition();
     248       248754 :     if (useGeo) {
     249            0 :         of.setPrecision(gPrecisionGeo);
     250            0 :         GeoConvHelper::getFinal().cartesian2geo(pos);
     251              :     }
     252       248754 :     of.openTag(tag);
     253              :     of.writeAttr(SUMO_ATTR_ID, p->getID());
     254       248754 :     of.writeOptionalAttr(SUMO_ATTR_X, pos.x(), mask);
     255       248754 :     of.writeOptionalAttr(SUMO_ATTR_Y, pos.y(), mask);
     256       248754 :     if (elevation) {
     257            0 :         of.writeOptionalAttr(SUMO_ATTR_Z, pos.z(), mask);
     258              :     }
     259       248754 :     of.writeOptionalAttr(SUMO_ATTR_ANGLE, GeomHelper::naviDegree(p->getAngle()), mask);
     260       248754 :     of.writeOptionalAttr(SUMO_ATTR_SPEED, p->getSpeed(), mask);
     261       248754 :     of.writeOptionalAttr(SUMO_ATTR_POSITION, p->getEdgePos(), mask);
     262       248754 :     of.writeOptionalAttr(SUMO_ATTR_EDGE, e->getID(), mask);
     263       248754 :     of.writeOptionalAttr(SUMO_ATTR_SLOPE, e->getLanes()[0]->getShape().slopeDegreeAtOffset(p->getEdgePos()), mask);
     264       295399 :     of.writeOptionalAttr(SUMO_ATTR_VEHICLE, v == nullptr ? "" : v->getID(), mask);
     265       248754 :     of.writeOptionalAttr(SUMO_ATTR_TYPE, p->getVehicleType().getID(), mask);
     266       497508 :     of.closeTag();
     267              : }
     268              : 
     269              : 
     270              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1