LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_Battery.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 75.2 % 282 212
Test Date: 2025-11-13 15:38:19 Functions: 86.8 % 38 33

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

Generated by: LCOV version 2.0-1