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-12-21 15:45:41 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       773789 : MSFCDExport::write(OutputDevice& of, SUMOTime timestep, bool elevation) {
      52       773789 :     const OptionsCont& oc = OptionsCont::getOptions();
      53       773789 :     const SUMOTime period = string2time(oc.getString("device.fcd.period"));
      54       773789 :     const SUMOTime begin = string2time(oc.getString("device.fcd.begin"));
      55       773789 :     if ((period > 0 && (timestep - begin) % period != 0) || timestep < begin) {
      56        56260 :         return;
      57              :     }
      58              :     const SumoXMLAttrMask mask = MSDevice_FCD::getWrittenAttributes();
      59       717529 :     const bool maskSet = oc.isSet("fcd-output.attributes");
      60       717529 :     const bool useGeo = oc.getBool("fcd-output.geo");
      61       803978 :     const bool signals = oc.getBool("fcd-output.signals") || (maskSet && of.useAttribute(SUMO_ATTR_SIGNALS, mask));
      62       803148 :     const bool writeAccel = oc.getBool("fcd-output.acceleration") || (maskSet && of.useAttribute(SUMO_ATTR_ACCELERATION, mask));
      63       804146 :     const bool writeDistance = oc.getBool("fcd-output.distance") || (maskSet && of.useAttribute(SUMO_ATTR_DISTANCE, mask));
      64       717529 :     const double maxLeaderDistance = oc.getFloat("fcd-output.max-leader-distance");
      65       717529 :     std::vector<std::string> params = oc.getStringVector("fcd-output.params");
      66       717529 :     MSNet* net = MSNet::getInstance();
      67              :     MSVehicleControl& vc = net->getVehicleControl();
      68      1435058 :     const double radius = oc.getFloat("device.fcd.radius");
      69       717529 :     const bool filter = MSDevice_FCD::getEdgeFilter().size() > 0;
      70              :     const bool shapeFilter = MSDevice_FCD::hasShapeFilter();
      71              :     std::set<const Named*> inRadius;
      72       717529 :     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      1435058 :     of.openTag("timestep").writeAttr(SUMO_ATTR_TIME, time2string(timestep));
      86      3091059 :     for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
      87      2373530 :         const SUMOVehicle* veh = it->second;
      88      2373530 :         const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(veh);
      89      2373530 :         const MSBaseVehicle* baseVeh = dynamic_cast<const MSBaseVehicle*>(veh);
      90      2373530 :         if (isVisible(veh)) {
      91      3074876 :             const bool hasOutput = hasOwnOutput(veh, filter, shapeFilter, (radius > 0 && inRadius.count(veh) > 0));
      92      1537438 :             if (hasOutput) {
      93       969312 :                 Position pos = veh->getPosition();
      94       969312 :                 if (useGeo) {
      95         2696 :                     of.setPrecision(gPrecisionGeo);
      96         2696 :                     GeoConvHelper::getFinal().cartesian2geo(pos);
      97              :                 }
      98       969312 :                 of.openTag(SUMO_TAG_VEHICLE);
      99              :                 of.writeAttr(SUMO_ATTR_ID, veh->getID());
     100       969312 :                 of.writeOptionalAttr(SUMO_ATTR_X, pos.x(), mask);
     101       969312 :                 of.writeOptionalAttr(SUMO_ATTR_Y, pos.y(), mask);
     102       969312 :                 of.setPrecision(gPrecision);
     103       969312 :                 if (elevation) {
     104        62507 :                     of.writeOptionalAttr(SUMO_ATTR_Z, pos.z(), mask);
     105              :                 }
     106       969312 :                 of.writeOptionalAttr(SUMO_ATTR_ANGLE, GeomHelper::naviDegree(veh->getAngle()), mask);
     107       969312 :                 of.writeOptionalAttr(SUMO_ATTR_TYPE, veh->getVehicleType().getID(), mask);
     108       969312 :                 of.writeOptionalAttr(SUMO_ATTR_SPEED, veh->getSpeed(), mask);
     109       969312 :                 of.writeOptionalAttr(SUMO_ATTR_POSITION, veh->getPositionOnLane(), mask);
     110       969312 :                 if (microVeh != nullptr) {
     111       912894 :                     of.writeOptionalAttr(SUMO_ATTR_LANE, microVeh->getLane()->getID(), mask);
     112              :                 } else {
     113        56418 :                     of.writeOptionalAttr(SUMO_ATTR_EDGE, veh->getEdge()->getID(), mask);
     114              :                 }
     115       969312 :                 of.writeOptionalAttr(SUMO_ATTR_SLOPE, veh->getSlope(), mask);
     116       969312 :                 if (microVeh != nullptr) {
     117       912894 :                     if (signals) {
     118        29614 :                         of.writeOptionalAttr(SUMO_ATTR_SIGNALS, toString(microVeh->getSignals()), mask);
     119              :                     }
     120       912894 :                     if (writeAccel) {
     121       149325 :                         of.writeOptionalAttr(SUMO_ATTR_ACCELERATION, toString(microVeh->getAcceleration()), mask);
     122       149325 :                         if (MSGlobals::gSublane) {
     123        54588 :                             of.writeOptionalAttr(SUMO_ATTR_ACCELERATION_LAT, microVeh->getLaneChangeModel().getAccelerationLat(), mask);
     124              :                         }
     125              :                     }
     126              :                 }
     127       969312 :                 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       969312 :                 of.writeOptionalAttr(SUMO_ATTR_ODOMETER, veh->getOdometer(), mask);
     136       969312 :                 of.writeOptionalAttr(SUMO_ATTR_POSITION_LAT, veh->getLateralPositionOnLane(), mask);
     137       969312 :                 if (microVeh != nullptr) {
     138       912894 :                     of.writeOptionalAttr(SUMO_ATTR_SPEED_LAT, microVeh->getLaneChangeModel().getSpeedLat(), mask);
     139              :                 }
     140       969312 :                 if (maxLeaderDistance >= 0 && microVeh != nullptr) {
     141        20345 :                     std::pair<const MSVehicle* const, double> leader = microVeh->getLeader(maxLeaderDistance);
     142        20345 :                     if (leader.first != nullptr) {
     143        14819 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_ID, toString(leader.first->getID()), mask);
     144        14819 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_SPEED, toString(leader.first->getSpeed()), mask);
     145        29638 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_GAP, toString(leader.second + microVeh->getVehicleType().getMinGap()), mask);
     146              :                     } else {
     147         5526 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_ID, "", mask);
     148         5526 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_SPEED, -1, mask);
     149         5526 :                         of.writeOptionalAttr(SUMO_ATTR_LEADER_GAP, -1, mask);
     150              :                     }
     151              :                 }
     152       988451 :                 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       969312 :                 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       969312 :                 if (MSGlobals::gUseMesoSim) {
     168        56418 :                     const MEVehicle* mesoVeh = dynamic_cast<const MEVehicle*>(veh);
     169        56418 :                     of.writeOptionalAttr(SUMO_ATTR_SEGMENT, mesoVeh->getSegmentIndex(), mask);
     170        56418 :                     of.writeOptionalAttr(SUMO_ATTR_QUEUE, mesoVeh->getQueIndex(), mask);
     171        56418 :                     of.writeOptionalAttr(SUMO_ATTR_ENTRYTIME, mesoVeh->getLastEntryTimeSeconds(), mask);
     172        56418 :                     of.writeOptionalAttr(SUMO_ATTR_EVENTTIME, mesoVeh->getEventTimeSeconds(), mask);
     173        59744 :                     of.writeOptionalAttr(SUMO_ATTR_BLOCKTIME, mesoVeh->getBlockTime() == SUMOTime_MAX ? -1.0 : mesoVeh->getBlockTimeSeconds(), mask);
     174              :                 }
     175      1938624 :                 of.closeTag();
     176              :             }
     177              :             // write persons and containers
     178      1537438 :             const MSEdge* edge = microVeh == nullptr ? veh->getEdge() : &veh->getLane()->getEdge();
     179              : 
     180      1537438 :             const std::vector<MSTransportable*>& persons = veh->getPersons();
     181      1582075 :             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      1537438 :             const std::vector<MSTransportable*>& containers = veh->getContainers();
     185      1540008 :             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       717529 :     if (net->hasPersons() && net->getPersonControl().hasTransportables()) {
     191              :         // write persons
     192              :         MSEdgeControl& ec = net->getEdgeControl();
     193              :         const MSEdgeVector& edges = ec.getEdges();
     194      2249777 :         for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
     195      2202185 :             if (filter && MSDevice_FCD::getEdgeFilter().count(*e) == 0) {
     196          104 :                 continue;
     197              :             }
     198      2202081 :             const std::vector<MSTransportable*>& persons = (*e)->getSortedPersons(timestep);
     199      2401899 :             for (MSTransportable* person : persons) {
     200       399636 :                 writeTransportable(of, *e, person, nullptr, filter, shapeFilter, inRadius.count(person) > 0, SUMO_TAG_PERSON, useGeo, elevation, mask);
     201              :             }
     202      2202081 :         }
     203              :     }
     204       717529 :     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      1435058 :     of.closeTag();
     219       717529 : }
     220              : 
     221              : bool
     222      2376268 : MSFCDExport::isVisible(const SUMOVehicle* veh) {
     223      2376268 :     return veh->isOnRoad() || veh->isParking() || veh->isRemoteControlled();
     224              : }
     225              : 
     226              : bool
     227      1540146 : MSFCDExport::hasOwnOutput(const SUMOVehicle* veh, bool filter, bool shapeFilter, bool isInRadius) {
     228           52 :     return ((!filter || MSDevice_FCD::getEdgeFilter().count(veh->getEdge()) > 0)
     229      1540122 :             && (!shapeFilter || MSDevice_FCD::shapeFilter(veh))
     230      3078082 :             && ((veh->getDevice(typeid(MSDevice_FCD)) != nullptr) || isInRadius));
     231              : }
     232              : 
     233              : bool
     234       250441 : MSFCDExport::hasOwnOutput(const MSTransportable* p, bool filter, bool shapeFilter, bool isInRadius) {
     235           52 :     return ((!filter || MSDevice_FCD::getEdgeFilter().count(p->getEdge()) > 0)
     236       250413 :             && (!shapeFilter || MSDevice_FCD::shapeFilter(p))
     237       500854 :             && ((p->getDevice(typeid(MSTransportableDevice_FCD)) != nullptr) || isInRadius));
     238              : }
     239              : 
     240              : void
     241       250441 : 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       250441 :     if (!hasOwnOutput(p, filter, shapeFilter, inRadius)) {
     245         1280 :         return;
     246              :     }
     247       249161 :     Position pos = p->getPosition();
     248       249161 :     if (useGeo) {
     249            0 :         of.setPrecision(gPrecisionGeo);
     250            0 :         GeoConvHelper::getFinal().cartesian2geo(pos);
     251              :     }
     252       249161 :     of.openTag(tag);
     253              :     of.writeAttr(SUMO_ATTR_ID, p->getID());
     254       249161 :     of.writeOptionalAttr(SUMO_ATTR_X, pos.x(), mask);
     255       249161 :     of.writeOptionalAttr(SUMO_ATTR_Y, pos.y(), mask);
     256       249161 :     if (elevation) {
     257            0 :         of.writeOptionalAttr(SUMO_ATTR_Z, pos.z(), mask);
     258              :     }
     259       249161 :     of.writeOptionalAttr(SUMO_ATTR_ANGLE, GeomHelper::naviDegree(p->getAngle()), mask);
     260       249161 :     of.writeOptionalAttr(SUMO_ATTR_SPEED, p->getSpeed(), mask);
     261       249161 :     of.writeOptionalAttr(SUMO_ATTR_POSITION, p->getEdgePos(), mask);
     262       249161 :     of.writeOptionalAttr(SUMO_ATTR_EDGE, e->getID(), mask);
     263       249161 :     of.writeOptionalAttr(SUMO_ATTR_SLOPE, e->getLanes()[0]->getShape().slopeDegreeAtOffset(p->getEdgePos()), mask);
     264       295806 :     of.writeOptionalAttr(SUMO_ATTR_VEHICLE, v == nullptr ? "" : v->getID(), mask);
     265       249161 :     of.writeOptionalAttr(SUMO_ATTR_TYPE, p->getVehicleType().getID(), mask);
     266       498322 :     of.closeTag();
     267              : }
     268              : 
     269              : 
     270              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1