LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_Battery.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 74.9 % 279 209
Test Date: 2024-11-22 15:46:21 Functions: 86.1 % 36 31

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2013-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_Battery.cpp
      15              : /// @author  Tamas Kurczveil
      16              : /// @author  Pablo Alvarez Lopez
      17              : /// @author  Mirko Barthauer
      18              : /// @date    20.12.2013
      19              : ///
      20              : // The Battery parameters for the vehicle
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <algorithm>
      25              : #include <utils/common/StringUtils.h>
      26              : #include <utils/options/OptionsCont.h>
      27              : #include <utils/iodevices/OutputDevice.h>
      28              : #include <utils/common/SUMOTime.h>
      29              : #include <utils/geom/GeomHelper.h>
      30              : #include <utils/emissions/HelpersEnergy.h>
      31              : #include <utils/xml/SUMOSAXAttributes.h>
      32              : #include <microsim/MSNet.h>
      33              : #include <microsim/MSLane.h>
      34              : #include <microsim/MSEdge.h>
      35              : #include <microsim/MSVehicle.h>
      36              : #include "MSDevice_StationFinder.h"
      37              : #include "MSDevice_Emissions.h"
      38              : #include "MSDevice_Battery.h"
      39              : 
      40              : #define DEFAULT_MAX_CAPACITY 35000
      41              : #define DEFAULT_CHARGE_RATIO 0.5
      42              : 
      43              : 
      44              : // ===========================================================================
      45              : // method definitions
      46              : // ===========================================================================
      47              : // ---------------------------------------------------------------------------
      48              : // static initialisation methods
      49              : // ---------------------------------------------------------------------------
      50              : void
      51        43644 : MSDevice_Battery::insertOptions(OptionsCont& oc) {
      52        87288 :     insertDefaultAssignmentOptions("battery", "Battery", oc);
      53              :     // custom options
      54        43644 :     oc.doRegister("device.battery.track-fuel", new Option_Bool(false));
      55        87288 :     oc.addDescription("device.battery.track-fuel", "Battery", TL("Track fuel consumption for non-electric vehicles"));
      56        43644 : }
      57              : 
      58              : 
      59              : void
      60      5104373 : MSDevice_Battery::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into, MSDevice_StationFinder* sf) {
      61              :     // Check if vehicle should get a battery
      62     10208678 :     if (sf != nullptr || equippedByDefaultAssignmentOptions(OptionsCont::getOptions(), "battery", v, false)) {
      63              :         // obtain parameter values
      64         1637 :         const double maximumBatteryCapacity = readParameterValue(v, SUMO_ATTR_MAXIMUMBATTERYCAPACITY, "battery.capacity", DEFAULT_MAX_CAPACITY);
      65         1637 :         const double actualBatteryCapacity = readParameterValue(v, SUMO_ATTR_ACTUALBATTERYCAPACITY, "battery.chargeLevel", maximumBatteryCapacity * DEFAULT_CHARGE_RATIO);
      66         1637 :         const double stoppingThreshold = readParameterValue(v, SUMO_ATTR_STOPPINGTHRESHOLD, "battery.stoppingThreshold", 0.1);
      67         1637 :         const double maximumChargeRate = readParameterValue(v, SUMO_ATTR_MAXIMUMCHARGERATE, "battery.maximumChargeRate", 150000.);
      68         3274 :         const std::string chargeLevelTable = v.getStringParam("device.battery.chargeLevelTable");
      69         3274 :         const std::string chargeCurveTable = v.getStringParam("device.battery.chargeCurveTable");
      70              : 
      71              :         // battery constructor
      72         1637 :         MSDevice_Battery* device = new MSDevice_Battery(v, "battery_" + v.getID(),
      73         3274 :                 actualBatteryCapacity, maximumBatteryCapacity, stoppingThreshold, maximumChargeRate, chargeLevelTable, chargeCurveTable);
      74              : 
      75              :         // Add device to vehicle
      76         1637 :         into.push_back(device);
      77              : 
      78         1637 :         if (sf != nullptr) {
      79              :             sf->setBattery(device);
      80              :         }
      81              :     }
      82      5104373 : }
      83              : 
      84              : 
      85              : double
      86         6548 : MSDevice_Battery::readParameterValue(SUMOVehicle& v, const SumoXMLAttr& attr, const std::string& paramName, double defaultVal) {
      87         6548 :     const std::string& oldParam = toString(attr);
      88         6548 :     const SUMOVTypeParameter& typeParams = v.getVehicleType().getParameter();
      89         6548 :     if (v.getParameter().hasParameter(oldParam) || typeParams.hasParameter(oldParam)) {
      90            0 :         WRITE_WARNINGF(TL("Battery device in vehicle '%' still uses old parameter '%'. Please update to 'device.%'."), v.getID(), oldParam, paramName);
      91            0 :         if (v.getParameter().getParameter(oldParam, "-") == "-") {
      92            0 :             return typeParams.getDouble(oldParam, defaultVal);
      93              :         }
      94            0 :         return StringUtils::toDouble(v.getParameter().getParameter(oldParam, "0"));
      95              :     }
      96        13096 :     return v.getFloatParam("device." + paramName, false, defaultVal);
      97              : }
      98              : 
      99              : 
     100              : // ---------------------------------------------------------------------------
     101              : // MSDevice_Battery-methods
     102              : // ---------------------------------------------------------------------------
     103         1637 : MSDevice_Battery::MSDevice_Battery(SUMOVehicle& holder, const std::string& id, const double actualBatteryCapacity, const double maximumBatteryCapacity,
     104         1637 :                                    const double stoppingThreshold, const double maximumChargeRate, const std::string& chargeLevelTable, const std::string& chargeCurveTable) :
     105              :     MSVehicleDevice(holder, id),
     106         1637 :     myActualBatteryCapacity(0),         // [actualBatteryCapacity <= maximumBatteryCapacity]
     107         1637 :     myMaximumBatteryCapacity(0),        // [maximumBatteryCapacity >= 0]
     108         1637 :     myStoppingThreshold(0),             // [stoppingThreshold >= 0]
     109         1637 :     myMaximumChargeRate(0),
     110         1637 :     myChargeLimit(-1),
     111         1637 :     myLastAngle(std::numeric_limits<double>::infinity()),
     112         1637 :     myChargingStopped(false),           // Initially vehicle don't charge stopped
     113         1637 :     myChargingInTransit(false),         // Initially vehicle don't charge in transit
     114         1637 :     myChargingStartTime(0),             // Initially charging start time (must be if the vehicle was launched at the charging station)
     115         1637 :     myConsum(0),                        // Initially the vehicle is stopped and therefore the consum is zero.
     116         1637 :     myTotalConsumption(0.0),
     117         1637 :     myTotalRegenerated(0.0),
     118         1637 :     myActChargingStation(nullptr),         // Initially the vehicle isn't over a Charging Station
     119         1637 :     myPreviousNeighbouringChargingStation(nullptr),    // Initially the vehicle wasn't over a Charging Station
     120         1637 :     myEnergyCharged(0),                 // Initially the energy charged is zero
     121         1637 :     myVehicleStopped(0),
     122         1637 :     myDepletedCount(0) {
     123              :     // Initially the vehicle is stopped and the corresponding variable is 0
     124              : 
     125         1637 :     if (maximumBatteryCapacity < 0) {
     126            0 :         WRITE_WARNINGF(TL("Battery builder: Vehicle '%' doesn't have a valid value for parameter % (%)."), getID(), toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY), toString(maximumBatteryCapacity));
     127              :     } else {
     128         1637 :         myMaximumBatteryCapacity = maximumBatteryCapacity;
     129              :     }
     130              : 
     131         1637 :     if (actualBatteryCapacity > maximumBatteryCapacity) {
     132            0 :         WRITE_WARNINGF(TL("Battery builder: Vehicle '%' has a % (%) greater than its % (%). A max battery capacity value will be assigned."),
     133              :                        getID(), toString(SUMO_ATTR_ACTUALBATTERYCAPACITY), toString(actualBatteryCapacity), toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY), toString(maximumBatteryCapacity));
     134            0 :         myActualBatteryCapacity = myMaximumBatteryCapacity;
     135              :     } else {
     136         1637 :         myActualBatteryCapacity = actualBatteryCapacity;
     137              :     }
     138              : 
     139         1637 :     if (stoppingThreshold < 0) {
     140            0 :         WRITE_WARNINGF(TL("Battery builder: Vehicle '%' doesn't have a valid value for parameter % (%)."), getID(), toString(SUMO_ATTR_STOPPINGTHRESHOLD), toString(stoppingThreshold));
     141              :     } else {
     142         1637 :         myStoppingThreshold = stoppingThreshold;
     143              :     }
     144              : 
     145         1673 :     myTrackFuel = PollutantsInterface::getFuel(holder.getVehicleType().getEmissionClass()) != "Electricity" && OptionsCont::getOptions().getBool("device.battery.track-fuel");
     146         1637 :     if (!myTrackFuel && !holder.getVehicleType().getParameter().wasSet(VTYPEPARS_EMISSIONCLASS_SET)) {
     147           72 :         WRITE_WARNINGF(TL("The battery device is active for vehicle '%' but no emission class is set. "
     148              :                           "Please consider setting an explicit emission class or battery outputs might be inconsistent with emission outputs!"),
     149              :                        holder.getID());
     150              :     }
     151              : 
     152         1637 :     if (maximumChargeRate < 0) {
     153            0 :         WRITE_WARNINGF(TL("Battery builder: Vehicle '%' doesn't have a valid value for parameter % (%)."), getID(), toString(SUMO_ATTR_MAXIMUMCHARGERATE), toString(maximumChargeRate));
     154              :     } else {
     155         1637 :         if (!chargeLevelTable.empty() && !chargeCurveTable.empty()) {
     156            0 :             LinearApproxHelpers::setPoints(myChargeCurve, chargeLevelTable, chargeCurveTable);
     157            0 :             if (!myTrackFuel) {
     158            0 :                 LinearApproxHelpers::scaleValues(myChargeCurve, 1. / 3600);
     159              :             }
     160            0 :             myMaximumChargeRate = LinearApproxHelpers::getMaximumValue(myChargeCurve);
     161              :         } else {
     162         1637 :             myMaximumChargeRate = maximumChargeRate;
     163         1637 :             if (!myTrackFuel) {
     164         1625 :                 myMaximumChargeRate /= 3600.;
     165              :             }
     166              :         }
     167              :     }
     168         1637 : }
     169              : 
     170              : 
     171         3274 : MSDevice_Battery::~MSDevice_Battery() {
     172         3274 : }
     173              : 
     174              : 
     175       373298 : bool MSDevice_Battery::notifyMove(SUMOTrafficObject& tObject, double /* oldPos */, double /* newPos */, double /* newSpeed */) {
     176       373298 :     if (!tObject.isVehicle()) {
     177              :         return false;
     178              :     }
     179              :     SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
     180              :     // Start vehicleStoppedTimer if the vehicle is stopped. In other case reset timer
     181       373298 :     if (veh.getSpeed() < myStoppingThreshold) {
     182              :         // Increase vehicle stopped timer
     183       133932 :         increaseVehicleStoppedTimer();
     184              :     } else {
     185              :         // Reset vehicle Stopped
     186       239366 :         resetVehicleStoppedTimer();
     187              :     }
     188              : 
     189              :     // Update Energy from the battery
     190       373298 :     EnergyParams* const params = myHolder.getEmissionParameters();
     191       373298 :     if (getMaximumBatteryCapacity() != 0) {
     192       373298 :         params->setDouble(SUMO_ATTR_ANGLE, myLastAngle == std::numeric_limits<double>::infinity() ? 0. : GeomHelper::angleDiff(myLastAngle, veh.getAngle()));
     193       373298 :         if (!myTrackFuel && !veh.getVehicleType().getParameter().wasSet(VTYPEPARS_EMISSIONCLASS_SET)) {
     194              :             // no explicit emission class, we fall back to the energy model; a warning has been issued on creation
     195          890 :             myConsum = PollutantsInterface::getEnergyHelper().compute(0, PollutantsInterface::ELEC, veh.getSpeed(), veh.getAcceleration(),
     196          890 :                        veh.getSlope(), params) * TS;
     197              :         } else {
     198       372853 :             myConsum = PollutantsInterface::compute(veh.getVehicleType().getEmissionClass(),
     199       372853 :                                                     myTrackFuel ? PollutantsInterface::FUEL : PollutantsInterface::ELEC,
     200       372853 :                                                     veh.getSpeed(), veh.getAcceleration(),
     201       745706 :                                                     veh.getSlope(), params) * TS;
     202              :         }
     203       373298 :         if (veh.isParking()) {
     204              :             // recuperation from last braking step is ok but further consumption should cease
     205          848 :             myConsum = MIN2(myConsum, 0.0);
     206              :         }
     207              : 
     208              :         // saturate between 0 and myMaximumBatteryCapacity [Wh]
     209       373298 :         if (myConsum > getActualBatteryCapacity() && getActualBatteryCapacity() > 0 && getMaximumBatteryCapacity() > 0) {
     210           44 :             myDepletedCount++;
     211           44 :             if (myDepletedCount == 1) {
     212           84 :                 WRITE_WARNINGF(TL("Battery of vehicle '%' is depleted, time=%."), veh.getID(), time2string(SIMSTEP));
     213              :             }
     214              :         }
     215              : 
     216              :         // Energy lost/gained from vehicle movement (via vehicle energy model) [Wh]
     217       373298 :         setActualBatteryCapacity(getActualBatteryCapacity() - myConsum);
     218              : 
     219              :         // Track total energy consumption and regeneration
     220       373298 :         if (myConsum > 0.0) {
     221       341538 :             myTotalConsumption += myConsum;
     222              :         } else {
     223        31760 :             myTotalRegenerated -= myConsum;
     224              :         }
     225              : 
     226       373298 :         myLastAngle = veh.getAngle();
     227              :     }
     228              : 
     229              :     // Check if vehicle has under their position one charge Station
     230       373298 :     const std::string chargingStationID = MSNet::getInstance()->getStoppingPlaceID(veh.getLane(), veh.getPositionOnLane(), SUMO_TAG_CHARGING_STATION);
     231              : 
     232              :     // If vehicle is over a charging station
     233       373298 :     if (chargingStationID != "") {
     234              :         // if the vehicle is almost stopped, or charge in transit is enabled, then charge vehicle
     235        34694 :         MSChargingStation* const cs = static_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(chargingStationID, SUMO_TAG_CHARGING_STATION));
     236        34694 :         const MSParkingArea* pa = cs->getParkingArea();
     237        34694 :         if (((veh.getSpeed() < myStoppingThreshold) || cs->getChargeInTransit()) && (pa == nullptr || veh.isParking())) {
     238              :             // Set Flags Stopped/intransit to
     239        32698 :             if (veh.getSpeed() < myStoppingThreshold) {
     240              :                 // vehicle ist almost stopped, then is charging stopped
     241        31583 :                 myChargingStopped = true;
     242              : 
     243              :                 // therefore isn't charging in transit
     244        31583 :                 myChargingInTransit = false;
     245              :             } else {
     246              :                 // vehicle is moving, and the Charging station allow charge in transit
     247         1115 :                 myChargingStopped = false;
     248              : 
     249              :                 // Therefore charge in transit
     250         1115 :                 myChargingInTransit = true;
     251              :             }
     252              : 
     253              :             // get pointer to charging station
     254        32698 :             myActChargingStation = cs;
     255              : 
     256              :             // Only update charging start time if vehicle allow charge in transit, or in other case
     257              :             // if the vehicle not allow charge in transit but it's stopped.
     258        32698 :             if ((myActChargingStation->getChargeInTransit()) || (veh.getSpeed() < myStoppingThreshold)) {
     259              :                 // Update Charging start time
     260        32698 :                 increaseChargingStartTime();
     261              :             }
     262              : 
     263              :             // time it takes the vehicle at the station < charging station time delay?
     264        32698 :             if (getChargingStartTime() > myActChargingStation->getChargeDelay()) {
     265              :                 // Enable charging vehicle
     266        31787 :                 myActChargingStation->setChargingVehicle(true);
     267              : 
     268              :                 // Calulate energy charged
     269        35003 :                 myEnergyCharged = MIN2(MIN2(myActChargingStation->getChargingPower(myTrackFuel) * myActChargingStation->getEfficency(), getMaximumChargeRate()) * TS, getMaximumBatteryCapacity() - getActualBatteryCapacity());
     270              : 
     271              :                 // Update Battery charge
     272        31787 :                 setActualBatteryCapacity(getActualBatteryCapacity() + myEnergyCharged);
     273              :             }
     274              :             // add charge value for output to myActChargingStation
     275        32698 :             myActChargingStation->addChargeValueForOutput(myEnergyCharged, this);
     276              :         }
     277              :         // else disable charging vehicle
     278              :         else {
     279         1996 :             cs->setChargingVehicle(false);
     280              :         }
     281              :         // disable charging vehicle from previous (not current) ChargingStation (reason: if there is no gap between two different chargingStations = the vehicle switches from used charging station to other one in a single timestap)
     282        34694 :         if (myPreviousNeighbouringChargingStation != nullptr && myPreviousNeighbouringChargingStation != cs) {
     283          452 :             myPreviousNeighbouringChargingStation->setChargingVehicle(false);
     284              :         }
     285        34694 :         myPreviousNeighbouringChargingStation = cs;
     286              :     }
     287              :     // In other case, vehicle will be not charged
     288              :     else {
     289              :         // Disable flags
     290       338604 :         myChargingInTransit = false;
     291       338604 :         myChargingStopped = false;
     292              : 
     293              :         // Disable charging vehicle
     294       338604 :         if (myActChargingStation != nullptr) {
     295          504 :             myActChargingStation->setChargingVehicle(false);
     296              :         }
     297              : 
     298              :         // Set charging station pointer to NULL
     299       338604 :         myActChargingStation = nullptr;
     300              : 
     301              :         // Set energy charged to 0
     302       338604 :         myEnergyCharged = 0.00;
     303              : 
     304              :         // Reset timer
     305       338604 :         resetChargingStartTime();
     306              :     }
     307              : 
     308              :     // Always return true.
     309              :     return true;
     310              : }
     311              : 
     312              : 
     313              : void
     314            0 : MSDevice_Battery::saveState(OutputDevice& out) const {
     315            0 :     out.openTag(SUMO_TAG_DEVICE);
     316              :     out.writeAttr(SUMO_ATTR_ID, getID());
     317              :     std::vector<std::string> internals;
     318            0 :     internals.push_back(toString(myActualBatteryCapacity));
     319            0 :     internals.push_back(toString(myLastAngle));
     320            0 :     internals.push_back(toString(myChargingStopped));
     321            0 :     internals.push_back(toString(myChargingInTransit));
     322            0 :     internals.push_back(toString(myChargingStartTime));
     323            0 :     internals.push_back(toString(myTotalConsumption));
     324            0 :     internals.push_back(toString(myTotalRegenerated));
     325            0 :     internals.push_back(toString(myEnergyCharged));
     326            0 :     internals.push_back(toString(myVehicleStopped));
     327            0 :     internals.push_back(getChargingStationID());
     328            0 :     std::string prevChargingID = (myPreviousNeighbouringChargingStation == nullptr) ? "NULL" : myPreviousNeighbouringChargingStation->getID();
     329            0 :     internals.push_back(prevChargingID);
     330            0 :     internals.push_back(toString(myMaximumChargeRate));
     331            0 :     out.writeAttr(SUMO_ATTR_STATE, toString(internals));
     332            0 :     out.closeTag();
     333            0 : }
     334              : 
     335              : 
     336              : void
     337            0 : MSDevice_Battery::loadState(const SUMOSAXAttributes& attrs) {
     338            0 :     std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
     339            0 :     bis >> myActualBatteryCapacity;
     340            0 :     bis >> myLastAngle;
     341            0 :     bis >> myChargingStopped;
     342            0 :     bis >> myChargingInTransit;
     343            0 :     bis >> myChargingStartTime;
     344            0 :     bis >> myTotalConsumption;
     345            0 :     bis >> myTotalRegenerated;
     346            0 :     bis >> myEnergyCharged;
     347            0 :     bis >> myVehicleStopped;
     348              :     std::string chargingID;
     349            0 :     bis >> chargingID;
     350            0 :     if (chargingID != "NULL") {
     351            0 :         myActChargingStation = dynamic_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(chargingID, SUMO_TAG_CHARGING_STATION));
     352              :     }
     353              :     std::string prevChargingID;
     354            0 :     bis >> prevChargingID;
     355            0 :     if (prevChargingID != "NULL") {
     356            0 :         myPreviousNeighbouringChargingStation = dynamic_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(prevChargingID, SUMO_TAG_CHARGING_STATION));
     357              :     }
     358            0 :     bis >> myMaximumChargeRate;
     359            0 : }
     360              : 
     361              : 
     362              : void
     363       405085 : MSDevice_Battery::setActualBatteryCapacity(const double actualBatteryCapacity) {
     364       405085 :     if (actualBatteryCapacity < 0) {
     365         1418 :         myActualBatteryCapacity = 0;
     366       403667 :     } else if (actualBatteryCapacity > myMaximumBatteryCapacity) {
     367            4 :         myActualBatteryCapacity = myMaximumBatteryCapacity;
     368              :     } else {
     369       403663 :         myActualBatteryCapacity = actualBatteryCapacity;
     370              :     }
     371       405085 : }
     372              : 
     373              : 
     374              : void
     375            9 : MSDevice_Battery::setMaximumBatteryCapacity(const double maximumBatteryCapacity) {
     376            9 :     if (myMaximumBatteryCapacity < 0) {
     377            0 :         WRITE_WARNINGF(TL("Trying to set into the battery device of vehicle '%' an invalid % (%)."), getID(), toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY), toString(maximumBatteryCapacity));
     378              :     } else {
     379            9 :         myMaximumBatteryCapacity = maximumBatteryCapacity;
     380              :     }
     381            9 : }
     382              : 
     383              : 
     384              : void
     385            0 : MSDevice_Battery::setStoppingThreshold(const double stoppingThreshold) {
     386            0 :     if (stoppingThreshold < 0) {
     387            0 :         WRITE_WARNINGF(TL("Trying to set into the battery device of vehicle '%' an invalid % (%)."), getID(), toString(SUMO_ATTR_STOPPINGTHRESHOLD), toString(stoppingThreshold));
     388              :     } else {
     389            0 :         myStoppingThreshold = stoppingThreshold;
     390              :     }
     391            0 : }
     392              : 
     393              : 
     394              : void
     395            0 : MSDevice_Battery::setMaximumChargeRate(const double chargeRate) {
     396            0 :     if (chargeRate < 0) {
     397            0 :         WRITE_WARNINGF(TL("Trying to set into the battery device of vehicle '%' an invalid % (%)."), getID(), toString(SUMO_ATTR_MAXIMUMCHARGERATE), toString(chargeRate));
     398              :     } else {
     399            0 :         myMaximumChargeRate = chargeRate;
     400              :     }
     401            0 : }
     402              : 
     403              : 
     404              : void
     405            8 : MSDevice_Battery::setChargeLimit(const double limit) {
     406            8 :     myChargeLimit = limit;
     407            8 : }
     408              : 
     409              : 
     410              : void
     411       338604 : MSDevice_Battery::resetChargingStartTime() {
     412       338604 :     myChargingStartTime = 0;
     413       338604 : }
     414              : 
     415              : 
     416              : void
     417        32698 : MSDevice_Battery::increaseChargingStartTime() {
     418        32698 :     myChargingStartTime += DELTA_T;
     419        32698 : }
     420              : 
     421              : 
     422              : void
     423       239366 : MSDevice_Battery::resetVehicleStoppedTimer() {
     424       239366 :     myVehicleStopped = 0;
     425       239366 : }
     426              : 
     427              : 
     428              : void
     429       133932 : MSDevice_Battery::increaseVehicleStoppedTimer() {
     430       133932 :     myVehicleStopped++;
     431       133932 : }
     432              : 
     433              : 
     434              : double
     435      1173700 : MSDevice_Battery::getActualBatteryCapacity() const {
     436      1173700 :     return myActualBatteryCapacity;
     437              : }
     438              : 
     439              : 
     440              : double
     441      1083011 : MSDevice_Battery::getMaximumBatteryCapacity() const {
     442      1083011 :     return myMaximumBatteryCapacity;
     443              : }
     444              : 
     445              : 
     446              : double
     447       315839 : MSDevice_Battery::getConsum() const {
     448       315839 :     return myConsum;
     449              : }
     450              : 
     451              : double
     452       315919 : MSDevice_Battery::getTotalConsumption() const {
     453       315919 :     return myTotalConsumption;
     454              : }
     455              : 
     456              : 
     457              : double
     458       315839 : MSDevice_Battery::getTotalRegenerated() const {
     459       315839 :     return myTotalRegenerated;
     460              : }
     461              : 
     462              : 
     463              : bool
     464       315749 : MSDevice_Battery::isChargingStopped() const {
     465       315749 :     return myChargingStopped;
     466              : }
     467              : 
     468              : 
     469              : bool
     470       315749 : MSDevice_Battery::isChargingInTransit() const {
     471       315749 :     return myChargingInTransit;
     472              : }
     473              : 
     474              : 
     475              : SUMOTime
     476        63733 : MSDevice_Battery::getChargingStartTime() const {
     477        63733 :     return myChargingStartTime;
     478              : }
     479              : 
     480              : 
     481              : SUMOTime
     482            0 : MSDevice_Battery::estimateChargingDuration(const double toCharge, const double csPower) const {
     483              :     //if (!myChargeCurve.empty()) {
     484              :     //    // TODO: integrate charge curve
     485              :     //}
     486            0 :     return TIME2STEPS(toCharge / MIN2(csPower, myMaximumChargeRate));
     487              : }
     488              : 
     489              : 
     490              : std::string
     491       353859 : MSDevice_Battery::getChargingStationID() const {
     492       353859 :     if (myActChargingStation != nullptr) {
     493              :         return myActChargingStation->getID();
     494              :     } else {
     495       301562 :         return "NULL";
     496              :     }
     497              : }
     498              : 
     499              : double
     500       395752 : MSDevice_Battery::getEnergyCharged() const {
     501       395752 :     return myEnergyCharged;
     502              : }
     503              : 
     504              : 
     505              : int
     506       315749 : MSDevice_Battery::getVehicleStopped() const {
     507       315749 :     return myVehicleStopped;
     508              : }
     509              : 
     510              : 
     511              : double
     512        30695 : MSDevice_Battery::getStoppingThreshold() const {
     513        30695 :     return myStoppingThreshold;
     514              : }
     515              : 
     516              : 
     517              : double
     518        31787 : MSDevice_Battery::getMaximumChargeRate() const {
     519        31787 :     double baseVal = (myChargeCurve.empty()) ? myMaximumChargeRate : LinearApproxHelpers::getInterpolatedValue(myChargeCurve, myActualBatteryCapacity / myMaximumBatteryCapacity);
     520        31787 :     return (myChargeLimit < 0) ? baseVal : MIN2(myChargeLimit, baseVal);
     521              : }
     522              : 
     523              : 
     524              : std::string
     525          738 : MSDevice_Battery::getParameter(const std::string& key) const {
     526         1476 :     if (key == toString(SUMO_ATTR_ACTUALBATTERYCAPACITY)
     527         1476 :             || key == toString(SUMO_ATTR_CHARGELEVEL)) {
     528           90 :         return toString(getActualBatteryCapacity());
     529          648 :     } else if (key == toString(SUMO_ATTR_ENERGYCONSUMED)) {
     530           90 :         return toString(getConsum());
     531          558 :     } else if (key == toString(SUMO_ATTR_TOTALENERGYCONSUMED)) {
     532           90 :         return toString(getTotalConsumption());
     533          468 :     } else if (key == toString(SUMO_ATTR_TOTALENERGYREGENERATED)) {
     534           90 :         return toString(getTotalRegenerated());
     535          378 :     } else if (key == toString(SUMO_ATTR_ENERGYCHARGED)) {
     536           90 :         return toString(getEnergyCharged());
     537          576 :     } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY) || key == "capacity") {
     538           99 :         return toString(getMaximumBatteryCapacity());
     539          189 :     } else if (key == toString(SUMO_ATTR_MAXIMUMCHARGERATE)) {
     540            0 :         return toString(getMaximumChargeRate());
     541          189 :     } else if (key == toString(SUMO_ATTR_CHARGINGSTATIONID)) {
     542           90 :         return getChargingStationID();
     543           99 :     } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
     544           90 :         WRITE_WARNING(TL("Getting the vehicle mass via parameters is deprecated, please use getMass for the vehicle or its type."));
     545           90 :         return toString(myHolder.getEmissionParameters()->getDouble(SUMO_ATTR_MASS));
     546              :     }
     547           18 :     throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
     548              : }
     549              : 
     550              : 
     551              : void
     552           18 : MSDevice_Battery::setParameter(const std::string& key, const std::string& value) {
     553              :     double doubleValue;
     554              :     try {
     555           18 :         doubleValue = StringUtils::toDouble(value);
     556            0 :     } catch (NumberFormatException&) {
     557            0 :         throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
     558            0 :     }
     559           36 :     if (key == toString(SUMO_ATTR_ACTUALBATTERYCAPACITY) || key == toString(SUMO_ATTR_CHARGELEVEL)) {
     560            0 :         setActualBatteryCapacity(doubleValue);
     561           36 :     } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY) || key == "capacity") {
     562            9 :         setMaximumBatteryCapacity(doubleValue);
     563            9 :     } else if (key == toString(SUMO_ATTR_MAXIMUMCHARGERATE)) {
     564            0 :         setMaximumChargeRate(doubleValue);
     565            9 :     } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
     566            9 :         WRITE_WARNING(TL("Setting the vehicle mass via parameters is deprecated, please use setMass for the vehicle or its type."));
     567            9 :         myHolder.getEmissionParameters()->setDouble(SUMO_ATTR_MASS, doubleValue);
     568              :     } else {
     569            0 :         throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
     570              :     }
     571           18 : }
     572              : 
     573              : 
     574              : void
     575          400 : MSDevice_Battery::notifyParking() {
     576              :     // @note: only charing is performed but no energy is consumed
     577          400 :     notifyMove(myHolder, myHolder.getPositionOnLane(), myHolder.getPositionOnLane(), myHolder.getSpeed());
     578          400 :     myConsum = 0;
     579          400 : }
     580              : 
     581              : 
     582              : void
     583         1577 : MSDevice_Battery::generateOutput(OutputDevice* tripinfoOut) const {
     584         1577 :     if (tripinfoOut != nullptr) {
     585          167 :         tripinfoOut->openTag("battery");
     586          334 :         tripinfoOut->writeAttr("depleted", toString(myDepletedCount));
     587          334 :         tripinfoOut->closeTag();
     588              :     }
     589         1577 : }
     590              : 
     591              : 
     592              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1