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 <utils/common/StringUtils.h>
25 : #include <utils/options/OptionsCont.h>
26 : #include <utils/iodevices/OutputDevice.h>
27 : #include <utils/common/SUMOTime.h>
28 : #include <utils/geom/GeomHelper.h>
29 : #include <utils/emissions/HelpersEnergy.h>
30 : #include <utils/xml/SUMOSAXAttributes.h>
31 : #include <microsim/MSNet.h>
32 : #include <microsim/MSLane.h>
33 : #include <microsim/MSEdge.h>
34 : #include <microsim/MSVehicle.h>
35 : #include "MSDevice_StationFinder.h"
36 : #include "MSDevice_Emissions.h"
37 : #include "MSDevice_Battery.h"
38 :
39 : #define DEFAULT_MAX_CAPACITY 35000
40 : #define DEFAULT_CHARGE_RATIO 0.5
41 :
42 :
43 : // ===========================================================================
44 : // method definitions
45 : // ===========================================================================
46 : // ---------------------------------------------------------------------------
47 : // static initialisation methods
48 : // ---------------------------------------------------------------------------
49 : void
50 36320 : MSDevice_Battery::insertOptions(OptionsCont& oc) {
51 72640 : insertDefaultAssignmentOptions("battery", "Battery", oc);
52 : // custom options
53 36320 : oc.doRegister("device.battery.track-fuel", new Option_Bool(false));
54 72640 : oc.addDescription("device.battery.track-fuel", "Battery", TL("Track fuel consumption for non-electric vehicles"));
55 36320 : }
56 :
57 :
58 : void
59 4658946 : MSDevice_Battery::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into, MSDevice_StationFinder* sf) {
60 : // Check if vehicle should get a battery
61 9318780 : if (sf != nullptr || equippedByDefaultAssignmentOptions(OptionsCont::getOptions(), "battery", v, false)) {
62 : // obtain parameter values
63 920 : const double maximumBatteryCapacity = readParameterValue(v, SUMO_ATTR_MAXIMUMBATTERYCAPACITY, "battery.capacity", DEFAULT_MAX_CAPACITY);
64 920 : const double actualBatteryCapacity = readParameterValue(v, SUMO_ATTR_ACTUALBATTERYCAPACITY, "battery.chargeLevel", maximumBatteryCapacity * DEFAULT_CHARGE_RATIO);
65 1840 : const double stoppingThreshold = readParameterValue(v, SUMO_ATTR_STOPPINGTHRESHOLD, "battery.stoppingThreshold", 0.1);
66 :
67 : // battery constructor
68 920 : MSDevice_Battery* device = new MSDevice_Battery(v, "battery_" + v.getID(),
69 920 : actualBatteryCapacity, maximumBatteryCapacity, stoppingThreshold);
70 :
71 : // Add device to vehicle
72 920 : into.push_back(device);
73 :
74 920 : if (sf != nullptr) {
75 : sf->setBattery(device);
76 : }
77 : }
78 4658946 : }
79 :
80 :
81 : double
82 2760 : MSDevice_Battery::readParameterValue(SUMOVehicle& v, const SumoXMLAttr& attr, const std::string& paramName, double defaultVal) {
83 2760 : const std::string& oldParam = toString(attr);
84 2760 : const SUMOVTypeParameter& typeParams = v.getVehicleType().getParameter();
85 2760 : if (v.getParameter().hasParameter(oldParam) || typeParams.hasParameter(oldParam)) {
86 0 : WRITE_WARNINGF(TL("Battery device in vehicle '%' still uses old parameter '%'. Please update to 'device.%'."), v.getID(), oldParam, paramName);
87 0 : if (v.getParameter().getParameter(oldParam, "-") == "-") {
88 0 : return typeParams.getDouble(oldParam, defaultVal);
89 : }
90 0 : return StringUtils::toDouble(v.getParameter().getParameter(oldParam, "0"));
91 : }
92 2760 : return getFloatParam(v, OptionsCont::getOptions(), paramName, defaultVal);
93 : }
94 :
95 :
96 : // ---------------------------------------------------------------------------
97 : // MSDevice_Battery-methods
98 : // ---------------------------------------------------------------------------
99 920 : MSDevice_Battery::MSDevice_Battery(SUMOVehicle& holder, const std::string& id, const double actualBatteryCapacity, const double maximumBatteryCapacity,
100 920 : const double stoppingThreshold) :
101 : MSVehicleDevice(holder, id),
102 920 : myActualBatteryCapacity(0), // [actualBatteryCapacity <= maximumBatteryCapacity]
103 920 : myMaximumBatteryCapacity(0), // [maximumBatteryCapacity >= 0]
104 920 : myStoppingThreshold(0), // [stoppingThreshold >= 0]
105 920 : myLastAngle(std::numeric_limits<double>::infinity()),
106 920 : myChargingStopped(false), // Initially vehicle don't charge stopped
107 920 : myChargingInTransit(false), // Initially vehicle don't charge in transit
108 920 : myChargingStartTime(0), // Initially charging start time (must be if the vehicle was launched at the charging station)
109 920 : myConsum(0), // Initially the vehicle is stopped and therefore the consum is zero.
110 920 : myTotalConsumption(0.0),
111 920 : myTotalRegenerated(0.0),
112 920 : myActChargingStation(nullptr), // Initially the vehicle isn't over a Charging Station
113 920 : myPreviousNeighbouringChargingStation(nullptr), // Initially the vehicle wasn't over a Charging Station
114 920 : myEnergyCharged(0), // Initially the energy charged is zero
115 920 : myVehicleStopped(0) { // Initially the vehicle is stopped and the corresponding variable is 0
116 :
117 920 : if (maximumBatteryCapacity < 0) {
118 0 : WRITE_WARNINGF(TL("Battery builder: Vehicle '%' doesn't have a valid value for parameter % (%)."), getID(), toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY), toString(maximumBatteryCapacity));
119 : } else {
120 920 : myMaximumBatteryCapacity = maximumBatteryCapacity;
121 : }
122 :
123 920 : if (actualBatteryCapacity > maximumBatteryCapacity) {
124 0 : WRITE_WARNINGF(TL("Battery builder: Vehicle '%' has a % (%) greater than its % (%). A max battery capacity value will be assigned."),
125 : getID(), toString(SUMO_ATTR_ACTUALBATTERYCAPACITY), toString(actualBatteryCapacity), toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY), toString(maximumBatteryCapacity));
126 0 : myActualBatteryCapacity = myMaximumBatteryCapacity;
127 : } else {
128 920 : myActualBatteryCapacity = actualBatteryCapacity;
129 : }
130 :
131 920 : if (stoppingThreshold < 0) {
132 0 : WRITE_WARNINGF(TL("Battery builder: Vehicle '%' doesn't have a valid value for parameter % (%)."), getID(), toString(SUMO_ATTR_STOPPINGTHRESHOLD), toString(stoppingThreshold));
133 : } else {
134 920 : myStoppingThreshold = stoppingThreshold;
135 : }
136 :
137 1900 : myTrackFuel = PollutantsInterface::getFuel(holder.getVehicleType().getEmissionClass()) != "Electricity" && OptionsCont::getOptions().getBool("device.battery.track-fuel");
138 920 : if (!myTrackFuel && !holder.getVehicleType().getParameter().wasSet(VTYPEPARS_EMISSIONCLASS_SET)) {
139 72 : WRITE_WARNINGF(TL("The battery device is active for vehicle '%' but no emission class is set. "
140 : "Please consider setting an explicit emission class or battery outputs might be inconsistent with emission outputs!"),
141 : holder.getID());
142 : }
143 920 : }
144 :
145 :
146 1840 : MSDevice_Battery::~MSDevice_Battery() {
147 1840 : }
148 :
149 :
150 203120 : bool MSDevice_Battery::notifyMove(SUMOTrafficObject& tObject, double /* oldPos */, double /* newPos */, double /* newSpeed */) {
151 203120 : if (!tObject.isVehicle()) {
152 : return false;
153 : }
154 : SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
155 : // Start vehicleStoppedTimer if the vehicle is stopped. In other case reset timer
156 203120 : if (veh.getSpeed() < myStoppingThreshold) {
157 : // Increase vehicle stopped timer
158 60150 : increaseVehicleStoppedTimer();
159 : } else {
160 : // Reset vehicle Stopped
161 142970 : resetVehicleStoppedTimer();
162 : }
163 :
164 : // Update Energy from the battery
165 203120 : EnergyParams* const params = myHolder.getEmissionParameters();
166 203120 : if (getMaximumBatteryCapacity() != 0) {
167 203120 : params->setDouble(SUMO_ATTR_ANGLE, myLastAngle == std::numeric_limits<double>::infinity() ? 0. : GeomHelper::angleDiff(myLastAngle, veh.getAngle()));
168 203120 : if (!myTrackFuel && !veh.getVehicleType().getParameter().wasSet(VTYPEPARS_EMISSIONCLASS_SET)) {
169 : // no explicit emission class, we fall back to the energy model; a warning has been issued on creation
170 890 : myConsum = PollutantsInterface::getEnergyHelper().compute(0, PollutantsInterface::ELEC, veh.getSpeed(), veh.getAcceleration(),
171 890 : veh.getSlope(), params) * TS;
172 : } else {
173 202675 : myConsum = PollutantsInterface::compute(veh.getVehicleType().getEmissionClass(),
174 202675 : myTrackFuel ? PollutantsInterface::FUEL : PollutantsInterface::ELEC,
175 202675 : veh.getSpeed(), veh.getAcceleration(),
176 405350 : veh.getSlope(), params) * TS;
177 : }
178 203120 : if (veh.isParking()) {
179 : // recuperation from last braking step is ok but further consumption should cease
180 848 : myConsum = MIN2(myConsum, 0.0);
181 : }
182 :
183 : // Energy lost/gained from vehicle movement (via vehicle energy model) [Wh]
184 203120 : setActualBatteryCapacity(getActualBatteryCapacity() - myConsum);
185 :
186 : // Track total energy consumption and regeneration
187 203120 : if (myConsum > 0.0) {
188 196061 : myTotalConsumption += myConsum;
189 : } else {
190 7059 : myTotalRegenerated -= myConsum;
191 : }
192 :
193 : // saturate between 0 and myMaximumBatteryCapacity [Wh]
194 203120 : if (getActualBatteryCapacity() < 0) {
195 0 : setActualBatteryCapacity(0);
196 0 : if (getMaximumBatteryCapacity() > 0) {
197 0 : WRITE_WARNINGF(TL("Battery of vehicle '%' is depleted."), veh.getID());
198 : }
199 203120 : } else if (getActualBatteryCapacity() > getMaximumBatteryCapacity()) {
200 0 : setActualBatteryCapacity(getMaximumBatteryCapacity());
201 : }
202 203120 : myLastAngle = veh.getAngle();
203 : }
204 :
205 : // Check if vehicle has under their position one charge Station
206 203120 : const std::string chargingStationID = MSNet::getInstance()->getStoppingPlaceID(veh.getLane(), veh.getPositionOnLane(), SUMO_TAG_CHARGING_STATION);
207 :
208 : // If vehicle is over a charging station
209 203120 : if (chargingStationID != "") {
210 : // if the vehicle is almost stopped, or charge in transit is enabled, then charge vehicle
211 7189 : MSChargingStation* const cs = static_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(chargingStationID, SUMO_TAG_CHARGING_STATION));
212 7189 : const MSParkingArea* pa = cs->getParkingArea();
213 7189 : if (((veh.getSpeed() < myStoppingThreshold) || cs->getChargeInTransit()) && (pa == nullptr || veh.isParking())) {
214 : // Set Flags Stopped/intransit to
215 5792 : if (veh.getSpeed() < myStoppingThreshold) {
216 : // vehicle ist almost stopped, then is charging stopped
217 4961 : myChargingStopped = true;
218 :
219 : // therefore isn't charging in transit
220 4961 : myChargingInTransit = false;
221 : } else {
222 : // vehicle is moving, and the Charging station allow charge in transit
223 831 : myChargingStopped = false;
224 :
225 : // Therefore charge in transit
226 831 : myChargingInTransit = true;
227 : }
228 :
229 : // get pointer to charging station
230 5792 : myActChargingStation = cs;
231 :
232 : // Only update charging start time if vehicle allow charge in transit, or in other case
233 : // if the vehicle not allow charge in transit but it's stopped.
234 5792 : if ((myActChargingStation->getChargeInTransit()) || (veh.getSpeed() < myStoppingThreshold)) {
235 : // Update Charging start time
236 5792 : increaseChargingStartTime();
237 : }
238 :
239 : // time it takes the vehicle at the station < charging station time delay?
240 5792 : if (getChargingStartTime() > myActChargingStation->getChargeDelay()) {
241 : // Enable charging vehicle
242 5084 : myActChargingStation->setChargingVehicle(true);
243 :
244 : // Calulate energy charged
245 5084 : myEnergyCharged = MIN2(myActChargingStation->getChargingPower(myTrackFuel) * myActChargingStation->getEfficency() * TS, getMaximumBatteryCapacity() - getActualBatteryCapacity());
246 :
247 : // Update Battery charge
248 5084 : setActualBatteryCapacity(getActualBatteryCapacity() + myEnergyCharged);
249 : }
250 : // add charge value for output to myActChargingStation
251 5792 : myActChargingStation->addChargeValueForOutput(myEnergyCharged, this);
252 : }
253 : // else disable charging vehicle
254 : else {
255 1397 : cs->setChargingVehicle(false);
256 : }
257 : // 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)
258 7189 : if (myPreviousNeighbouringChargingStation != nullptr && myPreviousNeighbouringChargingStation != cs) {
259 259 : myPreviousNeighbouringChargingStation->setChargingVehicle(false);
260 : }
261 7189 : myPreviousNeighbouringChargingStation = cs;
262 : }
263 : // In other case, vehicle will be not charged
264 : else {
265 : // Disable flags
266 195931 : myChargingInTransit = false;
267 195931 : myChargingStopped = false;
268 :
269 : // Disable charging vehicle
270 195931 : if (myActChargingStation != nullptr) {
271 314 : myActChargingStation->setChargingVehicle(false);
272 : }
273 :
274 : // Set charging station pointer to NULL
275 195931 : myActChargingStation = nullptr;
276 :
277 : // Set energy charged to 0
278 195931 : myEnergyCharged = 0.00;
279 :
280 : // Reset timer
281 195931 : resetChargingStartTime();
282 : }
283 :
284 : // Always return true.
285 : return true;
286 : }
287 :
288 :
289 : void
290 0 : MSDevice_Battery::saveState(OutputDevice& out) const {
291 0 : out.openTag(SUMO_TAG_DEVICE);
292 : out.writeAttr(SUMO_ATTR_ID, getID());
293 : std::vector<std::string> internals;
294 0 : internals.push_back(toString(myActualBatteryCapacity));
295 0 : internals.push_back(toString(myLastAngle));
296 0 : internals.push_back(toString(myChargingStopped));
297 0 : internals.push_back(toString(myChargingInTransit));
298 0 : internals.push_back(toString(myChargingStartTime));
299 0 : internals.push_back(toString(myTotalConsumption));
300 0 : internals.push_back(toString(myTotalRegenerated));
301 0 : internals.push_back(toString(myEnergyCharged));
302 0 : internals.push_back(toString(myVehicleStopped));
303 0 : internals.push_back(getChargingStationID());
304 0 : std::string prevChargingID = (myPreviousNeighbouringChargingStation == nullptr) ? "NULL" : myPreviousNeighbouringChargingStation->getID();
305 0 : internals.push_back(prevChargingID);
306 0 : out.writeAttr(SUMO_ATTR_STATE, toString(internals));
307 0 : out.closeTag();
308 0 : }
309 :
310 :
311 : void
312 0 : MSDevice_Battery::loadState(const SUMOSAXAttributes& attrs) {
313 0 : std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
314 0 : bis >> myActualBatteryCapacity;
315 0 : bis >> myLastAngle;
316 0 : bis >> myChargingStopped;
317 0 : bis >> myChargingInTransit;
318 0 : bis >> myChargingStartTime;
319 0 : bis >> myTotalConsumption;
320 0 : bis >> myTotalRegenerated;
321 0 : bis >> myEnergyCharged;
322 0 : bis >> myVehicleStopped;
323 : std::string chargingID;
324 0 : bis >> chargingID;
325 0 : if (chargingID != "NULL") {
326 0 : myActChargingStation = dynamic_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(chargingID, SUMO_TAG_CHARGING_STATION));
327 : }
328 : std::string prevChargingID;
329 0 : bis >> prevChargingID;
330 0 : if (prevChargingID != "NULL") {
331 0 : myPreviousNeighbouringChargingStation = dynamic_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(prevChargingID, SUMO_TAG_CHARGING_STATION));
332 : }
333 0 : }
334 :
335 :
336 : void
337 208204 : MSDevice_Battery::setActualBatteryCapacity(const double actualBatteryCapacity) {
338 208204 : if (actualBatteryCapacity < 0) {
339 2476 : myActualBatteryCapacity = 0;
340 205728 : } else if (actualBatteryCapacity > myMaximumBatteryCapacity) {
341 5 : myActualBatteryCapacity = myMaximumBatteryCapacity;
342 : } else {
343 205723 : myActualBatteryCapacity = actualBatteryCapacity;
344 : }
345 208204 : }
346 :
347 :
348 : void
349 10 : MSDevice_Battery::setMaximumBatteryCapacity(const double maximumBatteryCapacity) {
350 10 : if (myMaximumBatteryCapacity < 0) {
351 0 : WRITE_WARNINGF(TL("Trying to set into the battery device of vehicle '%' an invalid % (%)."), getID(), toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY), toString(maximumBatteryCapacity));
352 : } else {
353 10 : myMaximumBatteryCapacity = maximumBatteryCapacity;
354 : }
355 10 : }
356 :
357 :
358 : void
359 0 : MSDevice_Battery::setStoppingThreshold(const double stoppingThreshold) {
360 0 : if (stoppingThreshold < 0) {
361 0 : WRITE_WARNINGF(TL("Trying to set into the battery device of vehicle '%' an invalid % (%)."), getID(), toString(SUMO_ATTR_STOPPINGTHRESHOLD), toString(stoppingThreshold));
362 : } else {
363 0 : myStoppingThreshold = stoppingThreshold;
364 : }
365 0 : }
366 :
367 :
368 : void
369 195931 : MSDevice_Battery::resetChargingStartTime() {
370 195931 : myChargingStartTime = 0;
371 195931 : }
372 :
373 :
374 : void
375 5792 : MSDevice_Battery::increaseChargingStartTime() {
376 5792 : myChargingStartTime += DELTA_T;
377 5792 : }
378 :
379 :
380 : void
381 142970 : MSDevice_Battery::resetVehicleStoppedTimer() {
382 142970 : myVehicleStopped = 0;
383 142970 : }
384 :
385 :
386 : void
387 60150 : MSDevice_Battery::increaseVehicleStoppedTimer() {
388 60150 : myVehicleStopped++;
389 60150 : }
390 :
391 :
392 : double
393 894189 : MSDevice_Battery::getActualBatteryCapacity() const {
394 894189 : return myActualBatteryCapacity;
395 : }
396 :
397 :
398 : double
399 943660 : MSDevice_Battery::getMaximumBatteryCapacity() const {
400 943660 : return myMaximumBatteryCapacity;
401 : }
402 :
403 :
404 : double
405 263317 : MSDevice_Battery::getConsum() const {
406 263317 : return myConsum;
407 : }
408 :
409 : double
410 268869 : MSDevice_Battery::getTotalConsumption() const {
411 268869 : return myTotalConsumption;
412 : }
413 :
414 :
415 : double
416 263317 : MSDevice_Battery::getTotalRegenerated() const {
417 263317 : return myTotalRegenerated;
418 : }
419 :
420 :
421 : bool
422 263217 : MSDevice_Battery::isChargingStopped() const {
423 263217 : return myChargingStopped;
424 : }
425 :
426 :
427 : bool
428 263217 : MSDevice_Battery::isChargingInTransit() const {
429 263217 : return myChargingInTransit;
430 : }
431 :
432 :
433 : SUMOTime
434 11584 : MSDevice_Battery::getChargingStartTime() const {
435 11584 : return myChargingStartTime;
436 : }
437 :
438 :
439 : std::string
440 263317 : MSDevice_Battery::getChargingStationID() const {
441 263317 : if (myActChargingStation != nullptr) {
442 : return myActChargingStation->getID();
443 : } else {
444 257417 : return "NULL";
445 : }
446 : }
447 :
448 : double
449 269217 : MSDevice_Battery::getEnergyCharged() const {
450 269217 : return myEnergyCharged;
451 : }
452 :
453 :
454 : int
455 263217 : MSDevice_Battery::getVehicleStopped() const {
456 263217 : return myVehicleStopped;
457 : }
458 :
459 :
460 : double
461 5404 : MSDevice_Battery::getStoppingThreshold() const {
462 5404 : return myStoppingThreshold;
463 : }
464 :
465 :
466 : std::string
467 820 : MSDevice_Battery::getParameter(const std::string& key) const {
468 1640 : if (key == toString(SUMO_ATTR_ACTUALBATTERYCAPACITY)) {
469 100 : return toString(getActualBatteryCapacity());
470 720 : } else if (key == toString(SUMO_ATTR_ENERGYCONSUMED)) {
471 100 : return toString(getConsum());
472 1240 : } else if (key == toString(SUMO_ATTR_TOTALENERGYCONSUMED)) {
473 100 : return toString(getTotalConsumption());
474 1040 : } else if (key == toString(SUMO_ATTR_TOTALENERGYREGENERATED)) {
475 100 : return toString(getTotalRegenerated());
476 420 : } else if (key == toString(SUMO_ATTR_ENERGYCHARGED)) {
477 100 : return toString(getEnergyCharged());
478 640 : } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY)) {
479 110 : return toString(getMaximumBatteryCapacity());
480 420 : } else if (key == toString(SUMO_ATTR_CHARGINGSTATIONID)) {
481 100 : return getChargingStationID();
482 110 : } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
483 100 : WRITE_WARNING(TL("Getting the vehicle mass via parameters is deprecated, please use getMass for the vehicle or its type."));
484 100 : return toString(myHolder.getEmissionParameters()->getDouble(SUMO_ATTR_MASS));
485 : }
486 20 : throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
487 : }
488 :
489 :
490 : void
491 20 : MSDevice_Battery::setParameter(const std::string& key, const std::string& value) {
492 : double doubleValue;
493 : try {
494 20 : doubleValue = StringUtils::toDouble(value);
495 0 : } catch (NumberFormatException&) {
496 0 : throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
497 0 : }
498 40 : if (key == toString(SUMO_ATTR_ACTUALBATTERYCAPACITY)) {
499 0 : setActualBatteryCapacity(doubleValue);
500 40 : } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY)) {
501 10 : setMaximumBatteryCapacity(doubleValue);
502 10 : } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
503 10 : WRITE_WARNING(TL("Setting the vehicle mass via parameters is deprecated, please use setMass for the vehicle or its type."));
504 10 : myHolder.getEmissionParameters()->setDouble(SUMO_ATTR_MASS, doubleValue);
505 : } else {
506 0 : throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
507 : }
508 20 : }
509 :
510 :
511 : void
512 400 : MSDevice_Battery::notifyParking() {
513 : // @note: only charing is performed but no energy is consumed
514 400 : notifyMove(myHolder, myHolder.getPositionOnLane(), myHolder.getPositionOnLane(), myHolder.getSpeed());
515 400 : myConsum = 0;
516 400 : }
517 :
518 :
519 : /****************************************************************************/
|