LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_StationFinder.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 67 74 90.5 %
Date: 2024-04-29 15:38:36 Functions: 7 9 77.8 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-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    MSDevice_StationFinder.cpp
      15             : /// @author  Michael Behrisch
      16             : /// @date    2023-05-24
      17             : ///
      18             : // A device which triggers rerouting to nearby charging stations
      19             : /****************************************************************************/
      20             : #include <config.h>
      21             : 
      22             : #include <microsim/MSEdge.h>
      23             : #include <microsim/MSNet.h>
      24             : #include <microsim/MSStop.h>
      25             : #include <microsim/MSVehicleControl.h>
      26             : #include <microsim/output/MSDetectorControl.h>
      27             : #include <utils/options/OptionsCont.h>
      28             : #include <utils/emissions/PollutantsInterface.h>
      29             : #include <utils/emissions/HelpersEnergy.h>
      30             : #include <utils/iodevices/OutputDevice.h>
      31             : #include "MSRoutingEngine.h"
      32             : #include "MSDevice_Battery.h"
      33             : #include "MSDevice_StationFinder.h"
      34             : 
      35             : 
      36             : // ===========================================================================
      37             : // method definitions
      38             : // ===========================================================================
      39             : // ---------------------------------------------------------------------------
      40             : // static initialisation methods
      41             : // ---------------------------------------------------------------------------
      42             : void
      43       36320 : MSDevice_StationFinder::insertOptions(OptionsCont& oc) {
      44       72640 :     insertDefaultAssignmentOptions("stationfinder", "Battery", oc);
      45       72640 :     oc.doRegister("device.stationfinder.rescueTime", new Option_String("1800", "TIME"));
      46       72640 :     oc.addDescription("device.stationfinder.rescueTime", "Battery", TL("Time to wait for a rescue vehicle on the road side when the battery is empty"));
      47       36320 :     oc.doRegister("device.stationfinder.reserveFactor", new Option_Float(1.1));
      48       72640 :     oc.addDescription("device.stationfinder.reserveFactor", "Battery", TL("Additional battery buffer for unexpected traffic situation when estimating the battery need"));
      49       36320 :     oc.doRegister("device.stationfinder.emptyThreshold", new Option_Float(5));
      50       72640 :     oc.addDescription("device.stationfinder.emptyThreshold", "Battery", TL("Battery percentage to go into rescue mode"));
      51       72640 :     oc.doRegister("device.stationfinder.radius", new Option_String("180", "TIME"));
      52       72640 :     oc.addDescription("device.stationfinder.radius", "Battery", TL("Search radius in travel time seconds"));
      53       72640 :     oc.doRegister("device.stationfinder.repeat", new Option_String("60", "TIME"));
      54       72640 :     oc.addDescription("device.stationfinder.repeat", "Battery", TL("When to trigger a new search if no station has been found"));
      55       36320 :     oc.doRegister("device.stationfinder.maxChargePower", new Option_Float(1000.));
      56       72640 :     oc.addDescription("device.stationfinder.maxChargePower", "Battery", TL("The maximum charging speed of the vehicle battery"));
      57       72640 :     oc.doRegister("device.stationfinder.chargeType", new Option_String("charging"));
      58       72640 :     oc.addDescription("device.stationfinder.chargeType", "Battery", TL("Type of energy transfer"));
      59       72640 :     oc.doRegister("device.stationfinder.waitForCharge", new Option_String("600", "TIME"));
      60       72640 :     oc.addDescription("device.stationfinder.waitForCharge", "Battery", TL("After this waiting time vehicle searches for a new station when the initial one is blocked"));
      61       36320 : }
      62             : 
      63             : 
      64             : void
      65     4658946 : MSDevice_StationFinder::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
      66     4658946 :     OptionsCont& oc = OptionsCont::getOptions();
      67     9317892 :     if (equippedByDefaultAssignmentOptions(oc, "stationfinder", v, false)) {
      68          16 :         into.push_back(new MSDevice_StationFinder(v));
      69             :     }
      70     4658946 : }
      71             : 
      72             : 
      73             : // ---------------------------------------------------------------------------
      74             : // MSDevice_StationFinder-methods
      75             : // ---------------------------------------------------------------------------
      76          16 : MSDevice_StationFinder::MSDevice_StationFinder(SUMOVehicle& holder)
      77          16 :     : MSVehicleDevice(holder, "stationfinder_" + holder.getID()),
      78          16 :       myBattery(nullptr), myChargingStation(nullptr) {
      79          16 :     OptionsCont& oc = OptionsCont::getOptions();
      80          16 :     myReserveFactor = getFloatParam(holder, oc, "stationfinder.reserveFactor", 1.1);
      81          16 : }
      82             : 
      83             : 
      84          32 : MSDevice_StationFinder::~MSDevice_StationFinder() {
      85          32 : }
      86             : 
      87             : 
      88             : bool
      89        5956 : MSDevice_StationFinder::notifyMove(SUMOTrafficObject& /*veh*/, double /*oldPos*/, double /*newPos*/, double /*newSpeed*/) {
      90        5956 :     if (myChargingStation == nullptr) {
      91        5552 :         const SUMOTime now = SIMSTEP;
      92        5552 :         SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = MSRoutingEngine::getRouterTT(myHolder.getRNGIndex(), myHolder.getVClass());
      93        5552 :         const ConstMSEdgeVector& route = myHolder.getRoute().getEdges();
      94        5552 :         const ConstMSEdgeVector remainingRoute(route.begin() + myHolder.getRoutePosition(), route.end());
      95        5552 :         const double remainingTime = router.recomputeCosts(remainingRoute, &myHolder, now);
      96        5552 :         if (now > myHolder.getDeparture()) {
      97        5552 :             double expectedConsumption = myBattery->getTotalConsumption() / STEPS2TIME(now - myHolder.getDeparture()) * remainingTime;
      98        5552 :             if (expectedConsumption > myBattery->getActualBatteryCapacity() * myReserveFactor) {
      99           4 :                 const MSEdge* const start = myHolder.getEdge();
     100             :                 double minTime = std::numeric_limits<double>::max();
     101             :                 MSChargingStation* minStation = nullptr;
     102             :                 ConstMSEdgeVector minRoute;
     103             :                 // TODO do some form of bulk routing here
     104          24 :                 for (const auto& stop : MSNet::getInstance()->getStoppingPlaces(SUMO_TAG_CHARGING_STATION)) {
     105             :                     ConstMSEdgeVector routeTo;
     106          20 :                     const MSEdge* const csEdge = &stop.second->getLane().getEdge();
     107          20 :                     if (router.compute(start, myHolder.getPositionOnLane(), csEdge, stop.second->getBeginLanePosition(), &myHolder, now, routeTo)) {
     108             :                         ConstMSEdgeVector routeFrom;
     109          20 :                         if (csEdge == route.back() || router.compute(start, &stop.second->getLane().getEdge(), &myHolder, now, routeFrom)) {
     110          20 :                             if (csEdge != route.back()) {
     111          20 :                                 routeTo.insert(routeTo.end(), routeFrom.begin() + 1, routeFrom.end());
     112             :                             }
     113          20 :                             const double time = router.recomputeCosts(routeTo, &myHolder, now);
     114          20 :                             if (time < minTime) {
     115             :                                 minTime = time;
     116           4 :                                 minStation = static_cast<MSChargingStation*>(stop.second);
     117           4 :                                 minRoute = routeTo;
     118             :                             }
     119             :                         }
     120             :                     }
     121             :                 }
     122           4 :                 if (minStation != nullptr) {
     123           4 :                     if (myHolder.hasStops()) {
     124           0 :                         WRITE_WARNINGF(TL("Rerouting using station finder removes all upcoming stops for vehicle '%'."), myHolder.getID());
     125             :                     }
     126           4 :                     myHolder.replaceRouteEdges(minRoute, minTime, 0., getID());
     127           4 :                     myChargingStation = minStation;
     128           4 :                     SUMOVehicleParameter::Stop stopPar;
     129             :                     stopPar.chargingStation = minStation->getID();
     130           4 :                     stopPar.lane = minStation->getLane().getID();
     131           4 :                     stopPar.endPos = minStation->getEndLanePosition();
     132           4 :                     stopPar.duration = TIME2STEPS(expectedConsumption / minStation->getChargingPower(false) * myReserveFactor);
     133             :                     std::string errorMsg;
     134           4 :                     if (!myHolder.addStop(stopPar, errorMsg)) {
     135           0 :                         WRITE_ERROR(errorMsg);
     136           4 :                     } else if (errorMsg != "") {
     137           0 :                         WRITE_WARNING(errorMsg);
     138             :                     }
     139           4 :                 }
     140             :             }
     141             :         }
     142             :     }
     143        5956 :     return true;
     144             : }
     145             : 
     146             : 
     147             : bool
     148           0 : MSDevice_StationFinder::notifyIdle(SUMOTrafficObject& /*veh*/) {
     149           0 :     return true;
     150             : }
     151             : 
     152             : 
     153             : void
     154           0 : MSDevice_StationFinder::notifyMoveInternal(const SUMOTrafficObject& /*veh*/,
     155             :         const double /* frontOnLane */,
     156             :         const double /* timeOnLane */,
     157             :         const double /* meanSpeedFrontOnLane */,
     158             :         const double /* meanSpeedVehicleOnLane */,
     159             :         const double /* travelledDistanceFrontOnLane */,
     160             :         const double /* travelledDistanceVehicleOnLane */,
     161             :         const double /* meanLengthOnLane */) {
     162             : 
     163             :     // called by meso (see MSMeanData_Emissions::MSLaneMeanDataValues::notifyMoveInternal)
     164           0 : }
     165             : 
     166             : 
     167             : 
     168             : void
     169          16 : MSDevice_StationFinder::generateOutput(OutputDevice* tripinfoOut) const {
     170             :     if (tripinfoOut != nullptr) {
     171             :     }
     172          16 : }
     173             : 
     174             : 
     175             : /****************************************************************************/

Generated by: LCOV version 1.14